diff --git a/.gitattributes b/.gitattributes index fa6d5df..839d651 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,5 @@ # Auto detect text files and perform LF normalization * text=auto # Convert linux scripts to LF permanently -*.sh crlf=input \ No newline at end of file +*.sh text eol=lf +*.define text eol=lf diff --git a/.gitignore b/.gitignore index 0d0d0dc..063f8fb 100644 --- a/.gitignore +++ b/.gitignore @@ -42,14 +42,24 @@ verilator/obj_dir/* verilator/x64/* verilator/roms/* verilator/*.hex -src/os.asm -src/os.bin -src/os.lk -src/os.lst -src/os.map -src/os.noi -src/os.sym +rtl/*.hex .vscode/settings.json verilator/imgui.ini verilator/imgui.ini -docs/* +**/.vs/* +**/bin/* +**/obj/* +docs/vids/* +verilator/audio.wav +*.log +**/build/*.sym +**/build/*.rel +**/build/*.lst +**/build/*.map +**/build/*.noi +**/build/*.lk +**/build/*.asm +**/sound/res/* +**/sprites/res/* +**/tilemap/res/* +**/music/res/* \ No newline at end of file diff --git a/CURRENT_PROJECT b/CURRENT_PROJECT new file mode 100644 index 0000000..0deb2ce --- /dev/null +++ b/CURRENT_PROJECT @@ -0,0 +1 @@ +inputtest diff --git a/InputTest.qsf b/InputTest.qsf index 7619c2f..6073f37 100644 --- a/InputTest.qsf +++ b/InputTest.qsf @@ -50,7 +50,7 @@ set_global_assignment -name PHYSICAL_SYNTHESIS_ASYNCHRONOUS_SIGNAL_PIPELINING ON set_global_assignment -name ALM_REGISTER_PACKING_EFFORT MEDIUM set_global_assignment -name SEED 1 -#set_global_assignment -name VERILOG_MACRO "MISTER_FB=1" +set_global_assignment -name VERILOG_MACRO "MISTER_FB=1" #enable it only if 8bit indexed mode is used in core #set_global_assignment -name VERILOG_MACRO "MISTER_FB_PALETTE=1" @@ -60,6 +60,18 @@ set_global_assignment -name SEED 1 #do not enable DEBUG_NOHDMI in release! #set_global_assignment -name VERILOG_MACRO "MISTER_DEBUG_NOHDMI=1" +# Aznable specific defines +# ------------------------ +#set_global_assignment -name VERILOG_MACRO "DISABLE_CPU=1" +#set_global_assignment -name VERILOG_MACRO "DISABLE_CHARMAP=1" +#set_global_assignment -name VERILOG_MACRO "DISABLE_SPRITES=1" +#set_global_assignment -name VERILOG_MACRO "DISABLE_TILEMAP=1" +#set_global_assignment -name VERILOG_MACRO "DISABLE_MUSIC=1" +#set_global_assignment -name VERILOG_MACRO "DISABLE_SOUND=1" +#set_global_assignment -name VERILOG_MACRO "DISABLE_STARS_2=1" +#set_global_assignment -name VERILOG_MACRO "DISABLE_STARS_3=1" +#set_global_assignment -name VERILOG_MACRO "DEBUG_SPRITE_COLLISION=1" + source sys/sys.tcl source sys/sys_analog.tcl source files.qip diff --git a/InputTest.sv b/InputTest.sv index 07ce36e..0e6c2e3 100644 --- a/InputTest.sv +++ b/InputTest.sv @@ -2,8 +2,8 @@ Input Test - emu module Author: Jim Gregory - https://github.com/JimmyStones/ - Version: 1.0 - Date: 2021-07-12 + Version: 1.1 + Date: 2021-12-22 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 @@ -29,7 +29,7 @@ module emu input RESET, //Must be passed to hps_io module - inout [45:0] HPS_BUS, + inout [47:0] HPS_BUS, //Base video clock. Usually equals to CLK_SYS. output CLK_VIDEO, @@ -180,14 +180,14 @@ assign USER_OUT = '1; assign {UART_RTS, UART_TXD, UART_DTR} = 0; assign {SD_SCK, SD_MOSI, SD_CS} = 'Z; assign {SDRAM_DQ, SDRAM_A, SDRAM_BA, SDRAM_CLK, SDRAM_CKE, SDRAM_DQML, SDRAM_DQMH, SDRAM_nWE, SDRAM_nCAS, SDRAM_nRAS, SDRAM_nCS} = 'Z; -assign {DDRAM_CLK, DDRAM_BURSTCNT, DDRAM_ADDR, DDRAM_DIN, DDRAM_BE, DDRAM_RD, DDRAM_WE} = '0; +assign FB_FORCE_BLANK = 0; assign VGA_F1 = 0; assign VGA_SCALER = 0; assign HDMI_FREEZE = 0; -assign AUDIO_S = 0; -assign AUDIO_L = 0; -assign AUDIO_R = 0; + +assign AUDIO_S = 1; assign AUDIO_MIX = 0; + assign LED_DISK = 0; assign LED_POWER = 0; assign BUTTONS = 0; @@ -203,10 +203,25 @@ assign VIDEO_ARY = (!ar) ? 12'd3 : 12'd0; localparam CONF_STR = { "InputTest;;", "-;", + "O35,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%,CRT 75%;", + "OGJ,Analog Video H-Pos,0,-1,-2,-3,-4,-5,-6,-7,8,7,6,5,4,3,2,1;", + "OKN,Analog Video V-Pos,0,-1,-2,-3,-4,-5,-6,-7,8,7,6,5,4,3,2,1;", "O89,Aspect ratio,Original,Full Screen,[ARC1],[ARC2];", "-;", - "F0,BIN,Load BIOS;", + "O6,Rotate video,Off,On;", + "O7,Flip video,Off,On;", + "-;", + "RA,Open menu;", "-;", + "P1,Pause options;", + "P1OP,Pause when OSD is open,On,Off;", + "P1OQ,Dim video after 10s,On,Off;", + "-;", + "F0,BIN,Load BIOS;", + "F3,BIN,Load Sprite ROM;", + "F4,YM,Load Music (YM5/6);", + "-;", + "R0,Reset;", "J,A,B,X,Y,L,R,Select,Start;", "V,v",`BUILD_DATE }; @@ -287,6 +302,7 @@ hps_io #(.CONF_STR(CONF_STR)) hps_io .joystick_l_analog_3(joystick_l_analog_3), .joystick_l_analog_4(joystick_l_analog_4), .joystick_l_analog_5(joystick_l_analog_5), + .joystick_r_analog_0(joystick_r_analog_0), .joystick_r_analog_1(joystick_r_analog_1), .joystick_r_analog_2(joystick_r_analog_2), @@ -327,20 +343,27 @@ pll pll /////////////////// CLOCK DIVIDER //////////////////// wire ce_pix; +wire ce_2; jtframe_cen24 divider ( .clk(clk_sys), - .cen6(ce_pix) + .cen6(ce_pix), + .cen2(ce_2) ); /////////////////// VIDEO //////////////////// -wire hblank, vblank, hs, vs; +wire hblank, vblank, hs, vs, hs_original, vs_original; wire [7:0] r, g, b; + +wire rotate_ccw = status[7]; +wire no_rotate = ~status[6]; +wire flip = status[7]; +screen_rotate screen_rotate (.*); arcade_video #(320,24) arcade_video ( .*, .clk_video(clk_sys), - .RGB_in({r,g,b}), + .RGB_in(rgb_out), .HBlank(hblank), .VBlank(vblank), .HSync(hs), @@ -348,34 +371,67 @@ arcade_video #(320,24) arcade_video .fx(status[5:3]) ); +// H/V offset +wire [3:0] voffset = status[23:20]; +wire [3:0] hoffset = status[19:16]; +jtframe_resync jtframe_resync +( + .clk(clk_sys), + .pxl_cen(ce_pix), + .hs_in(hs_original), + .vs_in(vs_original), + .LVBL(~vblank), + .LHBL(~hblank), + .hoffset(hoffset), + .voffset(voffset), + .hs_out(hs), + .vs_out(vs) +); + +/////////////////// PAUSE SYSTEM /////////////////// +wire m_pause = joystick_0[8]; +wire pause_cpu; +wire [23:0] rgb_out; +pause #(8,8,8,24) pause ( + .*, + .user_button(m_pause), + .pause_request(), + .options(~status[26:25]) +); + /////////////////// MAIN CORE //////////////////// wire rom_download = ioctl_download && (ioctl_index < 8'd2); wire reset = (RESET | status[0] | buttons[1] | rom_download); assign LED_USER = rom_download; system system( - .clk_sys(clk_sys), - .ce_pix(ce_pix), + .clk_24(clk_sys), + .ce_6(ce_pix), + .ce_2(ce_2), .reset(reset), - .VGA_HS(hs), - .VGA_VS(vs), + .pause(pause_cpu), + .menu(status[10] || buttons[1]), + .VGA_HS(hs_original), + .VGA_VS(vs_original), .VGA_R(r), .VGA_G(g), .VGA_B(b), .VGA_HB(hblank), .VGA_VB(vblank), - .dn_addr(ioctl_addr[13:0]), + .dn_addr(ioctl_addr[16:0]), .dn_data(ioctl_dout), .dn_wr(ioctl_wr), .dn_index(ioctl_index), .joystick({joystick_5,joystick_4,joystick_3,joystick_2,joystick_1,joystick_0}), .analog_l({joystick_l_analog_5,joystick_l_analog_4,joystick_l_analog_3,joystick_l_analog_2,joystick_l_analog_1,joystick_l_analog_0}), .analog_r({joystick_r_analog_5,joystick_r_analog_4,joystick_r_analog_3,joystick_r_analog_2,joystick_r_analog_1,joystick_r_analog_0}), - .paddle({paddle_5,paddle_4,paddle_3,paddle_2,paddle_1,paddle_0}), + .paddle({paddle_5,paddle_4,paddle_3,paddle_2,paddle_1,paddle_0}), .spinner({7'b0,spinner_5,7'b0,spinner_4,7'b0,spinner_3,7'b0,spinner_2,7'b0,spinner_1,7'b0,spinner_0}), .ps2_key(ps2_key), .ps2_mouse({ps2_mouse_ext,7'b0,ps2_mouse}), - .timestamp(timestamp) + .timestamp(timestamp), + .AUDIO_L(AUDIO_L), + .AUDIO_R(AUDIO_R) ); endmodule diff --git a/MiSTer.pf b/MiSTer.pf deleted file mode 100644 index 1420b55..0000000 Binary files a/MiSTer.pf and /dev/null differ diff --git a/README.MD b/README.MD index 487d307..854365b 100644 --- a/README.MD +++ b/README.MD @@ -73,7 +73,7 @@ Start|End|Length|Name /src contains a C program compiled to Z80 assembly using sdcc. -All required ROMs (compiled program and font) are built into this core. +All required ROMs (compiled program, font, images, sounds and music) are built into this core. Selecting Load BIOS in the core allows hot loading of binary OS ROM files for easier development. diff --git a/build.sh b/build.sh index bcd756e..78aa899 100755 --- a/build.sh +++ b/build.sh @@ -1,17 +1,34 @@ -# Make C code -cd src -make clean +# Define current project and other variables +PROJECT=$(cat CURRENT_PROJECT) +CURRENTDIR=$(pwd) + +# Compile C code +cd src/$PROJECT +#make clean make all -cd .. +cd $CURRENTDIR -# Verilate HDL +# Compile verilator code cd verilator -./verilate.sh -cd .. +./verilate.sh $PROJECT +cd $CURRENTDIR -# Hexify roms -od -An -t x1 -v src/os.bin > verilator/rom.hex -od -An -t x1 -v src/os.bin > rtl/rom.hex -od -An -t x1 -v PETSCII.pf > verilator/font.hex -od -An -t x1 -v PETSCII.pf > rtl/font.hex +# Build target locations +TARGETS=( verilator rtl ) +# Hexify rom and font and copy to build targets +for TARGET in "${TARGETS[@]}"; do +od -An -t x1 -v src/$PROJECT/bin/rom.bin > $TARGET/rom.hex +od -An -t x1 -v font.pf > $TARGET/font.hex +done + +# Hexify resource binarys and copy to build targets +RESOURCES=( sprite palette music sound tilemap ) +for RESOURCE in "${RESOURCES[@]}"; do +if [ -r "resources/$PROJECT/$RESOURCE.bin" ]; then +echo "Updating resources/$PROJECT/$RESOURCE.bin" +for TARGET in "${TARGETS[@]}"; do +od -An -t x1 -v resources/$PROJECT/$RESOURCE.bin > $TARGET/$RESOURCE.hex +done +fi +done \ No newline at end of file diff --git a/clean.sh b/clean.sh new file mode 100644 index 0000000..cc3f9d3 --- /dev/null +++ b/clean.sh @@ -0,0 +1,4 @@ +# Make C code +cd src +make clean +cd .. diff --git a/files.qip b/files.qip index 4f7eb4a..506aeb7 100644 --- a/files.qip +++ b/files.qip @@ -3,7 +3,20 @@ set_global_assignment -name QIP_FILE rtl/tv80/TV80.qip set_global_assignment -name CDF_FILE jtag.cdf set_global_assignment -name QIP_FILE sys/sys.qip set_global_assignment -name VERILOG_FILE rtl/JTFRAME/jtframe_vtimer.v +set_global_assignment -name VERILOG_FILE rtl/JTFRAME/jtframe_resync.v set_global_assignment -name VERILOG_FILE rtl/JTFRAME/jtframe_cen24.v +set_global_assignment -name QIP_FILE rtl/jt49/jt49.qip +set_global_assignment -name QIP_FILE rtl/jt5205/jt5205.qip +set_global_assignment -name VERILOG_FILE rtl/charmap.v +set_global_assignment -name VERILOG_FILE rtl/sprite_engine.v +set_global_assignment -name VERILOG_FILE rtl/tilemap.v +set_global_assignment -name VERILOG_FILE rtl/lfsr.v +set_global_assignment -name VERILOG_FILE rtl/starfield.v +set_global_assignment -name VERILOG_FILE rtl/music.v +set_global_assignment -name VERILOG_FILE rtl/sound.v +set_global_assignment -name VERILOG_FILE rtl/generic_timer.v set_global_assignment -name VERILOG_FILE rtl/system.v set_global_assignment -name VERILOG_FILE rtl/dpram.v -set_global_assignment -name VERILOG_FILE rtl/spram.v \ No newline at end of file +set_global_assignment -name VERILOG_FILE rtl/dpram_w1r2.v +set_global_assignment -name VERILOG_FILE rtl/spram.v +set_global_assignment -name VERILOG_FILE rtl/pause.v \ No newline at end of file diff --git a/PETSCII.pf b/font.pf similarity index 100% rename from PETSCII.pf rename to font.pf diff --git a/gfx/images/01_asteroids-4_2#1.png b/gfx/images/01_asteroids-4_2#1.png new file mode 100644 index 0000000..048371d Binary files /dev/null and b/gfx/images/01_asteroids-4_2#1.png differ diff --git a/gfx/images/02_player1-4_2#2.png b/gfx/images/02_player1-4_2#2.png new file mode 100644 index 0000000..ee89059 Binary files /dev/null and b/gfx/images/02_player1-4_2#2.png differ diff --git a/gfx/images/03_explosions-4_2#2.png b/gfx/images/03_explosions-4_2#2.png new file mode 100644 index 0000000..9285357 Binary files /dev/null and b/gfx/images/03_explosions-4_2#2.png differ diff --git a/gfx/images/04_pickups-3_2#2.png b/gfx/images/04_pickups-3_2#2.png new file mode 100644 index 0000000..25f1343 Binary files /dev/null and b/gfx/images/04_pickups-3_2#2.png differ diff --git a/gfx/images/05_logo-8_2#3.png b/gfx/images/05_logo-8_2#3.png new file mode 100644 index 0000000..133869f Binary files /dev/null and b/gfx/images/05_logo-8_2#3.png differ diff --git a/gfx/palette.bin b/gfx/palette.bin new file mode 100644 index 0000000..658455e Binary files /dev/null and b/gfx/palette.bin differ diff --git a/gfx/sprite.bin b/gfx/sprite.bin new file mode 100644 index 0000000..b611e91 Binary files /dev/null and b/gfx/sprite.bin differ diff --git a/prereq.sh b/prereq.sh deleted file mode 100755 index d81631d..0000000 --- a/prereq.sh +++ /dev/null @@ -1,2 +0,0 @@ -sudo apt-get install sdcc srecord - diff --git a/resources/inputtest/music.bin b/resources/inputtest/music.bin new file mode 100644 index 0000000..ef511d6 Binary files /dev/null and b/resources/inputtest/music.bin differ diff --git a/resources/inputtest/music/game_over.ym b/resources/inputtest/music/game_over.ym new file mode 100644 index 0000000..1be779e Binary files /dev/null and b/resources/inputtest/music/game_over.ym differ diff --git a/resources/inputtest/music/main_theme.ym b/resources/inputtest/music/main_theme.ym new file mode 100644 index 0000000..262e6c7 Binary files /dev/null and b/resources/inputtest/music/main_theme.ym differ diff --git a/resources/inputtest/music/tracks.txt b/resources/inputtest/music/tracks.txt new file mode 100644 index 0000000..a70fe83 --- /dev/null +++ b/resources/inputtest/music/tracks.txt @@ -0,0 +1,2 @@ +main_theme.ym#maintheme +game_over.ym#gameover \ No newline at end of file diff --git a/resources/inputtest/palette.bin b/resources/inputtest/palette.bin new file mode 100644 index 0000000..eeca56b Binary files /dev/null and b/resources/inputtest/palette.bin differ diff --git a/resources/inputtest/sound.bin b/resources/inputtest/sound.bin new file mode 100644 index 0000000..a5b31c2 Binary files /dev/null and b/resources/inputtest/sound.bin differ diff --git a/resources/inputtest/sound/alarm.vox b/resources/inputtest/sound/alarm.vox new file mode 100644 index 0000000..1d0d6c7 Binary files /dev/null and b/resources/inputtest/sound/alarm.vox differ diff --git a/resources/inputtest/sound/alarm.wav b/resources/inputtest/sound/alarm.wav new file mode 100644 index 0000000..a91af84 Binary files /dev/null and b/resources/inputtest/sound/alarm.wav differ diff --git a/resources/inputtest/sound/explosion.vox b/resources/inputtest/sound/explosion.vox new file mode 100644 index 0000000..f6846ce Binary files /dev/null and b/resources/inputtest/sound/explosion.vox differ diff --git a/resources/inputtest/sound/explosion.wav b/resources/inputtest/sound/explosion.wav new file mode 100644 index 0000000..a3ae05f Binary files /dev/null and b/resources/inputtest/sound/explosion.wav differ diff --git a/resources/inputtest/sound/newtype.vox b/resources/inputtest/sound/newtype.vox new file mode 100644 index 0000000..125fcf8 Binary files /dev/null and b/resources/inputtest/sound/newtype.vox differ diff --git a/resources/inputtest/sound/newtype.wav b/resources/inputtest/sound/newtype.wav new file mode 100644 index 0000000..70cb11f Binary files /dev/null and b/resources/inputtest/sound/newtype.wav differ diff --git a/resources/inputtest/sound/pickup.vox b/resources/inputtest/sound/pickup.vox new file mode 100644 index 0000000..dbef5ec Binary files /dev/null and b/resources/inputtest/sound/pickup.vox differ diff --git a/resources/inputtest/sound/pickup.wav b/resources/inputtest/sound/pickup.wav new file mode 100644 index 0000000..05d55b0 Binary files /dev/null and b/resources/inputtest/sound/pickup.wav differ diff --git a/resources/inputtest/sound/samples.txt b/resources/inputtest/sound/samples.txt new file mode 100644 index 0000000..edd6c2e --- /dev/null +++ b/resources/inputtest/sound/samples.txt @@ -0,0 +1,4 @@ +explosion#player_explode +pickup#pickup_collect +alarm#alarm +newtype#newtype \ No newline at end of file diff --git a/resources/inputtest/sprite.bin b/resources/inputtest/sprite.bin new file mode 100644 index 0000000..a66a125 Binary files /dev/null and b/resources/inputtest/sprite.bin differ diff --git a/resources/inputtest/sprites/16_asteroids#1.png b/resources/inputtest/sprites/16_asteroids#1.png new file mode 100644 index 0000000..048371d Binary files /dev/null and b/resources/inputtest/sprites/16_asteroids#1.png differ diff --git a/resources/inputtest/sprites/16_explosions#2.png b/resources/inputtest/sprites/16_explosions#2.png new file mode 100644 index 0000000..9285357 Binary files /dev/null and b/resources/inputtest/sprites/16_explosions#2.png differ diff --git a/resources/inputtest/sprites/16_pickups#2.png b/resources/inputtest/sprites/16_pickups#2.png new file mode 100644 index 0000000..e771da7 Binary files /dev/null and b/resources/inputtest/sprites/16_pickups#2.png differ diff --git a/resources/inputtest/sprites/16_pings#3.png b/resources/inputtest/sprites/16_pings#3.png new file mode 100644 index 0000000..31cb382 Binary files /dev/null and b/resources/inputtest/sprites/16_pings#3.png differ diff --git a/resources/inputtest/sprites/16_player#2.png b/resources/inputtest/sprites/16_player#2.png new file mode 100644 index 0000000..3fb8e7c Binary files /dev/null and b/resources/inputtest/sprites/16_player#2.png differ diff --git a/resources/inputtest/sprites/16_pointer#3.png b/resources/inputtest/sprites/16_pointer#3.png new file mode 100644 index 0000000..f80f00b Binary files /dev/null and b/resources/inputtest/sprites/16_pointer#3.png differ diff --git a/resources/inputtest/sprites/32_title#3.png b/resources/inputtest/sprites/32_title#3.png new file mode 100644 index 0000000..e9ae519 Binary files /dev/null and b/resources/inputtest/sprites/32_title#3.png differ diff --git a/resources/inputtest/sprites/8_trails#2.png b/resources/inputtest/sprites/8_trails#2.png new file mode 100644 index 0000000..a54cc0b Binary files /dev/null and b/resources/inputtest/sprites/8_trails#2.png differ diff --git a/resources/inputtest/tilemap.bin b/resources/inputtest/tilemap.bin new file mode 100644 index 0000000..1c4fd88 Binary files /dev/null and b/resources/inputtest/tilemap.bin differ diff --git a/resources/inputtest/tilemap/tilemap.png b/resources/inputtest/tilemap/tilemap.png new file mode 100644 index 0000000..d273c14 Binary files /dev/null and b/resources/inputtest/tilemap/tilemap.png differ diff --git a/rtl/JTFRAME/jtframe_cen24.v b/rtl/JTFRAME/jtframe_cen24.v index f7f594e..ced07d7 100644 --- a/rtl/JTFRAME/jtframe_cen24.v +++ b/rtl/JTFRAME/jtframe_cen24.v @@ -19,46 +19,26 @@ // Input clock must be 24 MHz // Generates various clock enable signals +// Modifed by Jim Gregory - @mrjimmystones to remove redundant signals and add 2Mhz enable + module jtframe_cen24( input clk, // 24 MHz output reg cen12, - output cen8, output reg cen6, - output reg cen4, - output reg cen3, - output reg cen3q, // 1/4 advanced with respect to cen3 - output reg cen1p5, - // 180 shifted signals - output reg cen12b, - output reg cen6b, - output reg cen3b, - output reg cen3qb, - output reg cen1p5b + output reg cen2 ); reg [3:0] cencnt =4'd0; -reg [2:0] cencnt3=3'd0; -reg [2:0] cencnt8=3'd1; - -assign cen8 = cencnt8[2]; +reg [3:0] cencnt2=4'd0; always @(posedge clk) begin cencnt <= cencnt+4'd1; - cencnt3 <= cencnt3==3'd5 ? 3'd0 : (cencnt3+3'd1); - cencnt8 <= { cencnt8[1:0], cencnt8[2] }; + cencnt2 <= cencnt2==4'd12 ? 4'd0 : (cencnt2+4'd1); end always @(posedge clk) begin cen12 <= cencnt[0] == 1'd0; - cen12b <= cencnt[0] == 1'd1; - cen4 <= cencnt3 == 3'd0; cen6 <= cencnt[1:0] == 2'd0; - cen6b <= cencnt[1:0] == 2'd2; - cen3 <= cencnt[2:0] == 3'd0; - cen3b <= cencnt[2:0] == 3'h4; - cen3q <= cencnt[2:0] == 3'b110; - cen3qb <= cencnt[2:0] == 3'b010; - cen1p5 <= cencnt[3:0] == 4'd0; - cen1p5b<= cencnt[3:0] == 4'b1000; + cen2 <= cencnt2 == 4'd0; end endmodule \ No newline at end of file diff --git a/rtl/JTFRAME/jtframe_resync.v b/rtl/JTFRAME/jtframe_resync.v new file mode 100644 index 0000000..01dfa55 --- /dev/null +++ b/rtl/JTFRAME/jtframe_resync.v @@ -0,0 +1,108 @@ +/* This file is part of JT_FRAME. + JTFRAME 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 3 of the License, or + (at your option) any later version. + + JTFRAME 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 JTFRAME. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 25-9-2019 */ + +module jtframe_resync( + input clk, + input pxl_cen, + input hs_in, + input vs_in, + input LVBL, + input LHBL, + input [3:0] hoffset, + input [3:0] voffset, + output reg hs_out, + output reg vs_out +); + +parameter CNTW = 10; // max 1024 pixels/lines + +reg [CNTW-1:0] hs_pos[0:1], vs_hpos[0:1], vs_vpos[0:1],// relative positions of the original sync pulses + hs_len[0:1], vs_len[0:1], // count the length of the original sync pulses + hs_cnt, vs_cnt, // count the position of the original sync pulses + hs_hold, vs_hold; +reg last_LHBL, last_LVBL, last_hsin, last_vsin; + +wire hb_edge, hs_edge, hs_n_edge, vb_edge, vs_edge, vs_n_edge; +reg field; + +wire [CNTW-1:0] hpos_off = { {CNTW-4{hoffset[3]}}, hoffset[3:0] }; +wire [CNTW-1:0] htrip = hs_pos[field] + hpos_off; +wire [CNTW-1:0] vs_htrip = vs_hpos[field] + hpos_off; +wire [CNTW-1:0] vs_vtrip = vs_vpos[field] + { {CNTW-4{voffset[3]}}, voffset[3:0] }; + +assign hb_edge = LHBL && !last_LHBL; +assign hs_edge = hs_in && !last_hsin; +assign hs_n_edge = !hs_in && last_hsin; +assign vb_edge = LVBL && !last_LVBL; +assign vs_edge = vs_in && !last_vsin; +assign vs_n_edge = !vs_in && last_vsin; + +always @(posedge clk) if(pxl_cen) begin + last_LHBL <= LHBL; + last_LVBL <= LVBL; + last_hsin <= hs_in; + last_vsin <= vs_in; + + hs_cnt <= hb_edge ? {CNTW{1'b0}} : hs_cnt+1'b1; + if( vb_edge ) begin + vs_cnt <= {CNTW{1'b0}}; + field <= ~field; + end else if(hb_edge) + vs_cnt <= vs_cnt+1'b1; + + // Horizontal + if( hs_edge ) hs_pos[field] <= hs_cnt; + if( hs_n_edge ) hs_len[field] <= hs_cnt - hs_pos[field]; + + if( hs_cnt == htrip ) begin + hs_out <= 1; + hs_hold <= hs_len[field] - 1'b1; + end else begin + if( |hs_hold ) hs_hold <= hs_hold - 1'b1; + if( hs_hold == 0 ) hs_out <= 0; + end + + // Vertical + if( vs_edge ) begin + vs_hpos[field] <= hs_cnt; + vs_vpos[field] <= vs_cnt; + end + if( vs_n_edge ) vs_len[field] <= vs_cnt - vs_vpos[field]; + + if( hs_cnt == vs_htrip ) begin + if( vs_cnt == vs_vtrip ) begin + vs_hold <= vs_len[field] - 1'b1; + vs_out <= 1; + end else begin + if( |vs_hold ) vs_hold <= vs_hold - 1'b1; + if( vs_hold == 0 ) vs_out <= 0; + end + end + +end + +`ifdef SIMULATION +initial begin + hs_cnt = {CNTW{1'b0}}; + vs_cnt = {CNTW{1'b0}}; + hs_out = 0; + vs_out = 0; +end +`endif + +endmodule \ No newline at end of file diff --git a/rtl/charmap.v b/rtl/charmap.v new file mode 100644 index 0000000..f38a41c --- /dev/null +++ b/rtl/charmap.v @@ -0,0 +1,57 @@ +`timescale 1ns / 1ps +/*============================================================================ + Aznable (custom 8-bit computer system) - Casval (character map) + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-10-20 + + 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 3 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, see . +===========================================================================*/ + +module charmap ( + input clk, + input reset, + input [8:0] hcnt, + input [8:0] vcnt, + input [7:0] chrom_data_out, + input [7:0] fgcolram_data_out, + input [7:0] bgcolram_data_out, + input [7:0] chmap_data_out, + output [11:0] chram_addr, + output [11:0] chrom_addr, + output [7:0] r, + output [7:0] g, + output [7:0] b, + output a +); + +// Character map +wire [3:0] chpos_x = 4'd7 - hcnt[2:0]; +wire [2:0] chpos_y = vcnt[2:0]; +wire [5:0] chram_x = hcnt[8:3]; +wire [5:0] chram_y = vcnt[8:3]; +assign chram_addr = {chram_y, chram_x}; +assign chrom_addr = {1'b0, chmap_data_out[7:0], chpos_y}; +assign a = chrom_data_out[chpos_x[2:0]]; + +wire [2:0] r_temp = a ? fgcolram_data_out[2:0] : bgcolram_data_out[2:0]; +wire [2:0] g_temp = a ? fgcolram_data_out[5:3] : bgcolram_data_out[5:3]; +wire [1:0] b_temp = a ? fgcolram_data_out[7:6] : bgcolram_data_out[7:6]; + +assign r = {{2{r_temp}},2'b0}; +assign g = {{2{g_temp}},2'b0}; +assign b = {{3{b_temp}},2'b0}; + +endmodule \ No newline at end of file diff --git a/rtl/dpram.v b/rtl/dpram.v index a155273..c24eddc 100644 --- a/rtl/dpram.v +++ b/rtl/dpram.v @@ -40,8 +40,8 @@ module dpram #( initial begin if (init_file>0) begin - $display("Loading dpram from file:"); - $display(init_file); + // $display("Loading dpram from file:"); + // $display(init_file); $readmemh(init_file, mem); end end diff --git a/rtl/dpram_w1r2.v b/rtl/dpram_w1r2.v new file mode 100644 index 0000000..8b51888 --- /dev/null +++ b/rtl/dpram_w1r2.v @@ -0,0 +1,59 @@ +/*============================================================================ + Dual-port RAM module with single-width write port and double-width read port + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-10-29 + + 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 3 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, see . +===========================================================================*/ + +module dpram_w1r2 #( + parameter address_width = 10, + parameter data_width = 8, + parameter init_file= "" +) ( + input wire clock_a, + input wire wren_a, + input wire [address_width-1:0] address_a, + input wire [data_width-1:0] data_a, + + input wire clock_b, + input wire [address_width-1:0] address_b, + output reg [(data_width*2)-1:0] q_b +); + +initial begin + if (init_file>0) + begin + // $display("Loading dpram from file:"); + // $display(init_file); + $readmemh(init_file, mem); + end +end + +localparam ramLength = (2**address_width); +reg [data_width-1:0] mem [ramLength-1:0]; + +always @(posedge clock_a) begin + if(wren_a) begin + mem[address_a] <= data_a; + end +end + +always @(posedge clock_b) begin + q_b <= {mem[address_b], mem[address_b + 1'b1]}; +end + +endmodule \ No newline at end of file diff --git a/rtl/generic_timer.v b/rtl/generic_timer.v new file mode 100644 index 0000000..3afb976 --- /dev/null +++ b/rtl/generic_timer.v @@ -0,0 +1,56 @@ +`timescale 1ns / 1ps +/*============================================================================ + Aznable (custom 8-bit computer system) - Generic timer + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-10-20 + + 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 3 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, see . +===========================================================================*/ + +module generic_timer #( + parameter COUNTER_WIDTH = 16, + parameter DIVIDER_WIDTH = 15, + parameter INTERVAL = 15'd24000 +)( + input clk, + input reset, + output reg [COUNTER_WIDTH-1:0] counter +); + +reg [DIVIDER_WIDTH-1:0] divider = {DIVIDER_WIDTH{1'b0}}; + +always @(posedge clk or posedge reset) +begin + if(reset) + begin + counter <= {COUNTER_WIDTH{1'b0}}; + divider <= {DIVIDER_WIDTH{1'b0}}; + end + else + begin + if(divider==INTERVAL) + begin + counter <= counter + 1'b1; + divider <= {DIVIDER_WIDTH{1'b0}}; + end + else + begin + divider <= divider + 1'b1; + end + end +end + +endmodule \ No newline at end of file diff --git a/rtl/jt49/filter/jt49_dcrm.v b/rtl/jt49/filter/jt49_dcrm.v new file mode 100644 index 0000000..e84f2b1 --- /dev/null +++ b/rtl/jt49/filter/jt49_dcrm.v @@ -0,0 +1,56 @@ +/* This file is part of JT49. + + JT49 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 3 of the License, or + (at your option) any later version. + + JT49 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 JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-Jan-2019 + + */ + +// DC removal filter +// input is unsigned +// output is signed + +module jt49_dcrm( + input clk, + input cen, + input rst, + input [7:0] din, + output reg signed [7:0] dout +); + +wire signed [7:0] ave0, ave1; + +jt49_mave u_mave0( + .clk ( clk ), + .cen ( cen ), + .rst ( rst ), + .din ( {1'b0, din[7:1] } ), + .dout ( ave0 ) +); + +jt49_mave u_mave1( + .clk ( clk ), + .cen ( cen ), + .rst ( rst ), + .din ( ave0 ), + .dout ( ave1 ) +); + +always @(posedge clk) + if( cen ) + dout <= ({1'b0,din} - {ave1,1'b0})>>>1; + +endmodule \ No newline at end of file diff --git a/rtl/jt49/filter/jt49_dcrm2.v b/rtl/jt49/filter/jt49_dcrm2.v new file mode 100644 index 0000000..6646a30 --- /dev/null +++ b/rtl/jt49/filter/jt49_dcrm2.v @@ -0,0 +1,64 @@ +/* This file is part of JT49. + + JT49 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 3 of the License, or + (at your option) any later version. + + JT49 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 JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-Jan-2019 + + */ + +// DC removal filter +// input is unsigned +// output is signed + +module jt49_dcrm2 #(parameter sw=8) ( + input clk, + input cen, + input rst, + input [sw-1:0] din, + output signed [sw-1:0] dout +); + +localparam dw=10; // width of the decimal portion + +reg signed [sw+dw:0] integ, exact, error; +//reg signed [2*(9+dw)-1:0] mult; +// wire signed [sw+dw:0] plus1 = { {sw+dw{1'b0}},1'b1}; +reg signed [sw:0] pre_dout; +// reg signed [sw+dw:0] dout_ext; +reg signed [sw:0] q; + +always @(*) begin + exact = integ+error; + q = exact[sw+dw:dw]; + pre_dout = { 1'b0, din } - q; + //dout_ext = { pre_dout, {dw{1'b0}} }; + //mult = dout_ext; +end + +assign dout = pre_dout[sw-1:0]; + +always @(posedge clk) + if( rst ) begin + integ <= {sw+dw+1{1'b0}}; + error <= {sw+dw+1{1'b0}}; + end else if( cen ) begin + /* verilator lint_off WIDTH */ + integ <= integ + pre_dout; //mult[sw+dw*2:dw]; + /* verilator lint_on WIDTH */ + error <= exact-{q, {dw{1'b0}}}; + end + +endmodule \ No newline at end of file diff --git a/rtl/jt49/filter/jt49_dly.v b/rtl/jt49/filter/jt49_dly.v new file mode 100644 index 0000000..7142ec9 --- /dev/null +++ b/rtl/jt49/filter/jt49_dly.v @@ -0,0 +1,67 @@ +/* This file is part of JT49. + + JT49 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 3 of the License, or + (at your option) any later version. + + JT49 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 JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-Jan-2019 + + */ + +// Delay stage +// use for long delays + +module jt49_dly #(parameter dw=8, depth=10)( + input clk, + input cen, + input rst, + input [7:0] din, + output reg [7:0] dout, + output reg [7:0] pre_dout + +); + +reg [depth-1:0] rdpos, wrpos; + + +// memory +reg [dw-1:0] ram[0:2**depth-1]; +always @(posedge clk) + if(rst) + pre_dout <= {dw{1'b0}}; + else begin + pre_dout <= ram[rdpos]; + if( cen ) ram[wrpos] <= din; + end + +`ifdef SIMULATION +integer k; +initial begin + for(k=0;k<=2**depth-1;k=k+1) + ram[k] = 0; +end +`endif + +always @(posedge clk) + if( rst ) begin + rdpos <= { {depth-1{1'b0}}, 1'b1}; + wrpos <= {depth{1'b1}}; + dout <= {dw{1'b0}}; + end else if(cen) begin + dout <= pre_dout; + rdpos <= rdpos+1'b1; + wrpos <= wrpos+1'b1; + end + +endmodule // jt49_dly \ No newline at end of file diff --git a/rtl/jt49/filter/jt49_mave.v b/rtl/jt49/filter/jt49_mave.v new file mode 100644 index 0000000..2d02393 --- /dev/null +++ b/rtl/jt49/filter/jt49_mave.v @@ -0,0 +1,60 @@ +/* This file is part of JT49. + + JT49 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 3 of the License, or + (at your option) any later version. + + JT49 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 JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 15-Jan-2019 + + */ + +// Moving averager + +module jt49_mave #(parameter depth=8, dw=8)( + input clk, + input cen, + input rst, + input signed [dw-1:0] din, + output signed [dw-1:0] dout +); + +wire [dw-1:0] dly0; +wire [dw-1:0] pre_dly0; + +jt49_dly #(.depth(depth),.dw(dw)) u_dly0( + .clk ( clk ), + .cen ( cen ), + .rst ( rst ), + .din ( din ), + .dout ( dly0 ), + .pre_dout ( pre_dly0 ) +); + +// moving average +// D=2048 +reg signed [dw:0] diff; +reg signed [dw+depth-1:0] sum; + + +always @(posedge clk) + if( rst ) begin + diff <= {dw+1{1'd0}}; + sum <= {dw+depth+1{1'd0}}; + end else if(cen) begin + diff <= {1'b0,din } - { 1'b0, dly0 }; + sum <= { {depth{diff[dw]}}, diff } + sum; + end +assign dout = sum[dw+depth-1:depth]; + +endmodule \ No newline at end of file diff --git a/rtl/jt49/jt49.qip b/rtl/jt49/jt49.qip new file mode 100644 index 0000000..6568ae9 --- /dev/null +++ b/rtl/jt49/jt49.qip @@ -0,0 +1,7 @@ +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_bus.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_div.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_cen.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_eg.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_exp.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt49_noise.v ] diff --git a/rtl/jt49/jt49.v b/rtl/jt49/jt49.v new file mode 100644 index 0000000..d91dbf6 --- /dev/null +++ b/rtl/jt49/jt49.v @@ -0,0 +1,248 @@ +/* This file is part of JT49. + + JT49 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 3 of the License, or + (at your option) any later version. + + JT49 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 JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 10-Nov-2018 + + Based on sqmusic, by the same author + + */ + +module jt49 ( // note that input ports are not multiplexed + input rst_n, + input clk, // signal on positive edge + input clk_en /* synthesis direct_enable = 1 */, + input [3:0] addr, + input cs_n, + input wr_n, // write + input [7:0] din, + input sel, // if sel is low, the clock is divided by 2 + output reg [7:0] dout, + output reg [9:0] sound, // combined channel output + output reg [7:0] A, // linearised channel output + output reg [7:0] B, + output reg [7:0] C, + output sample, + + input [7:0] IOA_in, + output [7:0] IOA_out, + + input [7:0] IOB_in, + output [7:0] IOB_out +); + +parameter [1:0] COMP=2'b00; +parameter CLKDIV=3; +wire [1:0] comp = COMP; + +reg [7:0] regarray[15:0]; +wire [7:0] port_A, port_B; + +wire [4:0] envelope; +wire bitA, bitB, bitC; +wire noise; +reg Amix, Bmix, Cmix; + +wire cen16, cen256; + +assign IOA_out = regarray[14]; +assign IOB_out = regarray[15]; +assign port_A = !regarray[7][6] ? IOA_in : IOA_out; +assign port_B = !regarray[7][7] ? IOB_in : IOB_out; +assign sample = cen16; + +jt49_cen #(.CLKDIV(CLKDIV)) u_cen( + .clk ( clk ), + .rst_n ( rst_n ), + .cen ( clk_en ), + .sel ( sel ), + .cen16 ( cen16 ), + .cen256 ( cen256 ) +); + +// internal modules operate at clk/16 +jt49_div #(12) u_chA( + .clk ( clk ), + .rst_n ( rst_n ), + .cen ( cen16 ), + .period ( {regarray[1][3:0], regarray[0][7:0] } ), + .div ( bitA ) +); + +jt49_div #(12) u_chB( + .clk ( clk ), + .rst_n ( rst_n ), + .cen ( cen16 ), + .period ( {regarray[3][3:0], regarray[2][7:0] } ), + .div ( bitB ) +); + +jt49_div #(12) u_chC( + .clk ( clk ), + .rst_n ( rst_n ), + .cen ( cen16 ), + .period ( {regarray[5][3:0], regarray[4][7:0] } ), + .div ( bitC ) +); + +jt49_noise u_ng( + .clk ( clk ), + .cen ( cen16 ), + .rst_n ( rst_n ), + .period ( regarray[6][4:0] ), + .noise ( noise ) +); + +// envelope generator +wire eg_step; +wire [15:0] eg_period = {regarray[4'hc],regarray[4'hb]}; +wire null_period = eg_period == 16'h0; + +jt49_div #(16) u_envdiv( + .clk ( clk ), + .cen ( cen256 ), + .rst_n ( rst_n ), + .period ( eg_period ), + .div ( eg_step ) +); + +reg eg_restart; + +jt49_eg u_env( + .clk ( clk ), + .cen ( cen256 ), + .step ( eg_step ), + .rst_n ( rst_n ), + .restart ( eg_restart ), + .null_period( null_period ), + .ctrl ( regarray[4'hD][3:0] ), + .env ( envelope ) +); + +reg [4:0] logA, logB, logC, log; +wire [7:0] lin; + +jt49_exp u_exp( + .clk ( clk ), + .comp ( comp ), + .din ( log ), + .dout ( lin ) +); + +wire [4:0] volA = { regarray[ 8][3:0], regarray[ 8][3] }; +wire [4:0] volB = { regarray[ 9][3:0], regarray[ 9][3] }; +wire [4:0] volC = { regarray[10][3:0], regarray[10][3] }; +wire use_envA = regarray[ 8][4]; +wire use_envB = regarray[ 9][4]; +wire use_envC = regarray[10][4]; +wire use_noA = regarray[ 7][3]; +wire use_noB = regarray[ 7][4]; +wire use_noC = regarray[ 7][5]; + +reg [3:0] acc_st; + +always @(posedge clk) if( clk_en ) begin + Amix <= (noise|use_noA) & (bitA|regarray[7][0]); + Bmix <= (noise|use_noB) & (bitB|regarray[7][1]); + Cmix <= (noise|use_noC) & (bitC|regarray[7][2]); + + logA <= !Amix ? 5'd0 : (use_envA ? envelope : volA ); + logB <= !Bmix ? 5'd0 : (use_envB ? envelope : volB ); + logC <= !Cmix ? 5'd0 : (use_envC ? envelope : volC ); +end + +reg [9:0] acc; + +always @(posedge clk, negedge rst_n) begin + if( !rst_n ) begin + acc_st <= 4'b1; + acc <= 10'd0; + A <= 8'd0; + B <= 8'd0; + C <= 8'd0; + sound <= 10'd0; + end else if(clk_en) begin + acc_st <= { acc_st[2:0], acc_st[3] }; + acc <= acc + {2'b0,lin}; + case( acc_st ) + 4'b0001: begin + log <= logA; + acc <= 10'd0; + sound <= acc; + end + 4'b0010: begin + A <= lin; + log <= logB; + end + 4'b0100: begin + B <= lin; + log <= logC; + end + 4'b1000: begin // last sum + C <= lin; + end + default:; + endcase + end +end + +reg [7:0] read_mask; + +always @(*) + case(addr) + 4'h0,4'h2,4'h4,4'h7,4'hb,4'hc,4'he,4'hf: + read_mask = 8'hff; + 4'h1,4'h3,4'h5,4'hd: + read_mask = 8'h0f; + 4'h6,4'h8,4'h9,4'ha: + read_mask = 8'h1f; + endcase // addr + +// register array +wire write; +reg last_write; +wire wr_edge = write & ~last_write; + +assign write = !wr_n && !cs_n; + +always @(posedge clk, negedge rst_n) begin + if( !rst_n ) begin + dout <= 8'd0; + last_write <= 0; + eg_restart <= 0; + regarray[0]<=8'd0; regarray[4]<=8'd0; regarray[ 8]<=8'd0; regarray[12]<=8'd0; + regarray[1]<=8'd0; regarray[5]<=8'd0; regarray[ 9]<=8'd0; regarray[13]<=8'd0; + regarray[2]<=8'd0; regarray[6]<=8'd0; regarray[10]<=8'd0; regarray[14]<=8'd0; + regarray[3]<=8'd0; regarray[7]<=8'd0; regarray[11]<=8'd0; regarray[15]<=8'd0; + end else begin + last_write <= write; + // Data read + case( addr ) + 4'he: dout <= port_A; + 4'hf: dout <= port_B; + default: dout <= regarray[ addr ] & read_mask; + endcase + // Data write + if( write ) begin + regarray[addr] <= din; + if ( addr == 4'hD && wr_edge ) eg_restart <= 1; + end else begin + eg_restart <= 0; + end + end +end + +endmodule diff --git a/rtl/jt49/jt49_bus.v b/rtl/jt49/jt49_bus.v new file mode 100644 index 0000000..b7639d9 --- /dev/null +++ b/rtl/jt49/jt49_bus.v @@ -0,0 +1,101 @@ +/* This file is part of JT49. + + JT49 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 3 of the License, or + (at your option) any later version. + + JT49 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 JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 28-Jan-2019 + + Based on sqmusic, by the same author + + */ + +// This is a wrapper with the BDIR/BC1 pins + +module jt49_bus ( // note that input ports are not multiplexed + input rst_n, + input clk, // signal on positive edge + input clk_en /* synthesis direct_enable = 1 */, + // bus control pins of original chip + input bdir, + input bc1, + input [7:0] din, + + input sel, // if sel is low, the clock is divided by 2 + output [7:0] dout, + output [9:0] sound, // combined channel output + output [7:0] A, // linearised channel output + output [7:0] B, + output [7:0] C, + output sample, + + input [7:0] IOA_in, + output [7:0] IOA_out, + + input [7:0] IOB_in, + output [7:0] IOB_out +); + +parameter [1:0] COMP=2'b00; + +reg wr_n, cs_n; +reg [3:0] addr; +reg addr_ok; +reg [7:0] din_latch; + +always @(posedge clk) + if( !rst_n ) begin + wr_n <= 1'b1; + cs_n <= 1'b1; + addr <= 4'd0; + addr_ok <= 1'b1; + end else begin // I/O cannot use clk_en + // addr must be + case( {bdir,bc1} ) + 2'b00: { wr_n, cs_n } <= 2'b11; + 2'b01: { wr_n, cs_n } <= addr_ok ? 2'b10 : 2'b11; + 2'b10: begin + { wr_n, cs_n } <= addr_ok ? 2'b00 : 2'b11; + din_latch <= din; + end + 2'b11: begin + { wr_n, cs_n } <= 2'b11; + addr <= din[3:0]; + addr_ok <= din[7:4] == 4'd0; + end + endcase // {bdir,bc1} + end + +jt49 #(.COMP(COMP)) u_jt49( // note that input ports are not multiplexed + .rst_n ( rst_n ), + .clk ( clk ), // signal on positive edge + .clk_en ( clk_en ), // clock enable on negative edge + .addr ( addr[3:0] ), + .cs_n ( cs_n ), + .wr_n ( wr_n ), // write + .din ( din_latch ), + .sel ( sel ), // if sel is low, the clock is divided by 2 + .dout ( dout ), + .sound ( sound ), // combined channel output + .sample ( sample ), + .A ( A ), // linearised channel output + .B ( B ), + .C ( C ), + .IOA_in ( IOA_in ), + .IOA_out( IOA_out ), + .IOB_in ( IOB_in ), + .IOB_out( IOB_out ) +); + +endmodule // jt49_bus \ No newline at end of file diff --git a/rtl/jt49/jt49_cen.v b/rtl/jt49/jt49_cen.v new file mode 100644 index 0000000..671eceb --- /dev/null +++ b/rtl/jt49/jt49_cen.v @@ -0,0 +1,55 @@ +/* This file is part of JT49. + + JT49 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 3 of the License, or + (at your option) any later version. + + JT49 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 JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 10-Nov-2018 + + Based on sqmusic, by the same author + + */ + +module jt49_cen( + input clk, + input rst_n, + input cen, // base clock enable signal + input sel, // when low, divide by 2 once more + output reg cen16, + output reg cen256 +); + +reg [9:0] cencnt; +parameter CLKDIV = 3; // use 3 for standalone JT49 or 2 +localparam eg = CLKDIV; //8; + +wire toggle16 = sel ? ~|cencnt[CLKDIV-1:0] : ~|cencnt[CLKDIV:0]; +wire toggle256= sel ? ~|cencnt[eg-2:0] : ~|cencnt[eg-1:0]; + + +always @(posedge clk, negedge rst_n) begin + if(!rst_n) + cencnt <= 10'd0; + else begin + if(cen) cencnt <= cencnt+10'd1; + end +end + +always @(posedge clk) begin + cen16 <= cen & toggle16; + cen256 <= cen & toggle256; +end + + +endmodule // jt49_cen diff --git a/rtl/jt49/jt49_div.v b/rtl/jt49/jt49_div.v new file mode 100644 index 0000000..ac4564c --- /dev/null +++ b/rtl/jt49/jt49_div.v @@ -0,0 +1,52 @@ +/* This file is part of JT49. + + JT49 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 3 of the License, or + (at your option) any later version. + + JT49 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 JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 10-Nov-2018 + + Based on sqmusic, by the same author + + */ + + +module jt49_div #(parameter W=12 )( + (* direct_enable *) input cen, + input clk, // this is the divided down clock from the core + input rst_n, + input [W-1:0] period, + output reg div +); + +reg [W-1:0]count; + +wire [W-1:0] one = { {W-1{1'b0}}, 1'b1}; + +always @(posedge clk, negedge rst_n ) begin + if( !rst_n) begin + count <= one; + div <= 1'b0; + end + else if(cen) begin + if( count>=period ) begin + count <= one; + div <= ~div; + end + else + /*if( period!={W{1'b0}} )*/ count <= count + one ; + end +end + +endmodule diff --git a/rtl/jt49/jt49_eg.v b/rtl/jt49/jt49_eg.v new file mode 100644 index 0000000..46dd62a --- /dev/null +++ b/rtl/jt49/jt49_eg.v @@ -0,0 +1,88 @@ +/* This file is part of JT49. + + JT49 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 3 of the License, or + (at your option) any later version. + + JT49 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 JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 10-Nov-2018 + + Based on sqmusic, by the same author + + */ + +module jt49_eg( + (* direct_enable *) input cen, + input clk, // this is the divided down clock from the core + input step, + input null_period, + input rst_n, + input restart, + input [3:0] ctrl, + output reg [4:0]env +); + +reg inv, stop; +reg [4:0] gain; + +wire CONT = ctrl[3]; +wire ATT = ctrl[2]; +wire ALT = ctrl[1]; +wire HOLD = ctrl[0]; + +wire will_hold = !CONT || HOLD; + +always @(posedge clk) + if( cen ) env <= inv ? ~gain : gain; + +reg last_step; +wire step_edge = (step && !last_step) || null_period; +wire will_invert = (!CONT&&ATT) || (CONT&&ALT); +reg rst_latch, rst_clr; + +always @(posedge clk) begin + if( restart ) rst_latch <= 1; + else if(rst_clr ) rst_latch <= 0; +end + +always @( posedge clk, negedge rst_n ) + if( !rst_n) begin + gain <= 5'h1F; + inv <= 0; + stop <= 0; + rst_clr <= 0; + end + else if( cen ) begin + last_step <= step; + if( rst_latch ) begin + gain <= 5'h1F; + inv <= ATT; + stop <= 1'b0; + rst_clr <= 1; + end + else begin + rst_clr <= 0; + if (step_edge && !stop) begin + if( gain==5'h00 ) begin + if( will_hold ) + stop <= 1'b1; + else + gain <= gain-5'b1; + if( will_invert ) inv<=~inv; + end + else gain <= gain-5'b1; + end + end + end + +endmodule diff --git a/rtl/jt49/jt49_exp.v b/rtl/jt49/jt49_exp.v new file mode 100644 index 0000000..412a3f8 --- /dev/null +++ b/rtl/jt49/jt49_exp.v @@ -0,0 +1,174 @@ +/* This file is part of JT49. + + JT49 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 3 of the License, or + (at your option) any later version. + + JT49 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 JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 10-Nov-2018 + + Based on sqmusic, by the same author + + */ + + +// Compression vs dynamic range +// 0 -> 43.6dB +// 1 -> 29.1 +// 2 -> 21.8 +// 3 -> 13.4 + +module jt49_exp( + input clk, + input [1:0] comp, // compression + input [4:0] din, + output reg [7:0] dout +); + +reg [7:0] lut[0:127]; + +always @(posedge clk) + dout <= lut[ {comp,din} ]; + +initial begin + lut[0] = 8'd0; + lut[1] = 8'd1; + lut[2] = 8'd1; + lut[3] = 8'd1; + lut[4] = 8'd2; + lut[5] = 8'd2; + lut[6] = 8'd3; + lut[7] = 8'd3; + lut[8] = 8'd4; + lut[9] = 8'd5; + lut[10] = 8'd6; + lut[11] = 8'd7; + lut[12] = 8'd9; + lut[13] = 8'd11; + lut[14] = 8'd13; + lut[15] = 8'd15; + lut[16] = 8'd18; + lut[17] = 8'd22; + lut[18] = 8'd26; + lut[19] = 8'd31; + lut[20] = 8'd37; + lut[21] = 8'd45; + lut[22] = 8'd53; + lut[23] = 8'd63; + lut[24] = 8'd75; + lut[25] = 8'd90; + lut[26] = 8'd107; + lut[27] = 8'd127; + lut[28] = 8'd151; + lut[29] = 8'd180; + lut[30] = 8'd214; + lut[31] = 8'd255; + lut[32] = 8'd0; + lut[33] = 8'd7; + lut[34] = 8'd8; + lut[35] = 8'd10; + lut[36] = 8'd11; + lut[37] = 8'd12; + lut[38] = 8'd14; + lut[39] = 8'd15; + lut[40] = 8'd17; + lut[41] = 8'd20; + lut[42] = 8'd22; + lut[43] = 8'd25; + lut[44] = 8'd28; + lut[45] = 8'd31; + lut[46] = 8'd35; + lut[47] = 8'd40; + lut[48] = 8'd45; + lut[49] = 8'd50; + lut[50] = 8'd56; + lut[51] = 8'd63; + lut[52] = 8'd71; + lut[53] = 8'd80; + lut[54] = 8'd90; + lut[55] = 8'd101; + lut[56] = 8'd113; + lut[57] = 8'd127; + lut[58] = 8'd143; + lut[59] = 8'd160; + lut[60] = 8'd180; + lut[61] = 8'd202; + lut[62] = 8'd227; + lut[63] = 8'd255; + lut[64] = 8'd0; + lut[65] = 8'd18; + lut[66] = 8'd20; + lut[67] = 8'd22; + lut[68] = 8'd24; + lut[69] = 8'd26; + lut[70] = 8'd29; + lut[71] = 8'd31; + lut[72] = 8'd34; + lut[73] = 8'd37; + lut[74] = 8'd41; + lut[75] = 8'd45; + lut[76] = 8'd49; + lut[77] = 8'd53; + lut[78] = 8'd58; + lut[79] = 8'd63; + lut[80] = 8'd69; + lut[81] = 8'd75; + lut[82] = 8'd82; + lut[83] = 8'd90; + lut[84] = 8'd98; + lut[85] = 8'd107; + lut[86] = 8'd116; + lut[87] = 8'd127; + lut[88] = 8'd139; + lut[89] = 8'd151; + lut[90] = 8'd165; + lut[91] = 8'd180; + lut[92] = 8'd196; + lut[93] = 8'd214; + lut[94] = 8'd233; + lut[95] = 8'd255; + lut[96] = 8'd0; + lut[97] = 8'd51; + lut[98] = 8'd54; + lut[99] = 8'd57; + lut[100] = 8'd60; + lut[101] = 8'd63; + lut[102] = 8'd67; + lut[103] = 8'd70; + lut[104] = 8'd74; + lut[105] = 8'd78; + lut[106] = 8'd83; + lut[107] = 8'd87; + lut[108] = 8'd92; + lut[109] = 8'd97; + lut[110] = 8'd103; + lut[111] = 8'd108; + lut[112] = 8'd114; + lut[113] = 8'd120; + lut[114] = 8'd127; + lut[115] = 8'd134; + lut[116] = 8'd141; + lut[117] = 8'd149; + lut[118] = 8'd157; + lut[119] = 8'd166; + lut[120] = 8'd175; + lut[121] = 8'd185; + lut[122] = 8'd195; + lut[123] = 8'd206; + lut[124] = 8'd217; + lut[125] = 8'd229; + lut[126] = 8'd241; + lut[127] = 8'd255; + +end +endmodule diff --git a/rtl/jt49/jt49_noise.v b/rtl/jt49/jt49_noise.v new file mode 100644 index 0000000..ffc1fb9 --- /dev/null +++ b/rtl/jt49/jt49_noise.v @@ -0,0 +1,62 @@ +/* This file is part of JT49. + + JT49 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 3 of the License, or + (at your option) any later version. + + JT49 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 JT49. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 10-Nov-2018 + + Based on sqmusic, by the same author + + */ + + +module jt49_noise( + (* direct_enable *) input cen, + input clk, + input rst_n, + input [4:0] period, + output reg noise +); + +reg [5:0]count; +reg [16:0]poly17; +wire poly17_zero = poly17==17'b0; +wire noise_en; +reg last_en; + +wire noise_up = noise_en && !last_en; + +always @(posedge clk ) if(cen) begin + noise <= ~poly17[0]; +end + +always @( posedge clk, negedge rst_n ) + if( !rst_n ) + poly17 <= 17'd0; + else if( cen ) begin + last_en <= noise_en; + if( noise_up ) + poly17 <= { poly17[0] ^ poly17[3] ^ poly17_zero, poly17[16:1] }; + end + +jt49_div #(5) u_div( + .clk ( clk ), + .cen ( cen ), + .rst_n ( rst_n ), + .period ( period ), + .div ( noise_en ) +); + +endmodule \ No newline at end of file diff --git a/rtl/jt5205/jt5205.qip b/rtl/jt5205/jt5205.qip new file mode 100644 index 0000000..cfa67c3 --- /dev/null +++ b/rtl/jt5205/jt5205.qip @@ -0,0 +1,4 @@ +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt5205.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt5205_adpcm.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt5205_timing.v ] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) jt5205_interpol2x.v ] \ No newline at end of file diff --git a/rtl/jt5205/jt5205.v b/rtl/jt5205/jt5205.v new file mode 100644 index 0000000..0ada1a3 --- /dev/null +++ b/rtl/jt5205/jt5205.v @@ -0,0 +1,92 @@ +/* This file is part of JT5205. + JT5205 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 3 of the License, or + (at your option) any later version. + + JT5205 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 JT5205. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 30-10-2019 */ + +module jt5205( + input rst, + input clk, + input cen /* direct_enable */, + input [ 1:0] sel, // s pin + input [ 3:0] din, + output signed [11:0] sound, + output sample, + // This output pin is not part of MSM5205 I/O + // It helps integrating the system as it produces + // a strobe + // at the internal clock divider pace + output irq, + output vclk_o + `ifdef JT5205_DEBUG + , + output signed [11:0] debug_raw, + output debug_cen_lo + `endif +); + +// Enabling the interpolator changes the sound of Chun Li's beat in +// SF2 too much. So I decided to disable it +parameter INTERPOL=0; // 1 for simple linear interpolation. 0 for raw output + +wire cen_lo, cen_mid; +wire signed [11:0] raw; + +assign irq=cen_lo; // Notice that irq is active even if rst is high. This is + // important for games such as Tora e no michi. + +`ifdef JT5205_DEBUG +assign debug_raw = raw; +assign debug_cen_lo = cen_lo; +`endif + + +jt5205_timing u_timing( + .clk ( clk ), + .cen ( cen ), + .sel ( sel ), + .cen_lo ( cen_lo ), + .cen_mid( cen_mid ), + .cenb_lo( ), + .vclk_o (vclk_o ) +); + +jt5205_adpcm u_adpcm( + .rst ( rst ), + .clk ( clk ), + .cen_lo ( cen_lo ), + .cen_hf ( cen ), + .din ( din ), + .sound ( raw ) +); + +generate + if( INTERPOL == 1 ) begin + jt5205_interpol2x u_interpol( + .rst ( rst ), + .clk ( clk ), + .cen_mid( cen_mid ), + .din ( raw ), + .dout ( sound ) + ); + assign sample=cen_mid; // 2x the original sampling freq. because of interpolator + end else begin + assign sound = raw; + assign sample = cen_lo; + end +endgenerate + + +endmodule \ No newline at end of file diff --git a/rtl/jt5205/jt5205_adpcm.v b/rtl/jt5205/jt5205_adpcm.v new file mode 100644 index 0000000..840536c --- /dev/null +++ b/rtl/jt5205/jt5205_adpcm.v @@ -0,0 +1,120 @@ +/* This file is part of JT5205. + JT5205 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 3 of the License, or + (at your option) any later version. + + JT5205 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 JT5205. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 30-10-2019 */ + +module jt5205_adpcm( + input rst, + input clk, + (* direct_enable *) input cen_hf, + (* direct_enable *) input cen_lo, + input [ 3:0] din, + output reg signed [11:0] sound +); + +reg [ 5:0] delta_idx, idx_inc; +reg [10:0] delta[0:48]; + +reg [11:0] dn; +reg [12:0] qn; +reg up; +reg [ 2:0] factor; +reg [ 3:0] din_copy; +reg [ 5:0] next_idx; +reg signed [13:0] unlim; + +`ifdef SIMULATION +initial begin + sound = -12'd2; +end +`endif + +always @(posedge clk, posedge rst) begin + if( rst ) begin + factor <= 3'd0; + up <= 1'b0; + next_idx <= 6'd0; + dn <= 12'd0; + qn <= 13'd0; + end else if(cen_hf) begin + up <= cen_lo; + if( up ) begin + factor <= din_copy[2:0]; + dn <= { 1'b0, delta[delta_idx] }; + qn <= { 2'd0, delta[delta_idx]>>3}; + next_idx <= din_copy[2] ? (delta_idx+idx_inc) : (delta_idx-6'd1); + end else begin + if(factor[2]) begin + qn <= qn + {1'b0, dn }; + end + dn <= dn>>1; + factor <= factor<<1; + if( next_idx>6'd48) + next_idx <= din_copy[2] ? 6'd48 : 6'd0; + end + end +end + +always @(posedge clk ) if(cen_lo) begin + if( rst ) begin + // sound fades away after a rst but the rest level must be -2 + // otherwise noises can be heard (e.g. intro scene of Double Dragon) + if( sound>12'd0 || sound < -12'd2 ) + sound <= sound >>> 1; + else + sound <= -12'd2; + end else begin + sound <= unlim[13:12]!={2{unlim[11]}} ? { unlim[13], {11{~unlim[13]}}} : unlim[11:0]; + end +end + +function signed [13:0] extend; + input signed [11:0] a; + extend = { {2{a[11]}}, a }; +endfunction + +always @(*) begin + unlim = din_copy[3] ? extend(sound) - {1'b0, qn} : + extend(sound) + {1'b0, qn}; +end + +always @(posedge clk, posedge rst) begin + if( rst ) begin + delta_idx <= 6'd0; + din_copy <= 4'd0; + end else if(cen_lo) begin + case( din[1:0] ) + 2'd0: idx_inc <= 6'd2; + 2'd1: idx_inc <= 6'd4; + 2'd2: idx_inc <= 6'd6; + 2'd3: idx_inc <= 6'd8; + endcase + din_copy <= din; + delta_idx <= next_idx; + end +end + +initial begin +delta[ 0] = 11'd0016; delta[ 1] = 11'd0017; delta[ 2] = 11'd0019; delta[ 3] = 11'd0021; delta[ 4] = 11'd0023; delta[ 5] = 11'd0025; delta[ 6] = 11'd0028; +delta[ 7] = 11'd0031; delta[ 8] = 11'd0034; delta[ 9] = 11'd0037; delta[10] = 11'd0041; delta[11] = 11'd0045; delta[12] = 11'd0050; delta[13] = 11'd0055; +delta[14] = 11'd0060; delta[15] = 11'd0066; delta[16] = 11'd0073; delta[17] = 11'd0080; delta[18] = 11'd0088; delta[19] = 11'd0097; delta[20] = 11'd0107; +delta[21] = 11'd0118; delta[22] = 11'd0130; delta[23] = 11'd0143; delta[24] = 11'd0157; delta[25] = 11'd0173; delta[26] = 11'd0190; delta[27] = 11'd0209; +delta[28] = 11'd0230; delta[29] = 11'd0253; delta[30] = 11'd0279; delta[31] = 11'd0307; delta[32] = 11'd0337; delta[33] = 11'd0371; delta[34] = 11'd0408; +delta[35] = 11'd0449; delta[36] = 11'd0494; delta[37] = 11'd0544; delta[38] = 11'd0598; delta[39] = 11'd0658; delta[40] = 11'd0724; delta[41] = 11'd0796; +delta[42] = 11'd0876; delta[43] = 11'd0963; delta[44] = 11'd1060; delta[45] = 11'd1166; delta[46] = 11'd1282; delta[47] = 11'd1411; delta[48] = 11'd1552; +end + +endmodule \ No newline at end of file diff --git a/rtl/jt5205/jt5205_interpol2x.v b/rtl/jt5205/jt5205_interpol2x.v new file mode 100644 index 0000000..d77dd82 --- /dev/null +++ b/rtl/jt5205/jt5205_interpol2x.v @@ -0,0 +1,43 @@ +/* This file is part of JT5205. + JT5205 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 3 of the License, or + (at your option) any later version. + + JT5205 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 JT5205. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 30-12-2019 */ + +// Simple 2x interpolator +// Reduces HF content without altering too much the +// original sound + +module jt5205_interpol2x( + input rst, + input clk, + (* direct_enable *) input cen_mid, + input signed [11:0] din, + output reg signed [11:0] dout +); + +reg signed [11:0] last; + +always @(posedge clk, posedge rst) begin + if(rst) begin + last <= 12'd0; + dout <= 12'd0; + end else if(cen_mid) begin + last <= din; + dout <= (last>>>1)+(din>>>1); + end +end + +endmodule diff --git a/rtl/jt5205/jt5205_timing.v b/rtl/jt5205/jt5205_timing.v new file mode 100644 index 0000000..542d74f --- /dev/null +++ b/rtl/jt5205/jt5205_timing.v @@ -0,0 +1,69 @@ +/* This file is part of JT5205. + JT5205 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 3 of the License, or + (at your option) any later version. + + JT5205 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 JT5205. If not, see . + + Author: Jose Tejada Gomez. Twitter: @topapate + Version: 1.0 + Date: 30-10-2019 */ + +module jt5205_timing( + input clk, + (* direct_enable *) input cen, + input [ 1:0] sel, // s pin + output cen_lo, // sample rate + output cenb_lo, // sample rate (opposite phase) + output cen_mid, // 2x sample rate + output reg vclk_o +); + +reg [6:0] cnt=7'd0; +reg pre=1'b0, preb=1'b0; +reg [6:0] lim; + +always @(posedge clk) begin + case(sel) + 2'd0: lim <= 7'd95; + 2'd1: lim <= 7'd63; + 2'd2: lim <= 7'd47; + 2'd3: lim <= 7'd1; + endcase +end + +always @(posedge clk) begin + + if (sel == 2'd3) begin + cnt <= 7'd0; + vclk_o <= 1'b0; + end + if(cen) begin + if (sel != 2'd3) cnt <= cnt + 7'd1; + + pre <= 1'b0; + preb <= 1'b0; + if(cnt==lim) begin + vclk_o <= 1'b1; + cnt <= 7'd0; + pre <= 1'b1; + end + if(cnt==(lim>>1)) begin + preb <=1'b1; + vclk_o <= 1'b0; + end + end +end + +assign cen_lo = pre &cen; +assign cenb_lo = preb&cen; +assign cen_mid = (pre|preb)&cen; + +endmodule \ No newline at end of file diff --git a/rtl/lfsr.v b/rtl/lfsr.v new file mode 100644 index 0000000..cc0c0b7 --- /dev/null +++ b/rtl/lfsr.v @@ -0,0 +1,41 @@ +/*============================================================================ + Aznable (custom 8-bit computer system) - Linear-feedback shift register + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-06 + + Based on Project F: Ad Astra - Starfield + (C)2021 Will Green, open source hardware released under the MIT License + Learn more at https://projectf.io + + 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 3 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, see . +===========================================================================*/ + +module lfsr #( + parameter LEN=8, // shift register length + parameter TAPS=8'b10111000 // XOR taps + ) ( + input wire clk, // clock + input wire rst, // reset + input wire en, // enable + input wire [LEN-1:0] seed, + output reg [LEN-1:0] sreg // lfsr output + ); + + always @(posedge clk) begin + if (en) sreg <= {1'b0, sreg[LEN-1:1]} ^ (sreg[0] ? TAPS : {LEN{1'b0}}); + if (rst) sreg <= seed; + end +endmodule \ No newline at end of file diff --git a/rtl/music.hex b/rtl/music.hex new file mode 100644 index 0000000..5147457 --- /dev/null +++ b/rtl/music.hex @@ -0,0 +1,4096 @@ + 59 4d 36 21 4c 65 4f 6e 41 72 44 21 00 00 08 00 + 00 00 00 01 00 00 00 1e 84 80 00 32 00 00 04 00 + 00 00 55 6e 74 69 74 6c 65 64 20 2d 20 53 75 62 + 73 6f 6e 67 00 00 49 6d 70 6f 72 74 65 64 20 66 + 72 6f 6d 20 4d 69 64 69 20 62 79 20 41 72 6b 6f + 73 20 54 72 61 63 6b 65 72 20 32 00 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 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 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 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 61 61 61 61 61 61 61 61 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 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 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 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 61 61 61 61 61 61 61 61 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 8a 20 84 + e8 4c 4c 4c 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 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 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 8a 20 84 + e8 4c 4c 4c 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 61 61 61 61 + 61 61 61 61 61 61 61 61 61 61 61 61 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 8a 20 84 + e8 4c 4c 4c e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 8a 20 84 + e8 4c 4c 4c 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 8a 20 84 + e8 4c 4c 4c 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 + 35 35 35 35 35 35 35 35 35 35 35 35 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 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 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 61 61 61 61 61 61 61 61 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 + e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 e7 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a + 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 7a 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 07 08 08 + 08 09 09 09 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 07 08 08 + 08 09 09 09 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 07 08 08 + 08 09 09 09 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 07 08 08 + 08 09 09 09 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 07 08 08 + 08 09 09 09 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 + 03 03 03 03 03 03 03 03 03 03 03 03 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 de de de de + de de de de 18 18 18 18 18 18 18 18 4d 4d 4d 4d + 4d 4d 4d 4d bd bd bd bd bd bd bd bd de de de de + de de de de 18 18 18 18 18 18 18 18 4d 4d 4d 4d + 4d 4d 4d 4d bd bd bd bd bd bd bd bd de de de de + de de de de 18 18 18 18 18 18 18 18 4d 4d 4d 4d + 4d 4d 4d 4d bd bd bd bd bd bd bd bd de de de de + de de de de 18 18 18 18 18 18 18 18 4d 4d 4d 4d + 4d 4d 4d 4d bd bd bd bd bd bd bd bd de de de de + de de de de 18 18 18 18 18 18 18 18 76 76 76 76 + 76 76 76 76 bd bd bd bd bd bd bd bd de de de de + de de de de 18 18 18 18 18 18 18 18 76 76 76 76 + 76 76 76 76 bd bd bd bd bd bd bd bd de de de de + de de de de 18 18 18 18 18 18 18 18 76 76 76 76 + 76 76 76 76 bd bd bd bd bd bd bd bd de de de de + de de de de 18 18 18 18 18 18 18 18 76 76 76 76 + 76 76 76 76 bd bd bd bd bd bd bd bd fa fa fa fa + fa fa fa fa 4d 4d 4d 4d 4d 4d 4d 4d a4 a4 a4 a4 + a4 a4 a4 a4 f3 f3 f3 f3 f3 f3 f3 f3 fa fa fa fa + fa fa fa fa 4d 4d 4d 4d 4d 4d 4d 4d a4 a4 a4 a4 + a4 a4 a4 a4 f3 f3 f3 f3 f3 f3 f3 f3 fa fa fa fa + fa fa fa fa 4d 4d 4d 4d 4d 4d 4d 4d a4 a4 a4 a4 + a4 a4 a4 a4 f3 f3 f3 f3 f3 f3 f3 f3 fa fa fa fa + fa fa fa fa 4d 4d 4d 4d 4d 4d 4d 4d a4 a4 a4 a4 + a4 a4 a4 a4 f3 f3 f3 f3 f3 f3 f3 f3 de de de de + de de de de 29 29 29 29 29 29 29 29 76 76 76 76 + 76 76 76 76 bd bd bd bd bd bd bd bd de de de de + de de de de 29 29 29 29 29 29 29 29 76 76 76 76 + 76 76 76 76 bd bd bd bd bd bd bd bd de de de de + de de de de 29 29 29 29 29 29 29 29 76 76 76 76 + 76 76 76 76 bd bd bd bd bd bd bd bd de de de de + de de de de 29 29 29 29 29 29 29 29 76 76 76 76 + 76 76 76 76 bd bd bd bd bd bd bd bd bd 8a 20 84 + e8 4c 4c 4c 18 18 18 18 18 18 18 18 4d 4d 4d 4d + 4d 4d 4d 4d bd bd bd bd bd bd bd bd de de de de + de de de de 18 18 18 18 18 18 18 18 18 ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 de de de de + de de de de 18 18 18 18 18 18 18 18 4d 4d 4d 4d + 4d 4d 4d 4d bd bd bd bd bd bd bd bd de de de de + de de de de 18 18 18 18 18 18 18 18 18 ea d6 d6 + d6 d6 d6 d6 bd bd bd bd bd bd bd bd bd 8a 20 84 + e8 4c 4c 4c 18 18 18 18 18 18 18 18 18 ea d6 d6 + d6 d6 d6 d6 bd bd bd bd bd bd bd bd bd 8a 20 84 + e8 4c 4c 4c 18 18 18 18 18 18 18 18 18 ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 de de de de + de de de de de de de de de de de de de ea d6 d6 + d6 d6 d6 d6 bd bd bd bd bd bd bd bd bd 8a 20 84 + e8 4c 4c 4c 18 18 18 18 18 18 18 18 18 ea d6 d6 + d6 d6 d6 d6 bd bd bd bd bd bd bd bd bd 8a 20 84 + e8 4c 4c 4c 4d 4d 4d 4d 4d 4d 4d 4d a4 a4 a4 a4 + a4 a4 a4 a4 f3 f3 f3 f3 f3 f3 f3 f3 fa fa fa fa + fa fa fa fa 4d 4d 4d 4d 4d 4d 4d 4d 4d ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 fa fa fa fa + fa fa fa fa 4d 4d 4d 4d 4d 4d 4d 4d a4 a4 a4 a4 + a4 a4 a4 a4 f3 f3 f3 f3 f3 f3 f3 f3 fa fa fa fa + fa fa fa fa 4d 4d 4d 4d 4d 4d 4d 4d 4d ea d6 d6 + d6 d6 d6 d6 f3 f3 f3 f3 f3 f3 f3 f3 f3 8a 20 84 + e8 4c 4c 4c 29 29 29 29 29 29 29 29 29 ea d6 d6 + d6 d6 d6 d6 bd bd bd bd bd bd bd bd bd 8a 20 84 + e8 4c 4c 4c 29 29 29 29 29 29 29 29 29 ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 de de de de + de de de de de de de de de de de de de ea d6 d6 + d6 d6 d6 d6 bd bd bd bd bd bd bd bd bd 8a 20 84 + e8 4c 4c 4c 29 29 29 29 29 29 29 29 76 76 76 76 + 76 76 76 76 bd bd bd bd bd bd bd bd bd 8a 20 84 + e8 4c 4c 4c 18 18 18 18 18 18 18 18 18 70 5c 5c + 5c 5c 5c 5c bd bd bd bd bd bd bd bd bd 8a 20 84 + e8 4c 4c 4c 18 18 18 18 18 18 18 18 18 ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 de de de de + de de de de 18 18 18 18 18 18 18 18 4d 4d 4d 4d + 4d 4d 4d 4d bd bd bd bd bd bd bd bd bd 8a 20 84 + e8 4c 4c 4c 18 18 18 18 18 18 18 18 18 ea d6 d6 + d6 d6 d6 d6 bd bd bd bd bd bd bd bd bd 8a 20 84 + e8 4c 4c 4c 18 18 18 18 18 18 18 18 18 ea d6 d6 + d6 d6 d6 d6 bd bd bd bd bd bd bd bd bd 8a 20 84 + e8 4c 4c 4c 18 18 18 18 18 18 18 18 18 ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 de de de de + de de de de de de de de de de de de de ea d6 d6 + d6 d6 d6 d6 bd bd bd bd bd bd bd bd bd 8a 20 84 + e8 4c 4c 4c 18 18 18 18 18 18 18 18 18 ea d6 d6 + d6 d6 d6 d6 bd bd bd bd bd bd bd bd bd 8a 20 84 + e8 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c ea d6 d6 + d6 d6 d6 d6 f3 f3 f3 f3 f3 f3 f3 f3 f3 10 a6 0a + 6e d2 d2 d2 4d 4d 4d 4d 4d 4d 4d 4d 4d ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 8a 20 84 + e8 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c ea d6 d6 + d6 d6 d6 d6 f3 f3 f3 f3 f3 f3 f3 f3 f3 8a 20 84 + e8 4c 4c 4c 4d 4d 4d 4d 4d 4d 4d 4d 4d ea d6 d6 + d6 d6 d6 d6 f3 f3 f3 f3 f3 f3 f3 f3 f3 8a 20 84 + e8 4c 4c 4c 29 29 29 29 29 29 29 29 29 ea d6 d6 + d6 d6 d6 d6 bd bd bd bd bd bd bd bd bd 8a 20 84 + e8 4c 4c 4c 29 29 29 29 29 29 29 29 29 ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 de de de de + de de de de de de de de de de de de de ea d6 d6 + d6 d6 d6 d6 bd bd bd bd bd bd bd bd bd 8a 20 84 + e8 4c 4c 4c 29 29 29 29 29 29 29 29 76 76 76 76 + 76 76 76 76 bd bd bd bd bd bd bd bd 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 + 06 06 06 06 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 + 06 06 06 06 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 03 03 03 + 03 03 03 03 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 + 06 06 06 06 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 09 09 09 09 09 09 09 09 09 06 06 06 + 06 06 06 06 01 01 01 01 01 01 01 01 01 04 04 05 + 05 05 05 05 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 07 08 08 + 08 09 09 09 09 09 09 09 09 09 09 09 09 06 06 06 + 06 06 06 06 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 + 06 06 06 06 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 89 1f 83 + e7 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b 4b e9 d5 d5 + d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 a7 a7 a7 a7 + a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 ea d6 d6 + d6 d6 d6 d6 a7 a7 a7 a7 a7 a7 a7 a7 a7 8a 20 84 + e8 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c de de de de + de de de de bb bb bb bb bb bb bb bb a7 a7 a7 a7 + a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 ea d6 d6 + d6 d6 d6 d6 a7 a7 a7 a7 a7 a7 a7 a7 a7 8a 20 84 + e8 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c bb bb bb bb + bb bb bb bb de de de de de de de de bb bb bb bb + bb bb bb bb bb bb bb bb bb bb bb bb bb ea d6 d6 + d6 d6 d6 d6 bb bb bb bb bb bb bb bb bb 8a 20 84 + e8 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c fa fa fa fa + fa fa fa fa de de de de de de de de bb bb bb bb + bb bb bb bb bb bb bb bb bb bb bb bb bb ea d6 d6 + d6 d6 d6 d6 bb bb bb bb bb bb bb bb bb 8a 20 84 + e8 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c de de de de + de de de de fa fa fa fa fa fa fa fa fa fa fa fa + fa fa fa fa fa fa fa fa fa fa fa fa fa ea d6 d6 + d6 d6 d6 d6 fa fa fa fa fa fa fa fa fa 8a 20 84 + e8 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c 4d 4d 4d 4d + 4d 4d 4d 4d 18 18 18 18 18 18 18 18 fa fa fa fa + fa fa fa fa fa fa fa fa fa fa fa fa fa ea d6 d6 + d6 d6 d6 d6 fa fa fa fa fa fa fa fa fa 8a 20 84 + e8 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c 18 18 18 18 + 18 18 18 18 fa fa fa fa fa fa fa fa de de de de + de de de de de de de de de de de de de ea d6 d6 + d6 d6 d6 d6 de de de de de de de de de 8a 20 84 + e8 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c fa fa fa fa + fa fa fa fa de de de de de de de de bb bb bb bb + bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb + bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb + bb bb bb bb de de de de de de de de de ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 a7 a7 a7 a7 + a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 a7 bb bb bb bb + bb bb bb bb bb bb bb bb bb bb bb bb de de de de + de de de de fa fa fa fa fa fa fa fa fa fa fa fa + fa fa fa fa 18 18 18 18 18 18 18 18 18 18 18 18 + 18 18 18 18 18 18 18 18 18 18 18 18 4d 4d 4d 4d + 4d 4d 4d 4d 18 18 18 18 18 18 18 18 fa fa fa fa + fa fa fa fa fa fa fa fa fa fa fa fa 18 18 18 18 + 18 18 18 18 18 18 18 18 18 18 18 18 18 8a 20 84 + e8 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c 4c 18 18 18 18 + 18 18 18 18 18 18 18 18 18 18 18 18 fa fa fa fa + fa fa fa fa de de de de de de de de de de de de + de de bb bb bb bb bb bb bb bb bb bb bb 8a 20 84 + e8 4c 4c 4c bb bb bb bb bb bb bb bb de de de de + de de de de de de de de de de de de bb bb bb bb + bb bb bb bb bb bb bb bb bb bb bb bb bb ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 bb bb bb bb + bb bb bb bb d2 d2 d2 d2 d2 d2 d2 d2 de de de de + de de de de de de de de de de de de fa fa fa fa + fa fa fa fa de de de de de de de de de de de de + de de de de de de de de de de de de de de de de + de de de de de de de de de de fa fa fa fa fa fa + fa fa 18 18 18 18 18 18 18 18 18 18 fa fa fa fa + fa fa fa fa fa fa fa fa fa fa fa fa 18 18 18 18 + 18 18 18 18 18 18 18 18 18 18 18 18 de de de de + de de de de de de de de de de de de bb bb bb bb + bb bb bb bb bb bb bb bb bb bb 94 94 94 94 94 94 + 94 94 94 94 bb bb bb bb bb bb bb bb bb bb bb bb + bb bb bb bb 94 94 94 94 94 94 94 94 94 8a 20 84 + e8 4c 4c 4c 94 94 94 94 94 94 94 94 bb bb bb bb + bb bb bb bb bb bb bb bb bb bb 94 94 94 94 94 94 + 94 94 94 94 bb bb bb bb bb bb bb bb bb ea d6 d6 + d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 d6 00 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 02 03 03 + 03 04 04 04 04 04 04 04 04 04 04 04 04 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 + 06 06 06 06 00 00 00 00 00 00 00 00 00 07 08 08 + 08 09 09 09 09 09 09 09 09 09 09 09 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 + 06 06 06 06 00 00 00 00 00 00 00 00 00 07 08 08 + 08 09 09 09 09 09 09 09 09 09 09 09 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 + 06 06 06 06 00 00 00 00 00 00 00 00 00 07 08 08 + 08 09 09 09 09 09 09 09 09 09 09 09 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 + 06 06 06 06 00 00 00 00 00 00 00 00 00 07 08 08 + 08 09 09 09 09 09 09 09 09 09 09 09 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 + 06 06 06 06 00 00 00 00 00 00 00 00 00 07 08 08 + 08 09 09 09 09 09 09 09 09 09 09 09 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 + 06 06 06 06 00 00 00 00 00 00 00 00 00 07 08 08 + 08 09 09 09 09 09 09 09 09 09 09 09 01 01 01 01 + 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 + 06 06 06 06 00 00 00 00 00 00 00 00 00 07 08 08 + 08 09 09 09 09 09 09 09 09 09 09 09 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 07 08 08 + 08 09 09 09 09 09 09 09 09 09 09 09 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 07 08 08 + 08 09 09 09 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 07 08 08 + 08 09 09 09 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 01 00 00 00 + 00 00 00 00 01 01 01 01 01 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 00 00 00 1e 3a 3a 3a + 3a 3a 3e 3e 1e 1e 1e 1e 1e 3e 3e 3e 1e 1a 1a 1e + 3e 1e 1e 1e 1e 1e 1e 1e 1e 3e 3e 3f 1e 3a 3a 3a + 3a 3a 3e 3e 1e 1e 1e 1e 1e 3e 3e 3f 1e 1a 1a 1e + 3e 1e 1e 1e 1e 1e 1e 1e 1e 3e 3e 3e 1e 3a 3a 3a + 3a 3a 3e 3f 1e 1e 1e 1e 1e 3e 3e 3e 1e 1a 1a 1e + 3e 1e 1e 1e 1e 1e 1e 1e 1e 3e 3e 3f 1e 3a 3a 3a + 3a 3a 3e 3e 1e 1e 1e 1e 1e 3e 3e 3f 1e 1a 1a 1e + 3e 1e 1e 1e 1e 1e 1e 1e 1e 3e 3e 3f 1e 3a 3a 3a + 3a 3a 3e 3e 1e 1e 1e 1e 1e 3e 3e 3e 1e 1a 1a 1e + 3e 1e 1e 1e 1e 1e 1e 1e 1e 3e 3e 3f 1e 3a 3a 3a + 3a 3a 3e 3e 1e 1e 1e 1e 1e 3e 3e 3f 1e 1a 1a 1e + 3e 1e 1e 1e 1e 1e 1e 1e 1e 3e 3e 3e 1e 3a 3a 3a + 3a 3a 3e 3f 1e 1e 1e 1e 1e 3e 3e 3e 1e 1a 1a 1e + 3e 1e 1e 1e 1e 1e 1e 1e 1e 3e 3e 3f 1e 3a 3a 3a + 3a 3a 3e 3e 1e 1e 1e 1e 1e 3e 3e 3f 1e 1a 1a 1e + 3e 1e 1e 1e 1e 1e 1e 1e 1e 3e 3e 3f 1e 3a 3a 3a + 3a 3a 3e 3e 1e 1e 1e 1e 1e 3e 3e 3e 1e 1a 1a 1e + 3e 1e 1e 1e 1e 1e 1e 1e 1e 3e 3e 3f 1e 3a 3a 3a + 3a 3a 3e 3e 17 17 17 17 17 3f 3f 3f 1e 1a 1a 1e + 3e 1e 1e 1e 1e 1e 1e 1e 1e 3e 3e 3e 1e 3a 3a 3a + 3a 3a 3e 3f 1e 1e 1e 1e 1e 3e 3e 3e 1e 1a 1a 1e + 3e 1e 1e 1e 17 17 17 17 17 3f 3f 3f 1e 3a 3a 3a + 3a 3a 3e 3e 1e 1e 1e 1e 1e 3e 3e 3f 1e 1a 1a 1e + 3e 1e 1e 1e 1e 1e 1e 1e 1e 3e 3e 3f 1e 3a 3a 3a + 3a 3a 3e 3e 1e 1e 1e 1e 1e 3e 3e 3e 1e 1a 1a 1e + 3e 1e 1e 1e 1e 1e 1e 1e 1e 3e 3e 3f 1e 3a 3a 3a + 3a 3a 3e 3e 17 17 17 17 17 3f 3f 3f 1e 1a 1a 1e + 3e 1e 1e 1e 1e 1e 1e 1e 1e 3e 3e 3e 1e 3a 3a 3a + 3a 3a 3e 3f 1e 1e 1e 1e 1e 3e 3e 3e 1e 1a 1a 1e + 3e 1e 1e 1e 1e 1e 1e 1e 1e 3e 3e 3f 1e 3a 3a 3a + 3a 3a 3e 3e 17 17 17 17 17 3f 3f 3f 1e 1a 1a 1e + 3e 1e 1e 1e 1e 1e 1e 1e 1e 3e 3e 3f 1c 38 38 38 + 38 38 3c 3c 1c 1c 1c 1c 1c 3c 3c 3c 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3c 3d 1c 38 38 38 + 38 38 3c 3c 1c 1c 1c 1c 1c 3c 3c 3d 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3c 3c 1c 38 38 38 + 38 38 3c 3d 1c 1c 1c 1c 1c 3c 3c 3c 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3c 3d 1c 38 38 38 + 38 38 3c 3c 1c 1c 1c 1c 1c 3c 3c 3d 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3c 3d 1c 38 38 38 + 38 38 3c 3c 1c 1c 1c 1c 1c 3c 3c 3c 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3c 3d 1c 38 38 38 + 38 38 3c 3c 1c 1c 1c 1c 1c 3c 3c 3d 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3c 3c 1c 38 38 38 + 38 38 3c 3d 1c 1c 1c 1c 1c 3c 3c 3c 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3c 3d 1c 38 38 38 + 38 38 3c 3c 1c 1c 1c 1c 1c 3c 3c 3d 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3c 3d 1c 38 38 38 + 38 38 3c 3c 1c 1c 1c 1c 1c 3c 3c 3c 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3c 3d 1c 38 38 38 + 38 38 3c 3c 15 15 15 15 15 3d 3d 3d 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3c 3c 1c 38 38 38 + 38 38 3c 3d 1c 1c 1c 1c 1c 3c 3c 3c 1c 18 18 1c + 3c 1c 1c 1c 15 15 15 15 15 3d 3d 3d 1c 38 38 38 + 38 38 3c 3c 1c 1c 1c 1c 1c 3c 3c 3d 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3c 3d 1c 38 38 38 + 38 38 3c 3c 1c 1c 1c 1c 1c 3c 3c 3c 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3c 3d 1c 38 38 38 + 38 38 3c 3c 15 15 15 15 15 3d 3d 3d 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3c 3c 1c 38 38 38 + 38 38 3c 3d 1c 1c 1c 1c 1c 3c 3c 3c 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3c 3d 1c 38 38 38 + 38 38 3c 3c 15 15 15 15 15 3d 3d 3d 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3c 3d 2a 38 38 38 + 38 38 3a 3a 1c 1c 1c 1c 1c 3c 3c 3c 1c 18 18 1c + 3c 1c 1c 1c 31 31 31 31 31 39 39 39 1c 38 38 38 + 38 38 3c 3c 1c 1c 1c 1c 1c 3c 3c 3d 2a 28 28 2a + 3a 2a 2a 2a 2a 2a 2a 2a 2a 3a 3a 3a 31 38 38 38 + 38 38 39 39 1c 1c 1c 1c 1c 3c 3c 3c 1c 18 18 1c + 3c 1c 1c 1c 31 31 31 31 31 39 39 39 1c 38 38 38 + 38 38 3c 3c 1c 1c 1c 1c 1c 3c 3c 3d 2a 28 28 2a + 3a 2a 2a 2a 31 31 31 31 31 39 39 39 2a 38 38 38 + 38 38 3a 3a 1c 1c 1c 1c 1c 3c 3c 3c 0e 08 08 0e + 3e 0e 0e 0e 31 31 31 31 31 39 39 39 0e 38 38 38 + 38 38 3e 3e 1c 1c 1c 1c 1c 3c 3c 3d 2a 28 28 2a + 3a 2a 2a 2a 2a 2a 2a 2a 2a 3a 3a 3a 31 38 38 38 + 38 38 39 39 0e 0e 0e 0e 0e 3e 3e 3e 0e 08 08 0e + 3e 0e 0e 0e 31 31 31 31 31 39 39 39 0e 38 38 38 + 38 38 3e 3e 1c 1c 1c 1c 1c 3c 3c 3d 2a 28 28 2a + 3a 2a 2a 2a 31 31 31 31 31 39 39 39 2a 38 38 38 + 38 38 3a 3a 1c 1c 1c 1c 1c 3c 3c 3c 1c 18 18 1c + 3c 1c 1c 1c 31 31 31 31 31 39 39 39 1c 38 38 38 + 38 38 3c 3c 1c 1c 1c 1c 1c 3c 3c 3d 2a 28 28 2a + 3a 2a 2a 2a 2a 2a 2a 2a 2a 3a 3a 3a 31 38 38 38 + 38 38 39 39 1c 1c 1c 1c 1c 3c 3c 3c 1c 18 18 1c + 3c 1c 1c 1c 31 31 31 31 31 39 39 39 1c 38 38 38 + 38 38 3c 3c 1c 1c 1c 1c 1c 3c 3c 3d 2a 28 28 2a + 3a 2a 2a 2a 31 31 31 31 31 39 39 39 2a 38 38 38 + 38 38 3a 3a 1c 1c 1c 1c 1c 3c 3c 3c 0e 08 08 0e + 3e 0e 0e 0e 31 31 31 31 31 39 39 39 0e 38 38 38 + 38 38 3e 3e 1c 1c 1c 1c 1c 3c 3c 3d 2a 28 28 2a + 3a 2a 2a 2a 2a 2a 2a 2a 2a 3a 3a 3a 31 38 38 38 + 38 38 39 39 0e 0e 0e 0e 0e 3e 3e 3e 2a 28 28 2a + 3a 2a 2a 2a 1c 1c 1c 1c 1c 3c 3c 3d 2a 38 38 38 + 38 38 3a 3a 31 31 31 31 31 39 39 39 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3c 3d 2a 38 38 38 + 38 38 3a 3a 1c 1c 1c 1c 1c 3c 3c 3c 2a 28 28 2a + 3a 2a 2a 2a 31 31 31 31 31 39 39 3d 2a 38 38 38 + 38 38 3a 3a 31 31 31 31 31 39 39 39 2a 28 28 2a + 3a 2a 2a 2e 2a 2a 2a 2a 2a 3a 3a 3a 31 38 38 38 + 38 38 39 3d 38 38 38 38 38 38 38 38 38 38 38 38 + 38 38 38 38 31 31 31 31 31 39 39 39 2a 38 38 38 + 38 38 3a 3a 1c 1c 1c 1c 1c 3c 3c 3d 2a 28 28 2a + 3a 2a 2a 2a 31 31 31 31 31 39 39 3d 0e 38 38 38 + 38 38 3e 3e 1c 1c 1c 1c 1c 3c 3c 3c 2a 28 28 2a + 3a 2a 2a 2a 1c 1c 1c 1c 1c 3c 3c 3d 2a 38 38 38 + 38 38 3a 3a 31 31 31 31 31 39 39 39 2a 28 28 2a + 3a 2a 2a 2a 2a 2a 2a 2a 2a 3a 3a 3a 1c 38 38 38 + 38 38 3c 3d 2a 2a 2a 2a 2a 3a 3a 3a 2a 28 28 2a + 3a 2a 2a 2a 1c 1c 1c 1c 1c 3c 3c 3d 2a 38 38 38 + 38 38 3a 3a 1c 1c 1c 1c 1c 3c 3c 3d 0e 08 08 0e + 3e 0e 0e 0e 1c 1c 1c 1c 1c 3c 3c 3d 2a 38 38 38 + 38 38 3a 3a 2a 2a 2a 2a 2a 3a 3a 3a 2a 28 28 2a + 3a 2a 2a 2a 1c 1c 1c 1c 1c 3c 3c 3d 2a 38 38 38 + 38 38 3a 3a 31 31 31 31 31 39 39 39 2a 28 28 2a + 3a 2a 2a 2e 2a 2a 2a 2a 2a 3a 3a 3a 2a 38 38 38 + 38 38 3a 3b 2a 2a 2a 2a 2a 3a 3a 3a 2a 28 28 2a + 3a 2a 2a 2a 31 31 31 31 31 39 39 39 2a 38 38 38 + 38 38 3a 3a 1c 1c 1c 1c 1c 3c 3c 3d 2a 28 28 2a + 3a 2a 2a 2a 1c 1c 1c 1c 1c 3c 3c 3d 2a 38 38 38 + 38 38 3a 3a 1c 1c 1c 1c 1c 3c 3c 3c 2a 28 28 2a + 3a 2a 2a 2a 1c 1c 1c 1c 1c 3c 38 39 2a 38 38 38 + 38 38 3a 3a 31 31 31 31 31 39 39 39 2a 28 28 2a + 3a 2a 2a 2e 2a 2a 2a 2a 2a 3a 3a 3a 1c 38 38 38 + 38 38 3c 3d 2a 2a 2a 2a 2a 3a 3a 3a 2a 28 28 2a + 3a 2a 2a 2a 1c 1c 1c 1c 1c 3c 38 39 2a 38 38 38 + 38 38 3a 3a 31 31 31 31 31 39 39 39 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3c 3d 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 00 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 00 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 00 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 00 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 00 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0b 0a 09 08 + 07 06 05 04 0f 0d 0b 08 05 00 00 00 0b 0a 08 07 + 06 06 05 04 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0b 0a 09 08 + 07 06 05 04 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0b 0a 09 08 + 07 06 05 04 0f 0d 0b 08 05 00 00 00 0b 0a 08 07 + 06 06 05 04 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0f 0e 0d 0c 0b 0a 09 08 0f 0e 0c 0b + 0a 0a 09 08 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0b 0a 09 08 + 07 06 05 04 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0b 0a 09 08 07 06 05 04 0b 0a 09 08 + 07 06 05 04 0b 0a 09 08 07 06 05 04 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0b 0a + 09 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 00 00 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0b 0a + 09 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 00 00 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0b 0a + 09 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 00 00 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0b 0a + 09 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 00 00 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0b 0a + 09 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 00 00 0e 0c 0a 07 04 00 00 00 0d 0c 0b 0a + 09 08 07 06 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0b 0a + 09 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 00 00 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0f 0e 0d 0c + 0b 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 00 00 0e 0c 0a 07 04 00 00 00 0d 0c 0b 0a + 09 08 07 06 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0e 0d 0b 0a + 09 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 0f 0e 0d 0c + 0b 0a 09 08 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 00 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 + 03 02 01 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0d 0c 0b 0a 09 08 07 0f 0e 0d 0c + 0b 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 09 08 07 06 05 04 03 02 01 00 0f 0e 0d 0c + 0b 0a 00 00 0f 0d 0b 08 05 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 + 03 02 0e 0d 0c 0b 0a 09 08 07 06 05 0e 0d 0c 0b + 0a 09 00 00 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0b 0a + 09 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0f 0e 0d 0c 0b 0a 09 08 0f 0e 0d 0c + 0b 0a 09 08 0f 0d 0b 08 05 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 + 03 02 01 00 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 0e 0d 0c 0b 0a 09 08 07 0e 0d 0c 0b 0a 09 + 08 07 0e 0d 0c 0b 0a 09 08 07 06 05 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0e 0d 0c 0b + 0a 09 08 07 0e 0c 0a 07 04 00 00 00 0f 0e 0d 0c + 0b 0a 09 08 0f 0d 0b 08 05 00 00 00 0f 0e 0d 0c + 0b 0a 09 08 0f 0d 0b 08 05 00 0f 0e 0d 0c 0b 0a + 09 08 07 06 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 + 03 02 01 00 0f 0e 0d 0c 0b 0a 09 08 0f 0e 0d 0c + 0b 0a 00 00 0f 0e 0d 0c 0b 0a 09 08 0f 0e 0d 0c + 0b 0a 09 08 0f 0d 0b 08 05 00 0f 0e 0d 0c 0b 0a + 09 08 07 06 0f 0e 0d 0c 0b 0a 09 08 0f 0e 0c 0b + 0a 0a 09 08 0f 0d 0b 08 05 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 45 6e 64 21 + 59 4d 36 21 4c 65 4f 6e 41 72 44 21 00 00 03 00 + 00 00 00 01 00 00 00 1e 84 80 00 32 00 00 00 00 + 00 00 55 6e 74 69 74 6c 65 64 20 2d 20 53 75 62 + 73 6f 6e 67 00 00 49 6d 70 6f 72 74 65 64 20 66 + 72 6f 6d 20 4d 69 64 69 20 62 79 20 41 72 6b 6f + 73 20 54 72 61 63 6b 65 72 20 32 00 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 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 61 61 61 61 + 61 61 61 61 61 61 61 61 61 61 61 61 85 85 85 85 + 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 + 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 + 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 + 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 + 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 + 85 85 85 85 85 85 85 85 85 85 85 85 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 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 90 90 + 90 90 90 90 90 90 90 90 90 90 90 90 d9 d9 d9 d9 + d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 + d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 + d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 + d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 + d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 + d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 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 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 61 61 61 61 + 61 61 61 61 61 61 61 61 61 61 61 61 85 85 85 85 + 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 + 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 + 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 + 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 + 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 + 85 85 85 85 85 85 85 85 85 85 85 85 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 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 90 90 + 90 90 90 90 90 90 90 90 90 90 90 90 d9 d9 d9 d9 + d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 + d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 + d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 + d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 + d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 + d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 d9 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 06 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 06 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 + 06 06 06 06 06 06 06 06 06 06 06 06 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 05 + 05 05 05 05 05 05 05 05 05 05 05 05 d7 d7 d7 d7 + d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 + d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 + d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 + d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 + d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 + d7 d7 d7 76 76 76 76 76 76 76 76 76 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 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 61 61 61 61 + 61 61 61 76 76 76 76 76 76 76 76 76 a4 a4 a4 a4 + a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 + a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 + a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 + a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 + a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 76 76 76 76 76 76 + 76 76 76 61 61 61 61 61 61 61 61 61 3b 3b 3b 3b + 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b + 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b + 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b + 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b + 3b 3b 3b 3b 61 61 61 61 61 61 61 61 61 61 61 61 + 61 61 61 76 76 76 76 76 76 76 76 76 d7 d7 d7 d7 + d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 + d7 d7 d7 d7 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 + f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 31 31 31 31 + 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 + 31 31 31 31 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 + f3 f3 f3 d7 d7 d7 d7 d7 d7 d7 d7 d7 a4 a4 a4 a4 + a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 + a4 a4 a4 a4 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 + d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 f3 f3 f3 f3 + f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 f3 + f3 f3 f3 f3 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 d7 + d7 d7 d7 a4 a4 a4 a4 a4 a4 a4 a4 a4 61 61 61 61 + 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 + 61 61 61 61 76 76 76 76 76 76 76 76 76 76 76 76 + 76 76 76 76 76 76 76 76 76 76 76 76 a4 a4 a4 a4 + a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 a4 + a4 a4 a4 a4 76 76 76 76 76 76 76 76 76 76 76 76 + 76 76 76 61 61 61 61 61 61 61 61 61 3b 3b 3b 3b + 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b + 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b + 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b + 3b 3b 3b 3b 3b 61 61 61 61 61 61 61 61 61 76 76 + 76 76 76 76 61 61 61 61 61 61 61 61 61 76 76 76 + 76 76 76 76 76 76 a4 a4 a4 a4 a4 a4 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 02 02 02 02 + 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 + 02 02 02 02 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + 01 01 01 01 01 01 01 01 01 01 01 01 00 57 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 57 43 43 43 43 43 57 43 43 43 43 + 43 43 43 43 57 43 43 43 43 43 43 43 43 57 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 57 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 57 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 57 43 43 43 43 43 57 43 43 43 43 + 43 43 43 43 57 43 43 43 43 43 43 43 43 57 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 57 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 57 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 57 43 43 43 43 43 57 43 43 43 43 + 43 43 43 43 57 43 43 43 43 43 43 43 43 57 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 57 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 57 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 57 43 43 43 43 43 57 43 43 43 43 + 43 43 43 43 57 43 43 43 43 43 43 43 43 57 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 57 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 57 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 57 43 43 43 43 43 57 43 43 43 43 + 43 43 43 43 57 43 43 43 43 43 43 43 43 57 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 57 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 57 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 57 43 43 43 43 43 57 43 43 43 43 + 43 43 43 43 57 43 43 43 43 43 43 43 43 57 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 57 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 57 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 57 43 43 43 43 43 57 43 43 43 43 + 43 43 43 43 57 43 43 43 43 43 43 43 43 57 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 57 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 57 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 57 43 43 43 43 43 57 43 43 43 43 + 43 43 43 43 57 43 43 43 43 43 43 43 43 57 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 57 43 43 43 43 43 43 43 43 43 43 + 43 43 43 43 43 43 43 43 43 43 43 43 00 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 + 04 04 04 04 04 04 04 04 04 04 04 04 01 02 03 01 + 00 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 + 00 00 00 00 01 02 03 01 00 01 01 02 03 01 00 01 + 01 01 01 01 02 03 01 00 01 01 01 01 01 02 03 01 + 00 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 + 00 00 00 00 01 02 03 01 00 01 01 01 01 01 01 01 + 01 01 00 00 00 00 00 00 00 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 + 00 00 00 00 01 02 03 01 00 01 01 02 03 01 00 01 + 01 01 01 01 02 03 01 00 01 01 01 01 01 02 03 01 + 00 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 + 00 00 00 00 01 02 03 01 00 01 01 01 01 01 01 01 + 01 01 00 00 00 00 00 00 00 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 + 00 00 00 00 01 02 03 01 00 01 01 02 03 01 00 01 + 01 01 01 01 02 03 01 00 01 01 01 01 01 02 03 01 + 00 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 + 00 00 00 00 01 02 03 01 00 01 01 01 01 01 01 01 + 01 01 00 00 00 00 00 00 00 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 + 00 00 00 00 01 02 03 01 00 01 01 02 03 01 00 01 + 01 01 01 01 02 03 01 00 01 01 01 01 01 02 03 01 + 00 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 + 00 00 00 00 01 02 03 01 00 01 01 01 01 01 01 01 + 01 01 00 00 00 00 00 00 00 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 + 00 00 00 00 01 02 03 01 00 01 01 02 03 01 00 01 + 01 01 01 01 02 03 01 00 01 01 01 01 01 02 03 01 + 00 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 + 00 00 00 00 01 02 03 01 00 01 01 01 01 01 01 01 + 01 01 00 00 00 00 00 00 00 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 + 00 00 00 00 01 02 03 01 00 01 01 02 03 01 00 01 + 01 01 01 01 02 03 01 00 01 01 01 01 01 02 03 01 + 00 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 + 00 00 00 00 01 02 03 01 00 01 01 01 01 01 01 01 + 01 01 00 00 00 00 00 00 00 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 + 00 00 00 00 01 02 03 01 00 01 01 02 03 01 00 01 + 01 01 01 01 02 03 01 00 01 01 01 01 01 02 03 01 + 00 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 + 00 00 00 00 01 02 03 01 00 01 01 01 01 01 01 01 + 01 01 00 00 00 00 00 00 00 00 00 00 01 02 03 01 + 00 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 + 00 00 00 00 01 02 03 01 00 01 01 02 03 01 00 01 + 01 01 01 01 02 03 01 00 01 01 01 01 01 02 03 01 + 00 01 01 01 01 01 01 01 01 01 00 00 00 00 00 00 + 00 00 00 00 01 02 03 01 00 01 01 01 01 01 01 01 + 01 01 00 00 00 00 00 00 00 00 00 00 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3f 3f 3f 3f 3f + 3f 3f 3f 3f 1c 18 18 1c 3c 1c 1c 18 18 1c 3c 1c + 1c 1c 1c 1e 1a 1a 1e 3e 1e 1e 1e 1e 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3f 3f 3f 3f 3f + 3f 3f 3f 3f 1c 18 18 1c 3c 1c 1c 1c 1c 1c 1c 1c + 1c 1c 3c 3d 3d 3d 3d 3d 3d 3d 3d 3d 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3f 3f 3f 3f 3f + 3f 3f 3f 3f 1c 18 18 1c 3c 1c 1c 18 18 1c 3c 1c + 1c 1c 1c 1e 1a 1a 1e 3e 1e 1e 1e 1e 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3f 3f 3f 3f 3f + 3f 3f 3f 3f 1c 18 18 1c 3c 1c 1c 1c 1c 1c 1c 1c + 1c 1c 3c 3d 3d 3d 3d 3d 3d 3d 3d 3d 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3f 3f 3f 3f 3f + 3f 3f 3f 3f 1c 18 18 1c 3c 1c 1c 18 18 1c 3c 1c + 1c 1c 1c 1e 1a 1a 1e 3e 1e 1e 1e 1e 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3f 3f 3f 3f 3f + 3f 3f 3f 3f 1c 18 18 1c 3c 1c 1c 1c 1c 1c 1c 1c + 1c 1c 3c 3d 3d 3d 3d 3d 3d 3d 3d 3d 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3f 3f 3f 3f 3f + 3f 3f 3f 3f 1c 18 18 1c 3c 1c 1c 18 18 1c 3c 1c + 1c 1c 1c 1e 1a 1a 1e 3e 1e 1e 1e 1e 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3f 3f 3f 3f 3f + 3f 3f 3f 3f 1c 18 18 1c 3c 1c 1c 1c 1c 1c 1c 1c + 1c 1c 3c 3d 3d 3d 3d 3d 3d 3d 3d 3d 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3f 3f 3f 3f 3f + 3f 3f 3f 3f 1c 18 18 1c 3c 1c 1c 18 18 1c 3c 1c + 1c 1c 1c 1e 1a 1a 1e 3e 1e 1e 1e 1e 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3f 3f 3f 3f 3f + 3f 3f 3f 3f 1c 18 18 1c 3c 1c 1c 1c 1c 1c 1c 1c + 1c 1c 3c 3d 3d 3d 3d 3d 3d 3d 3d 3d 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3f 3f 3f 3f 3f + 3f 3f 3f 3f 1c 18 18 1c 3c 1c 1c 18 18 1c 3c 1c + 1c 1c 1c 1e 1a 1a 1e 3e 1e 1e 1e 1e 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3f 3f 3f 3f 3f + 3f 3f 3f 3f 1c 18 18 1c 3c 1c 1c 1c 1c 1c 1c 1c + 1c 1c 3c 3d 3d 3d 3d 3d 3d 3d 3d 3d 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3f 3f 3f 3f 3f + 3f 3f 3f 3f 1c 18 18 1c 3c 1c 1c 18 18 1c 3c 1c + 1c 1c 1c 1e 1a 1a 1e 3e 1e 1e 1e 1e 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3f 3f 3f 3f 3f + 3f 3f 3f 3f 1c 18 18 1c 3c 1c 1c 1c 1c 1c 1c 1c + 1c 1c 3c 3d 3d 3d 3d 3d 3d 3d 3d 3d 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3f 3f 3f 3f 3f + 3f 3f 3f 3f 1c 18 18 1c 3c 1c 1c 18 18 1c 3c 1c + 1c 1c 1c 1e 1a 1a 1e 3e 1e 1e 1e 1e 1c 18 18 1c + 3c 1c 1c 1c 1c 1c 1c 1c 1c 1c 3c 3d 3d 3d 3d 3d + 3d 3d 3d 3d 1c 18 18 1c 3c 1c 1c 1c 1c 1c 1c 1c + 1c 1c 3c 3d 3d 3d 3d 3d 3d 3d 3d 3d 0f 0e 0d 0c + 0b 0a 09 08 07 06 05 04 03 02 01 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 0d 0c 0b 0a 09 08 + 07 06 05 0d 0c 0b 0a 09 08 07 06 05 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 07 06 05 04 03 02 + 01 00 00 00 00 00 00 00 00 00 00 00 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 0d 0c 0b 0a 09 08 + 07 06 05 0d 0c 0b 0a 09 08 07 06 05 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 07 06 05 04 03 02 + 01 00 00 00 00 00 00 00 00 00 00 00 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 0d 0c 0b 0a 09 08 + 07 06 05 0e 0d 0c 0b 0a 09 08 07 06 0f 0e 0d 0c + 0b 0a 09 08 07 06 05 04 03 02 01 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 07 06 05 04 03 02 + 01 00 00 00 00 00 00 00 00 00 00 00 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 0d 0c 0b 0a 09 08 + 07 06 05 0d 0c 0b 0a 09 08 07 06 05 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 00 00 00 00 00 00 00 00 00 0f 0e 0d 0c + 0b 0a 09 08 07 06 05 04 03 02 01 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 0d 0c 0b 0a 09 08 + 07 06 05 0d 0c 0b 0a 09 08 07 06 05 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 07 06 05 04 03 02 + 01 00 00 00 00 00 00 00 00 00 00 00 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 0d 0c 0b 0a 09 08 + 07 06 05 0d 0c 0b 0a 09 08 07 06 05 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 07 06 05 04 03 02 + 01 00 00 00 00 00 00 00 00 00 00 00 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 0d 0c 0b 0a 09 08 + 07 06 05 0e 0d 0c 0b 0a 09 08 07 06 0f 0e 0d 0c + 0b 0a 09 08 07 06 05 04 03 02 01 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 07 06 05 04 03 02 + 01 00 00 00 00 00 00 00 00 00 00 00 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 0d 0c 0b 0a 09 08 + 07 06 05 0d 0c 0b 0a 09 08 07 06 05 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 00 00 00 00 00 00 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 07 06 05 04 03 02 + 01 00 00 00 00 00 00 00 00 00 00 00 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 + 03 02 01 0d 0c 0b 0a 09 08 07 06 05 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 07 06 05 04 03 02 + 01 00 00 00 00 00 00 00 00 00 00 00 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 07 06 05 04 03 02 + 01 00 00 0d 0c 0b 0a 09 08 07 06 05 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 + 03 02 01 00 00 00 00 00 00 00 00 00 0e 0d 0c 0b + 0a 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 0d 0c 0b 0a 09 08 + 07 06 05 0d 0c 0b 0a 09 08 07 06 05 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 07 06 05 04 03 02 + 01 00 00 00 00 00 00 00 00 00 00 00 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 07 06 05 04 03 02 + 01 00 00 0d 0c 0b 0a 09 08 07 06 05 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 00 00 00 00 00 00 00 00 00 0f 0e 0d 0c + 0b 0a 09 08 07 06 05 04 03 02 01 00 00 00 00 00 + 00 00 00 00 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 0d 0c 0b 0a 09 08 07 06 05 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 00 00 00 00 00 00 00 00 00 0f 0e 0d 0c + 0b 0a 09 08 07 06 05 04 03 02 01 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 07 06 05 04 03 02 + 01 00 00 0d 0c 0b 0a 09 08 07 06 05 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 07 06 05 04 03 02 + 01 00 00 00 00 00 00 00 00 00 00 00 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 + 02 01 00 0d 0c 0b 0a 09 08 07 06 05 0d 0c 0b 0a + 09 08 07 06 05 04 03 02 01 00 00 00 00 00 00 00 + 00 00 00 00 0d 0c 0b 0a 09 08 07 06 05 04 03 02 + 01 00 00 00 00 00 00 00 00 00 00 00 0d 0c 0b 0a + 09 08 07 06 05 0d 0c 0b 0a 09 08 07 06 05 0d 0c + 0b 0a 09 08 0d 0c 0b 0a 09 08 07 06 05 0d 0c 0b + 0a 09 08 07 06 05 0d 0c 0b 0a 09 08 0f 0e 0c 0b + 0a 0a 09 08 07 06 05 04 02 01 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0c 0b 0a 0a 0f 0e 0c 0b 0a 0a + 09 08 07 0f 0e 0c 0b 0a 0a 09 08 07 0f 0e 0c 0b + 0a 0a 09 08 07 06 05 04 02 01 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0c 0b 0a 0a 09 08 07 06 05 04 + 02 01 00 00 00 00 00 00 00 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 07 06 05 04 02 01 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0c 0b 0a 0a 0f 0e 0c 0b 0a 0a + 09 08 07 0f 0e 0c 0b 0a 0a 09 08 07 0f 0e 0c 0b + 0a 0a 09 08 07 06 05 04 02 01 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0c 0b 0a 0a 09 08 07 06 05 04 + 02 01 00 00 00 00 00 00 00 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 07 06 05 04 02 01 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0c 0b 0a 0a 0f 0e 0c 0b 0a 0a + 09 08 07 0f 0e 0c 0b 0a 0a 09 08 07 0f 0e 0c 0b + 0a 0a 09 08 07 06 05 04 02 01 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0c 0b 0a 0a 09 08 07 06 05 04 + 02 01 00 00 00 00 00 00 00 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 07 06 05 04 02 01 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0c 0b 0a 0a 0f 0e 0c 0b 0a 0a + 09 08 07 0f 0e 0c 0b 0a 0a 09 08 07 0f 0e 0c 0b + 0a 0a 09 08 07 06 05 04 02 01 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0c 0b 0a 0a 09 08 07 06 05 04 + 02 01 00 00 00 00 00 00 00 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 07 06 05 04 02 01 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0c 0b 0a 0a 0f 0e 0c 0b 0a 0a + 09 08 07 0f 0e 0c 0b 0a 0a 09 08 07 0f 0e 0c 0b + 0a 0a 09 08 07 06 05 04 02 01 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0c 0b 0a 0a 09 08 07 06 05 04 + 02 01 00 00 00 00 00 00 00 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 07 06 05 04 02 01 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0c 0b 0a 0a 0f 0e 0c 0b 0a 0a + 09 08 07 0f 0e 0c 0b 0a 0a 09 08 07 0f 0e 0c 0b + 0a 0a 09 08 07 06 05 04 02 01 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0c 0b 0a 0a 09 08 07 06 05 04 + 02 01 00 00 00 00 00 00 00 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 07 06 05 04 02 01 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0c 0b 0a 0a 0f 0e 0c 0b 0a 0a + 09 08 07 0f 0e 0c 0b 0a 0a 09 08 07 0f 0e 0c 0b + 0a 0a 09 08 07 06 05 04 02 01 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0c 0b 0a 0a 09 08 07 06 05 04 + 02 01 00 00 00 00 00 00 00 00 00 00 0f 0e 0c 0b + 0a 0a 09 08 07 06 05 04 02 01 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0c 0b 0a 0a 0f 0e 0c 0b 0a 0a + 09 08 07 0f 0e 0c 0b 0a 0a 09 08 07 0f 0e 0c 0b + 0a 0a 09 08 07 06 05 04 02 01 00 00 00 00 00 00 + 00 00 00 00 0f 0e 0c 0b 0a 0a 09 08 07 06 05 04 + 02 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff ff ff ff ff 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 45 6e 64 21 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff --git a/rtl/music.v b/rtl/music.v new file mode 100644 index 0000000..b8a2824 --- /dev/null +++ b/rtl/music.v @@ -0,0 +1,443 @@ +`timescale 1ns / 1ps +/*============================================================================ + Aznable (custom 8-bit computer system) - Deikun (music engine) + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 0.1 + Date: 2021-11-20 + + 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 3 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, see . +===========================================================================*/ + +module music #( + parameter ROM_WIDTH = 17 +)( + input clk, + input ce_2, + input reset, + + input [1:0] addr, + input [7:0] data_in, + output [7:0] data_out, + input write, + + input [7:0] musicrom_data_out, + output reg [ROM_WIDTH-1:0] musicrom_addr, + output [9:0] audio_out + ); + + // Music system state machine (ym player) + // - Currently recognises YM5/YM6 formats + // - Handles interleaved/non-interleaved data + // - Ignores DigiDrum samples completely + // - Variable play rate (50/60hz) + // - Recognises loop point + + reg [7:0] regarray[3:0]; + // Music control registers + // 0 - 1 = play, 2 = loop, 3 = stop + // 1-3 - Start address of music to play in ROM + + assign data_out = { 6'b0, ymp_loop, ymp_playing }; + + // YM2149 audio_out generator + reg [7:0] snd_data_in; + reg snd_wr; + + jt49 jt49_music( + .clk(clk), + .clk_en(ce_2), + .rst_n(~(reset || ymp_state == YM_INIT || ymp_state == YM_STOPPED )), // Hold YM2149 in reset while player state is initialising or stopped + .addr(ymp_register), + .din(snd_data_in), + .dout(), + .sound(audio_out), + .sample(), + .A(), + .B(), + .C(), + .sel(1'b1), + .cs_n(1'b0), + .wr_n(~snd_wr), + .IOA_in(), + .IOA_out(), + .IOB_in(), + .IOB_out() + ); + + localparam YM_INIT = 0; + localparam YM_WAIT = 1; + localparam YM_GETMODE = 2; + localparam YM_GETLENGTH_0 = 3; + localparam YM_GETLENGTH_1 = 4; + localparam YM_GETFREQUENCY = 5; + localparam YM_GETLOOP_0 = 6; + localparam YM_GETLOOP_1 = 7; + localparam YM_SKIPSTRINGS = 8; + localparam YM_STOPPED = 9; + + localparam YM_WAITFORFRAME = 12; + localparam YM_GETREGISTER = 13; + localparam YM_SETREGISTER = 14; + localparam YM_NEXTREGISTER = 15; + + localparam YM_REGCOUNT = 16; + + reg [ROM_WIDTH-1:0] ymp_trackoffset; + reg ymp_playing; + reg ymp_loop; + + reg [3:0] ymp_state; + reg [3:0] ymp_state_next; + reg [ROM_WIDTH-1:0] ymp_frame; + reg [3:0] ymp_register; + reg ymp_interleave; + reg ymp_is_50hz; + reg [2:0] ymp_skipstringindex = 3'b0; + reg [ROM_WIDTH-1:0] ymp_firstframe; + + reg [ROM_WIDTH-1:0] ymp_length; + reg [ROM_WIDTH-1:0] ymp_looppoint; + reg [(YM_REGCOUNT * 8)-1:0] ymp_registermask = { + 8'b00000000, + 8'b00000000, + 8'b00001111, + 8'b11111111, + 8'b11111111, + 8'b00011111, + 8'b00011111, + 8'b00011111, + 8'b11111111, + 8'b00011111, + 8'b00001111, + 8'b11111111, + 8'b00001111, + 8'b11111111, + 8'b00001111, + 8'b11111111 + }; + + reg [19:0] frame_timer_50; + reg [19:0] frame_timer_60; + localparam [19:0] frame_timer_max_50 = 20'd480000; + localparam [19:0] frame_timer_max_60 = 20'd400000; + + reg frame_ready; + + //`define YM_DEBUG + + always @(posedge clk) + begin + + // Frame timers + frame_timer_50 <= frame_timer_50 + 20'd1; + if(frame_timer_50 == frame_timer_max_50) + begin + frame_timer_50 <= 20'd0; + if(ymp_is_50hz) frame_ready <= 1'b1; + end + frame_timer_60 <= frame_timer_60 + 20'd1; + if(frame_timer_60 == frame_timer_max_60) + begin + frame_timer_60 <= 20'd0; + if(!ymp_is_50hz) frame_ready <= 1'b1; + end + + if( reset ) begin + regarray[0]<=8'd0; + regarray[1]<=8'd0; + regarray[2]<=8'd0; + regarray[3]<=8'd0; + ymp_state <= YM_INIT; + ymp_skipstringindex <= 3'b0; + end + else + begin + if( write ) begin +`ifdef YM_DEBUG + $display("YM->RAM->WRITE %x %x", addr, data_in); +`endif + regarray[addr] <= data_in; + end + else + begin + case(regarray[0]) + 8'd1: + begin +`ifdef YM_DEBUG + $display("YM->PLAY-TRACK %d %d", {regarray[1], regarray[2], regarray[3]}, regarray[0][1:0]); +`endif + regarray[0] <= 8'd0; + /* verilator lint_off WIDTH */ + ymp_trackoffset <= {{regarray[1], regarray[2], regarray[3]}}; + /* verilator lint_on WIDTH */ + ymp_playing <= 1'b1; + ymp_loop <= 1'b0; + ymp_state <= YM_INIT; + end + 8'd2: + begin +`ifdef YM_DEBUG + $display("YM->LOOP-TRACK %d %d", {regarray[1], regarray[2], regarray[3]}, regarray[0][1:0]); +`endif + regarray[0] <= 8'd0; + /* verilator lint_off WIDTH */ + ymp_trackoffset <= {{regarray[1], regarray[2], regarray[3]}}; + /* verilator lint_on WIDTH */ + ymp_playing <= 1'b1; + ymp_loop <= 1'b1; + ymp_state <= YM_INIT; + end + 8'd3: + begin +`ifdef YM_DEBUG + $display("YM->STOP-TRACK"); +`endif + ymp_playing <= 0; + regarray[0]<=8'd0; + regarray[1]<=8'd0; + regarray[2]<=8'd0; + regarray[3]<=8'd0; + ymp_state <= YM_STOPPED; + end + default: + begin + + end + endcase + end + + case (ymp_state) + YM_INIT: + begin + if(ymp_playing) + begin +`ifdef YM_DEBUG + $display("YM_INIT"); +`endif + // Reset player frame and register + ymp_frame <= {ROM_WIDTH{1'b0}}; + ymp_register <= 4'b0; + ymp_skipstringindex <= 3'b0; + // Set address to read first song attribute byte + musicrom_addr <= ymp_trackoffset + {{ROM_WIDTH-8{1'b0}},8'h13}; + + ymp_state_next <= YM_GETMODE; + ymp_state <= YM_WAIT; + end + end + + YM_WAIT: + begin + ymp_state <= ymp_state_next; + end + + YM_GETMODE: + begin +`ifdef YM_DEBUG + $display("YM_GETMODE %x %x", musicrom_addr, musicrom_data_out); +`endif + ymp_interleave <= musicrom_data_out[0]; + + // Set address to read song length byte 0 + musicrom_addr <= ymp_trackoffset + {{ROM_WIDTH-8{1'b0}},8'h0f}; + ymp_state <= YM_WAIT; + ymp_state_next <= YM_GETLENGTH_0; + end + + // Get song length + YM_GETLENGTH_0: + begin +`ifdef YM_DEBUG + $display("YM_GETLENGTH_0 %x %x", musicrom_addr, musicrom_data_out); +`endif + // Read song length byte 0 + ymp_length[7:0] <= musicrom_data_out; + + // Set address to read song length byte 1 + musicrom_addr <= ymp_trackoffset + {{ROM_WIDTH-8{1'b0}},8'h0e}; + ymp_state <= YM_WAIT; + ymp_state_next <= YM_GETLENGTH_1; + end + YM_GETLENGTH_1: + begin +`ifdef YM_DEBUG + $display("YM_GETLENGTH_1 %x %x", musicrom_addr, musicrom_data_out); +`endif + // Read song length byte 1 + ymp_length[14:8] <= musicrom_data_out[6:0]; + // Set address to frequency point + musicrom_addr <= ymp_trackoffset + {{ROM_WIDTH-8{1'b0}},8'h1b}; + ymp_state <= YM_WAIT; + ymp_state_next <= YM_GETFREQUENCY; + end + + // Get song playback frequency + YM_GETFREQUENCY: + begin +`ifdef YM_DEBUG + $display("YM_GETFREQUENCY %x %x", musicrom_addr, musicrom_data_out); +`endif + // Read song length byte 1 + ymp_is_50hz <= musicrom_data_out[7:0] == 8'd50; + // Set address to loop point + musicrom_addr <= ymp_trackoffset + {{ROM_WIDTH-8{1'b0}},8'h1f}; + ymp_state <= YM_WAIT; + ymp_state_next <= YM_GETLOOP_0; + end + + // Get song loop point + YM_GETLOOP_0: + begin +`ifdef YM_DEBUG + $display("YM_GETLOOP_0 %x %x", musicrom_addr, musicrom_data_out); +`endif + // Read song loop point byte 0 + ymp_looppoint[7:0] <= musicrom_data_out; + + // Set address to read song length byte 1 + musicrom_addr <= ymp_trackoffset + {{ROM_WIDTH-8{1'b0}},8'h1e}; + ymp_state <= YM_WAIT; + ymp_state_next <= YM_GETLOOP_1; + end + YM_GETLOOP_1: + begin +`ifdef YM_DEBUG + $display("YM_GETLOOP_1 %x %x", musicrom_addr, musicrom_data_out); +`endif + // Read song loop point byte 1 + ymp_looppoint[14:8] <= musicrom_data_out[6:0]; + // Set address to read past NT-string data + musicrom_addr <= ymp_trackoffset + {{ROM_WIDTH-8{1'b0}},8'h22}; + ymp_state <= YM_WAIT; + ymp_state_next <= YM_SKIPSTRINGS; + end + + // Skip past null terminated strings to find first frame data point + YM_SKIPSTRINGS: + begin +`ifdef YM_DEBUG + $display("YM_SKIPSTRINGS %x %x", musicrom_addr, musicrom_data_out); +`endif + if(musicrom_data_out == 8'b0) + begin + if(ymp_skipstringindex == 3'd2) + begin + ymp_firstframe <= musicrom_addr - ymp_trackoffset; + ymp_state <= YM_WAITFORFRAME; + end + else + begin + ymp_skipstringindex <= ymp_skipstringindex + 3'b1; + end + end + musicrom_addr <= musicrom_addr + {{ROM_WIDTH-1{1'b0}},1'b1}; + end + + // Main loop - wait for next vertical blank + YM_WAITFORFRAME: + begin + if(!ymp_playing) + begin +`ifdef YM_DEBUG + $display("ymp_playing %d - STOPPING MUSIC", ymp_playing); +`endif + ymp_state <= YM_INIT; + end + if(frame_ready) + begin +`ifdef YM_DEBUG + $display("YM_WAITFORFRAME f=%d l=%d ff=%d", ymp_frame, ymp_length, ymp_firstframe); +`endif + frame_ready <= 1'b0; + ymp_register <= 4'b0; + ymp_state <= YM_WAIT; + ymp_state_next <= YM_GETREGISTER; + end + end + + YM_GETREGISTER: + begin + // Calculate address for this frame+register combo in ROM + // - If ymp_interleave=1 then position is (register * length) + frame + // - If ymp_interleave=0 then position is (frame * 16) + register +`ifdef YM_DEBUG + $display("YM_GETREGISTER I %d F %d / %d R %d - A %x D %x", ymp_interleave, ymp_frame, ymp_length, ymp_register, musicrom_addr, musicrom_data_out); +`endif + if(ymp_interleave) + begin + musicrom_addr <= ymp_trackoffset + (ymp_register * ymp_length) + ymp_frame + ymp_firstframe; + end + else + begin + musicrom_addr <= ymp_trackoffset + {ymp_frame[11:0], 4'b0} + ymp_firstframe; + end + ymp_state <= YM_WAIT; + ymp_state_next <= YM_SETREGISTER; + end + + YM_SETREGISTER: + begin +`ifdef YM_DEBUG + $display("YM_SETREGISTER I %d F %d / %d R %d - A %x D %x", ymp_interleave,ymp_frame, ymp_length, ymp_register, musicrom_addr, musicrom_data_out); +`endif + snd_data_in <= musicrom_data_out & ymp_registermask[{ymp_register, 3'b0}+:8]; + snd_wr <= 1'b1; + ymp_state <= YM_NEXTREGISTER; + end + + YM_NEXTREGISTER: + begin +`ifdef YM_DEBUG + $display("YM_NEXTREGISTER I %d F %d / %d R %d - A %x D %x", ymp_interleave,ymp_frame, ymp_length, ymp_register, musicrom_addr, musicrom_data_out); +`endif + snd_wr <= 1'b0; + if(ymp_register == 4'd13) + begin + ymp_frame <= ymp_frame + 16'd1; + ymp_state <= YM_WAITFORFRAME; + if((ymp_frame + 16'd1)== ymp_length ) + begin + if(ymp_loop) + begin + // Set frame back to loop start +`ifdef YM_DEBUG + $display("YM LOOP I %d F %d / %d R %d - A %x D %x", ymp_interleave,ymp_frame, ymp_length, ymp_register, musicrom_addr, musicrom_data_out); +`endif + ymp_frame <= ymp_looppoint; + end + else + begin + // Stop playing + ymp_playing <= 0; + regarray[0]<=8'd0; + regarray[1]<=8'd0; + regarray[2]<=8'd0; + regarray[3]<=8'd0; + ymp_state <= YM_STOPPED; + end + end + end + else + begin + ymp_register <= ymp_register + 4'b1; + ymp_state <= YM_GETREGISTER; + end + + end + + endcase + end + end +endmodule \ No newline at end of file diff --git a/rtl/palette.hex b/rtl/palette.hex new file mode 100644 index 0000000..2888bc1 --- /dev/null +++ b/rtl/palette.hex @@ -0,0 +1,16 @@ + 00 00 d6 b5 a9 4a bd ef 94 a5 83 e0 83 e0 83 e0 + 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 + 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 + 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 + 00 00 80 0f 80 1f 81 bf 83 7f fe 40 ff e0 ff ff + fc 80 bc 40 82 a6 81 e4 81 83 81 02 fd 16 fc 10 + bd ff fe eb d5 80 80 07 83 e0 83 e0 83 e0 83 e0 + 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 + 00 00 83 ff 83 7f 82 df 81 b6 80 8d 80 00 ff ff + d7 3f 90 9b 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 + 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 + 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 + 00 00 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 + 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 + 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 + 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 83 e0 diff --git a/rtl/pause.v b/rtl/pause.v new file mode 100644 index 0000000..9a0c957 --- /dev/null +++ b/rtl/pause.v @@ -0,0 +1,100 @@ +//============================================================================ +// Generic pause handling for MiSTer cores. +// +// https://github.com/JimmyStones/Pause_MiSTer +// +// Copyright (c) 2021 Jim Gregory +// +// 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 3 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., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ +/* + Features: + - Pause can be triggered by user input, hiscore module or OSD opening (optionally controlled by setting in OSD) + - When paused the RGB outputs will be halved after 10 seconds to reduce burn-in (optionally controlled by setting in OSD) + - Reset signal will cancel user triggered pause + + Version history: + 0001 - 2021-03-15 - First marked release + 0002 - 2021-08-28 - Add optional output of dim_video signal (currently used by Galaga) +============================================================================ +*/ +module pause #( + parameter RW=8, // Width of red channel + parameter GW=8, // Width of green channel + parameter BW=8, // Width of blue channel + parameter CLKSPD = 12 // Main clock speed in MHz +) +( + input clk_sys, // Core system clock (should match HPS module) + input reset, // CPU reset signal (active-high) + input user_button, // User pause button signal (active-high) + input pause_request, // Pause requested by other code (active-high) + input [1:0] options, // Pause options from OSD + // [0] = pause in OSD (active-high) + // [1] = dim video (active-high) + input OSD_STATUS, // OSD is open (active-high) + input [(RW-1):0] r, // Red channel + input [(GW-1):0] g, // Green channel + input [(BW-1):0] b, // Blue channel + + output pause_cpu, // Pause signal to CPU (active-high) +`ifdef PAUSE_OUTPUT_DIM + output dim_video, // Dim video requested (active-high) +`endif + output [(RW+GW+BW-1):0] rgb_out // RGB output to arcade_video module + +); + +// Option constants +localparam pause_in_osd = 1'b0; +localparam dim_video_timer= 1'b1; + +reg pause_toggle = 1'b0; // User paused (active-high) +reg [31:0] pause_timer = 32'b0; // Time since pause +reg [31:0] dim_timeout = (CLKSPD*10000000); // Time until video output dim (10 seconds @ CLKSPD Mhz) +`ifndef PAUSE_OUTPUT_DIM +wire dim_video; // Dim video requested (active-high) +`endif + +assign pause_cpu = (pause_request | pause_toggle | (OSD_STATUS & options[pause_in_osd])) & !reset; +assign dim_video = (pause_timer >= dim_timeout); + +always @(posedge clk_sys) begin + + // Track user pause button down + reg user_button_last; + user_button_last <= user_button; + if(!user_button_last & user_button) pause_toggle <= ~pause_toggle; + + // Clear user pause on reset + if(pause_toggle & reset) pause_toggle <= 0; + + if(pause_cpu & options[dim_video_timer]) + begin + // Track pause duration for video dim + if((pause_timer> 1,g >> 1, b >> 1} : {r,g,b}; + +endmodule \ No newline at end of file diff --git a/rtl/pll/pll_0002_q13.qip b/rtl/pll/pll_0002_q13.qip deleted file mode 100644 index 9f8ded1..0000000 --- a/rtl/pll/pll_0002_q13.qip +++ /dev/null @@ -1,4 +0,0 @@ -set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_0002*|altera_pll:altera_pll_i*|*" -set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_0002*|altera_pll:altera_pll_i*|*" -set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_0002*|altera_pll:altera_pll_i*|*" -set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*" diff --git a/rtl/rom.hex b/rtl/rom.hex index 6c58d7c..a6eadaf 100644 --- a/rtl/rom.hex +++ b/rtl/rom.hex @@ -14,7 +14,7 @@ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 31 00 00 cd 77 3d cd 0a 2d c3 04 02 00 00 00 00 + 31 00 00 cd 97 77 cd b9 03 c3 04 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 @@ -30,956 +30,1886 @@ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 3e 02 cf c9 3e 00 cf 76 18 fd 3a 01 c5 87 5f 3a - ff c4 b7 20 07 3a 00 c5 b7 20 01 1c 21 fe c3 16 - 00 19 7e fd 21 02 c5 fd 77 00 fd 7e 00 b7 c8 01 - 13 c0 2a 07 c5 26 00 09 fd 7e 00 77 21 07 c5 34 - c9 40 20 0d 58 5a 66 76 12 59 11 63 16 29 75 6b - 74 72 dd e5 dd 21 00 00 dd 39 3b 01 00 75 2a 03 - c5 26 00 09 7e e6 04 4f af b9 17 dd 77 ff 4f 3a - fe c4 91 ca 28 03 0e 00 79 d6 02 30 14 3e 0a 81 - 5f 3e c0 ce 00 57 21 00 75 06 00 09 7e 12 0c 18 - e7 21 0b c0 4e cb 41 28 05 11 01 00 18 03 11 00 - 00 21 0d c0 73 cb 49 28 05 01 01 00 18 03 01 00 - 00 21 0c c0 71 3a 0a c0 32 01 c5 21 02 c5 36 00 - 3a 0c c0 b7 28 32 01 93 c0 2a 01 c5 26 00 09 36 - 01 21 48 02 4e 3a 01 c5 91 20 07 21 ff c4 36 01 - 18 46 21 49 02 4e 3a 01 c5 91 20 07 21 00 c5 36 - 01 18 35 cd 0a 02 18 30 01 93 c0 2a 01 c5 26 00 - 09 36 00 21 48 02 4e 3a 01 c5 91 20 07 21 ff c4 - 36 00 18 14 21 49 02 4e 3a 01 c5 91 20 07 21 00 - c5 36 00 18 03 cd 0a 02 dd 7e ff 32 fe c4 01 00 - 76 2a 06 c5 26 00 09 7e e6 01 4f 41 21 04 c5 5e - 78 93 28 23 21 05 c5 36 01 3a 00 76 32 11 c0 3a - 05 76 32 12 c0 3a 01 76 32 0e c0 3a 02 76 32 0f - c0 3a 04 76 32 10 c0 21 04 c5 71 33 dd e1 c9 3a - 0c c5 32 0d c5 3a 0e c5 32 0f c5 3a 08 c5 32 09 - c5 3a 0a c5 32 0b c5 3a 93 c1 32 10 c5 3a 94 c1 - 32 11 c5 3a 95 c1 32 12 c5 3a 96 c1 32 13 c5 3a - 00 70 cb 5f 20 14 01 93 c0 fd 21 4e 02 fd 6e 00 - 26 00 09 cb 46 20 03 af 18 02 3e 01 32 0c c5 3a - 00 70 cb 57 20 14 01 93 c0 fd 21 51 02 fd 6e 00 - 26 00 09 cb 46 20 03 af 18 02 3e 01 32 0e c5 3a - 00 70 cb 4f 20 14 01 93 c0 fd 21 4f 02 fd 6e 00 - 26 00 09 cb 46 20 03 af 18 02 3e 01 32 08 c5 3a - 00 70 0f 38 14 01 93 c0 fd 21 50 02 fd 6e 00 26 - 00 09 cb 46 20 03 af 18 02 3e 01 32 0a c5 3a 01 - 70 cb 5f 20 14 01 93 c0 fd 21 4c 02 fd 6e 00 26 - 00 09 cb 46 20 03 af 18 02 3e 01 32 93 c1 3a 01 - 70 cb 57 20 14 01 93 c0 fd 21 47 02 fd 6e 00 26 - 00 09 cb 46 20 03 af 18 02 3e 01 32 94 c1 3a 00 - 70 cb 67 20 14 01 93 c0 fd 21 45 02 fd 6e 00 26 - 00 09 cb 46 20 03 af 18 02 3e 01 32 95 c1 3a 00 - 70 cb 6f 20 14 01 93 c0 fd 21 4d 02 fd 6e 00 26 - 00 09 cb 46 20 03 af 18 02 3e 01 32 96 c1 c9 dd - e5 dd 21 00 00 dd 39 01 00 00 21 00 c0 79 96 78 - 23 9e 30 1b 21 00 80 09 dd 7e 04 77 21 00 88 09 - dd 7e 04 77 21 00 90 09 dd 7e 04 77 03 18 db dd - e1 c9 dd e5 dd 21 00 00 dd 39 01 00 00 21 00 c0 - 79 96 78 23 9e 30 0b 21 00 90 09 dd 7e 04 77 03 - 18 eb dd e1 c9 dd e5 dd 21 00 00 dd 39 f5 21 41 - 02 5e dd 66 08 2e 00 55 06 08 29 30 01 19 10 fa - dd 4e 07 06 00 09 eb dd 6e 04 dd 66 05 e5 cd 01 - 2f f1 4d 06 00 78 91 30 20 21 00 80 19 e3 dd 7e - 04 80 6f dd 7e 05 ce 00 67 7e e1 e5 77 21 00 88 - 19 dd 7e 06 77 13 04 18 dc dd f9 dd e1 c9 dd e5 - dd 21 00 00 dd 39 21 df ff 39 f9 21 41 02 5e dd - 66 08 2e 00 55 06 08 29 30 01 19 10 fa dd 4e 07 - 06 00 09 eb dd 7e 09 4f 17 9f 47 21 00 00 39 dd - 75 fd dd 74 fe d5 c5 dd 4e 04 dd 46 05 c5 e5 cd - cd 2e 21 06 00 39 f9 d1 dd 4e fd dd 46 fe c5 cd - 01 2f f1 dd 75 ff 0e 00 79 dd 96 ff 30 1f dd 6e - fd dd 66 fe 06 00 09 46 78 b7 28 11 21 00 80 19 - 70 21 00 88 19 dd 7e 06 77 13 0c 18 db dd f9 dd - e1 c9 dd e5 dd 21 00 00 dd 39 21 df ff 39 f9 21 - 41 02 5e dd 66 08 2e 00 55 06 08 29 30 01 19 10 - fa dd 4e 07 06 00 09 eb dd 4e 09 06 00 21 00 00 - 39 dd 75 fd dd 74 fe d5 c5 dd 4e 04 dd 46 05 c5 - e5 cd cd 2e 21 06 00 39 f9 d1 dd 4e fd dd 46 fe - c5 cd 01 2f f1 dd 75 ff 0e 00 79 dd 96 ff 30 1f - dd 6e fd dd 66 fe 06 00 09 46 78 b7 28 11 21 00 - 80 19 70 21 00 88 19 dd 7e 06 77 13 0c 18 db dd - f9 dd e1 c9 dd e5 dd 21 00 00 dd 39 21 d5 ff 39 - f9 21 41 02 5e dd 66 08 2e 00 55 06 08 29 30 01 - 19 10 fa dd 4e 07 06 00 09 eb 21 00 00 39 dd 75 - fd dd 74 fe 4d 44 d5 dd 6e 09 dd 66 0a e5 dd 6e - 04 dd 66 05 e5 c5 cd cd 2e 21 06 00 39 f9 d1 dd - 4e fd dd 46 fe c5 cd 01 2f f1 dd 75 ff 0e 00 79 - dd 96 ff 30 1f dd 6e fd dd 66 fe 06 00 09 46 78 - b7 28 11 21 00 80 19 70 21 00 88 19 dd 7e 06 77 - 13 0c 18 db dd f9 dd e1 c9 dd e5 dd 21 00 00 dd - 39 21 d5 ff 39 f9 21 41 02 5e dd 66 08 2e 00 55 - 06 08 29 30 01 19 10 fa dd 4e 07 06 00 09 eb 21 - 00 00 39 dd 75 fd dd 74 fe 4d 44 d5 dd 6e 09 dd - 66 0a e5 dd 6e 04 dd 66 05 e5 c5 cd cd 2e 21 06 - 00 39 f9 d1 dd 4e fd dd 46 fe c5 cd 01 2f f1 dd - 75 ff 0e 00 79 dd 96 ff 30 1f dd 6e fd dd 66 fe - 06 00 09 46 78 b7 28 11 21 00 80 19 70 21 00 88 - 19 dd 7e 06 77 13 0c 18 db dd f9 dd e1 c9 dd e5 - dd 21 00 00 dd 39 21 d5 ff 39 f9 21 41 02 5e dd - 66 08 2e 00 55 06 08 29 30 01 19 10 fa dd 4e 07 - 06 00 09 eb 21 00 00 39 dd 75 fe dd 74 ff 4d 44 - d5 dd 6e 0b dd 66 0c e5 dd 6e 09 dd 66 0a e5 dd - 6e 04 dd 66 05 e5 c5 cd cd 2e 21 08 00 39 f9 d1 - dd 4e fe dd 46 ff c5 cd 01 2f f1 dd 75 fd 0e 00 - 79 dd 96 fd 30 1f dd 6e fe dd 66 ff 06 00 09 46 - 78 b7 28 11 21 00 80 19 70 21 00 88 19 dd 7e 06 - 77 13 0c 18 db dd f9 dd e1 c9 dd e5 dd 21 00 00 - dd 39 21 41 02 5e dd 66 07 2e 00 55 06 08 29 30 - 01 19 10 fa dd 4e 06 06 00 09 eb 21 00 80 19 dd - 7e 04 77 21 00 88 19 dd 7e 05 77 dd e1 c9 dd e5 - dd 21 00 00 dd 39 21 41 02 5e dd 66 07 2e 00 55 - 06 08 29 30 01 19 10 fa dd 4e 06 06 00 09 eb 0e - 00 79 dd 96 08 30 14 21 00 80 19 dd 7e 04 77 21 - 00 88 19 dd 7e 05 77 13 0c 18 e6 dd e1 c9 dd e5 - dd 21 00 00 dd 39 21 41 02 5e dd 66 06 2e 00 55 - 06 08 29 30 01 19 10 fa dd 4e 05 06 00 09 11 00 - 88 19 dd 7e 04 77 dd e1 c9 dd e5 dd 21 00 00 dd - 39 21 41 02 5e dd 66 06 2e 00 55 06 08 29 30 01 - 19 10 fa dd 4e 05 06 00 09 11 00 90 19 dd 7e 04 - 77 dd e1 c9 dd e5 dd 21 00 00 dd 39 21 41 02 5e - dd 66 06 2e 00 55 06 08 29 30 01 19 10 fa dd 4e - 05 06 00 09 eb 0e 00 79 dd 96 07 30 0c 21 00 90 - 19 dd 7e 04 77 13 0c 18 ee dd e1 c9 dd e5 dd 21 - 00 00 dd 39 f5 f5 3b dd 4e 07 dd 5e 07 16 00 dd - 6e 08 26 00 19 79 1e 00 95 7b 9c e2 10 09 ee 80 - f2 ae 09 dd 56 0b 15 79 b7 28 06 21 15 c5 46 18 - 04 21 14 c5 46 c5 d5 33 dd 66 0a dd 6e 09 e5 c5 - 33 cd ea 07 f1 f1 c1 dd 36 fe 01 dd 5e 06 61 2e - 00 55 06 08 29 30 01 19 10 fa eb dd 7e 04 83 dd - 77 fc dd 7e 05 8a dd 77 fd dd 5e 0a dd 36 ff 00 - 7b 3c dd 77 fb dd 7e ff d6 08 30 38 dd 6e fc dd - 66 fd 7e dd a6 fe b7 28 06 21 15 c5 46 18 04 21 - 14 c5 46 c5 dd 56 0b d5 dd 7e 09 f5 33 c5 33 cd - ea 07 f1 f1 c1 dd 5e fb dd 7e fe 87 dd 77 fe dd - 34 ff 18 bc dd 7e fb dd 77 0a 0c c3 fa 08 dd f9 - dd e1 c9 dd e5 dd 21 00 00 dd 39 dd 46 04 dd 7e - 06 90 38 2d c5 dd 7e 05 f5 33 c5 33 dd 66 09 dd - 6e 08 e5 cd ea 07 f1 f1 c1 c5 dd 7e 07 f5 33 c5 - 33 dd 66 09 dd 6e 08 e5 cd ea 07 f1 f1 c1 04 18 - cd dd 46 05 04 78 dd 96 07 30 2d c5 c5 33 dd 66 - 04 dd 6e 09 e5 dd 7e 08 f5 33 cd ea 07 f1 f1 c1 - c5 c5 33 dd 66 06 dd 6e 09 e5 dd 7e 08 f5 33 cd - ea 07 f1 f1 c1 04 18 cd dd e1 c9 dd e5 dd 21 00 - 00 dd 39 dd 66 05 dd 6e 04 e5 dd 56 08 1e 95 d5 - cd ea 07 f1 f1 dd 66 05 dd 6e 06 e5 dd 56 08 1e - 89 d5 cd ea 07 f1 f1 dd 66 07 dd 6e 04 e5 dd 56 - 08 1e 8a d5 cd ea 07 f1 f1 dd 66 07 dd 6e 06 e5 - dd 56 08 1e 8b d5 cd ea 07 f1 f1 dd 46 04 04 78 - dd 96 06 30 2b c5 dd 7e 05 f5 33 c5 33 dd 56 08 - 1e 83 d5 cd ea 07 f1 f1 c1 c5 dd 7e 07 f5 33 c5 - 33 dd 56 08 1e 83 d5 cd ea 07 f1 f1 c1 04 18 cf - dd 46 05 04 78 dd 96 07 30 2b c5 c5 33 dd 7e 04 - f5 33 dd 56 08 1e 82 d5 cd ea 07 f1 f1 c1 c5 c5 - 33 dd 7e 06 f5 33 dd 56 08 1e 82 d5 cd ea 07 f1 - f1 c1 04 18 cf dd e1 c9 dd e5 dd 21 00 00 dd 39 - dd 66 05 dd 6e 04 e5 dd 56 08 1e 95 d5 cd ea 07 - f1 f1 dd 66 05 dd 6e 06 e5 dd 56 09 1e 89 d5 cd - ea 07 f1 f1 dd 66 07 dd 6e 04 e5 dd 56 09 1e 8a - d5 cd ea 07 f1 f1 dd 66 07 dd 6e 06 e5 dd 56 0a - 1e 8b d5 cd ea 07 f1 f1 dd 46 04 04 78 dd 96 06 - 30 2b c5 dd 7e 05 f5 33 c5 33 dd 56 09 1e 83 d5 - cd ea 07 f1 f1 c1 c5 dd 7e 07 f5 33 c5 33 dd 56 - 0a 1e 83 d5 cd ea 07 f1 f1 c1 04 18 cf dd 46 05 - 04 78 dd 96 07 30 2b c5 c5 33 dd 7e 04 f5 33 dd - 56 09 1e 82 d5 cd ea 07 f1 f1 c1 c5 c5 33 dd 7e - 06 f5 33 dd 56 0a 1e 82 d5 cd ea 07 f1 f1 c1 04 - 18 cf dd e1 c9 dd e5 dd 21 00 00 dd 39 dd 46 05 - dd 7e 06 dd 96 04 4f dd 7e 07 90 38 1b 51 14 c5 - 58 d5 dd 66 04 dd 6e 09 e5 dd 7e 08 f5 33 cd 1e - 08 f1 f1 33 c1 04 18 df dd e1 c9 dd e5 dd 21 00 - 00 dd 39 dd 46 05 dd 7e 06 dd 96 04 4f dd 7e 07 - 90 38 15 51 14 c5 58 d5 dd 66 04 dd 6e 08 e5 cd - b4 08 f1 f1 c1 04 18 e5 dd e1 c9 dd e5 dd 21 00 - 00 dd 39 dd 4e 05 dd 7e 06 dd 96 04 47 dd 7e 07 - 91 38 16 c5 c5 33 79 f5 33 dd 66 04 dd 6e 08 e5 - cd b4 08 f1 f1 c1 0c 18 e4 dd e1 c9 21 02 00 39 - 56 1e 1d d5 3e 27 f5 33 af f5 33 af f5 33 cd 2b - 0a f1 f1 33 c9 01 5e 00 78 d6 1d d0 16 00 58 7a - d6 27 30 30 c5 d5 79 f5 33 4a c5 3e ff f5 33 21 - 99 0c e5 cd d2 05 21 06 00 39 f9 d1 c1 63 24 c5 - d5 6a e5 af 47 c5 cd ea 07 f1 f1 d1 c1 0c 14 14 - 14 14 18 ca 43 04 04 18 bf 25 64 00 dd e5 dd 21 - 00 00 dd 39 dd cb 04 46 20 09 dd cb 05 46 20 03 - af 18 02 3e 01 4f c5 af f5 33 cd 9f 04 33 11 0b - 01 d5 3e ff f5 33 21 d0 0d e5 cd f5 04 f1 f1 33 - 11 06 04 d5 11 02 07 d5 3e 27 f5 33 af f5 33 af - f5 33 cd e8 0a 21 07 00 39 f9 c1 cb 41 28 05 11 - 1a 00 18 03 11 1d 00 43 c5 11 a4 52 d5 3e a4 f5 - 33 c5 33 11 03 27 d5 af f5 33 cd e8 0a 21 07 00 - 39 f9 c1 cb 41 ca cd 0d dd cb 04 46 28 0b dd cb - 05 46 28 05 21 02 00 18 03 21 01 00 7d 3d 20 03 - 3e 01 20 af 4f b7 28 05 11 27 00 18 03 11 13 00 - 79 b7 28 05 01 14 00 18 03 01 0a 00 e5 c5 d5 01 - 80 40 c5 3e c0 f5 33 16 1d d5 3e 1b f5 33 af f5 - 33 cd e8 0a 21 07 00 39 f9 d1 c1 e1 7d d6 02 20 - 1a 43 04 c5 11 80 40 d5 11 1d c0 d5 11 1b 27 d5 - c5 33 cd e8 0a 21 07 00 39 f9 c1 dd cb 04 46 28 - 1e 79 c6 f7 47 c5 3e 1c f5 33 c5 33 3e db f5 33 - 21 e4 0d e5 cd f5 04 f1 f1 33 c1 79 c6 14 4f dd - cb 05 46 28 18 79 c6 f8 47 3e 1c f5 33 c5 33 3e - db f5 33 21 f6 0d e5 cd f5 04 f1 f1 33 dd e1 c9 - 4d 69 53 54 65 72 20 49 6e 70 75 74 20 54 65 73 - 74 65 72 00 48 6f 6c 64 20 53 65 6c 65 63 74 3a - 20 4d 65 6e 75 00 53 74 61 72 74 3a 20 43 6f 6e - 74 69 6e 75 65 00 dd e5 dd 21 00 00 dd 39 f5 f5 - dd 7e 05 dd 77 ff c6 02 dd 77 fe f5 33 dd 56 04 - 1e fe d5 3e 95 f5 33 cd ea 07 f1 f1 dd 4e 04 79 - 3c dd 77 fd c5 3e 19 f5 33 dd 7e fe f5 33 dd 56 - fd 1e fe d5 3e 83 f5 33 cd 1e 08 f1 f1 33 c1 79 - c6 1a 5f c5 d5 dd 56 fe d5 11 89 fe d5 cd ea 07 - f1 f1 d1 c1 06 03 78 d6 08 30 2e dd 7e 05 80 57 - c5 d5 d5 33 dd 56 04 1e fe d5 3e 82 f5 33 cd ea - 07 f1 f1 d1 d5 d5 33 53 1e fe d5 3e 82 f5 33 cd - ea 07 f1 f1 d1 c1 04 18 cd dd 7e ff c6 08 47 c5 - d5 c5 33 dd 56 04 1e fe d5 3e 8a f5 33 cd ea 07 - f1 f1 d1 c1 c5 c5 33 53 1e fe d5 3e 8b f5 33 cd - ea 07 f1 f1 c1 79 c6 08 dd 77 fc c5 c5 33 dd 56 - fc 1e fe d5 3e 8b f5 33 cd ea 07 f1 f1 c1 79 c6 - 12 5f c5 d5 c5 33 53 1e fe d5 3e 8a f5 33 cd ea - 07 f1 f1 d1 c1 dd 7e ff c6 07 57 c5 d5 d5 33 dd - 56 fc 1e fe d5 3e 95 f5 33 cd ea 07 f1 f1 d1 d5 - d5 33 53 1e fe d5 3e 89 f5 33 cd ea 07 f1 f1 d1 - c1 c5 d5 3e 07 f5 33 c5 33 dd 56 fd 1e fe d5 3e - 83 f5 33 cd 1e 08 f1 f1 33 d1 c1 79 c6 09 5f c5 - 3e 09 f5 33 d5 33 53 1e fe d5 3e 83 f5 33 cd 1e - 08 f1 f1 33 c1 79 c6 13 57 c5 3e 07 f5 33 4a c5 - 11 83 fe d5 cd 1e 08 f1 f1 33 c1 dd 46 ff 04 c5 - c5 33 dd 56 fd 1e fe d5 3e 82 f5 33 cd ea 07 f1 - f1 dd 7e fe f5 33 dd 56 fd 1e fe d5 3e b1 f5 33 - cd ea 07 f1 f1 dd 7e 05 f5 33 dd 56 fd 1e fe d5 - 3e 95 f5 33 cd ea 07 f1 f1 c1 51 14 14 c5 3e 03 - f5 33 dd 7e 05 f5 33 d5 33 11 83 fe d5 cd 1e 08 - f1 f1 33 c1 79 c6 05 57 c5 d5 4a c5 11 82 fe d5 - cd ea 07 f1 f1 d1 d5 dd 7e fe f5 33 d5 33 11 b1 - fe d5 cd ea 07 f1 f1 d1 dd 7e 05 f5 33 d5 33 11 - 89 fe d5 cd ea 07 f1 f1 c1 79 c6 15 57 c5 d5 4a - c5 11 82 fe d5 cd ea 07 f1 f1 d1 d5 dd 7e fe f5 - 33 d5 33 11 b1 fe d5 cd ea 07 f1 f1 d1 dd 7e 05 - f5 33 d5 33 11 95 fe d5 cd ea 07 f1 f1 c1 79 c6 - 16 57 c5 3e 03 f5 33 dd 7e 05 f5 33 d5 33 11 83 - fe d5 cd 1e 08 f1 f1 33 c1 79 c6 19 57 d5 4a c5 - 11 82 fe d5 cd ea 07 f1 f1 d1 d5 dd 7e fe f5 33 - d5 33 11 b1 fe d5 cd ea 07 f1 f1 d1 dd 7e 05 f5 - 33 d5 33 11 89 fe d5 cd ea 07 dd f9 dd e1 c9 dd - e5 dd 21 00 00 dd 39 21 fa ff 39 f9 dd 7e 05 dd + 3e 02 cf c9 3e 00 cf 76 18 fd 21 67 32 5e 21 66 + 32 66 2e 00 55 06 08 29 30 01 19 10 fa 22 51 c5 + fd 21 00 80 fd 7e 00 cb 07 e6 01 32 53 c5 fd 7e + 00 e6 40 4f f6 00 c6 ff 3e 00 17 32 55 c5 fd 7e + 00 e6 20 4f 06 00 78 b1 c6 ff 3e 00 17 32 57 c5 + fd 7e 00 e6 10 4f af b9 17 32 59 c5 fd 21 83 c7 + fd 7e 00 3d ca e6 02 fd 7e 00 d6 02 ca ec 02 fd + 7e 00 d6 03 ca f2 02 fd 7e 00 d6 04 ca f8 02 fd + 7e 00 d6 05 ca fd 02 fd 7e 00 d6 06 ca 02 03 fd + 7e 00 d6 07 28 71 fd 7e 00 d6 08 28 6f fd 7e 00 + d6 09 28 6d fd 7e 00 d6 0a 28 6b fd 7e 00 d6 14 + 28 69 fd 7e 00 d6 16 28 67 fd 7e 00 d6 1e 28 65 + fd 7e 00 d6 1f 28 70 fd 7e 00 d6 28 28 73 fd 7e + 00 d6 29 28 71 fd 7e 00 d6 2a 28 60 fd 7e 00 d6 + 2b 28 68 c3 5d 03 cd e8 0b c3 68 03 cd 31 0e c3 + 68 03 cd fe 0b c3 68 03 cd aa 11 18 6b cd f3 0b + 18 66 cd 63 0f 18 61 cd 2c 0c 18 5c cd 6e 1e 18 + 57 cd ea 27 18 52 cd fa 27 18 4d cd 8e 06 18 48 + cd e9 06 18 43 21 83 c7 36 00 21 93 03 e5 cd dd + 26 f1 cd 4f 2c 18 31 cd ab 2e 18 2c cd bc 03 18 + 27 cd 8b 2c 18 22 cd ff 2c 18 1d 21 83 c7 36 00 + 21 9c 03 e5 cd dd 26 f1 cd ce 49 18 0b 21 a9 03 + e5 cd dd 26 f1 cd e8 0b 3a 53 c5 fd 21 54 c5 fd + 77 00 3a 55 c5 fd 21 56 c5 fd 77 00 3a 57 c5 fd + 21 58 c5 fd 77 00 3a 59 c5 fd 21 5a c5 fd 77 00 + c3 20 02 53 4e 45 4b 2e 41 5a 4e 00 5a 4f 52 42 + 4c 41 58 58 2e 41 5a 4e 00 49 4e 50 55 54 54 45 + 53 54 45 52 2e 41 5a 4e 00 c3 0a 02 dd e5 dd 21 + 00 00 dd 39 21 e1 ff 39 f9 af f5 33 cd 0f 33 33 + cd f8 30 cd 03 33 cd f5 2a cd 24 31 21 00 00 e5 + 21 00 00 e5 cd 44 31 f1 21 cc bd e3 21 cd cc e5 + cd c0 31 f1 f1 21 2f ca 36 00 21 30 ca 36 00 21 + 61 c6 36 00 21 00 00 39 dd 75 f7 dd 74 f8 dd 7e + f7 dd 77 f9 dd 7e f8 dd 77 fa 3a 00 80 e6 10 4f + af b9 17 32 59 c5 fd 21 59 c5 fd cb 00 46 ca 55 + 05 fd 21 5a c5 fd cb 00 46 c2 55 05 3a 30 ca ee + 80 d6 90 da 52 05 21 30 ca 7e c6 f0 77 cd c4 32 + cd eb 32 af dd 77 fb af dd 77 fe af dd 77 ff 21 + 61 c6 fd 21 5f c6 fd 7e 00 86 dd 77 fc fd 7e 01 + ce 00 dd 77 fd dd 6e fc dd 66 fd 7e dd 77 fd 21 + 61 c6 34 dd 7e fd d6 5f 28 53 dd 7e fd b7 28 4d + dd 7e f7 dd 86 ff dd 77 fb dd 7e f8 ce 00 dd 77 + fc dd 6e fb dd 66 fc dd 7e fd 77 dd 34 fe dd 7e + fe dd 77 fb 2a 5f c6 e5 cd b8 5d f1 4d 44 0b fd + 21 61 c6 fd 6e 00 26 00 af ed 42 38 06 fd 36 00 + 00 18 0a dd 34 ff dd 7e ff d6 16 38 82 dd 4e fb + 06 00 3e 16 91 5f 3e 00 98 57 6b 62 cb 7a 28 02 + eb 23 cb 2c cb 1d dd 75 fd af dd 77 ff af dd 77 + fe dd 7e ff dd 96 fd 5f cb 7b 20 29 7b 17 9f 57 + 7b 91 7a 98 e2 19 05 ee 80 f2 35 05 dd 6e f9 dd + 66 fa 19 7e fe 2d 28 07 c6 d3 5f 17 9f 18 03 11 + 01 00 dd 73 fe dd 5e ff 16 00 2a 62 c6 19 11 10 + 8c 19 dd 7e fe 77 dd 34 ff dd 7e ff d6 16 38 ad + 18 03 cd c4 32 fd 21 59 c5 fd cb 00 46 20 5c fd + 21 5a c5 fd cb 00 46 28 52 cd 41 2b cd 8e 1f fd + 21 81 c2 fd cb 00 46 20 4f fd 21 82 c2 fd cb 00 + 46 20 45 fd 21 80 c2 fd cb 00 46 20 3b fd 21 7f + c2 fd cb 00 46 20 31 fd 21 30 ca fd 34 00 fd 34 + 00 fd 21 7b c7 fd cb 00 46 28 10 fd 21 30 ca fd + 34 00 fd 34 00 fd 34 00 fd 34 00 3a 59 c5 fd 21 + 5a c5 fd 77 00 c3 1a 04 af f5 33 cd 0f 33 33 cd + f8 30 cd 03 33 cd f5 2a cd 34 31 3a 84 c7 32 83 + c7 dd f9 dd e1 c9 43 4f 44 45 20 41 4e 44 20 47 + 46 58 5f 2d 5f 4a 49 4d 4d 59 53 54 4f 4e 45 53 + 5f 5f 5f 4d 55 53 49 43 5f 2d 5f 44 41 52 52 49 + 4e 20 43 41 52 44 41 4e 49 5f 5f 5f 54 45 53 54 + 49 4e 47 5f 2d 5f 50 4f 52 4b 43 48 4f 50 20 45 + 58 50 52 45 53 53 5f 53 4f 52 47 45 4c 49 47 5f + 4d 20 57 41 4c 52 55 53 5f 5f 5f 45 58 54 52 41 + 20 54 48 41 4e 4b 53 5f 2d 5f 41 4c 41 4e 53 57 + 58 5f 53 4f 52 47 45 4c 49 47 5f 5f 5f 00 21 83 + c7 36 14 21 65 c6 36 04 21 64 c6 36 00 c9 21 83 + c7 36 16 21 65 c6 36 04 21 64 c6 36 0f c9 21 59 + c5 cb 46 c8 21 5a c5 cb 46 c0 fd 21 65 c6 fd 35 + 00 fd 7e 00 b7 c0 21 64 c6 4e 3e 1d 91 57 3e 27 + 91 47 3e 07 f5 33 3e 7f f5 33 58 d5 3a 64 c6 f5 + 33 3a 64 c6 f5 33 cd 5f 38 21 06 00 39 f9 fd 21 + 65 c6 fd 36 00 04 fd 21 64 c6 fd 34 00 fd 7e 00 + d6 10 ca 7e 06 c9 c3 7e 06 21 59 c5 cb 46 c8 21 + 5a c5 cb 46 c0 fd 21 65 c6 fd 35 00 fd 7e 00 b7 + c0 21 64 c6 4e 3e 1d 91 57 3e 27 91 47 af f5 33 + af f5 33 58 d5 3a 64 c6 f5 33 3a 64 c6 f5 33 cd + 5f 38 21 06 00 39 f9 21 65 c6 36 04 fd 21 64 c6 + fd 35 00 fd 7e 00 b7 c0 3a 85 c7 32 83 c7 c9 dd + e5 dd 21 00 00 dd 39 f5 f5 af 57 1e 01 d5 cd f8 + 20 f1 0e 00 79 fe 02 30 5c 3c dd 77 fc 3e 71 81 + dd 77 fd 3e c6 ce 00 dd 77 fe dd 6e fd dd 66 fe + 7e c6 05 dd 77 ff 3e 6f 81 5f 3e c6 ce 00 57 1a + c6 fb 47 c5 d5 dd 66 fc dd 6e ff e5 c5 33 3e ff + f5 33 21 ba 07 e5 cd 7b 34 21 06 00 39 f9 d1 c1 + dd 6e fd dd 66 fe 46 1a c5 c5 33 f5 33 cd 59 22 + f1 c1 0c 18 9f dd f9 dd e1 c9 4a 4f 59 20 25 64 + 00 af 57 1e 01 d5 cd f8 20 f1 3a 65 c7 47 05 21 + 63 c7 4e c5 33 51 1e ff d5 21 d3 08 e5 cd 9e 33 + f1 f1 33 21 65 c7 56 21 63 c7 46 3e 12 f5 33 3e + 12 f5 33 58 d5 cd d2 24 f1 f1 3a 65 c7 c6 13 5f + 3a 63 c7 4f 0c 7b f5 33 51 1e ff d5 21 df 08 e5 + cd 9e 33 f1 f1 33 3a 65 c7 c6 13 47 3a 63 c7 c6 + 0a 4f c5 33 51 1e ff d5 21 e2 08 e5 cd 9e 33 f1 + f1 33 21 68 c7 46 04 3a 65 c7 4f 0d c5 33 51 1e + 12 d5 3e ff f5 33 21 e5 08 e5 cd 7b 34 21 06 00 + 39 f9 3a 66 c7 5f 1d 3a 64 c7 c6 07 4f 7b f5 33 + 51 1e ff d5 21 ec 08 e5 cd 9e 33 f1 f1 33 21 66 + c7 56 21 64 c7 46 3e 12 f5 33 3e 12 f5 33 58 d5 + cd d2 24 f1 f1 3a 66 c7 c6 13 47 3a 64 c7 4f 0c + c5 33 51 1e ff d5 21 df 08 e5 cd 9e 33 f1 f1 33 + 3a 66 c7 c6 13 47 3a 64 c7 c6 0a 4f c5 33 51 1e + ff d5 21 e2 08 e5 cd 9e 33 f1 f1 33 3a 66 c7 c6 + 14 47 c5 33 11 3f 05 d5 21 f9 08 e5 cd 9e 33 f1 + f1 33 c9 41 4e 41 4c 4f 47 20 4c 45 46 54 00 58 + 3a 00 59 3a 00 50 41 44 20 25 64 00 41 4e 41 4c + 4f 47 20 52 49 47 48 54 00 43 79 63 6c 65 20 73 + 65 6c 65 63 74 65 64 20 70 61 64 20 77 69 74 68 + 20 41 20 2f 20 42 00 dd e5 dd 21 00 00 dd 39 21 + ec ff 39 f9 af 57 1e 01 d5 cd f8 20 f1 11 07 05 + d5 3e ff f5 33 21 f0 0a e5 cd 9e 33 f1 f1 33 11 + 15 05 d5 3e ff f5 33 21 fd 0a e5 cd 9e 33 f1 f1 + 33 11 19 05 d5 3e ff f5 33 21 01 0b e5 cd 9e 33 + f1 f1 33 11 1e 05 d5 3e ff f5 33 21 05 0b e5 cd + 9e 33 f1 f1 33 11 22 05 d5 3e ff f5 33 21 09 0b + e5 cd 9e 33 f1 f1 33 11 07 0d d5 3e ff f5 33 21 + 0d 0b e5 cd 9e 33 f1 f1 33 11 14 0d d5 3e ff f5 + 33 21 11 0b e5 cd 9e 33 f1 f1 33 21 00 00 39 eb + dd 73 f1 dd 72 f2 dd 73 f3 dd 72 f4 dd 73 f5 dd + 72 f6 dd 73 f7 dd 72 f8 dd 73 f9 dd 72 fa af dd + 77 ff dd 7e ff d6 06 d2 a6 0a dd 4e ff 06 00 03 + dd 71 fb dd 70 fc 4b 42 d5 dd 6e fb dd 66 fc e5 + 21 1a 0b e5 c5 cd 84 5d 21 06 00 39 f9 d1 dd 7e + ff dd 77 fe c6 06 67 dd 7e ff 87 4f 3e ff 91 dd + 77 fd dd 4e f1 dd 46 f2 d5 e5 33 3e 02 f5 33 dd + 7e fd f5 33 c5 cd 9e 33 f1 f1 33 d1 dd 4e f3 dd + 46 f4 d5 dd 6e fb dd 66 fc e5 21 20 0b e5 c5 cd + 84 5d 21 06 00 39 f9 d1 dd 7e fe c6 0e dd 77 fe + dd 4e f5 dd 46 f6 d5 dd 56 fe 1e 02 d5 dd 7e fd + f5 33 c5 cd 9e 33 f1 f1 33 d1 dd 4e f7 dd 46 f8 + d5 dd 6e fb dd 66 fc e5 21 26 0b e5 c5 cd 84 5d + 21 06 00 39 f9 d1 dd 4e f9 dd 46 fa d5 dd 56 fe + 1e 0e d5 dd 7e fd f5 33 c5 cd 9e 33 f1 f1 33 d1 + dd 34 ff c3 d2 09 11 02 15 d5 3e ff f5 33 21 2c + 0b e5 cd 9e 33 f1 f1 33 11 02 17 d5 3e ff f5 33 + 21 35 0b e5 cd 9e 33 f1 f1 33 11 10 17 d5 3e ff + f5 33 21 3b 0b e5 cd 9e 33 f1 f1 33 11 18 17 d5 + 3e ff f5 33 21 3f 0b e5 cd 9e 33 dd f9 dd e1 c9 + 52 4c 44 55 41 42 58 59 4c 52 73 53 00 41 4c 58 + 00 41 4c 59 00 41 52 58 00 41 52 59 00 50 4f 53 + 00 53 50 44 20 20 50 4f 53 00 4a 4f 59 25 64 00 + 50 41 44 25 64 00 53 50 4e 25 64 00 4b 45 59 42 + 4f 41 52 44 00 4d 4f 55 53 45 00 57 48 4c 00 42 + 54 4e 53 00 fd 21 03 00 fd 39 fd 7e 00 f5 33 fd + 2b fd 7e 00 f5 33 cd f8 20 f1 11 0f 04 d5 3e aa + f5 33 21 6d 0b e5 cd 9e 33 f1 f1 33 c9 42 55 54 + 54 4f 4e 20 54 45 53 54 00 21 6d c6 36 00 21 6e + c6 36 00 01 00 c0 1e 00 7b d6 0c 30 09 6b 26 00 + 09 36 01 1c 18 f2 0e 00 79 d6 06 d0 21 0c c0 06 + 00 09 36 01 21 12 c0 06 00 09 36 ff 21 18 c0 06 + 00 09 36 01 21 1e c0 06 00 09 36 ff 21 24 c0 06 + 00 09 36 01 21 2a c0 06 00 09 36 01 21 30 c0 06 + 00 09 36 01 69 26 00 29 29 11 36 c0 19 af 77 23 + 77 23 77 23 77 0c 18 b0 21 83 c7 36 02 cd 3f 07 + c3 79 0b 21 83 c7 36 06 cd c1 07 c3 79 0b 21 83 + c7 36 04 cd 17 09 af 57 1e 01 d5 11 09 02 d5 cd + 96 30 f1 f1 21 fa c4 36 24 21 9a c4 36 00 21 50 + 01 22 4e c0 2e 00 22 50 c0 c3 79 0b 21 83 c7 36 + 08 21 69 c7 36 00 21 6a c7 36 00 21 6b c7 36 00 + 21 6c c7 36 01 21 6d c7 36 00 21 6e c7 36 00 21 + 6f c7 36 00 af 57 1e 01 d5 cd 44 0b f1 11 03 0e + d5 3e ff f5 33 21 82 0c e5 cd 9e 33 f1 f1 33 11 + 02 19 d5 3e ee f5 33 21 a4 0c e5 cd 9e 33 f1 f1 + 33 c9 50 72 65 73 73 20 74 68 65 20 62 75 74 74 + 6f 6e 20 79 6f 75 20 77 61 6e 74 20 74 6f 20 74 + 65 73 74 00 52 65 6d 65 6d 62 65 72 20 74 6f 20 + 65 6e 61 62 6c 65 20 66 61 73 74 20 55 53 42 20 + 70 6f 6c 6c 69 6e 67 21 00 dd e5 dd 21 00 00 dd + 39 0e 01 79 fe 07 30 15 3d 5f 17 9f 57 21 54 c0 + 19 eb 21 54 c0 06 00 09 7e 12 0c 18 e6 21 5a c0 + dd 7e 04 77 dd e1 c9 21 7b c7 cb 46 20 0f 21 7c + c7 cb 46 28 08 3e 01 f5 33 cd c9 0c 33 21 7d c7 + cb 46 20 0f 21 7e c7 cb 46 28 08 3e 02 f5 33 cd + c9 0c 33 21 77 c7 cb 46 20 0f 21 78 c7 cb 46 28 + 08 3e 03 f5 33 cd c9 0c 33 21 79 c7 cb 46 20 0f + 21 7a c7 cb 46 28 08 3e 04 f5 33 cd c9 0c 33 21 + 81 c2 cb 46 20 0f 21 81 c7 cb 46 28 08 3e 05 f5 + 33 cd c9 0c 33 21 82 c2 cb 46 20 0f 21 82 c7 cb + 46 28 08 3e 06 f5 33 cd c9 0c 33 3a 54 c0 3d 3e + 01 28 01 af 4f 11 55 c0 79 b7 28 34 1a 3d 20 30 + 3a 56 c0 d6 02 20 29 3a 57 c0 d6 02 20 22 3a 58 + c0 d6 03 20 1b 3a 59 c0 d6 04 20 14 3a 5a c0 d6 + 05 20 0d af f5 33 cd c9 0c 33 21 83 c7 36 1e c9 + 79 b7 c8 1a 3d c0 3a 56 c0 d6 02 c0 3a 57 c0 d6 + 02 c0 3a 58 c0 d6 03 c0 3a 59 c0 d6 04 c0 3a 5a + c0 d6 06 c0 af f5 33 cd c9 0c 33 21 83 c7 36 2b + c9 fd 21 31 8a fd 7e 00 b7 28 0f fd 36 00 00 21 + 6d c6 36 00 cd ea 27 2e 01 c9 21 80 c2 cb 46 28 + 18 fd 21 6d c6 fd 34 00 fd 7e 00 d6 3c 20 0f fd + 36 00 00 cd ea 27 2e 01 c9 21 6d c6 36 00 2e 00 + c9 dd e5 dd 21 00 00 dd 39 21 f6 ff 39 f9 cd 41 + 2b 21 57 c5 cb 46 28 0d 21 58 c5 cb 46 20 06 cd + 8e 1f cd f7 0c 21 59 c5 cb 46 ca 5e 0f 21 5a c5 + cb 46 c2 5e 0f cd f1 0d cb 45 c2 5e 0f af dd 77 + fe dd 7e fe d6 02 d2 5e 0f dd 7e fe 87 87 dd 77 + f8 3e 71 dd 86 fe dd 77 f9 3e c6 ce 00 dd 77 fa + 3e 6f dd 86 fe dd 77 fb 3e c6 ce 00 dd 77 fc af + dd 77 ff dd 7e ff d6 0c d2 58 0f dd 7e ff d6 08 + 30 1f 01 00 81 dd 6e f8 26 00 09 4e dd 46 ff 21 + 01 00 04 18 01 29 10 fd 06 00 7d a1 4f 7c a0 18 + 23 01 00 81 dd 7e f8 3c 6f 17 9f 67 09 4e dd 7e + ff c6 f8 47 21 01 00 04 18 01 29 10 fd 06 00 7d + a1 4f 7c a0 79 b7 28 06 21 ff 00 e3 18 04 21 52 + 00 e3 dd 4e f6 dd 6e f9 dd 66 fa 5e 3e 57 dd 86 + ff 6f 3e c7 ce 00 67 7e 83 dd 77 fd dd 6e fb dd + 66 fc 5e 3e 4b dd 86 ff 6f 3e c7 ce 00 67 7e 83 + 47 dd 5e ff 16 00 6b 62 29 19 29 eb 21 73 c6 19 + eb dd 7e fd f5 33 c5 33 79 f5 33 d5 cd 9e 33 f1 + f1 33 dd 34 ff c3 a3 0e dd 34 fe c3 71 0e dd f9 + dd e1 c9 dd e5 dd 21 00 00 dd 39 f5 3b cd 41 2b + 21 57 c5 cb 46 28 66 21 58 c5 cb 46 20 5f cd 8e + 1f cd f7 0c fd 21 81 c2 fd cb 00 46 20 25 fd 21 + 81 c7 fd cb 00 46 28 1b fd 21 68 c7 fd 7e 00 d6 + 05 20 06 fd 36 00 00 18 07 3a 68 c7 3c 32 68 c7 + cd c1 07 21 82 c2 cb 46 20 23 21 82 c7 cb 46 28 + 1c fd 21 68 c7 fd 7e 00 b7 20 06 fd 36 00 05 18 + 09 3a 68 c7 21 68 c7 c6 ff 77 cd c1 07 21 59 c5 + cb 46 ca a1 11 21 5a c5 cb 46 c2 a1 11 cd f1 0d + cb 45 c2 a1 11 3a 63 c7 c6 09 4f 3a 65 c7 c6 09 + 5f 3a 5d c0 83 47 21 5b c0 6e dd 71 fd 7d dd 86 + fd d5 c5 33 57 1e 23 d5 cd 07 37 f1 33 d1 01 00 + 82 fd 21 68 c7 fd 6e 00 26 00 29 09 7e dd 77 fe + 01 00 82 fd 7e 00 87 3c 6f 17 9f 67 09 7e dd 77 + ff dd 7e fe 4f 17 9f 47 d5 21 0f 00 e5 c5 cd f7 + 5d f1 f1 d1 55 21 5b c0 72 dd 7e ff 4f 17 9f 47 + d5 21 0f 00 e5 c5 cd f7 5d f1 f1 d1 7d 32 5d c0 + 83 47 7a dd 86 fd c5 33 57 1e ff d5 cd 07 37 f1 + 33 3a 65 c7 c6 13 47 3a 63 c7 c6 03 4f dd 7e fe + f5 33 c5 33 51 1e ff d5 21 a6 11 e5 cd f7 33 21 + 06 00 39 f9 3a 65 c7 c6 13 47 3a 63 c7 c6 0c 4f + dd 7e ff f5 33 c5 33 51 1e ff d5 21 a6 11 e5 cd + f7 33 21 06 00 39 f9 3a 64 c7 c6 09 5f 3a 66 c7 + c6 09 4f 21 5e c0 6e dd 71 fd 7d dd 86 fd 4f 3a + 5c c0 83 47 d5 79 f5 33 c5 33 3e 23 f5 33 cd 07 + 37 f1 33 d1 01 00 83 fd 21 68 c7 fd 6e 00 26 00 + 29 09 7e dd 77 fe 01 00 83 fd 7e 00 87 3c 6f 17 + 9f 67 09 7e dd 77 ff dd 7e fe 4f 17 9f 47 d5 21 + 0f 00 e5 c5 cd f7 5d f1 f1 d1 55 21 5c c0 72 dd + 7e ff 4f 17 9f 47 d5 21 0f 00 e5 c5 cd f7 5d f1 + f1 d1 7d 32 5e c0 dd 86 fd 4f 7a 83 47 79 f5 33 + c5 33 3e ff f5 33 cd 07 37 f1 33 3a 66 c7 c6 13 + 47 3a 64 c7 c6 03 4f dd 7e fe f5 33 c5 33 51 1e + ff d5 21 a6 11 e5 cd f7 33 21 06 00 39 f9 3a 66 + c7 c6 13 47 3a 64 c7 c6 0c 4f dd 7e ff f5 33 c5 + 33 51 1e ff d5 21 a6 11 e5 cd f7 33 21 06 00 39 + f9 dd f9 dd e1 c9 25 34 64 00 dd e5 dd 21 00 00 + dd 39 21 d1 ff 39 f9 cd 41 2b 21 57 c5 cb 46 28 + 0d 21 58 c5 cb 46 20 06 cd 8e 1f cd f7 0c 21 59 + c5 cb 46 ca 90 18 21 5a c5 cb 46 c2 90 18 cd f1 + 0d cb 45 28 09 cd f8 30 cd e3 2f c3 90 18 21 00 + 00 39 dd 75 e0 dd 74 e1 dd 7e e0 dd 77 e2 dd 7e + e1 dd 77 e3 dd 7e e0 dd 77 e4 dd 7e e1 dd 77 e5 + dd 7e e0 dd 77 e6 dd 7e e1 dd 77 e7 21 0a 00 39 + dd 75 e8 dd 74 e9 dd 7e e8 dd 77 ea dd 7e e9 dd + 77 eb af dd 77 ff dd 7e ff d6 06 d2 02 16 dd 36 + fe 06 dd 7e ff c6 06 dd 77 f7 dd 7e ff 87 87 5f + dd 7e ff 87 dd 77 f8 16 00 7a fe 02 d2 fe 12 83 + 4f 7a dd 86 f8 dd 77 fd 21 00 81 06 00 09 7e dd + 77 f9 3e 00 dd 86 fd dd 77 fa 3e c0 ce 00 dd 77 + fb dd 6e fa dd 66 fb dd 7e f9 96 28 56 dd 36 fc + 01 7a b7 20 05 01 08 00 18 03 01 04 00 dd 71 fd + dd 4e fe af dd 77 fe dd 7e fe dd 96 fd 30 3e 0c + dd 7e f9 dd a6 fc b7 28 06 21 32 ca 46 18 04 21 + 31 ca 46 c5 d5 dd 7e f7 f5 33 51 1e ff d5 c5 33 + cd 93 36 f1 f1 d1 c1 dd 7e fc 87 dd 77 fc dd 34 + fe 18 c4 dd 7e fe c6 08 dd 77 fe 18 03 dd 71 fe + dd 6e fa dd 66 fb dd 7e f9 77 14 c3 59 12 dd 6e + ff 26 00 29 11 00 82 19 7e dd 77 fa dd 7e ff 87 + 3c 4f 17 9f 47 21 00 82 09 46 3e 0c dd 86 ff 5f + 3e c0 ce 00 57 1a 4f dd 7e fa 91 20 0f 3e 12 dd + 86 ff 6f 3e c0 ce 00 67 7e 90 28 59 78 6f 17 9f + 67 dd 7e fa dd 77 fb 17 9f dd 77 fc dd 7e e0 dd + 77 fd dd 7e e1 dd 77 fe c5 d5 e5 dd 6e fb dd 66 + fc e5 21 95 18 e5 dd 6e fd dd 66 fe e5 cd 84 5d + 21 08 00 39 f9 d1 c1 dd 7e ff c6 06 67 dd 6e e2 + dd 4e e3 c5 d5 e5 33 11 ff 14 d5 61 e5 cd 9e 33 + f1 f1 33 d1 c1 dd 7e fa 12 3e 12 dd 86 ff 6f 3e + c0 ce 00 67 70 dd 6e ff 26 00 29 11 00 83 19 7e + dd 77 fa dd 7e ff 87 3c 4f 17 9f 47 21 00 83 09 + 46 3e 18 dd 86 ff 5f 3e c0 ce 00 57 1a 4f dd 7e + fa 91 20 0f 3e 1e dd 86 ff 6f 3e c0 ce 00 67 7e + 90 28 59 78 6f 17 9f 67 dd 7e fa dd 77 fb 17 9f + dd 77 fc dd 7e e4 dd 77 fd dd 7e e5 dd 77 fe c5 + d5 e5 dd 6e fb dd 66 fc e5 21 95 18 e5 dd 6e fd + dd 66 fe e5 cd 84 5d 21 08 00 39 f9 d1 c1 dd 7e + ff c6 06 67 dd 6e e6 dd 4e e7 c5 d5 e5 33 11 ff + 1d d5 61 e5 cd 9e 33 f1 f1 33 d1 c1 dd 7e fa 12 + 3e 1e dd 86 ff 6f 3e c0 ce 00 67 70 01 00 84 dd + 6e ff 26 00 09 7e dd 77 fe 3e 24 dd 86 ff 5f 3e + c0 ce 00 57 1a 4f dd 7e fe 91 28 36 dd 6e fe 26 + 00 dd 4e e8 dd 46 e9 d5 e5 21 9c 18 e5 c5 cd 84 + 5d 21 06 00 39 f9 d1 dd 7e ff c6 0e 67 dd 4e ea + dd 46 eb d5 e5 33 11 ff 06 d5 c5 cd 9e 33 f1 f1 + 33 d1 dd 7e fe 12 dd 7e ff 87 3c 4f 17 9f 47 21 + 00 85 09 7e e6 01 4f dd 7e ff dd 77 fd af dd 77 + fe dd 6e fd dd 66 fe 29 11 00 85 19 7e dd 77 ec + 3e 2a dd 86 ff dd 77 ed 3e c0 ce 00 dd 77 ee dd + 6e ed dd 66 ee 46 dd 71 ef dd 7e ff c6 0e dd 77 + f0 dd 7e ef 90 ca a2 15 dd 7e fd dd 77 fd dd 7e + fe dd 77 fe 3e 03 18 08 dd cb fd 26 dd cb fe 16 + 3d 20 f5 dd 7e fd c6 36 dd 77 f1 dd 7e fe ce c0 + dd 77 f2 dd 5e f1 dd 56 f2 21 22 00 39 eb 01 04 + 00 ed b0 dd 7e ec dd 77 fd 17 9f dd 77 fe dd 7e + fd dd 77 f7 dd 7e fe dd 77 f8 17 9f dd 77 f9 dd + 77 fa dd 7e f3 dd 86 f7 dd 77 fb dd 7e f4 dd 8e + f8 dd 77 fc dd 7e f5 dd 8e f9 dd 77 fd dd 7e f6 + dd 8e fa dd 77 fe dd 5e f1 dd 56 f2 21 2a 00 39 + 01 04 00 ed b0 dd 46 fb c5 33 dd 56 f0 1e 18 d5 + 3e ff f5 33 21 9c 18 e5 cd 7b 34 21 06 00 39 f9 + 18 10 dd 7e ec 3d 28 06 dd 7e ec 3c 20 04 af dd + 77 ec 3e 30 dd 86 ff dd 77 fd 3e c0 ce 00 dd 77 + fe dd 6e fd dd 66 fe dd 7e ec 96 28 1b dd 7e ec + f5 33 dd 56 f0 1e 13 d5 3e ff f5 33 21 9c 18 e5 + cd f7 33 21 06 00 39 f9 dd 6e fd dd 66 fe dd 7e + ec 77 dd 6e ed dd 66 ee dd 7e ef 77 dd 34 ff c3 + 36 12 3a 1a c9 fd 21 66 c6 fd 96 00 20 0c 3a 1b + c9 fd 21 67 c6 fd 96 00 28 35 3a 1a c9 57 1e 15 + d5 11 ff 0b d5 21 a0 18 e5 cd 7b 34 21 06 00 39 + f9 11 0e 15 d5 3e ff f5 33 3a 1b c9 f5 33 cd 93 + 36 f1 f1 3a 1a c9 32 66 c6 3a 1b c9 32 67 c6 21 + 1d c9 cb 46 ca 8a 18 3a 8c c2 4f 17 9f 47 2a 4e + c0 09 22 4e c0 3a 8d c2 4f 17 9f 47 2a 50 c0 bf + ed 42 22 50 c0 3a 8e c2 4f 17 9f 47 2a 52 c0 09 + 22 52 c0 2a 4e c0 7d d6 20 7c 17 3f 1f de 80 30 + 08 21 20 00 22 4e c0 18 13 11 9f 82 29 3f cb 1c + cb 1d ed 52 38 06 21 9f 02 22 4e c0 2a 50 c0 7d + d6 20 7c 17 3f 1f de 80 30 08 21 20 00 22 50 c0 + 18 13 11 ff 81 29 3f cb 1c cb 1d ed 52 38 06 21 + ff 01 22 50 c0 2a 4e c0 4d 44 cb 7c 28 03 23 4d + 44 cb 28 cb 19 2a 50 c0 5d 54 cb 7c 28 02 eb 13 + cb 2a cb 1b 3a 8c c2 b7 20 06 3a 8d c2 b7 28 15 + 21 9a c4 36 01 c5 d5 d5 c5 3e 09 f5 33 cd 7b 2f + f1 f1 33 d1 c1 dd 71 fc dd 70 fd dd 7e fc c6 f0 + 4f dd 7e fd ce ff 47 d5 c5 11 08 17 d5 3e ff f5 + 33 21 a5 18 e5 cd fd 34 21 07 00 39 f9 d1 7b c6 + f0 4f 7a ce ff 47 d5 c5 11 0c 17 d5 3e ff f5 33 + 21 a5 18 e5 cd fd 34 21 07 00 39 f9 d1 21 52 c0 + 46 d5 c5 33 11 14 17 d5 3e ff f5 33 21 a5 18 e5 + cd 7b 34 21 06 00 39 f9 d1 3a 68 c6 fd 21 8f c2 + fd 96 00 28 58 0e 01 dd 36 fe 1c af dd 77 ff dd + 7e ff d6 03 30 2f dd 34 fe 3a 8f c2 a1 28 06 21 + 32 ca 46 18 04 21 31 ca 46 c5 d5 3e 17 f5 33 dd + 56 fe 1e ff d5 c5 33 cd 93 36 f1 f1 d1 c1 cb 21 + dd 34 ff 18 ca fd 21 8f c2 fd 7e 00 e6 01 32 83 + c2 fd 7e 00 e6 02 4f af b9 17 32 85 c2 3a 8f c2 + 32 68 c6 3a 69 c6 fd 21 90 c2 fd 96 00 28 40 0e + 01 dd 36 fe 1f af dd 77 ff dd 7e ff d6 05 30 2f + dd 34 fe 3a 90 c2 a1 28 06 21 32 ca 46 18 04 21 + 31 ca 46 c5 d5 3e 17 f5 33 dd 56 fe 1e ff d5 c5 + 33 cd 93 36 f1 f1 d1 c1 cb 21 dd 34 ff 18 ca 3a + 90 c2 32 69 c6 7b c6 f8 4f 7a ce ff 47 dd 7e fc + c6 f8 5f dd 7e fd ce ff 57 21 83 c2 cb 46 28 19 + 21 84 c2 cb 46 20 12 c5 d5 c5 d5 21 00 00 e5 cd + da 1e 21 06 00 39 f9 d1 c1 21 85 c2 cb 46 28 15 + 21 86 c2 cb 46 20 0e c5 d5 21 01 00 e5 cd da 1e + 21 06 00 39 f9 21 1d c9 36 00 cd 42 1f cd e3 2f + dd f9 dd e1 c9 25 34 64 25 34 64 00 25 34 64 00 + 25 30 32 78 00 25 33 64 00 21 69 c7 36 02 af f5 + 33 af f5 33 cd 44 0b f1 21 6d c7 36 3c 21 00 89 + 36 00 11 0e 0e d5 3e dd f5 33 21 f4 18 e5 cd 9e + 33 f1 f1 33 11 13 0f d5 11 13 dd d5 cd 93 36 f1 + f1 11 03 10 d5 3e dd f5 33 21 ff 18 e5 cd 9e 33 + f1 f1 33 c9 50 72 65 73 73 20 68 65 72 65 00 2d + 2d 2d 03 03 03 02 02 02 01 01 01 a6 a6 a6 7f 7f + 7f a6 a6 a6 01 01 01 02 02 02 03 03 03 2d 2d 2d + 00 21 57 c5 cb 46 ca cc 19 21 58 c5 cb 46 c2 cc + 19 3a 00 81 b7 ca cc 19 11 00 00 7a d6 08 30 22 + 21 00 81 4e 42 21 01 00 04 18 01 29 10 fd 06 00 + 7d a1 4f 7c a0 b1 28 06 21 6b c7 73 18 04 14 5a + 18 d9 21 69 c7 36 01 af f5 33 af f5 33 cd 44 0b + f1 11 05 0e d5 3e f8 f5 33 21 de 19 e5 cd 9e 33 + f1 f1 33 11 06 10 d5 3e ff f5 33 21 fc 19 e5 cd + 9e 33 f1 f1 33 21 6b c7 4e 06 00 69 60 29 09 29 + 29 11 bb c6 19 11 1a 10 d5 3e 07 f5 33 e5 cd 9e + 33 f1 f1 33 11 07 12 d5 3e 38 f5 33 21 11 1a e5 + cd 9e 33 f1 f1 33 21 6d c7 36 0a c9 21 59 c5 cb + 46 c8 21 5a c5 cb 46 c0 cd 8e 1f c3 f1 0d 48 69 + 74 20 74 68 65 20 62 75 74 74 6f 6e 20 61 74 20 + 65 61 63 68 20 70 72 6f 6d 70 74 00 53 65 6c 65 + 63 74 65 64 20 62 75 74 74 6f 6e 20 69 73 3a 20 + 00 50 72 65 73 73 20 61 67 61 69 6e 20 74 6f 20 + 73 74 61 72 74 20 74 65 73 74 00 21 57 c5 cb 46 + c8 21 58 c5 cb 46 c0 21 00 81 5e 21 6b c7 46 0e + 01 04 18 02 cb 21 10 fc 7b a1 4f fd 21 6d c7 fd + 7e 00 b7 28 0b 3a 00 81 b7 20 14 fd 35 00 18 0f + 79 b7 20 0b 3a 6c c7 b7 28 05 c5 cd a9 18 c1 21 + 6c c7 71 c9 dd e5 dd 21 00 00 dd 39 3b 21 00 81 + 4e 21 6b c7 46 21 01 00 04 18 01 29 10 fd 06 00 + 7d a1 4f 7c a0 b1 c6 ff 3e 00 17 4f dd 71 ff cb + 41 28 2f 3a 70 c7 b7 20 29 01 5f c0 fd 21 6f c7 + fd 6e 00 26 00 29 09 eb 3a 01 89 47 0e 00 3a 00 + 89 6f 26 00 79 b5 4f 78 b4 47 79 12 13 78 12 fd + 34 00 dd 7e ff 32 70 c7 21 59 c5 cb 46 ca c2 1b + 21 5a c5 cb 46 c2 c2 1b 21 6d c7 35 3e 10 f5 33 + 3a 73 c7 f5 33 af f5 33 cd 32 37 f1 33 3a 6d c7 + d6 1e 20 05 21 73 c7 36 02 3a 73 c7 b7 28 1b 21 + 6d c7 4e af cb 41 20 12 fd 21 73 c7 fd 34 00 3e + 23 fd 96 00 30 04 fd 36 00 00 3a 73 c7 b7 28 10 + 3e 10 f5 33 3a 73 c7 57 1e ff d5 cd 32 37 f1 33 + fd 21 74 c7 fd 7e 00 b7 28 24 fd 35 00 fd 7e 00 + b7 20 1b 3a 6e c7 d6 05 20 14 21 69 c7 36 03 21 + 71 c7 36 01 11 01 01 d5 cd 44 0b f1 18 54 3a 6d + c7 b7 20 4e 01 5d c2 fd 21 6e c7 fd 6e 00 26 00 + 29 09 eb 3a 01 89 47 0e 00 3a 00 89 6f 26 00 79 + b5 4f 78 b4 47 79 12 13 78 12 fd 46 00 04 c5 33 + 11 12 06 d5 3e ff f5 33 21 c6 1b e5 cd 7b 34 21 + 06 00 39 f9 21 6d c7 36 5a 21 74 c7 36 21 21 6e + c7 34 33 dd e1 c9 25 32 64 00 dd e5 dd 21 00 00 + dd 39 21 ed ff 39 f9 21 71 c7 cb 46 ca 10 1e 11 + 02 06 d5 3e ff f5 33 21 3a 1e e5 cd 9e 33 f1 f1 + 33 11 0b 06 d5 3e ff f5 33 21 42 1e e5 cd 9e 33 + f1 f1 33 dd 36 f1 07 af dd 77 f2 af dd 77 f3 dd + 77 f4 af dd 77 fe af dd 77 ff dd 7e f2 b7 c2 0b + 1e dd 7e fe dd 77 f5 af dd 77 f6 dd 7e f5 dd 77 + f7 dd 7e f6 dd 77 f8 dd cb f7 26 dd cb f8 16 dd + 7e fe d6 05 30 11 3e 5d dd 86 f7 6f 3e c2 dd 8e + f8 67 4e 23 46 18 03 01 ff ff dd 6e ff 26 00 29 + dd 75 f9 dd 74 fa 21 6f c7 dd 7e ff 96 30 1e 3e + 5f dd 86 f9 6f 3e c0 dd 8e fa 67 5e 23 56 dd 73 + ed dd 72 ee af dd 77 ef dd 77 f0 18 0f dd 36 ed + ff dd 36 ee ff af dd 77 ef dd 77 f0 dd 7e ed dd + 77 fb dd 7e ee dd 77 fc dd 7e f1 3c dd 77 fd 79 + dd 96 fb 78 dd 9e fc 30 3a dd 7e f7 c6 5d 6f dd + 7e f8 ce c2 67 5e 23 56 c5 d5 dd 56 f1 1e 02 d5 + 3e ff f5 33 21 4a 1e e5 cd fd 34 21 07 00 39 f9 + c1 dd 7e fd dd 77 f1 dd 34 fe dd 71 f3 dd 70 f4 + c3 1a 1c dd 7e fb 91 dd 7e fc 98 d2 04 1e 3e 5f + dd 86 f9 6f 3e c0 dd 8e fa 67 4e 23 46 c5 dd 56 + f1 1e 0b d5 3e ff f5 33 21 4a 1e e5 cd fd 34 21 + 07 00 39 f9 dd 4e f5 dd 46 f6 03 3e 05 b9 3e 00 + 98 e2 36 1d ee 80 fa 4a 1d 3e 5d dd 86 f7 6f 3e + c2 dd 8e f8 67 4e 23 46 18 03 01 ff ff dd 7e fb + dd 96 f3 5f dd 7e fc dd 9e f4 57 d5 cd 0c 5d f1 + dd 75 f9 dd 74 fa 79 dd 96 fb 4f 78 dd 9e fc 47 + c5 cd 0c 5d f1 dd 75 f7 dd 74 f8 4d 44 79 d6 f4 + 78 de 01 30 1f dd 6e f7 dd 66 f8 e5 dd 56 f1 1e + 14 d5 3e f8 f5 33 21 50 1e e5 cd 82 35 21 07 00 + 39 f9 18 54 dd 7e f9 dd 77 fb dd 7e fa dd 77 fc + 3e f4 dd be fb 3e 01 dd 9e fc 38 1f dd 6e f9 dd + 66 fa e5 dd 56 f1 1e 14 d5 3e 3f f5 33 21 5d 1e + e5 cd 82 35 21 07 00 39 f9 18 1d dd 6e f7 dd 66 + f8 e5 dd 56 f1 1e 14 d5 3e 07 f5 33 21 69 1e e5 + cd 82 35 21 07 00 39 f9 dd 7e fd dd 77 f1 dd 34 + ff c3 1a 1c dd 36 f2 01 c3 1a 1c 21 71 c7 36 00 + 21 59 c5 cb 46 28 1e 21 5a c5 cb 46 20 17 cd 8e + 1f cd f1 0d 21 7f c2 cb 46 28 0a 21 7f c7 cb 46 + 20 03 cd 2c 0c dd f9 dd e1 c9 50 72 6f 6d 70 74 + 73 00 50 72 65 73 73 65 73 00 25 36 64 6d 73 00 + 25 33 64 6d 73 20 62 65 66 6f 72 65 00 25 33 64 + 6d 73 20 61 66 74 65 72 00 3f 3f 3f 3f 00 fd 21 + 69 c7 fd 7e 00 b7 ca 21 19 fd 7e 00 3d ca 2b 1a + fd 7e 00 d6 02 ca 74 1a fd 7e 00 d6 03 ca ca 1b + c9 c3 21 19 c3 2b 1a c3 74 1a c3 ca 1b 21 76 c7 + 4e 06 00 21 76 c7 5e 16 00 fd 21 75 c7 fd 6e 00 + 26 00 19 79 95 78 9c e2 bc 1e ee 80 f0 51 c5 af + 47 0e 01 c5 3e 02 f5 33 d5 33 cd 96 30 f1 f1 c1 + 21 91 c4 09 36 00 03 18 ca 02 dd e5 dd 21 00 00 + dd 39 0e 00 1e 00 21 75 c7 7b 96 30 52 21 67 c2 + 16 00 19 7e b7 20 44 3a d9 1e 77 21 6f c2 06 00 + 09 36 00 3a 76 c7 81 47 c5 af 57 1e 01 d5 3e 02 + f5 33 c5 33 cd 96 30 f1 f1 c1 11 f1 c4 68 26 00 + 19 36 18 dd 6e 08 dd 66 09 e5 dd 6e 06 dd 66 07 + e5 c5 33 cd 7b 2f f1 f1 33 18 04 1c 4b 18 a7 dd + e1 c9 0e 00 21 75 c7 79 96 d0 3e 67 81 5f 3e c2 + ce 00 57 1a b7 28 34 3d 12 b7 20 2f 3a 76 c7 81 + 47 c6 f1 6f 3e c4 ce 00 67 34 3e 6f 81 6f 3e c2 + ce 00 67 7e 3c 77 d6 07 20 0d 78 c6 91 5f 3e 00 + ce c4 57 af 12 18 04 3a d9 1e 12 0c 18 b6 3a 7b + c7 fd 21 7c c7 fd 77 00 3a 7d c7 fd 21 7e c7 fd + 77 00 3a 77 c7 fd 21 78 c7 fd 77 00 3a 79 c7 fd + 21 7a c7 fd 77 00 3a 7f c2 fd 21 7f c7 fd 77 00 + 3a 80 c2 fd 21 80 c7 fd 77 00 3a 81 c2 fd 21 81 + c7 fd 77 00 3a 82 c2 fd 21 82 c7 fd 77 00 3a 83 + c2 fd 21 84 c2 fd 77 00 3a 85 c2 fd 21 86 c2 fd + 77 00 3a 00 81 0f 38 14 01 11 c3 fd 21 3f 2b fd + 6e 00 26 00 09 cb 46 20 03 af 18 02 3e 01 32 79 + c7 3a 00 81 cb 4f 20 14 01 11 c3 fd 21 3e 2b fd + 6e 00 26 00 09 cb 46 20 03 af 18 02 3e 01 32 77 + c7 3a 00 81 cb 57 20 14 01 11 c3 fd 21 40 2b fd + 6e 00 26 00 09 cb 46 20 03 af 18 02 3e 01 32 7d + c7 3a 00 81 cb 5f 20 14 01 11 c3 fd 21 3d 2b fd + 6e 00 26 00 09 cb 46 20 03 af 18 02 3e 01 32 7b + c7 3a 00 81 cb 67 20 14 01 11 c3 fd 21 34 2b fd + 6e 00 26 00 09 cb 46 20 03 af 18 02 3e 01 32 81 + c2 3a 00 81 cb 6f 20 14 01 11 c3 fd 21 3c 2b fd + 6e 00 26 00 09 cb 46 20 03 af 18 02 3e 01 32 82 + c2 3a 01 81 cb 5f 20 17 01 11 c3 fd 21 3b 2b fd + 6e 00 26 00 09 cb 46 20 06 3a 8f c2 b7 28 02 3e + 01 32 7f c2 3a 01 81 cb 57 20 17 01 11 c3 fd 21 + 36 2b fd 6e 00 26 00 09 cb 46 20 06 3a 90 c2 b7 + 28 02 3e 01 32 80 c2 c9 dd e5 dd 21 00 00 dd 39 + dd cb 04 46 20 08 dd cb 05 46 0e 00 28 02 0e 01 + c5 af f5 33 cd 0f 33 33 11 0b 01 d5 3e ff f5 33 + 21 23 22 e5 cd 9e 33 f1 f1 33 11 06 04 d5 11 02 + 07 d5 3e 27 f5 33 af f5 33 af f5 33 cd 94 39 21 + 07 00 39 f9 c1 cb 41 28 04 06 1a 18 02 06 1d c5 + 11 a4 52 d5 3e a4 f5 33 c5 33 11 03 27 d5 af f5 + 33 cd 94 39 21 07 00 39 f9 c1 cb 41 ca 20 22 dd + cb 04 46 28 0b dd cb 05 46 28 05 01 02 00 18 03 + 01 01 00 79 3d 3e 01 28 01 af 47 b7 28 05 11 27 + 00 18 03 11 13 00 78 b7 28 05 21 14 00 18 03 21 + 0a 00 e5 c5 d5 01 80 40 c5 3e c0 f5 33 16 1d d5 + 3e 1b f5 33 af f5 33 cd 94 39 21 07 00 39 f9 d1 + c1 e1 79 d6 02 20 1a 43 04 e5 11 80 40 d5 11 1d + c0 d5 11 1b 27 d5 c5 33 cd 94 39 21 07 00 39 f9 + e1 dd cb 04 46 28 1b 7d c6 f7 5f 01 37 22 e5 16 + 1c d5 3e db f5 33 c5 cd 9e 33 f1 f1 33 e1 7d c6 + 14 6f dd cb 05 46 28 18 7d c6 f8 47 3e 1c f5 33 + c5 33 3e db f5 33 21 49 22 e5 cd 9e 33 f1 f1 33 + dd e1 c9 4d 69 53 54 65 72 20 49 6e 70 75 74 20 + 54 65 73 74 65 72 00 48 6f 6c 64 20 53 65 6c 65 + 63 74 3a 20 4d 65 6e 75 00 53 74 61 72 74 3a 20 + 43 6f 6e 74 69 6e 75 65 00 dd e5 dd 21 00 00 dd + 39 f5 f5 dd 7e 05 dd 77 fc c6 02 dd 77 fd f5 33 + dd 56 04 1e fe d5 3e 95 f5 33 cd 93 36 f1 f1 dd + 4e 04 79 3c dd 77 fe c5 3e 19 f5 33 dd 7e fd f5 + 33 dd 56 fe 1e fe d5 3e 83 f5 33 cd c7 36 f1 f1 + 33 c1 79 c6 1a 5f c5 d5 dd 56 fd d5 11 89 fe d5 + cd 93 36 f1 f1 d1 c1 06 03 78 d6 08 30 2e dd 7e + 05 80 57 c5 d5 d5 33 dd 56 04 1e fe d5 3e 82 f5 + 33 cd 93 36 f1 f1 d1 d5 d5 33 53 1e fe d5 3e 82 + f5 33 cd 93 36 f1 f1 d1 c1 04 18 cd dd 7e fc c6 + 08 47 c5 d5 c5 33 dd 56 04 1e fe d5 3e 8a f5 33 + cd 93 36 f1 f1 d1 c1 c5 c5 33 53 1e fe d5 3e 8b + f5 33 cd 93 36 f1 f1 c1 79 c6 08 dd 77 ff c5 c5 + 33 dd 56 ff 1e fe d5 3e 8b f5 33 cd 93 36 f1 f1 + c1 79 c6 12 5f c5 d5 c5 33 53 1e fe d5 3e 8a f5 + 33 cd 93 36 f1 f1 d1 c1 dd 7e fc c6 07 57 c5 d5 + d5 33 dd 56 ff 1e fe d5 3e 95 f5 33 cd 93 36 f1 + f1 d1 d5 d5 33 53 1e fe d5 3e 89 f5 33 cd 93 36 + f1 f1 d1 c1 c5 d5 3e 07 f5 33 c5 33 dd 56 fe 1e + fe d5 3e 83 f5 33 cd c7 36 f1 f1 33 d1 c1 79 c6 + 09 5f c5 3e 09 f5 33 d5 33 53 1e fe d5 3e 83 f5 + 33 cd c7 36 f1 f1 33 c1 79 c6 13 57 c5 3e 07 f5 + 33 4a c5 11 83 fe d5 cd c7 36 f1 f1 33 c1 dd 46 + fc 04 c5 c5 33 dd 56 fe 1e fe d5 3e 82 f5 33 cd + 93 36 f1 f1 dd 7e fd f5 33 dd 56 fe 1e fe d5 3e + b1 f5 33 cd 93 36 f1 f1 dd 7e 05 f5 33 dd 56 fe + 1e fe d5 3e 95 f5 33 cd 93 36 f1 f1 c1 51 14 14 + c5 3e 03 f5 33 dd 7e 05 f5 33 d5 33 11 83 fe d5 + cd c7 36 f1 f1 33 c1 79 c6 05 57 c5 d5 4a c5 11 + 82 fe d5 cd 93 36 f1 f1 d1 d5 dd 7e fd f5 33 d5 + 33 11 b1 fe d5 cd 93 36 f1 f1 d1 dd 7e 05 f5 33 + d5 33 11 89 fe d5 cd 93 36 f1 f1 c1 79 c6 15 57 + c5 d5 4a c5 11 82 fe d5 cd 93 36 f1 f1 d1 d5 dd + 7e fd f5 33 d5 33 11 b1 fe d5 cd 93 36 f1 f1 d1 + dd 7e 05 f5 33 d5 33 11 95 fe d5 cd 93 36 f1 f1 + c1 79 c6 16 57 c5 3e 03 f5 33 dd 7e 05 f5 33 d5 + 33 11 83 fe d5 cd c7 36 f1 f1 33 c1 79 c6 19 57 + d5 4a c5 11 82 fe d5 cd 93 36 f1 f1 d1 d5 dd 7e + fd f5 33 d5 33 11 b1 fe d5 cd 93 36 f1 f1 d1 dd + 7e 05 f5 33 d5 33 11 89 fe d5 cd 93 36 dd f9 dd + e1 c9 dd e5 dd 21 00 00 dd 39 f5 3b dd 7e 05 dd 86 07 47 dd 7e 04 dd 86 06 4f c5 3e ff f5 33 c5 - 33 79 f5 33 dd 66 05 dd 6e 04 e5 cd 2b 0a f1 f1 - 33 c1 58 1d 0d dd 7e 05 dd 77 fa 3c dd 77 ff dd - 7e 04 dd 77 fe 47 04 c5 3e 23 f5 33 16 1b d5 79 - f5 33 dd 7e ff f5 33 c5 33 cd a5 0b 21 06 00 39 - f9 c1 dd 6e 06 26 00 5d 54 cb 7c 28 02 eb 13 cb - 2a cb 1b 7b dd 86 fe 4f dd 5e 07 16 00 6b 62 cb - 7a 28 03 6b 62 23 cb 2c cb 1d 7d dd 86 fa dd 77 - fb dd 66 06 25 c5 d5 e5 33 dd 7e fb f5 33 c5 33 - 11 83 23 d5 cd 1e 08 f1 f1 33 d1 c1 dd 46 ff dd - 6e 05 26 00 19 dd 70 fc dd 36 fd 00 dd 7e fc 95 - dd 7e fd 9c e2 49 11 ee 80 f2 62 11 c5 d5 c5 33 - 51 1e 23 d5 3e 82 f5 33 cd ea 07 f1 f1 d1 c1 04 - 18 cd dd 7e fb f5 33 51 1e 23 d5 3e 9b f5 33 cd - ea 07 dd f9 dd e1 c9 21 fc c3 36 0a 21 16 c5 36 - 00 21 18 c5 36 00 c9 dd e5 dd 21 00 00 dd 39 f5 - f5 3b cd 52 02 21 06 c0 cb 46 ca 56 12 21 07 c0 - cb 46 c2 56 12 cd 6f 03 21 0c c5 cb 46 28 1e 21 - 0d c5 cb 46 20 17 fd 21 97 c1 fd 35 00 3e 80 fd - 96 00 30 04 fd 36 00 03 21 17 c5 36 01 21 0e c5 - cb 46 28 1e 21 0f c5 cb 46 20 17 fd 21 97 c1 fd - 34 00 fd 7e 00 d6 04 20 04 fd 36 00 00 21 17 c5 - 36 01 21 93 c1 cb 46 20 07 21 10 c5 cb 46 20 1c - 21 95 c1 cb 46 20 07 21 12 c5 cb 46 20 0e 21 96 - c1 cb 46 20 41 21 13 c5 cb 46 28 3a fd 21 97 c1 - fd 7e 00 b7 28 16 fd 7e 00 3d 28 17 fd 7e 00 d6 - 02 28 17 fd 7e 00 d6 03 28 17 18 1a 21 fc c3 36 - 01 18 13 21 fc c3 36 05 18 0c 21 fc c3 36 03 18 - 05 21 fc c3 36 07 21 08 c0 cb 46 ca cb 13 21 09 - c0 cb 46 c2 cb 13 fd 21 16 c5 fd 7e 00 d6 0d d2 - 05 13 fd 5e 00 16 00 6b 4a cb 7a 28 03 13 6b 4a - cb 29 cb 1d 4d 41 04 78 c6 0f 5f 3e 0f 95 67 e5 - c5 01 36 24 c5 16 ff d5 3e 1c f5 33 e5 33 3e 0c - f5 33 cd e8 0a 21 07 00 39 f9 c1 e1 3e 01 95 30 - 3d 78 3d c6 0f 57 0d 3e 0f 91 47 c5 d5 af f5 33 - af f5 33 d5 33 3e 1b f5 33 c5 33 3e 0d f5 33 cd - a5 0b 21 06 00 39 f9 d1 c1 af f5 33 d5 33 3e 1b - f5 33 c5 33 3e 0d f5 33 cd db 0b f1 f1 33 fd 21 - 16 c5 fd 34 00 fd 7e 00 d6 0d c2 cb 13 21 17 c5 - 36 01 c3 cb 13 21 17 c5 cb 46 ca cb 13 0e 0a 1e - 00 7b d6 04 d2 c1 13 dd 71 ff 6b 26 00 dd 7e ff - c6 02 dd 77 fb dd 7e ff 3c dd 77 fc 29 dd 75 fd - dd 74 fe 3a 97 c1 93 20 40 d5 11 16 14 d5 3e 5f - f5 33 dd 56 fb 1e 1b d5 51 1e 0d d5 cd e8 0a 21 - 07 00 39 f9 d1 3e 19 dd 86 fd 6f 3e c5 dd 8e fe - 67 4e 23 46 d5 dd 56 fc 1e 0e d5 3e ff f5 33 c5 - cd f5 04 f1 f1 33 d1 18 3e d5 11 b6 64 d5 3e bf - f5 33 dd 56 fb 1e 1b d5 51 1e 0d d5 cd e8 0a 21 - 07 00 39 f9 d1 3e 19 dd 86 fd 6f 3e c5 dd 8e fe - 67 4e 23 46 d5 dd 56 fc 1e 0e d5 3e b6 f5 33 c5 - cd f5 04 f1 f1 33 d1 dd 4e ff 0c 0c 0c 1c c3 11 - 13 21 17 c5 36 00 21 18 c5 36 01 dd f9 dd e1 c9 - 21 fc c3 36 14 21 22 c5 36 04 21 21 c5 36 00 c9 - 21 fc c3 36 16 21 22 c5 36 04 21 21 c5 36 0f c9 - 21 08 c0 cb 46 c8 21 09 c0 cb 46 c0 fd 21 22 c5 - fd 35 00 fd 7e 00 b7 c0 21 21 c5 4e 3e 1d 91 57 - 3e 27 91 47 3e 07 f5 33 3e 7f f5 33 58 d5 3a 21 - c5 f5 33 3a 21 c5 f5 33 cd b3 09 21 06 00 39 f9 - 21 22 c5 36 04 fd 21 21 c5 fd 34 00 fd 7e 00 d6 - 10 c0 c3 e0 13 21 08 c0 cb 46 c8 21 09 c0 cb 46 - c0 fd 21 22 c5 fd 35 00 fd 7e 00 b7 c0 21 21 c5 - 4e 3e 1d 91 57 3e 27 91 47 af f5 33 af f5 33 58 - d5 3a 21 c5 f5 33 3a 21 c5 f5 33 cd b3 09 21 06 - 00 39 f9 21 22 c5 36 04 fd 21 21 c5 fd 35 00 fd - 7e 00 b7 c0 3a fd c3 32 fc c3 c9 dd e5 dd 21 00 - 00 dd 39 f5 f5 af 57 1e 01 d5 cd 9c 0c f1 0e 00 - 79 d6 02 30 5c 41 04 3e 2e 81 dd 77 fd 3e c5 ce - 00 dd 77 fe dd 6e fd dd 66 fe 7e c6 05 dd 77 fc - 3e 2c 81 5f 3e c5 ce 00 57 1a c6 fb dd 77 ff c5 - d5 c5 33 dd 7e fc f5 33 dd 56 ff 1e ff d5 21 16 - 15 e5 cd d2 05 21 06 00 39 f9 d1 c1 dd 6e fd dd - 66 fe 46 1a c5 c5 33 f5 33 cd 06 0e f1 c1 0c 18 - 9f dd f9 dd e1 c9 4a 4f 59 20 25 64 00 af 57 1e - 01 d5 cd 9c 0c f1 3a 22 c6 47 05 21 20 c6 4e c5 - 33 51 1e ff d5 21 2f 16 e5 cd f5 04 f1 f1 33 21 - 22 c6 56 21 20 c6 46 3e 12 f5 33 3e 12 f5 33 58 - d5 cd 7f 10 f1 f1 3a 22 c6 c6 13 5f 3a 20 c6 4f - 0c 7b f5 33 51 1e ff d5 21 3b 16 e5 cd f5 04 f1 - f1 33 3a 22 c6 c6 13 47 3a 20 c6 c6 0a 4f c5 33 - 51 1e ff d5 21 3e 16 e5 cd f5 04 f1 f1 33 21 25 - c6 46 04 3a 22 c6 4f 0d c5 33 51 1e 12 d5 3e ff - f5 33 21 41 16 e5 cd d2 05 21 06 00 39 f9 3a 23 - c6 5f 1d 3a 21 c6 c6 07 4f 7b f5 33 51 1e ff d5 - 21 48 16 e5 cd f5 04 f1 f1 33 21 23 c6 56 21 21 - c6 46 3e 12 f5 33 3e 12 f5 33 58 d5 cd 7f 10 f1 - f1 3a 23 c6 c6 13 47 3a 21 c6 4f 0c c5 33 51 1e - ff d5 21 3b 16 e5 cd f5 04 f1 f1 33 3a 23 c6 c6 - 13 47 3a 21 c6 c6 0a 4f c5 33 51 1e ff d5 21 3e - 16 e5 cd f5 04 f1 f1 33 3a 23 c6 c6 14 47 c5 33 - 11 3f 05 d5 21 55 16 e5 cd f5 04 f1 f1 33 c9 41 - 4e 41 4c 4f 47 20 4c 45 46 54 00 58 3a 00 59 3a - 00 50 41 44 20 25 64 00 41 4e 41 4c 4f 47 20 52 - 49 47 48 54 00 43 79 63 6c 65 20 73 65 6c 65 63 - 74 65 64 20 70 61 64 20 77 69 74 68 20 41 20 2f - 20 42 00 dd e5 dd 21 00 00 dd 39 21 ec ff 39 f9 - af 57 1e 01 d5 cd 9c 0c f1 11 07 05 d5 3e ff f5 - 33 21 4c 18 e5 cd f5 04 f1 f1 33 11 15 05 d5 3e - ff f5 33 21 59 18 e5 cd f5 04 f1 f1 33 11 19 05 - d5 3e ff f5 33 21 5d 18 e5 cd f5 04 f1 f1 33 11 - 1e 05 d5 3e ff f5 33 21 61 18 e5 cd f5 04 f1 f1 - 33 11 22 05 d5 3e ff f5 33 21 65 18 e5 cd f5 04 - f1 f1 33 11 07 0d d5 3e ff f5 33 21 69 18 e5 cd - f5 04 f1 f1 33 11 14 0d d5 3e ff f5 33 21 6d 18 - e5 cd f5 04 f1 f1 33 21 00 00 39 eb dd 73 fd dd - 72 fe dd 73 f7 dd 72 f8 dd 73 f5 dd 72 f6 dd 73 - f3 dd 72 f4 dd 73 fb dd 72 fc dd 36 ff 00 dd 7e - ff d6 06 d2 02 18 dd 4e ff 06 00 03 dd 71 f9 dd - 70 fa 4b 42 d5 dd 6e f9 dd 66 fa e5 21 76 18 e5 - c5 cd cd 2e 21 06 00 39 f9 d1 dd 7e ff dd 77 f2 - c6 06 67 dd 7e ff 87 4f 3e ff 91 dd 77 f1 dd 4e - fd dd 46 fe d5 e5 33 3e 02 f5 33 dd 7e f1 f5 33 - c5 cd f5 04 f1 f1 33 d1 dd 4e f7 dd 46 f8 d5 dd - 6e f9 dd 66 fa e5 21 7c 18 e5 c5 cd cd 2e 21 06 - 00 39 f9 d1 dd 7e f2 c6 0e dd 77 f2 dd 4e f5 dd - 46 f6 d5 dd 56 f2 1e 02 d5 dd 7e f1 f5 33 c5 cd - f5 04 f1 f1 33 d1 dd 4e f3 dd 46 f4 d5 dd 6e f9 - dd 66 fa e5 21 82 18 e5 c5 cd cd 2e 21 06 00 39 - f9 d1 dd 4e fb dd 46 fc d5 dd 56 f2 1e 0e d5 dd - 7e f1 f5 33 c5 cd f5 04 f1 f1 33 d1 dd 34 ff c3 - 2e 17 11 02 15 d5 3e ff f5 33 21 88 18 e5 cd f5 - 04 f1 f1 33 11 02 17 d5 3e ff f5 33 21 91 18 e5 - cd f5 04 f1 f1 33 11 10 17 d5 3e ff f5 33 21 97 - 18 e5 cd f5 04 f1 f1 33 11 18 17 d5 3e ff f5 33 - 21 9b 18 e5 cd f5 04 dd f9 dd e1 c9 52 4c 44 55 - 41 42 58 59 4c 52 73 53 00 41 4c 58 00 41 4c 59 - 00 41 52 58 00 41 52 59 00 50 4f 53 00 53 50 44 - 20 20 50 4f 53 00 4a 4f 59 25 64 00 50 41 44 25 - 64 00 53 50 4e 25 64 00 4b 45 59 42 4f 41 52 44 - 00 4d 4f 55 53 45 00 57 48 4c 00 42 54 4e 53 00 - 21 03 00 39 7e f5 33 21 03 00 39 7e f5 33 cd 9c - 0c f1 11 0f 04 d5 3e aa f5 33 21 c5 18 e5 cd f5 - 04 f1 f1 33 c9 42 55 54 54 4f 4e 20 54 45 53 54 - 00 21 2a c5 36 00 21 2b c5 36 00 01 98 c1 1e 00 - 7b d6 0c 30 09 6b 26 00 09 36 01 1c 18 f2 0e 00 - 79 d6 06 d0 21 a4 c1 06 00 09 36 01 21 aa c1 06 - 00 09 36 ff 21 b0 c1 06 00 09 36 01 21 b6 c1 06 - 00 09 36 ff 21 bc c1 06 00 09 36 01 21 c2 c1 06 - 00 09 36 01 21 c8 c1 06 00 09 36 01 69 26 00 29 - 29 11 ce c1 19 af 77 23 77 23 77 23 36 00 0c 18 - af 21 fc c3 36 02 cd 9b 14 c3 d1 18 21 fc c3 36 - 06 cd 1d 15 c3 d1 18 21 fc c3 36 04 cd 73 16 c3 - d1 18 21 fc c3 36 08 21 26 c6 36 00 21 27 c6 36 - 00 21 28 c6 36 00 21 29 c6 36 01 21 2a c6 36 00 - 21 2b c6 36 00 21 2c c6 36 00 af 57 1e 01 d5 cd - a0 18 f1 11 03 0e d5 3e ff f5 33 21 b8 19 e5 cd - f5 04 f1 f1 33 11 02 19 d5 3e ee f5 33 21 da 19 - e5 cd f5 04 f1 f1 33 c9 50 72 65 73 73 20 74 68 - 65 20 62 75 74 74 6f 6e 20 79 6f 75 20 77 61 6e - 74 20 74 6f 20 74 65 73 74 00 52 65 6d 65 6d 62 - 65 72 20 74 6f 20 65 6e 61 62 6c 65 20 66 61 73 - 74 20 55 53 42 20 70 6f 6c 6c 69 6e 67 21 00 dd - e5 dd 21 00 00 dd 39 0e 01 79 fe 07 30 15 3d 5f - 17 9f 57 21 e9 c1 19 eb 21 e9 c1 06 00 09 7e 12 - 0c 18 e6 21 ef c1 dd 7e 04 77 dd e1 c9 21 0c c5 - cb 46 20 0f 21 0d c5 cb 46 28 08 3e 01 f5 33 cd - ff 19 33 21 0e c5 cb 46 20 0f 21 0f c5 cb 46 28 - 08 3e 02 f5 33 cd ff 19 33 21 08 c5 cb 46 20 0f - 21 09 c5 cb 46 28 08 3e 03 f5 33 cd ff 19 33 21 - 0a c5 cb 46 20 0f 21 0b c5 cb 46 28 08 3e 04 f5 - 33 cd ff 19 33 21 95 c1 cb 46 20 0f 21 12 c5 cb - 46 28 08 3e 05 f5 33 cd ff 19 33 3a e9 c1 3d c0 - 3a ea c1 3d c0 3a eb c1 d6 02 c0 3a ec c1 d6 02 - c0 3a ed c1 d6 03 c0 3a ee c1 d6 04 c0 3a ef c1 - d6 05 c0 21 fd c3 36 1e af f5 33 cd ff 19 33 c3 - d0 13 21 94 c1 cb 46 28 18 fd 21 2a c5 fd 34 00 - fd 7e 00 d6 3c 20 0f fd 36 00 00 cd 77 11 2e 01 - c9 21 2a c5 36 00 2e 00 c9 dd e5 dd 21 00 00 dd - 39 21 f7 ff 39 f9 cd 52 02 21 06 c0 cb 46 28 0d - 21 07 c0 cb 46 20 06 cd 6f 03 cd 2d 1a 21 08 c0 - cb 46 ca 26 1c 21 09 c0 cb 46 c2 26 1c cd d2 1a - cb 45 c2 26 1c dd 36 ff 00 dd 7e ff d6 02 d2 26 - 1c dd 7e ff 87 87 dd 77 fe 3e 2e dd 86 ff dd 77 - fb 3e c5 ce 00 dd 77 fc 3e 2c dd 86 ff dd 77 f9 - 3e c5 ce 00 dd 77 fa dd 36 fd 00 dd 7e fd d6 0c - d2 20 1c dd 7e fd d6 08 30 1f 01 00 70 dd 6e fe - 26 00 09 4e dd 46 fd 21 01 00 04 18 01 29 10 fd - 06 00 7d a1 4f 7c a0 18 23 01 00 70 dd 7e fe 3c - 6f 17 9f 67 09 4e dd 7e fd c6 f8 47 21 01 00 04 - 18 01 29 10 fd 06 00 7d a1 4f 7c a0 79 b7 28 06 - 21 ff 00 e3 18 04 21 52 00 e3 dd 4e f7 dd 6e fb - dd 66 fc 5e 3e 14 dd 86 fd 6f 3e c6 ce 00 67 7e - 83 dd 77 f7 dd 6e f9 dd 66 fa 5e 3e 08 dd 86 fd - 6f 3e c6 ce 00 67 7e 83 47 dd 5e fd 16 00 6b 62 - 29 19 29 eb 21 30 c5 19 eb dd 7e f7 f5 33 c5 33 - 79 f5 33 d5 cd f5 04 f1 f1 33 dd 34 fd c3 6b 1b - dd 34 ff c3 39 1b dd f9 dd e1 c9 dd e5 dd 21 00 - 00 dd 39 f5 f5 3b cd 52 02 21 06 c0 cb 46 28 5d - 21 07 c0 cb 46 20 56 cd 6f 03 cd 2d 1a 21 95 c1 - cb 46 20 1f 21 12 c5 cb 46 28 18 fd 21 25 c6 fd - 7e 00 d6 05 20 06 fd 36 00 00 18 04 21 25 c6 34 - cd 1d 15 21 96 c1 cb 46 20 23 21 13 c5 cb 46 28 - 1c fd 21 25 c6 fd 7e 00 b7 20 06 fd 36 00 05 18 - 09 3a 25 c6 21 25 c6 c6 ff 77 cd 1d 15 21 08 c0 - cb 46 ca 60 1e 21 09 c0 cb 46 c2 60 1e cd d2 1a - cb 45 c2 60 1e 3a 20 c6 c6 09 4f 3a 22 c6 c6 09 - 5f 3a f2 c1 83 47 21 f0 c1 6e dd 71 fb 7d dd 86 - fb d5 c5 33 57 1e 23 d5 cd 5e 08 f1 33 d1 01 00 - 71 fd 21 25 c6 fd 6e 00 26 00 29 09 7e dd 77 fd - 01 00 71 fd 7e 00 87 3c 6f 17 9f 67 09 7e dd 77 - fc dd 7e fd 4f 17 9f 47 d5 21 0f 00 e5 c5 cd 29 - 2f f1 f1 d1 55 21 f0 c1 72 dd 7e fc 4f 17 9f 47 - d5 21 0f 00 e5 c5 cd 29 2f f1 f1 d1 7d 32 f2 c1 - 83 47 7a dd 86 fb c5 33 57 1e ff d5 cd 5e 08 f1 - 33 3a 22 c6 c6 13 47 3a 20 c6 4f 0c 0c 0c dd 7e - fd f5 33 c5 33 51 1e ff d5 21 65 1e e5 cd 4e 05 - 21 06 00 39 f9 3a 22 c6 c6 13 47 3a 20 c6 c6 0c - 4f dd 7e fc f5 33 c5 33 51 1e ff d5 21 65 1e e5 - cd 4e 05 21 06 00 39 f9 3a 21 c6 c6 09 5f 3a 23 - c6 c6 09 4f 21 f3 c1 6e dd 71 fc 7d dd 86 fc 4f - 3a f1 c1 83 47 d5 79 f5 33 c5 33 3e 23 f5 33 cd - 5e 08 f1 33 d1 01 00 72 fd 21 25 c6 fd 6e 00 26 - 00 29 09 7e dd 77 fe 01 00 72 fd 7e 00 87 3c 6f - 17 9f 67 09 7e dd 77 ff dd 7e fe 4f 17 9f 47 d5 - 21 0f 00 e5 c5 cd 29 2f f1 f1 d1 55 21 f1 c1 72 - dd 7e ff 4f 17 9f 47 d5 21 0f 00 e5 c5 cd 29 2f - f1 f1 d1 7d 32 f3 c1 dd 86 fc 4f 7a 83 47 79 f5 - 33 c5 33 3e ff f5 33 cd 5e 08 f1 33 3a 23 c6 c6 - 13 5f 3a 21 c6 4f 0c 0c 0c dd 56 fe d5 51 1e ff - d5 21 65 1e e5 cd 4e 05 21 06 00 39 f9 3a 23 c6 - c6 13 47 3a 21 c6 c6 0c 4f dd 7e ff f5 33 c5 33 - 51 1e ff d5 21 65 1e e5 cd 4e 05 21 06 00 39 f9 - dd f9 dd e1 c9 25 34 64 00 dd e5 dd 21 00 00 dd - 39 21 c8 ff 39 f9 cd 52 02 21 06 c0 cb 46 28 0d - 21 07 c0 cb 46 20 06 cd 6f 03 cd 2d 1a 21 08 c0 - cb 46 ca ff 23 21 09 c0 cb 46 c2 ff 23 cd d2 1a - cb 45 c2 ff 23 21 05 00 39 dd 75 db dd 74 dc dd - 7e db dd 77 df dd 7e dc dd 77 e0 dd 7e db dd 77 - e3 dd 7e dc dd 77 e4 dd 7e db dd 77 eb dd 7e dc - dd 77 ec 21 00 00 39 dd 75 f1 dd 74 f2 dd 7e f1 - dd 77 d7 dd 7e f2 dd 77 d8 dd 36 fa 00 dd 7e fa - d6 06 d2 a8 22 dd 36 f8 06 dd 7e fa c6 06 dd 77 - f9 dd 7e fa 87 87 dd 77 f3 dd 7e fa 87 dd 77 fc - 0e 00 79 fe 02 d2 bd 1f dd 86 f3 5f 79 dd 86 fc - 47 21 00 70 16 00 19 7e dd 77 f7 3e 98 80 5f 3e - c1 ce 00 57 1a 47 dd 7e f7 90 28 6c dd 36 f4 01 - 79 b7 20 0a dd 36 d9 08 dd 36 da 00 18 08 dd 36 - d9 04 dd 36 da 00 dd 7e d9 dd 77 fd dd 46 f8 dd - 36 fb 00 dd 7e fb dd 96 fd 30 47 04 dd 7e f7 dd - a6 f4 b7 28 08 3a 15 c5 dd 77 d9 18 06 3a 14 c5 - dd 77 d9 c5 d5 dd 7e f9 f5 33 c5 33 3e ff f5 33 - dd 7e d9 f5 33 cd ea 07 f1 f1 d1 c1 dd 7e f4 87 - dd 77 f4 dd 34 fb 18 bb dd 7e f8 c6 08 dd 77 f8 - 18 03 dd 70 f8 dd 7e f7 12 0c c3 12 1f dd 6e fa - 26 00 29 11 00 71 19 7e dd 77 fe dd 7e fa 87 3c - 4f 17 9f 47 21 00 71 09 46 3e a4 dd 86 fa 5f 3e - c1 ce 00 57 1a 4f dd 7e fe 91 20 0f 3e aa dd 86 - fa 6f 3e c1 ce 00 67 7e 90 28 53 78 6f 17 9f 67 - dd 7e fe dd 77 d9 17 9f dd 77 da e5 dd 6e db dd - 66 dc e5 fd e1 e1 c5 d5 e5 dd 6e d9 dd 66 da e5 - 21 04 24 e5 fd e5 cd cd 2e 21 08 00 39 f9 d1 c1 - dd 7e fa c6 06 67 dd 6e df dd 4e e0 c5 d5 e5 33 - 11 ff 14 d5 61 e5 cd f5 04 f1 f1 33 d1 c1 dd 7e - fe 12 3e aa dd 86 fa 6f 3e c1 ce 00 67 70 dd 6e - fa 26 00 29 11 00 72 19 7e dd 77 f6 dd 7e fa 87 - 3c 4f 17 9f 47 21 00 72 09 46 3e b0 dd 86 fa 5f - 3e c1 ce 00 57 1a 4f dd 7e f6 91 20 0f 3e b6 dd - 86 fa 6f 3e c1 ce 00 67 7e 90 28 53 78 6f 17 9f - 67 dd 7e f6 dd 77 d9 17 9f dd 77 da e5 dd 6e e3 - dd 66 e4 e5 fd e1 e1 c5 d5 e5 dd 6e d9 dd 66 da - e5 21 04 24 e5 fd e5 cd cd 2e 21 08 00 39 f9 d1 - c1 dd 7e fa c6 06 67 dd 6e eb dd 4e ec c5 d5 e5 - 33 11 ff 1d d5 61 e5 cd f5 04 f1 f1 33 d1 c1 dd - 7e f6 12 3e b6 dd 86 fa 6f 3e c1 ce 00 67 70 01 - 00 73 dd 6e fa 26 00 09 7e dd 77 ff 3e bc dd 86 - fa 5f 3e c1 ce 00 57 1a 4f dd 7e ff 91 28 38 dd - 6e ff 26 00 dd 4e f1 dd 46 f2 d5 e5 21 0b 24 e5 - c5 cd cd 2e 21 06 00 39 f9 d1 dd 7e fa c6 0e 4f - dd 6e d7 dd 66 d8 d5 51 1e 06 d5 3e ff f5 33 e5 - cd f5 04 f1 f1 33 d1 dd 7e ff 12 dd 7e fa 87 3c - 4f 17 9f 47 21 00 74 09 7e e6 01 4f dd 7e fa dd - 77 d9 dd 36 da 00 6f 26 00 29 11 00 74 19 7e dd - 77 f5 3e c2 dd 86 fa dd 77 dd 3e c1 ce 00 dd 77 - de dd 6e dd dd 66 de 46 dd 71 e1 dd 7e fa c6 0e - dd 77 e2 dd 7e e1 90 ca 48 22 3e 03 18 08 dd cb - d9 26 dd cb da 16 3d 20 f5 3e ce dd 86 d9 dd 77 - d9 3e c1 dd 8e da dd 77 da dd 5e d9 dd 56 da 21 - 1d 00 39 eb 01 04 00 ed b0 dd 7e f5 dd 77 e9 17 - 9f dd 77 ea dd 7e e9 dd 77 ed dd 7e ea dd 77 ee - 17 9f dd 77 ef dd 77 f0 dd 7e e5 dd 86 ed dd 77 - ed dd 7e e6 dd 8e ee dd 77 ee dd 7e e7 dd 8e ef - dd 77 ef dd 7e e8 dd 8e f0 dd 77 f0 dd 5e d9 dd - 56 da 21 25 00 39 01 04 00 ed b0 dd 46 ed c5 33 - dd 56 e2 1e 18 d5 3e ff f5 33 21 0b 24 e5 cd d2 - 05 21 06 00 39 f9 18 10 dd 7e f5 3d 28 06 dd 7e - f5 3c 20 04 dd 36 f5 00 3e c8 dd 86 fa dd 77 ed - 3e c1 ce 00 dd 77 ee dd 6e ed dd 66 ee dd 7e f5 - 96 28 1b dd 7e f5 f5 33 dd 56 e2 1e 13 d5 3e ff - f5 33 21 0b 24 e5 cd 4e 05 21 06 00 39 f9 dd 6e - ed dd 66 ee dd 7e f5 77 dd 6e dd dd 66 de dd 7e - e1 77 dd 34 fa c3 ed 1e 3a 01 c5 fd 21 23 c5 fd - 96 00 20 0c 3a 02 c5 fd 21 24 c5 fd 96 00 28 35 - 3a 01 c5 57 1e 15 d5 11 ff 0b d5 21 0f 24 e5 cd - d2 05 21 06 00 39 f9 11 0e 15 d5 3e ff f5 33 3a - 02 c5 f5 33 cd ea 07 f1 f1 3a 01 c5 32 23 c5 3a - 02 c5 32 24 c5 21 05 c5 cb 46 ca ff 23 fd 21 e6 - c1 fd 7e 00 21 0e c0 86 fd 77 00 fd 21 e7 c1 fd - 7e 00 21 0f c0 86 fd 77 00 fd 21 e8 c1 fd 7e 00 - 21 10 c0 86 fd 77 00 3a e6 c1 57 1e 17 d5 11 ff - 08 d5 21 14 24 e5 cd d2 05 21 06 00 39 f9 3a e7 - c1 57 1e 17 d5 11 ff 0c d5 21 14 24 e5 cd d2 05 - 21 06 00 39 f9 3a e8 c1 57 1e 17 d5 11 ff 14 d5 - 21 14 24 e5 cd d2 05 21 06 00 39 f9 3a 25 c5 fd - 21 11 c0 fd 96 00 28 3b 01 01 1c 1e 00 7b d6 03 - 30 2b 04 3a 11 c0 a1 28 06 21 15 c5 56 18 04 21 - 14 c5 56 c5 d5 3e 17 f5 33 c5 33 3e ff f5 33 d5 - 33 cd ea 07 f1 f1 d1 c1 cb 21 1c 18 d0 3a 11 c0 - 32 25 c5 3a 26 c5 fd 21 12 c0 fd 96 00 28 3b 01 - 01 1f 1e 00 7b d6 05 30 2b 04 3a 12 c0 a1 28 06 - 21 15 c5 56 18 04 21 14 c5 56 c5 d5 3e 17 f5 33 - c5 33 3e ff f5 33 d5 33 cd ea 07 f1 f1 d1 c1 cb - 21 1c 18 d0 3a 12 c0 32 26 c5 21 05 c5 36 00 dd - f9 dd e1 c9 25 34 64 25 34 64 00 25 34 64 00 25 - 30 32 78 00 25 33 64 00 21 26 c6 36 02 af f5 33 - af f5 33 cd a0 18 f1 21 2a c6 36 3c 21 00 78 36 - 00 11 0e 0e d5 3e dd f5 33 21 63 24 e5 cd f5 04 - f1 f1 33 11 13 0f d5 11 13 dd d5 cd ea 07 f1 f1 - 11 03 10 d5 3e dd f5 33 21 6e 24 e5 cd f5 04 f1 - f1 33 c9 50 72 65 73 73 20 68 65 72 65 00 2d 2d - 2d 03 03 03 02 02 02 01 01 01 a6 a6 a6 7f 7f 7f - a6 a6 a6 01 01 01 02 02 02 03 03 03 2d 2d 2d 00 - dd e5 dd 21 00 00 dd 39 3b 21 06 c0 cb 46 ca 4c - 25 21 07 c0 cb 46 c2 4c 25 3a 00 70 b7 ca 4c 25 - dd 36 ff 00 0e 00 79 d6 08 30 26 21 00 70 5e 41 - 21 01 00 04 18 01 29 10 fd 06 00 7d a3 5f 7c a0 - b3 28 08 dd 7e ff 32 28 c6 18 06 0c dd 71 ff 18 - d5 21 26 c6 36 01 af f5 33 af f5 33 cd a0 18 f1 - 11 05 0e d5 3e f8 f5 33 21 64 25 e5 cd f5 04 f1 - f1 33 11 06 10 d5 3e ff f5 33 21 82 25 e5 cd f5 - 04 f1 f1 33 21 28 c6 4e 06 00 69 60 29 09 29 29 - 11 78 c5 19 11 1a 10 d5 3e 07 f5 33 e5 cd f5 04 - f1 f1 33 11 07 12 d5 3e 38 f5 33 21 97 25 e5 cd - f5 04 f1 f1 33 21 2a c6 36 0a 18 14 21 08 c0 cb - 46 28 0d 21 09 c0 cb 46 20 06 cd 6f 03 cd d2 1a - 33 dd e1 c9 48 69 74 20 74 68 65 20 62 75 74 74 - 6f 6e 20 61 74 20 65 61 63 68 20 70 72 6f 6d 70 - 74 00 53 65 6c 65 63 74 65 64 20 62 75 74 74 6f - 6e 20 69 73 3a 20 00 50 72 65 73 73 20 61 67 61 - 69 6e 20 74 6f 20 73 74 61 72 74 20 74 65 73 74 - 00 21 06 c0 cb 46 c8 21 07 c0 cb 46 c0 21 00 70 - 5e 21 28 c6 46 0e 01 04 18 02 cb 21 10 fc 7b a1 - 4f fd 21 2a c6 fd 7e 00 b7 28 0b 3a 00 70 b7 20 - 14 fd 35 00 18 0f 79 b7 20 0b 3a 29 c6 b7 28 05 - c5 cd 18 24 c1 21 29 c6 71 c9 dd e5 dd 21 00 00 - dd 39 3b 21 00 70 4e 21 28 c6 46 21 01 00 04 18 - 01 29 10 fd 06 00 7d a1 4f 7c a0 b1 c6 ff 3e 00 - 17 4f dd 71 ff cb 41 28 2f 3a 2d c6 b7 20 29 01 - f4 c1 fd 21 2c c6 fd 6e 00 26 00 29 09 eb 3a 01 - 78 47 0e 00 3a 00 78 6f 26 00 79 b5 4f 78 b4 47 - 79 12 13 78 12 fd 34 00 dd 7e ff 32 2d c6 21 08 - c0 cb 46 ca 53 27 21 09 c0 cb 46 c2 53 27 21 2a - c6 35 3e 10 f5 33 3a 30 c6 f5 33 af f5 33 cd 89 - 08 f1 33 3a 2a c6 d6 1e 20 05 21 30 c6 36 02 3a - 30 c6 b7 28 26 21 2a c6 4e 06 00 21 02 00 e5 c5 - cd 1d 2f f1 f1 7c b5 20 12 fd 21 30 c6 fd 34 00 - 3e 23 fd 96 00 30 04 fd 36 00 00 3a 30 c6 b7 28 - 10 3e 10 f5 33 3a 30 c6 57 1e ff d5 cd 89 08 f1 - 33 fd 21 31 c6 fd 7e 00 b7 28 24 fd 35 00 fd 7e - 00 b7 20 1b 3a 2b c6 d6 05 20 14 21 26 c6 36 03 - 21 2e c6 36 01 11 01 01 d5 cd a0 18 f1 18 54 3a - 2a c6 b7 20 4e 01 f2 c3 fd 21 2b c6 fd 6e 00 26 - 00 29 09 eb 3a 01 78 47 0e 00 3a 00 78 6f 26 00 - 79 b5 4f 78 b4 47 79 12 13 78 12 fd 46 00 04 c5 - 33 11 12 06 d5 3e ff f5 33 21 57 27 e5 cd d2 05 - 21 06 00 39 f9 21 2a c6 36 5a 21 31 c6 36 21 21 - 2b c6 34 33 dd e1 c9 25 32 64 00 21 03 00 39 cb - 7e 28 0c 21 02 00 39 af 96 77 3e 00 23 9e 77 c1 - e1 e5 c5 c9 dd e5 dd 21 00 00 dd 39 21 ea ff 39 - f9 21 2e c6 cb 46 ca a8 29 11 02 06 d5 3e ff f5 - 33 21 d2 29 e5 cd f5 04 f1 f1 33 11 0b 06 d5 3e - ff f5 33 21 da 29 e5 cd f5 04 f1 f1 33 dd 36 fd - 07 dd 36 fa 00 dd 36 f0 00 dd 36 f1 00 dd 36 fb - 00 dd 36 fc 00 dd 7e fa b7 c2 a3 29 dd 7e fb dd - 77 fe dd 36 ff 00 dd 7e fe dd 77 f2 dd 7e ff dd - 77 f3 dd cb f2 26 dd cb f3 16 dd 7e fb d6 05 30 - 11 3e f2 dd 86 f2 6f 3e c3 dd 8e f3 67 4e 23 46 - 18 03 01 ff ff dd 6e fc 26 00 29 dd 75 f4 dd 74 - f5 21 2c c6 dd 7e fc 96 30 1f 3e f4 dd 86 f4 6f - 3e c1 dd 8e f5 67 5e 23 56 dd 73 f6 dd 72 f7 dd - 36 f8 00 dd 36 f9 00 18 10 dd 36 f6 ff dd 36 f7 - ff dd 36 f8 00 dd 36 f9 00 dd 7e f6 dd 77 ee dd - 7e f7 dd 77 ef dd 7e fd 3c dd 77 f6 79 dd 96 ee - 78 dd 9e ef 30 3a dd 7e f2 c6 f2 6f dd 7e f3 ce - c3 67 5e 23 56 c5 d5 dd 56 fd 1e 02 d5 3e ff f5 - 33 21 e2 29 e5 cd 54 06 21 07 00 39 f9 c1 dd 7e - f6 dd 77 fd dd 34 fb dd 71 f0 dd 70 f1 c3 c5 27 - dd 7e ee 91 dd 7e ef 98 d2 9c 29 dd 7e f4 c6 f4 - 6f dd 7e f5 ce c1 67 4e 23 46 c5 dd 56 fd 1e 0b - d5 3e ff f5 33 21 e2 29 e5 cd 54 06 21 07 00 39 - f9 dd 4e fe dd 46 ff 03 3e 05 b9 3e 00 98 e2 e3 - 28 ee 80 fa f7 28 dd 7e f2 c6 f2 6f dd 7e f3 ce - c3 67 4e 23 46 18 03 01 ff ff dd 7e ee dd 96 f0 - 5f dd 7e ef dd 9e f1 57 c5 d5 cd 5b 27 f1 c1 dd - 75 ec dd 74 ed 79 dd 96 ee 4f 78 dd 9e ef 47 c5 - cd 5b 27 f1 33 33 e5 dd 7e ea d6 f4 dd 7e eb de - 01 30 1b e1 e5 e5 dd 56 fd 1e 14 d5 3e f8 f5 33 - 21 e8 29 e5 cd d9 06 21 07 00 39 f9 18 42 3e f4 - dd be ec 3e 01 dd 9e ed 38 1d c1 e1 e5 c5 e5 dd - 56 fd 1e 14 d5 3e 3f f5 33 21 f5 29 e5 cd d9 06 - 21 07 00 39 f9 18 19 e1 e5 e5 dd 56 fd 1e 14 d5 - 3e 07 f5 33 21 01 2a e5 cd d9 06 21 07 00 39 f9 - dd 7e f6 dd 77 fd dd 34 fc c3 c5 27 dd 36 fa 01 - c3 c5 27 21 2e c6 36 00 21 08 c0 cb 46 28 1e 21 - 09 c0 cb 46 20 17 cd 6f 03 cd d2 1a 21 93 c1 cb - 46 28 0a 21 10 c5 cb 46 20 03 cd 62 19 dd f9 dd - e1 c9 50 72 6f 6d 70 74 73 00 50 72 65 73 73 65 - 73 00 25 36 64 6d 73 00 25 33 64 6d 73 20 62 65 - 66 6f 72 65 00 25 33 64 6d 73 20 61 66 74 65 72 - 00 3f 3f 3f 3f 00 fd 21 26 c6 fd 7e 00 b7 ca 90 - 24 fd 7e 00 3d ca b1 25 fd 7e 00 d6 02 ca fa 25 - fd 7e 00 d6 03 ca 74 27 c9 c3 90 24 c3 b1 25 c3 - fa 25 c3 74 27 21 fc c3 36 1f 21 3f c6 36 00 af - f5 33 cd 9f 04 33 3e 07 f5 33 cd 3c 0c 33 af 57 - 1e 12 d5 3e 07 f5 33 21 6c 2a e5 cd f5 04 f1 f1 - 33 21 33 c6 36 05 21 34 c6 36 01 c9 53 4e 45 4b - 00 21 fc c3 36 29 21 00 00 22 3d c6 2e 14 22 35 - c6 2e 0f 22 37 c6 21 39 c6 36 00 21 3a c6 36 01 - 21 3b c6 36 00 21 3c c6 36 01 af f5 33 cd 9f 04 - 33 3e 07 f5 33 cd 3c 0c 33 af 57 1e 12 d5 3e 07 - f5 33 21 de 2a e5 cd f5 04 f1 f1 33 21 37 c6 46 - 21 35 c6 4e c5 11 53 ff d5 cd ea 07 f1 f1 21 33 - c6 36 0e 21 32 c6 36 c8 21 34 c6 36 0e c9 53 4e - 45 4b 00 dd e5 dd 21 00 00 dd 39 f5 f5 3b 21 06 - c0 cb 46 28 71 21 07 c0 cb 46 20 6a 3a 3a c6 3d - 28 11 3a 00 70 cb 5f 28 0a 21 3c c6 36 ff 21 3b - c6 36 00 3a 3a c6 3c 28 11 3a 00 70 cb 57 28 0a - 21 3c c6 36 01 21 3b c6 36 00 3a 39 c6 3d 28 11 - 3a 00 70 cb 4f 28 0a 21 3b c6 36 ff 21 3c c6 36 - 00 3a 39 c6 3c 28 10 3a 00 70 0f 30 0a 21 3b c6 - 36 01 21 3c c6 36 00 3a 01 70 cb 57 28 08 21 fc - c3 36 00 c3 85 2c 21 08 c0 cb 46 ca 85 2c 21 09 - c0 cb 46 c2 85 2c fd 21 34 c6 fd 35 00 fd 7e 00 - b7 c2 3b 2c 21 37 c6 46 21 35 c6 4e c5 11 7f 66 - d5 cd ea 07 f1 f1 3a 3b c6 32 39 c6 3a 3c c6 32 - 3a c6 3a 39 c6 4f 17 9f 47 21 35 c6 7e 81 77 23 - 7e 88 77 3a 3a c6 4f 17 9f 47 21 37 c6 7e 81 77 - 23 7e 88 77 21 41 02 4e 06 00 c5 2a 37 c6 e5 cd - 5e 2e f1 f1 4d 44 2a 35 c6 09 01 00 80 09 7e b7 - 28 0b 21 fd c3 36 1e cd d0 13 c3 85 2c fd 21 3d - c6 fd 34 00 20 03 fd 34 01 21 37 c6 46 21 35 c6 - 4e c5 11 53 ff d5 cd ea 07 f1 f1 3a 33 c6 32 34 - c6 21 00 00 39 eb 4b 42 d5 2a 3d c6 e5 21 8a 2c - e5 c5 cd cd 2e 21 06 00 39 f9 d1 af 47 0e 23 c5 - 3e ff f5 33 d5 cd f5 04 f1 f1 33 fd 21 32 c6 fd - 35 00 fd 7e 00 b7 20 3d fd 36 00 c8 3e 03 fd 21 - 33 c6 fd 96 00 30 03 fd 35 00 21 33 c6 4e 06 00 - 21 02 00 39 5d 54 e5 c5 01 8a 2c c5 d5 cd cd 2e - 21 06 00 39 f9 e1 11 23 1d d5 3e ff f5 33 e5 cd - f5 04 f1 f1 33 dd f9 dd e1 c9 25 34 64 00 21 06 - c0 cb 46 28 1c 21 07 c0 cb 46 20 15 3a 01 70 cb - 5f c2 71 2a 3a 01 70 cb 57 28 06 21 fc c3 36 00 - c9 21 08 c0 cb 46 c8 21 09 c0 cb 46 c0 fd 21 34 - c6 fd 35 00 fd 7e 00 b7 c0 fd 21 3f c6 fd 7e 00 - d6 01 3e 00 17 fd 77 00 fd 7e 00 b7 20 05 01 00 - 00 18 03 01 ff 00 41 11 0e 0f d5 c5 33 21 fe 2c - e5 cd f5 04 f1 f1 33 3a 33 c6 32 34 c6 c9 50 52 - 45 53 53 20 53 54 41 52 54 00 21 42 02 5e 21 41 - 02 66 2e 00 55 06 08 29 30 01 19 10 fa 22 00 c0 - 3a 00 60 cb 07 e6 01 32 02 c0 3a 00 60 e6 40 f6 - 00 c6 ff 3e 00 17 32 04 c0 3a 00 60 e6 20 f6 00 - c6 ff 3e 00 17 32 06 c0 3a 00 60 e6 10 f6 00 c6 - ff 3e 00 17 32 08 c0 fd 21 fc c3 fd 7e 00 3d 28 - 6b fd 7e 00 d6 02 28 69 fd 7e 00 d6 03 28 67 fd - 7e 00 d6 04 28 65 fd 7e 00 d6 05 28 63 fd 7e 00 - d6 06 28 61 fd 7e 00 d6 07 28 5f fd 7e 00 d6 08 - 28 5d fd 7e 00 d6 09 28 5b fd 7e 00 d6 0a 28 59 - fd 7e 00 d6 14 28 57 fd 7e 00 d6 16 28 55 fd 7e - 00 d6 1e 28 53 fd 7e 00 d6 1f 28 51 fd 7e 00 d6 - 28 28 4f fd 7e 00 d6 29 28 4d 18 50 cd 41 19 18 - 4e cd f9 1a 18 49 cd 57 19 18 44 cd 69 1e 18 3f - cd 4c 19 18 3a cd 2b 1c 18 35 cd 62 19 18 30 cd - 06 2a 18 2b cd 77 11 18 26 cd 87 11 18 21 cd f0 - 13 18 1c cd 45 14 18 17 cd 35 2a 18 12 cd 8e 2c - 18 0d cd 71 2a 18 08 cd e3 2a 18 03 cd 41 19 3a - 02 c0 32 03 c0 3a 04 c0 32 05 c0 3a 06 c0 32 07 - c0 3a 08 c0 32 09 c0 c3 20 2d 44 69 67 69 74 61 - 6c 00 41 6e 61 6c 6f 67 00 41 64 76 61 6e 63 65 - 64 00 42 75 74 74 6f 6e 20 74 65 73 74 00 f1 c1 - d1 d5 c5 f5 af 6f b0 06 10 20 04 06 08 79 29 cb - 11 17 30 01 19 10 f7 c9 dd e5 dd 21 00 00 dd 39 - dd 6e 05 dd 66 06 e5 4e 23 46 e1 59 50 13 73 23 - 72 dd 7e 04 02 dd e1 c9 21 02 00 39 fd 21 06 00 - fd 39 fd 4e 00 fd 46 01 c5 fd 21 06 00 fd 39 fd - 4e 00 fd 46 01 c5 e5 21 78 2e e5 cd 8c 30 f1 f1 - f1 f1 4d 44 d1 e1 e5 d5 36 00 69 60 c9 dd e5 dd - 21 00 00 dd 39 21 08 00 39 eb 21 04 00 39 d5 dd - 4e 06 dd 46 07 c5 e5 21 78 2e e5 cd 8c 30 f1 f1 - f1 f1 4d 44 dd 5e 04 dd 56 05 af 12 69 60 dd e1 - c9 c1 e1 e5 c5 af 47 4f ed b1 21 ff ff ed 42 c9 - 21 03 00 39 5e 2b 6e cd 39 2f c3 67 2f f1 e1 d1 - d5 e5 f5 cd 41 2f c3 67 2f f1 e1 d1 d5 e5 f5 c3 - 41 2f 21 03 00 39 5e 2b 6e 7d 07 9f 67 7b 07 9f - 57 7c aa 17 7c f5 17 30 06 97 95 6f 9f 94 67 cb - 7a 28 06 97 93 5f 9f 92 57 cd 03 3b f1 d0 47 97 - 95 6f 9f 94 67 78 c9 17 eb d0 97 95 6f 9f 94 67 - c9 21 02 00 39 7e c6 30 47 3e 39 90 30 10 78 c6 - 07 47 21 03 00 39 cb 46 28 04 78 c6 20 47 21 06 - 00 39 7e 23 66 6f e5 c5 33 21 07 00 39 7e 23 66 - 6f cd 32 3b f1 33 c9 dd e5 dd 21 00 00 dd 39 dd - 7e 04 07 07 07 07 e6 0f 47 dd 6e 08 dd 66 09 e5 - dd 6e 06 dd 66 07 e5 dd 7e 05 f5 33 c5 33 cd 71 - 2f 21 06 00 39 f9 dd 7e 04 e6 0f 47 dd 6e 08 dd - 66 09 e5 dd 6e 06 dd 66 07 e5 dd 7e 05 f5 33 c5 - 33 cd 71 2f 21 06 00 39 f9 dd e1 c9 dd e5 dd 21 - 00 00 dd 39 21 f9 ff 39 f9 dd 5e 04 dd 56 05 d5 - 21 04 00 39 eb 01 04 00 ed b0 d1 21 04 00 19 4d - 44 dd 36 ff 20 0a 87 dd 77 fa dd 7e fe cb 07 e6 - 01 dd 77 f9 dd 7e fa dd b6 f9 dd 77 f9 02 dd cb - fb 26 dd cb fc 16 dd cb fd 16 dd cb fe 16 dd 7e - f9 dd 96 06 38 1f 0a dd 96 06 02 dd 7e fb f6 01 - dd 77 fb dd 7e fc dd 77 fc dd 7e fd dd 77 fd dd - 7e fe dd 77 fe dd 35 ff dd 7e ff b7 20 a7 21 02 - 00 39 01 04 00 ed b0 dd f9 dd e1 c9 dd e5 dd 21 - 00 00 dd 39 21 c5 ff 39 f9 dd 36 e6 00 dd 36 e7 - 00 21 06 00 39 dd 75 e8 dd 74 e9 21 05 00 39 dd - 75 e4 dd 74 e5 21 06 00 39 dd 75 d0 dd 74 d1 dd - 7e d0 c6 04 dd 77 d4 dd 7e d1 ce 00 dd 77 d5 dd - 7e d4 dd 77 d2 dd 7e d5 dd 77 d3 dd 7e d4 dd 77 - d7 dd 7e d5 dd 77 d8 dd 6e 08 dd 66 09 5e 23 dd - 75 08 dd 74 09 dd 73 d6 7b b7 ca db 3a dd 7e d6 - d6 25 c2 b8 3a dd 36 fc 00 dd 36 f9 00 dd 36 f8 - 00 dd 36 f7 00 dd 36 ff 00 dd 36 fe 00 dd 36 fd - 00 dd 36 fb 00 dd 36 f3 00 dd 36 db 00 dd 36 f2 - ff dd 7e 08 dd 77 d9 dd 7e 09 dd 77 da dd 6e d9 - dd 66 da 7e dd 77 dd dd 34 d9 20 03 dd 34 da dd - 7e d9 dd 77 08 dd 7e da dd 77 09 dd 7e dd d6 25 - 20 23 dd 6e 06 dd 66 07 e5 dd 7e dd f5 33 dd 6e - 04 dd 66 05 cd 32 3b f1 33 dd 34 e6 c2 e7 30 dd - 34 e7 c3 e7 30 dd 7e dd d6 30 38 40 3e 39 dd 96 - dd 38 39 dd 7e f2 3c 20 1f dd 7e db dd 77 dc 6f - 4d 29 29 09 29 dd 7e dd 85 c6 d0 dd 77 db b7 20 - 8c dd 36 f9 01 c3 3d 31 dd 6e f2 4d 29 29 09 29 - dd 7e dd 85 c6 d0 dd 77 f2 c3 3d 31 dd 7e dd d6 - 2e 20 0e dd 7e f2 3c c2 3d 31 dd 36 f2 00 c3 3d - 31 dd 7e dd d6 61 38 15 3e 7a dd 96 dd 38 0e dd - 7e dd e6 df dd 77 dd dd 36 fa 01 18 04 dd 36 fa - 00 dd 7e dd d6 20 ca a0 32 dd 7e dd d6 2b ca 99 - 32 dd 7e dd d6 2d 28 7a dd 7e dd d6 42 ca a7 32 - dd 7e dd d6 43 ca b5 32 dd 7e dd d6 44 ca bd 34 - dd 7e dd d6 46 ca d9 34 dd 7e dd d6 48 ca 3d 31 - dd 7e dd d6 49 ca bd 34 dd 7e dd d6 4a ca 3d 31 - dd 7e dd d6 4c 28 57 dd 7e dd d6 4f ca c7 34 dd - 7e dd d6 50 ca 14 34 dd 7e dd d6 53 ca fd 32 dd - 7e dd d6 54 ca 3d 31 dd 7e dd d6 55 ca cd 34 dd - 7e dd d6 58 ca d3 34 dd 7e dd d6 5a ca 3d 31 c3 - df 34 dd 36 fc 01 c3 3d 31 dd 36 f8 01 c3 3d 31 - dd 36 f7 01 c3 3d 31 dd 36 fe 01 c3 3d 31 dd 36 - fd 01 c3 3d 31 dd cb fe 46 28 11 dd 6e 0a dd 66 - 0b 23 dd 75 0a dd 74 0b 2b 46 18 11 dd 6e 0a dd - 66 0b 23 23 dd 75 0a dd 74 0b 2b 2b 46 dd 6e 06 - dd 66 07 e5 c5 33 dd 6e 04 dd 66 05 cd 32 3b f1 - 33 dd 34 e6 c2 09 35 dd 34 e7 c3 09 35 21 06 00 - 39 dd 75 d9 dd 74 da dd 6e 0a dd 66 0b 23 23 dd - 75 0a dd 74 0b 2b 2b 4e 23 46 dd 6e d9 dd 66 da - 71 23 70 c5 cd 01 2f f1 4d dd 7e f2 3c 20 03 dd - 71 f2 dd cb fc 46 20 3c 79 dd 96 db 30 36 dd 7e - db 91 47 dd 5e e6 dd 56 e7 78 05 b7 28 1d c5 d5 + 33 79 f5 33 dd 66 05 dd 6e 04 e5 cd d7 38 f1 f1 + 33 c1 78 c6 ff dd 77 fd 0d dd 5e 05 7b 3c dd 77 + fe dd 7e 04 dd 77 ff 57 14 d5 3e 23 f5 33 3e 1b + f5 33 dd 46 fd c5 dd 7e fe f5 33 d5 33 cd 51 3a + 21 06 00 39 f9 d1 dd 6e 06 26 00 4d 44 cb 7c 28 + 03 23 4d 44 cb 28 cb 19 79 dd 86 ff dd 77 ff dd + 4e 07 06 00 69 60 cb 78 28 03 69 60 23 cb 2c cb + 1d 7d 83 5f dd 7e 06 3d c5 d5 f5 33 7b f5 33 d5 + 33 11 83 23 d5 cd c7 36 f1 f1 33 d1 c1 dd 56 fe + dd 6e 05 26 00 09 dd 72 fd af dd 77 fe dd 7e fd + 95 dd 7e fe 9c e2 9a 25 ee 80 f2 b5 25 c5 d5 d5 + 33 dd 56 ff 1e 23 d5 3e 82 f5 33 cd 93 36 f1 f1 + d1 c1 14 18 cb 7b f5 33 dd 56 ff 1e 23 d5 3e 9b + f5 33 cd 93 36 dd f9 dd e1 c9 dd e5 dd 21 00 00 + dd 39 21 f9 ff 39 f9 0e 00 af dd 77 fd af dd 77 + fe c5 dd 6e 04 dd 66 05 e5 cd b8 5d f1 c1 dd 75 + f9 dd 36 ff 01 3a 00 80 e6 10 47 af b8 17 32 59 + c5 fd 21 59 c5 fd cb 00 46 ca cb 26 fd 21 5a c5 + fd cb 00 46 c2 cb 26 dd 5e ff 1d dd 66 08 2e 00 + 55 06 08 29 30 01 19 10 fa dd 7e 06 85 dd 77 fa + 0c dd 5e ff 16 00 1b dd 7e 04 83 dd 77 fb dd 7e + 05 8a dd 77 fc dd 7e 09 91 20 2c dd 6e fb dd 66 + fc 46 dd 7e 07 f5 33 dd 56 fa 1e ff d5 c5 33 cd + 93 36 f1 f1 dd 34 ff dd 7e f9 dd 96 ff 38 69 0e + 00 af dd 77 fe 18 54 dd 34 fe dd 7e 0a dd 96 fe + 20 49 dd 34 fd dd 7e fd d6 02 20 04 af dd 77 fd + dd 7e fd 3d 20 16 c5 dd 66 07 dd 6e fa e5 af f5 + 33 af f5 33 cd 93 36 f1 f1 c1 18 1b dd 6e fb dd + 66 fc 46 c5 dd 7e 07 f5 33 dd 56 fa 1e ff d5 c5 + 33 cd 93 36 f1 f1 c1 af dd 77 fe 3a 59 c5 fd 21 + 5a c5 fd 77 00 c3 f5 25 dd f9 dd e1 c9 21 67 32 + 5e 21 66 32 66 2e 00 55 06 08 29 30 01 19 10 fa + 22 51 c5 af f5 33 cd 7b 33 33 af f5 33 cd 0f 33 + 33 cd f8 30 cd e3 2f cd 34 31 3e 01 f5 33 af 57 + 1e ff d5 3e 3e f5 33 cd 93 36 f1 f1 11 08 01 d5 + 11 01 02 d5 3e 02 f5 33 2a 86 c7 e5 cd ca 25 21 + 07 00 39 f9 3e 01 f5 33 af 57 1e ff d5 3e 20 f5 + 33 cd 93 36 f1 26 03 e3 33 af 57 1e ff d5 3e 3e + f5 33 cd 93 36 f1 f1 11 02 01 d5 11 03 01 d5 3e + 02 f5 33 21 d8 27 e5 cd ca 25 21 07 00 39 f9 11 + 02 01 d5 11 03 01 d5 3e 07 f5 33 21 07 00 39 4e + 23 46 c5 cd ca 25 21 07 00 39 f9 3e 03 f5 33 af + 57 1e ff d5 3e 20 f5 33 cd 93 36 f1 26 05 e3 33 + af 57 1e ff d5 3e 3e f5 33 cd 93 36 f1 f1 11 08 + 01 d5 11 05 01 d5 3e 02 f5 33 21 de 27 e5 cd ca + 25 21 07 00 39 f9 11 28 03 d5 11 01 01 d5 af f5 + 33 cd 42 33 f1 f1 33 c9 4c 4f 41 44 20 00 2e 2e + 2e 00 41 5a 4e 41 42 4c 45 00 21 83 c7 36 0a 21 + 88 c7 36 00 21 8a c7 36 00 c9 dd e5 dd 21 00 00 + dd 39 f5 f5 3b cd 41 2b 21 57 c5 cb 46 ca db 28 + 21 58 c5 cb 46 c2 db 28 cd 8e 1f 21 7b c7 cb 46 + 28 1e 21 7c c7 cb 46 20 17 fd 21 87 c2 fd 35 00 + 3e 80 fd 96 00 30 04 fd 36 00 04 21 89 c7 36 01 + 21 7d c7 cb 46 28 1e 21 7e c7 cb 46 20 17 fd 21 + 87 c2 fd 34 00 fd 7e 00 d6 05 20 04 fd 36 00 00 + 21 89 c7 36 01 21 7f c2 cb 46 20 07 21 7f c7 cb + 46 20 1c 21 81 c2 cb 46 20 07 21 81 c7 cb 46 20 + 0e 21 82 c2 cb 46 20 53 21 82 c7 cb 46 28 4c 21 + 31 8a 36 00 3e 04 fd 21 87 c2 fd 96 00 38 3c fd + 4e 00 06 00 21 ab 28 09 09 09 e9 c3 ba 28 c3 c1 + 28 c3 c8 28 c3 cf 28 c3 d6 28 21 83 c7 36 01 18 + 1a 21 83 c7 36 05 18 13 21 83 c7 36 03 18 0c 21 + 83 c7 36 07 18 05 21 83 c7 36 2a 21 59 c5 cb 46 + ca 50 2a 21 5a c5 cb 46 c2 50 2a fd 21 88 c7 fd + 7e 00 d6 11 d2 8b 29 fd 5e 00 16 00 4b 42 cb 7a + 28 03 4b 42 03 cb 28 cb 19 79 c6 0f 57 3e 0f 91 + 47 c5 3e 24 f5 33 3e 36 f5 33 3e ff f5 33 d5 33 + 3e 1c f5 33 c5 33 3e 0c f5 33 cd 94 39 21 07 00 + 39 f9 c1 3e 01 91 30 3c 0d 79 c6 0f 57 3e 0f 91 + 47 c5 d5 af f5 33 af f5 33 d5 33 3e 1b f5 33 c5 + 33 3e 0d f5 33 cd 51 3a 21 06 00 39 f9 d1 c1 af + f5 33 d5 33 3e 1b f5 33 c5 33 3e 0d f5 33 cd 89 + 3a f1 f1 33 fd 21 88 c7 fd 34 00 fd 7e 00 d6 11 + c2 50 2a 21 89 c7 36 01 c3 50 2a 3a 89 c7 b7 ca + 50 2a 0e 08 1e 00 7b d6 05 d2 46 2a dd 71 fb 6b + 26 00 dd 7e fb c6 02 dd 77 fc dd 7e fb 3c dd 77 + fd 29 dd 75 fe dd 74 ff 3a 87 c2 93 20 40 d5 11 + 16 14 d5 3e 5f f5 33 dd 56 fc 1e 1b d5 51 1e 0d + d5 cd 94 39 21 07 00 39 f9 d1 3e 8b dd 86 fe 6f + 3e c7 dd 8e ff 67 4e 23 46 d5 dd 56 fd 1e 0e d5 + 3e ff f5 33 c5 cd 9e 33 f1 f1 33 d1 18 3e d5 11 + b6 64 d5 3e bf f5 33 dd 56 fc 1e 1b d5 51 1e 0d + d5 cd 94 39 21 07 00 39 f9 d1 3e 8b dd 86 fe 6f + 3e c7 dd 8e ff 67 4e 23 46 d5 dd 56 fd 1e 0e d5 + 3e b6 f5 33 c5 cd 9e 33 f1 f1 33 d1 dd 4e fb 0c + 0c 0c 1c c3 96 29 21 89 c7 36 00 21 8a c7 36 01 + dd f9 dd e1 c9 44 69 67 69 74 61 6c 00 41 6e 61 + 6c 6f 67 00 41 64 76 61 6e 63 65 64 00 42 75 74 + 74 6f 6e 20 74 65 73 74 00 43 72 65 64 69 74 73 + 00 dd e5 dd 21 00 00 dd 39 01 97 c7 dd 6e 04 26 + 00 29 29 09 eb 6b 62 4e 23 46 23 23 7e 2b 7e 32 + 11 8b 6b 62 46 23 4e 21 12 8b 71 01 13 8b 1a 02 + 21 10 8b dd 7e 05 b7 28 05 01 02 00 18 03 01 01 + 00 71 dd 7e 04 32 96 c7 dd e1 c9 3a 10 8b b7 28 + 0d 3a 96 c7 fd 21 02 00 fd 39 fd 96 00 c8 fd 21 + 03 00 fd 39 fd 7e 00 f5 33 fd 2b fd 7e 00 f5 33 + cd 81 2a f1 c9 21 10 8b 36 03 c9 3a 1a c9 87 5f + 3a 18 c9 b7 20 07 3a 19 c9 b7 20 01 1c 21 17 c8 + 16 00 19 7e fd 21 1b c9 fd 77 00 fd 7e 00 b7 c8 + 01 91 c2 2a 1e c9 26 00 09 fd 7e 00 77 21 1e c9 + 34 c9 0d 58 5a 66 76 12 59 11 63 16 29 75 6b 74 + 72 dd e5 dd 21 00 00 dd 39 3b 3a 01 86 e6 04 4f + af b9 17 dd 77 ff 21 17 c9 4e 91 ca 11 2c 0e 00 + 79 d6 02 30 14 3e 88 81 5f 3e c2 ce 00 57 21 00 + 86 06 00 09 7e 12 0c 18 e7 3a 89 c2 0f 30 05 01 + 01 00 18 03 01 00 00 21 8b c2 71 3a 89 c2 cb 4f + 28 05 01 01 00 18 03 01 00 00 21 8a c2 71 3a 88 + c2 32 1a c9 21 1b c9 36 00 3a 8a c2 b7 28 32 01 + 11 c3 2a 1a c9 26 00 09 36 01 21 37 2b 4e 3a 1a + c9 91 20 07 21 18 c9 36 01 18 46 21 38 2b 4e 3a + 1a c9 91 20 07 21 19 c9 36 01 18 35 cd fb 2a 18 + 30 01 11 c3 2a 1a c9 26 00 09 36 00 21 37 2b 4e + 3a 1a c9 91 20 07 21 18 c9 36 00 18 14 21 38 2b + 4e 3a 1a c9 91 20 07 21 19 c9 36 00 18 03 cd fb + 2a dd 7e ff 32 17 c9 3a 03 87 e6 01 4f 21 1c c9 + 46 90 28 23 21 1d c9 36 01 3a 00 87 32 8f c2 3a + 05 87 32 90 c2 3a 01 87 32 8c c2 3a 02 87 32 8d + c2 3a 04 87 32 8e c2 21 1c c9 71 33 dd e1 c9 21 + 83 c7 36 1f 21 2c c9 36 00 af f5 33 cd 0f 33 33 + 3e 07 f5 33 cd ba 3a 33 af 57 1e 12 d5 3e 07 f5 + 33 21 86 2c e5 cd 9e 33 f1 f1 33 21 20 c9 36 05 + 21 21 c9 36 01 c9 53 4e 45 4b 00 21 83 c7 36 29 + 21 00 00 22 2a c9 2e 14 22 22 c9 2e 0f 22 24 c9 + 21 26 c9 36 00 21 27 c9 36 01 21 28 c9 36 00 21 + 29 c9 36 01 af f5 33 cd 0f 33 33 3e 07 f5 33 cd + ba 3a 33 af 57 1e 12 d5 3e 07 f5 33 21 fa 2c e5 + cd 9e 33 f1 f1 33 3a 24 c9 21 22 c9 46 f5 33 c5 + 33 11 53 ff d5 cd 93 36 f1 f1 21 20 c9 36 0e 21 + 1f c9 36 c8 21 21 c9 36 0e c9 53 4e 45 4b 00 dd + e5 dd 21 00 00 dd 39 f5 f5 3b 21 57 c5 cb 46 28 + 71 21 58 c5 cb 46 20 6a 3a 27 c9 3d 28 11 3a 00 + 81 cb 5f 28 0a 21 29 c9 36 ff 21 28 c9 36 00 3a + 27 c9 3c 28 11 3a 00 81 cb 57 28 0a 21 29 c9 36 + 01 21 28 c9 36 00 3a 26 c9 3d 28 11 3a 00 81 cb + 4f 28 0a 21 28 c9 36 ff 21 29 c9 36 00 3a 26 c9 + 3c 28 10 3a 00 81 0f 30 0a 21 28 c9 36 01 21 29 + c9 36 00 3a 01 81 cb 57 28 08 21 83 c7 36 00 c3 + a2 2e 21 59 c5 cb 46 ca a2 2e 21 5a c5 cb 46 c2 + a2 2e fd 21 21 c9 fd 35 00 fd 7e 00 b7 c2 58 2e + 3a 24 c9 21 22 c9 46 f5 33 c5 33 11 7f 66 d5 cd + 93 36 f1 f1 3a 28 c9 32 26 c9 3a 29 c9 32 27 c9 + 3a 26 c9 4f 17 9f 47 21 22 c9 7e 81 77 23 7e 88 + 77 3a 27 c9 4f 17 9f 47 21 24 c9 7e 81 77 23 7e + 88 77 21 66 32 4e 06 00 c5 2a 24 c9 e5 cd 18 5d + f1 f1 4d 44 2a 22 c9 09 4d 44 21 00 98 09 7e b7 + 28 0b 21 85 c7 36 1e cd 6e 06 c3 a2 2e 2a 2a c9 + 23 22 2a c9 3a 24 c9 21 22 c9 46 f5 33 c5 33 11 + 53 ff d5 cd 93 36 f1 f1 3a 20 c9 32 21 c9 21 00 + 00 39 eb 4b 42 d5 2a 2a c9 e5 21 a7 2e e5 c5 cd + 84 5d 21 06 00 39 f9 d1 af 47 0e 23 c5 3e ff f5 + 33 d5 cd 9e 33 f1 f1 33 fd 21 1f c9 fd 35 00 fd + 7e 00 b7 20 3d fd 36 00 c8 3e 03 fd 21 20 c9 fd + 96 00 30 03 fd 35 00 21 20 c9 4e 06 00 21 02 00 + 39 5d 54 e5 c5 01 a7 2e c5 d5 cd 84 5d 21 06 00 + 39 f9 e1 11 23 1d d5 3e ff f5 33 e5 cd 9e 33 f1 + f1 33 dd f9 dd e1 c9 25 34 64 00 fd 21 57 c5 fd + cb 00 46 28 1f fd 21 58 c5 fd cb 00 46 20 15 3a + 01 81 cb 5f c2 8b 2c 3a 01 81 cb 57 28 06 21 83 + c7 36 00 c9 21 59 c5 cb 46 c8 21 5a c5 cb 46 c0 + fd 21 21 c9 fd 35 00 fd 7e 00 b7 c0 fd 21 2c c9 + fd 7e 00 d6 01 3e 00 17 32 2c c9 fd 7e 00 b7 20 + 05 01 00 00 18 03 01 ff 00 11 0e 0f d5 79 f5 33 + 21 21 2f e5 cd 9e 33 f1 f1 33 3a 20 c9 32 21 c9 + c9 50 52 45 53 53 20 53 54 41 52 54 00 dd e5 dd + 21 00 00 dd 39 dd 6e 04 26 00 29 29 4d 44 21 2e + c9 09 eb 6b 62 7e 23 7e 32 01 8b 1a 32 00 8b eb + 5e 23 56 21 ae c9 09 7e 23 66 6f 19 eb 21 05 8b + 72 21 04 8b 73 21 08 8b 36 01 dd e1 c9 21 0c 8b + fd 21 02 00 fd 39 fd 7e 00 77 c9 dd e5 dd 21 00 + 00 dd 39 01 31 c4 dd 6e 04 26 00 09 dd 4e 06 71 + 01 11 c4 dd 6e 04 26 00 09 dd 7e 05 77 01 71 c4 + dd 6e 04 26 00 09 dd 4e 08 71 01 51 c4 dd 6e 04 + 26 00 09 dd 7e 07 77 dd e1 c9 01 31 c4 79 21 02 + 00 39 86 4f 30 01 04 fd 21 03 00 fd 39 fd 7e 01 + 02 01 11 c4 79 21 02 00 39 86 4f 30 01 04 fd 7e + 00 02 c9 dd e5 dd 21 00 00 dd 39 f5 0e 00 1e 00 + 21 2e ca 7b 96 d2 91 30 21 91 c4 16 00 19 cb 46 + ca 81 30 79 51 14 c6 00 4f 3e 00 ce b0 47 3e 31 + 83 6f 3e c5 ce 00 67 7e dd 77 ff 3e 71 83 6f 3e + c4 ce 00 67 7e dd b6 ff 02 7a 14 c6 00 4f 3e 00 + ce b0 47 3e 51 83 6f 3e c4 ce 00 67 7e 02 7a 14 + c6 00 4f 3e 00 ce b0 47 3e f1 83 6f 3e c4 ce 00 + 67 7e 87 87 dd 77 ff 3e 31 83 6f 3e c4 ce 00 67 + 6e dd 7e ff b5 02 7a 4a 0c c6 00 dd 77 fe 3e 00 + ce b0 dd 77 ff 21 11 c4 16 00 19 7e e1 e5 77 18 + 0c 21 00 b0 06 00 09 36 00 79 c6 04 4f 1c c3 f0 + 2f dd f9 dd e1 c9 dd e5 dd 21 00 00 dd 39 01 91 + c4 dd 6e 04 26 00 09 36 01 01 b1 c4 dd 6e 04 26 + 00 09 af dd be 07 17 77 01 d1 c4 dd 6e 04 26 00 + 09 dd 7e 05 77 01 11 c5 dd 6e 04 26 00 09 dd 7e + 06 77 01 31 c5 dd 6e 04 26 00 09 dd 7e 07 0f 0f + e6 c0 4f cb f9 dd 7e 05 87 87 87 87 b1 4f dd 7e + 06 87 87 b1 77 dd e1 c9 01 91 c4 1e 00 21 2e ca + 7b 96 d0 6b 26 00 09 36 00 1c 18 f1 21 02 00 39 + 4e 11 91 c4 21 03 00 39 7e 91 d8 69 26 00 19 36 + 00 0c 18 f0 21 00 8a 36 01 21 10 8a 36 01 21 20 + 8a 36 01 c9 21 00 8a 36 00 21 10 8a 36 00 21 20 + 8a 36 00 c9 dd e5 dd 21 00 00 dd 39 21 00 00 e5 + 21 00 00 e5 dd 6e 06 dd 66 07 e5 dd 6e 04 dd 66 + 05 e5 cd 9b 6e f1 f1 f1 f1 7d 0f e6 80 4f c5 dd + 6e 06 dd 66 07 e5 dd 6e 04 dd 66 05 e5 21 80 43 + e5 21 00 00 e5 cd d6 6a f1 f1 f1 f1 d5 e5 cd 98 + 6f f1 f1 c1 e5 cd 0c 5d f1 eb 7a b1 32 21 8a 21 + 22 8a 73 cb 23 cb 12 7a b1 32 11 8a 21 12 8a 73 + cb 23 cb 12 7a b1 32 01 8a 21 02 8a 73 dd e1 c9 + dd e5 dd 21 00 00 dd 39 21 00 00 e5 21 00 00 e5 + dd 6e 06 dd 66 07 e5 dd 6e 04 dd 66 05 e5 cd 9b + 6e f1 f1 f1 f1 7d 0f e6 80 4f c5 dd 6e 06 dd 66 + 07 e5 dd 6e 04 dd 66 05 e5 21 80 43 e5 21 00 00 + e5 cd d6 6a f1 f1 f1 f1 d5 e5 cd 98 6f f1 f1 c1 + e5 cd 0c 5d f1 eb 7a b1 32 23 8a 21 24 8a 73 cb + 23 cb 12 7a b1 32 13 8a 21 14 8a 73 cb 23 cb 12 + 7a b1 32 03 8a 21 04 8a 73 dd e1 c9 dd e5 dd 21 + 00 00 dd 39 cd 30 5c dd 4e 05 06 00 dd 5e 04 16 + 00 79 93 4f 78 9a 47 03 c5 e5 cd d4 5d f1 f1 dd + 4e 04 09 dd e1 c9 40 20 dd e5 dd 21 00 00 dd 39 + cd 30 5c dd 7e 06 dd 96 04 4f dd 7e 07 dd 9e 05 + 47 03 c5 e5 cd ec 5d f1 f1 4d 44 dd 6e 04 dd 66 + 05 09 dd e1 c9 dd e5 dd 21 00 00 dd 39 cd 30 5c + dd 7e 05 4f 17 9f 47 dd 7e 04 5f 17 9f 57 79 93 + 4f 78 9a 47 03 c5 e5 cd d4 5d f1 f1 7d dd 86 04 + 6f dd e1 c9 21 00 8c 3a 2f ca 77 21 01 8c 3a 30 + ca 77 c9 21 02 8c 36 01 3a 02 8c b7 20 fa c9 21 + 02 8c 36 02 3a 02 8c b7 20 fa c9 21 02 8c 36 03 + 3a 02 8c b7 20 fa c9 21 02 8c 36 04 3a 02 8c b7 + 20 fa c9 21 02 8c 36 05 3a 02 8c b7 20 fa c9 dd + e5 dd 21 00 00 dd 39 01 00 00 21 51 c5 79 96 78 + 23 9e 30 1b 21 00 98 09 dd 7e 04 77 21 00 a0 09 + dd 7e 04 77 21 00 a8 09 dd 7e 04 77 03 18 db dd + e1 c9 dd e5 dd 21 00 00 dd 39 dd 46 06 dd 7e 07 + dd 96 05 4f dd 7e 08 90 38 1e 79 3c c5 f5 33 c5 + 33 dd 7e 05 f5 33 af f5 33 dd 7e 04 f5 33 cd c7 + 36 f1 f1 33 c1 04 18 dc dd e1 c9 dd e5 dd 21 00 + 00 dd 39 01 00 00 21 51 c5 79 96 78 23 9e 30 0b + 21 00 a8 09 dd 7e 04 77 03 18 eb dd e1 c9 dd e5 + dd 21 00 00 dd 39 f5 21 66 32 5e dd 66 08 2e 00 + 55 06 08 29 30 01 19 10 fa dd 4e 07 06 00 09 eb + dd 6e 04 dd 66 05 e5 cd b8 5d f1 4d 06 00 78 91 + 30 20 21 00 98 19 e3 dd 7e 04 80 6f dd 7e 05 ce + 00 67 7e e1 e5 77 21 00 a0 19 dd 7e 06 77 13 04 + 18 dc dd f9 dd e1 c9 dd e5 dd 21 00 00 dd 39 21 + df ff 39 f9 21 66 32 5e dd 66 08 2e 00 55 06 08 + 29 30 01 19 10 fa dd 4e 07 06 00 09 eb dd 7e 09 + 4f 17 9f 47 21 00 00 39 dd 75 fd dd 74 fe d5 c5 + dd 4e 04 dd 46 05 c5 e5 cd 84 5d 21 06 00 39 f9 + d1 dd 4e fd dd 46 fe c5 cd b8 5d f1 dd 75 ff 0e + 00 79 dd 96 ff 30 1f dd 6e fd dd 66 fe 06 00 09 + 46 78 b7 28 11 21 00 98 19 70 21 00 a0 19 dd 7e + 06 77 13 0c 18 db dd f9 dd e1 c9 dd e5 dd 21 00 + 00 dd 39 21 df ff 39 f9 21 66 32 5e dd 66 08 2e + 00 55 06 08 29 30 01 19 10 fa dd 4e 07 06 00 09 + eb dd 4e 09 06 00 21 00 00 39 dd 75 fd dd 74 fe + d5 c5 dd 4e 04 dd 46 05 c5 e5 cd 84 5d 21 06 00 + 39 f9 d1 dd 4e fd dd 46 fe c5 cd b8 5d f1 dd 75 + ff 0e 00 79 dd 96 ff 30 1f dd 6e fd dd 66 fe 06 + 00 09 46 78 b7 28 11 21 00 98 19 70 21 00 a0 19 + dd 7e 06 77 13 0c 18 db dd f9 dd e1 c9 dd e5 dd + 21 00 00 dd 39 21 d5 ff 39 f9 21 66 32 5e dd 66 + 08 2e 00 55 06 08 29 30 01 19 10 fa dd 4e 07 06 + 00 09 eb 21 00 00 39 dd 75 fd dd 74 fe 4d 44 d5 + dd 6e 09 dd 66 0a e5 dd 6e 04 dd 66 05 e5 c5 cd + 84 5d 21 06 00 39 f9 d1 dd 4e fd dd 46 fe c5 cd + b8 5d f1 dd 75 ff 0e 00 79 dd 96 ff 30 1f dd 6e + fd dd 66 fe 06 00 09 46 78 b7 28 11 21 00 98 19 + 70 21 00 a0 19 dd 7e 06 77 13 0c 18 db dd f9 dd + e1 c9 dd e5 dd 21 00 00 dd 39 21 d5 ff 39 f9 21 + 66 32 5e dd 66 08 2e 00 55 06 08 29 30 01 19 10 + fa dd 4e 07 06 00 09 eb 21 00 00 39 dd 75 fd dd + 74 fe 4d 44 d5 dd 6e 09 dd 66 0a e5 dd 6e 04 dd + 66 05 e5 c5 cd 84 5d 21 06 00 39 f9 d1 dd 4e fd + dd 46 fe c5 cd b8 5d f1 dd 75 ff 0e 00 79 dd 96 + ff 30 1f dd 6e fd dd 66 fe 06 00 09 46 78 b7 28 + 11 21 00 98 19 70 21 00 a0 19 dd 7e 06 77 13 0c + 18 db dd f9 dd e1 c9 dd e5 dd 21 00 00 dd 39 21 + d5 ff 39 f9 21 66 32 5e dd 66 08 2e 00 55 06 08 + 29 30 01 19 10 fa dd 4e 07 06 00 09 eb 21 00 00 + 39 dd 75 fd dd 74 fe 4d 44 d5 dd 6e 0b dd 66 0c + e5 dd 6e 09 dd 66 0a e5 dd 6e 04 dd 66 05 e5 c5 + cd 84 5d 21 08 00 39 f9 d1 dd 4e fd dd 46 fe c5 + cd b8 5d f1 dd 75 ff 0e 00 79 dd 96 ff 30 1f dd + 6e fd dd 66 fe 06 00 09 46 78 b7 28 11 21 00 98 + 19 70 21 00 a0 19 dd 7e 06 77 13 0c 18 db dd f9 + dd e1 c9 dd e5 dd 21 00 00 dd 39 21 66 32 5e dd + 66 07 2e 00 55 06 08 29 30 01 19 10 fa dd 4e 06 + 06 00 09 eb 21 00 98 19 dd 7e 04 77 21 00 a0 19 + dd 7e 05 77 dd e1 c9 dd e5 dd 21 00 00 dd 39 21 + 66 32 5e dd 66 07 2e 00 55 06 08 29 30 01 19 10 + fa dd 4e 06 06 00 09 eb 0e 00 79 dd 96 08 30 14 + 21 00 98 19 dd 7e 04 77 21 00 a0 19 dd 7e 05 77 + 13 0c 18 e6 dd e1 c9 dd e5 dd 21 00 00 dd 39 21 + 66 32 5e dd 66 06 2e 00 55 06 08 29 30 01 19 10 + fa dd 4e 05 06 00 09 11 00 a0 19 dd 7e 04 77 dd + e1 c9 dd e5 dd 21 00 00 dd 39 21 66 32 5e dd 66 + 06 2e 00 55 06 08 29 30 01 19 10 fa dd 4e 05 06 + 00 09 11 00 a8 19 dd 7e 04 77 dd e1 c9 dd e5 dd + 21 00 00 dd 39 21 66 32 5e dd 66 06 2e 00 55 06 + 08 29 30 01 19 10 fa dd 4e 05 06 00 09 eb 0e 00 + 79 dd 96 07 30 0c 21 00 a8 19 dd 7e 04 77 13 0c + 18 ee dd e1 c9 dd e5 dd 21 00 00 dd 39 f5 f5 dd + 7e 07 dd 77 fe dd 4e 07 06 00 dd 6e 08 26 00 09 + dd 4e fe 06 00 79 95 78 9c e2 be 37 ee 80 f2 5a + 38 dd 56 0b 15 dd 7e fe b7 28 06 21 32 ca 46 18 + 04 21 31 ca 46 d5 33 dd 66 0a dd 6e 09 e5 c5 33 + cd 93 36 f1 f1 dd 36 fc 01 dd 5e 06 dd 66 fe 2e + 00 55 06 08 29 30 01 19 10 fa eb dd 7e 04 83 4f + dd 7e 05 8a 47 dd 5e 0a af dd 77 ff 7b 3c dd 77 + fd dd 7e ff d6 08 30 36 0a dd a6 fc b7 28 06 21 + 32 ca 56 18 04 21 31 ca 56 c5 dd 7e 0b f5 33 7b + f5 33 dd 7e 09 f5 33 d5 33 cd 93 36 f1 f1 c1 dd + 5e fd dd 7e fc 87 dd 77 fc dd 34 ff 18 be dd 7e + fd dd 77 0a dd 34 fe c3 a5 37 dd f9 dd e1 c9 dd + e5 dd 21 00 00 dd 39 dd 46 04 dd 7e 06 90 38 2d + c5 dd 7e 05 f5 33 c5 33 dd 66 09 dd 6e 08 e5 cd + 93 36 f1 f1 c1 c5 dd 7e 07 f5 33 c5 33 dd 66 09 + dd 6e 08 e5 cd 93 36 f1 f1 c1 04 18 cd dd 46 05 + 04 78 dd 96 07 30 2d c5 c5 33 dd 66 04 dd 6e 09 + e5 dd 7e 08 f5 33 cd 93 36 f1 f1 c1 c5 c5 33 dd + 66 06 dd 6e 09 e5 dd 7e 08 f5 33 cd 93 36 f1 f1 + c1 04 18 cd dd e1 c9 dd e5 dd 21 00 00 dd 39 dd + 66 05 dd 6e 04 e5 dd 56 08 1e 95 d5 cd 93 36 f1 + f1 dd 66 05 dd 6e 06 e5 dd 56 08 1e 89 d5 cd 93 + 36 f1 f1 dd 66 07 dd 6e 04 e5 dd 56 08 1e 8a d5 + cd 93 36 f1 f1 dd 66 07 dd 6e 06 e5 dd 56 08 1e + 8b d5 cd 93 36 f1 f1 dd 46 04 04 78 dd 96 06 30 + 2b c5 dd 7e 05 f5 33 c5 33 dd 56 08 1e 83 d5 cd + 93 36 f1 f1 c1 c5 dd 7e 07 f5 33 c5 33 dd 56 08 + 1e 83 d5 cd 93 36 f1 f1 c1 04 18 cf dd 46 05 04 + 78 dd 96 07 30 2b c5 c5 33 dd 7e 04 f5 33 dd 56 + 08 1e 82 d5 cd 93 36 f1 f1 c1 c5 c5 33 dd 7e 06 + f5 33 dd 56 08 1e 82 d5 cd 93 36 f1 f1 c1 04 18 + cf dd e1 c9 dd e5 dd 21 00 00 dd 39 dd 66 05 dd + 6e 04 e5 dd 56 08 1e 95 d5 cd 93 36 f1 f1 dd 66 + 05 dd 6e 06 e5 dd 56 09 1e 89 d5 cd 93 36 f1 f1 + dd 66 07 dd 6e 04 e5 dd 56 09 1e 8a d5 cd 93 36 + f1 f1 dd 66 07 dd 6e 06 e5 dd 56 0a 1e 8b d5 cd + 93 36 f1 f1 dd 46 04 04 78 dd 96 06 30 2b c5 dd + 7e 05 f5 33 c5 33 dd 56 09 1e 83 d5 cd 93 36 f1 + f1 c1 c5 dd 7e 07 f5 33 c5 33 dd 56 0a 1e 83 d5 + cd 93 36 f1 f1 c1 04 18 cf dd 46 05 04 78 dd 96 + 07 30 2b c5 c5 33 dd 7e 04 f5 33 dd 56 09 1e 82 + d5 cd 93 36 f1 f1 c1 c5 c5 33 dd 7e 06 f5 33 dd + 56 0a 1e 82 d5 cd 93 36 f1 f1 c1 04 18 cf dd e1 + c9 dd e5 dd 21 00 00 dd 39 dd 46 05 dd 7e 06 dd + 96 04 4f dd 7e 07 90 38 1d 79 3c c5 f5 33 c5 33 + dd 66 04 dd 6e 09 e5 dd 7e 08 f5 33 cd c7 36 f1 + f1 33 c1 04 18 dd dd e1 c9 dd e5 dd 21 00 00 dd + 39 dd 4e 05 dd 7e 06 dd 96 04 47 dd 7e 07 91 38 + 16 c5 c5 33 79 f5 33 dd 66 04 dd 6e 08 e5 cd 5d + 37 f1 f1 c1 0c 18 e4 dd e1 c9 21 02 00 39 56 1e + 1d d5 3e 27 f5 33 af f5 33 af f5 33 cd d7 38 f1 + f1 33 c9 01 5e 00 78 d6 1d d0 16 00 58 7a d6 27 + 30 32 c5 d5 79 f5 33 4a c5 3e ff f5 33 21 19 3b + e5 cd 7b 34 21 06 00 39 f9 d1 c1 7b 3c c5 d5 f5 + 33 d5 33 af 47 c5 cd 93 36 f1 f1 d1 c1 0c 7a c6 + 04 57 18 c8 43 04 04 18 bd 25 64 00 21 70 c5 36 + 00 21 95 3b 4e 06 00 c5 c5 2a 33 ca e5 cd 18 5d + f1 f1 c1 22 5b c5 c5 2a 35 ca e5 cd 18 5d f1 f1 + 22 5d c5 21 00 80 cb 46 c8 2a 47 ca 01 0a 00 c5 + e5 cd ef 5b f1 f1 22 47 ca 2a 49 ca 01 0a 00 c5 + e5 cd ef 5b f1 f1 22 49 ca 2a 4b ca 01 0a 00 c5 + e5 cd ef 5b f1 f1 22 4b ca 2a 4d ca 01 0a 00 c5 + e5 cd ef 5b f1 f1 22 4d ca 21 4f ca 36 01 21 d0 + 07 22 45 ca c9 10 10 b8 0b 03 02 fd 21 2f ca fd + 34 00 fd 34 00 fd 7e 00 ee 80 d6 90 d8 21 2f ca + 7e c6 f0 77 cd d3 32 3e 10 21 61 ca 86 4f 3e 8c + 23 8e 47 21 60 ca fd 21 5e ca fd 7e 00 86 5f fd + 7e 01 ce 00 57 1a c6 d3 02 21 60 ca 34 2a 5e ca + e5 cd b8 5d f1 4d 44 fd 21 60 ca fd 6e 00 26 00 + bf ed 42 c0 fd 36 00 00 c9 dd e5 dd 21 00 00 dd + 39 21 f6 ff 39 f9 af f5 33 cd 7b 33 33 3e 01 f5 + 33 af f5 33 cd cb 2a f1 cd 24 31 21 00 00 e5 21 + 00 00 e5 cd 44 31 f1 21 00 bf e3 21 00 00 e5 cd + c0 31 f1 f1 06 10 21 96 3b 4e 59 16 00 6b 62 29 + 19 29 19 29 19 29 19 29 19 29 19 29 19 29 19 29 + 19 29 19 29 29 29 29 29 dd 75 fe dd 74 ff 16 00 + 59 6b 62 29 19 29 29 29 19 29 29 33 33 e5 0e 00 + af dd 77 fb dd 7e fb d6 01 30 5f dd 70 fc af dd + 77 fd dd 7e fd d6 04 30 49 c5 af f5 33 af 57 1e + 02 d5 dd 7e fc f5 33 cd 96 30 f1 f1 c1 3e f1 dd + 86 fc 6f 3e c4 ce 00 67 71 dd 6e fd 26 00 29 29 + 29 29 29 11 80 00 19 c5 11 e0 ff d5 e5 dd 7e fc + f5 33 cd 7b 2f f1 f1 33 c1 0c dd 34 fc dd 34 fd + 18 b0 dd 46 fc dd 34 fb 18 9a af dd 77 f8 af dd + 77 f9 3a 00 80 e6 10 4f af b9 17 32 59 c5 fd 21 + 59 c5 fd cb 00 46 28 3d fd 21 5a c5 fd cb 00 46 + 20 33 3a 6e c5 32 6f c5 3a 00 81 e6 10 32 6e c5 + 3a 6e c5 b7 28 07 3a 6f c5 b7 ca 9d 3e cd 9b 3b + cd c4 32 cd e3 2f 3a 01 81 cb 57 28 08 21 70 c5 + 36 01 c3 9d 3e fd 21 59 c5 fd cb 00 46 c2 90 3e + fd 21 5a c5 fd cb 00 46 ca 90 3e dd 7e fe dd 96 + f6 dd 7e ff dd 9e f7 e2 5c 3d ee 80 f2 14 3e dd + 7e f6 dd 96 fe 6f dd 7e f7 dd 9e ff 67 dd 75 fc + dd 74 fd 21 06 00 e5 dd 6e fc dd 66 fd e5 cd f7 + 5d f1 f1 eb 4b 42 3e 40 b9 3e 00 98 e2 91 3d ee + 80 f2 99 3d 11 40 00 18 07 7a b3 20 03 11 02 00 + dd 7e fe 83 dd 77 fe dd 7e ff 8a dd 77 ff 0e 10 + 1e 00 7b d6 02 30 61 fd 21 96 3b fd 6e 00 26 00 + c5 d5 e5 dd 6e fe dd 66 ff e5 cd f7 5d f1 e3 fd + e1 d1 c1 6b 26 00 29 29 29 29 45 54 fd e5 e1 7d + 80 6f 7c 8a 47 dd 75 fa dd 70 fb dd 70 fc dd 36 + fd 00 16 00 7a d6 08 30 18 21 71 c4 06 00 09 dd + 7e fc 77 21 51 c4 06 00 09 dd 7e fa 77 0c 14 18 + e3 1c 18 9e dd 36 f9 01 cd e3 52 dd 7e f8 b7 20 + 22 3a 0a c6 3d 20 1c dd 7e f9 3d 20 16 11 0c 11 + d5 3e ff f5 33 21 a2 3e e5 cd 9e 33 f1 f1 33 dd + 36 f8 01 fd 21 70 ca fd 35 00 af fd 96 00 e2 53 + 3e ee 80 fa 8d 3e 21 07 c6 4e 06 00 69 60 29 29 + 09 29 01 32 00 c5 e5 cd f7 5d f1 f1 4d 3a db 52 + 21 70 ca 91 77 af fd 21 70 ca fd 96 00 e2 82 3e + ee 80 fa 8a 3e 21 70 ca 36 01 cd 27 59 cd 22 5a + 3a 59 c5 fd 21 5a c5 fd 77 00 c3 e2 3c dd f9 dd + e1 c9 50 72 65 73 73 20 41 20 74 6f 20 73 74 61 + 72 74 00 dd e5 dd 21 00 00 dd 39 21 f6 ff 39 f9 + fd 21 3b ca fd 36 00 00 3a 00 80 e6 10 4f af b9 + 17 32 59 c5 fd 21 59 c5 fd cb 00 46 ca 0b 40 fd + 21 5a c5 fd cb 00 46 c2 0b 40 3a 0b b4 b7 ca 81 + 3f 3a 0a b4 b7 28 68 3a f5 c5 3d c2 81 3f af 57 + 1e 01 d5 11 0a 01 d5 cd 96 30 f1 f1 3a f6 c5 4f + 06 00 11 00 00 21 57 ca 7e 81 77 23 7e 88 77 23 + 7e 8b 77 23 7e 8a 77 3a f6 c5 4f 06 00 11 00 00 + 21 6a c5 7e 81 77 23 7e 88 77 23 7e 8b 77 23 7e + 8a 77 21 f5 c5 36 02 21 f7 c5 36 28 01 fb c4 0a + 21 6b ca 86 02 3e 01 f5 33 cd 2d 2f 33 18 22 0e + 00 21 65 ca 79 96 30 19 11 00 b4 79 c6 0c 6f 17 + 9f 67 19 7e b7 28 07 21 74 ca 36 01 18 03 0c 18 + e0 af dd 77 ff 21 2e ca dd 7e ff 96 30 1c 3e 00 + dd 86 ff dd 77 fd 3e b4 ce 00 dd 77 fe dd 6e fd + dd 66 fe 36 00 dd 34 ff 18 db cd e3 2f 3a 07 c6 + fd 21 5f c5 fd 77 00 fd 7e 00 fd 21 63 ca fd 96 + 00 28 27 3a 5f c5 32 63 ca 3a 5f c5 f5 33 cd e9 + 6f 33 d5 e5 21 a3 bc e5 21 0a d7 e5 cd d6 6a f1 + f1 f1 f1 d5 e5 cd c0 31 f1 f1 3a 6e c5 fd 21 6f + c5 fd 77 00 3a 00 81 e6 10 32 6e c5 3a 01 81 cb + 57 28 08 21 70 c5 36 01 c3 70 48 fd 21 59 c5 fd + cb 00 46 c2 63 48 fd 21 5a c5 fd cb 00 46 ca 63 + 48 3a 08 c6 b7 28 0f af fd 21 41 ca fd be 00 17 + f5 33 cd 88 55 33 cd 22 5a cd 60 4f 3a 3b ca d6 + 02 3e 01 28 01 af f5 33 cd dd 4b 33 cd 43 51 fd + 21 3b ca fd 7e 00 d6 02 28 07 fd 7e 00 d6 03 20 + 50 fd 21 40 ca fd 34 00 fd 7e 00 d6 3c 38 0f fd + 21 3f ca fd 34 00 fd 21 40 ca fd 36 00 00 3a 09 + c6 b7 28 2d 3a 08 c6 57 1e 01 d5 11 ff 26 d5 21 + 75 48 e5 cd 7b 34 21 06 00 39 f9 fd 21 09 c6 fd + 36 00 00 3a 08 c6 b7 20 08 fd 21 3b ca fd 36 00 + 07 3e 0a fd 21 3b ca fd 96 00 da c8 47 fd 4e 00 + 06 00 21 c9 40 09 09 09 e9 c3 ea 40 c3 ee 41 c3 + d6 42 c3 a6 43 c3 d4 45 c3 f9 45 c3 4c 46 c3 d6 + 46 c3 fc 46 c3 c8 47 c3 bb 47 21 3e ca 36 00 21 + 00 00 22 42 ca 21 41 ca 36 00 3a 4f ca f5 33 21 + 04 01 e5 2a 37 ca e5 cd 78 54 f1 f1 33 3a e0 52 + 32 07 c6 fd 21 57 ca fd 36 00 00 fd 36 01 00 fd + 36 02 00 fd 36 03 00 fd 21 62 c5 fd 36 00 e7 fd + 36 01 03 fd 36 02 00 fd 36 03 00 21 5c ca 36 00 + 21 5b ca 36 00 21 00 00 22 67 ca cd be 4a cd 45 + 4e cd f4 50 3a 51 ca 32 50 ca af 57 1e 02 d5 3e + 3f f5 33 21 79 48 e5 cd 9e 33 f1 f1 33 af 57 1e + 0f d5 3e 3f f5 33 21 7d 48 e5 cd 9e 33 f1 f1 33 + af 57 1e 23 d5 3e 3f f5 33 21 88 48 e5 cd 9e 33 + f1 f1 33 3a 08 c6 57 1e 01 d5 11 ff 26 d5 21 75 + 48 e5 cd 7b 34 21 06 00 39 f9 11 0a 0b d5 3e 3f + f5 33 21 8e 48 e5 cd 9e 33 f1 f1 33 11 05 0e d5 + 3e 38 f5 33 21 a3 48 e5 cd 9e 33 f1 f1 33 11 05 + 11 d5 3e 1f f5 33 21 c1 48 e5 cd 9e 33 f1 f1 33 + 21 3b ca 36 05 2a 47 ca 22 3c ca c3 c8 47 21 3b + ca 36 02 21 00 00 22 42 ca 21 44 ca 36 00 21 3e + ca 34 21 3f ca 36 00 21 40 ca 36 00 21 41 ca 36 + 01 fd 21 3e ca fd 7e 00 d6 0d 30 18 ed 5b 97 3b + fd 4e 00 06 00 d5 c5 cd 18 5d f1 f1 dd 75 fe dd + 74 ff 18 10 2a 97 3b 4d 44 29 09 29 29 09 dd 75 + fe dd 74 ff dd 4e fe dd 46 ff 21 60 c5 fd 21 45 + ca fd 7e 00 81 77 fd 7e 01 88 23 77 3e 01 f5 33 + af f5 33 cd cb 2a f1 21 9a 3b 5e 21 3e ca 66 2e + 00 55 06 08 29 30 01 19 10 fa 4d 3a 99 3b 81 32 + e5 c5 fd 21 e5 c5 fd 4e 00 06 00 59 50 cb 78 28 + 05 59 50 13 13 13 cb 2a cb 1b cb 2a cb 1b 7b c6 + 02 32 e6 c5 3a e5 c5 c6 05 32 e4 c5 3a 65 ca fd + 21 e4 c5 fd 96 00 30 06 3a 65 ca 32 e4 c5 af 57 + 1e 1d d5 11 ff 12 d5 21 df 48 e5 cd 7b 34 21 06 + 00 39 f9 c3 c8 47 21 07 c6 4e 06 00 2a 42 ca 09 + 22 42 ca fd 21 44 ca fd 34 00 3e 0a fd 96 00 30 + 35 2a 60 c5 01 64 00 c5 e5 cd ef 5b f1 f1 4d 44 + 2a 42 ca c5 e5 cd ef 5b f1 f1 45 c5 33 11 12 1d + d5 3e ff f5 33 21 df 48 e5 cd 7b 34 21 06 00 39 + f9 21 44 ca 36 00 21 60 c5 fd 21 42 ca fd 7e 00 + 96 fd 7e 01 23 9e 38 17 11 12 1d d5 3e ff f5 33 + 21 e5 48 e5 cd 9e 33 f1 f1 33 21 3b ca 36 03 fd + 21 50 ca fd 35 00 fd 7e 00 b7 20 09 3a 51 ca 32 + 50 ca cd ab 4f 21 5c ca 7e fd 21 07 c6 fd 86 00 + 77 21 5d ca fd 21 5c ca fd 7e 00 96 da c8 47 21 + 5d ca d5 fd e5 d1 1a 96 12 d1 fd 21 57 ca fd 34 + 00 c2 c8 47 fd 34 01 c2 c8 47 fd 34 02 c2 c8 47 + fd 34 03 c3 c8 47 21 5c ca 7e fd 21 07 c6 fd 86 + 00 77 21 5d ca fd 21 5c ca fd 7e 00 96 38 21 21 + 5d ca d5 fd e5 d1 1a 96 12 d1 fd 21 57 ca fd 34 + 00 20 0d fd 34 01 20 08 fd 34 02 20 03 fd 34 03 + 3a e3 c5 b7 c2 c8 47 21 3b ca 36 04 2a 49 ca 22 + 3c ca 21 41 ca 36 00 21 96 3b 4e 06 00 c5 2a 39 + ca e5 cd 18 5d f1 f1 4d 44 21 95 3b 5e 16 00 c5 + d5 2a 37 ca e5 cd 18 5d f1 f1 c1 11 06 18 d5 c5 + e5 cd 8c 52 21 06 00 39 f9 21 3e ca 4e 06 00 c5 + 11 09 0b d5 3e ff f5 33 21 ea 48 e5 cd fd 34 21 + 07 00 39 f9 fd 21 df 52 fd 6e 00 26 00 fd 21 de + 52 fd 4e 00 06 00 bf ed 42 5d 54 cb 7c 28 02 eb + 13 cb 2a cb 1b 2a 60 c5 d5 01 3c 00 c5 e5 cd ef + 5b f1 f1 d1 16 00 d5 e5 cd ef 5b f1 f1 dd 75 fa + dd 74 fb 21 3f ca 5e 16 00 dd 7e fa dd 46 fb 93 + 4f 78 9a 47 21 56 ca 5e 16 00 d5 c5 cd 18 5d f1 + f1 dd 75 fc dd 74 fd 4d 7c 47 17 9f 5f 57 21 66 + c5 7e 81 77 23 7e 88 77 23 7e 8b 77 23 7e 8a 77 + dd 46 fd cb 78 28 2f af dd 96 fc 4f 3e 00 dd 9e + fd 47 17 9f 5f 57 21 57 ca 7e 91 23 7e 98 23 7e + 9b 23 7e 9a 30 10 ed 4b 57 ca 21 00 00 bf ed 42 + dd 75 fc dd 74 fd dd 7e fc dd 77 f6 dd 7e fd dd + 77 f7 17 9f dd 77 f8 dd 77 f9 21 57 ca 7e dd 86 + f6 77 23 7e dd 8e f7 77 23 7e dd 8e f8 77 23 7e + dd 8e f9 77 3a 3f ca dd 77 fe af dd 77 ff dd 6e + fe dd 66 ff e5 11 0e 0d d5 3e ff f5 33 21 03 49 + e5 cd fd 34 21 07 00 39 f9 dd 6e fa dd 66 fb e5 + 11 0f 0e d5 3e ff f5 33 21 0d 49 e5 cd fd 34 21 + 07 00 39 f9 dd 4e fc dd 46 fd af b9 98 e2 72 45 + ee 80 f2 92 45 dd 6e fc dd 66 fd e5 11 0d 10 d5 + 3e 18 f5 33 21 16 49 e5 cd 82 35 21 07 00 39 f9 + 18 12 11 0e 10 d5 3e 5b f5 33 21 21 49 e5 cd 9e + 33 f1 f1 33 2a 59 ca e5 2a 57 ca e5 11 0d 12 d5 + 3e ff f5 33 21 2d 49 e5 cd 07 36 21 09 00 39 f9 + 11 1e 1d d5 11 0a 1d d5 af f5 33 cd 42 33 f1 f1 + 33 c3 c8 47 cd e3 52 fd 21 e0 52 fd 4e 00 fd 21 + 07 c6 fd 7e 00 91 30 06 fd 34 00 c3 c8 47 fd 21 + 3b ca fd 36 00 05 c3 c8 47 cd e3 52 2a 3c ca 2b + 22 3c ca fd 21 3c ca fd 7e 01 fd b6 00 c2 c8 47 + 11 27 14 d5 3e 02 f5 33 af f5 33 af f5 33 cd 42 + 33 f1 f1 33 11 07 10 d5 3e ff f5 33 21 38 49 e5 + cd 9e 33 f1 f1 33 21 3b ca 36 06 2a 4b ca 22 3c + ca fd 21 3f ca fd 36 00 00 c3 c8 47 cd e3 52 3a + de 52 fd 21 07 c6 fd 96 00 30 03 fd 35 00 fd 21 + 40 ca fd 34 00 fd 7e 00 d6 0f 38 37 3e 02 f5 33 + cd 2d 2f 33 3a 3f ca b7 28 05 01 07 00 18 03 01 + 3f 00 11 10 0e d5 79 f5 33 21 54 49 e5 cd 9e 33 + f1 f1 33 3a 3f ca d6 01 3e 00 17 32 3f ca 21 40 + ca 36 00 2a 3c ca 2b 22 3c ca fd 21 3c ca fd 7e + 01 fd b6 00 c2 c8 47 11 27 10 d5 3e 0e f5 33 af + f5 33 af f5 33 cd 42 33 f1 f1 33 21 3b ca 36 01 + cd be 4a c3 c8 47 11 10 0e d5 3e 03 f5 33 21 5c + 49 e5 cd 9e 33 f1 f1 33 cd f5 2a 2a 4d ca 22 3c + ca fd 21 3b ca fd 36 00 08 c3 c8 47 2a 3c ca 2b + 22 3c ca fd 21 3c ca fd 7e 01 fd b6 00 c2 c8 47 + 11 01 01 d5 cd 81 2a f1 11 27 0e d5 3e 0e f5 33 + af f5 33 af f5 33 cd 42 33 f1 f1 33 2a 59 ca e5 + 2a 57 ca e5 11 0a 0b d5 3e ff f5 33 21 66 49 e5 + cd 07 36 21 09 00 39 f9 21 67 ca 4e 23 46 11 00 + 00 d5 c5 11 05 0e d5 3e 3f f5 33 21 77 49 e5 cd + 07 36 21 09 00 39 f9 2a 68 c5 e5 2a 66 c5 e5 11 + 09 10 d5 3e 38 f5 33 21 8d 49 e5 cd 07 36 21 09 + 00 39 f9 2a 6c c5 e5 2a 6a c5 e5 11 07 12 d5 3e + 1f f5 33 21 9f 49 e5 cd 07 36 21 09 00 39 f9 11 + 0a 15 d5 3e ff f5 33 21 b3 49 e5 cd 9e 33 f1 f1 + 33 fd 21 3b ca fd 36 00 0a 18 0d 3a 6e c5 b7 28 + 07 3a 6f c5 b7 ca 70 48 3a 57 ca fd 21 62 c5 fd + 96 00 20 24 3a 58 ca fd 21 62 c5 fd 96 01 20 18 + 3a 59 ca fd 21 62 c5 fd 96 02 20 0c 3a 5a ca fd + 21 62 c5 fd 96 03 28 6b 21 52 ca 7e fd 21 57 ca + fd 96 00 23 7e fd 9e 01 23 7e fd 9e 02 23 7e fd + 9e 03 30 0b 11 52 ca 21 57 ca 01 04 00 ed b0 2a + 59 ca e5 2a 57 ca e5 3e 01 f5 33 af 57 1e ff d5 + 21 c7 49 e5 cd 07 36 21 09 00 39 f9 2a 54 ca e5 + 2a 52 ca e5 11 10 01 d5 3e ff f5 33 21 ca 49 e5 + cd 07 36 21 09 00 39 f9 11 62 c5 21 57 ca 01 04 + 00 ed b0 3a 59 c5 fd 21 5a c5 fd 77 00 c3 c8 3e + dd f9 dd e1 c9 25 32 64 00 31 55 50 00 48 49 47 + 48 20 53 43 4f 52 45 00 53 48 49 50 53 00 41 76 + 6f 69 64 20 74 68 65 20 61 73 74 65 72 6f 69 64 + 73 21 00 55 73 65 20 41 20 74 6f 20 62 6f 6f 73 + 74 20 66 6f 72 20 74 69 6d 65 20 62 6f 6e 75 73 + 00 43 6f 6c 6c 65 63 74 20 67 65 6d 73 20 66 6f + 72 20 65 78 74 72 61 20 70 6f 69 6e 74 73 00 25 + 33 64 25 25 00 31 30 30 25 00 2d 2d 20 46 49 45 + 4c 44 20 25 64 20 43 4f 4d 50 4c 45 54 45 44 20 + 2d 2d 00 54 69 6d 65 3a 20 25 36 64 00 50 61 72 + 3a 20 25 36 64 00 42 6f 6e 75 73 3a 20 25 36 64 + 00 4e 6f 20 62 6f 6e 75 73 20 3a 28 00 53 63 6f + 72 65 3a 20 25 36 64 00 2d 20 45 6e 74 65 72 69 + 6e 67 20 61 73 74 65 72 6f 69 64 20 66 69 65 6c + 64 20 2d 00 44 41 4e 47 45 52 21 00 47 41 4d 45 + 20 4f 56 45 52 00 46 69 6e 61 6c 20 53 63 6f 72 + 65 3a 20 25 36 64 00 41 73 74 65 72 6f 69 64 73 + 20 65 76 61 64 65 64 3a 20 25 36 64 00 54 69 6d + 65 20 62 6f 6e 75 73 65 73 3a 20 25 36 64 00 50 + 69 63 6b 75 70 20 62 6f 6e 75 73 65 73 3a 20 25 + 36 64 00 50 72 65 73 73 20 41 20 74 6f 20 63 6f + 6e 74 69 6e 75 65 00 25 64 00 25 36 64 00 cd 1c + 3b cd f5 2a af f5 33 cd 0f 33 33 cd f8 30 3a 70 + c5 b7 c0 3a 4f ca f5 33 21 00 01 e5 2a 37 ca e5 + cd 78 54 f1 f1 33 21 96 3b 4e 06 00 c5 2a 39 ca + e5 cd 18 5d f1 f1 4d 44 21 95 3b 5e 16 00 c5 d5 + 2a 37 ca e5 cd 18 5d f1 f1 c1 11 06 18 d5 c5 e5 + cd 8c 52 21 06 00 39 f9 cd d3 58 cd f9 3b cd 03 + 33 af f5 33 cd 0f 33 33 cd f8 30 3a 70 c5 b7 c0 + cd b3 3e 18 8f 43 4f 44 45 20 41 4e 44 20 47 46 + 58 20 42 59 20 4a 49 4d 4d 59 53 54 4f 4e 45 53 + 20 20 20 2e 2e 2e 20 20 20 4d 55 53 49 43 20 42 + 59 20 44 41 52 52 49 4e 20 43 41 52 44 41 4e 49 + 20 20 20 2e 2e 2e 20 20 20 00 fd 21 e5 c5 fd 4e + 00 fd 7e 00 d6 1e 30 08 3e 1e 91 47 17 9f 18 02 + 06 00 3a e5 c5 d6 78 30 08 3e 78 91 5f 17 9f 18 + 03 11 00 00 7b f5 33 c5 33 cd 3c 32 f1 c9 dd e5 + dd 21 00 00 dd 39 f5 3b 21 96 3b 4e 06 00 69 60 + 29 29 29 29 09 29 29 29 29 22 e1 c5 af dd 77 ff + 21 65 ca dd 7e ff 96 d2 d8 4b dd 6e ff 26 00 29 + 4d 44 21 71 c5 09 e3 c5 21 40 01 e5 21 20 00 e5 + cd 68 32 f1 f1 c1 fd 21 95 3b fd 5e 00 16 00 c5 + d5 e5 cd 18 5d f1 f1 eb c1 e1 e5 73 23 72 21 91 + c5 09 eb 3a 66 ca 06 00 12 13 78 12 3e b1 dd 86 + ff 4f 3e c5 ce 00 47 21 e6 c5 af 96 57 c5 3a e6 + c5 f5 33 d5 33 cd 95 32 f1 7d c1 02 3e c1 dd 86 + ff 4f 3e c5 ce 00 47 3a e5 c5 c6 10 c5 57 1e 04 + d5 cd 3c 32 f1 7d c1 02 3e d1 dd 86 ff 4f 3e c5 + ce 00 47 c5 cd 8a 4a 7d c1 02 dd 7e ff c6 0c 4f + 21 f1 c4 06 00 09 e5 c5 3e 07 f5 33 af f5 33 cd + 3c 32 f1 7d c1 e1 77 c5 11 01 01 d5 af 47 c5 cd + 96 30 f1 f1 c1 21 91 c4 06 00 09 36 00 e1 e5 5e + 23 56 fd 21 95 3b fd 6e 00 26 00 c5 e5 d5 cd ef + 5b f1 f1 c1 11 00 00 d5 e5 79 f5 33 cd 7b 2f f1 + f1 33 dd 34 ff c3 e0 4a dd f9 dd e1 c9 dd e5 dd + 21 00 00 dd 39 21 f3 ff 39 f9 21 e3 c5 36 00 dd + 7e 04 3d 3e 01 28 01 af dd 77 f3 af dd 77 ff 21 + 65 ca dd 7e ff 96 d2 40 4e dd 7e ff dd 77 fe c6 + 0c dd 77 f4 21 e4 c5 dd 7e ff 96 d2 3a 4e 3e d1 + dd 86 ff dd 77 f5 3e c5 ce 00 dd 77 f6 dd 6e f5 + dd 66 f6 4e 79 b7 28 3c dd 7e f3 b7 ca 3a 4e 79 + 3d c1 e1 e5 c5 77 b7 c2 3a 4e 3e f1 dd 86 f4 4f + 3e c4 ce 00 47 c5 3e 07 f5 33 af f5 33 cd 3c 32 + f1 7d c1 02 3e 91 dd 86 f4 6f 3e c4 ce 00 67 36 + 01 c3 3a 4e 21 e3 c5 34 dd 6e ff 26 00 29 4d 44 + 21 71 c5 09 dd 75 f7 dd 74 f8 5e 23 56 3e b1 dd + 86 ff dd 77 f9 3e c5 ce 00 dd 77 fa dd 6e f9 dd + 66 fa 6e 7d 17 9f 67 19 eb dd 6e f7 dd 66 f8 73 + 23 72 dd 6e f7 dd 66 f8 7e dd 77 fd 23 7e dd 77 + fe 21 5b c5 7b 96 7a 23 9e 30 15 dd 6e f7 dd 66 + f8 fd 21 5d c5 fd 7e 00 77 23 fd 7e 01 77 18 21 + 21 5d c5 7e dd 96 fd 23 7e dd 9e fe 30 13 dd 6e + f7 dd 66 f8 fd 21 5b c5 fd 7e 00 77 23 fd 7e 01 + 77 21 91 c5 09 dd 75 fb dd 74 fc 4e 23 46 21 e1 + c5 79 96 78 23 9e da e1 4d 3e 91 dd 86 f4 4f 3e + c4 ce 00 47 af 02 21 40 01 e5 21 20 00 e5 cd 68 + 32 f1 f1 fd 21 95 3b fd 4e 00 06 00 c5 c5 e5 cd + 18 5d f1 f1 dd 75 fd dd 74 fe c1 dd 6e f7 dd 66 + f8 dd 7e fd 77 23 dd 7e fe 77 21 96 3b 5e c5 fd + 21 66 ca fd 66 00 2e 00 55 06 08 29 30 01 19 10 + fa c1 eb dd 6e fb dd 66 fc 73 23 72 fd 5e 00 16 + 00 d5 c5 dd 6e fd dd 66 fe e5 cd ef 5b f1 e3 dd + 7e f4 f5 33 cd 7b 2f f1 f1 33 21 e6 c5 af 96 47 + 3a e6 c5 f5 33 c5 33 cd 95 32 f1 7d dd 6e f9 dd + 66 fa 77 3e c1 dd 86 ff 4f 3e c5 ce 00 47 3a e5 + c5 c6 10 c5 57 1e 04 d5 cd 3c 32 f1 7d c1 02 cd + 8a 4a 7d c1 e1 e5 c5 77 2a 67 ca 23 22 67 ca 18 + 59 3e c1 dd 86 ff 5f 3e c5 ce 00 57 1a 5f 17 9f + 57 fd 21 5f c5 fd 6e 00 26 00 19 09 eb dd 6e fb + dd 66 fc 73 23 72 21 96 3b 4e 06 00 c5 d5 cd ef + 5b f1 f1 4d 44 dd 6e f7 dd 66 f8 5e 23 56 fd 21 + 95 3b fd 6e 00 26 00 c5 e5 d5 cd ef 5b f1 e3 dd + 7e f4 f5 33 cd 7b 2f f1 f1 33 dd 34 ff c3 ff 4b + dd f9 dd e1 c9 01 1d 00 21 69 ca 5e 16 00 21 1d + 00 19 79 95 78 9c e2 5b 4e ee 80 f0 51 c5 af 47 + 0e 01 c5 3e 01 f5 33 d5 33 cd 96 30 f1 f1 c1 21 + 91 c4 09 36 00 03 18 d0 04 dd e5 dd 21 00 00 dd + 39 21 fa ff 39 f9 dd 7e 06 dd 77 ff 0e 00 21 69 + ca 79 96 d2 5b 4f 21 e7 c5 06 00 09 7e b7 c2 57 + 4f e5 c5 11 02 07 d5 cd 3c 32 f1 7d c1 e1 77 21 + ea c5 06 00 09 36 00 21 ed c5 06 00 09 dd 46 04 + 70 79 c6 1d dd 77 fa 3e 91 dd 86 fa 6f 3e c4 ce + 00 67 36 01 3e f1 dd 86 fa 5f 3e c4 ce 00 57 78 + 87 87 c6 08 12 21 96 3b 5e 16 00 c5 d5 2a fd c5 + e5 cd ef 5b f1 f1 c1 e5 c5 11 fc 08 d5 cd 95 32 + f1 7d c1 e1 5f 17 9f 57 19 dd 75 fb dd 74 fc 21 + 95 3b 5e 16 00 c5 d5 2a fb c5 e5 cd ef 5b f1 f1 + c1 e5 c5 11 fc 08 d5 cd 95 32 f1 7d c1 e1 5f 17 + 9f 57 dd 73 fd dd 72 fe 19 c5 dd 5e fb dd 56 fc + d5 e5 dd 7e fa f5 33 cd 7b 2f f1 f1 33 c1 dd 35 + ff dd 7e ff b7 28 04 0c c3 8e 4e dd f9 dd e1 c9 + 0e 00 21 69 ca 79 96 d0 3e e7 81 5f 3e c5 ce 00 + 57 1a b7 28 33 3d 12 b7 20 2e 79 c6 1d 47 c6 f1 + 6f 3e c4 ce 00 67 34 3e ea 81 6f 3e c5 ce 00 67 + 7e 3c 77 d6 04 20 0d 78 c6 91 5f 3e 00 ce c4 57 + af 12 18 04 3a 78 4e 12 0c 18 b7 dd e5 dd 21 00 + 00 dd 39 21 f7 ff 39 f9 0e 00 1e 00 21 6a ca 7b + 96 d2 ef 50 3e f5 83 dd 77 f7 3e c5 ce 00 dd 77 + f8 e1 e5 7e b7 c2 ea 50 79 c6 0a dd 77 f9 c5 3e + 03 f5 33 af f5 33 cd 3c 32 f1 7d c1 47 69 26 00 + 29 dd 75 fa dd 74 fb 3e f0 dd 86 fa dd 77 fc 3e + c5 dd 8e fb dd 77 fd c5 21 10 01 e5 21 30 00 e5 + cd 68 32 f1 f1 c1 fd 21 95 3b fd 5e 00 16 00 c5 + d5 e5 cd 18 5d f1 f1 eb c1 dd 6e fc dd 66 fd 73 + 23 72 3e f2 dd 86 fa dd 77 fe 3e c5 dd 8e fb dd + 77 ff 21 96 3b 5e c5 21 6c ca 66 2e 00 55 06 08 + 29 30 01 19 10 fa c1 eb dd 6e fe dd 66 ff 73 23 + 72 3e f4 81 5f 3e c5 ce 00 57 d5 78 5f 87 83 87 + 87 d1 c5 d5 f5 33 af f5 33 cd 3c 32 f1 7d d1 c1 + 12 e1 e5 36 01 3e f6 81 5f 3e c5 ce 00 57 48 79 + 3c d5 5f 87 83 87 87 87 83 87 d1 12 c5 11 01 01 + d5 3e 01 f5 33 dd 7e f9 f5 33 cd 96 30 f1 f1 c1 + 11 f1 c4 dd 6e f9 26 00 19 79 c6 10 77 21 6c ca + 4e 06 00 dd 6e fc dd 66 fd 5e 23 56 fd 21 95 3b + fd 6e 00 26 00 c5 e5 d5 cd ef 5b f1 e3 dd 7e f9 + f5 33 cd 7b 2f f1 f1 33 18 05 1c 4b c3 bc 4f dd + f9 dd e1 c9 21 96 3b 4e 59 16 00 6b 62 29 29 29 + 29 19 29 29 29 29 22 f8 c5 79 87 87 87 32 fa c5 + 01 0a 00 21 6a ca 5e 16 00 21 0a 00 19 79 95 78 + 9c e2 26 51 ee 80 f0 51 c5 af 47 0e 01 c5 3e 01 + f5 33 d5 33 cd 96 30 f1 f1 c1 21 91 c4 09 36 00 + 03 18 d0 dd e5 dd 21 00 00 dd 39 21 f8 ff 39 f9 + 0e 00 21 6a ca 79 96 d2 87 52 3e f5 81 5f 3e c5 + ce 00 57 1a b7 ca 83 52 79 c6 0a 47 69 26 00 29 + dd 75 fa dd 74 fb 3e f2 dd 86 fa dd 77 fc 3e c5 + dd 8e fb dd 77 fd dd 6e fc dd 66 fd 7e dd 77 fe + 23 7e dd 77 ff 3e f4 81 6f 3e c5 ce 00 67 7e dd + 77 f8 17 9f dd 77 f9 3a 5f c5 26 00 dd 86 f8 6f + 7c dd 8e f9 67 7d dd 86 fe 6f 7c dd 8e ff 67 dd + 75 fe dd 74 ff dd 6e fc dd 66 fd dd 7e fe 77 23 + dd 7e ff 77 21 f8 c5 7e dd 96 fe 23 7e dd 9e ff + 30 10 3e 91 80 6f 3e c4 ce 00 67 36 00 af 12 c3 + 83 52 1a d6 02 20 38 3e f7 81 dd 77 fe 3e c5 ce + 00 dd 77 ff dd 6e fe dd 66 ff 7e 3d dd 6e fe dd + 66 ff 77 b7 20 19 3e 91 80 6f 3e c4 ce 00 67 36 + 00 af 12 dd 6e fe dd 66 ff 3a 6d ca 77 18 54 dd + 6e fc dd 66 fd 5e 23 56 fd 21 96 3b fd 6e 00 26 + 00 c5 e5 d5 cd ef 5b f1 f1 dd 75 fe dd 74 ff c1 + dd 7e fa c6 f0 6f dd 7e fb ce c5 67 5e 23 56 fd + 21 95 3b fd 6e 00 26 00 c5 e5 d5 cd ef 5b f1 f1 + c1 c5 dd 5e fe dd 56 ff d5 e5 c5 33 cd 7b 2f f1 + f1 33 c1 0c c3 52 51 dd f9 dd e1 c9 fd 21 0a c6 + fd 36 00 00 fd 21 0b c6 fd 36 00 00 fd 21 0c c6 + fd 36 00 00 fd 21 02 00 fd 39 fd 7e 00 32 0d c6 + fd 7e 01 32 0e c6 fd 23 fd 23 fd 7e 00 32 0f c6 + fd 7e 01 32 10 c6 fd 23 fd 23 fd 7e 00 32 75 ca + fd 23 fd 7e 00 32 76 ca c9 14 03 0a 03 05 0c 20 + 40 78 78 3a fd c5 fd 21 0f c6 fd 96 00 20 0d 3a + fe c5 fd 21 0f c6 fd 96 01 ca 9d 53 ed 4b 0f c6 + 2a fd c5 79 95 4f 78 9c 47 3a 75 ca 5f 17 9f 57 + d5 c5 cd f7 5d f1 f1 22 13 c6 fd 21 13 c6 fd 7e + 01 fd b6 00 20 08 2a 0f c6 22 fd c5 18 51 fd 21 + 76 ca fd 4e 00 06 00 79 fd 21 13 c6 fd 96 00 78 + fd 9e 01 e2 48 53 ee 80 f2 51 53 ed 43 13 c6 18 + 20 21 76 ca 4e 06 00 af 91 4f 3e 00 98 47 2a 13 + c6 7d 91 7c 98 e2 6a 53 ee 80 f2 71 53 ed 43 13 + c6 ed 4b 13 c6 21 fd c5 7e 81 77 23 7e 88 77 21 + 96 3b 4e 06 00 c5 2a fd c5 e5 cd ef 5b f1 f1 4d + 5c 21 7c c4 16 00 73 21 5c c4 71 18 08 fd 21 0c + c6 fd 36 00 01 3a fb c5 fd 21 0d c6 fd 96 00 20 + 0d 3a fc c5 fd 21 0d c6 fd 96 01 ca 5b 54 ed 4b + 0d c6 2a fb c5 79 95 4f 78 9c 47 21 75 ca 5e 16 + 00 d5 c5 cd f7 5d f1 f1 22 11 c6 fd 21 11 c6 fd + 7e 01 fd b6 00 20 08 2a 0d c6 22 fb c5 18 51 fd + 21 76 ca fd 4e 00 06 00 79 fd 21 11 c6 fd 96 00 + 78 fd 9e 01 e2 09 54 ee 80 f2 12 54 ed 43 11 c6 + 18 20 21 76 ca 4e 06 00 af 91 4f 3e 00 98 47 2a + 11 c6 7d 91 7c 98 e2 2b 54 ee 80 f2 32 54 ed 43 + 11 c6 ed 4b 11 c6 21 fb c5 7e 81 77 23 7e 88 77 + 21 95 3b 4e 06 00 c5 2a fb c5 e5 cd ef 5b f1 e3 + 3e 0b f5 33 cd ba 2f f1 33 18 08 fd 21 0b c6 fd + 36 00 01 3a 0b c6 b7 28 06 3a 0c c6 b7 20 03 af + 18 02 3e 01 32 0a c6 c9 dd e5 dd 21 00 00 dd 39 + 21 95 3b 46 58 16 00 6b 62 29 29 29 29 29 22 ff + c5 6b 62 29 29 19 29 29 19 29 29 29 29 22 01 c6 + 21 96 3b 4e 59 16 00 6b 62 29 29 29 29 29 22 03 + c6 6b 62 29 19 29 19 29 19 29 29 19 29 29 22 05 + c6 26 00 c5 68 e5 dd 6e 04 dd 66 05 e5 cd 18 5d + f1 f1 c1 22 fb c5 06 00 c5 dd 6e 06 dd 66 07 e5 + cd 18 5d f1 f1 22 fd c5 3a de 52 32 07 c6 21 6e + ca 36 00 21 6f ca 36 00 21 74 ca 36 00 dd 7e 08 + 32 08 c6 21 09 c6 36 01 21 73 ca 36 00 21 71 ca + 36 00 21 72 ca 36 00 21 fc c4 36 20 11 01 01 d5 + 11 0b 01 d5 cd 96 30 f1 f1 dd 6e 06 dd 66 07 e5 + dd 6e 04 dd 66 05 e5 3e 0b f5 33 cd 7b 2f f1 f1 + 33 3a db 52 32 70 ca dd e1 c9 af f5 33 cd 2d 2f + 33 3e 01 f5 33 21 00 00 e5 cd 79 4e f1 33 3e 02 + f5 33 21 01 00 e5 cd 79 4e f1 33 21 9c c4 36 00 + 21 09 c6 36 01 fd 21 08 c6 fd 7e 00 b7 c8 fd 35 + 00 3a e2 52 32 73 ca c9 dd e5 dd 21 00 00 dd 39 + 3a 73 ca b7 28 4c 21 74 ca 36 00 3a de 52 fd 21 + 07 c6 fd 96 00 30 03 fd 35 00 fd 21 73 ca fd 35 + 00 fd 7e 00 b7 c2 d0 58 3a 08 c6 f5 33 2a 39 ca + e5 2a 37 ca e5 cd 78 54 f1 f1 33 af 57 1e 01 d5 + 11 0b 01 d5 cd 96 30 f1 f1 3a e1 52 32 71 ca c3 + d0 58 3a 71 ca b7 28 3c 21 74 ca 36 00 fd 21 71 + ca fd 35 00 fd 7e 00 b7 20 0f 11 01 01 d5 11 0b + 01 d5 cd 96 30 f1 f1 18 2c fd 21 72 ca fd 34 00 + fd 7e 00 d6 04 20 1e fd 36 00 00 01 9c c4 0a ee + 01 02 18 11 fd 21 74 ca fd 7e 00 b7 28 07 fd 36 + 00 00 cd 4a 55 af fd 21 6e ca fd 96 00 e2 42 56 + ee 80 f2 4b 56 21 6e ca 35 18 0d fd 21 6e ca fd + cb 00 7e 28 03 fd 34 00 af fd 21 6f ca fd 96 00 + e2 65 56 ee 80 f2 6e 56 21 6f ca 35 18 0d fd 21 + 6f ca fd cb 00 7e 28 03 fd 34 00 dd cb 04 46 ca + 4c 57 3a 00 81 0f 30 18 21 d9 52 4e 3a 6e ca 91 + e2 95 56 ee 80 f2 a0 56 3a da 52 21 6e ca 86 77 + 3a 00 81 cb 4f 28 2b 3a d9 52 4f 17 9f 47 af 91 + 4f 3e 00 98 47 3a 6e ca 5f 17 9f 57 79 93 78 9a + e2 c5 56 ee 80 f2 d2 56 21 da 52 4e 21 6e ca 7e + 91 77 3a 00 81 cb 57 28 18 21 d9 52 4e 3a 6f ca + 91 e2 e6 56 ee 80 f2 f1 56 3a da 52 21 6f ca 86 + 77 3a 00 81 cb 5f 28 2b 3a d9 52 4f 17 9f 47 af + 91 4f 3e 00 98 47 3a 6f ca 5f 17 9f 57 79 93 78 + 9a e2 16 57 ee 80 f2 23 57 21 da 52 4e 21 6f ca + 7e 91 77 3a 00 81 cb 67 28 13 21 df 52 4e fd 21 + 07 c6 fd 7e 00 91 30 14 fd 34 00 18 0f 3a de 52 + fd 21 07 c6 fd 96 00 30 03 fd 35 00 3a 6e ca ee + 80 d6 7e 30 05 01 22 00 18 19 3e 02 fd 21 6e ca + fd 96 00 e2 68 57 ee 80 f2 70 57 01 23 00 18 03 + 01 20 00 21 fc c4 71 3a 6e ca 4f 17 9f 47 2a fb + c5 09 22 fb c5 3a 6f ca 4f 17 9f 47 2a fd c5 09 + 22 fd c5 dd cb 04 46 ca 44 58 21 ff c5 fd 21 fb + c5 fd 7e 00 96 fd 7e 01 23 9e 30 16 2a ff c5 22 + fb c5 fd 21 6e ca fd cb 00 7e 28 33 fd 36 00 00 + 18 2d 21 01 c6 7e fd 21 fb c5 fd 96 00 23 7e fd + 9e 01 30 1b 2a 01 c6 22 fb c5 af fd 21 6e ca fd + 96 00 e2 e7 57 ee 80 f2 ef 57 21 6e ca 36 00 21 + 03 c6 fd 21 fd c5 fd 7e 00 96 fd 7e 01 23 9e 30 + 16 2a 03 c6 22 fd c5 fd 21 6f ca fd cb 00 7e 28 + 33 fd 36 00 00 18 2d 21 05 c6 7e fd 21 fd c5 fd + 96 00 23 7e fd 9e 01 30 1b 2a 05 c6 22 fd c5 af + fd 21 6f ca fd 96 00 e2 3c 58 ee 80 f2 44 58 21 + 6f ca 36 00 21 96 3b 4e 06 00 c5 2a fd c5 e5 cd + ef 5b f1 f1 4d 44 21 95 3b 5e 16 00 c5 d5 2a fb + c5 e5 cd ef 5b f1 e3 3e 0b f5 33 cd 7b 2f f1 f1 + 33 fd 21 70 ca fd 35 00 af fd 96 00 e2 81 58 ee + 80 fa d0 58 21 07 c6 4e 06 00 69 60 cb 78 28 04 + 21 07 00 09 cb 2c cb 1d cb 2c cb 1d cb 2c cb 1d + e5 3e 06 f5 33 af f5 33 cd 3c 32 f1 7d e1 85 4f + 3a db 52 21 70 ca 91 77 af fd 21 70 ca fd 96 00 + e2 c5 58 ee 80 fa cd 58 21 70 ca 36 00 cd 27 59 + dd e1 c9 21 96 3b 4e 59 16 00 6b 62 29 29 29 29 + 19 29 29 29 29 22 5b c6 3a 95 3b 87 87 32 5d c6 + 79 87 81 87 87 32 5e c6 01 00 00 21 77 ca 5e 16 + 00 79 93 78 9a e2 0a 59 ee 80 f0 51 c5 af 47 0e + 02 c5 3e 01 f5 33 d5 33 cd 96 30 f1 f1 c1 21 91 + c4 09 36 00 03 18 d4 dd e5 dd 21 00 00 dd 39 f5 + f5 0e 00 1e 00 21 77 ca 7b 96 d2 1d 5a 21 51 c6 + 16 00 19 7e b7 c2 18 5a 21 07 c6 5e 16 00 6b 62 + cb 7a 28 04 21 07 00 19 cb 2c cb 1d cb 2c cb 1d + cb 2c cb 1d 7d c6 03 47 3e 3d 81 5f 3e c6 ce 00 + 57 af 90 c5 d5 c5 33 f5 33 cd 95 32 f1 7d d1 c1 + 12 21 47 c6 06 00 09 fd 21 dc 52 fd 46 00 70 69 + 26 00 29 dd 75 fe dd 74 ff 3e 15 dd 86 fe dd 77 + fc 3e c6 dd 8e ff dd 77 fd 21 5d c6 5e 16 00 2a + fb c5 19 eb e1 e5 73 23 72 3e 29 dd 86 fe dd 77 + fc 3e c6 dd 8e ff dd 77 fd 21 5e c6 5e 16 00 2a + fd c5 19 dd 75 fe dd 74 ff 58 16 00 fd 21 07 c6 + fd 6e 00 26 00 19 dd 7e fe 95 5f dd 7e ff 9c 57 + e1 e5 73 23 72 21 51 c6 06 00 09 3a dd 52 77 c5 + af 57 1e 02 d5 06 01 c5 cd 96 30 f1 f1 c1 21 f1 + c4 06 00 09 36 00 18 05 1c 4b c3 35 59 dd f9 dd + e1 c9 dd e5 dd 21 00 00 dd 39 21 f4 ff 39 f9 af + dd 77 ff 21 77 ca dd 7e ff 96 d2 ea 5b 3e 51 dd + 86 ff dd 77 fb 3e c6 ce 00 dd 77 fc dd 6e fb dd + 66 fc 7e dd 77 fe b7 ca e4 5b dd 7e ff dd 77 f4 + dd 6e ff 26 00 29 4d 44 21 29 c6 09 dd 75 f5 dd + 74 f6 7e dd 77 fd 23 7e dd 77 fe 3e 47 dd 86 ff + 5f 3e c6 ce 00 57 1a 5f 17 9f 57 fd 21 07 c6 fd + 6e 00 26 00 19 dd 5e fd dd 56 fe 19 eb dd 6e f5 + dd 66 f6 73 23 72 21 5b c6 7e 93 23 7e 9a 30 18 + 3e 91 dd 86 ff 4f 3e c4 ce 00 47 af 02 dd 6e fb + dd 66 fc 36 00 c3 e4 5b dd 6e fb dd 66 fc 7e 3d + dd 6e fb dd 66 fc 77 b7 20 2c 3e f1 dd 86 ff 6f + 3e c4 ce 00 67 5e 1c 73 3e 03 93 30 0f 3e 91 dd + 86 ff 5f 3e c4 ce 00 57 af 12 18 0a 3a dd 52 dd + 6e fb dd 66 fc 77 21 15 c6 09 dd 75 f7 dd 74 f8 + 7e dd 77 fb 23 7e dd 77 fc 3e 3d dd 86 ff dd 77 + fd 3e c6 ce 00 dd 77 fe dd 6e fd dd 66 fe 7e dd + 77 fe dd 77 fd 17 9f dd 77 fe dd 7e fb dd 77 f9 + dd 7e fc dd 77 fa dd 7e fd dd 77 fb dd 7e fe dd + 77 fc dd 7e fb dd 86 f9 dd 77 fd dd 7e fc dd 8e + fa dd 77 fe dd 6e f7 dd 66 f8 dd 7e fd 77 23 dd + 7e fe 77 dd 6e f5 dd 66 f6 7e dd 77 fb 23 7e dd + 77 fc 3a 96 3b dd 77 fa dd 77 f9 af dd 77 fa dd + 6e f9 dd 66 fa e5 dd 6e fb dd 66 fc e5 cd ef 5b + f1 f1 dd 75 f9 dd 74 fa 3a 95 3b dd 77 fb af dd + 77 fc dd 6e fb dd 66 fc e5 dd 6e fd dd 66 fe e5 + cd ef 5b f1 f1 dd 75 fd dd 74 fe dd 6e f9 dd 66 + fa e5 dd 6e fd dd 66 fe e5 dd 7e f4 f5 33 cd 7b + 2f f1 f1 33 dd 34 ff c3 33 5a dd f9 dd e1 c9 f1 + e1 d1 d5 e5 f5 18 0a 21 03 00 39 5e 2b 6e 26 00 + 54 7b e6 80 b2 20 10 06 10 ed 6a 17 93 30 01 83 + 3f ed 6a 10 f6 5f c9 06 09 7d 6c 26 00 cb 1d ed + 6a ed 52 30 01 19 3f 17 10 f5 cb 10 50 5f eb c9 + dd e5 dd 21 00 00 dd 39 21 f8 ff 39 f9 fd 21 78 + ca fd 5e 00 fd 56 01 fd 6e 02 fd 66 03 dd 72 f8 + dd 75 f9 dd 74 fa af dd 77 fb 06 02 dd cb fa 3e + dd cb f9 1e dd cb f8 1e 10 f2 7b dd ae f8 dd 77 + fc 7a dd ae f9 dd 77 fd 7d dd ae fa dd 77 fe 7c + dd ae fb dd 77 ff dd 46 fc dd 6e fd dd 66 fe 0e + 00 cb 20 ed 6a dd 7e fc a9 5f dd 7e fd a8 57 dd + 7e fe ad 6f dd 7e ff ac 67 dd 74 f8 af dd 77 f9 + dd 77 fa dd 77 fb dd cb f8 3e 7b dd ae f8 dd 77 + fc 7a dd ae f9 dd 77 fd 7d dd ae fa dd 77 fe 7c + dd ae fb dd 77 ff 11 78 ca 21 04 00 39 01 04 00 + ed b0 dd 6e fc dd 66 fd cb bc dd f9 dd e1 c9 21 + 02 00 39 4e 23 46 1e 00 af fd 21 78 ca fd 71 00 + fd 70 01 fd 73 02 f6 80 32 7b ca c9 e1 d1 d5 e5 + af 6f 67 ed 52 f0 eb c9 f1 c1 d1 d5 c5 f5 af 6f + b0 06 10 20 04 06 08 79 29 cb 11 17 30 01 19 10 + f7 c9 dd e5 dd 21 00 00 dd 39 dd 6e 05 dd 66 06 + 4e 23 46 2b 59 50 13 73 23 72 dd 7e 04 02 dd e1 + c9 21 02 00 39 fd 21 06 00 fd 39 fd 4e 00 fd 46 + 01 c5 fd 2b fd 2b fd 4e 00 fd 46 01 c5 e5 21 32 + 5d e5 cd 65 5f f1 f1 f1 f1 4d 44 d1 e1 e5 d5 36 + 00 69 60 c9 dd e5 dd 21 00 00 dd 39 21 08 00 39 + eb 21 04 00 39 d5 dd 4e 06 dd 46 07 c5 e5 21 32 + 5d e5 cd 65 5f f1 f1 f1 f1 4d 44 dd 5e 04 dd 56 + 05 af 12 69 60 dd e1 c9 c1 e1 e5 c5 af 47 4f ed + b1 21 ff ff ed 42 c9 21 03 00 39 5e 2b 6e cd 07 + 5e c3 35 5e f1 e1 d1 d5 e5 f5 cd 0f 5e c3 35 5e + 21 03 00 39 5e 2b 6e cd fe 5b eb c9 f1 e1 d1 d5 + e5 f5 cd 01 5c eb c9 f1 e1 d1 d5 e5 f5 c3 0f 5e + 21 03 00 39 5e 2b 6e 7d 07 9f 67 7b 07 9f 57 7c + aa 17 7c f5 17 30 06 97 95 6f 9f 94 67 cb 7a 28 + 06 97 93 5f 9f 92 57 cd 01 5c f1 d0 47 97 95 6f + 9f 94 67 78 c9 17 eb d0 97 95 6f 9f 94 67 c9 fd + 21 02 00 fd 39 fd 7e 00 c6 30 47 3e 39 90 30 10 + 78 c6 07 47 fd 23 fd cb 00 46 28 04 78 c6 20 47 + fd 21 06 00 fd 39 fd 6e 00 fd 66 01 e5 c5 33 fd + 2b fd 2b fd 6e 00 fd 66 01 cd d5 6a f1 33 c9 dd + e5 dd 21 00 00 dd 39 dd 46 04 cb 38 cb 38 cb 38 + cb 38 dd 6e 08 dd 66 09 e5 dd 6e 06 dd 66 07 e5 + dd 7e 05 f5 33 c5 33 cd 3f 5e 21 06 00 39 f9 dd + 7e 04 e6 0f 47 dd 6e 08 dd 66 09 e5 dd 6e 06 dd + 66 07 e5 dd 7e 05 f5 33 c5 33 cd 3f 5e 21 06 00 + 39 f9 dd e1 c9 dd e5 dd 21 00 00 dd 39 21 f9 ff + 39 f9 dd 5e 04 dd 56 05 d5 21 05 00 39 eb 01 04 + 00 ed b0 d1 21 04 00 19 4d 44 dd 36 fa 20 0a 87 + dd 77 f9 dd 7e ff cb 07 e6 01 dd 77 fb dd 7e f9 + dd b6 fb dd 77 fb 02 dd cb fc 26 dd cb fd 16 dd + cb fe 16 dd cb ff 16 dd 7e fb dd 96 06 38 1f 0a + dd 96 06 02 dd 7e fc f6 01 dd 77 fc dd 7e fd dd + 77 fd dd 7e fe dd 77 fe dd 7e ff dd 77 ff dd 35 + fa dd 7e fa b7 20 a7 21 03 00 39 01 04 00 ed b0 + dd f9 dd e1 c9 dd e5 dd 21 00 00 dd 39 21 cd ff + 39 f9 af dd 77 fa dd 77 fb 21 08 00 39 dd 75 e0 + dd 74 e1 21 12 00 39 dd 75 e2 dd 74 e3 21 08 00 + 39 dd 75 e4 dd 74 e5 dd 7e e4 c6 04 dd 77 e6 dd + 7e e5 ce 00 dd 77 e7 dd 7e e6 dd 77 e8 dd 7e e7 + dd 77 e9 dd 7e e6 dd 77 ea dd 7e e7 dd 77 eb dd + 6e 08 dd 66 09 5e 23 dd 75 08 dd 74 09 dd 73 ff + 7b b7 ca bf 6a dd 7e ff d6 25 c2 9c 6a af dd 77 + ec af dd 77 ed af dd 77 ee af dd 77 ef af dd 77 + f0 af dd 77 f1 af dd 77 f2 af dd 77 f3 af dd 77 + f4 af dd 77 fc dd 77 fd dd 36 f5 ff dd 36 f6 ff + dd 7e 08 dd 77 f8 dd 7e 09 dd 77 f9 dd 6e f8 dd + 66 f9 7e dd 77 ff dd 34 f8 20 03 dd 34 f9 dd 7e + f8 dd 77 08 dd 7e f9 dd 77 09 dd 7e ff d6 25 20 + 23 dd 6e 06 dd 66 07 e5 dd 7e ff f5 33 dd 6e 04 + dd 66 05 cd d5 6a f1 33 dd 34 fa c2 bf 5f dd 34 + fb c3 bf 5f dd 7e ff d6 30 38 73 3e 39 dd 96 ff + 38 6c dd 7e f5 dd a6 f6 3c 20 42 dd 4e fc dd 46 + fd 69 60 29 29 09 29 dd 75 d3 dd 74 d4 dd 7e ff + dd 77 fe af dd 77 ff dd 4e fe dd 46 ff dd 6e d3 + dd 66 d4 09 7d c6 d0 dd 77 fc 7c ce ff dd 77 fd + dd b6 fc c2 1c 60 dd 36 ed 01 c3 1c 60 dd 4e f5 + dd 46 f6 69 60 29 29 09 29 dd 4e ff 06 00 09 7d + c6 d0 dd 77 f5 7c ce ff dd 77 f6 c3 1c 60 dd 7e + ff d6 2e 20 14 dd 7e f5 dd a6 f6 3c c2 1c 60 af + dd 77 f5 dd 77 f6 c3 1c 60 dd 7e ff d6 61 38 15 + 3e 7a dd 96 ff 38 0e dd 7e ff e6 df dd 77 ff dd + 36 f7 01 18 04 af dd 77 f7 dd 7e ff d6 20 ca b8 + 61 dd 7e ff d6 2b ca b1 61 dd 7e ff d6 2d 28 7a + dd 7e ff d6 42 ca bf 61 dd 7e ff d6 43 ca cd 61 + dd 7e ff d6 44 ca 2b 64 dd 7e ff d6 46 ca 47 64 + dd 7e ff d6 48 ca 1c 60 dd 7e ff d6 49 ca 2b 64 + dd 7e ff d6 4a ca 1c 60 dd 7e ff d6 4c 28 57 dd + 7e ff d6 4f ca 35 64 dd 7e ff d6 50 ca 82 63 dd + 7e ff d6 53 ca 15 62 dd 7e ff d6 54 ca 1c 60 dd + 7e ff d6 55 ca 3b 64 dd 7e ff d6 58 ca 41 64 dd + 7e ff d6 5a ca 1c 60 c3 4d 64 dd 36 ec 01 c3 1c + 60 dd 36 ee 01 c3 1c 60 dd 36 ef 01 c3 1c 60 dd + 36 f1 01 c3 1c 60 dd 36 f2 01 c3 1c 60 dd cb f1 + 46 28 11 dd 6e 0a dd 66 0b 23 dd 75 0a dd 74 0b + 2b 46 18 11 dd 6e 0a dd 66 0b 23 23 dd 75 0a dd + 74 0b 2b 2b 46 dd 6e 06 dd 66 07 e5 c5 33 dd 6e + 04 dd 66 05 cd d5 6a f1 33 dd 34 fa c2 7a 64 dd + 34 fb c3 7a 64 21 08 00 39 dd 75 f8 dd 74 f9 dd + 6e 0a dd 66 0b 23 23 dd 75 0a dd 74 0b 2b 2b 4e + 23 46 dd 6e f8 dd 66 f9 71 23 70 c5 cd b8 5d f1 + 4d 44 dd 7e f5 dd a6 f6 3c 20 06 dd 71 f5 dd 70 + f6 dd cb ec 46 20 67 79 dd 96 fc 78 dd 9e fd 30 + 5d dd 7e fc 91 dd 77 fe dd 7e fd 98 dd 77 ff dd + 5e fa dd 56 fb dd 6e fe dd 66 ff dd 7e fe c6 ff + dd 77 fe dd 7e ff ce ff dd 77 ff 7c b5 28 1d c5 + d5 dd 6e 06 dd 66 07 e5 3e 20 f5 33 dd 6e 04 dd + 66 05 cd d5 6a f1 33 d1 c1 13 18 c9 dd 73 fa dd + 72 fb dd 7e fe dd 77 fc dd 7e ff dd 77 fd dd 7e + f5 dd 77 fe dd 7e f6 dd 77 ff dd 5e fa dd 56 fb + dd 6e f8 dd 66 f9 7e 23 66 6f 7e dd 77 fb b7 28 + 5a af dd be fe dd 9e ff e2 ed 62 ee 80 f2 3b 63 + dd 6e fe dd 66 ff 2b dd 75 fe dd 74 ff c5 d5 dd + 6e 06 dd 66 07 e5 dd 7e fb f5 33 dd 6e 04 dd 66 + 05 cd d5 6a f1 33 d1 c1 13 dd 6e f8 dd 66 f9 7e + 23 66 6f 23 dd 75 fa dd 74 fb dd 6e f8 dd 66 f9 + dd 7e fa 77 23 dd 7e fb 77 18 95 dd 73 fa dd 72 + fb dd cb ec 46 ca 7a 64 79 dd 96 fc 78 dd 9e fd + d2 7a 64 dd 7e fc 91 4f dd 7e fd 98 47 69 60 0b + 7c b5 ca 6e 64 c5 d5 dd 6e 06 dd 66 07 e5 3e 20 + f5 33 dd 6e 04 dd 66 05 cd d5 6a f1 33 d1 c1 13 + 18 db 21 08 00 39 eb dd 6e 0a dd 66 0b 23 23 dd + 75 0a dd 74 0b 2b 2b 4e 23 46 79 12 13 78 12 dd + 6e 06 dd 66 07 e5 3e 30 f5 33 dd 6e 04 dd 66 05 + cd d5 6a f1 33 dd 4e fa dd 46 fb 03 c5 dd 6e 06 + dd 66 07 e5 3e 78 f5 33 dd 6e 04 dd 66 05 cd d5 + 6a f1 33 c1 03 21 09 00 39 56 c5 dd 6e 06 dd 66 + 07 e5 dd 6e 04 dd 66 05 e5 dd 7e f7 f5 33 d5 33 + cd 7f 5e 21 06 00 39 f9 c1 03 03 dd 6e e0 dd 66 + e1 56 c5 dd 6e 06 dd 66 07 e5 dd 6e 04 dd 66 05 + e5 dd 7e f7 f5 33 d5 33 cd 7f 5e 21 06 00 39 f9 + c1 03 03 dd 71 fa dd 70 fb 18 4f dd 36 f0 01 dd + 36 f4 0a 18 45 dd 36 f4 08 18 3f dd 36 f4 0a 18 + 39 dd 36 f4 10 18 33 dd 36 f3 01 18 2d dd 6e 06 + dd 66 07 e5 dd 7e ff f5 33 dd 6e 04 dd 66 05 cd + d5 6a f1 33 dd 34 fa 20 11 dd 34 fb 18 0c dd 73 + fa dd 72 fb dd 71 fc dd 70 fd dd cb f3 46 ca 36 + 65 21 08 00 39 dd 75 f8 dd 74 f9 dd 7e 0a c6 04 + dd 77 fc dd 7e 0b ce 00 dd 77 fd dd 7e fc dd 77 + 0a dd 7e fd dd 77 0b dd 7e fc c6 fc dd 77 fe dd + 7e fd ce ff dd 77 ff dd 5e fe dd 56 ff 21 2f 00 + 39 eb 01 04 00 ed b0 dd 5e f8 dd 56 f9 21 2f 00 + 39 01 04 00 ed b0 21 08 00 39 dd 75 fc dd 74 fd + 36 ca 23 36 6a dd 7e fa dd 77 fe dd 7e fb dd 77 + ff dd 6e fc dd 66 fd 4e 23 46 59 50 13 dd 6e fc + dd 66 fd 73 23 72 0a 47 b7 ca bf 5f dd 6e 06 dd + 66 07 e5 c5 33 dd 6e 04 dd 66 05 cd d5 6a f1 33 + dd 34 fe 20 03 dd 34 ff dd 7e fe dd 77 fa dd 7e + ff dd 77 fb 18 bb dd 7e f4 b7 ca bf 5f dd 7e e2 + dd 77 f8 dd 7e e3 dd 77 f9 dd cb f1 46 ca d8 65 + 21 08 00 39 dd 75 fe dd 74 ff dd 7e 0a c6 01 dd + 77 f5 dd 7e 0b ce 00 dd 77 f6 dd 7e f5 dd 77 0a + dd 7e f6 dd 77 0b dd 6e f5 dd 66 f6 2b 7e dd 77 + f6 dd 77 d1 af dd 77 d2 dd 77 d3 dd 77 d4 dd 5e + fe dd 56 ff 21 04 00 39 01 04 00 ed b0 dd cb f0 + 46 c2 d7 66 dd 5e fe dd 56 ff 21 00 00 39 eb 01 + 04 00 ed b0 dd 7e cd dd 77 d1 dd 36 d2 00 dd 36 + d3 00 dd 36 d4 00 dd 5e fe dd 56 ff 21 04 00 39 + 01 04 00 ed b0 c3 d7 66 dd cb f2 46 28 58 21 08 + 00 39 dd 75 f5 dd 74 f6 dd 7e 0a c6 04 dd 77 f2 + dd 7e 0b ce 00 dd 77 f3 dd 7e f2 dd 77 0a dd 7e + f3 dd 77 0b dd 7e f2 c6 fc dd 77 fe dd 7e f3 ce + ff dd 77 ff dd 5e fe dd 56 ff 21 04 00 39 eb 01 + 04 00 ed b0 dd 5e f5 dd 56 f6 21 04 00 39 01 04 + 00 ed b0 c3 d7 66 21 08 00 39 dd 75 fe dd 74 ff + dd 7e 0a c6 02 dd 77 f2 dd 7e 0b ce 00 dd 77 f3 + dd 7e f2 dd 77 0a dd 7e f3 dd 77 0b dd 7e f2 c6 + fe dd 77 f5 dd 7e f3 ce ff dd 77 f6 dd 6e f5 dd + 66 f6 7e dd 77 f5 23 7e dd 77 f6 dd 7e f5 dd 77 + d1 dd 7e f6 dd 77 d2 17 9f dd 77 d3 dd 77 d4 dd + 5e fe dd 56 ff 21 04 00 39 01 04 00 ed b0 dd cb + f0 46 20 33 dd 5e fe dd 56 ff 21 00 00 39 eb 01 + 04 00 ed b0 dd 7e cd dd 77 d1 dd 7e ce dd 77 d2 + dd 36 d3 00 dd 36 d4 00 dd 5e fe dd 56 ff 21 04 + 00 39 01 04 00 ed b0 dd cb f0 46 28 5f 21 08 00 + 39 dd 75 fe dd 74 ff eb 21 04 00 39 eb 01 04 00 + ed b0 dd cb d4 7e 28 40 dd 5e fe dd 56 ff 21 00 + 00 39 eb 01 04 00 ed b0 af dd 96 cd dd 77 d1 3e + 00 dd 9e ce dd 77 d2 3e 00 dd 9e cf dd 77 d3 3e + 00 dd 9e d0 dd 77 d4 dd 5e fe dd 56 ff 21 04 00 + 39 01 04 00 ed b0 18 04 af dd 77 f0 dd 36 ff 01 + dd 4e f8 dd 46 f9 af dd 77 f8 dd 77 f9 21 0c 00 + 39 36 00 dd 5e e4 dd 56 e5 c5 dd 7e f4 f5 33 d5 + cd d5 5e f1 33 c1 dd cb ff 46 20 21 dd 6e e8 dd + 66 e9 7e 87 87 87 87 5f dd 6e e8 dd 66 e9 7e 07 + 07 07 07 e6 0f b3 5f 0a b3 02 0b 18 08 dd 6e e6 + dd 66 e7 7e 02 dd 34 f8 20 03 dd 34 f9 dd 7e ff + ee 01 dd 77 ff dd 6e e4 dd 66 e5 5e 23 56 23 23 + 7e 2b 6e b5 b2 b3 20 95 dd 71 f3 dd 70 f4 dd 7e + f8 dd 77 f5 dd 7e f9 dd 77 f6 dd 7e fd dd b6 fc + 20 08 dd 36 fc 01 af dd 77 fd dd cb ed 46 20 6c + dd cb ec 46 20 66 dd 7e fc dd 77 f8 dd 7e fd dd + 77 f9 dd 7e f5 dd 77 fe dd 34 fe dd 7e fe dd 77 + fd af dd 77 fe dd 7e fd dd 96 f8 dd 7e fe dd 9e + f9 30 2d dd 6e 06 dd 66 07 e5 3e 20 f5 33 dd 6e + 04 dd 66 05 cd d5 6a f1 33 dd 34 fa 20 03 dd 34 + fb dd 6e f8 dd 66 f9 2b dd 75 f8 dd 74 f9 18 b2 + dd 7e f8 dd 77 fc dd 7e f9 dd 77 fd dd cb f0 46 + 28 2d dd 6e 06 dd 66 07 e5 3e 2d f5 33 dd 6e 04 + dd 66 05 cd d5 6a f1 33 dd 34 fa 20 03 dd 34 fb + dd 6e fc dd 66 fd 2b dd 75 fc dd 74 fd 18 6c dd + 7e f6 dd b6 f5 28 64 dd cb ee 46 28 2d dd 6e 06 + dd 66 07 e5 3e 2b f5 33 dd 6e 04 dd 66 05 cd d5 + 6a f1 33 dd 34 fa 20 03 dd 34 fb dd 6e fc dd 66 + fd 2b dd 75 fc dd 74 fd 18 31 dd cb ef 46 28 2b dd 6e 06 dd 66 07 e5 3e 20 f5 33 dd 6e 04 dd 66 - 05 cd 32 3b f1 33 d1 c1 13 18 de dd 73 e6 dd 72 - e7 dd 70 db dd 46 f2 dd 5e e6 dd 56 e7 dd 6e d9 - dd 66 da 7e 23 66 6f 7e dd 77 dc b7 28 4a 68 05 - af 95 e2 97 33 ee 80 f2 d8 33 c5 d5 dd 6e 06 dd - 66 07 e5 dd 7e dc f5 33 dd 6e 04 dd 66 05 cd 32 - 3b f1 33 d1 c1 13 dd 6e d9 dd 66 da 7e 23 66 6f - 23 dd 75 de dd 74 df dd 6e d9 dd 66 da dd 7e de - 77 23 dd 7e df 77 18 a5 dd 73 e6 dd 72 e7 dd cb - fc 46 ca 09 35 79 dd 96 db d2 09 35 dd 7e db 91 - 4f 79 0d b7 ca 00 35 c5 d5 dd 6e 06 dd 66 07 e5 - 3e 20 f5 33 dd 6e 04 dd 66 05 cd 32 3b f1 33 d1 - c1 13 18 dd 21 06 00 39 eb dd 6e 0a dd 66 0b 23 - 23 dd 75 0a dd 74 0b 2b 2b 4e 23 46 79 12 13 78 - 12 dd 6e 06 dd 66 07 e5 3e 30 f5 33 dd 6e 04 dd - 66 05 cd 32 3b f1 33 dd 4e e6 dd 46 e7 03 c5 dd - 6e 06 dd 66 07 e5 3e 78 f5 33 dd 6e 04 dd 66 05 - cd 32 3b f1 33 c1 03 21 07 00 39 56 c5 dd 6e 06 - dd 66 07 e5 dd 6e 04 dd 66 05 e5 dd 7e fa f5 33 - d5 33 cd a7 2f 21 06 00 39 f9 c1 03 03 dd 6e e8 - dd 66 e9 56 c5 dd 6e 06 dd 66 07 e5 dd 6e 04 dd - 66 05 e5 dd 7e fa f5 33 d5 33 cd a7 2f 21 06 00 - 39 f9 c1 03 03 dd 71 e6 dd 70 e7 18 4c dd 36 ff - 01 dd 36 f3 0a 18 42 dd 36 f3 08 18 3c dd 36 f3 - 0a 18 36 dd 36 f3 10 18 30 dd 36 fb 01 18 2a dd - 6e 06 dd 66 07 e5 dd 7e dd f5 33 dd 6e 04 dd 66 - 05 cd 32 3b f1 33 dd 34 e6 20 0e dd 34 e7 18 09 - dd 73 e6 dd 72 e7 dd 71 db dd cb fb 46 ca c5 35 - 21 06 00 39 dd 75 de dd 74 df dd 7e 0a c6 04 dd - 77 d9 dd 7e 0b ce 00 dd 77 da dd 7e d9 dd 77 0a - dd 7e da dd 77 0b dd 7e d9 c6 fc dd 77 d9 dd 7e - da ce ff dd 77 da dd 5e d9 dd 56 da 21 1b 00 39 - eb 01 04 00 ed b0 dd 5e de dd 56 df 21 1b 00 39 - 01 04 00 ed b0 21 06 00 39 dd 75 e0 dd 74 e1 36 - e6 23 36 3a dd 7e e6 dd 77 de dd 7e e7 dd 77 df - dd 6e e0 dd 66 e1 4e 23 46 59 50 13 dd 6e e0 dd - 66 e1 73 23 72 0a 47 b7 ca e7 30 dd 6e 06 dd 66 - 07 e5 c5 33 dd 6e 04 dd 66 05 cd 32 3b f1 33 dd - 34 de 20 03 dd 34 df dd 7e de dd 77 e6 dd 7e df - dd 77 e7 18 bb dd 7e f3 b7 ca e7 30 dd 7e e4 dd - 77 e0 dd 7e e5 dd 77 e1 dd cb fe 46 ca 69 36 21 - 06 00 39 dd 75 de dd 74 df dd 7e 0a c6 01 dd 77 - d9 dd 7e 0b ce 00 dd 77 da dd 7e d9 dd 77 0a dd - 7e da dd 77 0b dd 6e d9 dd 66 da 2b 7e dd 77 dc - dd 77 ea dd 36 eb 00 dd 36 ec 00 dd 36 ed 00 dd - 5e de dd 56 df 21 25 00 39 01 04 00 ed b0 dd cb - ff 46 c2 74 37 dd 5e de dd 56 df 21 25 00 39 eb - 01 04 00 ed b0 dd 7e ea dd 77 ea dd 36 eb 00 dd - 36 ec 00 dd 36 ed 00 dd 5e de dd 56 df 21 25 00 - 39 01 04 00 ed b0 c3 74 37 dd cb fd 46 28 58 21 - 06 00 39 dd 75 ea dd 74 eb dd 7e 0a c6 04 dd 77 - de dd 7e 0b ce 00 dd 77 df dd 7e de dd 77 0a dd - 7e df dd 77 0b dd 7e de c6 fc dd 77 de dd 7e df - ce ff dd 77 df dd 5e de dd 56 df 21 29 00 39 eb - 01 04 00 ed b0 dd 5e ea dd 56 eb 21 29 00 39 01 - 04 00 ed b0 c3 74 37 21 06 00 39 dd 75 ee dd 74 - ef dd 7e 0a c6 02 dd 77 ea dd 7e 0b ce 00 dd 77 - eb dd 7e ea dd 77 0a dd 7e eb dd 77 0b dd 7e ea - c6 fe dd 77 ea dd 7e eb ce ff dd 77 eb dd 7e ea - dd 77 ea dd 7e eb dd 77 eb dd 6e ea dd 66 eb 7e - dd 77 ea 23 7e dd 77 eb dd 7e ea dd 77 ea dd 7e - eb dd 77 eb 17 9f dd 77 ec dd 77 ed dd 5e ee dd - 56 ef 21 25 00 39 01 04 00 ed b0 dd cb ff 46 20 - 33 dd 5e ee dd 56 ef 21 25 00 39 eb 01 04 00 ed - b0 dd 7e ea dd 77 ea dd 7e eb dd 77 eb dd 36 ec - 00 dd 36 ed 00 dd 5e ee dd 56 ef 21 25 00 39 01 - 04 00 ed b0 dd cb ff 46 28 5f 21 06 00 39 dd 75 - ee dd 74 ef eb 21 25 00 39 eb 01 04 00 ed b0 dd - cb ed 7e 28 40 dd 5e ee dd 56 ef 21 25 00 39 eb - 01 04 00 ed b0 af dd 96 ea dd 77 ea 3e 00 dd 9e - eb dd 77 eb 3e 00 dd 9e ec dd 77 ec 3e 00 dd 9e - ed dd 77 ed dd 5e ee dd 56 ef 21 25 00 39 01 04 - 00 ed b0 18 04 dd 36 ff 00 dd 36 f4 01 dd 4e e0 - dd 46 e1 dd 36 ee 00 21 0a 00 39 36 00 dd 5e d0 - dd 56 d1 c5 dd 7e f3 f5 33 d5 cd fc 2f f1 33 c1 - dd cb f4 46 20 23 dd 6e d2 dd 66 d3 7e 07 07 07 - 07 e6 f0 5f dd 6e d2 dd 66 d3 7e 07 07 07 07 e6 - 0f b3 5f 0a b3 02 0b 18 08 dd 6e d4 dd 66 d5 7e - 02 dd 34 ee dd 7e f4 ee 01 dd 77 f4 dd 6e d0 dd - 66 d1 5e 23 56 23 23 7e 2b 6e b5 b2 b3 20 98 dd - 71 ea dd 70 eb dd 7e ee dd 77 ee dd 7e db b7 20 - 04 dd 36 db 01 dd cb f9 46 20 5e dd cb fc 46 20 - 58 dd 7e e6 dd 77 e0 dd 7e e7 dd 77 e1 dd 7e db - dd 77 de dd 7e ee dd 77 dc dd 34 dc dd 7e dc dd - 96 de 30 23 dd 6e 06 dd 66 07 e5 3e 20 f5 33 dd - 6e 04 dd 66 05 cd 32 3b f1 33 dd 34 e0 20 03 dd - 34 e1 dd 35 de 18 cc dd 7e e0 dd 77 e6 dd 7e e1 - dd 77 e7 dd 7e de dd 77 db dd cb ff 46 28 23 dd - 6e 06 dd 66 07 e5 3e 2d f5 33 dd 6e 04 dd 66 05 - cd 32 3b f1 33 dd 34 e6 20 03 dd 34 e7 dd 35 db - 18 56 dd 7e ee b7 28 50 dd cb f8 46 28 23 dd 6e - 06 dd 66 07 e5 3e 2b f5 33 dd 6e 04 dd 66 05 cd - 32 3b f1 33 dd 34 e6 20 03 dd 34 e7 dd 35 db 18 - 27 dd cb f7 46 28 21 dd 6e 06 dd 66 07 e5 3e 20 - f5 33 dd 6e 04 dd 66 05 cd 32 3b f1 33 dd 34 e6 - 20 03 dd 34 e7 dd 35 db dd cb fc 46 20 57 dd 7e - e6 dd 77 e0 dd 7e e7 dd 77 e1 dd 7e db dd 77 de - dd 4e de dd 35 de dd 7e ee 91 30 52 dd cb f9 46 - 28 0a dd 36 d9 30 dd 36 da 00 18 08 dd 36 d9 20 - dd 36 da 00 dd 46 d9 dd 6e 06 dd 66 07 e5 c5 33 - dd 6e 04 dd 66 05 cd 32 3b f1 33 dd 34 e0 20 c0 - dd 34 e1 18 bb dd 7e ee dd 96 db 30 0b dd 7e db - dd 96 ee dd 77 dc 18 18 dd 36 dc 00 18 12 dd 7e - e0 dd 77 e6 dd 7e e1 dd 77 e7 dd 7e de dd 77 dc - dd 7e ea dd 77 ea dd 7e eb dd 77 eb dd 7e e6 dd - 77 e0 dd 7e e7 dd 77 e1 dd 7e ee dd 77 ee dd 4e - ee dd 35 ee 79 b7 28 6a dd 7e f4 ee 01 dd 77 f4 - dd cb f4 46 20 1e dd 34 ea 20 03 dd 34 eb dd 6e - ea dd 66 eb 7e 07 07 07 07 e6 0f dd 6e d4 dd 66 - d5 77 18 10 dd 6e ea dd 66 eb 7e e6 0f dd 6e d4 - dd 66 d5 77 dd 6e d7 dd 66 d8 46 dd 6e 06 dd 66 - 07 e5 dd 6e 04 dd 66 05 e5 dd 7e fa f5 33 c5 33 - cd 71 2f 21 06 00 39 f9 dd 34 e0 20 91 dd 34 e1 - 18 8c dd 7e e0 dd 77 e6 dd 7e e1 dd 77 e7 dd cb - fc 46 ca e7 30 dd 7e e0 dd 77 f5 dd 7e e1 dd 77 - f6 dd 4e dc 79 0d b7 ca e7 30 c5 dd 6e 06 dd 66 - 07 e5 3e 20 f5 33 dd 6e 04 dd 66 05 cd 32 3b f1 - 33 c1 dd 34 f5 20 03 dd 34 f6 dd 7e f5 dd 77 e6 - dd 7e f6 dd 77 e7 18 cc dd 6e 06 dd 66 07 e5 dd - 7e d6 f5 33 dd 6e 04 dd 66 05 cd 32 3b f1 33 dd - 34 e6 c2 e7 30 dd 34 e7 c3 e7 30 dd 6e e6 dd 66 - e7 dd f9 dd e1 c9 3c 4e 4f 20 46 4c 4f 41 54 3e - 00 f1 e1 d1 d5 e5 f5 18 0a 21 03 00 39 5e 2b 6e - 26 00 54 7b e6 80 b2 20 10 06 10 ed 6a 17 93 30 - 01 83 3f ed 6a 10 f6 5f c9 06 09 7d 6c 26 00 cb - 1d ed 6a ed 52 30 01 19 3f 17 10 f5 cb 10 50 5f - eb c9 e9 00 00 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 00 c2 60 00 00 00 00 00 00 00 00 00 00 00 00 51 - 71 21 31 00 00 00 00 00 00 5a 7a 53 73 41 61 57 - 77 22 32 00 00 00 00 43 63 58 78 44 64 45 65 24 - 34 c2 33 00 00 00 00 20 20 56 76 46 66 54 74 52 - 72 25 35 00 00 00 00 4e 6e 42 62 48 68 47 67 59 - 79 5e 36 00 00 00 00 00 00 4d 6d 4a 6a 55 75 26 - 37 2a 38 00 00 00 00 3c 2c 4b 6b 49 69 4f 6f 29 - 30 28 39 00 00 00 00 3e 2e 3f 2f 4c 6c 3a 3b 50 - 70 5f 2d 00 00 00 00 00 00 40 27 00 00 7b 5b 2b - 3d 00 00 00 00 2b 3d 00 00 0a 0a 7d 5d 00 00 7c - 5c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 00 08 08 00 00 00 00 00 00 00 00 00 00 00 00 00 + 05 cd d5 6a f1 33 dd 34 fa 20 03 dd 34 fb dd 6e + fc dd 66 fd 2b dd 75 fc dd 74 fd dd cb ec 46 20 + 62 dd 7e fc dd 77 f8 dd 7e fd dd 77 f9 dd 4e f8 + dd 46 f9 dd 6e f8 dd 66 f9 2b dd 75 f8 dd 74 f9 + dd 7e f5 91 dd 7e f6 98 30 62 dd cb ed 46 28 0a + dd 36 fd 30 af dd 77 fe 18 08 dd 36 fd 20 af dd + 77 fe dd 46 fd dd 6e 06 dd 66 07 e5 c5 33 dd 6e + 04 dd 66 05 cd d5 6a f1 33 dd 34 fa 20 af dd 34 + fb 18 aa dd 7e f5 dd 96 fc dd 7e f6 dd 9e fd 30 + 14 dd 7e fc dd 96 f5 dd 77 f8 dd 7e fd dd 9e f6 + dd 77 f9 18 07 af dd 77 f8 dd 77 f9 dd 7e f3 dd + 77 fd dd 7e f4 dd 77 fe dd 7e fa dd 77 f3 dd 7e + fb dd 77 f4 dd 7e f5 dd 77 fb dd 7e f6 dd 77 fc + dd 7e fb dd 77 f5 dd 7e fc dd 77 f6 dd 6e fb dd + 66 fc 2b dd 75 fb dd 74 fc dd 7e f6 dd b6 f5 28 + 6c dd 7e ff ee 01 dd 77 ff dd cb ff 46 20 1e dd + 34 fd 20 03 dd 34 fe dd 6e fd dd 66 fe 7e 07 07 + 07 07 e6 0f dd 6e e6 dd 66 e7 77 18 10 dd 6e fd + dd 66 fe 7e e6 0f dd 6e e6 dd 66 e7 77 dd 6e ea + dd 66 eb 46 dd 6e 06 dd 66 07 e5 dd 6e 04 dd 66 + 05 e5 dd 7e f7 f5 33 c5 33 cd 3f 5e 21 06 00 39 + f9 dd 34 f3 c2 a0 69 dd 34 f4 c3 a0 69 dd 7e f3 + dd 77 fa dd 7e f4 dd 77 fb dd cb ec 46 ca bf 5f + dd 7e f3 dd 77 fe dd 7e f4 dd 77 ff dd 7e f8 dd + 77 fc dd 7e f9 dd 77 fd dd 4e fc dd 46 fd dd 6e + fc dd 66 fd 2b dd 75 fc dd 74 fd 78 b1 ca bf 5f + dd 6e 06 dd 66 07 e5 3e 20 f5 33 dd 6e 04 dd 66 + 05 cd d5 6a f1 33 dd 34 fe 20 03 dd 34 ff dd 7e + fe dd 77 fa dd 7e ff dd 77 fb 18 bc dd 6e 06 dd + 66 07 e5 dd 7e ff f5 33 dd 6e 04 dd 66 05 cd d5 + 6a f1 33 dd 34 fa c2 bf 5f dd 34 fb c3 bf 5f dd + 6e fa dd 66 fb dd f9 dd e1 c9 3c 4e 4f 20 46 4c + 4f 41 54 3e 00 e9 dd e5 dd 21 00 00 dd 39 21 ec + ff 39 f9 21 00 00 39 eb 21 18 00 39 01 04 00 ed + b0 21 04 00 39 eb 21 1c 00 39 01 04 00 ed b0 21 + 00 00 39 4e 23 46 23 7e 23 b6 b0 b1 28 10 21 04 + 00 39 7e 23 4e 23 5e 23 46 b0 b3 b1 20 08 21 00 + 00 5d 54 c3 96 6e 21 00 00 39 4e 23 46 23 5e 23 + 7e cb 07 e6 01 dd 77 ff 21 04 00 39 4e 23 46 23 + 5e 23 7e cb 07 e6 01 dd ae ff 4f 21 00 00 39 5e + 23 56 23 23 7e 2b 6e 67 06 17 cb 3c cb 1d cb 1a + cb 1b 10 f6 7b 06 00 c6 82 dd 77 fe 78 ce ff dd + 77 ff 21 04 00 39 5e 23 56 23 23 7e 2b 6e 67 06 + 17 cb 3c cb 1d cb 1a cb 1b 10 f6 16 00 dd 6e fe + dd 66 ff 19 dd 75 fe dd 74 ff 21 00 00 39 dd 75 + f4 dd 74 f5 21 00 00 39 5e 23 56 23 7e 23 46 6f + cb bd 26 00 dd 73 f6 dd 72 f7 7d f6 80 dd 77 f8 + dd 74 f9 c5 dd 5e f4 dd 56 f5 21 0c 00 39 01 04 + 00 ed b0 c1 21 04 00 39 dd 75 f4 dd 74 f5 21 04 + 00 39 5e 23 56 23 7e 23 46 6f cb bd 26 00 dd 73 + f6 dd 72 f7 7d f6 80 dd 77 f8 dd 74 f9 c5 dd 5e + f4 dd 56 f5 21 0c 00 39 01 04 00 ed b0 c1 21 00 + 00 39 5e 23 56 23 23 7e 2b 66 dd 72 f6 dd 74 f7 + af dd 77 f8 dd 77 f9 21 04 00 39 5e 23 56 23 23 + 7e 2b 66 6a 11 00 00 c5 d5 e5 dd 6e f8 dd 66 f9 + e5 dd 6e f6 dd 66 f7 e5 cd fb 6f f1 f1 f1 f1 c1 + dd 75 fa dd 74 fb dd 73 fc dd 72 fd 21 00 00 39 + 5e 23 56 23 7e 23 46 16 00 dd 73 f6 dd 72 f7 af + dd 77 f8 dd 77 f9 21 04 00 39 5e 23 56 23 23 7e + 2b 66 6a 11 00 00 c5 d5 e5 dd 6e f8 dd 66 f9 e5 + dd 6e f6 dd 66 f7 e5 cd fb 6f f1 f1 f1 f1 c1 dd + 74 f6 dd 73 f7 dd 72 f8 af dd 77 f9 dd 7e fa dd + 86 f6 dd 77 fa dd 7e fb dd 8e f7 dd 77 fb dd 7e + fc dd 8e f8 dd 77 fc dd 7e fd dd 8e f9 dd 77 fd + 21 04 00 39 5e 23 56 23 7e 23 46 16 00 dd 73 f6 + dd 72 f7 af dd 77 f8 dd 77 f9 21 00 00 39 5e 23 + 56 23 23 7e 2b 66 6a 11 00 00 c5 d5 e5 dd 6e f8 + dd 66 f9 e5 dd 6e f6 dd 66 f7 e5 cd fb 6f f1 f1 + f1 f1 c1 dd 74 f6 dd 73 f7 dd 72 f8 af dd 77 f9 + dd 7e fa dd 86 f6 dd 77 fa dd 7e fb dd 8e f7 dd + 77 fb dd 7e fc dd 8e f8 dd 77 fc dd 7e fd dd 8e + f9 dd 77 fd dd 7e fa c6 40 dd 77 fa dd 7e fb ce + 00 dd 77 fb dd 7e fc ce 00 dd 77 fc 30 03 dd 34 + fd dd cb fd 7e 28 33 dd 7e fa c6 40 dd 77 fa dd + 7e fb ce 00 dd 77 fb dd 7e fc ce 00 dd 77 fc 30 + 03 dd 34 fd 06 08 dd cb fd 3e dd cb fc 1e dd cb + fb 1e dd cb fa 1e 10 ee 18 21 06 07 dd cb fd 3e + dd cb fc 1e dd cb fb 1e dd cb fa 1e 10 ee dd 6e + fe dd 66 ff 2b dd 75 fe dd 74 ff dd 7e fa dd 77 + fa dd 7e fb dd 77 fb dd 7e fc e6 7f dd 77 fc dd + 7e fd dd 77 fd dd 7e ff ee 80 d6 81 38 25 21 00 + 00 39 79 b7 28 08 01 00 00 11 00 80 18 06 01 00 + 00 11 00 00 cb fb 7a f6 7f 71 23 70 23 73 23 77 + c3 88 6e dd cb ff 7e 28 0e 21 00 00 39 af 77 23 + 77 23 77 23 77 18 71 21 00 00 39 eb 79 b7 28 10 + af dd 77 f6 dd 77 f7 dd 77 f8 dd 36 f9 80 18 0d + af dd 77 f6 dd 77 f7 dd 77 f8 dd 77 f9 dd 6e fe + dd 7e ff 67 17 9f 01 00 00 3e 07 29 3d 20 fc dd + 7e f6 b1 f5 dd 7e f7 b0 4f dd 7e f8 b5 6f dd 7e + f9 b4 67 f1 dd b6 fa dd 77 f6 79 dd b6 fb dd 77 + f7 7d dd b6 fc dd 77 f8 7c dd b6 fd dd 77 f9 21 + 0a 00 39 01 04 00 ed b0 21 00 00 39 5e 23 56 23 + 23 7e 2b 6e 67 eb dd f9 dd e1 c9 dd e5 dd 21 00 + 00 dd 39 21 f4 ff 39 f9 21 00 00 39 eb 21 10 00 + 39 01 04 00 ed b0 21 04 00 39 eb 21 14 00 39 01 + 04 00 ed b0 21 00 00 39 eb 21 08 00 39 eb 01 04 + 00 ed b0 21 04 00 39 4e 23 46 23 5e 23 56 dd 7e + fc b1 4f dd 7e fd b0 47 dd 7e fe b3 6f dd 7e ff + b2 67 79 b7 20 0d b0 20 0a bf ed 6a 20 05 2e 00 + c3 93 6f 21 00 00 39 4e 23 46 23 5e 23 56 cb 7a + 28 49 21 04 00 39 4e 23 46 23 5e 23 56 cb 7a 28 + 3a 21 04 00 39 eb 21 08 00 39 eb 01 04 00 ed b0 + 21 00 00 39 4e 23 46 23 5e 23 56 dd 7e fc 91 dd + 7e fd 98 dd 7e fe 9b dd 7e ff 9a e2 50 6f ee 80 + f2 57 6f 2e 01 18 3c 2e 00 18 38 21 00 00 39 eb + 21 08 00 39 eb 01 04 00 ed b0 21 04 00 39 4e 23 + 46 23 5e 23 56 dd 7e fc 91 dd 7e fd 98 dd 7e fe + 9b dd 7e ff 9a e2 8a 6f ee 80 f2 91 6f 2e 01 18 + 02 2e 00 dd f9 dd e1 c9 dd e5 dd 21 00 00 dd 39 + dd 6e 06 dd 66 07 e5 dd 6e 04 dd 66 05 e5 cd 79 + 71 f1 f1 eb 4b 5a 79 d6 ff 7b de 7f 7d de 00 7c + 17 3f 1f de 80 38 05 21 ff 7f 18 1a af b9 3e 80 + 9b 3e ff 9d 3e ff 9c e2 dc 6f ee 80 fa e4 6f 21 + 00 80 18 02 69 63 dd e1 c9 21 02 00 39 4e 06 00 + 11 00 00 d5 c5 cd a0 72 f1 f1 c9 dd e5 dd 21 00 + 00 dd 39 21 f8 ff 39 f9 21 0c 00 39 eb 4b 42 03 + 03 dd 71 fe dd 70 ff 6b 62 23 23 4e 23 46 21 10 + 00 39 e3 e1 e5 7e 23 66 6f d5 e5 c5 cd 18 5d f1 + f1 4d 44 d1 dd 6e fe dd 66 ff 71 23 70 4b 42 03 + 03 dd 71 fc dd 70 fd 6b 62 23 23 7e dd 77 fe 23 + 7e dd 77 ff e1 e5 23 23 4e 23 46 6b 62 7e 23 66 + 6f d5 e5 c5 cd 18 5d f1 f1 d1 dd 7e fe 85 4f dd + 7e ff 8c 47 dd 6e fc dd 66 fd 71 23 70 4b 42 03 + 03 dd 71 fd dd 70 fe 6b 62 23 23 4e 23 46 6b 62 + 23 7e dd 77 ff e1 e5 23 66 d5 c5 dd 5e ff 2e 00 + 55 06 08 29 30 01 19 10 fa c1 d1 09 4d 44 dd 6e + fd dd 66 fe 71 23 70 e1 e5 4e 6b 62 23 66 d5 59 + 2e 00 55 06 08 29 30 01 19 10 fa d1 dd 75 fa dd + 74 fb c1 c5 03 dd 71 fe dd 70 ff 6b 62 4e e1 e5 + 23 66 d5 59 2e 00 55 06 08 29 30 01 19 10 fa d1 + 4d 44 dd 6e fe dd 66 ff 71 23 70 c1 c5 03 03 03 + dd 71 fc dd 70 fd c1 c5 03 dd 71 fe dd 70 ff e1 + e5 23 4e 23 46 79 dd 86 fa 4f 78 dd 8e fb 47 dd + 6e fe dd 66 ff 71 23 70 79 dd 96 fa 78 dd 9e fb + 3e 00 17 dd 6e fc dd 66 fd 77 4b 42 1a 5f e1 e5 + 66 c5 2e 00 55 06 08 29 30 01 19 10 fa c1 eb 7b + 02 03 7a 02 c1 c5 af 02 dd 7e 04 dd 86 08 6f dd + 7e 05 dd 8e 09 67 dd 7e 06 dd 8e 0a 5f dd 7e 07 + dd 8e 0b 57 dd f9 dd e1 c9 dd e5 dd 21 00 00 dd + 39 dd 7e 07 cb bf dd b6 06 dd b6 05 dd b6 04 20 + 07 21 00 00 5d 54 18 5b 21 00 00 e5 21 00 00 e5 + dd 6e 06 dd 66 07 e5 dd 6e 04 dd 66 05 e5 cd 9b + 6e f1 f1 f1 f1 7d b7 28 27 dd 7e 07 ee 80 57 dd + 4e 04 dd 46 05 dd 5e 06 d5 c5 cd f6 71 f1 f1 af + 95 6f 3e 00 9c 67 3e 00 9b 5f 3e 00 9a 57 18 13 + dd 6e 06 dd 66 07 e5 dd 6e 04 dd 66 05 e5 cd f6 + 71 f1 f1 dd e1 c9 dd e5 dd 21 00 00 dd 39 21 f6 + ff 39 f9 21 00 00 39 eb 21 0e 00 39 01 04 00 ed + b0 21 00 00 39 4e 23 46 23 7e 23 b6 b0 b1 28 0e + 21 00 00 39 4e 23 46 23 5e 23 7e 07 30 07 21 00 + 00 5d 54 18 66 21 00 00 39 4e 23 46 23 5e 23 56 + 06 07 cb 3a cb 1b 10 fa 0e 00 7b c6 6a dd 77 fa + 79 ce ff dd 77 fb 21 00 00 39 4e 23 46 23 5e 23 + 56 7b cb bf 1e 00 dd 71 fc dd 70 fd f6 80 dd 77 + fe dd 73 ff dd 7e fa ed 44 3c 18 10 dd cb ff 2e + dd cb fe 1e dd cb fd 1e dd cb fc 1e 3d 20 ed dd + 6e fc dd 66 fd dd 5e fe dd 56 ff dd f9 dd e1 c9 + dd e5 dd 21 00 00 dd 39 f5 f5 dd 7e 07 dd b6 06 + dd b6 05 dd b6 04 20 08 21 00 00 5d 54 c3 75 73 + 0e 96 dd 7e 06 d6 80 dd 7e 07 de 00 30 13 dd cb + 04 26 dd cb 05 16 dd cb 06 16 dd cb 07 16 0d 18 + e1 dd 7e 07 b7 28 36 dd cb 04 46 28 1d dd 7e 04 + c6 02 dd 77 04 dd 7e 05 ce 00 dd 77 05 dd 7e 06 + ce 00 dd 77 06 30 03 dd 34 07 dd cb 07 3e dd cb + 06 1e dd cb 05 1e dd cb 04 1e 0c 18 c4 dd 7e 04 + dd 77 04 dd 7e 05 dd 77 05 dd 7e 06 e6 7f dd 77 + 06 dd 7e 07 dd 77 07 21 00 00 39 06 00 11 00 00 + 3e 17 cb 21 cb 10 cb 13 cb 12 3d 20 f5 79 dd b6 + 04 4f 78 dd b6 05 47 7b dd b6 06 5f 7a dd b6 07 + 71 23 70 23 73 23 77 21 00 00 39 5e 23 56 23 23 + 7e 2b 6e 67 eb dd f9 dd e1 c9 e6 05 00 00 02 00 + 00 01 01 ff ff 01 01 01 00 00 07 07 05 10 52 00 + 00 00 00 00 4c 00 00 00 00 00 44 00 00 00 00 00 + 55 00 00 00 00 00 41 00 00 00 00 00 42 00 00 00 + 00 00 58 00 00 00 00 00 59 00 00 00 00 00 4c 00 + 00 00 00 00 52 00 00 00 00 00 53 65 6c 00 00 00 + 53 74 61 72 74 00 44 50 41 44 20 52 69 67 68 74 + 00 00 44 50 41 44 20 4c 65 66 74 00 00 00 44 50 + 41 44 20 44 6f 77 6e 00 00 00 44 50 41 44 20 55 + 70 00 00 00 00 00 41 00 00 00 00 00 00 00 00 00 + 00 00 42 00 00 00 00 00 00 00 00 00 00 00 58 00 + 00 00 00 00 00 00 00 00 00 00 59 00 00 00 00 00 + 00 00 00 00 00 00 4c 00 00 00 00 00 00 00 00 00 + 00 00 52 00 00 00 00 00 00 00 00 00 00 00 53 65 + 6c 65 63 74 00 00 00 00 00 00 53 74 61 72 74 00 + 00 00 00 00 00 00 06 02 04 04 18 16 16 14 03 17 + 09 0d 05 05 06 04 05 06 04 05 01 01 05 05 01 14 + 05 05 00 00 00 00 00 01 00 00 00 00 00 00 00 00 + 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 + 00 e2 27 00 00 00 55 2a 5d 2a 64 2a 6d 2a 79 2a + 20 ff 00 00 00 00 60 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 01 00 01 03 00 00 - 00 00 00 00 00 00 00 00 00 00 00 30 31 00 00 00 - 3a 2e 42 2e 49 2e 52 2e 00 00 01 01 ff ff 01 01 - 01 00 00 07 07 05 10 52 00 00 00 00 00 4c 00 00 - 00 00 00 44 00 00 00 00 00 55 00 00 00 00 00 41 - 00 00 00 00 00 42 00 00 00 00 00 58 00 00 00 00 - 00 59 00 00 00 00 00 4c 00 00 00 00 00 52 00 00 - 00 00 00 53 65 6c 00 00 00 53 74 61 72 74 00 44 - 50 41 44 20 52 69 67 68 74 00 00 44 50 41 44 20 - 4c 65 66 74 00 00 00 44 50 41 44 20 44 6f 77 6e - 00 00 00 44 50 41 44 20 55 70 00 00 00 00 00 41 - 00 00 00 00 00 00 00 00 00 00 00 42 00 00 00 00 - 00 00 00 00 00 00 00 58 00 00 00 00 00 00 00 00 - 00 00 00 59 00 00 00 00 00 00 00 00 00 00 00 4c - 00 00 00 00 00 00 00 00 00 00 00 52 00 00 00 00 - 00 00 00 00 00 00 00 53 65 6c 65 63 74 00 00 00 - 00 00 00 53 74 61 72 74 00 00 00 00 00 00 00 06 - 02 04 04 18 16 16 14 03 17 09 0d 05 05 06 04 05 - 06 04 05 01 01 05 05 01 14 05 05 00 00 00 00 00 - 01 00 00 00 00 00 00 00 00 00 00 00 14 00 0f 00 - 00 01 00 01 00 00 00 01 44 02 78 b1 28 08 11 fc - c3 21 33 3b ed b0 c9 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c2 60 + 00 00 00 00 00 00 00 00 00 00 00 00 51 71 21 31 + 00 00 00 00 00 00 5a 7a 53 73 41 61 57 77 22 32 + 00 00 00 00 43 63 58 78 44 64 45 65 24 34 c2 33 + 00 00 00 00 20 20 56 76 46 66 54 74 52 72 25 35 + 00 00 00 00 4e 6e 42 62 48 68 47 67 59 79 5e 36 + 00 00 00 00 00 00 4d 6d 4a 6a 55 75 26 37 2a 38 + 00 00 00 00 3c 2c 4b 6b 49 69 4f 6f 29 30 28 39 + 00 00 00 00 3e 2e 3f 2f 4c 6c 3a 3b 50 70 5f 2d + 00 00 00 00 00 00 40 27 00 00 7b 5b 2b 3d 00 00 + 00 00 2b 3d 00 00 0a 0a 7d 5d 00 00 7c 5c 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 08 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 01 00 00 00 00 14 00 0f + 00 00 01 00 01 00 00 00 20 00 00 00 00 18 13 00 + 00 d3 13 00 00 5f 17 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 18 13 00 00 bb 00 00 + 00 8c 03 00 00 b6 15 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 20 00 00 30 31 02 00 + 50 01 b8 00 c8 00 00 00 00 00 00 00 00 00 00 00 + 20 4e 78 00 f0 00 78 00 b4 00 03 00 78 88 13 00 + 00 0a 00 00 00 00 00 00 64 45 4a 00 d5 01 00 04 + 10 00 00 00 03 01 04 00 0a 00 00 01 00 00 00 00 + 06 1c 0a 01 00 00 80 01 1d 04 78 b1 28 08 11 5f + c6 21 7a 73 ed b0 c9 diff --git a/rtl/sound.hex b/rtl/sound.hex new file mode 100644 index 0000000..79fdec9 --- /dev/null +++ b/rtl/sound.hex @@ -0,0 +1,722 @@ + 08 81 98 08 18 08 91 90 1b 3b 2b 4d 23 d1 82 a1 + d2 8a 09 86 99 10 9a 5a 23 78 48 88 b1 1a 07 08 + 32 f3 93 7a f0 2a 01 a8 31 00 cc c8 42 8b 3e 88 + 51 98 96 12 8a 95 9a e8 80 6b 0a 11 98 58 02 a9 + 80 a1 58 83 f8 28 c1 99 9a 18 1f 20 a2 29 91 72 + e3 a8 58 8a 01 d2 39 09 11 a9 2d 81 01 00 3a 70 + 92 a3 0a 20 c5 8e a3 1a 12 90 fc 09 22 e8 29 90 + 29 3a 68 c2 99 01 90 c3 93 c3 8c 78 92 19 2a 1c + 12 81 04 ab 79 a4 91 90 19 90 08 a6 98 84 c9 70 + 0e 18 80 91 80 0a 0b b8 04 08 cb 18 39 86 c1 08 + 39 b4 d3 18 5b 09 83 92 6e 29 28 a7 89 80 01 00 + b4 0d 10 30 ae 20 82 00 c0 1a 03 b2 d2 b0 89 f0 + 49 8c 1b 68 80 88 a3 88 0a d1 a1 8d 82 84 93 3f + 00 91 84 81 8f 18 19 04 89 89 12 01 c6 28 29 81 + a1 04 83 59 0c a0 d1 88 3a 8f 02 1e 10 1a d1 05 + a1 08 81 89 e1 3e 38 89 28 0b 3b b7 a9 11 91 8a + 02 b0 18 1c 12 b8 bf 0b 18 1a f0 c8 40 90 2a d7 + 0a 18 19 08 30 22 80 a4 04 cb 21 0b 75 98 0c d5 + 09 19 19 28 09 08 90 c4 b3 05 8a 28 4c 29 20 d0 + 11 a8 1b 82 cc 02 9f 28 98 a2 c9 03 4d 00 d0 8a + 00 2f a2 70 98 a3 99 58 09 02 84 ab 49 83 80 91 + 60 4c 90 39 9a c2 a5 90 90 b2 89 09 12 78 08 0e + 88 20 2d 43 3c 03 e3 b2 9a 28 b0 9a da 28 88 b8 + ad 7a 18 d8 49 90 95 90 90 12 b9 0c 48 80 39 b5 + a8 2a 03 32 5d 02 2b 94 0b 11 58 c5 9c 08 82 90 + 20 c4 29 01 1c 38 73 b3 78 90 80 2b 10 05 c2 b8 + 18 3a 80 99 1e 11 b3 0e a6 b4 be 22 8b 8c 18 a0 + c2 00 b0 3a ba 18 78 25 80 90 1d 80 02 9e 80 11 + 88 85 90 b1 12 72 0b 79 01 99 21 29 90 21 3f d1 + 80 d0 a3 0a 1a 14 b3 b0 4a 4d 29 18 08 9b 3a 7e + a7 89 81 82 b2 88 e8 12 a0 5b 18 18 14 9c 18 18 + 88 d8 10 88 b0 b0 e9 02 9a 99 3c 79 a4 00 68 91 + 38 91 b7 90 3b d2 22 ba 11 88 09 90 7a 88 98 7a + a6 09 82 88 81 0e 91 10 a9 22 d8 83 83 93 ef 30 + 80 11 ab 4c 00 83 81 c9 a3 11 5e 18 90 30 0a 94 + a6 a9 83 29 09 8c a0 6a 92 8a 58 a9 e8 88 88 a2 + 1f 12 18 90 58 37 c8 90 21 18 02 80 26 19 4d 80 + a9 31 f3 1b 29 a8 10 c9 3a 8a 97 9a 16 d0 89 2a + 00 10 b3 18 bb 10 68 b9 e9 52 1a 93 9e 40 18 90 + a1 12 e8 10 09 01 c2 2a d1 10 39 4b aa 17 3a 02 + 89 a0 49 c7 4b 19 00 c1 12 9a 2a 6a aa 13 f2 29 + ab a7 2b a3 80 9e 28 92 a9 09 10 6c 92 9a 4a 10 + 88 c6 98 39 e3 00 80 b1 49 01 8a 5a a5 8c 30 8e + 80 08 b5 b8 10 19 a4 88 b7 82 4c 80 11 23 aa 6d + 18 18 01 91 d9 41 a2 c8 89 59 92 99 80 90 1b 16 + 12 b0 12 7c 11 c9 48 88 28 0b a8 a4 b1 f8 88 80 + c8 31 f0 91 3b 5b 10 b3 8d 81 2c 08 20 b9 03 5b + 13 f2 a0 b1 21 4a d9 2b 59 49 c4 00 aa 58 a2 08 + 5a 49 80 a1 25 01 81 a9 87 b2 91 88 69 4d 18 91 + 0a 32 b9 13 3d d0 03 92 18 18 d2 99 8f 8a b6 10 + 0b d2 4b b6 8c 08 a3 0b 2a 3d 29 99 13 b2 c4 a8 + 82 b5 d0 20 0c 3a 82 3e 40 b0 85 8a 80 03 94 a9 + 4b 20 b2 38 d1 85 19 9d 53 81 31 c9 50 89 a8 10 + 00 79 aa 58 89 a4 c0 00 82 b0 85 bb 48 a9 3b 23 + c8 90 c1 6b 0b 22 c0 1a 3e 31 a9 f0 02 0b d8 19 + 84 2a c2 3b c0 19 49 01 87 22 0c 08 61 ca 11 01 + bb 37 90 01 d9 49 20 aa 02 90 8c 10 4d 19 a1 80 + 8a 95 a8 94 c8 6a 91 88 28 c4 aa 22 0b 27 09 8a + 68 19 01 2e 82 08 9b d3 b9 27 1d 81 09 81 80 88 + c3 80 2a 2e 4b 48 c8 11 08 b0 82 94 87 a2 1b 2a + 1a 58 91 59 98 08 30 dd 42 90 c3 82 a9 e0 98 32 + 69 81 9a 0c 27 89 88 09 5a 0a 83 14 ba 88 49 a5 + bc 18 a5 00 b0 aa 99 7a b1 01 41 bf 10 3a 83 b5 + ca 40 9a 2a 83 84 1c 09 85 b2 85 bb 39 28 40 8d + 04 83 98 09 50 9a 58 9c 95 13 ca 11 28 b0 3a c3 + 2d 02 d3 1d 21 99 1b 32 c8 8d d4 81 0b a9 51 8b + 01 90 b1 06 8c 09 61 b1 b0 2c 31 08 19 f1 18 41 + a0 8a 40 8b 5a b5 88 11 c0 b1 69 02 bb 00 3f 01 + 0a 92 a8 28 95 d0 3b 82 ba 71 c9 1a 40 91 a9 e3 + 98 03 1c 1f 19 22 b9 18 3a f4 b1 09 20 68 a9 94 + 29 82 90 94 3d 11 a9 39 e2 49 2c 12 90 91 d4 0b + 86 1b 10 82 ab 4f 20 02 b1 08 e2 0c 03 11 1d 2a + 18 9c 97 18 81 a8 28 0b 93 86 ea 39 09 b0 05 2a + bc 18 2b 8c 03 e0 82 c2 b4 0f 28 a1 09 83 1a ae + 33 0a 12 f8 88 11 91 18 61 ac 84 10 d0 29 a2 30 + 83 e3 8e 2a 41 98 83 10 10 ab 78 00 a4 98 14 c3 + 3c 09 82 00 b1 f9 7b 11 89 00 a2 a2 9b 5a 4b 93 + c1 c4 a2 8f 3b 01 99 16 b8 b3 4a 8a 02 0a 11 0c + 07 9a 38 09 88 86 d8 89 23 81 1a f2 0e 11 2b 01 + 88 05 b0 a9 58 8b 82 93 f1 20 0d 02 19 1b a5 a6 + 9b 28 0a 32 d2 c1 91 1a 21 7b a1 12 a9 a8 6c 20 + 03 a5 aa d3 1c 09 21 19 99 f2 18 0c 29 92 f9 10 + 99 23 00 4c 02 c4 9b 14 0a 29 82 00 10 7a 85 c8 + 81 28 a4 42 f0 19 2a 94 01 00 a2 cc 58 81 18 a0 + 80 30 0c 39 f9 31 b9 94 2f 02 1b b5 80 99 01 3d + 9b 26 9b 09 06 88 0b 99 94 23 dc 28 01 11 a5 a8 + bc 0b 93 1a 15 2c 12 20 93 8a a0 91 75 b0 0b 13 + 3c d0 92 6b d1 1a 21 13 1e a2 cb 22 09 33 da 08 + 83 22 df 00 11 09 8a a0 12 bd 23 45 cd 10 81 81 + 58 d9 00 89 23 9f 83 99 10 2c 11 c9 41 a0 61 a0 + 18 94 0b 58 a2 0b 84 90 60 a1 89 2a 91 91 aa 75 + b0 8a 61 aa 92 11 8a 50 d8 12 90 93 3c 82 0e 28 + 9a a5 21 ab 80 94 0d a3 91 9e 34 bf 82 8a 9a 12 + b0 8a 2a 07 d8 29 00 18 09 b7 2b d2 1a a1 09 33 + 88 4e 05 8a 30 03 a2 18 d8 63 1a 88 a1 12 c8 10 + 58 23 9f e0 31 a9 08 12 9f 92 0d 81 10 99 83 2d + 91 81 8a 08 e0 48 a0 40 9a 00 98 2b 87 2f 18 b8 + 11 30 90 1a 81 88 07 bf 28 a4 9a 52 00 1a b8 88 + 46 8c 81 13 1a ca 34 8a 02 2b a0 90 76 09 89 00 + 02 1a b2 9f 32 b0 30 5a e9 82 1c c2 3b 92 18 b1 + a0 ae 88 9a 58 90 3f b5 0a 02 0c 91 00 ba c8 30 + cc 82 88 71 fa 80 21 19 89 13 88 13 9e ab a7 78 + 88 89 00 33 01 2c e9 22 01 88 89 24 9a 8b d1 10 + 02 39 92 2b 27 1c 92 3e a5 0a 84 1a a4 39 f9 8a + 98 30 03 4b a3 8e 98 32 a4 3f a4 9a 85 10 88 99 + 9a 92 71 9a 13 0a c8 21 91 ca 30 91 26 4a d1 21 + 80 89 19 86 2a 84 31 04 2f e0 18 a1 31 98 19 a0 + 48 b9 10 10 ba 83 fa 21 61 ca 0a b9 40 c2 40 aa + 09 fc 82 01 29 c9 38 b4 2b ca a3 82 11 8d 9b 93 + 70 92 98 51 c1 30 fc 10 03 78 b8 03 1b 90 cb 33 + 9a 07 3a a2 0c c2 41 88 80 88 08 93 73 9c 33 ac + 83 71 a9 80 21 8b 24 0a 02 0d 91 04 48 fb 02 18 + 89 a4 2c a2 0a 80 bb aa 17 38 bc 98 80 54 9b 88 + 82 28 fa 0c d1 61 9a 03 10 9a a0 50 bc 83 31 80 + 01 81 8b fb a3 71 1b 91 92 2a f0 11 18 45 8d 80 + 11 1c d0 00 08 08 89 a9 14 b9 53 9a c9 84 39 dd + 98 80 80 53 19 8a b1 19 de a1 00 45 11 28 a9 cb + db 37 19 80 88 38 bb 12 33 40 91 d8 1b b0 28 88 + f9 03 78 b8 22 bc 84 31 1a 86 30 ba 81 11 bf 80 + 9b b1 73 09 b8 21 ca 44 21 1a 90 f8 80 43 9d 96 + 29 b0 10 81 0a c8 08 54 8c ca 04 29 91 89 89 be + 92 11 11 88 38 f9 8a 17 41 0a a1 9b 88 88 02 71 + 00 85 8b 04 34 ad b0 60 89 9b 04 10 99 00 84 20 + 99 88 88 14 79 b3 61 8b ea 80 12 29 a2 29 cd aa + 92 51 cb 15 20 88 ad c0 54 08 98 99 98 9b a1 21 + a8 54 18 91 0d ab 82 12 78 a0 02 31 9c c1 19 03 + 10 52 21 ff a3 51 98 89 a8 91 41 08 d9 00 19 18 + a9 1a a8 d0 55 1b eb 80 23 28 98 00 88 ae bb 84 + 41 9b a1 22 0f ea 04 38 99 01 08 18 fc 82 40 b8 + 81 52 98 80 39 fc 84 21 89 01 39 cc 01 11 11 03 + 9f c0 11 22 01 b9 80 28 ad a4 70 88 01 00 02 88 + 20 59 c8 55 8b a8 00 11 40 98 30 b1 82 9a e8 18 + 9a 1d 42 2b fd 92 22 8a d9 23 8d a0 42 0b fb 92 + 32 8c 02 3b fc 11 01 02 89 cc 91 42 88 91 31 21 + de 11 01 82 13 30 db 80 24 28 13 33 70 ac a5 32 + 90 8b 91 21 c0 1c 33 28 cf e8 03 88 0a c0 1b a9 + 94 8d 89 89 af 81 14 3c f8 01 80 89 21 2a bc a2 + 01 94 8a 2a 83 20 f0 1b b0 19 61 10 a1 aa b8 14 + 70 99 90 a2 73 21 39 c9 12 51 08 72 a0 2c a8 03 + 42 a9 10 fa 33 51 ca 30 8a 8b 02 25 0c da ca 48 + 0a b2 80 bc 02 00 10 c0 8c 98 04 8d 88 74 08 0d + a9 15 11 aa a0 03 73 8a 8c 90 34 11 ab 81 44 22 + b8 18 0a d9 91 73 28 9a 91 9b 99 80 10 07 11 ab + e9 14 50 1c b3 71 89 99 99 15 91 01 ae 89 33 0a + 92 33 af d8 90 81 90 97 29 09 8a 9a a1 91 07 38 + 0f a8 03 1a 00 ca 93 23 08 50 03 22 4b db bb 43 + 56 11 81 39 be 98 12 80 08 04 11 32 73 9a fa 10 + 03 29 9e a0 80 a9 32 98 87 0b ed aa 89 01 10 8c + 89 90 bc b0 22 52 08 da e9 88 21 11 11 19 cc c8 + 02 31 2b aa b0 92 8c ab 57 50 09 9a 91 22 27 2b + 27 31 9c 02 04 32 88 18 13 24 1c c8 14 22 a9 72 + 02 8b bd 89 01 09 a1 27 a9 c8 0b c9 33 3c c0 91 + 19 fc a9 85 08 42 8c e9 00 11 28 10 99 23 a9 94 + 26 22 09 ac ab 89 10 11 33 40 8a 97 44 20 ad 98 + 80 a0 26 32 89 a0 33 62 29 a9 90 37 08 99 04 54 + bb da 0a 26 34 9b ec 80 82 28 ba a8 b9 31 ad 1a + 99 bb a8 dc 98 93 01 59 98 14 80 dc eb b9 00 33 + 32 20 53 42 aa b0 03 01 a9 ec eb aa 13 42 10 a9 + 91 23 53 70 a4 19 0a f0 35 30 88 80 85 43 40 8b + ba 90 22 8b a0 17 1b bc 93 57 13 09 bc bb b8 21 + 43 28 18 ba fb ab 89 90 43 50 1a c0 25 13 8e ba + ba 12 8a 14 91 60 cd a9 00 11 19 b9 12 72 98 08 + 8c ba 19 91 01 15 75 00 00 88 02 31 00 23 9c 81 + 87 31 28 41 50 a4 34 8b db a1 28 43 08 da 0c 90 + b8 c9 18 27 19 9b 0b 01 16 98 a0 39 62 18 09 80 + 9c 98 a0 93 82 30 44 72 21 ab cd ba 23 23 1d b0 + 04 51 89 bd 36 23 28 aa ca 98 27 31 21 8b 90 11 + 45 18 8b 02 03 81 3c f1 21 bc b9 2c da 30 d1 1f + b8 b9 18 0b da 9a a8 65 18 9c c9 9a 80 08 9a c9 + 10 42 10 88 ea 81 40 18 bf a0 11 52 8b ba 91 64 + 12 09 b9 00 31 08 33 a8 01 77 21 12 b9 a9 33 27 + 68 00 18 aa ad 91 82 62 28 10 b9 81 80 e8 28 09 + 40 99 d8 00 9e aa e9 91 30 8a 1a e8 a2 19 9a 54 + 21 1b b2 18 64 10 99 88 cd 01 c9 54 43 18 a9 cb + a2 24 50 8a 88 83 51 80 9d 09 15 31 98 bd b0 26 + 10 11 80 10 a2 73 18 09 a9 b8 4a a2 a9 98 12 44 + 0d ca aa b9 12 cf 80 03 08 a8 fc 9e 90 41 98 91 + 02 ad ab cb 98 13 50 10 00 a9 61 b9 93 11 40 bf + b8 a8 26 18 a8 83 2c 89 9d 06 32 08 98 86 09 88 + 0b b2 35 2e 99 21 81 27 19 98 aa 00 cf 08 99 14 + 08 98 43 19 aa 9a ba d8 af 9a b1 44 80 41 19 aa + a9 b4 ba 0f a8 09 41 82 48 bb d8 a1 55 50 01 9b + ab a2 90 40 35 8a 82 44 51 01 01 9d 82 33 31 02 + 01 32 ce 52 80 a2 0b 91 cf a8 88 02 0a 28 9d a8 + 1a 92 a9 db 28 f0 8c db 01 23 3a fa 20 90 0d d0 + 8a 12 2a ba ba a9 54 93 98 a9 42 80 37 4c 99 a9 + 08 c9 13 05 3b 23 ea 11 32 10 88 01 12 74 10 01 + 08 82 48 b0 9a a8 81 52 43 50 23 39 58 f8 99 80 + 12 34 ae 98 9d a0 28 ab c9 ba da b9 92 ea 09 8d + 80 c1 11 76 0a 90 99 90 94 41 88 98 06 08 2a a8 + 32 30 37 20 61 22 08 26 8a b0 74 01 11 00 19 98 + a8 24 51 09 81 88 11 12 21 35 42 1a bb 99 85 73 + 18 89 bb c9 08 88 09 99 9a bf ba ce a8 10 12 28 + be db 88 99 aa bf c9 88 00 88 98 9b aa 57 12 29 + 9b 00 89 d1 0b ba b1 47 51 00 a9 92 60 21 31 02 + c0 dc a3 72 32 10 00 9b b3 43 73 01 ad ca 90 90 + 22 10 9d 9b 9b 06 0b db b0 9d c8 11 08 89 ac ad + c9 98 c8 28 80 0c b9 d9 80 82 32 0a ac bc d9 25 + 48 03 2a 8a 93 91 8b 2a b2 77 18 34 1a 82 51 d9 + 36 1a 02 01 43 18 09 00 00 e9 d9 10 14 41 21 32 + 91 ad ab cd 04 02 21 48 80 8a 9a a8 ff a8 23 32 + 38 11 af b8 cb 90 38 09 db b9 b8 3b 48 82 9b bf + fb 10 04 11 88 8b 89 ea 12 25 32 10 20 90 23 02 + 45 20 21 8f 05 03 34 43 10 98 aa 29 24 81 17 1a + 9a 80 21 83 72 28 ca 99 bd 9b 8b c0 93 13 41 4a + b1 19 fc fa 8a 21 89 80 82 a1 4c d9 ac ba 02 31 + 73 20 8d ca ab c0 08 12 44 10 23 88 aa 83 8a ba + 4b f8 23 36 33 1a 32 80 d1 8e 01 46 13 28 10 b9 + 8b 98 80 bd 9a 35 04 1a 01 89 34 18 e5 2a c9 1c + 8a a2 0a 11 cf ab ea 00 80 08 ba b9 88 a1 8b 53 + aa 49 df 98 13 21 23 0c 98 99 8c e0 bc 98 53 1a + a8 15 80 1c 24 82 10 62 00 81 31 01 74 80 9b 88 + a8 02 71 81 42 82 80 1b b9 9b 07 3a 80 2a ff 88 + a0 09 a8 49 10 d1 31 a0 1e ab aa b0 52 03 37 1a + 00 92 0b 28 02 60 ad 09 03 00 20 c6 10 bf 91 9a + 04 89 27 28 28 08 00 40 81 01 21 33 9e 37 12 80 + ab ca 22 1a 87 31 01 08 98 80 11 bf da 91 42 80 + 41 90 31 91 4a 10 85 40 aa fd ac 00 10 b8 bc 88 + b0 29 20 8a fa 9f a9 81 01 c8 8a cb a1 82 41 28 + 86 8d 88 8b ba 81 87 53 18 82 2b a8 28 14 0c 85 + 18 12 36 09 19 e0 11 51 82 12 0a 02 c8 36 1b b6 + 48 90 98 9c 00 02 8a 0b 99 d1 dc bb bb 92 ce 89 + 9a aa 13 bf a9 9a aa 09 0b c9 c8 80 08 80 9b c8 + 08 88 24 53 26 52 98 10 00 31 04 43 0a 34 80 92 + 21 62 12 27 50 88 29 aa 45 01 88 33 76 18 03 18 + 12 3d b2 19 40 19 c1 92 3b ca 29 00 39 fb 15 cb + 51 12 81 9f a0 13 28 12 89 a8 08 9a da e9 21 92 + 20 cd 80 09 28 ab b3 2c 97 60 aa ba 45 80 00 09 + b3 71 18 98 89 93 60 12 98 75 80 31 a0 23 30 08 + b8 d0 9f 19 a2 09 cd 99 b1 09 db c8 ba 61 89 a9 + 9d 8a ca 91 11 8a be ab ca a8 19 b8 32 ec 00 80 + 10 68 d9 8b aa a9 98 98 01 33 43 34 20 18 14 50 + be 91 02 38 13 25 47 54 08 24 00 03 11 52 81 39 + 8d c9 12 40 14 08 04 51 88 19 9c 92 29 a4 41 01 + 3d b8 80 08 11 10 8f f0 11 00 0b c9 a8 8c 89 8b + 91 da a2 1c b8 c9 de 9a 02 21 ca 13 20 2b b8 37 + 4a 23 8c a9 27 88 98 50 25 10 31 80 21 98 28 85 + 20 60 81 05 88 02 3c da 9a fc 81 10 01 03 20 01 + bc ba e8 02 cd 82 ad 91 39 a9 39 d0 0b 8a c0 22 + 1b f9 99 19 b9 cd 99 e8 89 92 22 89 23 19 0b e9 + 8c 8a a9 14 71 88 e8 81 05 20 35 1a 08 89 13 b3 + 75 00 98 31 0b a5 42 11 00 18 2a e9 02 8a 88 27 + 61 81 39 80 9a c9 b0 88 d1 71 08 22 90 1a 06 2a + b9 19 da 2a aa 1a f3 28 a9 c3 81 2a 9a 9a ab fc + 48 80 80 00 01 03 22 22 01 01 80 99 88 08 11 32 + 54 35 33 33 39 54 8a 92 05 20 11 23 04 30 31 11 + 10 18 01 11 11 21 12 20 01 c0 18 8b d8 be a8 98 + fd 90 19 aa 88 8f da 9c a0 9a d0 09 99 91 0e 88 + ab 8a db bc a1 01 51 80 03 23 bf c9 19 b9 1a 04 + 13 18 12 01 22 43 89 32 44 33 34 23 42 12 23 23 + 22 22 11 22 10 10 23 11 11 22 21 00 88 09 0b 9a + ab 9a c9 81 f9 2b 0a fc 09 89 91 90 8c f9 88 b9 + 9b 00 cc 08 89 99 10 ac 98 90 10 98 05 51 8a 86 + 8b 00 12 2b 07 52 13 21 73 12 12 01 91 74 22 22 + 89 13 01 17 18 41 23 20 a0 40 0a c8 43 b9 35 09 + 14 2f a2 32 28 09 9a 8b 99 aa ba bb bb bb ca ca + 9a a9 a9 a9 aa ab ab 9a aa 99 99 9b 0a d8 a9 9a + 9d a0 81 42 02 be ab c1 42 53 09 15 11 10 00 02 + 88 34 3c 97 61 11 00 08 23 02 01 91 0a 72 11 09 + 24 f8 31 8b 1a ea 99 ca 99 b9 cb 1b ea 0b 98 fc + 98 8a 99 08 d8 29 bb 2f a0 aa c9 91 21 8c 19 ca + 12 ae a1 0a be 04 0d 82 13 31 08 b3 3f b9 34 22 + 28 15 11 52 ab 22 99 73 21 11 c8 34 88 80 62 83 + 49 03 a0 29 0c 93 0c d1 58 40 80 99 a1 13 8c c8 + 35 3b c1 9f 80 82 11 ad b9 0c 88 23 8b f8 09 cb + 9a 99 28 d1 ae a0 a0 23 80 3a fb 89 9b e8 aa 31 + 24 99 28 92 8c 35 29 1c b1 17 38 90 88 21 a1 23 + 13 71 00 10 22 92 18 11 40 82 40 71 98 30 c9 24 + a1 25 18 15 19 12 18 14 2c 90 0a 73 19 be a0 04 + 21 1b 92 ca 89 a8 bb aa 00 90 98 20 dd 80 89 00 + 8a fb 18 1a c3 1a 89 e9 a9 92 24 33 78 a0 1a 83 + 29 c9 07 28 aa 80 42 24 80 3b e1 32 23 23 89 90 + 2c c9 89 36 30 8b a9 a0 9d d9 1a 90 24 90 1d bb + bb d0 1b 8c a8 b9 9c 90 89 a8 1c 01 11 f0 9a 81 + 33 9b 43 31 bd 18 d0 2c 99 43 53 25 18 a8 99 30 + 58 a8 a4 41 02 20 b0 41 c8 8d 14 10 10 22 1b 95 + 0b 93 34 1b 31 ba 10 9a d3 39 26 10 ac 90 40 a9 + 28 35 91 40 aa a0 88 b8 5b aa ab a0 83 d0 8a 31 + 2b 80 3a c2 03 3a 92 cc 09 d1 42 22 88 a9 0a cc + 83 50 14 00 08 aa 83 23 32 1a 01 20 01 99 83 50 + 99 90 16 30 0b 94 81 22 29 b4 38 0c a1 12 1e 01 + 11 00 1c 90 89 c0 31 01 bb ca 08 ab cd 02 01 8f + 81 3a a0 0a cb 8b fa 11 9b b8 03 2e 93 40 8a 09 + ba 11 90 e9 03 9a 02 19 01 3c d9 09 98 04 00 89 + 18 b9 92 42 98 22 08 02 18 03 24 2b 08 02 32 32 + 02 b8 13 99 88 20 10 21 01 01 a9 c9 89 49 80 a2 + 19 bc 0b bb 99 9a 90 13 ab da 89 88 8a b0 cb b8 + 04 22 8b 22 9b ba 19 93 11 1a 80 29 84 14 04 00 + 98 10 21 1a 91 80 20 20 81 33 00 21 98 02 8b 01 + 23 31 01 b8 03 20 01 10 18 b1 22 30 b0 30 b9 21 + 90 0a 80 81 19 08 9b 80 81 99 ba 10 da aa a1 8b + 10 0a 12 9c 9a b0 88 00 88 ab 93 41 9b 10 90 21 + 9a 10 91 08 84 28 80 99 02 22 30 08 00 92 20 08 + 01 18 21 00 81 20 81 11 10 88 00 08 01 00 00 01 + 08 08 89 01 89 11 88 88 80 9a 81 89 9a 10 99 c8 + 0a 98 8b b8 98 99 8a 19 91 88 90 9a 80 a9 99 88 + 80 80 09 28 a8 80 08 90 90 00 00 80 20 81 91 08 + 21 00 01 00 01 01 99 01 09 08 89 12 10 88 08 08 + 80 89 02 00 10 80 90 09 09 90 00 88 09 18 80 00 + 89 00 80 88 08 88 08 80 88 00 08 80 09 08 80 09 + 08 88 88 88 00 00 00 89 00 09 01 08 08 10 98 00 + 80 08 88 01 08 00 00 88 00 80 09 81 01 80 08 80 + 00 80 08 08 80 08 00 08 08 80 00 88 00 80 90 80 + 08 00 88 08 08 08 08 08 80 08 80 80 08 08 08 08 + 80 09 00 80 80 80 80 80 80 80 80 80 80 09 00 08 + 09 00 08 80 80 80 08 00 09 2a 18 94 e6 d4 c3 a0 + 3f 5c 28 a6 c2 8a 5b 03 d2 1c 20 c3 0c 30 d2 2d + 12 b8 49 b3 3e 84 9b 23 bb 43 cb 51 ba 42 bb 26 + 9b 85 0a a1 48 ba 43 9d 93 38 d9 24 0b c0 42 9c + 91 41 ab a2 51 9c 90 42 8a c9 24 29 bc 82 42 8b + ca 14 32 ac c9 14 31 9b da 03 43 0a bd a0 24 32 + 9b db 91 34 41 9a bc a0 14 33 29 cb ca 91 34 42 + 09 ab cb 90 23 53 20 8a cb bb 90 34 34 32 0a bb + db aa 82 24 34 32 08 ab cb ca a8 01 34 33 33 20 + 8b cc bb bb a9 01 43 43 33 41 10 9a bb bb aa b9 + 90 00 12 12 11 01 10 80 88 98 89 88 88 80 80 80 + 00 08 00 08 80 08 80 80 88 00 80 80 88 00 80 80 + 80 80 80 08 08 99 11 21 88 92 e8 a0 18 37 3a 00 + 2f d8 a3 50 20 e9 8c 15 08 18 09 a8 61 a0 ba 22 + a1 00 1f da 24 79 a2 08 19 a0 91 82 34 f8 9c 90 + 34 3a b0 1d 40 83 49 ba b0 59 f8 10 82 10 9c 02 + 41 b4 1c 80 aa a0 44 1d 08 b1 59 30 d8 80 03 b2 + 0e 38 48 ab e4 98 22 1a 8c a3 c0 12 62 00 eb 81 + 20 28 8d a8 00 17 8a 22 1b 98 8c 07 1a 9b 80 11 + 80 a3 49 a5 26 a9 2e 99 02 93 b0 1b 1a 27 07 0a + 09 b9 11 ab 00 e0 52 13 0b 98 c8 32 ea 81 01 2c + 09 41 38 e8 26 8b 8e 82 82 03 e0 08 00 18 28 8b + 82 d2 0e 81 a2 88 72 89 ac 40 00 91 d0 a0 82 11 + ca 70 32 bb bb 41 a8 2b 89 21 64 93 88 e0 a9 89 + 9f 32 32 18 bb 84 8c b8 48 b3 c2 79 b3 87 0c 88 + 00 09 a1 30 80 81 58 b3 b9 c8 ca 58 12 79 00 b9 + b5 19 81 b5 c9 3a a7 28 09 3f 98 b5 18 2b 99 86 + 09 03 ab 94 2c 28 b3 aa 50 9b a8 07 3a 88 89 13 + a0 d6 28 9f 08 a8 13 49 94 8a 2b 02 9c 09 06 2a + 98 d0 08 a3 c2 47 09 0a 98 1e 88 33 10 d8 98 38 + 95 8a 00 a9 3a 00 b7 32 1f 9b 19 a7 18 11 8d 80 + a1 a0 36 20 9b 9a 49 b8 28 0a 11 97 13 fa 12 00 + 99 40 c0 12 99 dc 02 39 10 b1 34 9f 82 13 d9 78 + a8 08 89 82 a1 48 98 82 9e 46 8a 19 8a 80 09 00 + 0b d1 24 10 44 b0 ba 9a 83 40 99 3b 0f 9b c6 05 + 28 09 fa 11 23 89 1f a2 99 32 20 d2 8d 80 29 25 + 08 9b a1 b9 61 8a 21 da 38 85 12 bd 0a 34 91 99 + 0d 82 91 3a 9b aa 17 70 21 db 98 84 22 99 ad 98 + 24 03 1c 08 a3 a0 4d 0b 88 d5 12 1a 90 b0 22 4a + cd 93 22 08 ce 20 b3 62 1e 99 00 13 99 a8 92 04 + 13 8a e9 80 48 8c 1b 10 72 90 d9 20 12 bd 09 04 + 97 8c 10 91 10 99 9b 14 13 9d 90 3b 58 10 e9 10 + 82 18 8f 03 08 92 c0 81 5b 9a 93 16 93 0d a9 23 + 8d 81 00 71 9a 9b 92 29 03 52 2b f8 c8 30 03 2a + c1 95 9d 89 40 28 89 89 93 41 e0 b0 20 a1 78 18 + 9b d8 32 94 89 08 39 fc 04 02 3b 9b c0 12 0a 21 + 52 bf 09 81 13 00 da 30 1c 00 81 18 06 e0 19 0d + 14 80 2c a8 81 33 9b 96 d8 39 92 20 9c 90 51 c9 + 28 19 00 23 ba bf b7 21 99 9a 90 33 21 28 ff 91 + 42 09 d0 0a 28 12 4a e9 18 24 a0 88 0e 82 02 1a + 9b 58 90 28 e2 81 08 a2 bb 50 41 8f 99 32 82 03 + df 81 11 18 88 bb b7 30 0d 80 81 89 50 8c 88 23 + 80 d8 01 b4 03 8c cb 61 3b 88 c1 a9 73 0c a0 00 + 92 32 bc d1 20 18 28 0f b1 35 8b 01 98 c3 23 af + 81 2a 11 1c 9b 17 00 9a 80 a0 71 98 9b 01 02 60 + bb b4 80 22 29 eb 21 81 83 09 fa 50 80 93 ad 00 + 50 99 18 d9 25 1a 90 8c 10 35 9c 80 98 15 1a a9 + 2b 01 54 d9 83 1d 21 9a a0 68 92 19 ba 95 1a 32 + b9 e8 49 85 00 ca 10 89 64 bd 21 a8 31 c9 11 81 + 08 09 f0 48 89 4a d0 40 a1 2a c8 48 a3 2a b9 01 + 48 03 cd 02 8b 71 aa 11 c0 40 a0 1b 80 02 3c 80 + b1 07 8d 20 c2 29 80 99 02 82 0f 83 a8 51 aa 0e + 13 02 d0 a0 32 0e 09 00 7a 90 82 01 e0 08 38 90 + b9 51 1d 09 83 29 89 d1 24 a9 aa 61 2d 99 33 99 + e0 25 99 b1 21 2f 92 10 0e 10 01 a8 83 8a 88 32 + f1 80 1a 82 99 12 03 fb 51 0e 82 3a b8 25 ba 03 + 4a f1 20 8e 12 09 a9 42 ba 11 4b b2 15 bb 13 1b + c1 50 bb 44 ad 13 0b a3 3a d1 38 b8 21 8b 97 0a + a2 38 d8 32 c9 21 9b 30 0b 04 99 81 09 81 09 80 + 08 80 80 80 08 08 08 00 99 39 00 98 2c 22 ad 07 + 8c 22 99 95 b0 10 b6 f5 3f 84 aa 22 aa 48 b3 1d + 03 9a 21 d0 59 c2 2a 92 0c 14 c8 39 91 09 04 9f + 22 a9 18 00 90 03 da 68 b2 28 ba 43 e8 31 bb 50 + a8 12 8d 4e 59 a3 90 88 93 1d 02 90 b7 99 18 19 + 90 20 af 58 90 81 89 6d 12 a8 83 ac 50 c2 00 a8 + 20 a1 91 09 19 0b 53 f8 39 2e 02 89 1a 49 88 00 + 18 d3 1b 01 a4 f3 1e 03 a8 82 8d 32 ba 13 1e 00 + 2a 19 08 5a 8d 42 d8 21 a8 03 d1 18 c3 19 b2 28 + c1 4f 03 8b 18 4b 90 20 0e 11 88 93 a1 09 97 c2 + 91 89 20 d2 80 3d 19 18 18 8f 79 90 11 9b 11 2a + c5 a1 00 b0 24 f1 08 92 99 82 3e 81 3b 1a 10 3f + 2a 82 2c e4 3c b5 09 a4 99 12 b8 20 a9 38 91 1e + 18 3c 29 01 2f 12 9b 15 c0 38 e2 2a b6 0a 93 8a + 96 8c 21 99 19 28 9a 69 91 1b 95 0c 21 b1 01 e1 + 29 b2 03 c1 08 00 92 d0 7a b1 7a 91 2b 3a 80 28 + c2 09 08 c6 88 a3 09 c4 8a 14 ae 23 ad 22 9b 49 + 19 81 1d 28 80 08 00 b1 b5 83 f1 2b a5 18 f3 1d + 11 89 82 1d 28 89 3a 88 28 0a 84 09 f4 88 80 b3 + 05 f8 30 b8 38 c0 4b 83 1c 80 5a 91 09 10 8b 17 + a9 94 09 92 90 a6 b9 42 c9 22 8d 20 8a 59 90 49 + b0 6a 92 a1 81 8c 25 c8 94 1d 93 1a b3 4c 82 1d + 03 1f 10 00 90 19 01 b2 a3 8a a7 a9 22 f2 2b b2 + 69 b0 49 0b 48 89 19 02 1b b5 2a e2 19 a4 8a b7 + 8a 85 8a 94 1c 81 2b 93 3e 08 4b 80 3b d7 9a 40 + d2 1a 09 30 f2 09 00 08 a2 1a 92 3c 00 80 8b 7e + 22 c1 92 1d 04 a0 08 98 30 c9 50 b0 18 1a 96 a9 + 5a 80 03 ca 68 a1 08 92 1b c5 1a b6 98 09 3a b7 + 8b 20 1b 94 1c 11 9a 32 d9 33 e9 48 a3 a8 1a 49 + c3 1a 09 24 f0 2a 01 0a 81 29 d3 3f 02 a1 a1 4d + 83 80 c1 4a a3 1d 02 9a 21 8d 23 e0 3b 10 a4 a9 + 48 a1 10 d1 3a c2 4b b5 08 a9 79 a2 90 2b 20 b4 + 0b 81 39 d2 2c 94 8c 21 90 a5 8d 48 b2 18 8c 32 + c0 81 2b 88 80 60 f0 49 a8 41 d0 29 88 12 c0 18 + 8b 31 a9 83 a0 7e 03 99 91 6b 83 c1 29 99 34 d9 + 30 c1 4c 82 00 e1 3b 00 92 88 1c 21 0b c5 2a a8 + 6a 02 ba 78 8b 16 a8 b7 a8 2a 11 aa 32 b8 85 9d + 59 88 29 89 30 b8 38 d6 c2 89 5b 93 91 b8 7a 94 + a0 19 2b 96 99 00 2b 10 91 94 9f 30 90 b5 0c 28 + a3 81 c8 41 d0 28 88 91 1a 3d 84 8a 1d 40 a0 80 + 18 8c 24 9b b7 0b 21 b3 b5 ab 60 a0 93 8a 18 88 + 5a b9 70 9d 41 a9 18 29 80 d5 0a a2 20 d1 00 81 + 9c 33 9c b7 2d 00 01 a0 1b 40 aa 23 9c 03 8b 31 + f1 28 c9 43 f0 01 89 18 a3 2c a3 4c 80 10 90 0d + 40 a8 03 8b 1a 24 b8 e4 2b a1 31 f0 10 2b 81 b5 + 88 b9 70 c0 20 98 1b 33 da 15 9b 29 32 f1 88 2b + 01 b7 9a 20 98 11 c1 2a c1 7a a2 00 2e 10 18 c1 + 3a 3e 85 8a 93 1b 93 88 03 f8 59 a1 02 d1 2b a4 + 2b a2 4b 0c 23 0d 93 2c 1a 04 89 d3 4c 93 98 04 + ca 42 c9 13 a8 88 38 80 e2 6b 88 21 ab 30 2d 00 + 83 9e 02 2a c2 84 a9 3c 24 d8 03 9c 31 c1 29 c2 + 3c 88 31 da 70 e3 0c 20 a3 9b 6a 18 a5 9a 39 81 + a2 9a 48 0a 86 c2 90 4f 20 b3 98 1b 58 c3 0b 11 + a2 89 2b 12 b9 5a 12 f2 1e 20 a2 a0 3c 03 a9 28 + a3 82 9f 41 f1 1a 2b 23 f2 0b 28 01 b1 29 90 08 + 4b 93 d4 1f 12 a0 90 4d 13 e0 28 a0 11 9b 31 b2 + 9c 79 93 b0 4c 10 93 9b 5a 94 8a 83 89 b2 6c 85 + b8 3a 2a a7 99 19 39 b2 2b 03 ba 79 90 85 c8 6b + 83 a0 91 3d 83 88 98 21 d8 5a 92 91 99 6a a7 9a + 30 a9 32 e8 30 b0 29 88 95 a9 4b 02 c5 9b 69 92 + 98 82 0b 85 0d 02 90 0b 59 a4 b8 49 0a 87 a9 12 + 8b 11 8a 32 f8 5a 80 83 ab 59 94 a8 00 2b 92 82 + b0 93 9c 7a b7 0a 09 4a 93 c1 4a 98 48 8a b7 b8 + 69 92 a0 19 2a a7 a1 8a 28 80 0a 41 d9 69 92 b3 + 8b 7b 02 90 b2 7c 82 88 81 92 a2 0f 22 c1 80 1a + 00 a4 8a 81 4b 0b 60 c0 3d 4a 01 c4 8b 20 88 a5 + 99 10 a0 21 f2 80 0d 48 a2 a3 99 4b 81 2a 90 7b + 80 4b 94 a8 3b 2a 87 c0 20 9b 41 e1 28 d2 29 b1 + 38 d1 19 19 08 02 9f 30 1d 03 99 0a 5b 28 c4 08 + a9 79 91 81 91 88 91 00 f5 8a 82 2d 83 99 10 0e + 30 9b 78 99 5a 80 18 a2 1b 93 08 f3 08 b2 29 d5 + a0 82 9d 50 c1 10 9a 49 88 19 00 2e 11 2e 02 0b + 00 3d 02 a0 85 aa 24 d0 83 c2 09 a5 89 b4 2c 08 + 29 09 2d 5a 09 48 a8 20 9a 38 82 b1 a7 a9 85 89 + b5 88 b5 90 82 c2 88 0c 32 c8 29 2d 5a 09 4c 11 + 0b 00 4b 92 2b a6 c2 01 e1 12 e0 11 a9 11 93 f1 + 2c 28 a4 1f 10 1b 85 99 10 8b 69 90 03 d8 49 a1 + 10 a8 5b 83 a0 82 8c 83 4f 11 b2 88 1c 58 b1 20 + ba 68 a0 28 c5 9a 11 1b b7 8a 28 08 95 b8 38 b9 + 79 90 02 c0 5c 02 90 a2 2e 12 9a 03 9a 12 9e 40 + d2 18 a9 68 b2 08 a3 0c 20 89 a7 8c 20 1b 96 99 + 2a 08 38 c0 31 e8 49 91 92 b3 2f 04 a9 95 0c 10 + 09 18 80 1a 1b 78 c2 18 9a 40 c2 88 84 ab 24 ab + 87 9a 38 0b 23 e0 3a a0 6b 80 39 c3 1c 28 81 c5 + 9a 22 b9 23 e0 11 aa 79 b4 88 98 6a 92 0a 84 a9 + 30 ba 70 c0 28 98 21 d1 19 92 0c 15 aa 05 9d 30 + 98 84 b0 3b 81 3e 83 0b 91 7b 81 1a 01 99 50 d0 + 30 f0 30 d1 10 b8 7a 93 99 10 90 01 b0 6c 01 1a + a4 90 a0 6c 12 d1 2b 00 12 f1 18 98 12 b9 5b 04 + c8 38 8b 17 b8 11 8c 38 a2 08 c4 1c 01 2c 94 0b + 03 a9 3a 89 60 f1 3b a3 2a c4 0a 83 9b 32 d8 31 + e0 49 a0 13 e8 39 88 2b 22 c8 06 ab 33 bd 24 b8 + 10 98 3c 96 8b 96 0c 03 9a 04 a9 39 98 6a b5 0b + 83 1c 83 88 a3 99 6c 00 11 f1 28 b8 69 91 80 81 + b0 59 b0 58 d1 3a 98 5a 81 90 01 c0 59 b0 58 c1 + 10 a9 48 90 81 00 ba 70 aa 35 d9 48 98 29 92 1d + 05 aa 22 ac 24 b9 31 b9 5a 82 8a 97 9b 32 bb 52 + d0 11 c0 3a 82 9a 06 ab 42 bc 42 c9 22 b8 3b 02 + 99 87 9d 23 9d 13 9b 04 8c 20 90 08 a6 0c 03 8e + 13 aa 12 8b 4a 95 0d 04 9b 14 9b 05 9a 02 88 0a + 12 0e 05 8d 12 8b 05 9a 02 92 d1 4e 11 a1 1b 84 + 0c 03 9a 04 aa 38 80 82 e2 2d 02 1e 03 99 93 1e + 28 83 e2 88 2b 02 0d 03 0b a5 0b 20 b4 a8 1a 7a + a3 2b c5 1b 80 4b 95 b1 19 a0 58 d2 2a c4 0a 08 + 3b 95 b0 5a a1 49 c1 38 e2 1a 08 10 c3 9a 79 98 + 30 e1 10 b1 3c 82 80 a3 aa 68 b0 59 b2 20 d0 4a + 88 10 92 c8 58 b9 60 c1 10 b8 5a 81 88 82 aa 60 + ba 78 a0 21 d8 49 81 99 22 d9 41 c9 58 b1 28 b0 + 39 81 a8 50 d0 30 c9 58 b1 39 b0 59 a1 1b 23 f8 + 40 ba 78 b1 28 b2 2b 01 9a 51 f1 29 b0 69 a1 29 + b3 09 18 c1 59 e2 3b b3 4b 92 2b a4 90 1c 10 3c + b6 1a b2 5b b7 98 00 92 9a 49 0a 22 d1 01 b0 4e + 39 81 b5 b8 31 f1 2b 18 11 d2 89 4c 11 a2 a0 29 + b6 9a 39 19 b7 a0 1a 3b 18 83 b0 11 9f 58 99 23 + e8 20 99 3c 39 92 c7 b0 3a 98 59 a1 38 f2 89 29 + 08 10 e2 29 d2 2b 80 5c 03 b0 18 98 5b 94 1d 85 + 9b 22 9c 22 b0 28 b4 0b 04 9c 23 f0 20 b0 5a b4 + 1b 84 9a 20 9a 59 90 2a 94 8c 22 9c 24 c0 83 ab + 31 89 0b 61 c8 23 cc 42 ba 31 c1 a4 90 a8 7a a3 + 08 d2 3a a0 7b 01 88 82 a9 5b 19 4b 95 a8 95 9a + 20 0b 22 c2 a2 a4 ae 78 a1 18 b2 1a a4 2f 03 9b + 16 b8 3a 88 4d 03 9a 05 9c 48 99 30 d1 18 b3 2d + 11 98 12 f1 2a b3 5c 82 0b 85 a8 3b 82 2e 03 9b + 07 aa 31 aa 48 90 29 b5 8a 11 99 05 f2 09 92 1a + 92 2d 84 b1 1a 00 3e 02 0d 04 9b 24 c9 6a 94 a8 + 02 a0 0c 58 a1 83 d0 4a a3 0a 00 18 c3 0c 5c 20 + 91 c4 8b 31 b9 38 8b 17 d1 2b 2a 28 a5 a9 31 e1 + 2a 90 48 d2 1a 00 09 2b 11 96 f2 0b 28 3c 95 9a + 13 d1 1b 3b 4a a7 9a 21 aa 50 b8 31 f2 09 08 1a + 03 ba 68 c2 3d 00 3c a6 99 20 99 28 a2 2a c5 8c + 21 8b 24 c8 20 b1 3e 11 98 97 b9 40 b0 28 a0 39 + d4 8a 39 89 22 e0 39 b3 2e 10 1a a5 9a 38 80 88 + 92 3a f6 9b 40 9a 14 b9 48 a1 1b 28 2b d7 9b 40 + 9b 42 c8 21 e2 0a 29 2b 13 f1 18 a2 2d 01 1b a7 + 98 01 99 4a 80 19 c7 a8 20 9b 58 a0 39 c3 1b 18 + 2e 22 d0 20 c1 2a a4 1c 85 a9 12 a8 1c 5b 28 94 + b9 31 9d 33 e0 02 b9 69 a2 08 92 b1 3a 0c 7a a4 + 1a b4 0a 02 9a 49 91 19 c7 aa 40 a8 21 e0 39 90 + 29 a1 3c 03 d2 0a 95 1f 03 9b 23 c9 31 c8 59 a2 + 1b 86 b9 40 b8 48 b0 49 b3 2b 90 5b 18 80 2b d7 + 8b 22 ab 34 d8 21 c1 19 80 3e 12 c1 18 b2 3d 93 + 2d 95 8a 83 8b 39 2a 1c 87 aa 41 c8 30 c0 38 c1 + 28 c2 1a 18 a3 2a f5 0c 83 0c 13 ab 34 d8 20 9a + 4a 11 b8 33 f0 3a b2 4b a4 2c a4 0b 11 88 1b 97 + 9b 34 cb 60 a9 30 c0 30 c0 4a 91 00 92 c1 3d 82 + 2d 03 9c 13 ac 41 aa 48 a4 b0 22 f8 49 a1 3b a5 + 0b 84 8b 13 9c 21 b2 0a 97 9c 58 a8 48 c1 3a b3 + 3c 92 2b 94 a0 08 81 2f 14 c9 31 d0 38 c0 49 b2 + 3a b3 80 1c 84 1f 04 9b 14 ab 33 c9 31 d0 28 a1 + 19 1a 80 5b b5 2b d3 3b e5 0c 20 98 02 b3 c2 2d + 18 28 c4 8a 83 8c 38 1d 13 e3 a0 2c 29 3a c3 2b + b7 89 80 4c 02 a1 a2 0a 29 90 6e 11 98 83 9b 48 + a8 59 a4 a1 a1 2e 4a 81 19 b5 89 93 1e 12 a9 05 + a9 18 09 3f 30 d2 00 98 4a a2 2c 83 88 c4 0c 39 + 81 89 04 ba 16 aa 31 c8 40 c1 19 92 0c 7a a4 88 + b4 0b 03 0e 12 a8 84 aa 49 09 10 92 f2 29 d3 2d + 82 1b 85 9b 22 a9 3b 28 09 b7 a9 58 a0 4a b2 5b + b5 0a 81 1b 39 a4 1c 87 aa 42 d8 30 d0 39 b3 1c + 02 8c 48 a1 2b 97 9a 13 ab 41 b9 50 c0 39 c2 2c + 18 80 01 f3 0b 85 9a 12 8c 31 c8 38 99 4b 14 c9 + 24 d8 38 b0 59 b2 3a d4 8a 4b 10 08 b5 8b 06 aa + 32 c9 40 c0 39 a0 28 8c 40 9b 26 ba 32 ba 42 c9 + 31 d0 30 d0 39 9a 40 a8 06 c9 32 ca 50 a9 31 d1 + 10 c1 19 0a 49 0b 17 b9 23 bb 51 c8 30 c0 38 c2 + 2b 91 3b 01 d5 9a 05 9c 33 cb 51 d0 20 c2 08 88 + 29 89 13 ca 35 ca 41 ba 41 c8 48 b1 4a a2 3b a1 + 11 c0 05 ba 50 b9 50 d1 28 c2 2a b2 5c 00 18 b2 + 84 c9 58 a9 58 b1 28 c2 2a b3 4c 82 1b a5 80 c2 + 1a a2 5b b4 3d a5 0b 04 9b 23 9e 21 99 84 9a 12 + 8d 13 9d 22 aa 25 ba 32 bd 41 ab 35 c9 22 bb 60 + aa 50 b0 30 d0 38 c0 49 a0 38 d1 39 b0 59 a0 38 + e2 2a b3 4d 83 0c 85 99 83 99 82 2d 83 1d 94 0b + 85 8c 22 ab 41 b8 30 d1 29 98 28 0d 25 c8 13 d0 + 3d 11 a2 9a 32 e8 4a 94 99 11 9c 50 c1 2b 84 a9 + 38 b1 39 d4 1d 02 99 12 b9 5a 93 0b 11 8c 33 f1 + 2c 02 99 03 ba 68 b2 3e 02 89 83 ab 41 c1 3d 01 + 0b 07 b8 38 c3 1c 02 0d 14 c0 29 a3 0b 12 0f 20 + b3 1c 03 9c 23 d9 59 b5 8a 03 ab 51 d0 3a a5 8b + 13 ab 50 b0 4b 83 9b 32 d8 48 b1 3d 02 0b 04 b8 + 39 a3 1e 30 c1 10 e3 1c 84 9b 40 99 21 d1 2a 92 + 1c 28 88 4b 97 a9 13 d9 58 b1 3b a5 8a 03 b8 49 + a2 2e 21 b8 48 d2 3d 94 0c 12 b9 59 a2 1a 84 aa + 59 a2 2c 84 9b 32 d0 4b 83 8c 30 b0 49 b4 0c 05 + b8 39 a1 4c 03 c8 38 c3 0a 96 b0 4e 12 a8 28 b3 + 0c 5c 12 a8 83 9d 23 e1 2b 81 2b 82 2b a7 b3 c1 + 2b 02 0b 94 2f 12 d1 29 a1 3c 95 9b 59 91 19 a4 + 8a 12 d3 9b 69 92 0b 03 1f 12 c0 3a a3 2d 83 8c + 48 b3 0a 00 92 a1 c4 0f 48 b2 2c 11 8a 14 e0 3a + 94 a8 18 0a 49 92 99 4a a7 a9 21 c1 29 b4 1e 20 + a8 39 a2 2b b7 a0 19 10 b3 3f 11 9c 50 d1 2b 04 + aa 31 c8 49 a4 8c 30 b0 3a 93 8b 21 d5 a8 3b a7 + 8b 30 a9 59 a3 0d 13 c1 19 a3 0c 13 d1 2c 3a a5 + 8b 31 c8 59 b4 8b 32 e0 3a 93 0d 21 c0 4b 84 a9 + 20 b3 8a 11 d3 1f 30 c1 2c 03 9c 31 d2 2c 84 a9 + 38 b3 2e 03 a9 4a 82 a0 2c 04 c0 3a b6 8b 31 d1 + 3c 83 9b 50 c1 2b 85 aa 40 c2 1b 03 b9 39 80 08 + 0d 58 b2 3d 85 a9 38 d4 0c 12 b8 49 b5 8b 31 c0 + 4b 84 aa 48 a1 18 b6 b0 3d 21 c0 3b 85 b9 5a 83 + 9b 31 d2 1c 13 d1 1a 94 9a 59 a3 0d 30 b1 3d 03 + b0 2a b7 99 38 c2 1c 21 c1 2c 12 b9 59 a4 8b 30 + d3 0c 22 d0 3a 94 9b 48 b3 1d 21 b0 3b 85 b8 4a + a6 a9 49 a3 0c 21 c1 2d 12 a9 5b 84 a9 49 a3 0c + 21 d2 1b 13 d0 3c 03 b9 5a 94 9a 49 a3 0c 30 d3 + 0c 13 d1 2b 03 c8 4a 93 8c 30 c2 2e 20 a1 2c 03 + c1 1a 84 c1 2b 96 a8 3b 83 9b 79 a3 8b 48 c3 0b + 30 d2 1c 13 d0 3b 84 b8 4a 83 c8 4a 83 b8 4a a5 + 9a 49 a4 9a 49 a4 8a 20 c3 0c 21 d3 0c 20 b3 8a + 30 d2 1c 21 c2 0b 40 c2 0b 59 a3 8c 48 b3 1e 38 + b4 8b 49 a5 9a 49 a4 9a 49 a4 8b 38 b5 9a 49 a4 + 8b 48 b4 9a 49 a4 a8 4a 93 a8 3b 84 c0 4b 03 d0 + 3d 21 b1 2d 21 c2 0b 31 d2 8a 49 a4 9a 4a 84 c0 + 3c 12 c1 1b 22 e2 1c 11 b4 8b 30 d3 0b 38 c3 8b + 6b 03 c0 4c 11 c3 0c 30 c2 0c 48 b4 99 39 a5 a8 + 3c 03 c0 3c 12 d2 0b 49 a4 99 4b 84 b0 3d 11 b3 + 0d 49 a4 99 3c 12 c1 2c 20 b3 9a 6a 83 b8 4c 21 + d2 89 3b 04 d1 1b 38 a3 9a 4a 01 91 98 3d 12 d3 + 8b 6b 04 c1 1b 39 a6 b0 2c 20 b4 99 4b 84 c1 2c + 39 b6 a0 2c 20 b4 b1 2d 38 b5 a8 3c 11 b4 9a 49 + 94 b1 1c 39 94 c1 1c 49 a5 a8 3c 28 a4 a8 3c 11 + b4 9a 5b 02 b2 1c 4a 83 e3 8b 5a 82 b2 0b 5a 83 + c2 0c 49 81 a2 8b 5a 02 d3 8b 5a 84 c1 1c 39 83 + d2 0b 4a 01 a3 b0 4e 20 b4 99 4b 84 c2 0a 3a 94 + c2 8a 5b 28 a4 b1 2d 39 82 b2 99 49 a4 b1 1c 49 + 94 c2 0c 5b 03 d3 a8 4c 28 a3 a1 0a 29 09 02 c4 + a0 2a 00 0a 4a 95 f3 8c 5a 02 d3 a8 4c 28 93 c2 + 89 4c 20 b4 b1 1b 20 91 89 28 b5 a0 2f 38 a4 a0 + 08 0a 4c 12 d4 a8 4c 28 b6 a8 3c 28 92 98 00 91 + 0b 30 b1 3c 03 c3 c1 3f 30 e4 a8 3c 20 a2 a1 0b + 49 00 93 c1 09 2b 06 d2 0c 38 93 c1 3f 11 b3 99 + 5c 11 b2 88 00 90 3f 21 d3 99 4b 03 d1 1a 3b 84 + c1 1b 38 b5 9a 30 a8 3b 12 f4 9b 7a 02 c2 0b 4a + 02 c2 0b 38 90 09 82 b3 1f 39 b7 99 4b 03 d2 0b + 4a 01 b3 98 1a 39 c3 08 a5 a9 6c 21 c2 0c 48 b3 + 99 3a 08 a7 b8 5b 03 c1 1a 11 c2 2f 20 c4 8a 3b + 11 c4 99 3a a4 98 19 01 a1 1d 5a 83 c0 2a 83 b0 + 2c 48 b4 99 29 84 d2 8b 59 93 b1 2f 38 b5 a8 3c + 12 d3 8b 48 b5 99 3b 84 b1 2c 02 b1 2c 2a 28 b7 + a9 5b 03 d1 2b 01 92 b2 2f 39 93 aa 6a 94 a8 3a + 94 a9 3a 0a 23 f3 9b 5a 84 b0 3b 08 3a b7 9a 59 + b5 99 4c 11 99 4b 12 f4 b2 0b 5a 00 88 82 a1 a2 + 1f 4a 02 c2 88 82 b2 0c 5b 12 d4 a9 4b 10 80 09 + 85 d2 0b 4b 29 83 d3 99 2a 2a 29 08 01 f5 b2 1d + 4a 83 b0 2a 02 d2 8a 5b 11 a2 a2 b2 08 91 2f 5b + 13 f3 a9 4b 29 02 c2 90 82 b1 3f 4a 95 c2 89 3b + 02 c1 2c 28 93 c1 1c 38 a3 a0 3f 38 b4 b3 a9 6b + 12 c1 09 10 b3 8c 5c 4a 03 e3 a8 3b 01 88 08 19 + a7 c3 99 3c 29 96 b1 2e 3a 2a 2a 02 e5 c3 a0 1b + 4b 3a 18 93 e4 a0 1b 5b 28 93 d3 b2 88 1b 3b 4c + 39 84 e3 99 29 09 2a 29 00 93 d5 c3 8b 5b 29 08 + 01 e5 b2 8a 5c 28 93 c2 90 1a 4c 28 a4 b3 b2 0c + 6c 28 93 c2 89 2a 18 82 b2 89 3d 20 b6 a0 80 0b + 7c 39 a6 b2 89 3d 28 92 b4 a0 1a 4d 39 93 d3 99 + 3c 4a 02 d3 a0 1b 5a 01 a1 92 a0 3f 39 93 d3 99 + 4c 3a 84 c3 a0 1b 3b 28 a6 c3 a8 4d 3a 02 c3 98 + 00 89 28 a4 b2 98 3e 49 b6 a8 3c 39 92 b2 88 2a + 03 e0 2a 12 e3 8d 49 93 a8 3c 20 a2 b4 8d 5a 83 + d3 98 19 81 89 3a b7 99 3a 2c 20 c4 98 2b 20 b3 + 98 01 f4 8b 49 81 c6 b0 4d 28 92 b3 98 1a 4a 93 + 99 22 e2 99 6c 28 94 c1 1b 49 93 a0 09 2a 00 88 + 19 a7 d2 1c 4a 01 b4 c3 8c 5a 01 a0 08 09 10 98 + 20 c5 b1 2f 4a 84 c2 88 1b 4a 00 80 82 d3 90 98 + 4b 08 03 f2 0b 4a 01 b2 89 3b 10 b1 7c 03 c2 90 + 1b 3c 48 d5 a1 0a 5b 20 b3 98 08 03 e8 6c 11 b3 + b2 0c 4a 01 91 a2 89 5c 04 c1 1c 28 a5 99 2a 29 + b6 98 19 1a 02 c2 99 7c 12 c2 88 2c 20 b3 89 19 + 2a 21 f4 9b 48 81 a2 0d 39 08 84 d8 4c 10 08 a5 + b0 3b 11 a1 0a 3b a7 b1 1a 5f 38 b4 8a 01 1c 04 + c1 1a 3c 10 91 89 29 20 f7 b0 2a 09 28 09 3c 28 + c7 b3 a8 3d 3a 11 b2 8a 39 95 d4 b1 2d 3a 01 99 + 3a 18 b7 d3 99 4b 01 88 00 09 01 d5 b1 2e 38 91 + 80 8a 3b 30 e5 a0 09 4d 39 92 a0 01 b5 b3 c4 a0 + 1b 4c 2b 5a 02 c3 c3 9a 4b 3b 19 28 a7 b2 88 95 + c1 1c 4a 18 08 91 09 84 b2 a0 3f 4b 38 b5 a0 19 + 01 b3 8e 4a 00 a4 b2 8a 6c 12 d3 99 4c 29 83 c3 + 99 2b 11 90 2d 5b 12 f3 b2 0b 6b 28 92 a1 0b 5a + 95 b1 09 3d 11 b3 8c 5b 20 c6 b1 1c 3a 10 92 b2 + 0a 21 d4 9a 5c 28 93 c3 99 5d 28 a4 b2 0a 3b 10 + a2 8a 49 a7 c2 89 3e 39 94 c3 a8 3c 39 92 a0 19 + 18 94 c1 1c 5b 12 e3 a1 0a 4c 11 a2 90 09 19 80 + 80 3d 4a b7 b1 2c 4a 18 a4 b2 0c 5a 01 b3 a1 0a + 3a a6 a9 5c 28 94 d3 99 3d 39 93 b2 89 19 01 b5 + 9b 7b 11 a3 c2 0c 4a 02 d3 98 19 2b 20 c5 99 3b + 11 b4 a8 4c 2a 03 f3 99 4b 20 b4 b1 1b 4b 01 92 + b1 3e 38 a4 b1 1e 4a 01 a2 a1 0a 4c 03 c3 99 3d + 38 a4 c2 0b 4b 20 b5 b0 2c 3b 96 b1 08 1a 2c 31 + f3 8b 49 80 81 91 0b 5b 31 d3 98 92 89 29 d4 0b + 10 9a 68 93 1c 82 8a 18 0c b6 c2 1a 28 a2 80 09 + 6e 28 b4 b3 0b 4a 49 d3 0b 12 ba 4a 02 90 0b 3c + 27 b4 9a 4d 10 a2 08 81 a1 a8 6c 39 92 e4 99 3a + 2a 81 b5 b0 6b 10 82 b4 8a 3a 49 b2 81 d2 2c 02 + 2a a3 8d 83 4a f3 0d 28 93 a8 2b 96 aa 21 8a 3a + 05 c2 0b 28 9d 32 a8 25 d8 38 09 38 b9 95 b8 21 + 8e 12 c9 32 d8 49 b1 6a 93 8a 22 9a 01 c2 bb 6b + 04 d3 1e 21 a0 00 8a 12 a0 31 ac 68 a2 2b e3 0b + 12 99 02 d0 7a 00 09 02 9a 32 9b 12 f2 0b 22 b5 + d2 88 b7 b2 19 80 4f 3a 1a 5c 28 93 b3 c4 c2 88 + 81 0c 3b 18 80 83 e4 8a 5b 2a 2a 01 c3 b2 b4 b3 + b4 a9 5b 19 10 a1 a4 9c 7c 4a 29 02 b4 b3 a1 92 + b2 8a 82 83 b8 1b 84 bf 5d 3c 3b 20 a4 c2 a2 90 + 00 80 20 c6 b0 2b 10 99 22 1b 6e 5c 20 80 93 c2 + 89 39 a2 88 c5 b1 8b 30 d2 0a 18 3d 5b 29 94 b2 + 0b 3c 1a 38 f4 a0 81 92 b1 12 e4 1c 3a 3d 22 f2 + 88 88 1b 7b 28 92 80 b5 a8 39 94 b0 08 80 10 d4 + d3 b0 1a 2e 5b 29 18 a3 09 08 4d 3a 96 b1 08 02 + b4 a1 d5 b1 1d 20 98 29 92 98 4a 3e 4a 00 81 9a + 4a 88 87 e2 90 88 29 a3 99 85 c3 8b 5a 19 18 08 + 10 5f 21 c0 29 94 98 18 08 80 93 e2 a0 84 c2 8a + 38 8a 79 b3 3e 20 8b 02 9a 49 1b 12 aa 37 f1 09 + 00 00 80 a5 b0 2c 2a 10 c6 b1 1a 19 5d 38 09 18 + 91 a3 c0 2b 00 0c 4a 14 f4 c1 08 19 3a 02 a1 1c + 28 c4 b8 39 98 4d 01 0d 30 98 04 c1 2a c5 8b 02 + 99 16 c1 01 c0 3c 18 2a a5 8b 39 1a 39 99 79 a3 + 1c 86 c0 02 99 58 a1 93 d1 89 2b 28 19 5b 02 b1 + 2f 30 a9 14 d0 10 99 38 b1 02 f1 19 94 98 2a 21 + f5 a8 20 aa 7a 02 a8 18 0a 20 c2 b2 c8 6b 01 2a + e6 99 20 90 2d 10 91 d4 8a 2a 4b 97 a8 18 91 1b + 3a 29 82 b1 a6 b8 6c 21 b3 a1 a3 c2 1b 00 2d 38 + 90 08 8b 2d 14 aa 79 b2 4f 28 92 a1 01 c2 2a a7 + 8a 11 98 03 ab 4a 09 30 f2 0b 21 b0 5a e5 8a 28 + 98 19 4e 22 d1 08 88 1a 28 08 02 b2 1c 22 d0 02 + a1 a5 e0 3a 2b 48 b4 a3 a9 7e 20 a1 2a 02 a0 2a + b6 ab 21 d3 89 3a 2b 09 84 c1 02 08 2d 6c 85 c0 + 29 81 92 bc 6a 83 a2 99 6c 21 90 0a 08 80 2b 09 + 3d 85 c4 a0 1a 00 4a b6 b1 2a 01 89 3f 11 c0 2a + 02 a0 3d 2a 84 d1 0b 30 98 49 93 a5 8e 20 b4 99 + 2b 30 d3 0d 4a 12 d3 a1 09 01 8a 49 94 99 2d 2b + 4a 94 b0 19 88 1b 7a 83 f4 a8 4a 00 29 11 a1 8c + 03 b9 15 ea 6a 81 98 00 91 91 89 4c 04 aa 41 c2 + 09 4c 12 c8 4b 94 89 02 e1 2b 3a 12 d2 90 1b 34 + f2 1d 20 98 18 a2 a8 4a 18 98 28 05 ba 59 a2 13 + e4 b0 09 1a 49 b7 8a 11 9c 5a 82 b1 18 81 19 92 + e0 02 91 a1 3c 24 ac 13 e8 5c 11 a1 18 92 0e 20 + c3 98 82 a4 8b 3b 1e 58 b3 9c 59 a5 99 18 92 a0 + 1a 90 6b 07 a0 2a 00 89 81 80 91 91 a6 9d 48 c1 + 3a 91 a1 3c 50 b4 80 0a 11 d0 4c 02 b8 09 01 e4 + 0b 20 08 94 10 a2 2f 95 c0 2c 28 00 92 0b 30 c3 + c1 b4 0e 59 a3 91 89 29 b2 18 a4 ac 5a 81 89 2a + 03 b7 d2 0a 3a 29 22 f3 a9 5b 01 98 22 e2 2a a4 + 1f 39 a3 a8 91 9a 6b 20 a0 18 87 c1 1b 11 0a 03 + a0 00 a1 2e 20 9b 30 f3 0d 5b 04 c0 3a 94 99 11 + 98 1b 38 c5 b1 1c 49 00 b4 0e 39 94 b1 1a 28 a3 + b2 a2 1c 20 3b 17 c2 8b 5c 01 98 38 90 3b 02 c3 + 99 1b 27 e2 1b 38 a1 90 89 94 9c 10 b8 7c 31 c3 + 98 88 0d 39 c3 1b 15 b1 1a 10 09 7a 02 a8 10 91 + 98 80 08 91 1a 18 00 91 90 19 80 00 90 08 80 80 + 08 88 19 01 89 18 80 00 80 88 08 80 08 08 08 08 + 08 80 08 80 08 08 08 81 90 09 18 80 08 08 80 08 + 80 08 08 08 08 diff --git a/rtl/sound.v b/rtl/sound.v new file mode 100644 index 0000000..a95d870 --- /dev/null +++ b/rtl/sound.v @@ -0,0 +1,149 @@ +`timescale 1ns / 1ps +/*============================================================================ + Aznable (custom 8-bit computer system) - Charles (sound engine) + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 0.1 + Date: 2021-12-21 + + 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 3 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, see . +===========================================================================*/ + +module sound #( + parameter ROM_WIDTH +)( + input clk, + input reset, + + input [3:0] addr, + input [7:0] data_in, + input write, + + input [7:0] soundrom_data_out, + output reg [ROM_WIDTH-1:0] soundrom_addr, + output signed [11:0] audio_out + ); + +wire sample; // Is m5205 requesting sample data +reg [3:0] snd_data_in; // 4 bit data input to m5205 +reg [ROM_WIDTH-1:0] soundrom_addr_target; // Current sample end position + +reg [7:0] volume; // Sound output volume +reg m5205_ce; // Counter for 375KHz clock enable +reg m5205_phase; // Memory address phase counter - 0 = 4 high bits, 1 = 4 low bits +reg playing; // Is sound playing +reg [13:0] ce_counter; // Counter for 375KHz clock enable + +always @(posedge clk) +begin + if(reset) + begin + // Clear all signals on reset + ce_counter <= 14'd0; + soundrom_addr <= {ROM_WIDTH{1'b0}}; + soundrom_addr_target <= {ROM_WIDTH{1'b0}}; + playing <= 1'b0; + end + + // Generate 375Khz clock enable + m5205_ce <= (ce_counter == 14'd0); + if(ce_counter == 14'd63) + begin + ce_counter <= 14'd0; + end + else + begin + ce_counter <= ce_counter + 14'd1; + end + + if(write) + begin + // Disable playback when CPU is sending commands + playing <= 1'b0; + case (addr[3:2]) + 2'd0: + begin + // Set initial address (sample beginning) + soundrom_addr[{addr[0],3'd0} +: 8] <= data_in; + end + 2'd1: + begin + // Set target address (sample end) + soundrom_addr_target[{addr[0],3'd0} +: 8] <= data_in; + end + 2'd2: + begin + // Trigger play + //$display("playing write: start=%d end=%d", soundrom_addr, soundrom_addr_target); + ce_counter <= 14'd0; + playing <= 1'b1; + end + 2'd3: + begin + // Set volume + $display("set volume: %d", data_in); + volume <= data_in; + end + default: + begin + + end + endcase + end + + // Generate m5205 data input + if(playing) + begin + // If playing and m5205 is requesting a sample, load 4 bits from ROM and shift phase for next read + if(sample) + begin + // Shift phase for next read + m5205_phase <= m5205_phase + 1'd1; + if(m5205_phase == 1'b1) + begin + // Increment music ROM address + soundrom_addr <= soundrom_addr + {{ROM_WIDTH-1{1'b0}},1'b1}; + // Get 4 low bits from ROM + snd_data_in <= soundrom_data_out[3:0]; + // If target address has been reach, stop playing + if(soundrom_addr_target == soundrom_addr) playing <= 1'b0; + end + else + begin + // Get 4 high bits from ROM + snd_data_in <= soundrom_data_out[7:4]; + end + end + end + else + begin + snd_data_in <= 4'd0; + end + +end + +// M5205 +jt5205 #(.INTERPOL(0)) m5205( + .rst(~playing), // Hold reset while sound is not playing so it can return to zero + .clk(clk), + .cen(m5205_ce), // 375Khz clock enable + .sel(2'b10), // 8Khz sample rate + .din(snd_data_in), + .sound(audio_out), + .sample(sample), // Requesting a sample + .irq(), + .vclk_o() +); + +endmodule \ No newline at end of file diff --git a/rtl/spram.v b/rtl/spram.v index c37bed8..b226dfa 100644 --- a/rtl/spram.v +++ b/rtl/spram.v @@ -36,7 +36,7 @@ reg [data_width-1:0] mem [ramLength-1:0]; always @(posedge clock) begin q <= mem[address]; if(wren) begin - q <= data; + //q <= data; mem[address] <= data; end end diff --git a/rtl/sprite.hex b/rtl/sprite.hex new file mode 100644 index 0000000..b175b2a --- /dev/null +++ b/rtl/sprite.hex @@ -0,0 +1,865 @@ + 00 06 10 06 35 06 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 01 02 03 04 05 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 03 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 04 00 00 00 04 01 01 01 01 02 + 02 02 02 02 02 03 00 00 00 00 04 02 02 01 01 01 + 01 02 02 02 02 02 05 00 00 04 03 03 03 03 03 03 + 03 03 03 03 03 03 05 00 00 00 01 03 03 03 03 03 + 03 03 03 03 03 03 00 00 00 00 00 00 00 00 00 00 + 00 00 04 03 03 04 04 00 00 00 02 03 04 05 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 04 02 02 03 04 04 05 00 00 04 03 03 05 00 00 00 + 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 04 + 01 02 03 04 05 00 00 00 00 01 03 04 00 00 00 00 + 00 00 00 00 00 01 00 00 00 00 00 00 00 00 04 02 + 02 03 04 05 00 00 00 00 00 02 03 05 00 00 00 00 + 00 00 00 00 00 02 00 00 00 00 00 00 04 01 02 03 + 03 05 00 00 00 00 00 00 04 03 03 00 00 00 00 00 + 00 00 00 00 04 03 00 00 00 00 00 04 02 02 03 03 + 05 00 00 00 00 00 00 00 01 03 04 00 00 00 00 00 + 00 00 00 00 01 03 00 00 00 04 01 02 03 03 04 05 + 00 00 00 00 00 00 00 00 02 03 05 00 00 00 00 00 + 00 00 00 00 02 03 00 00 00 01 02 03 03 05 00 00 + 00 00 00 00 00 00 00 00 02 03 00 00 00 00 00 00 + 00 00 00 04 03 03 00 00 00 02 02 03 03 03 02 01 + 01 02 02 04 05 00 00 00 03 03 03 02 02 01 01 02 + 02 02 03 03 03 04 00 00 00 04 03 03 03 03 03 03 + 03 03 03 03 04 05 00 00 04 03 03 03 03 03 03 03 + 03 03 03 03 04 05 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 02 05 00 00 00 00 00 00 04 02 + 01 01 01 01 02 02 02 05 00 00 00 00 00 04 02 01 + 01 01 01 02 02 02 03 03 00 00 00 00 00 01 03 03 + 03 03 03 03 03 03 03 04 05 00 00 00 04 02 03 03 + 03 03 03 03 03 03 02 03 00 00 00 00 04 02 03 04 + 05 00 00 00 00 04 03 03 04 00 00 00 01 03 03 04 + 05 00 00 00 00 04 03 03 00 00 00 00 01 03 04 05 + 00 00 00 00 00 00 02 03 03 00 00 04 02 03 05 00 + 00 00 00 00 00 00 03 04 00 00 00 00 02 03 05 00 + 00 00 00 00 00 00 02 03 04 00 00 01 03 04 00 00 + 00 00 00 00 00 00 03 05 00 00 00 04 02 03 00 00 + 00 00 00 00 00 04 03 03 05 00 00 02 03 05 00 00 + 00 00 00 00 00 04 04 00 00 00 00 01 03 03 05 00 + 00 00 00 00 04 02 03 04 00 00 04 03 03 03 02 01 + 01 01 02 02 02 03 04 00 00 00 00 02 03 03 03 02 + 01 01 02 02 03 03 04 05 00 00 01 03 03 03 03 03 + 03 03 03 03 03 03 05 00 00 00 04 02 03 03 03 03 + 03 03 03 03 03 04 05 00 00 00 02 03 03 04 05 00 + 00 00 00 00 04 03 00 00 00 00 01 03 03 05 05 02 + 03 03 03 03 05 00 00 00 00 00 02 03 05 00 00 00 + 00 00 00 04 02 03 00 00 00 00 02 03 03 00 00 05 + 02 03 03 03 03 04 00 00 00 00 03 03 03 03 02 01 + 01 02 02 03 03 03 00 00 00 00 04 03 05 00 00 00 + 00 05 02 03 03 04 05 00 00 00 04 03 03 03 03 03 + 03 03 03 03 03 04 00 00 00 00 00 00 00 00 00 00 + 00 00 00 05 03 03 04 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 02 + 05 00 00 00 00 00 02 04 00 00 00 00 04 03 05 00 + 00 00 00 00 00 00 00 00 00 00 00 00 04 01 03 03 + 04 00 00 00 00 00 03 03 05 00 00 00 01 03 04 00 + 00 00 00 00 00 00 00 00 00 00 00 04 02 03 03 03 + 03 00 00 00 00 00 03 03 04 00 00 00 02 03 05 00 + 00 00 00 00 00 00 00 00 00 00 00 01 03 03 05 03 + 03 05 00 00 00 00 04 03 03 00 00 04 03 03 00 00 + 00 00 00 00 00 00 00 00 00 00 04 02 03 03 00 03 + 03 04 00 00 00 00 02 03 04 00 00 01 03 04 00 00 + 00 00 00 00 00 00 00 00 00 04 02 03 03 05 00 04 + 03 03 00 00 00 00 03 03 05 00 00 02 03 05 00 00 + 00 00 00 00 00 00 00 00 04 02 03 03 05 00 00 04 + 03 03 05 00 00 00 03 04 00 00 00 02 03 00 00 00 + 00 00 00 00 00 00 00 00 01 03 03 03 02 01 01 02 + 03 03 04 00 00 00 03 05 00 00 04 03 03 00 00 00 + 00 00 00 00 00 00 00 04 02 03 03 03 03 03 03 03 + 03 03 03 00 00 00 03 00 00 00 01 03 04 00 00 00 + 00 00 00 00 00 00 04 02 03 03 04 05 00 00 00 00 + 04 03 03 00 00 00 03 00 00 00 02 03 05 00 00 00 + 00 00 00 00 00 04 01 03 04 05 00 00 00 00 00 00 + 00 01 03 05 00 00 04 00 00 00 03 03 03 02 01 01 + 01 02 03 04 00 02 03 03 05 00 00 00 00 00 00 00 + 00 02 03 04 00 00 05 00 00 00 04 03 03 03 03 03 + 03 03 04 05 00 04 03 04 00 00 00 00 00 00 00 00 + 00 04 03 03 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 04 01 03 00 00 00 00 00 00 00 + 00 04 01 02 00 00 04 01 03 00 00 00 00 00 00 00 + 00 04 01 02 00 00 02 03 03 05 00 00 00 00 00 00 + 04 01 03 03 00 00 02 03 03 05 00 00 00 00 00 00 + 04 01 03 03 00 00 04 01 03 03 05 00 00 00 00 04 + 02 03 03 05 00 00 04 01 03 03 05 00 00 00 00 04 + 02 03 03 05 00 00 00 04 02 03 03 05 00 04 01 02 + 03 03 05 00 00 00 00 04 02 03 03 05 00 04 01 02 + 03 03 05 00 00 00 00 00 04 02 03 03 05 02 03 03 + 03 05 00 00 00 00 00 00 04 02 03 03 05 02 03 03 + 03 05 00 00 00 00 00 00 00 04 02 03 03 03 03 03 + 05 00 00 00 00 00 00 00 00 04 02 03 03 03 03 03 + 05 00 00 00 00 00 00 00 00 00 04 03 03 03 03 05 + 00 00 00 00 00 00 00 00 00 00 04 03 03 03 03 05 + 00 00 00 00 00 00 00 00 00 04 02 03 03 03 03 00 + 00 00 00 00 00 00 00 00 00 04 02 03 03 03 03 00 + 00 00 00 00 00 00 00 00 04 01 03 03 03 03 03 05 + 00 00 00 00 00 00 00 00 04 01 03 03 03 03 03 05 + 00 00 00 00 00 00 04 01 02 03 03 05 04 02 03 03 + 05 00 00 00 00 00 04 01 02 03 03 05 04 02 03 03 + 05 00 00 00 00 00 02 03 03 03 05 00 00 04 02 03 + 03 05 00 00 00 00 02 03 03 03 05 00 00 04 02 03 + 03 05 00 00 00 05 04 03 03 05 00 00 00 00 04 03 + 03 04 00 00 00 00 04 03 03 05 00 00 00 00 04 03 + 03 04 00 00 00 04 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 05 04 03 02 01 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 01 01 02 02 + 00 00 00 00 00 00 00 00 00 00 00 00 01 03 03 02 + 02 04 00 00 00 00 00 00 00 00 00 01 01 03 03 04 + 02 02 00 00 00 00 00 00 00 00 01 03 03 02 03 03 + 02 02 00 00 00 00 00 00 00 00 02 03 02 02 03 02 + 02 04 00 00 00 00 00 00 00 00 00 04 02 03 02 02 + 04 00 00 00 00 00 00 00 00 00 00 00 00 00 04 04 + 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 01 01 01 03 00 + 00 00 00 00 00 00 00 00 00 00 01 01 03 03 03 02 + 00 00 00 00 00 00 00 00 00 00 01 03 03 02 02 03 + 02 00 00 00 00 00 00 00 00 01 01 02 03 01 03 03 + 02 04 00 00 00 00 00 00 00 01 03 03 03 03 02 02 + 03 02 00 00 00 00 00 00 00 00 03 03 02 04 02 03 + 02 04 00 00 00 00 00 00 00 00 00 02 03 02 02 02 + 04 00 00 00 00 00 00 00 00 00 00 04 02 03 02 04 + 00 00 00 00 00 00 00 00 00 00 00 00 04 02 04 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 01 01 03 00 00 + 00 00 00 00 00 00 00 00 00 00 01 01 03 03 03 01 + 01 00 00 00 00 00 00 00 00 00 01 03 02 03 03 03 + 03 03 00 00 00 00 00 00 00 03 03 03 02 02 03 02 + 02 04 00 00 00 00 00 00 00 01 03 02 02 04 03 02 + 02 04 00 00 00 00 00 00 00 01 03 02 04 01 03 02 + 02 00 00 00 00 00 00 00 00 03 03 02 02 03 02 02 + 04 00 00 00 00 00 00 00 00 03 02 04 02 03 03 02 + 00 00 00 00 00 00 00 00 00 04 02 02 02 02 03 00 + 00 00 00 00 00 00 00 00 00 00 02 04 00 02 04 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 03 03 01 01 00 + 00 00 00 00 00 00 00 00 00 01 01 02 03 03 02 02 + 02 00 00 00 00 00 00 00 00 01 02 03 03 02 02 02 + 03 04 00 00 00 00 00 00 01 01 03 03 02 03 03 03 + 03 03 03 00 00 00 00 00 01 01 03 02 02 03 04 02 + 02 03 03 04 00 00 00 00 01 03 02 02 02 02 02 02 + 02 03 02 04 00 00 00 00 03 03 03 03 02 02 02 02 + 02 03 02 02 00 00 00 00 03 01 03 03 02 02 02 04 + 02 03 02 00 00 00 00 00 03 03 03 02 02 02 03 02 + 02 02 00 00 00 00 00 00 00 02 03 03 03 03 04 02 + 04 00 00 00 00 00 00 00 00 00 00 00 04 04 02 02 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 01 + 01 00 00 00 00 00 00 00 00 00 01 01 03 02 03 03 + 03 03 00 00 00 00 00 00 00 01 01 02 03 04 03 03 + 03 04 04 00 00 00 00 00 00 01 03 03 03 02 03 03 + 02 02 03 00 00 00 00 00 00 01 02 02 03 03 03 02 + 04 02 00 00 00 00 00 00 00 03 03 04 03 03 02 04 + 02 02 00 00 00 00 00 00 00 03 03 02 03 03 03 02 + 03 03 03 00 00 00 00 00 00 01 03 03 03 02 03 02 + 03 03 02 00 00 00 00 00 00 01 02 03 03 03 02 02 + 03 02 04 04 00 00 00 00 01 03 02 04 03 03 02 03 + 03 02 04 00 00 00 00 00 00 04 02 02 02 03 02 03 + 02 04 00 00 00 00 00 00 00 00 02 02 03 02 02 04 + 00 00 00 00 00 00 00 00 00 00 00 02 02 02 04 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 + 03 03 03 01 00 00 00 00 00 00 00 00 01 01 01 02 + 03 03 03 03 00 00 00 00 00 01 01 03 03 01 02 04 + 02 03 03 03 00 00 00 00 01 01 03 02 03 01 03 02 + 04 03 03 02 00 00 00 01 01 03 03 04 03 03 03 03 + 02 01 03 02 00 00 00 04 02 03 03 02 03 03 03 03 + 03 03 02 02 04 00 00 00 02 02 02 03 03 03 03 02 + 02 02 02 02 04 00 00 00 00 00 02 02 03 03 02 02 + 04 00 00 00 00 00 00 00 00 00 00 02 02 02 02 04 + 00 00 00 00 00 00 00 00 00 00 00 04 02 02 04 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 01 01 00 00 00 + 01 01 00 00 00 00 00 00 00 01 01 02 01 03 03 03 + 03 03 03 00 00 00 00 00 00 01 04 02 02 03 04 03 + 03 03 04 04 00 00 00 00 01 01 03 02 03 03 02 03 + 03 02 02 03 00 00 00 01 01 01 03 02 03 03 03 03 + 03 02 02 03 00 00 00 01 01 03 03 04 02 03 02 02 + 03 03 02 02 00 00 00 01 03 03 03 03 03 03 02 03 + 03 03 03 03 00 00 00 02 02 03 03 03 03 03 03 03 + 02 03 03 02 02 00 00 00 02 03 02 02 03 03 02 03 + 02 03 02 04 04 00 00 00 00 03 04 02 02 03 03 03 + 03 03 02 02 00 00 00 00 00 02 02 02 02 02 03 02 + 03 02 04 00 00 00 00 00 00 00 00 02 02 03 02 02 + 02 00 00 00 00 00 00 00 00 00 00 00 04 02 02 04 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 01 01 01 01 03 00 00 + 00 02 04 00 00 00 00 00 00 03 01 03 03 02 02 02 + 02 02 02 04 00 00 00 00 01 01 03 03 03 03 03 03 + 02 03 03 02 00 00 00 01 01 02 03 03 02 03 03 03 + 03 04 02 02 04 00 01 03 01 02 03 03 03 03 03 03 + 03 03 02 02 02 00 01 01 03 03 03 02 03 03 03 03 + 02 03 02 02 00 00 01 03 02 03 03 03 03 03 02 02 + 02 03 03 03 02 00 00 01 03 03 02 03 03 03 03 03 + 02 02 03 03 02 04 01 01 03 03 03 03 03 02 03 03 + 02 04 03 02 02 04 01 01 03 02 03 03 03 03 03 02 + 03 03 03 02 04 00 01 02 03 02 03 03 03 03 02 03 + 03 03 02 02 04 00 00 01 02 04 02 03 02 03 04 03 + 03 02 02 04 00 00 00 00 02 02 03 03 03 03 03 03 + 02 02 04 04 00 00 00 00 00 04 02 02 02 03 02 02 + 02 02 00 00 00 00 00 00 00 00 00 00 02 04 02 04 + 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 01 02 01 00 + 00 00 00 00 00 00 00 00 00 00 00 01 02 02 02 02 + 00 00 00 00 00 00 00 00 00 00 00 02 02 03 03 02 + 00 00 00 00 00 00 00 00 00 00 00 02 03 04 03 02 + 00 00 00 00 00 00 00 00 00 00 00 02 02 03 02 02 + 00 00 00 00 00 00 00 00 00 00 00 01 02 02 02 01 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 01 02 02 01 00 + 00 00 00 00 00 00 00 00 00 00 01 02 03 02 02 01 + 00 00 00 00 00 00 00 00 00 01 02 02 03 02 02 02 + 01 00 00 00 00 00 00 00 00 02 02 02 03 03 03 02 + 02 01 00 00 00 00 00 00 00 02 03 03 04 04 03 02 + 02 02 00 00 00 00 00 00 00 02 03 04 04 04 04 03 + 03 02 00 00 00 00 00 00 00 02 02 03 03 04 04 03 + 02 02 00 00 00 00 00 00 00 01 02 02 03 03 03 02 + 02 01 00 00 00 00 00 00 00 00 01 02 02 02 02 02 + 01 00 00 00 00 00 00 00 00 00 00 01 02 02 01 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 + 00 00 00 00 00 00 00 00 00 00 01 02 02 02 02 02 + 02 01 00 00 00 00 00 00 00 01 02 03 03 03 03 03 + 03 02 01 00 00 00 00 00 01 02 03 03 04 04 03 03 + 03 03 02 01 00 00 00 00 02 03 03 04 04 04 04 04 + 03 03 02 02 01 00 00 01 02 03 04 04 00 00 04 04 + 04 03 03 02 02 00 00 02 03 03 04 00 00 00 00 00 + 04 04 03 03 02 00 00 02 03 03 04 00 00 00 00 00 + 00 04 04 03 02 00 00 02 03 03 04 04 00 00 00 00 + 04 04 03 03 02 00 00 02 02 03 03 04 04 00 00 04 + 04 03 03 03 02 00 00 01 02 02 03 03 04 04 04 04 + 03 03 03 02 02 00 00 00 01 02 02 03 03 04 04 03 + 03 03 02 02 01 00 00 00 00 01 02 02 03 03 03 03 + 02 02 02 01 00 00 00 00 00 00 01 02 02 03 03 02 + 02 01 00 00 00 00 00 00 00 00 00 00 02 02 02 01 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 01 02 01 00 00 + 00 00 00 00 00 00 00 00 00 01 02 03 03 04 04 03 + 03 02 01 00 00 00 00 00 01 02 03 04 04 04 04 04 + 04 03 02 01 00 00 00 00 02 03 04 04 04 00 00 04 + 04 04 03 02 01 00 00 01 03 04 04 00 00 00 00 00 + 04 04 04 03 02 00 00 02 03 04 00 00 00 00 00 00 + 00 04 04 04 03 00 00 03 04 00 00 00 00 00 00 00 + 00 00 04 04 03 00 00 04 04 00 00 00 00 00 00 00 + 00 00 00 04 04 00 00 04 04 00 00 00 00 00 00 00 + 00 00 04 04 04 00 00 03 04 04 00 00 00 00 00 00 + 00 00 04 04 03 00 00 02 03 04 04 00 00 00 00 00 + 00 04 04 04 03 00 00 01 02 03 04 04 04 00 00 00 + 04 04 04 03 02 00 00 00 01 02 03 04 04 04 00 04 + 04 04 03 02 01 00 00 00 00 01 02 03 04 04 04 04 + 03 02 01 00 00 00 00 00 00 00 00 01 02 03 03 02 + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 01 01 00 + 00 00 00 00 00 00 00 00 00 00 00 00 01 02 02 01 + 00 00 00 00 00 00 00 00 00 00 00 01 02 04 03 02 + 00 00 00 00 00 00 00 00 00 00 00 01 02 03 02 01 + 00 00 00 00 00 00 00 00 00 00 00 00 01 02 01 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 01 02 01 00 + 00 00 00 00 00 00 00 00 00 00 00 00 01 02 02 01 + 00 00 00 00 00 00 00 00 00 00 00 01 02 03 03 02 + 01 00 00 00 00 00 00 00 00 00 01 02 03 04 04 03 + 02 02 01 00 00 00 00 00 00 01 02 02 02 03 04 02 + 01 00 00 00 00 00 00 00 00 00 00 01 02 02 03 02 + 00 00 00 00 00 00 00 00 00 00 00 00 00 01 02 01 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 01 02 01 + 00 00 00 00 00 00 00 00 00 00 00 00 00 02 03 02 + 00 00 00 00 00 00 00 00 00 00 00 00 01 02 03 02 + 01 00 00 00 00 00 00 00 00 00 00 01 02 03 04 03 + 02 01 00 00 00 00 00 00 00 01 02 02 03 04 00 04 + 03 02 01 00 00 00 00 00 00 02 03 03 04 00 00 04 + 03 02 02 00 00 00 00 00 00 01 02 02 03 04 04 03 + 02 01 00 00 00 00 00 00 00 00 00 01 02 03 04 03 + 02 00 00 00 00 00 00 00 00 00 00 00 01 02 03 02 + 01 00 00 00 00 00 00 00 00 00 00 00 00 01 02 01 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 01 02 01 + 00 00 00 00 00 00 00 00 00 00 00 00 00 02 03 02 + 00 00 00 00 00 00 00 00 00 00 00 00 01 02 00 02 + 01 00 00 00 00 00 00 00 00 00 00 01 02 03 00 03 + 02 01 00 00 00 00 00 00 00 01 02 02 00 00 00 00 + 00 02 01 00 00 00 00 00 00 02 03 00 00 00 00 00 + 00 02 02 00 00 00 00 00 00 01 02 02 00 00 00 00 + 02 01 00 00 00 00 00 00 00 00 00 01 02 00 00 03 + 02 00 00 00 00 00 00 00 00 00 00 00 01 02 03 02 + 01 00 00 00 00 00 00 00 00 00 00 00 00 01 02 01 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 03 02 03 + 00 00 00 00 00 00 00 00 00 00 00 00 03 03 04 02 + 01 00 00 00 00 00 00 00 00 00 03 02 02 04 02 02 + 02 02 01 00 00 00 00 00 00 00 00 00 03 02 02 01 + 01 00 00 00 00 00 00 00 00 00 00 00 00 01 02 01 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 05 05 00 + 00 00 00 00 00 00 00 00 00 00 00 00 05 06 06 05 + 00 00 00 00 00 00 00 00 00 00 00 05 06 07 05 08 + 09 00 00 00 00 00 00 00 00 00 00 05 06 05 08 09 + 09 00 00 00 00 00 00 00 00 00 00 00 05 08 09 09 + 00 00 00 00 00 00 00 00 00 00 00 00 00 09 09 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 0a 0a 00 + 00 00 00 00 00 00 00 00 00 00 00 00 0a 07 0b 0c + 00 00 00 00 00 00 00 00 00 00 00 00 0a 0b 0c 0d + 00 00 00 00 00 00 00 00 00 00 00 00 00 0c 0d 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 07 0e 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 0e 0f 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 02 02 02 02 00 00 + 02 02 00 00 00 00 00 00 00 00 02 00 00 00 00 02 + 00 00 02 00 00 00 00 00 00 00 02 00 00 00 00 02 + 00 00 02 00 00 00 00 00 00 00 02 02 02 00 00 02 + 00 00 02 00 00 00 00 00 00 00 00 00 00 02 00 02 + 00 00 02 00 00 00 00 00 00 00 00 00 00 02 00 02 + 00 00 02 00 00 00 00 00 00 00 00 00 00 02 00 02 + 00 00 02 00 00 00 00 00 00 00 02 02 02 00 00 00 + 02 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 08 00 00 08 08 00 00 + 00 08 08 00 00 00 00 00 08 08 00 08 00 00 08 00 + 08 00 00 08 00 00 00 00 00 08 00 08 00 00 08 00 + 08 00 00 08 00 00 00 00 00 08 00 08 00 00 08 00 + 08 00 00 08 00 00 00 00 00 08 00 08 00 00 08 00 + 08 00 00 08 00 00 00 00 00 08 00 08 00 00 08 00 + 08 00 00 08 00 00 00 00 00 08 00 08 00 00 08 00 + 08 00 00 08 00 00 00 00 00 08 00 00 08 08 00 00 + 00 08 08 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 0b 00 0b 0b 0b 0b 00 + 00 0b 0b 00 00 00 00 00 0b 0b 00 0b 00 00 00 00 + 0b 00 00 0b 00 00 00 00 00 0b 00 0b 00 00 00 00 + 0b 00 00 0b 00 00 00 00 00 0b 00 0b 0b 0b 00 00 + 0b 00 00 0b 00 00 00 00 00 0b 00 00 00 00 0b 00 + 0b 00 00 0b 00 00 00 00 00 0b 00 00 00 00 0b 00 + 0b 00 00 0b 00 00 00 00 00 0b 00 00 00 00 0b 00 + 0b 00 00 0b 00 00 00 00 00 0b 00 0b 0b 0b 00 00 + 00 0b 0b 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 0f 0f 00 00 00 0f 0f 00 + 00 00 0f 0f 00 00 00 0f 00 00 0f 00 0f 00 00 0f + 00 0f 00 00 0f 00 00 00 00 00 0f 00 0f 00 00 0f + 00 0f 00 00 0f 00 00 00 00 00 0f 00 0f 00 00 0f + 00 0f 00 00 0f 00 00 00 00 0f 00 00 0f 00 00 0f + 00 0f 00 00 0f 00 00 00 0f 00 00 00 0f 00 00 0f + 00 0f 00 00 0f 00 00 0f 00 00 00 00 0f 00 00 0f + 00 0f 00 00 0f 00 00 0f 0f 0f 0f 00 00 0f 0f 00 + 00 00 0f 0f 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 00 + 00 00 00 00 00 00 00 00 00 00 00 00 06 07 07 06 + 00 00 00 00 00 00 00 00 00 00 00 00 06 07 07 06 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 00 + 00 00 00 00 00 00 00 00 00 00 00 00 06 07 07 06 + 00 00 00 00 00 00 00 00 00 00 00 06 07 06 06 07 + 06 00 00 00 00 00 00 00 00 00 00 06 07 06 06 07 + 06 00 00 00 00 00 00 00 00 00 00 00 06 07 07 06 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 00 + 00 00 00 00 00 00 00 00 00 00 00 00 06 07 07 06 + 00 00 00 00 00 00 00 00 00 00 00 06 07 06 06 07 + 06 00 00 00 00 00 00 00 00 00 06 07 06 00 00 06 + 07 06 00 00 00 00 00 00 00 00 06 07 06 00 00 06 + 07 06 00 00 00 00 00 00 00 00 00 06 07 06 06 07 + 06 00 00 00 00 00 00 00 00 00 00 00 06 07 07 06 + 00 00 00 00 00 00 00 00 00 00 00 00 00 06 06 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 06 + 00 00 00 00 00 00 00 00 00 00 00 06 07 07 07 07 + 06 00 00 00 00 00 00 00 00 00 06 07 07 06 06 07 + 07 06 00 00 00 00 00 00 00 06 07 07 06 00 00 06 + 07 07 06 00 00 00 00 00 00 06 07 06 00 00 00 00 + 06 07 06 00 00 00 00 00 00 06 07 06 00 00 00 00 + 06 07 06 00 00 00 00 00 00 06 07 07 06 00 00 06 + 07 07 06 00 00 00 00 00 00 00 06 07 07 06 06 07 + 07 06 00 00 00 00 00 00 00 00 00 06 07 07 07 07 + 06 00 00 00 00 00 00 00 00 00 00 00 06 06 06 06 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 06 + 00 00 00 00 00 00 00 00 00 00 06 06 07 07 07 07 + 06 06 00 00 00 00 00 00 00 06 07 07 07 06 06 07 + 07 07 06 00 00 00 00 00 00 06 07 06 06 00 00 06 + 06 07 06 00 00 00 00 00 06 07 07 06 00 00 00 00 + 06 07 07 06 00 00 00 00 06 07 06 00 00 00 00 00 + 00 06 07 06 00 00 00 00 06 07 06 00 00 00 00 00 + 00 06 07 06 00 00 00 00 06 07 07 06 00 00 00 00 + 06 07 07 06 00 00 00 00 00 06 07 06 06 00 00 06 + 06 07 06 00 00 00 00 00 00 06 07 07 07 06 06 07 + 07 07 06 00 00 00 00 00 00 00 06 06 07 07 07 07 + 06 06 00 00 00 00 00 00 00 00 00 00 06 06 06 06 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 06 + 00 00 00 00 00 00 00 00 00 00 06 06 07 07 07 07 + 06 06 00 00 00 00 00 00 00 06 07 07 07 06 06 07 + 07 07 06 00 00 00 00 00 06 07 07 06 06 00 00 06 + 06 07 07 06 00 00 00 00 06 07 06 00 00 00 00 00 + 00 06 07 06 00 00 00 06 07 07 06 00 00 00 00 00 + 00 06 07 07 06 00 00 06 07 06 00 00 00 00 00 00 + 00 00 06 07 06 00 00 06 07 06 00 00 00 00 00 00 + 00 00 06 07 06 00 00 06 07 07 06 00 00 00 00 00 + 00 06 07 07 06 00 00 00 06 07 06 00 00 00 00 00 + 00 06 07 06 00 00 00 00 06 07 07 06 06 00 00 06 + 06 07 07 06 00 00 00 00 00 06 07 07 07 06 06 07 + 07 07 06 00 00 00 00 00 00 00 06 06 07 07 07 07 + 06 06 00 00 00 00 00 00 00 00 00 00 06 06 06 06 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 06 06 06 06 + 00 00 00 00 00 00 00 00 00 00 06 06 07 07 07 07 + 06 06 00 00 00 00 00 00 00 06 07 07 07 06 06 07 + 07 07 06 00 00 00 00 00 06 07 07 06 06 00 00 06 + 06 07 07 06 00 00 00 06 07 07 06 00 00 00 00 00 + 00 06 07 07 06 00 00 06 07 06 00 00 00 00 00 00 + 00 00 06 07 06 00 06 07 07 06 00 00 00 00 00 00 + 00 00 06 07 07 06 06 07 06 00 00 00 00 00 00 00 + 00 00 00 06 07 06 06 07 06 00 00 00 00 00 00 00 + 00 00 00 06 07 06 06 07 07 06 00 00 00 00 00 00 + 00 00 06 07 07 06 00 06 07 06 00 00 00 00 00 00 + 00 00 06 07 06 00 00 06 07 07 06 00 00 00 00 00 + 00 06 07 07 06 00 00 00 06 07 07 06 06 00 00 06 + 06 07 07 06 00 00 00 00 00 06 07 07 07 06 06 07 + 07 07 06 00 00 00 00 00 00 00 06 06 07 07 07 07 + 06 06 00 00 00 00 00 00 00 00 00 00 06 06 06 06 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 02 01 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 10 02 00 + 00 00 00 00 00 00 00 00 00 00 00 00 02 11 05 01 + 00 00 00 00 00 00 00 00 00 00 00 00 02 05 12 02 + 00 00 00 00 00 00 00 00 00 00 00 00 02 12 12 02 + 00 00 00 00 00 00 00 00 00 00 00 00 10 02 02 02 + 00 00 00 00 00 00 00 00 00 00 00 00 10 10 02 01 + 00 00 00 00 00 00 00 00 00 00 00 00 10 10 02 01 + 00 00 00 00 00 00 00 04 03 00 00 00 02 02 01 13 + 00 00 00 04 03 00 00 02 01 00 00 00 10 10 02 01 + 00 00 00 02 01 00 00 10 02 13 01 13 10 02 02 01 + 13 01 13 10 02 00 00 10 02 13 01 13 02 02 02 01 + 13 01 13 10 02 00 00 02 01 13 01 13 02 01 01 01 + 13 01 13 02 01 00 00 01 01 00 00 00 01 00 00 01 + 00 00 00 01 01 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 02 01 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 10 02 00 + 00 00 00 00 00 00 00 00 00 00 00 00 11 05 02 01 + 00 00 00 00 00 00 00 00 00 00 00 00 05 12 02 02 + 00 00 00 00 00 00 00 00 00 00 00 00 12 12 02 02 + 00 00 00 00 00 00 00 00 00 00 00 00 02 02 02 02 + 00 00 00 00 00 00 00 00 00 00 00 00 10 10 02 01 + 00 00 00 00 00 00 00 00 00 00 00 00 10 10 02 01 + 00 00 00 00 00 00 00 00 00 04 03 00 02 02 01 13 + 00 04 03 00 00 00 00 00 00 02 01 00 10 10 02 01 + 00 02 01 00 00 00 00 00 00 10 02 13 10 02 02 13 + 13 10 02 00 00 00 00 00 00 10 02 13 02 02 02 01 + 13 10 02 00 00 00 00 00 00 02 01 13 02 01 01 01 + 13 02 01 00 00 00 00 00 00 01 01 00 01 00 01 00 + 00 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 02 01 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 10 02 00 + 00 00 00 00 00 00 00 00 00 00 00 00 02 02 05 12 + 00 00 00 00 00 00 00 00 00 00 00 00 10 02 12 12 + 00 00 00 00 00 00 00 00 00 00 00 00 10 02 12 12 + 00 00 00 00 00 00 00 00 00 00 00 00 10 10 02 02 + 00 00 00 00 00 00 00 00 00 00 00 00 10 10 02 01 + 00 00 00 00 00 00 00 00 00 00 00 00 10 10 02 01 + 00 00 00 00 00 00 00 00 00 04 03 00 02 02 01 13 + 00 04 03 00 00 00 00 00 00 02 01 00 10 10 02 01 + 00 02 01 00 00 00 00 00 00 10 02 13 10 02 02 01 + 13 10 02 00 00 00 00 00 00 10 02 13 02 02 02 01 + 13 10 02 00 00 00 00 00 00 02 01 13 02 01 01 01 + 13 02 01 00 00 00 00 00 00 01 01 00 00 01 00 01 + 00 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 06 06 06 06 06 06 00 00 00 00 + 00 00 00 00 00 00 06 08 08 08 08 08 06 00 00 00 + 00 00 00 00 00 00 06 09 09 09 09 08 06 00 00 00 + 00 00 00 00 00 00 06 09 09 09 08 06 00 00 00 00 + 00 00 00 00 00 00 06 09 09 09 09 08 06 00 00 00 + 00 00 00 00 00 00 06 09 09 06 09 09 08 06 00 00 + 00 00 00 00 00 00 00 06 06 00 06 09 09 08 06 00 + 00 00 00 00 00 00 00 00 00 00 00 06 09 09 08 06 + 00 00 00 00 00 00 00 00 00 00 00 00 06 09 09 08 + 06 00 00 00 00 00 00 00 00 00 00 00 00 06 09 06 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 07 04 00 00 00 00 00 00 04 03 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 04 03 00 00 00 00 00 00 03 02 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 03 02 00 00 00 00 00 00 02 01 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 02 01 00 00 00 00 00 00 01 01 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 diff --git a/rtl/sprite_engine.v b/rtl/sprite_engine.v new file mode 100644 index 0000000..0aba34d --- /dev/null +++ b/rtl/sprite_engine.v @@ -0,0 +1,845 @@ +`timescale 1ns / 1ps +/*============================================================================ + Aznable (custom 8-bit computer system) - Comet (sprite engine) + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 0.1 + Date: 2021-10-31 + + 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 3 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, see . +===========================================================================*/ + +module sprite_engine #( + parameter SPRITE_RAM_WIDTH = 7, + parameter SPRITE_ROM_WIDTH = 14, + parameter SPRITE_POSITION_WIDTH = 9, + parameter SPRITE_COLRAM_WIDTH = 5, + parameter SPRITE_SIZE_WIDTH = 5 // Width of sprite size related operations +)( + input clk, + input reset, + input pause, + input hsync, + input vsync, + input vblank, + input [SPRITE_POSITION_WIDTH-1:0] hcnt, + input [SPRITE_POSITION_WIDTH-1:0] vcnt, + + input [7:0] spriterom_data_out, + input [7:0] spriteram_data_out, + input [15:0] palrom_data_out, + input [15:0] spritelbram_data_out, + input spritecollisionram_data_out, + + output reg [SPRITE_RAM_WIDTH-1:0] spriteram_addr, + output reg [SPRITE_COLRAM_WIDTH-1:0] spritecollisionram_addr, + output reg spritecollisionram_data_in, + output reg [SPRITE_ROM_WIDTH-1:0] sprom_addr, + output reg [7:0] palrom_addr, + output [SPRITE_POSITION_WIDTH:0] spritelbram_rd_addr, + output reg [SPRITE_POSITION_WIDTH:0] spritelbram_wr_addr, + + output reg spritelbram_wr, + output reg [15:0] spritelbram_data_in, + + output reg spritecollisionram_wr, + +`ifdef DEBUG_SPRITE_COLLISION + output reg [16:0] spritedebugram_addr_b, + output reg [7:0] spritedebugram_data_in_b, + input [7:0] spritedebugram_data_out_b, + output reg spritedebugram_wr_b, +`endif + + output [7:0] spr_r, + output [7:0] spr_g, + output [7:0] spr_b, + output spr_a +); + +// State machine constants +localparam SE_INIT = 0; +localparam SE_IDLE = 1; +localparam SE_WAIT = 2; +localparam SE_RESET = 3; +localparam SE_CLEAR_BUFFER = 4; +localparam SE_SETUP_READ_Y = 5; +localparam SE_READ_Y_UPPER = 6; +localparam SE_READ_Y_LOWER = 7; +localparam SE_CHECK_Y = 8; +localparam SE_READ_X_UPPER = 9; +localparam SE_READ_X_LOWER = 10; +localparam SE_SETUP_WRITE = 11; +localparam SE_GET_PIXEL = 12; +localparam SE_STAGE_PIXEL = 13; +localparam SE_WRITE_PIXEL = 14; +localparam SE_LINE_COMPLETE = 15; + +localparam SE_SETUP_LOAD_8x8_UPPER = 20; +localparam SE_SETUP_LOAD_8x8_LOWER = 21; +localparam SE_SETUP_LOAD_16x16_UPPER = 22; +localparam SE_SETUP_LOAD_16x16_LOWER = 23; +localparam SE_SETUP_LOAD_32x32_UPPER = 24; +localparam SE_SETUP_LOAD_32x32_LOWER = 25; + + +// Sprite line buffer has two slots - read and write. They alternate when hsync goes high. +reg spritelb_slot_rd = 1'b0; +reg spritelb_slot_wr = 1'b1; + +// Track last hsync value +reg hsync_last; + +// Sprite state machine control +reg [4:0] spr_state; +reg [4:0] spr_state_next; +// Sprite index counter and maximum sprite limit +reg [5:0] spr_index; +localparam spr_index_max = 6'd31; +// Sprite maximum sizes +localparam [6:0] spr_ram_item_width = 4; +localparam [SPRITE_POSITION_WIDTH-1:0] spr_line_max = 352; +reg [SPRITE_POSITION_WIDTH-1:0] spr_size; // Size of sprite in pixels (always square) +reg [SPRITE_POSITION_WIDTH-1:0] spr_x; // Sprite X position +reg [SPRITE_POSITION_WIDTH-1:0] spr_y; // Sprite Y position +reg spr_enable; // Sprite visibility enabled +reg spr_collide; // Sprite collision enabled +reg [1:0] spr_palette_index; // Sprite palette index +reg [5:0] spr_image_index; // Sprite image index +localparam [SPRITE_POSITION_WIDTH-1:0] spr_border_size = 32; // Sprite screen border width +reg [SPRITE_POSITION_WIDTH-1:0] spr_active_y; // Current active sprite engine Y +reg [SPRITE_SIZE_WIDTH:0] spr_pixel_index;// Current sprite X pixel +reg [SPRITE_ROM_WIDTH-1:0] spr_rom_offset; // Offset for current sprite size in image ROM +reg [9:0] spr_rom_y_offset; // Offset for current sprite Y line in image ROM + +localparam [SPRITE_POSITION_WIDTH-1:0] spr_size_8x8 = {{SPRITE_POSITION_WIDTH-5{1'b0}}, 5'd7}; +localparam [SPRITE_POSITION_WIDTH-1:0] spr_size_16x16 = {{SPRITE_POSITION_WIDTH-5{1'b0}}, 5'd15}; +localparam [SPRITE_POSITION_WIDTH-1:0] spr_size_32x32 = {{SPRITE_POSITION_WIDTH-5{1'b0}}, 5'd31}; +reg [SPRITE_ROM_WIDTH-1:0] spr_rom_offset_8x8; +reg [SPRITE_ROM_WIDTH-1:0] spr_rom_offset_16x16; +reg [SPRITE_ROM_WIDTH-1:0] spr_rom_offset_32x32; + + //`define CASVAL_DEBUG + //`define CASVAL_DEBUG_TIMES + //`define CASVAL_DEBUG_OUTLINE + +`ifdef CASVAL_DEBUG_TIMES +parameter SPR_TIMER_WIDTH = 11; +reg [SPR_TIMER_WIDTH-1:0] spr_timer_idle; +reg [SPR_TIMER_WIDTH-1:0] spr_linetime_max; +reg [SPR_TIMER_WIDTH-1:0] spr_timer_line; +`endif + +// Sprite engine outputs +assign spritelbram_rd_addr = {spritelb_slot_rd, (hcnt + spr_border_size)}; +assign spr_r = {spritelbram_data_out[4:0],spritelbram_data_out[4:2]}; +assign spr_g = {spritelbram_data_out[9:5],spritelbram_data_out[9:7]}; +assign spr_b = {spritelbram_data_out[14:10],spritelbram_data_out[14:12]}; +assign spr_a = spritelbram_data_out[15]; + +// Collision system +localparam CP_IDLE = 0; +localparam CP_WAIT = 1; +localparam CP_STAGE_PIXEL = 2; +localparam CP_CHECK_PIXEL = 3; +localparam CP_WRITE_PIXEL = 4; + +localparam CS_IDLE = 0; +localparam CS_WAIT = 1; +localparam CS_DETECT_BEGIN = 2; +localparam CS_DETECT = 3; +localparam CS_DETECT_COMPLETE = 4; + +reg [3:0] col_primary_state = CP_IDLE; +reg [3:0] col_primary_state_next; + +reg [3:0] col_secondary_state = CS_IDLE; +reg [3:0] col_secondary_state_next; + +reg [SPRITE_POSITION_WIDTH-1:0] col_x; +reg [4:0] col_spriteindex; + +reg [SPRITE_POSITION_WIDTH-1:0] col_buffer_primary_addr; +reg col_buffer_primary_wr; +reg [31:0] col_buffer_primary_data_in; +wire [31:0] col_buffer_primary_data_out; + +reg [SPRITE_POSITION_WIDTH-1:0] col_buffer_secondary_addr; +reg col_buffer_secondary_wr; +reg [31:0] col_buffer_secondary_data_in; +wire [31:0] col_buffer_secondary_data_out; + +reg [31:0] col_buffer_secondary_collisions; +wire [4:0] col_buffer_secondary_collisions_count1; +wire [4:0] col_buffer_secondary_collisions_count2; + +count count1 ( + .clk(clk), + .a(col_buffer_secondary_collisions), + .sum(col_buffer_secondary_collisions_count1) +); +count count2 ( + .clk(clk), + .a(col_buffer_secondary_data_out), + .sum(col_buffer_secondary_collisions_count2) +); + +reg col_buffer_primary_is_a; + +//`define CASVAL_COLLISION_PRIMARY_DEBUG +//`define CASVAL_COLLISION_SECONDARY_DEBUG +reg [15:0] col_secondary_timer; + +always @(posedge clk) +begin + + if(reset) + begin + spr_state <= SE_IDLE; + end + + hsync_last <= hsync; + + if(!pause) + begin + // Primary collision state machine - Takes stage pixel instruction from sprite engine state machine + col_secondary_timer <= col_secondary_timer + 16'd1; + case (col_primary_state) + + CP_IDLE: + begin + + end + + CP_WAIT: + begin + col_primary_state <= col_primary_state_next; + end + + CP_STAGE_PIXEL: + begin +`ifdef CASVAL_COLLISION_PRIMARY_DEBUG + $display("CP_STAGE_PIXEL: x=%d i=%d", col_x, col_spriteindex); +`endif + // Set primary buffer to read existing pixel + col_buffer_primary_addr <= col_x; + col_buffer_primary_wr <= 1'b0; + + //col_primary_state <= CP_CHECK_PIXEL; + col_primary_state_next <= CP_CHECK_PIXEL; + col_primary_state <= CP_WAIT; + end + + CP_CHECK_PIXEL: + begin +`ifdef CASVAL_COLLISION_PRIMARY_DEBUG + $display("CP_CHECK_PIXEL: x,y=%d,%d i=%d ra=%x do=%b m=%b di=%", col_x, spr_active_y, col_spriteindex, col_buffer_primary_addr, col_buffer_primary_data_out, (32'b1 << col_spriteindex),col_buffer_primary_data_out | (32'b1 << col_spriteindex)); +`endif + col_buffer_primary_data_in <= col_buffer_primary_data_out | (32'b1 << col_spriteindex); + col_buffer_primary_wr <= 1'b1; + col_primary_state <= CP_WRITE_PIXEL; + end + + CP_WRITE_PIXEL: + begin +`ifdef CASVAL_COLLISION_PRIMARY_DEBUG + $display("CP_WRITE_PIXEL: x,y=%d,%d i=%d - wa=%x di=%x do=%x", col_x, spr_active_y, col_spriteindex, col_buffer_primary_addr, col_buffer_primary_data_in, col_buffer_primary_data_out); +`endif + col_buffer_primary_wr <= 1'b0; + col_buffer_primary_data_in <= 32'b0; + col_primary_state <= CP_IDLE; + end + endcase + end +// Sprite engine state machine +`ifdef CASVAL_DEBUG_TIMES + spr_timer_line <= spr_timer_line + 1'b1; +`endif + case (spr_state) + SE_INIT: + begin +`ifdef CASVAL_DEBUG_TIMES + // Reset line timer maximum + spr_linetime_max <= {{SPR_TIMER_WIDTH-1{1'b0}},1'b1}; +`endif + // Start loading sprite ROM offsets + sprom_addr <= {SPRITE_ROM_WIDTH{1'b0}}; + spr_state <= SE_WAIT; + spr_state_next <= SE_SETUP_LOAD_32x32_UPPER; + end + + SE_SETUP_LOAD_32x32_UPPER: + begin +`ifdef CASVAL_DEBUG + $display("CASVAL->SE_SETUP_LOAD_32x32_UPPER: addr=%x dout=%x", sprom_addr, spriterom_data_out); +`endif + // Load upper byte of 32x32 image offset + spr_rom_offset_32x32[SPRITE_ROM_WIDTH-1:8] <= spriterom_data_out[SPRITE_ROM_WIDTH-9:0]; + // Increment sprite ROM address + sprom_addr <= sprom_addr + {{SPRITE_ROM_WIDTH-1{1'b0}},1'b1}; + // Move to next state + spr_state <= SE_WAIT; + spr_state_next <= SE_SETUP_LOAD_32x32_LOWER; + end + SE_SETUP_LOAD_32x32_LOWER: + begin +`ifdef CASVAL_DEBUG + $display("CASVAL->SE_SETUP_LOAD_32x32_LOWER: addr=%x dout=%x", sprom_addr, spriterom_data_out); +`endif + // Load lower byte of 32x32 image offset + spr_rom_offset_32x32[7:0] <= spriterom_data_out; + // Increment sprite ROM address + sprom_addr <= sprom_addr + {{SPRITE_ROM_WIDTH-1{1'b0}},1'b1}; + // Move to next state + spr_state <= SE_WAIT; + spr_state_next <= SE_SETUP_LOAD_16x16_UPPER; + end + + SE_SETUP_LOAD_16x16_UPPER: + begin +`ifdef CASVAL_DEBUG + $display("CASVAL->SE_SETUP_LOAD_16x16_UPPER: addr=%x dout=%x", sprom_addr, spriterom_data_out); +`endif + // Load upper byte of 16x16 image offset + spr_rom_offset_16x16[SPRITE_ROM_WIDTH-1:8] <= spriterom_data_out[SPRITE_ROM_WIDTH-9:0]; + // Increment sprite ROM address + sprom_addr <= sprom_addr + {{SPRITE_ROM_WIDTH-1{1'b0}},1'b1}; + // Move to next state + spr_state <= SE_WAIT; + spr_state_next <= SE_SETUP_LOAD_16x16_LOWER; + end + SE_SETUP_LOAD_16x16_LOWER: + begin +`ifdef CASVAL_DEBUG + $display("CASVAL->SE_SETUP_LOAD_16x16_LOWER: addr=%x dout=%x", sprom_addr, spriterom_data_out); +`endif + // Load lower byte of 16x16 image offset + spr_rom_offset_16x16[7:0] <= spriterom_data_out; + // Increment sprite ROM address + sprom_addr <= sprom_addr + {{SPRITE_ROM_WIDTH-1{1'b0}},1'b1}; + // Move to next state + spr_state <= SE_WAIT; + spr_state_next <= SE_SETUP_LOAD_8x8_UPPER; + end + + SE_SETUP_LOAD_8x8_UPPER: + begin +`ifdef CASVAL_DEBUG + $display("CASVAL->SE_SETUP_LOAD_8x8_UPPER: addr=%x dout=%x", sprom_addr, spriterom_data_out); +`endif + // Load upper byte of 8x8 image offset + spr_rom_offset_8x8[SPRITE_ROM_WIDTH-1:8] <= spriterom_data_out[SPRITE_ROM_WIDTH-9:0]; + // Increment sprite ROM address + sprom_addr <= sprom_addr + {{SPRITE_ROM_WIDTH-1{1'b0}},1'b1}; + // Move to next state + spr_state <= SE_WAIT; + spr_state_next <= SE_SETUP_LOAD_8x8_LOWER; + end + SE_SETUP_LOAD_8x8_LOWER: + begin +`ifdef CASVAL_DEBUG + $display("CASVAL->SE_SETUP_LOAD_8x8_LOWER: addr=%x dout=%x", sprom_addr, spriterom_data_out); +`endif + // Load lower byte of 8x8 image offset + spr_rom_offset_8x8[7:0] <= spriterom_data_out; + // Increment sprite ROM address + sprom_addr <= sprom_addr + {{SPRITE_ROM_WIDTH-1{1'b0}},1'b1}; + // Move to next state + spr_state <= SE_IDLE; + end + + SE_IDLE: + begin + // Wait for hsync to go high outside of reset + if(reset == 1'b0 && hsync && !hsync_last) + begin + // Rotate line buffer slots + spritelb_slot_rd <= spritelb_slot_rd + 1'b1; + spritelb_slot_wr <= spritelb_slot_wr + 1'b1; + // Calculate active Y line + spr_active_y <= (vcnt == 9'd255) ? spr_border_size : (vcnt + spr_border_size) + 9'd1; + + spr_state <= SE_RESET; + end +`ifdef CASVAL_DEBUG_TIMES + else + begin + spr_timer_idle <= spr_timer_idle + 1'b1; + end +`endif + end + + SE_WAIT: + begin + spr_state <= spr_state_next; + end + + SE_RESET: + begin + // Reset sprite index + spr_index <= 6'd0; + +`ifdef CASVAL_DEBUG_TIMES + $display("CASVAL->LEAVING SE_IDLE: vcnt = %d spr_active_y = %d", vcnt, spr_active_y); + $display("CASVAL->LEAVING SE_IDLE: spr_timer_idle = %d, spr_linetime_max=%d", spr_timer_idle, spr_linetime_max); + spr_timer_line <= {SPR_TIMER_WIDTH{1'b0}}; +`endif + + // Setup line buffer RAM for clear operation + spritelbram_wr_addr <= {spritelb_slot_wr, {SPRITE_POSITION_WIDTH{1'b0}}}; + spritelbram_wr <= 1'b1; + spritelbram_data_in <= 16'b0; + + spr_state <= SE_CLEAR_BUFFER; + end + + SE_CLEAR_BUFFER: + begin + if(spritelbram_wr_addr[8:0] < spr_line_max[8:0]) + begin + spritelbram_wr_addr <= spritelbram_wr_addr + 1'b1; + end + else + begin + // Disable line buffer write + spritelbram_wr <= 1'b0; + + spr_state <= SE_SETUP_READ_Y; + end + end + + SE_SETUP_READ_Y: + begin + // Setup address to read Y from sprite RAM + spriteram_addr <= spr_index * spr_ram_item_width; + + spr_state <= SE_WAIT; + spr_state_next <= SE_READ_Y_UPPER; + end + SE_READ_Y_UPPER: + begin +`ifdef CASVAL_DEBUG + $display("CASVAL->SE_READ_Y_UPPER: spr: %d addr=%x dout=%x", spr_index, spriteram_addr, spriteram_data_out); +`endif + // Read enable bit from sprite RAM + spr_enable <= spriteram_data_out[7]; + // Read collide bit from sprite RAM + spr_collide <= spriteram_data_out[6]; + // Read palette index bits from sprite RAM + spr_palette_index <= spriteram_data_out[5:4]; + // Read size bits from sprite RAM + spr_size <= (spriteram_data_out[3:2] == 2'd2 ? spr_size_8x8 : + spriteram_data_out[3:2] == 2'd1 ? spr_size_16x16 : + spriteram_data_out[3:2] == 2'd0 ? spr_size_32x32 : {SPRITE_POSITION_WIDTH{1'b0}}); + // Read Y upper 1 bit from sprite RAM + spr_y[8] <= spriteram_data_out[0]; + // Increment sprite RAM address + spriteram_addr <= spriteram_addr + 1'b1; + + spr_state <= SE_WAIT; + spr_state_next <= SE_READ_Y_LOWER; + end + SE_READ_Y_LOWER: + begin +`ifdef CASVAL_DEBUG + $display("CASVAL->SE_READ_Y_LOWER: spr: %d addr=%x dout=%x", spr_index, spriteram_addr, spriteram_data_out); +`endif + // Read Y lower 8 bits from sprite RAM + spr_y[7:0] <= spriteram_data_out; + // Increment sprite RAM address + spriteram_addr <= spriteram_addr + 1'b1; + + spr_state <= SE_CHECK_Y; + end + + SE_CHECK_Y: + begin +`ifdef CASVAL_DEBUG + //$display("CASVAL->SE_CHECK_Y: spr_index=%d y: %d", spr_index, spr_y); +`endif + //// If this sprite is enabled and current line is within sprite Y area + if(spr_enable==1'b1 && spr_active_y >= spr_y && spr_active_y <= spr_y + spr_size) + begin +`ifdef CASVAL_DEBUG + $display("SE_CHECK_Y PASSED: spr_index=%d", spr_index); +`endif + spr_state <= SE_READ_X_UPPER; + end + else + begin + // If no then move to next sprite or finish + if(spr_index == spr_index_max) + begin + spr_state <= SE_LINE_COMPLETE; + end + else + begin + // Increment sprite index + spr_index <= spr_index + 1'd1; + + spr_state <= SE_SETUP_READ_Y; + end + end + end + + SE_READ_X_UPPER: + begin +`ifdef CASVAL_DEBUG + $display("CASVAL->SE_READ_X_UPPER: addr=%x dout=%x", spriteram_addr, spriteram_data_out); +`endif + // Read image index 6 bits from sprite RAM + spr_image_index <= spriteram_data_out[7:2]; + + // Read X upper 1 bit from sprite RAM + spr_x[8] <= spriteram_data_out[0]; + // Increment sprite RAM address + spriteram_addr <= spriteram_addr + 1'b1; + + spr_state <= SE_WAIT; + spr_state_next <= SE_READ_X_LOWER; + end + SE_READ_X_LOWER: + begin +`ifdef CASVAL_DEBUG + $display("CASVAL->SE_READ_X_LOWER: addr=%x dout=%x", spriteram_addr, spriteram_data_out); +`endif + // Read X lower 8 bits from sprite RAM + spr_x[7:0] <= spriteram_data_out; + // Set up offset for sprite ROM read + spr_rom_y_offset <= spr_active_y - spr_y; + // Set up ROM offset for sprite size + case(spr_size) + spr_size_32x32: spr_rom_offset <= spr_rom_offset_32x32; + spr_size_16x16: spr_rom_offset <= spr_rom_offset_16x16; + default: spr_rom_offset <= spr_rom_offset_8x8; + endcase + + spr_state <= SE_SETUP_WRITE; + end + + SE_SETUP_WRITE: + begin +`ifdef CASVAL_DEBUG + $display("CASVAL->SE_SETUP_WRITE: AY: %d Y: %d X: %d I: %d O: %d", spr_active_y, spr_y, spr_x, spr_image_index, spr_rom_y_offset); +`endif + // Enable line buffer write + spritelbram_wr <= 1'b0; + // Setup line buffer write address + spritelbram_wr_addr <= {spritelb_slot_wr, spr_x}; + // Set sprite rom read address + case(spr_size) + spr_size_32x32: + begin + sprom_addr <= spr_rom_offset + { spr_image_index[3:0], 10'b0} + { spr_rom_y_offset[7:0], 5'b0}; + end + spr_size_16x16: + begin + sprom_addr <= spr_rom_offset + { spr_image_index[5:0], 8'b0} + { spr_rom_y_offset[8:0], 4'b0}; + end + default: + begin + // Default to 8x8 + sprom_addr <= spr_rom_offset + { 2'b0, spr_image_index[5:0], 6'b0} + { spr_rom_y_offset[9:0], 3'b0}; + end + endcase + + // Reset sprite pixel index and count + spr_pixel_index <= {SPRITE_SIZE_WIDTH+1{1'b0}}; + + spr_state <= SE_WAIT; + spr_state_next <= SE_GET_PIXEL; + end + + SE_GET_PIXEL: + begin + if(spr_pixel_index > spr_size[SPRITE_SIZE_WIDTH:0]) + begin + // Move to next sprite or finish + if(spr_index == spr_index_max) + begin + spr_state <= SE_LINE_COMPLETE; + end + else + begin + spr_index <= spr_index + 5'd1; + spr_state <= SE_SETUP_READ_Y; + end + end + else + begin +`ifdef CASVAL_DEBUG + $display("CASVAL->SE_GET_PIXEL: y: %d, x: %d i: %d, sprom_addr < %x, palrom_addr < %x", spr_y, spr_pixel_index, spr_image_index, sprom_addr, {spriterom_data_out[4:0],1'b0}); +`endif + // Setup palette address to read pixel colour + palrom_addr <= {spr_palette_index, spriterom_data_out[4:0],1'b0}; + // Increment sprite ROM address + sprom_addr <= sprom_addr + 1'b1; + // Disable line buffer write + spritelbram_wr <= 1'b0; + + spr_state <= SE_WAIT; + spr_state_next <= SE_STAGE_PIXEL; + end + end + + SE_STAGE_PIXEL: + begin + +`ifdef CASVAL_DEBUG_OUTLINE + /* verilator lint_off WIDTH */ + if(spr_pixel_index == 0 || spr_pixel_index == spr_size || spr_active_y == spr_y || spr_active_y == (spr_y + spr_size)) begin + spritelbram_data_in <= 16'hFFFF; + spritelbram_wr <= 1'b1; + spr_state <= SE_WRITE_PIXEL; + end + /* verilator lint_on WIDTH */ + else + begin +`endif + // Get pixel colour from palette rom + if(palrom_data_out[15]) + begin + // If palette colour alpha is high, stage input to line buffer +`ifdef CASVAL_DEBUG + $display("CASVAL->SE_STAGE_PIXEL: ay: %d y: %d, x: %d i: %d, spritelbram_data_in < %x", spr_active_y, spr_y, spr_pixel_index, spr_image_index, palrom_data_out); +`endif + // Enable line buffer write + spritelbram_wr <= 1'b1; + // Fill line buffer data in with palette ROM data out + spritelbram_data_in <= palrom_data_out; + + // Trigger collision check (not in vblank) + if(!vblank && spr_collide) + begin + col_spriteindex <= spr_index[4:0]; + col_x <= spr_x + {{(SPRITE_POSITION_WIDTH-SPRITE_SIZE_WIDTH)-1{1'b0}}, spr_pixel_index}; + col_primary_state <= CP_STAGE_PIXEL; + end + // Move to write pixel state + spr_state <= SE_WRITE_PIXEL; + end + else + begin + // Pixel is transparent so move to next +`ifdef CASVAL_DEBUG + $display("CASVAL->SE_STAGE_PIXEL: y: %d, x: %d i: %d, spritelbram_data_in < %x - FAIL ALPHA CHECK", spr_y,spr_pixel_index, spr_image_index, palrom_data_out); +`endif + // Increment line buffer write address + spritelbram_wr_addr <= spritelbram_wr_addr + 1'b1; + // Increment sprite pixel index + spr_pixel_index <= spr_pixel_index + 1'b1; + + spr_state <= SE_GET_PIXEL; + end + end +`ifdef CASVAL_DEBUG_OUTLINE + end +`endif + + SE_WRITE_PIXEL: + begin + // Get pixel colour from palette rom and stage input to line buffer +`ifdef CASVAL_DEBUG + $display("CASVAL->SE_WRITE_PIXEL: y: %d, x: %d i: %d, spritelbram_wr_addr < %d, spritelbram_data_in=%b", spr_y, spr_pixel_index, spr_image_index, spritelbram_wr_addr[SPRITE_POSITION_WIDTH-1:0], spritelbram_data_in); +`endif + // Disable line buffer write + spritelbram_wr <= 1'b0; + // Increment line buffer write address + spritelbram_wr_addr <= spritelbram_wr_addr + 1'b1; + // Increment sprite pixel index + spr_pixel_index <= spr_pixel_index + 1'b1; + + spr_state <= SE_GET_PIXEL; + end + + SE_LINE_COMPLETE: + begin + // Once all sprites have been processed for each pixel return to idle +`ifdef CASVAL_DEBUG_TIMES + $display("CASVAL->SE_LINE_COMPLETE: counter=%d", spr_timer_line); + // Update slowest line counter + if(spr_timer_line > spr_linetime_max) + begin + spr_linetime_max <= spr_timer_line; + end + // Reset idle timer + spr_timer_idle <= {SPR_TIMER_WIDTH{1'b0}}; +`endif + spr_state <= SE_IDLE; + end + endcase + + + if(!pause) + begin + + // Collision FSM + // When hsync goes high, rotate collision buffers and start detection pass for previous line + if(hsync && !hsync_last) + begin + col_secondary_state <= CS_DETECT_BEGIN; + col_buffer_primary_is_a <= ~col_buffer_primary_is_a; + end + + case (col_secondary_state) + CS_WAIT: + begin + col_secondary_state <= col_secondary_state_next; + end + CS_DETECT_BEGIN: + begin + // Reset address and write states for secondary buffer + col_buffer_secondary_addr <= 9'b0; + col_buffer_secondary_data_in <= 32'b0; + col_buffer_secondary_wr <= 1'b1; + col_buffer_secondary_collisions <= 32'b0; + + col_secondary_timer <= 16'b0; + + col_secondary_state <= CS_DETECT; + +`ifdef CASVAL_COLLISION_SECONDARY_DEBUG + $display("CS_DETECT_BEGIN t=%d hc=d%", col_secondary_timer, hcnt); +`endif + + end + + CS_DETECT: + begin +`ifdef CASVAL_COLLISION_SECONDARY_DEBUG + $display("CS_DETECT t=%d : x=%d c=%d cc1=%d", col_secondary_timer, col_buffer_secondary_addr, col_buffer_secondary_collisions, col_buffer_secondary_collisions_count1,); +`endif + + // Check each pixel for a collision + if(col_buffer_secondary_collisions_count2 > 5'd1) + begin + //$display("CS_DETECT t=%d : x=%d c=%d cc1=%d", col_secondary_timer, col_buffer_secondary_addr, col_buffer_secondary_collisions, col_buffer_secondary_collisions_count1); + col_buffer_secondary_collisions <= col_buffer_secondary_collisions | col_buffer_secondary_data_out; + +`ifdef DEBUG_SPRITE_COLLISION + //$display("CS_DETECT_DEBUG_OUT t=%d : a=%x", col_secondary_timer, ((spr_active_y) * 9'd320) + {8'b0, col_buffer_secondary_addr}); + spritedebugram_data_in_b <= 8'hFF; + spritedebugram_wr_b <= 1'b1; + spritedebugram_addr_b <= ((spr_active_y) * 9'd320) + {8'b0, col_buffer_secondary_addr}; +`endif + end + + if(col_buffer_secondary_addr == spr_line_max - 1'b1) + begin + spritecollisionram_wr <= 1'b0; + spritecollisionram_addr <= {SPRITE_COLRAM_WIDTH{1'b0}}; +`ifdef CASVAL_COLLISION_SECONDARY_DEBUG + $display(">CS_DETECT_COMPLETE t=%d : y=%d hc=%d vc=%d", col_secondary_timer, spr_active_y, hcnt, vcnt); +`endif + col_secondary_state <= CS_DETECT_COMPLETE; + end + else + begin + col_buffer_secondary_addr <= col_buffer_secondary_addr + 9'b1; + end + end + + CS_DETECT_COMPLETE: + begin + // Copy individual bits from col_buffer_secondary_collisions into sprite collision ram + if(spritecollisionram_wr == 1'b0) + begin +`ifdef CASVAL_COLLISION_SECONDARY_DEBUG + $display("CS_DETECT_COMPLETE t=%d : RD b=%b c=%d x=%d col=%d y=%d do=%d di=%d", col_secondary_timer, col_buffer_secondary_collisions, col_buffer_secondary_collisions_count1, spritecollisionram_addr, col_buffer_secondary_collisions[spritecollisionram_addr], spr_active_y, spritecollisionram_data_out, col_buffer_secondary_collisions[spritecollisionram_addr] | spritecollisionram_data_out); +`endif + if(col_buffer_secondary_collisions_count1 > 5'b0) + begin + spritecollisionram_data_in <= col_buffer_secondary_collisions[spritecollisionram_addr] | spritecollisionram_data_out; + end + else + begin + spritecollisionram_data_in <= spritecollisionram_data_out; + end + spritecollisionram_wr <= 1'b1; + col_secondary_state <= CS_WAIT; + col_secondary_state_next <= CS_DETECT_COMPLETE; + end + else + begin +`ifdef CASVAL_COLLISION_SECONDARY_DEBUG + $display("CS_DETECT_COMPLETE WR t=%d : x=%d b=%b c=%d col=%d y=%d do=%d di=%d", col_secondary_timer, spritecollisionram_addr, col_buffer_secondary_collisions, col_buffer_secondary_collisions_count1, col_buffer_secondary_collisions[spritecollisionram_addr], spr_active_y, spritecollisionram_data_out, col_buffer_secondary_collisions[spritecollisionram_addr] | spritecollisionram_data_out); +`endif + if(spritecollisionram_addr == {SPRITE_COLRAM_WIDTH{1'b1}}) + begin +`ifdef CASVAL_COLLISION_SECONDARY_DEBUG + $display("CS_DETECT_COMPLETE FINISHED t=%d hc=d%", col_secondary_timer, hcnt); + $display("CS_DETECT_COMPLETE FINISHED t=%d : b=%b bc=%d col=%d y=%d do=%d di=%d", col_secondary_timer, col_buffer_secondary_collisions, col_buffer_secondary_collisions_count1, col_buffer_secondary_collisions[spritecollisionram_addr], spr_active_y, spritecollisionram_data_out, col_buffer_secondary_collisions[spritecollisionram_addr] | spritecollisionram_data_out); +`endif + spritecollisionram_addr <= {SPRITE_COLRAM_WIDTH{1'b0}}; + col_secondary_state <= CS_IDLE; + end + else + begin + spritecollisionram_addr <= spritecollisionram_addr + {{SPRITE_COLRAM_WIDTH-1{1'b0}},1'b1}; + col_secondary_state <= CS_WAIT; + col_secondary_state_next <= CS_DETECT_COMPLETE; + end + spritecollisionram_wr <= 1'b0; + end + end + endcase + end +end + +wire [31:0] col_buffer_data_out_a; +wire [31:0] col_buffer_data_out_b; + +assign col_buffer_primary_data_out = col_buffer_primary_is_a ? col_buffer_data_out_a : col_buffer_data_out_b; +assign col_buffer_secondary_data_out = !col_buffer_primary_is_a ? col_buffer_data_out_a : col_buffer_data_out_b; + +// Sprite Collision Buffer RAM A +spram #(9,32) spritecollisionbufferram_a +( + .clock(clk), + .address(col_buffer_primary_is_a ? col_buffer_primary_addr : col_buffer_secondary_addr), + .wren(col_buffer_primary_is_a ? col_buffer_primary_wr : col_buffer_secondary_wr), + .data(col_buffer_primary_is_a ? col_buffer_primary_data_in : col_buffer_secondary_data_in), + .q(col_buffer_data_out_a) +); +// Sprite Collision Buffer RAM B +spram #(9,32) spritecollisionbufferram_b +( + .clock(clk), + .address(!col_buffer_primary_is_a ? col_buffer_primary_addr : col_buffer_secondary_addr), + .wren(!col_buffer_primary_is_a ? col_buffer_primary_wr : col_buffer_secondary_wr), + .data(!col_buffer_primary_is_a ? col_buffer_primary_data_in : col_buffer_secondary_data_in), + .q(col_buffer_data_out_b) +); + +endmodule + + +module count +( + input clk, + input [31:0] a, + output reg [4:0] sum +); + +reg [5:0] n; + +always @(negedge clk) begin + + sum = 0; + for (n=0; n<=6'd31; n=n+6'd1) begin + sum = sum + {4'b0,a[n[4:0]]}; + end + +end +endmodule \ No newline at end of file diff --git a/rtl/starfield.v b/rtl/starfield.v new file mode 100644 index 0000000..d125faa --- /dev/null +++ b/rtl/starfield.v @@ -0,0 +1,142 @@ +/*============================================================================ + Aznable (custom 8-bit computer system) - Moroboshi (starfield) + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-06 + + Based on Project F: Ad Astra - Starfield + (C)2021 Will Green, open source hardware released under the MIT License + Learn more at https://projectf.io + + 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 3 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, see . +===========================================================================*/ + +`default_nettype none +`timescale 1ns / 1ps + +module starfield #( + parameter [LEN-1:0] H=800, + parameter [LEN-1:0] V=525, + parameter LEN=25, + parameter TAPS=25'b1010000000000000000000000, + parameter SEED=25'b1111111111111110000000000, + parameter MASK=25'b1111111111111111111111111 + ) ( + input wire clk, + input wire en, + input wire pause, + input wire rst, + input wire vblank, + input wire [2:0] addr, // Write address - 0 = enable, 1 = horizontal direction + speed msbs, 2 = horizontal speed lsbs, 3 = vertical direction + speed msbs, 4 = vertical speed lsbs + input wire [7:0] data_in, + input wire write, + output wire sf_on, // star on (alpha) + output wire [7:0] sf_star // star brightness + ); + + reg [LEN-1:0] RST_CNT; // counter starts at zero, so sub 1 + reg [LEN-1:0] seed; + reg enabled; + + reg vdirection; + reg [14:0] vspeed_set; + reg [7:0] vincrement; + reg [15:0] vtimer; + wire [14:0] vspeed_actual = pause ? 15'b0 : vspeed_set; + + reg hdirection; + reg [14:0] hspeed_set; + reg [7:0] hincrement; + reg [15:0] htimer; + wire [14:0] hspeed_actual = pause ? 15'b0 : hspeed_set; + + wire [LEN-1:0] sf_reg; + reg [LEN-1:0] sf_cnt; + + always @(posedge clk) + begin + + // Reset seed + if(rst) + begin + seed <= SEED; + RST_CNT <= (H * V) - 1'b1; + end + + // CPU write + if(write) + begin + case(addr) + 3'd0: enabled <= data_in[0]; + 3'd1: begin hdirection <= data_in[7]; hspeed_set[14:8] <= data_in[6:0]; end + 3'd2: hspeed_set[7:0] <= data_in; + 3'd3: begin vdirection <= data_in[7]; vspeed_set[14:8] <= data_in[6:0]; end + 3'd4: vspeed_set[7:0] <= data_in; + default: + begin + + end + endcase + end + + if (en) + begin + sf_cnt <= sf_cnt + 1'b1; + + if(sf_cnt == RST_CNT) + begin + + htimer = htimer + hspeed_actual; + hincrement = 8'b0; + if(htimer >= 16'hFF) + begin + hincrement = htimer[15:8] > 8'b0 ? htimer[15:8] : 8'b1; + htimer = htimer - {hincrement[7:0], 8'b0}; + end + vtimer = vtimer + vspeed_actual; + vincrement = 8'b0; + if(vtimer >= 16'hFF) + begin + vincrement = vtimer[15:8] > 8'b0 ? vtimer[15:8] : 8'b1; + vtimer = vtimer - {vincrement[7:0], 8'b0}; + end + + /* verilator lint_off WIDTH */ + if(pause) + RST_CNT <= (H * V) - 1'b1; + else + RST_CNT <= (H * (vdirection ? V + vincrement : V - vincrement)) + (hdirection ? hincrement : -hincrement) - 1'b1; + + /* verilator lint_on WIDTH */ + sf_cnt <= 0; + end + end + if (rst) sf_cnt <= 0; + end + + assign sf_on = &{sf_reg | MASK} & enabled; + assign sf_star = sf_reg[7:0]; + + lfsr #( + .LEN(LEN), + .TAPS(TAPS) + ) lsfr_sf ( + .clk(clk), + .rst(sf_cnt == {LEN{1'b0}} ), + .en(en), + .seed(seed), + .sreg(sf_reg) + ); +endmodule \ No newline at end of file diff --git a/rtl/system.v b/rtl/system.v index dd1c2b6..157cfdc 100644 --- a/rtl/system.v +++ b/rtl/system.v @@ -21,10 +21,13 @@ ===========================================================================*/ module system ( - input clk_sys, - input ce_pix, + input clk_24, + input ce_6, + input ce_2, input reset, - input [13:0] dn_addr, + input pause, + input menu, // Active-high trigger to open menu in system + input [16:0] dn_addr, input dn_wr, input [7:0] dn_data, input [7:0] dn_index, @@ -41,7 +44,7 @@ module system ( // 6 devices, 8 bits each - paddle 0..255 input [47:0] paddle, - // 6 devices, 16 bits eachspinner [7:0] -128..+127, [8] - toggle with every update, [9-15] padding + // 6 devices, 16 bits each spinner [7:0] -128..+127, [8] - toggle with every update, [9-15] padding input [95:0] spinner, // ps2 alternative interface. @@ -61,7 +64,9 @@ module system ( output [7:0] VGA_G, output [7:0] VGA_B, output VGA_HB, - output VGA_VB + output VGA_VB, + output [15:0] AUDIO_L, + output [15:0] AUDIO_R ); localparam [8:0] VGA_WIDTH = 9'd320; @@ -78,11 +83,11 @@ wire [8:0] vcnt; // Display timing module from JTFRAME jtframe_vtimer #( .HB_START(VGA_WIDTH - 1'b1), - .VB_START(VGA_HEIGHT- 1'b1) + .VB_START(VGA_HEIGHT - 1'b1) ) vtimer ( - .clk(clk_sys), - .pxl_cen(ce_pix), + .clk(clk_24), + .pxl_cen(ce_6), .V(vcnt), .H(hcnt), .Hinit(), @@ -94,91 +99,21 @@ jtframe_vtimer #( ); // Millisecond timer -reg [15:0] timer; -reg [14:0] timer_divider = 15'd0; - -always @(posedge clk_sys) -begin - if(timer_cs == 1'b1 && cpu_wr_n == 1'b0) - begin - timer <= 16'd0; - timer_divider <= 15'd0; - end - else - begin - if(timer_divider==15'd24000) - begin - timer <= timer + 16'd1; - timer_divider <= 15'd0; - end - else - begin - timer_divider <= timer_divider + 15'd1; - end - end -end - -// Character map -wire [3:0] chpos_x = 4'd7 - hcnt[2:0]; -wire [2:0] chpos_y = vcnt[2:0]; -wire [5:0] chram_x = hcnt[8:3]; -wire [5:0] chram_y = vcnt[8:3]; -wire [11:0] chram_addr = {chram_y, chram_x}; -wire [11:0] chrom_addr = {1'b0, chmap_data_out[7:0], chpos_y}; -wire chpixel = chrom_data_out[chpos_x[2:0]]; - -// RGB mixer -wire [2:0] r_temp = chpixel ? fgcolram_data_out[2:0] : bgcolram_data_out[2:0]; -wire [2:0] g_temp = chpixel ? fgcolram_data_out[5:3] : bgcolram_data_out[5:3]; -wire [1:0] b_temp = chpixel ? fgcolram_data_out[7:6] : bgcolram_data_out[7:6]; - -// Convert RGb to 24bpp -assign VGA_R = {{2{r_temp}},2'b0}; -assign VGA_G = {{2{g_temp}},2'b0}; -assign VGA_B = {{3{b_temp}},2'b0}; - -// CPU control signals -wire [15:0] cpu_addr; -wire [7:0] cpu_din; -wire [7:0] cpu_dout; -wire cpu_rd_n; -wire cpu_wr_n; -wire cpu_mreq_n; - -// include Z80 CPU -tv80s T80x ( - .reset_n ( !reset ), - .clk ( clk_sys ), - .wait_n ( 1'b1 ), - .int_n ( 1'b1 ), - .nmi_n ( 1'b1 ), - .busrq_n ( 1'b1 ), - .mreq_n ( cpu_mreq_n ), - .rd_n ( cpu_rd_n ), - .wr_n ( cpu_wr_n ), - .A ( cpu_addr ), - .di ( cpu_din ), - .dout ( cpu_dout ), - .m1_n (), - .iorq_n (), - .rfsh_n (), - .halt_n (), - .busak_n () - ); - -// RAM data to CPU -wire [7:0] pgrom_data_out; -wire [7:0] chrom_data_out; -wire [7:0] wkram_data_out; -wire [7:0] chram_data_out; -wire [7:0] fgcolram_data_out; -wire [7:0] bgcolram_data_out; - -// RAM data to GFX -wire [7:0] chmap_data_out; +wire [15:0] timer; +generic_timer #(16,15,24) ms_timer +( + .clk(clk_24), + .reset(reset || (timer_cs && !cpu_wr_n)), + .counter(timer) +); // Hardware inputs -wire [7:0] in0_data_out = {VGA_HS, VGA_VS,VGA_HB, VGA_VB, 4'b1000}; +`ifdef DEBUG_SIMULATION + wire debug = 1'b1; +`else + wire debug = 1'b0; +`endif +wire [7:0] in0_data_out = {VGA_HS, VGA_VS,VGA_HB, VGA_VB, 2'b10, menu, debug}; wire [7:0] joystick_data_out = joystick[{cpu_addr[4:0],3'd0} +: 8]; wire [7:0] analog_l_data_out = analog_l[{cpu_addr[3:0],3'd0} +: 8]; wire [7:0] analog_r_data_out = analog_r[{cpu_addr[3:0],3'd0} +: 8]; @@ -188,44 +123,114 @@ wire [7:0] ps2_key_data_out = ps2_key[{cpu_addr[0],3'd0} +: 8]; wire [7:0] ps2_mouse_data_out = ps2_mouse[{cpu_addr[2:0],3'd0} +: 8]; wire [7:0] timestamp_data_out = timestamp[{cpu_addr[2:0],3'd0} +: 8]; wire [7:0] timer_data_out = timer[{cpu_addr[0],3'd0} +: 8]; +wire [7:0] tilemapcontrol_data_out; +wire [7:0] music_data_out; // CPU address decodes -wire pgrom_cs = cpu_addr[15:14] == 2'b00; -//wire chrom_cs = cpu_addr[15:12] == 4'b0100; // CPU never accesses the character ROM data directly -wire chram_cs = cpu_addr[15:11] == 5'b10000; -wire fgcolram_cs = cpu_addr[15:11] == 5'b10001; -wire bgcolram_cs = cpu_addr[15:11] == 5'b10010; -wire wkram_cs = cpu_addr[15:14] == 2'b11; -wire in0_cs = cpu_addr == 16'h6000; -wire joystick_cs = cpu_addr[15:8] == 8'b01110000; -wire analog_l_cs = cpu_addr[15:8] == 8'b01110001; -wire analog_r_cs = cpu_addr[15:8] == 8'b01110010; -wire paddle_cs = cpu_addr[15:8] == 8'b01110011; -wire spinner_cs = cpu_addr[15:8] == 8'b01110100; -wire ps2_key_cs = cpu_addr[15:8] == 8'b01110101; -wire ps2_mouse_cs = cpu_addr[15:8] == 8'b01110110; -wire timestamp_cs = cpu_addr[15:8] == 8'b01110111; -wire timer_cs = cpu_addr[15:8] == 8'b01111000; +// - Program ROM +wire pgrom_cs = cpu_addr[15] == 1'b0; +// - Memory mapped inputs +wire [7:0] memory_map_addr = cpu_addr[15:8]; +wire in0_cs = memory_map_addr == 8'b10000000; +wire joystick_cs = memory_map_addr == 8'b10000001; +wire analog_l_cs = memory_map_addr == 8'b10000010; +wire analog_r_cs = memory_map_addr == 8'b10000011; +wire paddle_cs = memory_map_addr == 8'b1000100; +wire spinner_cs = memory_map_addr == 8'b10000101; +wire ps2_key_cs = memory_map_addr == 8'b10000110; +wire ps2_mouse_cs = memory_map_addr == 8'b10000111; +wire timestamp_cs = memory_map_addr == 8'b10001000; +wire timer_cs = memory_map_addr == 8'b10001001; +wire starfield1_cs = memory_map_addr == 8'b10001010 && cpu_addr[5:4] == 2'b00; +wire starfield2_cs = memory_map_addr == 8'b10001010 && cpu_addr[5:4] == 2'b01; +wire starfield3_cs = memory_map_addr == 8'b10001010 && cpu_addr[5:4] == 2'b10; +wire system_pause_cs = cpu_addr == 16'b1000101000110000; +wire system_menu_cs = cpu_addr == 16'b1000101000110001; +wire sound_cs = cpu_addr[15:4] == 12'b100010110000; +wire music_cs = cpu_addr[15:4] == 12'b100010110001; -//always @(posedge timestamp[32]) begin -// $display("%b", timestamp); -// end -//always @(posedge clk_sys) begin -// if(pgrom_cs) $display("%x pgrom o %x", cpu_addr, pgrom_data_out); -// if(wkram_cs) $display("%x wkram i %x o %x w %b", cpu_addr, cpu_dout, wkram_data_out, wkram_wr); -// if(chram_cs) $display("%x chram i %x o %x w %b", cpu_addr, cpu_dout, chram_data_out, chram_wr); -// if(fgcolram_cs) $display("%x fgcolram i %x o %x w %b", cpu_addr, cpu_dout, fgcolram_data_out, fgcolram_wr); -// if(in0_cs) $display("%x in0 i %x o %x", cpu_addr, cpu_dout, in0_data_out); -// if(joystick_cs) $display("joystick %b %b", joystick_bit, joystick_data_out); -// if(analog_l_cs) $display("analog_l %b %b", analog_l_bit, analog_l_data_out); -// if(analog_r_cs) $display("analog_r %b %b", analog_r_bit, analog_r_data_out); -// if(paddle_cs) $display("paddle %b", paddle_data_out); -// if(ps2_key_cs) $display("ps2_key %b %x", ps2_key_data_out, cpu_addr[3:0]); -// $display("%x", cpu_addr); -//end -// always @(posedge ps2_mouse[24]) begin -// $display("%b", ps2_mouse); -// end +// - Casval (character map) +wire chram_cs = cpu_addr[15:11] == 5'b10011; +wire fgcolram_cs = cpu_addr[15:11] == 5'b10100; +wire bgcolram_cs = cpu_addr[15:11] == 5'b10101; +// - Comet (sprite engine) +wire spriteram_cs = cpu_addr[15:11] == 5'b10110 && !spritecollisionram_cs; +wire spritecollisionram_cs = memory_map_addr == 8'b10110100; +// - Zechs (tile map) +wire tilemapcontrol_cs = cpu_addr[15:2] == 14'b10001100000000; +wire tilemapram_cs = cpu_addr >= 16'h8C10 && cpu_addr < 16'h8F10; +// - CPU working RAM +wire wkram_cs = cpu_addr[15:14] == 2'b11; + +// System pause trigger +reg pause_trigger = 0; +wire pause_system = pause || pause_trigger; +always @(posedge clk_24) begin + if(system_pause_cs && !cpu_wr_n) pause_trigger <= 1'b1; + if(pause) pause_trigger<=1'b0; +end + +// System menu trigger +reg menu_trigger; +always @(posedge clk_24) begin + if(menu) menu_trigger <= 1'b1; + if(system_menu_cs && !cpu_wr_n) menu_trigger <= 1'b0; +end + +always @(posedge clk_24) begin + //if(pgrom_cs) $display("%x pgrom o %x", cpu_addr, pgrom_data_out); + //if(wkram_cs) $display("%x wkram i %x o %x w %b", cpu_addr, cpu_dout, wkram_data_out, wkram_wr); + //if(chram_cs) $display("%x chram i %x o %x w %b", cpu_addr, cpu_dout, chram_data_out, chram_wr); + //if(fgcolram_cs) $display("%x fgcolram i %x o %x w %b", cpu_addr, cpu_dout, fgcolram_data_out, fgcolram_wr); + //if(in0_cs) $display("%x in0 i %x o %x", cpu_addr, cpu_dout, in0_data_out); + //if(joystick_cs) $display("joystick %b %b", joystick_bit, joystick_data_out); + //if(analog_l_cs) $display("analog_l %b %b", analog_l_bit, analog_l_data_out); + //if(analog_r_cs) $display("analog_r %b %b", analog_r_bit, analog_r_data_out); + //if(paddle_cs) $display("paddle %b", paddle_data_out); + //if(ps2_key_cs) $display("ps2_key %b %x", ps2_key_data_out, cpu_addr[3:0]); + // if(starfield1_cs) $display("starfield1 %b %b", cpu_addr, cpu_dout); + // if(starfield2_cs) $display("starfield2 %b %b", cpu_addr, cpu_dout); + // if(starfield3_cs) $display("starfield3 %b %b", cpu_addr, cpu_dout); + //if(!cpu_wr_n) $display("cpu_write %x %b",cpu_addr, cpu_dout); + //if(spritecollisionram_cs && !cpu_wr_n) $display("spritecollisionram %b %b %b", cpu_wr_n, cpu_addr, cpu_dout); + //if(spriteram_cs && !cpu_wr_n) $display("spriteram_cs %x %b", cpu_addr[SPRITE_RAM_WIDTH-1:0], cpu_dout); + //if(sound_cs && !cpu_wr_n) $display("sound_cs %b %b", cpu_addr, cpu_dout); + //if(music_cs && !cpu_wr_n) $display("music_cs %b %b", cpu_addr, cpu_dout); + //if(tilemapcontrol_cs) $display("tilemapcontrol_cs addr=%x dout=%x din=%x wr=%b", cpu_addr, cpu_dout, tilemapcontrol_data_out, cpu_wr_n); + //if(tilemapram_cs && !cpu_wr_n) $display("tilemapram_cs addr=%x dout=%x", cpu_addr, cpu_dout); +end + +// ROM data available to CPU +wire [7:0] pgrom_data_out; +wire [7:0] chrom_data_out; + +// RAM data available to CPU +wire [7:0] wkram_data_out; +wire [7:0] chram_data_out; +wire [7:0] fgcolram_data_out; +wire [7:0] bgcolram_data_out; + +// RAM data not available to CPU +wire [7:0] chmap_data_out; + +// Rom upload write enables +wire pgrom_wr = dn_wr && dn_index == 8'd0; +wire chrom_wr = dn_wr && dn_index == 8'd1; +wire palrom_wr = dn_wr && dn_index == 8'd2; +wire spriterom_wr = dn_wr && dn_index == 8'd3; +wire musicrom_wr = dn_wr && dn_index == 8'd4; +wire soundrom_wr = dn_wr && dn_index == 8'd5; +wire tilemaprom_wr = dn_wr && dn_index == 8'd6; + +// Ram write enables +wire wkram_wr = !cpu_wr_n && wkram_cs; +wire chram_wr = !cpu_wr_n && chram_cs; +wire fgcolram_wr = !cpu_wr_n && fgcolram_cs; +wire bgcolram_wr = !cpu_wr_n && bgcolram_cs; +wire spriteram_wr = !cpu_wr_n && spriteram_cs; +wire spritecollisionram_wr; +wire tilemapcontrol_wr = !cpu_wr_n && tilemapcontrol_cs; +wire tilemapram_wr = !cpu_wr_n && tilemapram_cs; // CPU data mux assign cpu_din = pgrom_cs ? pgrom_data_out : @@ -233,6 +238,7 @@ assign cpu_din = pgrom_cs ? pgrom_data_out : chram_cs ? chram_data_out : fgcolram_cs ? fgcolram_data_out : bgcolram_cs ? bgcolram_data_out : + spritecollisionram_cs ? {8{spritecollisionram_data_out_cpu}} : in0_cs ? in0_data_out : joystick_cs ? joystick_data_out : analog_l_cs ? analog_l_data_out : @@ -243,111 +249,655 @@ assign cpu_din = pgrom_cs ? pgrom_data_out : ps2_mouse_cs ? ps2_mouse_data_out : timestamp_cs ? timestamp_data_out : timer_cs ? timer_data_out : + tilemapcontrol_cs ? tilemapcontrol_data_out : + music_cs ? music_data_out : + system_menu_cs ? {8{menu_trigger}} : 8'b00000000; -// Rom upload write enables -wire pgrom_wr = dn_wr && dn_index == 8'b0; -wire chrom_wr = dn_wr && dn_index == 8'b1; +// CPU control signals +wire [15:0] cpu_addr; +wire [7:0] cpu_din; +wire [7:0] cpu_dout; +wire cpu_wr_n; -// Ram write enables -wire wkram_wr = !cpu_wr_n && wkram_cs; -wire chram_wr = !cpu_wr_n && chram_cs; -wire fgcolram_wr = !cpu_wr_n && fgcolram_cs; -wire bgcolram_wr = !cpu_wr_n && bgcolram_cs; +// reg cpu_cen_count; // 24 Mhz +wire cpu_cen = 1'b1; +// always @(posedge clk_24) +// begin +// cpu_cen_count <= cpu_cen_count + 1'b1; +// end +`ifndef DISABLE_CPU +// include Z80 CPU +tv80e #( + .Mode(1), + .IOWait(0) +) T80x ( + .reset_n (!reset), + .clk (clk_24), + .cen (cpu_cen), + .wait_n (!pause_system), + .int_n (1'b1), + .nmi_n (1'b1), + .busrq_n (1'b1), + .mreq_n (), + .rd_n (), + .wr_n (cpu_wr_n), + .A (cpu_addr), + .di (cpu_din), + .dout (cpu_dout), + .m1_n (), + .iorq_n (), + .rfsh_n (), + .halt_n (), + .busak_n () +); +`endif + +wire [7:0] charmap_r; +wire [7:0] charmap_g; +wire [7:0] charmap_b; +wire charmap_a; +`ifndef DISABLE_CHARMAP +// Casval - character map +wire [11:0] chram_addr; +wire [11:0] chrom_addr; +charmap casval +( + .clk(clk_24), + .reset(reset), + .hcnt(hcnt), + .vcnt(vcnt), + .chrom_data_out(chrom_data_out), + .fgcolram_data_out(fgcolram_data_out), + .bgcolram_data_out(bgcolram_data_out), + .chmap_data_out(chmap_data_out), + .chram_addr(chram_addr), + .chrom_addr(chrom_addr), + .r(charmap_r), + .g(charmap_g), + .b(charmap_b), + .a(charmap_a) +); +`endif + +// Zechs - tile map +wire [7:0] tilemap_r; +wire [7:0] tilemap_g; +wire [7:0] tilemap_b; +wire tilemap_a; +`ifndef DISABLE_TILEMAP +localparam TILEMAP_ROM_WIDTH = 17; +localparam TILEMAP_RAM_WIDTH = 10; +wire [TILEMAP_ROM_WIDTH-1:0] tilemaprom_addr; +wire [15:0] tilemaprom_data_out; +wire [TILEMAP_RAM_WIDTH-1:0] tilemapram_addr; +wire [7:0] tilemapram_data_out; +wire tilemapram_ctl_wr; +wire [7:0] tilemapram_ctl_data_in; + +tilemap #( + .TILEMAP_RAM_WIDTH(TILEMAP_RAM_WIDTH), + .TILEMAP_ROM_WIDTH(TILEMAP_ROM_WIDTH) +) zechs +( + .clk(clk_24), + .reset(reset), + .pause(pause_system), + .hcnt(hcnt), + .vcnt(vcnt), + .hblank(VGA_HB), + .addr(cpu_addr[1:0]), + .data_in(cpu_dout), + .write(tilemapcontrol_wr), + .tilemaprom_data_out(tilemaprom_data_out), + .tilemapram_data_out(tilemapram_data_out), + .tilemapcontrol_data_out(tilemapcontrol_data_out), + .tilemapram_ctl_wr(tilemapram_ctl_wr), + .tilemapram_ctl_data_in(tilemapram_ctl_data_in), + .tilemapram_addr(tilemapram_addr), + .tilemaprom_addr(tilemaprom_addr), + .tilemap_r(tilemap_r), + .tilemap_g(tilemap_g), + .tilemap_b(tilemap_b), + .tilemap_a(tilemap_a) +); + +`endif + +// Palettes +wire [7:0] palrom_addr; +wire [15:0] palrom_data_out; +// Comet - sprite engine +wire [7:0] spr_r; +wire [7:0] spr_g; +wire [7:0] spr_b; +wire spr_a; +wire spritecollisionram_data_out_cpu; +`ifndef DISABLE_SPRITES +localparam SPRITE_POSITION_WIDTH = 9; +localparam SPRITE_RAM_WIDTH = 7; +localparam SPRITE_ROM_WIDTH = 14; +localparam SPRITE_COLRAM_WIDTH = 5; +wire [SPRITE_ROM_WIDTH-1:0] sprom_addr; +wire [7:0] spriterom_data_out; +wire [SPRITE_RAM_WIDTH-1:0] spriteram_addr; +wire [7:0] spriteram_data_out; +wire [SPRITE_COLRAM_WIDTH-1:0] spritecollisionram_addr; +wire spritecollisionram_data_out; +wire spritecollisionram_data_in; +wire [SPRITE_POSITION_WIDTH:0] spritelbram_rd_addr; +wire [SPRITE_POSITION_WIDTH:0] spritelbram_wr_addr; +wire spritelbram_wr; +wire [15:0] spritelbram_data_in; +wire [15:0] spritelbram_data_out; +sprite_engine #( + .SPRITE_RAM_WIDTH(SPRITE_RAM_WIDTH), + .SPRITE_ROM_WIDTH(SPRITE_ROM_WIDTH), + .SPRITE_POSITION_WIDTH(SPRITE_POSITION_WIDTH), + .SPRITE_COLRAM_WIDTH(SPRITE_COLRAM_WIDTH) +) comet +( + .clk(clk_24), + .reset(reset), + .pause(pause_system), + .hsync(VGA_HS), + .vsync(VGA_VS), + .vblank(VGA_VB), + .hcnt(hcnt), + .vcnt(vcnt), + .spriterom_data_out(spriterom_data_out), + .spriteram_data_out(spriteram_data_out), + .palrom_data_out(palrom_data_out), + .spritelbram_data_out(spritelbram_data_out), + .spritecollisionram_data_in(spritecollisionram_data_in), + .spritecollisionram_data_out(spritecollisionram_data_out), + .spriteram_addr(spriteram_addr), + .spritecollisionram_addr(spritecollisionram_addr), + .sprom_addr(sprom_addr), + .palrom_addr(palrom_addr), + .spritelbram_rd_addr(spritelbram_rd_addr), + .spritelbram_wr_addr(spritelbram_wr_addr), + .spritelbram_wr(spritelbram_wr), + .spritecollisionram_wr(spritecollisionram_wr), + .spritelbram_data_in(spritelbram_data_in), +`ifdef DEBUG_SPRITE_COLLISION + .spritedebugram_addr_b(spritedebugram_addr_b), + .spritedebugram_wr_b(spritedebugram_wr_b), + .spritedebugram_data_in_b(spritedebugram_data_in_b), + .spritedebugram_data_out_b(spritedebugram_data_out_b), +`endif + .spr_r(spr_r), + .spr_g(spr_g), + .spr_b(spr_b), + .spr_a(spr_a) +); + +// Sprite collision debug +`ifdef DEBUG_SPRITE_COLLISION +localparam SD_WAIT = 0; +localparam SD_CLEAR_BEGIN = 1; +localparam SD_CLEAR = 2; +reg [2:0] sd_state; +reg vblank_last; +reg [15:0] vblank_start; +always @(posedge clk_24) +begin + vblank_last <= VGA_VB; + case(sd_state) + SD_WAIT: + begin + spritedebugram_wr_a <= 1'b0; + spritedebugram_addr_a <= (({8'b0,vcnt} + 17'd16) * 17'd320) + {8'b0,hcnt} + 17'd19; + + if(!pause_system) + begin + if(VGA_VB && !vblank_last) + begin + sd_state <= SD_CLEAR_BEGIN; + end + end + end + + SD_CLEAR_BEGIN: + begin + //$display("SD_CLEAR_BEGIN: %d %d", hcnt, vcnt); + spritedebugram_addr_a <= 17'b0; + spritedebugram_data_in_a <= 8'd0; + spritedebugram_wr_a <= 1'b1; + sd_state <= SD_CLEAR; + end + + SD_CLEAR: + begin + + if(pause_system) + begin + sd_state <= SD_WAIT; + end + else + begin + if(spritedebugram_addr_a > 17'd79000) + begin + spritedebugram_addr_a <= 17'b0; + sd_state <= SD_WAIT; + //$display("SD_CLEAR_END: %d %d", hcnt, vcnt); + spritedebugram_wr_a <= 1'b0; + end + else + begin + spritedebugram_addr_a <= spritedebugram_addr_a + 17'b1; + end + end + end + endcase +end +`endif +`endif + +// Moroboshi (starfield) +wire sf_on1; +wire [7:0] sf_star1; +starfield #( + .H(396), + .V(256), + .LEN(22), + .SEED(22'h1FFFFF), + .MASK(22'b0000111100001111000011), + .TAPS(22'b1100000000000000000000) +) stars1 +( + .clk(clk_24), + .rst(reset), + .vblank(VGA_VB), + .en(ce_6), + .pause(pause_system), + .addr(cpu_addr[2:0]), + .data_in(cpu_dout), + .write(starfield1_cs && !cpu_wr_n), + .sf_on(sf_on1), + .sf_star(sf_star1) +); +wire sf_on2; +wire [7:0] sf_star2; +`ifndef DISABLE_STARS_2 +starfield #( + .H(396), + .V(256), + .LEN(21), + .SEED(21'h1FFFF0), + .MASK(21'b000011110000111100001), + .TAPS(21'b101010000000000000000) +) stars2 +( + .clk(clk_24), + .rst(reset), + .vblank(VGA_VB), + .en(ce_6), + .pause(pause_system), + .addr(cpu_addr[2:0]), + .data_in(cpu_dout), + .write(starfield2_cs && !cpu_wr_n), + .sf_on(sf_on2), + .sf_star(sf_star2) +); +`endif +wire sf_on3; +wire [7:0] sf_star3; +`ifndef DISABLE_STARS_3 +starfield #( + .H(396), + .V(256), + .LEN(21), + .SEED(21'h1FFF00), + .MASK(21'b000011110000111100001), + .TAPS(21'b101000000000000000000) +) stars3 +( + .clk(clk_24), + .rst(reset), + .vblank(VGA_VB), + .en(ce_6), + .pause(pause_system), + .addr(cpu_addr[2:0]), + .data_in(cpu_dout), + .write(starfield3_cs && !cpu_wr_n), + .sf_on(sf_on3), + .sf_star(sf_star3) +); +`endif + +wire sf_on = sf_on1 || sf_on2 || sf_on3; +wire [7:0] sf_star_colour = sf_on1 ? sf_star1[7:0] : sf_on2 ? {1'b0,sf_star2[6:0]} : sf_on3 ? {2'b0,sf_star3[5:0]} : 8'b0; + +// RGB mixer +`ifdef DEBUG_SPRITE_COLLISION +// highlight collisions +assign VGA_R = spritedebugram_data_out_a > 8'b0 ? spritedebugram_data_out_a : spr_a ? spr_r : charmap_a ? charmap_r : sf_on ? sf_star_colour : 8'b0; +assign VGA_G = spr_a ? spr_g : charmap_a ? charmap_g : sf_on ? sf_star_colour : 8'b0; +assign VGA_B = spritedebugram_data_out_a > 8'b0 ? spritedebugram_data_out_a : spr_a ? spr_b : charmap_a ? charmap_b : sf_on ? sf_star_colour : 8'b0; +`endif +`ifndef DEBUG_SPRITE_COLLISION +assign VGA_R = spr_a ? spr_r : charmap_a ? charmap_r : tilemap_a ? tilemap_r : sf_on ? sf_star_colour : 8'b0; +assign VGA_G = spr_a ? spr_g : charmap_a ? charmap_g : tilemap_a ? tilemap_g : sf_on ? sf_star_colour : 8'b0; +assign VGA_B = spr_a ? spr_b : charmap_a ? charmap_b : tilemap_a ? tilemap_b : sf_on ? sf_star_colour : 8'b0; +`endif + +// Music player +wire [9:0] music_audio_out; +`ifndef DISABLE_MUSIC +localparam MUSIC_ROM_WIDTH = 16; +wire [MUSIC_ROM_WIDTH-1:0] musicrom_addr; +wire [7:0] musicrom_data_out; + +music #(.ROM_WIDTH(MUSIC_ROM_WIDTH)) music ( + .clk(clk_24), + .ce_2(ce_2), + .reset(reset), + .addr(cpu_addr[1:0]), + .data_in(cpu_dout), + .data_out(music_data_out), + .write(music_cs && ~cpu_wr_n), + .musicrom_addr(musicrom_addr), + .musicrom_data_out(musicrom_data_out), + .audio_out(music_audio_out) +); +`endif + + +// M5205 sound player +wire signed [11:0] snd_audio_out; +`ifndef DISABLE_SOUND +localparam SOUND_ROM_WIDTH = 14; +wire [SOUND_ROM_WIDTH-1:0] soundrom_addr; +wire [7:0] soundrom_data_out; + +sound #(.ROM_WIDTH(SOUND_ROM_WIDTH)) sound ( + .clk(clk_24), + .reset(reset), + .addr(cpu_addr[3:0]), + .data_in(cpu_dout), + .write(sound_cs && ~cpu_wr_n), + .soundrom_addr(soundrom_addr), + .soundrom_data_out(soundrom_data_out), + .audio_out(snd_audio_out) +); +`endif + +// Mix audio (badly) +wire signed [15:0] music_signed = { 2'b0, music_audio_out, 4'b0 }; +wire signed [15:0] audio_signed = { 1'b0, (snd_audio_out + 12'b100000000000), 3'b0 } + 16'b1100000000000000; + +assign AUDIO_L = audio_signed + music_signed; +assign AUDIO_R = AUDIO_L; // MEMORY // ------ +localparam PROGRAM_ROM_WIDTH = 15; -// Program ROM - 0x0000 - 0x3FFF (0x4000 / 16384 bytes) -dpram #(14,8, "rom.hex") pgrom +// Program ROM - 0x0000 - 0x7FFF (0x6000 / 32768 bytes) +dpram #(PROGRAM_ROM_WIDTH,8, "rom.hex") pgrom ( - .clock_a(clk_sys), - .address_a(cpu_addr[13:0]), + .clock_a(clk_24), + .address_a(cpu_addr[PROGRAM_ROM_WIDTH-1:0]), .wren_a(1'b0), .data_a(), .q_a(pgrom_data_out), - .clock_b(clk_sys), - .address_b(dn_addr[13:0]), + .clock_b(clk_24), + .address_b(dn_addr[PROGRAM_ROM_WIDTH-1:0]), .wren_b(pgrom_wr), .data_b(dn_data), .q_b() ); -// Char ROM - 0x4000 - 0x47FF (0x0400 / 2048 bytes) +`ifndef DISABLE_CHARMAP +// Char ROM - 0x9000 - 0x97FF (0x0800 / 2048 bytes) dpram #(11,8, "font.hex") chrom ( - .clock_a(clk_sys), + .clock_a(clk_24), .address_a(chrom_addr[10:0]), .wren_a(1'b0), .data_a(), .q_a(chrom_data_out), - .clock_b(clk_sys), + .clock_b(clk_24), .address_b(dn_addr[10:0]), .wren_b(chrom_wr), .data_b(dn_data), .q_b() ); - -// Char RAM - 0x8000 - 0x87FF (0x0800 / 2048 bytes) +// Char index RAM - 0x9800 - 0x9FFF (0x0800 / 2048 bytes) dpram #(11,8) chram ( - .clock_a(clk_sys), + .clock_a(clk_24), .address_a(cpu_addr[10:0]), .wren_a(chram_wr), .data_a(cpu_dout), .q_a(chram_data_out), - .clock_b(clk_sys), + .clock_b(clk_24), .address_b(chram_addr[10:0]), .wren_b(1'b0), .data_b(), .q_b(chmap_data_out) ); -// Char foreground color RAM - 0x8800 - 0x8FFF (0x0800 / 2048 bytes) +// Char foreground color RAM - 0xA000 - 0xA7FF (0x0800 / 2048 bytes) dpram #(11,8) fgcolram ( - .clock_a(clk_sys), + .clock_a(clk_24), .address_a(cpu_addr[10:0]), .wren_a(fgcolram_wr), .data_a(cpu_dout), .q_a(), - .clock_b(clk_sys), + .clock_b(clk_24), .address_b(chram_addr[10:0]), .wren_b(1'b0), .data_b(), .q_b(fgcolram_data_out) ); -// Char background color RAM - 0x9000 - 0x97FF (0x0800 / 2048 bytes) +// Char background color RAM - 0xA800 - 0xAFFF (0x0800 / 2048 bytes) dpram #(11,8) bgcolram ( - .clock_a(clk_sys), + .clock_a(clk_24), .address_a(cpu_addr[10:0]), .wren_a(bgcolram_wr), .data_a(cpu_dout), .q_a(), - .clock_b(clk_sys), + .clock_b(clk_24), .address_b(chram_addr[10:0]), .wren_b(1'b0), .data_b(), .q_b(bgcolram_data_out) ); +`endif + +`ifndef DISABLE_TILEMAP +// Tilemap index RAM +dpram #(TILEMAP_RAM_WIDTH,8) tilemapram +( + .clock_a(clk_24), + .address_a(cpu_addr[TILEMAP_RAM_WIDTH-1:0] - {{TILEMAP_RAM_WIDTH-5{1'b0}},5'h10}), + .wren_a(tilemapram_wr), + .data_a(cpu_dout), + .q_a(), + + .clock_b(clk_24), + .address_b(tilemapram_addr), + .wren_b(tilemapram_ctl_wr), + .data_b(tilemapram_ctl_data_in), + .q_b(tilemapram_data_out) +); +// Tilemap ROM (0x1000 / 4096 bytes) +dpram_w1r2 #(TILEMAP_ROM_WIDTH,8, "tilemap.hex") tilemaprom +( + .clock_a(clk_24), + .address_a(dn_addr[TILEMAP_ROM_WIDTH-1:0]), + .wren_a(tilemaprom_wr), + .data_a(dn_data), + + .clock_b(clk_24), + .address_b(tilemaprom_addr), + .q_b(tilemaprom_data_out) +); +`endif + +`ifndef DISABLE_SPRITES +// Sprite RAM - 0xB000 - 0xB07F (0x0080 / 128 bytes) +dpram #(SPRITE_RAM_WIDTH,8) spriteram +( + .clock_a(clk_24), + .address_a(cpu_addr[SPRITE_RAM_WIDTH-1:0]), + .wren_a(spriteram_wr), + .data_a(cpu_dout), + .q_a(), + + .clock_b(clk_24), + .address_b(spriteram_addr), + .wren_b(1'b0), + .data_b(), + .q_b(spriteram_data_out) +); + +// Sprite Collision RAM - 0xB400 - 0xB47F (0x0080 / 128 bytes) +dpram #(SPRITE_COLRAM_WIDTH,1) spritecollisionram +( + .clock_a(clk_24), + .address_a(cpu_addr[SPRITE_COLRAM_WIDTH-1:0]), + .wren_a(spritecollisionram_cs && ~cpu_wr_n), + .data_a(cpu_dout[0]), + .q_a(spritecollisionram_data_out_cpu), + + .clock_b(clk_24), + .address_b(spritecollisionram_addr), + .wren_b(spritecollisionram_wr), + .data_b(spritecollisionram_data_in), + .q_b(spritecollisionram_data_out) +); + +`ifdef DEBUG_SPRITE_COLLISION +reg [16:0] spritedebugram_addr_a; +wire [16:0] spritedebugram_addr_b; +reg [7:0] spritedebugram_data_in_a; +wire [7:0] spritedebugram_data_in_b; +wire [7:0] spritedebugram_data_out_a; +wire [7:0] spritedebugram_data_out_b; +reg spritedebugram_wr_a; +wire spritedebugram_wr_b; + +// Sprite Debug Frame Buffer +dpram #(17,8) spritedebugram +( + .clock_a(clk_24), + .address_a(spritedebugram_addr_a), + .wren_a(spritedebugram_wr_a), + .data_a(spritedebugram_data_in_a), + .q_a(spritedebugram_data_out_a), + + .clock_b(clk_24), + .address_b(spritedebugram_addr_b), + .wren_b(spritedebugram_wr_b), + .data_b(spritedebugram_data_in_b), + .q_b(spritedebugram_data_out_b) +); +`endif + +// Sprite linebuffer RAM - 0xB800 - 0xBFFF (0x0800 / 2048 bytes) +dpram #(SPRITE_POSITION_WIDTH+1,16) spritelbram +( + .clock_a(clk_24), + .address_a(spritelbram_wr_addr), + .wren_a(spritelbram_wr), + .data_a(spritelbram_data_in), + .q_a(), + + .clock_b(clk_24), + .address_b(spritelbram_rd_addr), + .wren_b(1'b0), + .data_b(), + .q_b(spritelbram_data_out) +); + +// Sprite ROM - 0x11000 - 0x11800 (0x1000 / 4096 bytes) +dpram #(SPRITE_ROM_WIDTH,8, "sprite.hex") spriterom +( + .clock_a(clk_24), + .address_a(sprom_addr), + .wren_a(1'b0), + .data_a(), + .q_a(spriterom_data_out), + + .clock_b(clk_24), + .address_b(dn_addr[SPRITE_ROM_WIDTH-1:0]), + .wren_b(spriterom_wr), + .data_b(dn_data), + .q_b() +); +`endif // Work RAM - 0xC000 - 0xFFFF (0x4000 / 16384 bytes) spram #(14,8) wkram ( - .clock(clk_sys), + .clock(clk_24), .address(cpu_addr[13:0]), .wren(wkram_wr), .data(cpu_dout), .q(wkram_data_out) ); +// Palette ROM - 0x10000 - 0x10040 (0x0100 / 256 bytes) +dpram_w1r2 #(8,8, "palette.hex") palrom +( + .clock_a(clk_24), + .address_a(dn_addr[7:0]), + .wren_a(palrom_wr), + .data_a(dn_data), + + .clock_b(clk_24), + .address_b(palrom_addr), + .q_b(palrom_data_out) +); + +`ifndef DISABLE_MUSIC +// Music ROM - 128kB +dpram #(MUSIC_ROM_WIDTH,8, "music.hex") musicrom +( + .clock_a(clk_24), + .address_a(musicrom_addr), + .wren_a(1'b0), + .data_a(), + .q_a(musicrom_data_out), + + .clock_b(clk_24), + .address_b(dn_addr[MUSIC_ROM_WIDTH-1:0]), + .wren_b(musicrom_wr), + .data_b(dn_data), + .q_b() +); +`endif + +`ifndef DISABLE_SOUND +// Sound ROM - 64kB +dpram #(SOUND_ROM_WIDTH,8, "sound.hex") soundrom +( + .clock_a(clk_24), + .address_a(soundrom_addr), + .wren_a(1'b0), + .data_a(), + .q_a(soundrom_data_out), + + .clock_b(clk_24), + .address_b(dn_addr[SOUND_ROM_WIDTH-1:0]), + .wren_b(soundrom_wr), + .data_b(dn_data), + .q_b() +); +`endif + + endmodule diff --git a/rtl/tilemap.v b/rtl/tilemap.v new file mode 100644 index 0000000..d183296 --- /dev/null +++ b/rtl/tilemap.v @@ -0,0 +1,401 @@ +`timescale 1ns / 1ps +/*============================================================================ + Aznable (custom 8-bit computer system) - Zechs (tilemap) + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 0.1 + Date: 2022-01-04 + + 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 3 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, see . +===========================================================================*/ + +module tilemap #( + parameter TILEMAP_ROM_WIDTH = 15, + parameter TILEMAP_RAM_WIDTH = 10, + parameter [9:0] TILEMAP_WIDTH = 10'd352, + parameter [9:0] TILEMAP_HEIGHT = 10'd272, + parameter [9:0] TILEMAP_BORDER = 10'd16, + parameter [4:0] TILEMAP_CELLS_X = 5'd22, + parameter [4:0] TILEMAP_CELLS_Y = 5'd17 +)( + input clk, + input reset, + input pause, + input [8:0] hcnt, + input [8:0] vcnt, + input hblank, + + input [1:0] addr, + input [7:0] data_in, + input write, + + input [15:0] tilemaprom_data_out, + input [7:0] tilemapram_data_out, + output [7:0] tilemapcontrol_data_out, + output reg [TILEMAP_RAM_WIDTH-1:0] tilemapram_addr, + output reg [TILEMAP_ROM_WIDTH-1:0] tilemaprom_addr, + output reg tilemapram_ctl_wr, + output reg [7:0] tilemapram_ctl_data_in, + + output reg [7:0] tilemap_r, + output reg [7:0] tilemap_g, + output reg [7:0] tilemap_b, + output reg tilemap_a +); + +// Tilemap control registers +// 0 - Tilemap offset X (signed) +// 1 - Tilemap offset Y (signed) +// 2 - Tilemap control trigger +// -> 0 = IDLE +// -> 1 = SCROLL LEFT +// -> 2 = SCROLL RIGHT +// -> 3 = SCROLL UP +// -> 4 = SCROLL DOWN +// -> 5 = CLEAR +reg [7:0] tilemapreg [3:0]; +assign tilemapcontrol_data_out = tilemapreg[addr]; + +// Current tilemap read positions +reg [9:0] tilemap_pos_x; +reg [9:0] tilemap_pos_y; + +// Current tilemap scroll offsets +/* verilator lint_off WIDTH */ +wire signed [9:0] tilemap_offset_x = $signed(tilemapreg[0]); // Convert scroll control x register to signed +wire signed [9:0] tilemap_offset_y = $signed(tilemapreg[1]); // Convert scroll control y register to signed +/* verilator lint_on WIDTH */ + +// Tilemap read machine state +reg [1:0] tilemap_read_state; +reg [15:0] tilemap_read_cycles; + +// Tilemap control state constants +localparam TM_CTL_IDLE = 0; +localparam TM_CTL_SCROLL = 1; +localparam TM_CTL_CLEAR = 2; + +// Tilemap control machine +reg [2:0] tilemap_ctl_state; +reg [4:0] tilemap_ctl_x; +reg [4:0] tilemap_ctl_y; +reg [15:0] tilemap_ctl_cycles; +reg [8:0] tilemap_ctl_hstart; +reg [8:0] tilemap_ctl_vstart; + +// Tilemap scroll state constants +localparam TM_SCROLL_START = 0; +localparam TM_SCROLL_WAIT = 1; +localparam TM_SCROLL_GETINDEX = 2; +localparam TM_SCROLL_SETINDEX = 3; + +// Tilemap scroll control +reg [4:0] tilemap_scroll_state; +reg [4:0] tilemap_scroll_state_next; +reg [4:0] tilemap_scroll_start_pos; +reg [4:0] tilemap_scroll_target_pos; +reg tilemap_scroll_axis; +reg tilemap_scroll_dir; + +// Tilemap clear state constants +localparam TM_CLEAR_PREP = 0; +localparam TM_CLEAR_WRITE = 1; +localparam TM_CLEAR_DONE = 2; + +// Tilemap clear control +reg [2:0] tilemap_clear_state; + +reg [8:0] hcnt_last; +reg hblank_last; + +//`define TM_DEBUG + +always @(posedge clk) begin + + hblank_last <= hblank; + + if(reset) + begin + // Reset tilemap control registers + tilemapreg[0] <= 8'b0; + tilemapreg[1] <= 8'b0; + tilemapreg[2] <= 8'b0; + tilemapreg[3] <= 8'b0; + tilemap_read_state <= 2'b0; + + // Start tilemap clear process + tilemap_clear_state <= TM_CLEAR_PREP; + tilemap_ctl_x = 5'd0; + tilemap_ctl_y = 5'd0; + tilemap_ctl_state <= TM_CTL_CLEAR; + end + else + begin + + if(write) + begin + // Write tilemap control data from CPU + tilemapreg[addr[1:0]] <= data_in; + + // If control trigger is set and control state machine is idle + if(addr[1:0] == 2'd2 && tilemap_ctl_state == TM_CTL_IDLE) + begin +`ifdef TM_DEBUG + $display("TM WRITE: a=%x d=%x", addr[1:0], data_in); +`endif + case(data_in) + 8'd1: // SCROLL LEFT + begin + tilemap_scroll_dir <= 1'b0; + tilemap_scroll_axis <= 1'b0; + tilemap_scroll_start_pos = 5'd1; + tilemap_scroll_target_pos = TILEMAP_CELLS_X - 5'd1; + tilemap_scroll_state <= TM_SCROLL_START; + tilemap_ctl_x = tilemap_scroll_start_pos; + tilemap_ctl_y = 5'd0; + tilemap_ctl_state <= TM_CTL_SCROLL; + tilemap_ctl_hstart <= hcnt; + tilemap_ctl_vstart <= vcnt; + end + 8'd2: // SCROLL RIGHT + begin + tilemap_scroll_dir <= 1'b1; + tilemap_scroll_axis <= 1'b0; + tilemap_scroll_start_pos = TILEMAP_CELLS_X - 5'd2; + tilemap_scroll_target_pos = 5'd0; + tilemap_scroll_state <= TM_SCROLL_START; + tilemap_ctl_x = tilemap_scroll_start_pos; + tilemap_ctl_y = 5'd0; + tilemap_ctl_state <= TM_CTL_SCROLL; + tilemap_ctl_hstart <= hcnt; + tilemap_ctl_vstart <= vcnt; + end + 8'd3: // SCROLL UP + begin + tilemap_scroll_dir <= 1'b0; + tilemap_scroll_axis <= 1'b1; + tilemap_scroll_start_pos = 5'd1; + tilemap_scroll_target_pos = TILEMAP_CELLS_Y - 5'd1; + tilemap_scroll_state <= TM_SCROLL_START; + tilemap_ctl_x = 5'd0; + tilemap_ctl_y = tilemap_scroll_start_pos; + tilemap_ctl_state <= TM_CTL_SCROLL; + tilemap_ctl_hstart <= hcnt; + tilemap_ctl_vstart <= vcnt; + end + 8'd4: // SCROLL DOWN + begin + tilemap_scroll_dir <= 1'b1; + tilemap_scroll_axis <= 1'b1; + tilemap_scroll_start_pos = TILEMAP_CELLS_Y - 5'd2; + tilemap_scroll_target_pos = 5'd0; + tilemap_scroll_state <= TM_SCROLL_START; + tilemap_ctl_x = 5'd0; + tilemap_ctl_y = tilemap_scroll_start_pos; + tilemap_ctl_state <= TM_CTL_SCROLL; + tilemap_ctl_hstart <= hcnt; + tilemap_ctl_vstart <= vcnt; + end + 8'd5: // CLEAR + begin + tilemap_clear_state <= TM_CLEAR_PREP; + tilemap_ctl_x = 5'd0; + tilemap_ctl_y = 5'd0; + tilemap_ctl_state <= TM_CTL_CLEAR; + tilemap_ctl_hstart <= hcnt; + tilemap_ctl_vstart <= vcnt; + end + default: + begin + + end + endcase + end + end + + case(tilemap_ctl_state) + TM_CTL_IDLE: + begin + tilemap_ctl_cycles <= 16'b0; + hcnt_last <= hcnt; + if(hcnt == 9'd395 && hcnt_last == 9'd394) + begin + // When end of HBLANK is reached, reset tilemap read state + tilemap_read_state <= 2'b0; + tilemap_read_cycles <= 16'b0; + end + else + begin + tilemap_read_cycles <= tilemap_read_cycles + 1'b1; + tilemap_read_state <= tilemap_read_state + 2'b1; + case(tilemap_read_state) + 2'b00: + begin + // - Calculate next pixel lookup address + tilemap_pos_x = $signed($signed((hcnt == 9'd395 ? 9'd0 : hcnt + 9'd1)) + TILEMAP_BORDER) + $signed(tilemap_offset_x); + tilemap_pos_y = $signed($signed((vcnt == 9'd255 ? 9'd0 : vcnt)) + TILEMAP_BORDER) + $signed(tilemap_offset_y); + // - Set tilemapram lookup address + tilemapram_addr <= { tilemap_pos_y[8:4], tilemap_pos_x[8:4] }; + // Set colour output for previous ROM lookup + tilemap_r = {tilemaprom_data_out[4:0],tilemaprom_data_out[4:2]}; + tilemap_g = {tilemaprom_data_out[9:5],tilemaprom_data_out[9:7]}; + tilemap_b = {tilemaprom_data_out[14:10],tilemaprom_data_out[14:12]}; + tilemap_a = tilemaprom_data_out[15]; + end + 2'b10: + begin + // Set ROM lookup address based on index RAM and cell offset + tilemaprom_addr <= { tilemapram_data_out[TILEMAP_ROM_WIDTH-10:0], tilemap_pos_y[3:0], tilemap_pos_x[3:0], 1'b0 }; + end + default: begin end + endcase + end + end + TM_CTL_SCROLL: + begin + tilemap_ctl_cycles <= tilemap_ctl_cycles + 16'b1; + case(tilemap_scroll_state) + TM_SCROLL_WAIT: + begin + tilemap_scroll_state <= tilemap_scroll_state_next; + end + TM_SCROLL_START: + begin +`ifdef TM_DEBUG + $display("TM_SCROLL_START: axis=%b dir=%b", tilemap_scroll_axis, tilemap_scroll_dir); +`endif + tilemapram_addr <= { tilemap_ctl_y, tilemap_ctl_x }; + tilemap_scroll_state <= TM_SCROLL_WAIT; + tilemap_scroll_state_next <= TM_SCROLL_GETINDEX; + end + TM_SCROLL_GETINDEX: + begin +`ifdef TM_DEBUG + $display("TM_SCROLL_GETINDEX: %d/%d - %x %d", tilemap_ctl_x, tilemap_ctl_y, tilemapram_addr, tilemapram_data_out); +`endif + tilemapram_ctl_data_in <= tilemapram_data_out; + if(tilemap_scroll_axis) + begin + tilemapram_addr <= { tilemap_scroll_dir ? tilemap_ctl_y + 5'd1 : tilemap_ctl_y - 5'd1, tilemap_ctl_x }; + end + else + begin + tilemapram_addr <= { tilemap_ctl_y, tilemap_scroll_dir ? tilemap_ctl_x + 5'd1 : tilemap_ctl_x - 5'd1 }; + end + tilemapram_ctl_wr <= 1'b1; + tilemap_scroll_state <= TM_SCROLL_WAIT; + tilemap_scroll_state_next <= TM_SCROLL_SETINDEX; + end + TM_SCROLL_SETINDEX: + begin +`ifdef TM_DEBUG + $display("TM_SCROLL_SETINDEX: %d/%d - %x %d", tilemap_ctl_x, tilemap_ctl_y, tilemapram_addr, tilemapram_ctl_data_in); +`endif + tilemapram_ctl_wr <= 1'b0; + if((tilemap_scroll_axis ? tilemap_ctl_y : tilemap_ctl_x) == tilemap_scroll_target_pos) + begin + if(!tilemap_scroll_axis ? (tilemap_ctl_y == TILEMAP_CELLS_Y - 5'd1) : (tilemap_ctl_x == TILEMAP_CELLS_X - 5'd1)) + begin + // Scroll process completed + tilemap_ctl_state <= TM_CTL_IDLE; +`ifdef TM_DEBUG + $display("TM_SCROLL_COMPLETE - in %d | vstart: %d vend: %d | hstart: %d hend: %d", tilemap_ctl_cycles, tilemap_ctl_vstart, vcnt, tilemap_ctl_hstart, hcnt); +`endif + // Clear trigger control register + tilemapreg[2] <= 8'b0; + end + else + begin + if(tilemap_scroll_axis) + begin + tilemap_ctl_y = tilemap_scroll_start_pos; + tilemap_ctl_x = tilemap_ctl_x + 5'd1; + end + else + begin + tilemap_ctl_x = tilemap_scroll_start_pos; + tilemap_ctl_y = tilemap_ctl_y + 5'd1; + end + tilemapram_addr <= { tilemap_ctl_y, tilemap_ctl_x }; + tilemap_scroll_state <= TM_SCROLL_WAIT; + tilemap_scroll_state_next <= TM_SCROLL_GETINDEX; + end + end + else + begin + if(tilemap_scroll_axis) + begin + tilemap_ctl_y = tilemap_scroll_dir ? tilemap_ctl_y - 5'd1 : tilemap_ctl_y + 5'd1; + end + else + begin + tilemap_ctl_x = tilemap_scroll_dir ? tilemap_ctl_x - 5'd1 : tilemap_ctl_x + 5'd1; + end + tilemapram_addr <= { tilemap_ctl_y, tilemap_ctl_x }; + tilemap_scroll_state <= TM_SCROLL_WAIT; + tilemap_scroll_state_next <= TM_SCROLL_GETINDEX; + end + end + endcase + end + TM_CTL_CLEAR: + begin + case(tilemap_clear_state) + TM_CLEAR_PREP: + begin +`ifdef TM_DEBUG + $display("TM_CLEAR_PREP tilemap_ctl_x=%d tilemap_ctl_y=%d", tilemap_ctl_x, tilemap_ctl_y); +`endif + tilemapram_addr <= { tilemap_ctl_y, tilemap_ctl_x }; + tilemapram_ctl_wr <= 1'b1; + tilemapram_ctl_data_in <= 8'b0; + tilemap_clear_state <= TM_CLEAR_WRITE; + end + TM_CLEAR_WRITE: + begin +`ifdef TM_DEBUG + $display("TM_CLEAR_WRITE tilemap_ctl_x=%d tilemap_ctl_y=%d", tilemap_ctl_x, tilemap_ctl_y); +`endif + tilemap_clear_state <= TM_CLEAR_PREP; + tilemap_ctl_x = tilemap_ctl_x + 5'd1; + if(tilemap_ctl_x == TILEMAP_CELLS_X) + begin + tilemap_ctl_x = 5'd0; + if(tilemap_ctl_y == TILEMAP_CELLS_Y) + begin + tilemap_clear_state <= TM_CLEAR_DONE; + end + else + begin + tilemap_ctl_y = tilemap_ctl_y + 5'd1; + end + end + end + TM_CLEAR_DONE: + begin +`ifdef TM_DEBUG + $display("TM_CLEAR_DONE tilemap_ctl_x=%d tilemap_ctl_y=%d", tilemap_ctl_x, tilemap_ctl_y); +`endif + tilemapram_ctl_wr <= 1'b0; + tilemap_ctl_state <= TM_CTL_IDLE; + // Clear trigger control register + tilemapreg[2] <= 8'b0; + end + endcase + end + endcase + end +end + +endmodule \ No newline at end of file diff --git a/rtl/tv80/TV80.qip b/rtl/tv80/TV80.qip index 10942d1..0608f02 100644 --- a/rtl/tv80/TV80.qip +++ b/rtl/tv80/TV80.qip @@ -3,4 +3,5 @@ set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "tv80_a set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "tv80_mcode.v"] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "tv80_reg.v"] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "tv80n.v"] -set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "tv80s.v"] \ No newline at end of file +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "tv80s.v"] +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "tv80e.v"] \ No newline at end of file diff --git a/rtl/tv80/tv80e.v b/rtl/tv80/tv80e.v new file mode 100644 index 0000000..411b065 --- /dev/null +++ b/rtl/tv80/tv80e.v @@ -0,0 +1,161 @@ +`timescale 1ns / 1ps +// +// TV80 8-Bit Microprocessor Core +// Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org) +// +// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +module tv80e (/*AUTOARG*/ + // Outputs + m1_n, mreq_n, iorq_n, rd_n, wr_n, rfsh_n, halt_n, busak_n, A, dout, + // Inputs + reset_n, clk, cen, wait_n, int_n, nmi_n, busrq_n, di + ); + + parameter Mode = 0; // 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + parameter T2Write = 1; // 0 => wr_n active in T3, /=0 => wr_n active in T2 + parameter IOWait = 1; // 0 => Single cycle I/O, 1 => Std I/O cycle + + + input reset_n; + input clk; + input cen; + input wait_n; + input int_n; + input nmi_n; + input busrq_n; + output m1_n; + output mreq_n; + output iorq_n; + output rd_n; + output wr_n; + output rfsh_n; + output halt_n; + output busak_n; + output [15:0] A; + input [7:0] di; + output [7:0] dout; + + reg mreq_n; + reg iorq_n; + reg rd_n; + reg wr_n; + + wire intcycle_n; + wire no_read; + wire write; + wire iorq; + reg [7:0] di_reg; + wire [6:0] mcycle; + wire [6:0] tstate; + + tv80_core #(Mode, IOWait) i_tv80_core + ( + .cen (cen), + .m1_n (m1_n), + .iorq (iorq), + .no_read (no_read), + .write (write), + .rfsh_n (rfsh_n), + .halt_n (halt_n), + .wait_n (wait_n), + .int_n (int_n), + .nmi_n (nmi_n), + .reset_n (reset_n), + .busrq_n (busrq_n), + .busak_n (busak_n), + .clk (clk), + .IntE (), + .stop (), + .A (A), + .dinst (di), + .di (di_reg), + .dout (dout), + .mc (mcycle), + .ts (tstate), + .intcycle_n (intcycle_n) + ); + + always @(posedge clk or negedge reset_n) + begin + if (!reset_n) + begin + rd_n <= #1 1'b1; + wr_n <= #1 1'b1; + iorq_n <= #1 1'b1; + mreq_n <= #1 1'b1; + di_reg <= #1 0; + end + else if(cen) + begin + rd_n <= #1 1'b1; + wr_n <= #1 1'b1; + iorq_n <= #1 1'b1; + mreq_n <= #1 1'b1; + if (mcycle[0]) + begin + if (tstate[1] || (tstate[2] && wait_n == 1'b0)) + begin + rd_n <= #1 ~ intcycle_n; + mreq_n <= #1 ~ intcycle_n; + iorq_n <= #1 intcycle_n; + end + `ifdef TV80_REFRESH + if (tstate[3]) + mreq_n <= #1 1'b0; + `endif + end // if (mcycle[0]) + else + begin + if ((tstate[1] || (tstate[2] && wait_n == 1'b0)) && no_read == 1'b0 && write == 1'b0) + begin + rd_n <= #1 1'b0; + iorq_n <= #1 ~ iorq; + mreq_n <= #1 iorq; + end + if (T2Write == 0) + begin + if (tstate[2] && write == 1'b1) + begin + wr_n <= #1 1'b0; + iorq_n <= #1 ~ iorq; + mreq_n <= #1 iorq; + end + end + else + begin + if ((tstate[1] || (tstate[2] && wait_n == 1'b0)) && write == 1'b1) + begin + wr_n <= #1 1'b0; + iorq_n <= #1 ~ iorq; + mreq_n <= #1 iorq; + end + end // else: !if(T2write == 0) + + end // else: !if(mcycle[0]) + + if (tstate[2] && wait_n == 1'b1) + di_reg <= #1 di; + end // else: !if(!reset_n) + end // always @ (posedge clk or negedge reset_n) + +endmodule // t80s + diff --git a/src/Makefile b/src/Makefile deleted file mode 100644 index 4ce31fc..0000000 --- a/src/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -SDCC=sdcc -CPU=z80 -CODE=os -OBJ=os.rel -DATALOC=0xC000 - -all: $(CODE).bin - -%.rel: %.c - $(SDCC) -m$(CPU) -c --data-loc $(DATALOC) $< - -%.ihx: $(OBJ) - $(SDCC) -m$(CPU) --data-loc $(DATALOC) $(OBJ) - -%.hex: %.ihx - mv $< $@ - -%.bin: %.hex - srec_cat $< -intel -o $@ -binary - -disasm: $(CODE).bin - z80dasm -a -t -g 0 $< - -clean: - rm -rf *~ *.asm *.ihx *.lk *.lst *.map *.noi *.rel *.sym *.hex *.bin diff --git a/src/inputtest/.define b/src/inputtest/.define new file mode 100644 index 0000000..4c5c7f1 --- /dev/null +++ b/src/inputtest/.define @@ -0,0 +1,10 @@ +//DISABLE_CPU +//DISABLE_SPRITES +//DISABLE_TILEMAP +//DISABLE_CHARMAP +//DEBUG_SPRITE_COLLISION +//DISABLE_STARS_1 +//DISABLE_STARS_2 +//DISABLE_STARS_3 +//DISABLE_MUSIC +//DISABLE_SOUND \ No newline at end of file diff --git a/src/inputtest/Makefile b/src/inputtest/Makefile new file mode 100644 index 0000000..11d304c --- /dev/null +++ b/src/inputtest/Makefile @@ -0,0 +1,2 @@ +DEFINES=-DPROJECT_NAME=inputtest +include ../shared/Makefile diff --git a/src/inputtest/credits.c b/src/inputtest/credits.c new file mode 100644 index 0000000..0277480 --- /dev/null +++ b/src/inputtest/credits.c @@ -0,0 +1,132 @@ +/*============================================================================ + Aznable OS - Credits + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2022-01-05 + + 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 3 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, see . +===========================================================================*/ +#include "../shared/sys.h" +#include "../shared/ui.h" +#include "../shared/ps2.h" +#include "../shared/sprite.h" +#include "../shared/music.h" +#include "../shared/tilemap.h" +#include "../shared/starfield.h" +#include "credits.h" +#include "inputtester_sys.h" + +const char *credits_text = "CODE AND GFX_-_JIMMYSTONES___MUSIC_-_DARRIN CARDANI___TESTING_-_PORKCHOP EXPRESS_SORGELIG_M WALRUS___EXTRA THANKS_-_ALANSWX_SORGELIG___"; +unsigned char credits_pos = 0; +unsigned short credits_entry_pos = (16 * 32); + +void app_credits() +{ + clear_chars(0); + clear_sprites(); + clear_tilemap(); + stop_music(); + + enable_starfield(); + set_starfield_speed_x(0); + set_starfield_speed_y(-0.1f); + + tilemap_offset_x = 0; + tilemap_offset_y = 0; + + char credits_line[22]; + credits_pos = 0; + + while (1) + { + vblank = CHECK_BIT(input0, INPUT_VBLANK); + + if (VBLANK_RISING) + { + if (tilemap_offset_y >= 16) + { + tilemap_offset_y -= 16; + update_tilemap_offset(); + + scroll_tilemap_up(); + + unsigned char d; + unsigned char c; + unsigned char credits_line_len = 0; + for (d = 0; d < 22; d++) + { + c = credits_text[credits_pos]; + credits_pos++; + if (c == '_' || c == 0) + { + break; + } + else + { + credits_line[d] = c; + credits_line_len++; + } + if (credits_pos >= strlen(credits_text) - 1) + { + credits_pos = 0; + break; + } + } + signed char credits_line_pre = (22 - credits_line_len) / 2; + for (d = 0; d < 22; d++) + { + c = 0; + signed char i = d - credits_line_pre; + if (i >= 0 && i < credits_line_len) + { + c = (credits_line[i] != '-') ? (credits_line[i] - 45) : 1; + } + tilemapram[credits_entry_pos + d] = c; + } + } + else + { + update_tilemap_offset(); + } + } + + if (VBLANK_FALLING) + { + handle_ps2(); + basic_input(); + if (input_a || input_b || input_select || input_start) + { + break; + } + signed dir = 1; + tilemap_offset_y += 2; + if (input_up) + { + tilemap_offset_y += 4; + } + } + + vblank_last = vblank; + } + + clear_chars(0); + clear_sprites(); + clear_tilemap(); + stop_music(); + + disable_starfield(); + + state = defaultstate; +} \ No newline at end of file diff --git a/src/inputtest/credits.h b/src/inputtest/credits.h new file mode 100644 index 0000000..0d83108 --- /dev/null +++ b/src/inputtest/credits.h @@ -0,0 +1,22 @@ +/*============================================================================ + Aznable OS - Credits + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2022-01-05 + + 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 3 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, see . +===========================================================================*/ + +extern void app_credits(); \ No newline at end of file diff --git a/src/fader.c b/src/inputtest/fader.c similarity index 94% rename from src/fader.c rename to src/inputtest/fader.c index 060ae69..261aef1 100644 --- a/src/fader.c +++ b/src/inputtest/fader.c @@ -19,12 +19,11 @@ with this program. If not, see . ===========================================================================*/ -#pragma once +#include "../shared/sys.h" +#include "../shared/ui.h" +#include "fader.h" +#include "inputtester_sys.h" -#include "sys.c" - -// Fade in/out constants -#define fadefreq 4 // Fade in/out variables unsigned char fade = 0; unsigned char fadetimer = 0; diff --git a/src/inputtest/fader.h b/src/inputtest/fader.h new file mode 100644 index 0000000..ac6c9fc --- /dev/null +++ b/src/inputtest/fader.h @@ -0,0 +1,42 @@ +/*============================================================================ + Input Test - Fader + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-07-12 + + 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 3 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, see . +===========================================================================*/ +#ifndef FADER_H +#define FADER_H + +// Fade in/out constants +#define fadefreq 4 +// Fade in/out variables +extern unsigned char fade; +extern unsigned char fadetimer; + +// Initialise fadeout state +extern void start_fadeout(); + +// Initialise fadein state +extern void start_fadein(); + +// Fade out state +extern void fadeout(); + +// Fade in state +extern void fadein(); + +#endif \ No newline at end of file diff --git a/src/inputtester.c b/src/inputtest/inputtester_app.c similarity index 85% rename from src/inputtester.c rename to src/inputtest/inputtester_app.c index 6499452..ab7fb36 100644 --- a/src/inputtester.c +++ b/src/inputtest/inputtester_app.c @@ -1,29 +1,35 @@ /*============================================================================ - Input Test - Input test state handlers + Input Test - Input test state handlers - Author: Jim Gregory - https://github.com/JimmyStones/ - Version: 1.0 - Date: 2021-07-13 + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-07-13 - 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 3 of the License, or (at your option) - any later version. + 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 3 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. + 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, see . + You should have received a copy of the GNU General Public License along + with this program. If not, see . ===========================================================================*/ -#pragma once - -#include "sys.c" -#include "fader.c" -#include "menu.c" +#include "../shared/sys.h" +#include "../shared/ui.h" +#include "../shared/ps2.h" +#include "../shared/sprite.h" +#include "fader.h" +#include "menu.h" +#include "sprite_images.h" +#include "inputtester_app.h" +#include "inputtester_sys.h" +#include "inputtester_ui.h" +#include "inputtester_pings.h" // Input tester variables unsigned char joystick_last[12]; @@ -42,9 +48,11 @@ unsigned char mse_button2_last = 255; signed char mse_x_last = 1; signed char mse_y_last = 1; signed char mse_w_last = 1; -unsigned char mse_x_acc; -unsigned char mse_y_acc; -unsigned char mse_w_acc; +signed short mse_x_acc; +signed short mse_y_acc; +signed short mse_w_acc; + +#define MOUSE_POINTER_SPRITE 9 // Mode switcher variables char modeswitchtimer_select = 0; @@ -261,6 +269,13 @@ void start_inputtester_advanced() // Draw page page_inputtester_advanced(); + // Setup mouse pointer + enable_sprite(MOUSE_POINTER_SPRITE, sprite_palette_pointer, sprite_size_pointer, 0); + spr_index[MOUSE_POINTER_SPRITE] = sprite_index_pointer_first; + spr_on[MOUSE_POINTER_SPRITE] = 0; + mse_x_acc = 336; + mse_y_acc = 256; + // Reset last states for inputs reset_inputstates(); } @@ -316,12 +331,22 @@ void handle_codes() { pushhistory(5); } + if (!input_b && input_b_last) + { + pushhistory(6); + } // Check for SNEK code if (history[0] == 1 && history[1] == 1 && history[2] == 2 && history[3] == 2 && history[4] == 3 && history[5] == 4 && history[6] == 5) { - nextstate = STATE_START_ATTRACT; pushhistory(0); - start_fadeout(); + state = STATE_START_ATTRACT; + return; + } + // Check for Zorblax code + if (history[0] == 1 && history[1] == 1 && history[2] == 2 && history[3] == 2 && history[4] == 3 && history[5] == 4 && history[6] == 6) + { + pushhistory(0); + state = STATE_START_ZORBLAXX; return; } } @@ -329,6 +354,15 @@ void handle_codes() // Menu opening handler bool modeswitcher() { + // Check system menu trigger + if (system_menu) + { + system_menu = 0; + modeswitchtimer_select = 0; + start_menu(); + return 1; + } + // Open menu if select is held if (input_select) { @@ -351,7 +385,7 @@ bool modeswitcher() void inputtester_digital() { - // // Handle PS/2 inputs whenever possible to improve latency + // Handle PS/2 inputs whenever possible to improve latency handle_ps2(); // Handle secret code detection (joypad 1 directions) @@ -493,14 +527,16 @@ void inputtester_advanced() // Handle test mode switch if (modeswitcher()) { + clear_sprites(); + update_sprites(); return; } // Draw joystick inputs (only update each byte if value has changed) for (char inputindex = 0; inputindex < 6; inputindex++) { - char m = 0b00000001; - char x = 6; + char mask = 0b00000001; + char cx = 6; char y = 6 + inputindex; char inputoffset = (inputindex * 4); char lastoffset = (inputindex * 2); @@ -511,18 +547,18 @@ void inputtester_advanced() char joy = joystick[index]; if (joy != joystick_last[lastindex]) { - m = 0b00000001; + mask = 0b00000001; char bytes = (b == 0 ? 8 : 4); for (char i = 0; i < bytes; i++) { - x++; - write_char((joy & m) ? asc_1 : asc_0, 0xFF, x, y); - m <<= 1; + cx++; + write_char((joy & mask) ? asc_1 : asc_0, 0xFF, cx, y); + mask <<= 1; } } else { - x += 8; + cx += 8; } joystick_last[lastindex] = joy; } @@ -595,12 +631,37 @@ void inputtester_advanced() if (mse_changed) { + // Mouse position accumulator mse_x_acc += mse_x; - mse_y_acc += mse_y; + mse_y_acc -= mse_y; mse_w_acc += mse_w; - write_stringf("%3d", 0xFF, 8, 23, mse_x_acc); - write_stringf("%3d", 0xFF, 12, 23, mse_y_acc); + // Enforce mouse pointer limit + if (mse_x_acc < 32) + { + mse_x_acc = 32; + } + else if (mse_x_acc >= 671) + { + mse_x_acc = 671; + } + if (mse_y_acc < 32) + { + mse_y_acc = 32; + } + else if (mse_y_acc >= 511) + { + mse_y_acc = 511; + } + unsigned short mx = (mse_x_acc / 2); + unsigned short my = (mse_y_acc / 2); + if (mse_x != 0 || mse_y != 0) + { + spr_on[MOUSE_POINTER_SPRITE] = 1; + set_sprite_position(MOUSE_POINTER_SPRITE, mx, my); + } + write_stringf_ushort("%3d", 0xFF, 8, 23, mx - 16); + write_stringf_ushort("%3d", 0xFF, 12, 23, my - 16); write_stringf("%3d", 0xFF, 20, 23, mse_w_acc); if (mse_button1_last != mse_button1) @@ -613,8 +674,10 @@ void inputtester_advanced() write_char((mse_button1 & m) ? asc_1 : asc_0, 0xFF, x, 23); m <<= 1; } - mse_button1_last = mse_button1; + input_mouse_left = CHECK_BIT(mse_button1, 0); + input_mouse_right = CHECK_BIT(mse_button1, 1); } + mse_button1_last = mse_button1; if (mse_button2_last != mse_button2) { char x = 31; @@ -625,10 +688,23 @@ void inputtester_advanced() write_char((mse_button2 & m) ? asc_1 : asc_0, 0xFF, x, 23); m <<= 1; } - mse_button2_last = mse_button2; } + mse_button2_last = mse_button2; + + if (input_mouse_left && !input_mouse_left_last) + { + add_ping(0, mx - 8, my - 8); + } + if (input_mouse_right && !input_mouse_right_last) + { + add_ping(1, mx - 8, my - 8); + } + mse_changed = 0; } + + handle_pings(); + update_sprites(); } } @@ -780,14 +856,6 @@ void btntest_test() } } -unsigned short abs(signed short value) -{ - if (value < 0) - { - value = value * -1; - } - return value; -} // Button test - results view void btntest_results() { diff --git a/src/inputtest/inputtester_app.h b/src/inputtest/inputtester_app.h new file mode 100644 index 0000000..4a2ea84 --- /dev/null +++ b/src/inputtest/inputtester_app.h @@ -0,0 +1,78 @@ +/*============================================================================ + Input Test - Input test state handlers + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-07-13 + + 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 3 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, see . +===========================================================================*/ + +#ifndef INPUTTESTER_H +#define INPUTTESTER_H + +// Mode switcher variables +extern char modeswitchtimer_select; +extern char modeswitchtimer_start; + +#define PAD_COUNT 2 +#define BUTTON_COUNT 12 + +#define color_button_active 0xFF +#define color_button_inactive 0b01010010 +#define analog_size 18 +#define analog_ratio 15 // 256 / 17; +#define timestamp_clock_index 32 +#define timestamp_index_1 8 +#define timestamp_index_2 16 +#define timestamp_index_3 24 +// Button test constants +#define btntest_mode_select 0 +#define btntest_mode_ready 1 +#define btntest_mode_test 2 +#define btntest_mode_results 3 +#define btntest_timer_start 60 // vblanks to wait before first prompt +#define btntest_timer_interval 90 // vblanks to wait between prompts +#define btntest_timer_visible 30 // vblanks to wait between prompts +#define btntest_counter_max 5 // Number of button presses required +#define btntest_max 255 +#define btntest_highlight_start 2 +#define btntest_highlight_end 35 + +// Initialise digital inputtester state and draw static elements +extern void start_inputtester_digital(); + +// Initialise analog inputtester state and draw static elements +extern void start_inputtester_analog(); + +// Initialise advanced inputtester state and draw static elements +extern void start_inputtester_advanced(); + +// Initialise button test state and draw static elements +extern void start_btntest(); + +// Digital input tester state +extern void inputtester_digital(); + +// Analog input tester state +extern void inputtester_analog(); + +// Advanced input tester state +extern void inputtester_advanced(); + +// Button test - mode handler +extern void btntest(); + + +#endif \ No newline at end of file diff --git a/src/inputtest/inputtester_pings.c b/src/inputtest/inputtester_pings.c new file mode 100644 index 0000000..9ebab58 --- /dev/null +++ b/src/inputtest/inputtester_pings.c @@ -0,0 +1,88 @@ +/*============================================================================ + Input Test - Mouse ping animations + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-12-22 + + 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 3 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, see . +===========================================================================*/ + +#include "../shared/sys.h" +#include "../shared/sprite.h" +#include "sprite_images.h" +#include "inputtester_pings.h" + +#define const_ping_max 8 +unsigned char ping_max = const_ping_max; +unsigned char ping_sprite_first = 0; +unsigned char ping_timer[const_ping_max]; +unsigned char ping_frame[const_ping_max]; +unsigned char ping_type[const_ping_max]; +const unsigned char ping_lifespan = 2; +#define ping_frame_count 7 +#define ping_type_count 2 + +void setup_pings() +{ + for (int e = ping_sprite_first; e < ping_sprite_first + ping_max; e++) + { + enable_sprite(e, sprite_palette_pings, sprite_size_pings, false); + spr_on[e] = false; + } +} + +void add_ping(unsigned type, unsigned short x, unsigned short y) +{ + for (unsigned char e = 0; e < ping_max; e++) + { + if (ping_timer[e] == 0) + { + ping_timer[e] = ping_lifespan; + ping_frame[e] = 0; + type = 0; + // ping_type[e] = type; + unsigned char sprite = ping_sprite_first + e; + enable_sprite(sprite, sprite_palette_pings, sprite_size_pings, 0); + spr_index[sprite] = sprite_index_pings_first + (type * ping_frame_count); + set_sprite_position(sprite, x, y); + return; + } + } +} + +void handle_pings() +{ + for (unsigned char t = 0; t < ping_max; t++) + { + if (ping_timer[t] > 0) + { + ping_timer[t]--; + if (ping_timer[t] == 0) + { + unsigned char sprite = ping_sprite_first + t; + spr_index[sprite]++; + ping_frame[t]++; + if (ping_frame[t] == ping_frame_count) + { + spr_on[sprite] = false; + } + else + { + ping_timer[t] = ping_lifespan; + } + } + } + } +} \ No newline at end of file diff --git a/src/inputtest/inputtester_pings.h b/src/inputtest/inputtester_pings.h new file mode 100644 index 0000000..7120bd0 --- /dev/null +++ b/src/inputtest/inputtester_pings.h @@ -0,0 +1,38 @@ +/*============================================================================ + Input Test - Mouse ping animations + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-12-22 + + 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 3 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, see . +===========================================================================*/ + +#ifndef INPUTTESTER_PINGS_H +#define INPUTTESTER_PINGS_H + +extern unsigned char ping_max; +extern unsigned char ping_sprite_first; +extern unsigned char ping_timer[]; +extern unsigned char ping_frame[]; +extern unsigned char ping_type[]; +extern const unsigned char ping_lifespan; + +extern void setup_pings(); + +extern void add_ping(unsigned type, unsigned short x, unsigned short y); + +extern void handle_pings(); + +#endif \ No newline at end of file diff --git a/src/sys_custom.c b/src/inputtest/inputtester_sys.c similarity index 71% rename from src/sys_custom.c rename to src/inputtest/inputtester_sys.c index b24dc79..849c6cd 100644 --- a/src/sys_custom.c +++ b/src/inputtest/inputtester_sys.c @@ -19,37 +19,9 @@ with this program. If not, see . ===========================================================================*/ -#pragma once -#include "sys.c" -#include "ps2.c" - -// Application states -#define STATE_START_INPUTTESTER 1 -#define STATE_INPUTTESTER 2 - -#define STATE_START_INPUTTESTERADVANCED 3 -#define STATE_INPUTTESTERADVANCED 4 - -#define STATE_START_INPUTTESTERANALOG 5 -#define STATE_INPUTTESTERANALOG 6 - -#define STATE_START_BTNTEST 7 -#define STATE_BTNTEST 8 - -#define STATE_START_MENU 9 -#define STATE_MENU 10 - -#define STATE_FADEOUT 20 -#define STATE_START_FADEIN 21 -#define STATE_FADEIN 22 - -#define STATE_START_ATTRACT 30 -#define STATE_ATTRACT 31 - -#define STATE_START_GAME_SNEK 40 -#define STATE_GAME_SNEK 41 - -#define GET_TIMER ((unsigned short)timer[1] << 8) | (unsigned char)timer[0] +#include "../shared/sys.h" +#include "../shared/ps2.h" +#include "inputtester_sys.h" // DPAD tracker bool input_left = 0; @@ -69,6 +41,17 @@ bool input_a_last = 0; bool input_b; bool input_b_last = 0; +// Mouse tracker +bool input_mouse_left; +bool input_mouse_left_last; +bool input_mouse_right; +bool input_mouse_right_last; + +// Input tester application state +char state = 0; +char defaultstate = STATE_START_INPUTTESTER; +char nextstate = 0; + // Track joypad 1 directions and start for menu control void basic_input() { @@ -80,12 +63,15 @@ void basic_input() input_select_last = input_select; input_a_last = input_a; input_b_last = input_b; - input_up = CHECK_BIT(joystick[0], 3) || kbd_down[KEY_UP]; - input_down = CHECK_BIT(joystick[0], 2) || kbd_down[KEY_DOWN]; - input_left = CHECK_BIT(joystick[0], 1) || kbd_down[KEY_LEFT]; + input_mouse_left_last = input_mouse_left; + input_mouse_right_last = input_mouse_right; + input_right = CHECK_BIT(joystick[0], 0) || kbd_down[KEY_RIGHT]; - input_start = CHECK_BIT(joystick[1], 3) || kbd_down[KEY_1]; - input_select = CHECK_BIT(joystick[1], 2) || kbd_down[KEY_ESC]; + input_left = CHECK_BIT(joystick[0], 1) || kbd_down[KEY_LEFT]; + input_down = CHECK_BIT(joystick[0], 2) || kbd_down[KEY_DOWN]; + input_up = CHECK_BIT(joystick[0], 3) || kbd_down[KEY_UP]; input_a = CHECK_BIT(joystick[0], 4) || kbd_down[KEY_ENTER]; input_b = CHECK_BIT(joystick[0], 5) || kbd_down[KEY_SPACE]; + input_start = CHECK_BIT(joystick[1], 3) || kbd_down[KEY_1]|| mse_button1; + input_select = CHECK_BIT(joystick[1], 2) || kbd_down[KEY_ESC] || mse_button2; } diff --git a/src/inputtest/inputtester_sys.h b/src/inputtest/inputtester_sys.h new file mode 100644 index 0000000..5f2c66e --- /dev/null +++ b/src/inputtest/inputtester_sys.h @@ -0,0 +1,89 @@ +/*============================================================================ + Input Test - Custom system functions + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-07-12 + + 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 3 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, see . +===========================================================================*/ + +#ifndef INPUTTESTER_SYS_H +#define INPUTTESTER_SYS_H + +// Application states +#define STATE_START_INPUTTESTER 1 +#define STATE_INPUTTESTER 2 + +#define STATE_START_INPUTTESTERADVANCED 3 +#define STATE_INPUTTESTERADVANCED 4 + +#define STATE_START_INPUTTESTERANALOG 5 +#define STATE_INPUTTESTERANALOG 6 + +#define STATE_START_BTNTEST 7 +#define STATE_BTNTEST 8 + +#define STATE_START_MENU 9 +#define STATE_MENU 10 + +#define STATE_FADEOUT 20 +#define STATE_START_FADEIN 21 +#define STATE_FADEIN 22 + +#define STATE_START_ATTRACT 30 +#define STATE_ATTRACT 31 + +#define STATE_START_GAME_SNEK 40 +#define STATE_GAME_SNEK 41 + +#define STATE_START_CREDITS 42 + +#define STATE_START_ZORBLAXX 43 + +#define GET_TIMER ((unsigned short)timer[1] << 8) | (unsigned char)timer[0] + +// DPAD tracker +extern bool input_left; +extern bool input_left_last; +extern bool input_right; +extern bool input_right_last; +extern bool input_up; +extern bool input_up_last; +extern bool input_down; +extern bool input_down_last; +extern bool input_start; +extern bool input_start_last; +extern bool input_select; +extern bool input_select_last; +extern bool input_a; +extern bool input_a_last; +extern bool input_b; +extern bool input_b_last; + +// Mouse tracker +extern bool input_mouse_left; +extern bool input_mouse_left_last; +extern bool input_mouse_right; +extern bool input_mouse_right_last; + +// Input tester application state +extern char state; +extern char defaultstate; +extern char nextstate; + +// Track joypad 1 directions and start for menu control +extern void basic_input(); + +#endif \ No newline at end of file diff --git a/src/ui_custom.c b/src/inputtest/inputtester_ui.c similarity index 98% rename from src/ui_custom.c rename to src/inputtest/inputtester_ui.c index d165c80..c78a8ae 100644 --- a/src/ui_custom.c +++ b/src/inputtest/inputtester_ui.c @@ -18,10 +18,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . ===========================================================================*/ -#pragma once #include - -#define color_pad_outline 0xFE +#include "../shared/sys.h" +#include "../shared/ui.h" +#include "inputtester_ui.h" void page_frame(bool showMenuButton, bool showContinueButton) { @@ -93,8 +93,6 @@ void draw_pad(char xo, char yo) write_char(char_corner_round_tr, color_pad_outline, xo + 25, yo); } -#define color_analog_grid 0x23 - // Draw game pad outline void draw_analog(char xo, char yo, char xs, char ys) { diff --git a/src/inputtest/inputtester_ui.h b/src/inputtest/inputtester_ui.h new file mode 100644 index 0000000..0931a23 --- /dev/null +++ b/src/inputtest/inputtester_ui.h @@ -0,0 +1,35 @@ +/*============================================================================ + Input Test - Custom UI functions + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-07-12 + + 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 3 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, see . +===========================================================================*/ +#ifndef INPUTTESTER_UI_H +#define INPUTTESTER_UI_H + +#define color_pad_outline 0xFE +#define color_analog_grid 0x23 + +extern void page_frame(bool showMenuButton, bool showContinueButton); + +// Draw game pad outline +extern void draw_pad(char xo, char yo); + +// Draw game pad outline +extern void draw_analog(char xo, char yo, char xs, char ys); + +#endif \ No newline at end of file diff --git a/src/inputtest/loader.c b/src/inputtest/loader.c new file mode 100644 index 0000000..61dbd2e --- /dev/null +++ b/src/inputtest/loader.c @@ -0,0 +1,120 @@ +/*============================================================================ + Aznable OS - System loader + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2022-01-07 + + 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 3 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, see . +===========================================================================*/ +#include "../shared/sys.h" +#include "../shared/ui.h" +#include "../shared/sound.h" +#include "../shared/sprite.h" +#include "../shared/starfield.h" +#include "sound_samples.h" + +const char *system_title = "AZNABLE"; + +// Loader (aesthetic pointlessness) +void intro_text(const char *text, unsigned char start_x, unsigned char start_y, unsigned char space_x, unsigned char speed, unsigned char flash_speed) +{ + unsigned char text_timer = 0; + unsigned char text_length = 1; + unsigned char text_flash = 0; + unsigned char text_flash_timer = 0; + unsigned char text_char_count = strlen(text); + + // Speed things up in debug mode + if (CHECK_BIT(input0, 0)) + { + speed = 1; + flash_speed = 1; + } + + while (1) + { + vblank = CHECK_BIT(input0, INPUT_VBLANK); + + // Aznable title intro + if (VBLANK_RISING) + { + unsigned char xpos = start_x + ((text_length - 1) * space_x); + text_timer++; + if (text_timer == speed) + { + write_char(text[text_length - 1], 0xFF, xpos, start_y); + text_length++; + if (text_length > text_char_count) + { + break; + } + text_timer = 0; + text_flash_timer = 0; + } + else + { + text_flash_timer++; + if (text_flash_timer == flash_speed) + { + text_flash++; + if (text_flash == 2) + { + text_flash = 0; + } + if (text_flash == 1) + { + write_char(0, 0, xpos, start_y); + } + else + { + write_char(text[text_length - 1], 0xFF, xpos, start_y); + } + text_flash_timer = 0; + } + } + } + vblank_last = vblank; + } +} +void loader(const char *title) +{ + + // Set charmap area + chram_size = chram_cols * chram_rows; + // Clear charmap + clear_bgcolor(0); + clear_chars(0); + // Reset sprites + clear_sprites(); + update_sprites(); + // Reset starfields + disable_starfield(); + + // OS Intro + write_char('>', 0xFF, 0, 1); + intro_text(system_title, 2, 1, 2, 8, 1); + write_char(' ', 0xFF, 0, 1); + + write_char('>', 0xFF, 0, 3); + intro_text("LOAD ", 2, 3, 1, 2, 1); + intro_text(title, 7, 3, 1, 2, 1); + write_char(' ', 0xFF, 0, 3); + + write_char('>', 0xFF, 0, 5); + intro_text("...", 2, 5, 1, 8, 1); + + // Clear characters + clear_char_area(0, 1, 1, 40, 3); +} \ No newline at end of file diff --git a/src/inputtest/loader.h b/src/inputtest/loader.h new file mode 100644 index 0000000..57fe5e5 --- /dev/null +++ b/src/inputtest/loader.h @@ -0,0 +1,27 @@ +/*============================================================================ + Aznable OS - System loader + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2022-01-07 + + 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 3 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, see . +===========================================================================*/ +#ifndef LOADER_H +#define LOADER_H + +// System intro text +extern void loader(const char *title); + +#endif \ No newline at end of file diff --git a/src/menu.c b/src/inputtest/menu.c similarity index 71% rename from src/menu.c rename to src/inputtest/menu.c index efb5510..878baad 100644 --- a/src/menu.c +++ b/src/inputtest/menu.c @@ -1,5 +1,5 @@ /*============================================================================ - Aznable OS - Popup menu functions + Aznable OS - Popup menu functions Author: Jim Gregory - https://github.com/JimmyStones/ Version: 1.0 @@ -18,42 +18,23 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . ===========================================================================*/ -#pragma once - -// Menu constants -#define menu_tx 12 -#define menu_bx 28 -#define menu_my 15 -#define menu_openholdtime 60 -#define menu_count 4 - -#define menu_panel_outline_high 0xFF -#define menu_panel_outline_mid 0b00110110 -#define menu_panel_outline_low 0b00100100 -#define menu_panel_back 0x00 - -#define menu_outline_high 0b10111111 -#define menu_outline_mid 0b10110110 -#define menu_outline_low 0b01100100 -#define menu_text 0b10110110 -#define menu_back 0x00 - -#define menu_sel_outline_high 0b01011111 -#define menu_sel_outline_mid 0b00010110 -#define menu_sel_outline_low 0b00010100 -#define menu_sel_text 0xFF -#define menu_sel_back 0b00001001 +#include "../shared/sys.h" +#include "../shared/ui.h" +#include "../shared/ps2.h" +#include "menu.h" +#include "inputtester_sys.h" // Menu variables -char menu_timer = 0; -char menu_index; -bool menu_dirty = 0; -bool menu_ready = 0; +unsigned char menu_timer = 0; +unsigned char menu_index; +unsigned char menu_dirty = 0; +unsigned char menu_ready = 0; char *menu_string[] = { "Digital", "Analog", "Advanced", - "Button test"}; + "Button test", + "Credits"}; // Initialise menu state void start_menu() @@ -66,9 +47,9 @@ void start_menu() // Menu state void menu() { - // // Handle PS/2 inputs whenever possible to improve latency - handle_ps2(); - + // // Handle PS/2 inputs whenever possible to improve latency + handle_ps2(); + // Check inputs at end of each scanline. Is this too much?! if (HBLANK_RISING) { @@ -93,6 +74,8 @@ void menu() } if ((!input_start && input_start_last) || (!input_a && input_a_last) || (!input_b && input_b_last)) { + // Clear menu flag to avoid double trigger + system_menu = 0; switch (menu_index) { case 0: @@ -107,6 +90,9 @@ void menu() case 3: state = STATE_START_BTNTEST; break; + case 4: + state = STATE_START_CREDITS; + break; } } } @@ -114,7 +100,7 @@ void menu() // As soon as vsync is detected start drawing screen updates if (VBLANK_RISING) { - char maxsize = (menu_count * 3) + 1; + char maxsize = (menu_count * 3) + 1 + (menu_count % 2); if (menu_timer < maxsize) { @@ -125,7 +111,7 @@ void menu() if (oy1 > 1) { fill(menu_tx + 1, my - (oy1 - 1), menu_bx - 1, my + (oy2 - 1), 0, 0); - fill_bgcolor(menu_tx + 1, my - (oy1 - 1), menu_bx - 1, my + (oy2 - 1), menu_panel_back); + fill_bgcol(menu_tx + 1, my - (oy1 - 1), menu_bx - 1, my + (oy2 - 1), menu_panel_back); } menu_timer++; if (menu_timer == maxsize) @@ -137,20 +123,20 @@ void menu() { if (menu_dirty) { - char ty = menu_my - ((menu_count * 3) / 2) + 1; + char ty = menu_my - ((menu_count * 3) / 2); for (char m = 0; m < menu_count; m++) { if (menu_index == m) { panel_shaded(menu_tx + 1, ty, menu_bx - 1, ty + 2, menu_sel_outline_high, menu_sel_outline_mid, menu_sel_outline_low); write_string(menu_string[m], menu_sel_text, menu_tx + 2, ty + 1); - //fill_bgcolor(menu_tx + 1, ty, menu_bx - 1, ty + 2, menu_sel_back); + // fill_bgcol(menu_tx + 1, ty, menu_bx - 1, ty + 2, menu_sel_back); } else { panel_shaded(menu_tx + 1, ty, menu_bx - 1, ty + 2, menu_outline_high, menu_outline_mid, menu_outline_low); write_string(menu_string[m], menu_text, menu_tx + 2, ty + 1); - //fill_bgcolor(menu_tx + 1, ty, menu_bx - 1, ty + 2, menu_back); + // fill_bgcol(menu_tx + 1, ty, menu_bx - 1, ty + 2, menu_back); } ty += 3; } diff --git a/src/inputtest/menu.h b/src/inputtest/menu.h new file mode 100644 index 0000000..4d47548 --- /dev/null +++ b/src/inputtest/menu.h @@ -0,0 +1,62 @@ +/*============================================================================ + Aznable OS - Popup menu functions + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-07-13 + + 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 3 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, see . +===========================================================================*/ + +#ifndef MENU_H +#define MENU_H + +// Menu constants +#define menu_tx 12 +#define menu_bx 28 +#define menu_my 15 +#define menu_openholdtime 60 +#define menu_count 5 + +#define menu_panel_outline_high 0xFF +#define menu_panel_outline_mid 0b00110110 +#define menu_panel_outline_low 0b00100100 +#define menu_panel_back 0x00 + +#define menu_outline_high 0b10111111 +#define menu_outline_mid 0b10110110 +#define menu_outline_low 0b01100100 +#define menu_text 0b10110110 +#define menu_back 0x00 + +#define menu_sel_outline_high 0b01011111 +#define menu_sel_outline_mid 0b00010110 +#define menu_sel_outline_low 0b00010100 +#define menu_sel_text 0xFF +#define menu_sel_back 0b00001001 + +// Menu variables +extern unsigned char menu_timer; +extern unsigned char menu_index; +extern unsigned char menu_dirty; +extern unsigned char menu_ready; +extern char *menu_string[]; + +// Initialise menu state +extern void start_menu(); + +// Menu state +extern void menu(); + +#endif \ No newline at end of file diff --git a/src/inputtest/music_tracks.c b/src/inputtest/music_tracks.c new file mode 100644 index 0000000..da0c519 --- /dev/null +++ b/src/inputtest/music_tracks.c @@ -0,0 +1,5 @@ +#ifndef MUSIC_TRACKS_C +#define MUSIC_TRACKS_C +#include "music_tracks.h" +unsigned long music_track_address[] = {0u,32864u}; +#endif diff --git a/src/inputtest/music_tracks.h b/src/inputtest/music_tracks.h new file mode 100644 index 0000000..47a6efb --- /dev/null +++ b/src/inputtest/music_tracks.h @@ -0,0 +1,7 @@ +#ifndef MUSIC_TRACKS_H +#define MUSIC_TRACKS_H +#define const_music_track_max 32 +extern unsigned long music_track_address[const_music_track_max]; +#define const_music_maintheme 0 +#define const_music_gameover 1 +#endif diff --git a/src/os.c b/src/inputtest/os.c similarity index 68% rename from src/os.c rename to src/inputtest/os.c index 012fcb0..b91aeb3 100644 --- a/src/os.c +++ b/src/inputtest/os.c @@ -1,9 +1,9 @@ /*============================================================================ - MiSTer test harness OS - Main application + Aznable OS - Input Tester main application Author: Jim Gregory - https://github.com/JimmyStones/ - Version: 1.0 - Date: 2021-07-12 + Version: 1.1 + Date: 2022-01-07 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 @@ -18,23 +18,24 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . ===========================================================================*/ - -#include -#include -#include - -#include "sys.c" -#include "sys_custom.c" -#include "ps2.c" -#include "ui.c" -#include "ui_custom.c" -#include "menu.c" -#include "inputtester.c" -#include "snek.c" -#include "fader.c" +#include "../shared/sys.h" +#include "../shared/ui.h" +#include "../shared/sprite.h" +#include "../shared/sound.h" +#include "../shared/tilemap.h" +#include "loader.h" +#include "sprite_images.h" +#include "sound_samples.h" +#include "inputtester_app.h" +#include "inputtester_sys.h" +#include "menu.h" +#include "zorblaxx_app.h" +#include "snek_app.h" +#include "fader.h" +#include "credits.h" // Main entry and state machine -void main() +void app_main() { chram_size = chram_cols * chram_rows; while (1) @@ -42,7 +43,7 @@ void main() hsync = input0 & 0x80; vsync = input0 & 0x40; hblank = input0 & 0x20; - vblank = input0 & 0x10; + vblank = CHECK_BIT(input0, INPUT_VBLANK); switch (state) { case STATE_START_INPUTTESTER: @@ -88,25 +89,38 @@ void main() break; case STATE_START_ATTRACT: - start_attract(); + state = 0; + loader("SNEK.AZN"); + start_snek_attract(); break; case STATE_ATTRACT: snek_attract(); break; + case STATE_START_CREDITS: + app_credits(); + break; case STATE_START_GAME_SNEK: - start_gameplay(); + start_snek_gameplay(); break; case STATE_GAME_SNEK: snek_gameplay(); break; + case STATE_START_ZORBLAXX: + state = 0; + loader("ZORBLAXX.AZN"); + app_zorblaxx(); + break; default: // Start default state + //state = STATE_START_ZORBLAXX; + //state = STATE_START_CREDITS; + loader("INPUTTESTER.AZN"); start_inputtester_digital(); - //start_inputtester_advanced(); - //start_inputtester_analog(); - //start_btntest(); + // start_inputtester_advanced(); + // start_inputtester_analog(); + // start_btntest(); break; } @@ -116,3 +130,9 @@ void main() vblank_last = vblank; } } + +// Main entry +void main() +{ + app_main(); +} diff --git a/src/snek.c b/src/inputtest/snek_app.c similarity index 94% rename from src/snek.c rename to src/inputtest/snek_app.c index f4ad5bc..4821571 100644 --- a/src/snek.c +++ b/src/inputtest/snek_app.c @@ -19,15 +19,13 @@ with this program. If not, see . ===========================================================================*/ -#pragma once +#include "../shared/sys.h" +#include "../shared/ui.h" +#include "../shared/sprite.h" +#include "snek_app.h" +#include "inputtester_sys.h" +#include "fader.h" -#include "sys.c" -#include "fader.c" - -// SNEK constants -#define movefreqinit 14 -#define movefreqdecfreq 200 -#define playerchar 83 // SNEK variables unsigned char movefreqdectimer = 0; unsigned char movefreq = 0; @@ -44,7 +42,7 @@ unsigned int length = 0; unsigned char attractstate = 0; // Initialise attract state and draw static elements -void start_attract() +void start_snek_attract() { state = STATE_ATTRACT; attractstate = 0; @@ -56,7 +54,7 @@ void start_attract() } // Initialise attract state and draw static elements -void start_gameplay() +void start_snek_gameplay() { state = STATE_GAME_SNEK; length = 0; @@ -158,7 +156,7 @@ void snek_attract() { if (CHECK_BIT(joystick[1], 3)) // start to start { - start_gameplay(); + start_snek_gameplay(); return; } if (CHECK_BIT(joystick[1], 2)) // select to quit diff --git a/src/inputtest/snek_app.h b/src/inputtest/snek_app.h new file mode 100644 index 0000000..f606ffd --- /dev/null +++ b/src/inputtest/snek_app.h @@ -0,0 +1,56 @@ +/*============================================================================ + Input Test - Snek mini-game + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-07-12 + + 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 3 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, see . +===========================================================================*/ + +#ifndef SNEK_H +#define SNEK_H + +// SNEK constants +#define movefreqinit 14 +#define movefreqdecfreq 200 +#define playerchar 83 +// SNEK variables +extern unsigned char movefreqdectimer; +extern unsigned char movefreq; +extern unsigned char movetimer; +extern signed int x; +extern signed int y; +extern signed char xd; +extern signed char yd; +extern signed char nxd; +extern signed char nyd; +extern unsigned int length; + +// Attract mode variables +extern unsigned char attractstate; + +// Initialise attract state and draw static elements +extern void start_snek_attract(); + +// Initialise attract state and draw static elements +extern void start_snek_gameplay(); + +// SNEK - gameplay state +extern void snek_gameplay(); + +// SNEK - attract state +extern void snek_attract(); + +#endif \ No newline at end of file diff --git a/src/inputtest/sound_samples.c b/src/inputtest/sound_samples.c new file mode 100644 index 0000000..974ec27 --- /dev/null +++ b/src/inputtest/sound_samples.c @@ -0,0 +1,6 @@ +#ifndef SOUND_SAMPLES_C +#define SOUND_SAMPLES_C +#include "sound_samples.h" +unsigned long sound_sample_address[] = {0u,4888u,5075u,5983u}; +unsigned long sound_sample_length[] = {4888u,187u,908u,5558u}; +#endif diff --git a/src/inputtest/sound_samples.h b/src/inputtest/sound_samples.h new file mode 100644 index 0000000..4d327b8 --- /dev/null +++ b/src/inputtest/sound_samples.h @@ -0,0 +1,10 @@ +#ifndef SOUND_SAMPLES_H +#define SOUND_SAMPLES_H +#define const_sound_sample_max 32 +extern unsigned long sound_sample_address[const_sound_sample_max]; +extern unsigned long sound_sample_length[const_sound_sample_max]; +#define const_sound_player_explode 0 +#define const_sound_pickup_collect 1 +#define const_sound_alarm 2 +#define const_sound_newtype 3 +#endif diff --git a/src/inputtest/sprite_images.h b/src/inputtest/sprite_images.h new file mode 100644 index 0000000..8fd73c2 --- /dev/null +++ b/src/inputtest/sprite_images.h @@ -0,0 +1,59 @@ +#ifndef SPRITE_IMAGES_H +#define SPRITE_IMAGES_H +#define sprite_index_title_first 0 +#define sprite_index_title_count 4 +#define sprite_index_title_last 3 +#define sprite_palette_title 2 +#define sprite_size_title 0 +#define sprite_pixelsize_title 32 +#define sprite_halfpixelsize_title 16 +#define sprite_index_asteroids_first 0 +#define sprite_index_asteroids_count 8 +#define sprite_index_asteroids_last 7 +#define sprite_palette_asteroids 0 +#define sprite_size_asteroids 1 +#define sprite_pixelsize_asteroids 16 +#define sprite_halfpixelsize_asteroids 8 +#define sprite_index_explosions_first 8 +#define sprite_index_explosions_count 8 +#define sprite_index_explosions_last 15 +#define sprite_palette_explosions 1 +#define sprite_size_explosions 1 +#define sprite_pixelsize_explosions 16 +#define sprite_halfpixelsize_explosions 8 +#define sprite_index_pickups_first 16 +#define sprite_index_pickups_count 8 +#define sprite_index_pickups_last 23 +#define sprite_palette_pickups 1 +#define sprite_size_pickups 1 +#define sprite_pixelsize_pickups 16 +#define sprite_halfpixelsize_pickups 8 +#define sprite_index_pings_first 24 +#define sprite_index_pings_count 8 +#define sprite_index_pings_last 31 +#define sprite_palette_pings 2 +#define sprite_size_pings 1 +#define sprite_pixelsize_pings 16 +#define sprite_halfpixelsize_pings 8 +#define sprite_index_player_first 32 +#define sprite_index_player_count 4 +#define sprite_index_player_last 35 +#define sprite_palette_player 1 +#define sprite_size_player 1 +#define sprite_pixelsize_player 16 +#define sprite_halfpixelsize_player 8 +#define sprite_index_pointer_first 36 +#define sprite_index_pointer_count 1 +#define sprite_index_pointer_last 36 +#define sprite_palette_pointer 2 +#define sprite_size_pointer 1 +#define sprite_pixelsize_pointer 16 +#define sprite_halfpixelsize_pointer 8 +#define sprite_index_trails_first 0 +#define sprite_index_trails_count 4 +#define sprite_index_trails_last 3 +#define sprite_palette_trails 1 +#define sprite_size_trails 2 +#define sprite_pixelsize_trails 8 +#define sprite_halfpixelsize_trails 4 +#endif diff --git a/src/inputtest/zorblaxx_app.c b/src/inputtest/zorblaxx_app.c new file mode 100644 index 0000000..234e30d --- /dev/null +++ b/src/inputtest/zorblaxx_app.c @@ -0,0 +1,667 @@ +/*============================================================================ + Aznable OS - Zorblaxx demo application + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-27 + + 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 3 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, see . +===========================================================================*/ + +/* + Sprite indexes: + 0-9 - Trails + 10 - Pickup + 11 - Player + 12-27 - Asteroids + 28-31 - Explosions +*/ + +#include "../shared/sys.h" +#include "../shared/sprite.h" +#include "../shared/tilemap.h" +#include "../shared/ui.h" +#include "../shared/music.h" +#include "../shared/sound.h" +#include "../shared/starfield.h" +#include "sprite_images.h" +#include "sound_samples.h" +#include "music_tracks.h" +#include "zorblaxx_app.h" +#include "zorblaxx_player.h" +#include "zorblaxx_trails.h" +#include "zorblaxx_explosions.h" +#include "zorblaxx_pickups.h" +#include "zorblaxx_asteroids.h" + +// Area and units +const unsigned char x_divisor = 16; +const unsigned char y_divisor = 16; +unsigned short x_min = 2; +unsigned short x_max = 336; +unsigned short x_h_min; +unsigned short x_h_max; +unsigned char scroll_speed; + +// Game defaults +unsigned short player_spawn_x = ((320 / 2) - 8) + 32; +unsigned short player_spawn_y = 200; + +// Game states +typedef enum +{ + game_start, + enter_field, + in_field, + field_ending, + field_complete, + in_warp, + approaching_field, + game_over, + game_over_waitforstats, + game_over_stats, + game_over_waitforscoreentry + +} game_state_enum; + +game_state_enum game_state = 0; +unsigned short game_state_timer = 0; + +// Level progression +unsigned char level_number = 0; +unsigned char level_time = 0; +unsigned char level_time_timer = 0; +unsigned char level_playercontrol = 0; +unsigned short level_progress = 0; +unsigned char level_progress_timer = 0; +unsigned short level_progress_max; +unsigned short level_progress_base = 20000; +const unsigned short level_progress_per_level = 3000; +unsigned short game_state_warp_timeout_first = 120; +unsigned short game_state_warp_timeout = 240; +unsigned short game_state_danger_timeout = 120; +unsigned short game_state_gameover_timeout = 180; +const unsigned char asteroids_difficulty_base = 3; +const unsigned char asteroids_difficulty_multiplier = 2; +unsigned char player_lives_default = 3; + +unsigned char pickup_spawn_timer = 0; +unsigned char pickup_spawn_timer_min = 120; + +unsigned long high_score = 5000; +unsigned char bonus_score_multiplier = 10; +unsigned long player_score = 0; +unsigned long player_score_last; +unsigned long time_bonuses_collected; +unsigned long pickup_bonuses_collected; +unsigned char high_score_passed = 0; +unsigned char player_score_timer = 0; +unsigned char player_score_timer_frequency = 100; + +unsigned char button_a; +unsigned char button_a_last; +unsigned char pleaseStop; // Set to 1 to fall back to OS + +void setup_variables() +{ + pleaseStop = 0; + x_h_min = (unsigned short)(x_min * x_divisor); + x_h_max = (unsigned short)(x_max * x_divisor); + + unsigned char debug = CHECK_BIT(input0, 0); + if (debug) + { + game_state_warp_timeout_first /= 10; + game_state_warp_timeout /= 10; + game_state_danger_timeout /= 10; + game_state_gameover_timeout /= 10; + player_lives_default = 1; + level_progress_base = 2000; + } +} + +const char *scroller_text = "CODE AND GFX BY JIMMYSTONES ... MUSIC BY DARRIN CARDANI ... "; +unsigned char scroller_pos = 0; +unsigned short scroller_entry_pos = (14 * 32) + 21; + +void update_scroller() +{ + tilemap_offset_x += 2; + if (tilemap_offset_x >= 16) + { + tilemap_offset_x -= 16; + + scroll_tilemap_left(); + + tilemapram[scroller_entry_pos] = scroller_text[scroller_pos] - 45; + scroller_pos++; + if (scroller_pos == strlen(scroller_text)) + { + scroller_pos = 0; + } + } +} + +void intro_loop() +{ + + clear_bgcolor(0); + + // Start intro music loop + play_music_if(const_music_maintheme, 1); + + // Setup starfield layer speeds + enable_starfield(); + set_starfield_speed_x(0); + set_starfield_speed_y(-0.5f); + + // Setup title sprites + unsigned char title_sprite = 16; + unsigned short title_x = ((320 / 2) + 32) - 64; + signed short title_y = -32 * y_divisor; + signed short title_target_y = 100 * y_divisor; + unsigned char si = 0; + for (unsigned char y = 0; y < 1; y++) + { + for (unsigned char x = 0; x < 4; x++) + { + enable_sprite(title_sprite, sprite_palette_title, sprite_size_title, 0); + spr_index[title_sprite] = sprite_index_title_first + si; + set_sprite_position(title_sprite, title_x + (x * 32), -32); + si++; + title_sprite++; + } + } + + unsigned char show_instruction = 0; + unsigned char title_ready = 0; + + while (1) + { + vblank = CHECK_BIT(input0, INPUT_VBLANK); + + if (VBLANK_RISING) + { + + button_a_last = button_a; + button_a = CHECK_BIT(joystick[0], 4); + // If button pressed, leave intro and start game + if (button_a && !button_a_last) + { + return; + } + update_scroller(); + update_tilemap_offset(); + update_sprites(); + + // Press select to quit + if (CHECK_BIT(joystick[1], 2)) + { + pleaseStop = 1; + return; + } + } + + if (VBLANK_FALLING) + { + // Move title into position + if (title_y < title_target_y) + { + signed short diff = (title_target_y - title_y) / 6; + if (diff > 64) + { + diff = 64; + } + else if (diff == 0) + { + diff = 2; + } + title_y += diff; + title_sprite = 16; + for (unsigned char y = 0; y < 2; y++) + { + unsigned short sy = (title_y / y_divisor) + (y * 16); + for (unsigned char x = 0; x < 8; x++) + { + spr_y_h[title_sprite] = sy >> 8; + spr_y_l[title_sprite] = (unsigned char)sy; + title_sprite++; + } + } + } + else + { + title_ready = 1; + } + + // Move player into position + move_player_to_target(); + + if (show_instruction == 0 && player_ready == 1 && title_ready == 1) + { + write_string("Press A to start", 0xFF, 12, 17); + show_instruction = 1; + } + + // Trail + player_trail_timer--; + if (player_trail_timer <= 0) + { + player_trail_timer = player_trail_frequency - ((player_speed * 10) / 50); + if (player_trail_timer <= 0) + { + player_trail_timer = 1; + } + add_player_trail(); + } + handle_trails(); + } + vblank_last = vblank; + } +} + +// Starfield variables +unsigned char scroll_speed_last = 0; +unsigned char sf_speed1 = 4; + +void game_loop() +{ + + game_state = game_start; + + while (1) + { + vblank = CHECK_BIT(input0, INPUT_VBLANK); + + if (VBLANK_RISING) + { + + // Detect player collision + if (spritecollisionram[player_sprite]) + { + if (spritecollisionram[pickup_sprite_first]) + { + // Player collects pickup + if (pickup_state[0] == 1) + { + enable_sprite(pickup_sprite_first, sprite_palette_pickups, sprite_size_pickups, 0); + player_score += pickup_value[0]; + pickup_bonuses_collected += pickup_value[0]; + pickup_state[0] = 2; + pickup_timer[0] = 40; + spr_index[pickup_sprite_first] += pickup_type_count; + play_sound(const_sound_pickup_collect); + } + } + else + { + for (unsigned char a = 0; a < asteroids_max; a++) + { + if (spritecollisionram[asteroids_sprite_first + a]) + { + player_hit = true; + break; + } + } + } + } + for (unsigned char sprite = 0; sprite < sprite_max; sprite++) + { + spritecollisionram[sprite] = 0; + } + + // Update sprite registers + update_sprites(); + + // Update starfield + scroll_speed = player_speed; + if (scroll_speed != scroll_speed_last) + { + scroll_speed_last = scroll_speed; + set_starfield_speed_y(scroll_speed * -0.02f); + } + + // Track player button press + button_a_last = button_a; + button_a = CHECK_BIT(joystick[0], 4); + + // Press Select to quit + if (CHECK_BIT(joystick[1], 2)) + { + pleaseStop = 1; + return; + } + } + + if (VBLANK_FALLING) + { + if (player_lives > 0) + { + handle_player(level_playercontrol); + } + handle_trails(); + handle_explosions(); + handle_asteroids(game_state == in_field); + handle_pickups(); + + if (game_state == in_field || game_state == field_ending) + { + level_time_timer++; + if (level_time_timer >= 60) + { + level_time++; + level_time_timer = 0; + } + if (player_lives_changed) + { + write_stringf("%2d", 0xFF, 38, 1, player_lives); + player_lives_changed = false; + if (player_lives == 0) + { + game_state = game_over; + } + } + } + + // Game state machine + switch (game_state) + { + case game_start: + + // Reset progress + level_number = 0; + level_progress = 0; + level_playercontrol = 0; + + // Reset player + setup_player(player_spawn_x, 260, player_lives_default); + player_speed = player_speed_warp; // Preset player to warp speed! + + // Reset scores and stats + player_score = 0; + player_score_last = 999; + player_score_timer = 0; + high_score_passed = 0; + asteroids_evaded = 0; + + // Setup asteroids + setup_asteroids(); + + // Setup explosions + setup_explosions(); + + // Setup pickups + setup_pickups(); + pickup_spawn_timer = pickup_spawn_timer_min; + + // Draw score titles + write_string("1UP", 0b00111111, 2, 0); + write_string("HIGH SCORE", 0b00111111, 15, 0); + write_string("SHIPS", 0b00111111, 35, 0); + write_stringf("%2d", 0xFF, 38, 1, player_lives); + + // Draw instructions for first warp + write_string("Avoid the asteroids!", 0b00111111, 10, 11); + write_string("Use A to boost for time bonus", 0b00111000, 5, 14); + write_string("Collect gems for extra points", 0b00011111, 5, 17); + + game_state = in_warp; + game_state_timer = game_state_warp_timeout_first; + + break; + case enter_field: // Player is entering a new field + game_state = in_field; + level_progress = 0; + level_progress_timer = 0; + level_number++; + level_time = 0; + level_time_timer = 0; + level_playercontrol = 1; + unsigned short per_level = level_number < 13 ? (level_number * level_progress_per_level) : 13 * level_progress_per_level; + level_progress_max = level_progress_base + per_level; + + // Start main music loop + play_music_if(const_music_maintheme, 1); + + // Update asteroid difficulty + asteroids_difficulty = asteroids_difficulty_base + (level_number * asteroids_difficulty_multiplier); + asteroids_difficulty_speedspread = 2 + (asteroids_difficulty / 4); + + asteroids_active_max = 5 + asteroids_difficulty; + if (asteroids_active_max > asteroids_max) + { + asteroids_active_max = asteroids_max; + } + + // Write 0% progress indicator + write_stringf("%3d%%", 0xFF, 18, 29, 0); + + break; + case in_field: + // Level progress + level_progress += player_speed; + level_progress_timer++; + if (level_progress_timer > 10) + { + unsigned char progress = level_progress / (level_progress_max / 100); + write_stringf("%3d%%", 0xFF, 18, 29, progress); + level_progress_timer = 0; + } + if (level_progress >= level_progress_max) + { + write_string("100%", 0xFF, 18, 29); + game_state = field_ending; + } + + // Generate pickups + pickup_spawn_timer--; + if (pickup_spawn_timer == 0) + { + pickup_spawn_timer = pickup_spawn_timer_min; + spawn_pickup(); + } + + // Player score + player_score_timer += player_speed; + if (player_score_timer >= player_score_timer_frequency) + { + player_score_timer -= player_score_timer_frequency; + player_score++; + } + break; + case field_ending: + // Level ended - wait for all asteroids to clear + + // Keep scoring until asteroids are clear + player_score_timer += player_speed; + if (player_score_timer >= player_score_timer_frequency) + { + player_score_timer -= player_score_timer_frequency; + player_score++; + } + if (asteroids_active == 0) + { + game_state = field_complete; + game_state_timer = 0; + game_state_timer = game_state_warp_timeout; + + // Start score music loop + + level_playercontrol = 0; + set_player_target(player_spawn_x * x_divisor, player_spawn_y * y_divisor, 6, 24); + + write_stringf_ushort("-- FIELD %d COMPLETED --", 0xFF, 9, 11, level_number); + + unsigned char par_speed = ((player_speed_max - player_speed_min) / 2); + unsigned short par_time = level_progress_max / 60 / par_speed; + signed short bonus = (par_time - level_time) * bonus_score_multiplier; + time_bonuses_collected += bonus; + if (bonus < 0) + { + if ((-bonus) > player_score) + { + bonus = -player_score; + } + } + player_score += bonus; + + write_stringf_ushort("Time: %6d", 0xFF, 14, 13, level_time); + write_stringf_ushort("Par: %6d", 0xFF, 15, 14, par_time); + if (bonus > 0) + { + write_stringf_short("Bonus: %6d", 0b00011000, 13, 16, bonus); + } + else + { + write_string("No bonus :(", 0b01011011, 14, 16); + } + write_stringf_ulong("Score: %6d", 0xFF, 13, 18, player_score); + clear_char_area(0, 10, 29, 30, 29); + } + break; + case field_complete: // Display field completed screen while bringing ship up to speed + move_player_to_target(); + if (player_speed < player_speed_warp) + { + player_speed++; + } + else + { + game_state = in_warp; + } + break; + case in_warp: // Do a bit of warp speed + move_player_to_target(); + game_state_timer--; + if (game_state_timer == 0) + { + clear_char_area(0, 0, 2, 39, 20); + write_string("- Entering asteroid field -", 0xFF, 07, 16); + game_state = approaching_field; + game_state_timer = game_state_danger_timeout; + level_time = 0; + } + break; + case approaching_field: // Slow down again ready for start + move_player_to_target(); + if (player_speed > player_speed_min) + { + player_speed--; + } + + level_time_timer++; + if (level_time_timer >= 15) + { + play_sound(const_sound_alarm); + write_string("DANGER!", level_time ? 0b00000111 : 0b00111111, 16, 14); + level_time = !level_time; + level_time_timer = 0; + } + + game_state_timer--; + if (game_state_timer == 0) + { + clear_char_area(0, 0, 14, 39, 16); + game_state = enter_field; + setup_asteroids(); + } + break; + case game_over: + write_string("GAME OVER", 0b00000011, 16, 14); + stop_music(); + game_state_timer = game_state_gameover_timeout; + game_state = game_over_waitforstats; + break; + case game_over_waitforstats: + game_state_timer--; + if (game_state_timer == 0) + { + play_music(const_music_gameover, 1); + clear_char_area(0, 0, 14, 39, 14); + + // Write stats + write_stringf_ulong("Final Score: %6d", 0xFF, 10, 11, player_score); + + write_stringf_ulong("Asteroids evaded: %6d", 0b00111111, 5, 14, asteroids_evaded); + write_stringf_ulong("Time bonuses: %6d", 0b00111000, 9, 16, time_bonuses_collected); + write_stringf_ulong("Pickup bonuses: %6d", 0b00011111, 7, 18, pickup_bonuses_collected); + + write_string("Press A to continue", 0xFF, 10, 21); + + game_state = game_over_waitforscoreentry; + } + break; + case game_over_waitforscoreentry: + if (button_a && !button_a_last) + { + return; + } + break; + } + + // Only update scores if they have changed + if (player_score != player_score_last) + { + // Update high score + if (player_score > high_score) + { + high_score = player_score; + } + + // Draw player score + write_stringf_ulong("%d", 0xFF, 0, 1, player_score); + + // Draw highscore + write_stringf_ulong("%6d", 0xFF, 16, 1, high_score); + + player_score_last = player_score; + } + } + + vblank_last = vblank; + } +} + +void app_zorblaxx() +{ + setup_variables(); + stop_music(); + + while (1) + { + clear_chars(0); + clear_sprites(); + if (pleaseStop) + { + return; + } + + setup_player(player_spawn_x, 256, player_lives_default); + set_player_target(player_spawn_x * x_divisor, player_spawn_y * y_divisor, 6, 24); + setup_trails(); + + intro_loop(); + + // Clear character map and title sprites + clear_tilemap(); + clear_chars(0); + clear_sprites(); + if (pleaseStop) + { + return; + } + + game_loop(); + } +} \ No newline at end of file diff --git a/src/inputtest/zorblaxx_app.h b/src/inputtest/zorblaxx_app.h new file mode 100644 index 0000000..969e501 --- /dev/null +++ b/src/inputtest/zorblaxx_app.h @@ -0,0 +1,50 @@ +/*============================================================================ + Aznable OS - Zorblaxx demo application + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-27 + + 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 3 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, see . +===========================================================================*/ + +#ifndef ZORBLAXX_APP_H +#define ZORBLAXX_APP_H + +// Area and units +extern const unsigned char x_divisor; +extern const unsigned char y_divisor; +extern unsigned short x_min; +extern unsigned short x_max; +extern unsigned short x_h_min; +extern unsigned short x_h_max; +extern unsigned char scroll_speed; + +// Game defaults +extern unsigned short player_spawn_x; +extern unsigned short player_spawn_y; + +// Sprite indexes +#define trail_sprite_first 0 +#define pickup_sprite_first 10 +#define player_sprite 11 +#define asteroids_sprite_first 12 +#define explosion_sprite_first 29 + +// Method headers +extern void intro_loop(); +extern void game_loop(); +extern void app_zorblaxx(); + +#endif \ No newline at end of file diff --git a/src/inputtest/zorblaxx_asteroids.c b/src/inputtest/zorblaxx_asteroids.c new file mode 100644 index 0000000..de6f605 --- /dev/null +++ b/src/inputtest/zorblaxx_asteroids.c @@ -0,0 +1,123 @@ + +/*============================================================================ + Aznable OS - Zorblaxx demo application - Asteroid routines + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-27 + + 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 3 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, see . +===========================================================================*/ + +#include "../shared/sys.h" +#include "../shared/sprite.h" +#include "sprite_images.h" +#include "zorblaxx_app.h" +#include "zorblaxx_asteroids.h" + +#define const_asteroids_max 16 +unsigned char asteroids_max = const_asteroids_max; +unsigned short asteroids_x[const_asteroids_max]; +unsigned short asteroids_y[const_asteroids_max]; +signed char asteroids_xs[const_asteroids_max]; +signed char asteroids_ys[const_asteroids_max]; +unsigned char asteroids_timer[const_asteroids_max]; +unsigned short asteroids_y_max; +unsigned char asteroid_spawn_y = 0; +unsigned char asteroids_active; +unsigned char asteroids_active_max; +unsigned char asteroids_difficulty; +unsigned char asteroids_difficulty_speedspread; +unsigned short asteroids_evaded = 0; + +unsigned char get_asteroid_timer() +{ + unsigned char min_wait = asteroids_difficulty < 30 ? 30 - asteroids_difficulty : 0; + unsigned char max_wait = asteroids_difficulty < 120 ? 120 - asteroids_difficulty : 0; + unsigned char random = rand_uchar(min_wait, max_wait); + return random; +} + +void setup_asteroids() +{ + asteroids_y_max = 272 * y_divisor; + + for (unsigned char m = 0; m < asteroids_max; m++) + { + asteroids_x[m] = rand_ushort(32, 320) * x_divisor; + asteroids_y[m] = asteroid_spawn_y; + asteroids_xs[m] = rand_schar(-asteroids_difficulty_speedspread, asteroids_difficulty_speedspread); + asteroids_ys[m] = rand_uchar(4, 16 + asteroids_difficulty); + asteroids_timer[m] = get_asteroid_timer(); + + unsigned char sprite = asteroids_sprite_first + m; + spr_index[sprite] = sprite_index_asteroids_first + rand_uchar(0, sprite_index_asteroids_count - 1); + enable_sprite(sprite, sprite_palette_asteroids, sprite_size_asteroids, true); + spr_on[sprite] = false; + set_sprite_position(sprite, asteroids_x[m] / x_divisor, 0); + } +} + +void handle_asteroids(unsigned char spawn_enabled) +{ + asteroids_active = 0; + for (unsigned char m = 0; m < asteroids_max; m++) + { + unsigned char sprite = asteroids_sprite_first + m; + if (m < asteroids_active_max) + { + if (asteroids_timer[m] > 0) + { + if (spawn_enabled == 1) + { + asteroids_timer[m]--; + if (asteroids_timer[m] == 0) + { + spr_index[sprite] = rand_uchar(sprite_index_asteroids_first, sprite_index_asteroids_last); + spr_on[sprite] = 1; + } + } + } + else + { + asteroids_active++; + asteroids_x[m] += asteroids_xs[m]; + if (asteroids_x[m] < x_h_min) + { + asteroids_x[m] = x_h_max; + } + else if (asteroids_x[m] > x_h_max) + { + asteroids_x[m] = x_h_min; + } + if (asteroids_y[m] >= asteroids_y_max) + { + spr_on[sprite] = 0; + asteroids_x[m] = rand_ushort(32, 320) * x_divisor; + asteroids_y[m] = asteroid_spawn_y * y_divisor; + set_sprite_position(sprite, asteroids_x[m] / x_divisor, asteroid_spawn_y); + asteroids_xs[m] = rand_schar(-asteroids_difficulty_speedspread, asteroids_difficulty_speedspread); + asteroids_ys[m] = rand_uchar(4, 16 + asteroids_difficulty); + asteroids_timer[m] = get_asteroid_timer(); + asteroids_evaded++; + } + else + { + asteroids_y[m] += asteroids_ys[m] + scroll_speed; + set_sprite_position(sprite, asteroids_x[m] / x_divisor, asteroids_y[m] / y_divisor); + } + } + } + } +} \ No newline at end of file diff --git a/src/inputtest/zorblaxx_asteroids.h b/src/inputtest/zorblaxx_asteroids.h new file mode 100644 index 0000000..db2cddc --- /dev/null +++ b/src/inputtest/zorblaxx_asteroids.h @@ -0,0 +1,43 @@ + +/*============================================================================ + Aznable OS - Zorblaxx demo application - Asteroid routines + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-27 + + 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 3 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, see . +===========================================================================*/ + +#ifndef ZORBLAXX_ASTEROIDS_H +#define ZORBLAXX_ASTEROIDS_H + +extern unsigned char asteroids_max; +extern unsigned short asteroids_x[]; +extern unsigned short asteroids_y[]; +extern signed char asteroids_xs[]; +extern signed char asteroids_ys[]; +extern unsigned char asteroids_timer[]; +extern unsigned short asteroids_y_max; +extern unsigned char asteroids_active_max; +extern unsigned char asteroids_active; +extern unsigned char asteroids_difficulty; +extern unsigned char asteroids_difficulty_speedspread; +extern unsigned short asteroids_evaded; + +extern void setup_asteroids(); + +extern void handle_asteroids(unsigned char spawn_enabled); + +#endif \ No newline at end of file diff --git a/src/inputtest/zorblaxx_explosions.c b/src/inputtest/zorblaxx_explosions.c new file mode 100644 index 0000000..c6fd764 --- /dev/null +++ b/src/inputtest/zorblaxx_explosions.c @@ -0,0 +1,93 @@ +/*============================================================================ + Aznable OS - Zorblaxx demo application - Explosion routines + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-27 + + 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 3 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, see . +===========================================================================*/ + +#include "../shared/sys.h" +#include "../shared/sprite.h" +#include "sprite_images.h" +#include "zorblaxx_app.h" +#include "zorblaxx_player.h" +#include "zorblaxx_explosions.h" + +// Explosions +#define const_explosion_max 3 +unsigned char explosion_max = const_explosion_max; +unsigned char explosion_timer[const_explosion_max]; +unsigned char explosion_frame[const_explosion_max]; +unsigned char explosion_type[const_explosion_max]; +const unsigned char explosion_lifespan = 4; +#define explosion_frame_count 4 +#define explosion_type_count 2 + +void setup_explosions() +{ + for (int e = explosion_sprite_first; e < explosion_sprite_first + explosion_max; e++) + { + enable_sprite(e, sprite_palette_explosions, sprite_size_explosions, 0); + spr_on[e] = false; + } +} + +void add_explosion(unsigned type, unsigned char count) +{ + for (unsigned char e = 0; e < explosion_max; e++) + { + if (explosion_timer[e] == 0) + { + explosion_timer[e] = rand_uchar(2, 7); + explosion_frame[e] = 0; + explosion_type[e] = type; + unsigned char sprite = explosion_sprite_first + e; + spr_on[sprite] = 1; + spr_index[sprite] = sprite_index_explosions_first + (type * explosion_frame_count); + set_sprite_position(sprite, (player_x / x_divisor) + rand_schar(-4, 8), (player_y / y_divisor) + rand_schar(-4, 8)); + count--; + if (count == 0) + { + return; + } + } + } +} + +void handle_explosions() +{ + for (unsigned char t = 0; t < explosion_max; t++) + { + if (explosion_timer[t] > 0) + { + explosion_timer[t]--; + if (explosion_timer[t] == 0) + { + unsigned char sprite = explosion_sprite_first + t; + spr_index[sprite]++; + explosion_frame[t]++; + if (explosion_frame[t] == explosion_frame_count) + { + spr_on[sprite] = false; + } + else + { + explosion_timer[t] = explosion_lifespan; + } + } + } + } +} \ No newline at end of file diff --git a/src/inputtest/zorblaxx_explosions.h b/src/inputtest/zorblaxx_explosions.h new file mode 100644 index 0000000..86d5d7a --- /dev/null +++ b/src/inputtest/zorblaxx_explosions.h @@ -0,0 +1,38 @@ +/*============================================================================ + Aznable OS - Zorblaxx demo application - Explosion routines + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-27 + + 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 3 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, see . +===========================================================================*/ + +#ifndef ZORBLAXX_EXPLOSIONS_H +#define ZORBLAXX_EXPLOSIONS_H + +// Explosions +extern unsigned char explosion_max; +extern unsigned char explosion_timer[]; +extern unsigned char explosion_frame[]; +extern unsigned char explosion_type[]; +extern const unsigned char explosion_lifespan; + +extern void setup_explosions(); + +extern void add_explosion(unsigned type, unsigned char count); + +extern void handle_explosions(); + +#endif \ No newline at end of file diff --git a/src/inputtest/zorblaxx_pickups.c b/src/inputtest/zorblaxx_pickups.c new file mode 100644 index 0000000..286381b --- /dev/null +++ b/src/inputtest/zorblaxx_pickups.c @@ -0,0 +1,107 @@ +/*============================================================================ + Aznable OS - Zorblaxx demo application - Pickup routines + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-27 + + 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 3 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, see . +===========================================================================*/ + +#include "../shared/sys.h" +#include "../shared/sprite.h" +#include "sprite_images.h" +#include "zorblaxx_app.h" +#include "zorblaxx_pickups.h" +#include "zorblaxx_asteroids.h" +#include "zorblaxx_player.h" + +#define const_pickup_max 1 +#define const_type_count 4 +unsigned char pickup_max = const_pickup_max; +unsigned char pickup_type_count = const_type_count; +unsigned char pickup_spawn_y = 0; +unsigned char pickup_spawn_interval = 10; +unsigned short pickup_x[const_pickup_max]; +unsigned short pickup_y[const_pickup_max]; +signed char pickup_ys[const_pickup_max]; +unsigned char pickup_state[const_pickup_max]; +unsigned char pickup_value[const_pickup_max]; +unsigned char pickup_timer[const_pickup_max]; +unsigned short pickup_y_max; +unsigned char pickup_y_offset; + +void spawn_pickup() +{ + for (unsigned char t = 0; t < pickup_max; t++) + { + if (pickup_state[t] == 0) + { + unsigned char sprite = pickup_sprite_first + t; + unsigned char type = rand_uchar(0, const_type_count - 1); + + pickup_x[t] = rand_ushort(48, 272) * x_divisor; + pickup_y[t] = pickup_spawn_y * y_divisor; + pickup_ys[t] = rand_uchar(0, type * 12); + pickup_state[t] = 1; + pickup_value[t] = 50 * (type + 1); + enable_sprite(sprite, sprite_palette_pickups, sprite_size_pickups, 1); + spr_index[sprite] = sprite_index_pickups_first + type; + set_sprite_position(sprite, pickup_x[t] / x_divisor, pickup_spawn_y); + return; + } + } +} + +void setup_pickups() +{ + pickup_y_max = 272 * y_divisor; + pickup_y_offset = (8 * y_divisor); + for (int t = pickup_sprite_first; t < pickup_sprite_first + pickup_max; t++) + { + enable_sprite(t, sprite_palette_pickups, sprite_size_pickups, false); + spr_on[t] = false; + } +} + +void handle_pickups() +{ + for (unsigned char t = 0; t < pickup_max; t++) + { + if (pickup_state[t] > 0) + { + unsigned char sprite = pickup_sprite_first + t; + pickup_y[t] += (pickup_ys[t] + scroll_speed); + if ((pickup_y[t] > pickup_y_max) > 0) + { + spr_on[sprite] = false; + pickup_state[t] = 0; + continue; + } + + if (pickup_state[t] == 2) + { + pickup_timer[t]--; + if (pickup_timer[t] == 0) + { + spr_on[sprite] = false; + pickup_state[t] = 0; + pickup_timer[t] = pickup_spawn_interval; + continue; + } + } + set_sprite_position(sprite, pickup_x[t] / x_divisor, pickup_y[t] / y_divisor); + } + } +} \ No newline at end of file diff --git a/src/inputtest/zorblaxx_pickups.h b/src/inputtest/zorblaxx_pickups.h new file mode 100644 index 0000000..4a1f829 --- /dev/null +++ b/src/inputtest/zorblaxx_pickups.h @@ -0,0 +1,38 @@ +/*============================================================================ + Aznable OS - Zorblaxx demo application - Pickup routines + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-27 + + 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 3 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, see . +===========================================================================*/ + +#ifndef ZORBLAXX_PICKUPS_H +#define ZORBLAXX_PICKUPS_H + +// Pickups +extern unsigned char pickup_max; +extern unsigned char pickup_type_count; +extern unsigned char pickup_state[]; +extern unsigned char pickup_value[]; +extern unsigned char pickup_timer[]; + +extern void spawn_pickup(); + +extern void setup_pickups(); + +extern void handle_pickups(); + +#endif \ No newline at end of file diff --git a/src/inputtest/zorblaxx_player.c b/src/inputtest/zorblaxx_player.c new file mode 100644 index 0000000..33579c4 --- /dev/null +++ b/src/inputtest/zorblaxx_player.c @@ -0,0 +1,380 @@ +/*============================================================================ + Aznable OS - Zorblaxx demo application - Player routines + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-27 + + 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 3 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, see . +===========================================================================*/ + +#include "../shared/sys.h" +#include "../shared/sprite.h" +#include "../shared/sound.h" +#include "sprite_images.h" +#include "sound_samples.h" +#include "zorblaxx_app.h" +#include "zorblaxx_player.h" +#include "zorblaxx_trails.h" +#include "zorblaxx_asteroids.h" +#include "zorblaxx_explosions.h" + +// Player +const signed char player_max_speed = 20; +const unsigned char player_accel = 3; +const unsigned char player_trail_frequency = 10; +const unsigned char player_trail_speed = 3; +const unsigned char player_trail_lifespan = 5; +unsigned short player_x; +unsigned short player_y; +signed char player_xs = 0; +signed char player_ys = 0; +unsigned short player_x_min; +unsigned short player_x_max; +unsigned short player_y_min; +unsigned short player_y_max; +const unsigned char player_speed_min = 12; +const unsigned char player_speed_max = 32; +const unsigned char player_speed_warp = 64; +unsigned char player_speed; +signed char player_trail_timer = 1; + +unsigned char player_lives; +unsigned char player_lives_changed; +unsigned char player_invincible_timer = 0; +unsigned char player_invincible_flash = 0; +const unsigned char player_invincible_timeout = 120; +unsigned char player_respawn_timer = 0; +const unsigned char player_respawn_timeout = 120; +unsigned char player_hit = 0; + +unsigned char player_ready; +unsigned char player_ready_x; +unsigned char player_ready_y; +unsigned short player_x_target; +unsigned short player_y_target; +signed short player_x_diff; +signed short player_y_diff; +unsigned char player_target_divider = 6; +unsigned char player_target_maxspeed = 28; + +void set_player_target(unsigned short x, unsigned short y, unsigned char divider, unsigned char maxspeed) +{ + player_ready = 0; + player_ready_x = 0; + player_ready_y = 0; + player_x_target = x; + player_y_target = y; + player_target_divider = divider; + player_target_maxspeed = maxspeed; +} + +void move_player_to_target() +{ + if (player_y != player_y_target) + { + player_y_diff = (((signed short)player_y_target - (signed short)player_y)) / (signed char)player_target_divider; + if (player_y_diff == 0) + { + player_y = player_y_target; + } + else + { + if (player_y_diff > player_target_maxspeed) + { + player_y_diff = player_target_maxspeed; + } + else + { + if (player_y_diff < -player_target_maxspeed) + { + player_y_diff = -player_target_maxspeed; + } + } + player_y += player_y_diff; + } + unsigned short y = player_y / y_divisor; + spr_y_h[player_sprite] = y >> 8; + spr_y_l[player_sprite] = (unsigned char)y; + } + else + { + player_ready_y = 1; + } + if (player_x != player_x_target) + { + player_x_diff = (((signed short)player_x_target - (signed short)player_x)) / (signed short)player_target_divider; + if (player_x_diff == 0) + { + player_x = player_x_target; + } + else + { + if (player_x_diff > player_target_maxspeed) + { + player_x_diff = player_target_maxspeed; + } + else + { + if (player_x_diff < -player_target_maxspeed) + { + player_x_diff = -player_target_maxspeed; + } + } + player_x += player_x_diff; + } + set_sprite_position_x(player_sprite, player_x / x_divisor); + } + else + { + player_ready_x = 1; + } + player_ready = player_ready_x && player_ready_y; +} + +// Player +void setup_player(unsigned short x, unsigned short y, unsigned char lives) +{ + // Player bounds + player_x_min = 32 * x_divisor; + player_x_max = 336 * x_divisor; + player_y_min = 32 * y_divisor; + player_y_max = 244 * y_divisor; + + // Player initial position + player_x = x * x_divisor; + player_y = y * y_divisor; + player_speed = player_speed_min; + player_xs = 0; + player_ys = 0; + + player_hit = false; + player_lives = lives; + player_lives_changed = true; + player_respawn_timer = 0; + player_invincible_timer = 0; + player_invincible_flash = 0; + + // Initialise player sprite + spr_index[player_sprite] = sprite_index_player_first; + enable_sprite(player_sprite, sprite_palette_player, sprite_size_player, true); + + set_sprite_position(player_sprite, x, y); + + // Trails + player_trail_timer = player_trail_frequency; +} + +void player_destroyed() +{ + play_sound(const_sound_player_explode); + add_explosion(0, 1); + add_explosion(1, 2); + spr_on[player_sprite] = false; + player_lives_changed = true; + if (player_lives > 0) + { + player_lives--; + player_respawn_timer = player_respawn_timeout; + } +} + +void handle_player(bool allow_control) +{ + // If player is currently dead and a respawn is scheduled + if (player_respawn_timer > 0) + { + player_hit = false; + + // Decelerate player speed to minimum + if (player_speed > player_speed_min) + { + player_speed--; + } + // Decrement respawn timer + player_respawn_timer--; + // Respawn the player when timer reaches 0 + if (player_respawn_timer == 0) + { + // Set player to spawn position + setup_player(player_spawn_x, player_spawn_y, player_lives); + // Enable invincibility and set timer + enable_sprite(player_sprite, sprite_palette_player, sprite_size_player, false); + player_invincible_timer = player_invincible_timeout; + } + return; + } + + // If player is currently invincible + if (player_invincible_timer > 0) + { + // Ignore any collisions + player_hit = false; + // Decrement invincibility timer + player_invincible_timer--; + // Wait for invincibility timer to expire + if (player_invincible_timer == 0) + { + // Re-enable collision when invincibility runs out + enable_sprite(player_sprite, sprite_palette_player, sprite_size_player, true); + } + else + { + // Increment flash timer + player_invincible_flash++; + // Wait for invincibility flash timer to roll over + if (player_invincible_flash == 4) + { + // Reset timer + player_invincible_flash = 0; + // Flip player sprite visibility + spr_on[player_sprite] = !spr_on[player_sprite]; + } + } + } + else + { + // If player is hit then destroy player + if (player_hit) + { + player_hit = false; + player_destroyed(); + } + } + + // Gradually reduce player move speed to zero + if (player_xs > 0) + { + player_xs--; + } + else if (player_xs < 0) + { + player_xs++; + } + if (player_ys > 0) + { + player_ys--; + } + else if (player_ys < 0) + { + player_ys++; + } + + // Is player control activated? + if (allow_control) + { + // Use player directional inputs to increase/decrease velocity, enforcing max speed limits + if (CHECK_BIT(joystick[0], 0) && player_xs < player_max_speed) + { + player_xs += player_accel; + } + if (CHECK_BIT(joystick[0], 1) && player_xs > -player_max_speed) + { + player_xs -= player_accel; + } + if (CHECK_BIT(joystick[0], 2) && player_ys < player_max_speed) + { + player_ys += player_accel; + } + if (CHECK_BIT(joystick[0], 3) && player_ys > -player_max_speed) + { + player_ys -= player_accel; + } + + // Use player boost input to increase/decrease player flight speed, enforcing max speed limits + if (CHECK_BIT(joystick[0], 4)) + { + if (player_speed < player_speed_max) + { + player_speed++; + } + } + else + { + if (player_speed > player_speed_min) + { + player_speed--; + } + } + } + + // Set player sprite image + spr_index[player_sprite] = (player_xs < -2 ? sprite_index_player_first + 2 : player_xs > 2 ? sprite_index_player_first + 3 + : sprite_index_player_first); + + // Integrate player move velocity + player_x += player_xs; + player_y += player_ys; + + // Enforce player position limits when player is in control (disabled when not to allow ship to animate off screen) + if (allow_control) + { + // Enforce X minimum (left) + if (player_x < player_x_min) + { + player_x = player_x_min; + if (player_xs < 0) + { + player_xs = 0; + } + } + // Enforce X maximum (right) + else if (player_x > player_x_max) + { + player_x = player_x_max; + if (player_xs > 0) + { + player_xs = 0; + } + } + + // Enforce Y minimum (top) + if (player_y < player_y_min) + { + player_y = player_y_min; + if (player_ys < 0) + { + player_ys = 0; + } + } + // Enforce Y maximum (bottom) + else if (player_y > player_y_max) + { + player_y = player_y_max; + if (player_ys > 0) + { + player_ys = 0; + } + } + } + + // Set sprite position with low res coordinates + set_sprite_position(player_sprite, player_x / x_divisor, player_y / y_divisor); + + // Decrease player trail timer + player_trail_timer--; + // Spawn player trail when timer expires + if (player_trail_timer <= 0) + { + // Generate next particle timer (emission rate) + unsigned char reduce = (player_speed / 8) + rand_uchar(0, 6); + player_trail_timer = player_trail_frequency - reduce; + if (player_trail_timer <= 0) + { + player_trail_timer = 0; + } + // Spawn a player trail entity + add_player_trail(); + } +} \ No newline at end of file diff --git a/src/inputtest/zorblaxx_player.h b/src/inputtest/zorblaxx_player.h new file mode 100644 index 0000000..9bab82a --- /dev/null +++ b/src/inputtest/zorblaxx_player.h @@ -0,0 +1,63 @@ +/*============================================================================ + Aznable OS - Zorblaxx demo application - Player routines + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-27 + + 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 3 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, see . +===========================================================================*/ + +#pragma once + +// Player +extern const signed char player_max_speed; +extern const unsigned char player_accel; +extern const unsigned char player_trail_frequency; +extern const unsigned char player_trail_speed; +extern const unsigned char player_trail_lifespan; +extern unsigned short player_x; +extern unsigned short player_y; +extern signed char player_xs; +extern signed char player_ys; +extern unsigned short player_x_min; +extern unsigned short player_x_max; +extern unsigned short player_y_min; +extern unsigned short player_y_max; +extern const unsigned char player_speed_min; +extern const unsigned char player_speed_max; +extern const unsigned char player_speed_warp; +extern unsigned char player_speed; +extern signed char player_trail_timer; + +extern unsigned char player_lives; +extern unsigned char player_lives_changed; +extern const unsigned char player_invincible_timeout; +extern const unsigned char player_respawn_timeout; +extern unsigned char player_hit; + +extern unsigned char player_ready; +extern unsigned char player_ready_x; +extern unsigned char player_ready_y; + +extern unsigned short player_x_target; +extern unsigned short player_y_target; +extern signed short player_x_diff; +extern signed short player_y_diff; + +extern void set_player_target(unsigned short x, unsigned short y, unsigned char divider, unsigned char maxspeed); +extern void move_player_to_target(); + +extern void setup_player(unsigned short x, unsigned short y, unsigned char lives); +extern void handle_player(bool allow_control); \ No newline at end of file diff --git a/src/inputtest/zorblaxx_trails.c b/src/inputtest/zorblaxx_trails.c new file mode 100644 index 0000000..f3757af --- /dev/null +++ b/src/inputtest/zorblaxx_trails.c @@ -0,0 +1,107 @@ +/*============================================================================ + Aznable OS - Zorblaxx demo application - Trail routines + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-27 + + 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 3 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, see . +===========================================================================*/ + +#include "../shared/sys.h" +#include "../shared/sprite.h" +#include "sprite_images.h" +#include "zorblaxx_app.h" +#include "zorblaxx_trails.h" +#include "zorblaxx_asteroids.h" +#include "zorblaxx_player.h" + +#define const_trail_max 10 +unsigned char trail_max = const_trail_max; +unsigned short trail_x[const_trail_max]; +unsigned short trail_y[const_trail_max]; +signed char trail_xs[const_trail_max]; +signed char trail_ys[const_trail_max]; +unsigned char trail_timer[const_trail_max]; +unsigned short trail_y_max; +unsigned char trail_x_offset; +unsigned char trail_y_offset; + +void setup_trails() +{ + trail_y_max = 272 * y_divisor; + trail_x_offset = (4 * x_divisor); + trail_y_offset = (12 * y_divisor); + for (int t = trail_sprite_first; t < trail_sprite_first + trail_max; t++) + { + enable_sprite(t, sprite_palette_trails, sprite_size_trails, false); + spr_on[t] = false; + } +} + +void add_player_trail() +{ + for (unsigned char t = 0; t < trail_max; t++) + { + if (trail_timer[t] == 0) + { + unsigned char spread = 3 + (player_speed / 8); + trail_xs[t] = rand_schar(-spread, spread); + trail_ys[t] = player_trail_speed; + + trail_x[t] = (player_x + trail_x_offset); + trail_y[t] = (player_y + trail_y_offset) - (player_trail_speed + player_speed); + + trail_timer[t] = player_trail_lifespan; + unsigned char sprite = trail_sprite_first + t; + enable_sprite(sprite, sprite_palette_trails, sprite_size_trails, false); + spr_index[sprite] = sprite_index_trails_first; + return; + } + } +} + +void handle_trails() +{ + for (unsigned char t = 0; t < trail_max; t++) + { + if (trail_timer[t] > 0) + { + unsigned char sprite = trail_sprite_first + t; + trail_y[t] += trail_ys[t] + player_speed; + if ((trail_y[t] > trail_y_max) > 0) + { + spr_on[sprite] = false; + trail_timer[t] = 0; + continue; + } + trail_timer[t]--; + if (trail_timer[t] == 0) + { + spr_index[sprite]++; + if (spr_index[sprite] > sprite_index_trails_last) + { + spr_on[sprite] = false; + } + else + { + trail_timer[t] = player_trail_lifespan; + } + } + trail_x[t] += trail_xs[t]; + + set_sprite_position(sprite, trail_x[t] / x_divisor, trail_y[t] / y_divisor); + } + } +} \ No newline at end of file diff --git a/src/inputtest/zorblaxx_trails.h b/src/inputtest/zorblaxx_trails.h new file mode 100644 index 0000000..9753a31 --- /dev/null +++ b/src/inputtest/zorblaxx_trails.h @@ -0,0 +1,40 @@ +/*============================================================================ + Aznable OS - Zorblaxx demo application - Trail routines + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-27 + + 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 3 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, see . +===========================================================================*/ + +#ifndef ZORBLAXX_TRAILS_H +#define ZORBLAXX_TRAILS_H + +// Trails +extern unsigned char trail_max; +extern unsigned short trail_x[]; +extern unsigned short trail_y[]; +extern signed char trail_xs[]; +extern signed char trail_ys[]; +extern unsigned char trail_timer[]; +extern unsigned short trail_y_max; + +extern void setup_trails(); + +extern void add_player_trail(); + +extern void handle_trails(); + +#endif \ No newline at end of file diff --git a/src/shared/Makefile b/src/shared/Makefile new file mode 100644 index 0000000..e49cd79 --- /dev/null +++ b/src/shared/Makefile @@ -0,0 +1,37 @@ +SDCC=sdcc +CPU=z80 +DATALOC=0xC000 + +OUT_DIR=build/ +MAIN=os +OUTPUT=rom + +SHARED_PATH=../shared/ +SHARED_RELS_ALL=$(patsubst %.c,build/%.rel,$(wildcard $(SHARED_PATH)*.c)) # Get all c files from src/shared/ folder +IGNORE_SHARED_RELS=$(patsubst %, build/../shared/%.rel, $(IGNORE_SHARED)) # Format shared files to ignore correctly for filtering +SHARED_RELS=$(filter-out $(IGNORE_SHARED_RELS), $(SHARED_RELS_ALL)) # Filter out ignored shared files + +PROJECT_RELS_ALL=$(patsubst %.c,build/%.rel,$(wildcard *.c)) # Get all c files from src/[project] folder +IGNORE_PROJECT_RELS=$(patsubst %, build/%.rel, $(IGNORE_PROJECT)) # Format project files to ignore correctly for filtering +PROJECT_RELS_FILTERED=$(filter-out $(IGNORE_PROJECT_RELS),$(PROJECT_RELS_ALL)) # Filter out ignored shared files +PROJECT_RELS=$(patsubst build/$(MAIN).rel,,$(PROJECT_RELS_FILTERED)) # Remove main c file + +TARGET_RELS=$(patsubst build/$(MAIN).rel,,$(wildcard build/*.rel)) + +all: $(OUTPUT).bin + +build/$(OUTPUT).ihx: $(PROJECT_RELS) $(SHARED_RELS) + $(SDCC) $(DEFINES) -m$(CPU) --data-loc $(DATALOC) -o $(OUT_DIR)$(OUTPUT).ihx $(MAIN).c $(TARGET_RELS) + +build/%.rel: %.c + $(SDCC) $(DEFINES) -m$(CPU) --data-loc $(DATALOC) -o $(OUT_DIR) -c $< + +$(OUTPUT).bin: build/$(OUTPUT).ihx + srec_cat $< -intel -o $@ -binary + rm build/$(OUTPUT).ihx + mv $(OUTPUT).bin bin/$(OUTPUT).bin + rm -f build/$(OUTPUT).* + +clean: + rm -f build/* + rm -f bin/* diff --git a/src/shared/music.c b/src/shared/music.c new file mode 100644 index 0000000..d24333f --- /dev/null +++ b/src/shared/music.c @@ -0,0 +1,55 @@ +/*============================================================================ + Aznable OS - Music engine (YM player) + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.1 + Date: 2022-01-07 + + 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 3 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, see . +===========================================================================*/ + +#include "../shared/sys.h" +#include "../shared/music.h" + +#define const_music_track_max 32 +unsigned char music_track_max = const_music_track_max; + +unsigned char music_last_played = 255; + +#include myPATH(../PROJECT_NAME/,music_tracks.h) // Include auto generated track array + +void play_music(unsigned char track, unsigned char loop) +{ + // Write track start address (3 bytes) + musicram[1] = (unsigned char)(music_track_address[track] >> 16); + musicram[2] = music_track_address[track] >> 8; + musicram[3] = music_track_address[track]; + // Write start track instruction (2 for looping, 1 for single play) + musicram[0] = loop ? 2 : 1; + music_last_played = track; +} + +void play_music_if(unsigned char track, unsigned char loop) +{ + if (musicram[0] == 0 || music_last_played != track) + { + play_music(track, loop); + } +} + +void stop_music() +{ + // Send stop command + musicram[0] = 3; +} \ No newline at end of file diff --git a/src/shared/music.h b/src/shared/music.h new file mode 100644 index 0000000..92cb937 --- /dev/null +++ b/src/shared/music.h @@ -0,0 +1,30 @@ +/*============================================================================ + Aznable OS - Music engine (YM player) + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.1 + Date: 2022-01-07 + + 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 3 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, see . +===========================================================================*/ +#ifndef MUSIC_H +#define MUSIC_H + +extern unsigned char music_track_max; + +extern void play_music(unsigned char track, unsigned char loop); +extern void play_music_if(unsigned char track, unsigned char loop); +extern void stop_music(); + +#endif \ No newline at end of file diff --git a/src/ps2.c b/src/shared/ps2.c similarity index 80% rename from src/ps2.c rename to src/shared/ps2.c index dbbd062..752a2bc 100644 --- a/src/ps2.c +++ b/src/shared/ps2.c @@ -19,8 +19,8 @@ with this program. If not, see . ===========================================================================*/ -#pragma once -#include "sys.c" +#include "sys.h" +#include "ps2.h" // COMMAND KEYS const char KEY_TAB = 0x0d; @@ -37,51 +37,12 @@ const char KEY_CTRL = 0x63; // EXT 0 = LEFT, EXT 1 = RIGHT const char KEY_1 = 0x16; const char KEY_SPACE = 0x29; -// UNMAPPED COMMAND KEYS -// 0x7c, //55 KEY_KPASTERISK -// 0x05, //59 KEY_F1 -// 0x06, //60 KEY_F2 -// 0x04, //61 KEY_F3 -// 0x0c, //62 KEY_F4 -// 0x03, //63 KEY_F5 -// 0x0b, //64 KEY_F6 -// 0x83, //65 KEY_F7 -// 0x0a, //66 KEY_F8 -// 0x01, //67 KEY_F9 -// 0x09, //68 KEY_F10 -// 0x6c, //71 KEY_KP7 -// 0x75, //72 KEY_KP8 -// 0x7d, //73 KEY_KP9 -// 0x7b, //74 KEY_KPMINUS -// 0x6b, //75 KEY_KP4 -// 0x73, //76 KEY_KP5 -// 0x74, //77 KEY_KP6 -// 0x79, //78 KEY_KPPLUS -// 0x69, //79 KEY_KP1 -// 0x72, //80 KEY_KP2 -// 0x7a, //81 KEY_KP3 -// 0x70, //82 KEY_KP0 -// 0x71, //83 KEY_KPDOT -// 0x61, //86 KEY_102ND -// 0x78, //87 KEY_F11 -// 0x07, //88 KEY_F12 - // EXTENSION KEYS const char KEY_UP = 0x75; const char KEY_LEFT = 0x6b; const char KEY_RIGHT = 0x74; const char KEY_DOWN = 0x72; -// UNMAPPED EXTENSION KEYS -// EXT | 0x5a, //96 KEY_KPENTER -// EXT | 0x4a, //98 KEY_KPSLASH -// EXT | 0x6c, //102 KEY_HOME -// EXT | 0x7d, //104 KEY_PAGEUP -// EXT | 0x69, //107 KEY_END -// EXT | 0x7a, //109 KEY_PAGEDOWN -// EXT | 0x70, //110 KEY_INSERT -// EXT | 0x71, //111 KEY_DELETE - char kbd_UK[256] = { 0, 0, // 0x00 @@ -197,7 +158,6 @@ char kbd_scan = 0; char kbd_pressed; char kbd_extend; char kbd_ascii = 0; -char kbd_clock_index = 1; char mse_lastclock = 0; bool mse_changed = 1; @@ -206,7 +166,6 @@ signed char mse_y; signed char mse_w; char mse_button1; char mse_button2; -char mse_clock_index = 3; char kbd_buffer[128]; char kbd_buffer_len = 0; @@ -229,7 +188,7 @@ void get_ascii() void handle_ps2() { - bool kbd_clock = CHECK_BIT(ps2_key[kbd_clock_index], 2); + bool kbd_clock = CHECK_BIT(ps2_key[1], 2); if (kbd_clock != kbd_lastclock) { for (char k = 0; k < 2; k++) @@ -275,7 +234,7 @@ void handle_ps2() } kbd_lastclock = kbd_clock; - bool mse_clock = CHECK_BIT(ps2_mouse[mse_clock_index], 0); + bool mse_clock = CHECK_BIT(ps2_mouse[3], 0); if (mse_clock != mse_lastclock) { mse_changed = 1; diff --git a/src/shared/ps2.h b/src/shared/ps2.h new file mode 100644 index 0000000..1dd8c8b --- /dev/null +++ b/src/shared/ps2.h @@ -0,0 +1,106 @@ +/*============================================================================ + Aznable OS - PS/2 interface functions + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.1 + Date: 2021-10-20 + + 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 3 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, see . +===========================================================================*/ +#ifndef PS2_H +#define PS2_H + +// COMMAND KEYS +extern const char KEY_TAB; +extern const char KEY_CAPSLOCK; +extern const char KEY_ENTER; +extern const char KEY_BACKSPACE; +extern const char KEY_ESC; +extern const char KEY_LEFTSHIFT; +extern const char KEY_RIGHTSHIFT; +extern const char KEY_ALT; +extern const char KEY_CTRL; + +// USEFUL KEYS +extern const char KEY_1; +extern const char KEY_SPACE; + +// UNMAPPED COMMAND KEYS +// 0x7c, //55 KEY_KPASTERISK +// 0x05, //59 KEY_F1 +// 0x06, //60 KEY_F2 +// 0x04, //61 KEY_F3 +// 0x0c, //62 KEY_F4 +// 0x03, //63 KEY_F5 +// 0x0b, //64 KEY_F6 +// 0x83, //65 KEY_F7 +// 0x0a, //66 KEY_F8 +// 0x01, //67 KEY_F9 +// 0x09, //68 KEY_F10 +// 0x6c, //71 KEY_KP7 +// 0x75, //72 KEY_KP8 +// 0x7d, //73 KEY_KP9 +// 0x7b, //74 KEY_KPMINUS +// 0x6b, //75 KEY_KP4 +// 0x73, //76 KEY_KP5 +// 0x74, //77 KEY_KP6 +// 0x79, //78 KEY_KPPLUS +// 0x69, //79 KEY_KP1 +// 0x72, //80 KEY_KP2 +// 0x7a, //81 KEY_KP3 +// 0x70, //82 KEY_KP0 +// 0x71, //83 KEY_KPDOT +// 0x61, //86 KEY_102ND +// 0x78, //87 KEY_F11 +// 0x07, //88 KEY_F12 + +// EXTENSION KEYS +extern const char KEY_UP; +extern const char KEY_LEFT; +extern const char KEY_RIGHT; +extern const char KEY_DOWN; + +// UNMAPPED EXTENSION KEYS +// EXT | 0x5a, //96 KEY_KPENTER +// EXT | 0x4a, //98 KEY_KPSLASH +// EXT | 0x6c, //102 KEY_HOME +// EXT | 0x7d, //104 KEY_PAGEUP +// EXT | 0x69, //107 KEY_END +// EXT | 0x7a, //109 KEY_PAGEDOWN +// EXT | 0x70, //110 KEY_INSERT +// EXT | 0x71, //111 KEY_DELETE + +extern char kbd_shift_left; +extern char kbd_shift_right; +extern char kbd_scan; +extern char kbd_pressed; +extern char kbd_extend; +extern char kbd_ascii; + +extern bool mse_changed; +extern signed char mse_x; +extern signed char mse_y; +extern signed char mse_w; +extern char mse_button1; +extern char mse_button2; + +extern char kbd_buffer[128]; +extern char kbd_buffer_len; +extern bool kbd_down[256]; + +extern void get_ascii(); + +extern void handle_ps2(); + +#endif \ No newline at end of file diff --git a/src/shared/sound.c b/src/shared/sound.c new file mode 100644 index 0000000..07c926e --- /dev/null +++ b/src/shared/sound.c @@ -0,0 +1,46 @@ +/*============================================================================ + Aznable OS - Sound engine (M5205 sample player) + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-12-20 + + 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 3 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, see . +===========================================================================*/ + +#include "sys.h" +#include "sound.h" + +#define const_sound_sample_max 32 +unsigned char sound_sample_max = const_sound_sample_max; +#include myPATH(../PROJECT_NAME/,sound_samples.h) // Include auto generated track array + +void play_sound(unsigned char sample) +{ + // Write sample start address (2 bytes) + sndram[1] = sound_sample_address[sample] >> 8; + sndram[0] = sound_sample_address[sample]; + // Write sample length (2 bytes) + unsigned short end = sound_sample_address[sample] + sound_sample_length[sample]; + sndram[5] = end >> 8; + sndram[4] = end; + // Write play instruction + sndram[8] = 1; +} + +void set_sound_volume(unsigned char volume) +{ + // Write sample volume + sndram[12] = volume; +} \ No newline at end of file diff --git a/src/shared/sound.h b/src/shared/sound.h new file mode 100644 index 0000000..68426a9 --- /dev/null +++ b/src/shared/sound.h @@ -0,0 +1,29 @@ +/*============================================================================ + Aznable OS - Sound engine (M5205 sample player) + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-12-20 + + 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 3 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, see . +===========================================================================*/ +#ifndef SOUND_H +#define SOUND_H + +extern unsigned char sound_sample_max; + +extern void play_sound(unsigned char sample); +extern void set_sound_volume(unsigned char volume); + +#endif \ No newline at end of file diff --git a/src/shared/sprite.c b/src/shared/sprite.c new file mode 100644 index 0000000..643f9a3 --- /dev/null +++ b/src/shared/sprite.c @@ -0,0 +1,96 @@ +/*============================================================================ + Aznable OS - Casval (sprite engine) + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-27 + + 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 3 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, see . +===========================================================================*/ + +#include "sys.h" +#include "sprite.h" + +#define const_sprite_max 32 +unsigned char sprite_max = const_sprite_max; +unsigned char spr_x_l[const_sprite_max]; +unsigned char spr_x_h[const_sprite_max]; +unsigned char spr_y_l[const_sprite_max]; +unsigned char spr_y_h[const_sprite_max]; +bool spr_on[const_sprite_max]; +bool spr_collide[const_sprite_max]; +unsigned char spr_palette_index[const_sprite_max]; +unsigned char spr_index[const_sprite_max]; +unsigned char spr_size[const_sprite_max]; + +unsigned char spr_highbits[const_sprite_max]; // Temp cache of high bits excluding upper 2 Y bits + +void set_sprite_position(unsigned char sprite, unsigned short x, unsigned short y) +{ + spr_x_h[sprite] = x >> 8; + spr_x_l[sprite] = (unsigned char)x; + spr_y_h[sprite] = y >> 8; + spr_y_l[sprite] = (unsigned char)y; +} +void set_sprite_position_x(unsigned char sprite, unsigned short x) +{ + spr_x_h[sprite] = x >> 8; + spr_x_l[sprite] = (unsigned char)x; +} + +void update_sprites() +{ + unsigned char s = 0; + for (unsigned char sprite = 0; sprite < sprite_max; sprite++) + { + if (spr_on[sprite]) + { + // Set sprite properties + spriteram[s++] = spr_highbits[sprite] | spr_y_h[sprite]; // Enabled (1 bit) + Collide (1 bit) + Size (2 bits) + Palette Index (2 bits) + Position Y (upper 2 bits) + spriteram[s++] = spr_y_l[sprite]; // Position Y (lower 8 bits) + spriteram[s++] = spr_index[sprite] << 2 | spr_x_h[sprite]; // Sprite Index (6 bits) + Position X (upper 2 bits) + spriteram[s++] = spr_x_l[sprite]; // Position X (lower 8 bits) + } + else + { + // Clear first sprite byte to disable + spriteram[s] = 0; + s += 4; + } + } +} + +void enable_sprite(unsigned char sprite, unsigned char palette_index, unsigned char size, unsigned char collide) +{ + spr_on[sprite] = 1; + spr_collide[sprite] = collide; + spr_palette_index[sprite] = palette_index; + spr_size[sprite] = size; + spr_highbits[sprite] = 1 << 7 | collide << 6 | palette_index << 4 | size << 2; +} + +void clear_sprites() +{ + for (unsigned char sprite = 0; sprite < sprite_max; sprite++) + { + spr_on[sprite] = 0; + } +} +void clear_sprites_range(unsigned char first, unsigned char last) +{ + for (unsigned char sprite = first; sprite <= last; sprite++) + { + spr_on[sprite] = 0; + } +} \ No newline at end of file diff --git a/src/shared/sprite.h b/src/shared/sprite.h new file mode 100644 index 0000000..5e68975 --- /dev/null +++ b/src/shared/sprite.h @@ -0,0 +1,47 @@ +/*============================================================================ + Aznable OS - Casval (sprite engine) + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-27 + + 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 3 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, see . +===========================================================================*/ +#ifndef SPRITE_H +#define SPRITE_H + +extern unsigned char sprite_max; +extern unsigned char spr_x_l[]; +extern unsigned char spr_x_h[]; +extern unsigned char spr_y_l[]; +extern unsigned char spr_y_h[]; +extern bool spr_on[]; +extern bool spr_collide[]; +extern unsigned char spr_palette_index[]; +extern unsigned char spr_index[]; +extern unsigned char spr_size[]; + +extern void set_sprite_position(unsigned char sprite, unsigned short x, unsigned short y); + +extern void set_sprite_position_x(unsigned char sprite, unsigned short x); + +extern void update_sprites(); + +extern void enable_sprite(unsigned char sprite, unsigned char palette_index, unsigned char size, unsigned char collide); + +extern void clear_sprites(); + +extern void clear_sprites_range(unsigned char first, unsigned char last); + +#endif \ No newline at end of file diff --git a/src/shared/starfield.c b/src/shared/starfield.c new file mode 100644 index 0000000..8d799fb --- /dev/null +++ b/src/shared/starfield.c @@ -0,0 +1,62 @@ +/*============================================================================ + Aznable OS - Moroboshi (starfield) + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-27 + + 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 3 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, see . +===========================================================================*/ +#include "sys.h" + +void enable_starfield() +{ + starfield1[0] = 1; + starfield2[0] = 1; + starfield3[0] = 1; +} +void disable_starfield() +{ + starfield1[0] = 0; + starfield2[0] = 0; + starfield3[0] = 0; +} + +void set_starfield_speed_x(float speed) +{ + unsigned char dir = (speed < 0) << 7; + unsigned short mag = (unsigned short)abs(speed * 256); + starfield3[1] = dir | mag >> 8; + starfield3[2] = (unsigned char)mag; + mag = mag << 1; + starfield2[1] = dir | mag >> 8; + starfield2[2] = (unsigned char)mag; + mag = mag << 1; + starfield1[1] = dir | mag >> 8; + starfield1[2] = (unsigned char)mag; +} + +void set_starfield_speed_y(float speed) +{ + unsigned char dir = (speed < 0) << 7; + unsigned short mag = (unsigned short)abs(speed * 256); + starfield3[3] = dir | mag >> 8; + starfield3[4] = (unsigned char)mag; + mag = mag << 1; + starfield2[3] = dir | mag >> 8; + starfield2[4] = (unsigned char)mag; + mag = mag << 1; + starfield1[3] = dir | mag >> 8; + starfield1[4] = (unsigned char)mag; +} \ No newline at end of file diff --git a/src/shared/starfield.h b/src/shared/starfield.h new file mode 100644 index 0000000..da8bfa9 --- /dev/null +++ b/src/shared/starfield.h @@ -0,0 +1,32 @@ +/*============================================================================ + Aznable OS - Moroboshi (starfield) + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2021-11-27 + + 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 3 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, see . +===========================================================================*/ +#ifndef STARFIELD_H +#define STARFIELD_H + +extern void enable_starfield(); + +extern void disable_starfield(); + +extern void set_starfield_speed_x(float speed); + +extern void set_starfield_speed_y(float speed); + +#endif \ No newline at end of file diff --git a/src/sys.c b/src/shared/sys.c similarity index 52% rename from src/sys.c rename to src/shared/sys.c index ea57b0f..b026712 100644 --- a/src/sys.c +++ b/src/shared/sys.c @@ -2,8 +2,8 @@ Aznable OS - System interface functions Author: Jim Gregory - https://github.com/JimmyStones/ - Version: 1.1 - Date: 2021-10-20 + Version: 1.2 + Date: 2021-11-27 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 @@ -19,33 +19,18 @@ with this program. If not, see . ===========================================================================*/ -#pragma once - #include #include -#include +#include +#include +#include -// Memory mapped IO -// - Inputs -unsigned char __at(0x6000) input0; -unsigned char __at(0x7000) joystick[24]; -unsigned char __at(0x7100) analog_l[12]; -unsigned char __at(0x7200) analog_r[12]; -unsigned char __at(0x7300) paddle[6]; -unsigned char __at(0x7400) spinner[12]; -unsigned char __at(0x7500) ps2_key[2]; -unsigned char __at(0x7600) ps2_mouse[6]; -unsigned char __at(0x7700) timestamp[5]; -unsigned char __at(0x7800) timer[2]; -// - Graphics RAM -unsigned char __at(0x8000) chram[2048]; -unsigned char __at(0x8800) fgcolram[2048]; -unsigned char __at(0x9000) bgcolram[2048]; +#include "sys.h" // Character map const unsigned char chram_cols = 64; const unsigned char chram_rows = 32; -unsigned int chram_size; +unsigned short chram_size; // Hardware inputs bool hsync; @@ -57,15 +42,18 @@ bool hblank_last; bool vblank; bool vblank_last; -// Macros -#define CHECK_BIT(var, pos) ((var) & (1 << (pos))) -#define SET_BIT(var,pos) ((var) |= (1 << (pos))) -#define CLEAR_BIT(var,pos) ((var) &= ~(1 << (pos))) -#define VBLANK_RISING (vblank && !vblank_last) -#define VSYNC_RISING (vsync && !vsync_last) -#define HBLANK_RISING (hblank && !hblank_last) -#define HSYNC_RISING (hsync && !hsync_last) +// Helper functions +unsigned char rand_uchar(unsigned char lower, unsigned char upper) +{ + return (rand() % (upper - lower + 1)) + lower; +} -// Application state -char state = 0; -char nextstate = 0; +unsigned short rand_ushort(unsigned short lower, unsigned short upper) +{ + return (rand() % (upper - lower + 1)) + lower; +} + +signed char rand_schar(signed char lower, signed char upper) +{ + return (rand() % (upper - lower + 1)) + lower; +} diff --git a/src/shared/sys.h b/src/shared/sys.h new file mode 100644 index 0000000..600e046 --- /dev/null +++ b/src/shared/sys.h @@ -0,0 +1,110 @@ +/*============================================================================ + Aznable OS - System interface functions + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.2 + Date: 2021-11-27 + + 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 3 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, see . +===========================================================================*/ +#ifndef SYS_H +#define SYS_H + +#include +#include +#include +#include + +// Memory mapped IO +// - Inputs +unsigned char __at(0x8000) input0; +unsigned char __at(0x8100) joystick[24]; +unsigned char __at(0x8200) analog_l[12]; +unsigned char __at(0x8300) analog_r[12]; +unsigned char __at(0x8400) paddle[6]; +unsigned char __at(0x8500) spinner[12]; +unsigned char __at(0x8600) ps2_key[2]; +unsigned char __at(0x8700) ps2_mouse[6]; +unsigned char __at(0x8800) timestamp[5]; +unsigned char __at(0x8900) timer[2]; +unsigned char __at(0x8A00) starfield1[5]; +unsigned char __at(0x8A10) starfield2[5]; +unsigned char __at(0x8A20) starfield3[5]; +unsigned char __at(0x8A30) system_pause; +unsigned char __at(0x8A31) system_menu; + +// - Casval (character map) +unsigned char __at(0x9800) chram[2048]; +unsigned char __at(0xA000) fgcolram[2048]; +unsigned char __at(0xA800) bgcolram[2048]; +// - Comet (sprite engine) +unsigned char __at(0xB000) spriteram[512]; +unsigned char __at(0xB400) spritecollisionram[32]; +// - Zechs (tilemap) +unsigned char __at(0x8C00) tilemapctl[4]; +unsigned char __at(0x8C10) tilemapram[1024]; +// - Charles (sound) +unsigned char __at(0x8B00) sndram[16]; +// - Deikun (music) +unsigned char __at(0x8B10) musicram[4]; + +// Character map +extern const unsigned char chram_cols; +extern const unsigned char chram_rows; +extern unsigned short chram_size; + +// Hardware inputs +extern bool hsync; +extern extern bool hsync_last; +extern bool vsync; +extern bool vsync_last; +extern bool hblank; +extern bool hblank_last; +extern bool vblank; +extern bool vblank_last; + +// INPUT 0 bits +#define INPUT_HBLANK 5 +#define INPUT_VBLANK 4 + +// Macros +#define CHECK_BIT(var, pos) ((var) & (1 << (pos))) +#define SET_BIT(var, pos) ((var) |= (1 << (pos))) +#define CLEAR_BIT(var, pos) ((var) &= ~(1 << (pos))) +#define VBLANK_RISING (vblank && !vblank_last) +#define VSYNC_RISING (vsync && !vsync_last) +#define HBLANK_RISING (hblank && !hblank_last) +#define HSYNC_RISING (hsync && !hsync_last) +#define VBLANK_FALLING (!vblank && vblank_last) +#define VSYNC_FALLING (!vsync && vsync_last) +#define HBLANK_FALLING (!hblank && hblank_last) +#define HSYNC_FALLING (!hsync && hsync_last) + +#define GET_TIMER ((unsigned short)timer[1] << 8) | (unsigned char)timer[0] + +// Auto include handling +#define myIDENT(x) x +#define myXSTR(x) #x +#define mySTR(x) myXSTR(x) +#define myPATH(x,y) mySTR(myIDENT(x)myIDENT(y)) + +// Helper functions +extern unsigned char rand_uchar(unsigned char lower, unsigned char upper); + +extern unsigned short rand_ushort(unsigned short lower, unsigned short upper); + +extern signed char rand_schar(signed char lower, signed char upper); + + +#endif \ No newline at end of file diff --git a/src/shared/tilemap.c b/src/shared/tilemap.c new file mode 100644 index 0000000..4fd5e4b --- /dev/null +++ b/src/shared/tilemap.c @@ -0,0 +1,68 @@ +/*============================================================================ + Aznable OS - Zechs (tilemap engine) + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2022-01-03 + + 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 3 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, see . +===========================================================================*/ + +#include "sys.h" +#include "tilemap.h" + +signed char tilemap_offset_x = 0; +signed char tilemap_offset_y = 0; + +void update_tilemap_offset() +{ + tilemapctl[0] = tilemap_offset_x; + tilemapctl[1] = tilemap_offset_y; +} + +void scroll_tilemap_left() +{ + tilemapctl[2] = 1; + while (tilemapctl[2] != 0) + { + } +} +void scroll_tilemap_right() +{ + tilemapctl[2] = 2; + while (tilemapctl[2] != 0) + { + } +} +void scroll_tilemap_up() +{ + tilemapctl[2] = 3; + while (tilemapctl[2] != 0) + { + } +} +void scroll_tilemap_down() +{ + tilemapctl[2] = 4; + while (tilemapctl[2] != 0) + { + } +} +void clear_tilemap() +{ + tilemapctl[2] = 5; + while (tilemapctl[2] != 0) + { + } +} \ No newline at end of file diff --git a/src/shared/tilemap.h b/src/shared/tilemap.h new file mode 100644 index 0000000..cb9f5f4 --- /dev/null +++ b/src/shared/tilemap.h @@ -0,0 +1,34 @@ +/*============================================================================ + Aznable OS - Zechs (tilemap engine) + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.0 + Date: 2022-01-03 + + 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 3 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, see . +===========================================================================*/ +#ifndef TILEMAP_H +#define TILEMAP_H + +extern signed char tilemap_offset_x; +extern signed char tilemap_offset_y; + +extern void update_tilemap_offset(); +extern void scroll_tilemap_left(); +extern void scroll_tilemap_right(); +extern void scroll_tilemap_up(); +extern void scroll_tilemap_down(); +extern void clear_tilemap(); + +#endif \ No newline at end of file diff --git a/src/ui.c b/src/shared/ui.c similarity index 87% rename from src/ui.c rename to src/shared/ui.c index 2653030..61ed622 100644 --- a/src/ui.c +++ b/src/shared/ui.c @@ -19,26 +19,16 @@ with this program. If not, see . ===========================================================================*/ -#pragma once -#include "sys.c" +#include "sys.h" +#include "ui.h" char asc_0 = 48; char asc_1 = 49; -#define char_corner_round_tl 149 -#define char_corner_round_tr 137 -#define char_corner_round_bl 138 -#define char_corner_round_br 139 -#define char_line_h 131 -#define char_line_v 130 -#define char_t_up 177 -#define char_dot 27 -#define char_cross 155 - // Set all character RAM to specified character void clear_chars(char c) { - for (unsigned int p = 0; p < chram_size; p++) + for (unsigned short p = 0; p < chram_size; p++) { chram[p] = c; fgcolram[p] = c; @@ -46,10 +36,18 @@ void clear_chars(char c) } } +void clear_char_area(char c, unsigned char tx, unsigned char ty, unsigned char bx, unsigned char by) +{ + for (char y = ty; y <= by; y++) + { + write_char_row(c, 0, tx, y, (bx - tx) + 1); + } +} + // Set all character background colours to specified void clear_bgcolor(char color) { - for (unsigned int p = 0; p < chram_size; p++) + for (unsigned short p = 0; p < chram_size; p++) { bgcolram[p] = color; } @@ -58,7 +56,7 @@ void clear_bgcolor(char color) // Write string to character RAM void write_string(const char *string, char color, unsigned char x, unsigned char y) { - unsigned int p = (y * chram_cols) + x; + unsigned short p = (y * chram_cols) + x; unsigned char l = strlen(string); for (char c = 0; c < l; c++) { @@ -71,7 +69,7 @@ void write_string(const char *string, char color, unsigned char x, unsigned char // Write formatted string to character RAM (signed char data) void write_stringfs(const char *format, char color, unsigned char x, unsigned char y, signed char data) { - unsigned int p = (y * chram_cols) + x; + unsigned short p = (y * chram_cols) + x; char temp[30]; sprintf(temp, format, data); unsigned char l = strlen(temp); @@ -88,9 +86,9 @@ void write_stringfs(const char *format, char color, unsigned char x, unsigned ch } // Write formatted string to character RAM (unsigned char data) -void write_stringf(const char *format, char color, unsigned char x, unsigned char y, char data) +void write_stringf(const char *format, char color, unsigned char x, unsigned char y, unsigned char data) { - unsigned int p = (y * chram_cols) + x; + unsigned short p = (y * chram_cols) + x; char temp[30]; sprintf(temp, format, data); unsigned char l = strlen(temp); @@ -109,7 +107,7 @@ void write_stringf(const char *format, char color, unsigned char x, unsigned cha // Write formatted string to character RAM (unsigned short data) void write_stringf_ushort(const char *format, char color, unsigned char x, unsigned char y, unsigned short data) { - unsigned int p = (y * chram_cols) + x; + unsigned short p = (y * chram_cols) + x; char temp[40]; sprintf(temp, format, data); unsigned char l = strlen(temp); @@ -126,9 +124,9 @@ void write_stringf_ushort(const char *format, char color, unsigned char x, unsig } // Write formatted string to character RAM (signed short data) -void write_stringf_short(const char *format, char color, unsigned char x, unsigned char y, short data) +void write_stringf_short(const char *format, char color, unsigned char x, unsigned char y, signed short data) { - unsigned int p = (y * chram_cols) + x; + unsigned short p = (y * chram_cols) + x; char temp[40]; sprintf(temp, format, data); unsigned char l = strlen(temp); @@ -147,7 +145,7 @@ void write_stringf_short(const char *format, char color, unsigned char x, unsign // Write formatted string to character RAM (unsigned long data) void write_stringf_ulong(const char *format, char color, unsigned char x, unsigned char y, unsigned long data) { - unsigned int p = (y * chram_cols) + x; + unsigned short p = (y * chram_cols) + x; char temp[40]; sprintf(temp, format, data); unsigned char l = strlen(temp); @@ -166,7 +164,7 @@ void write_stringf_ulong(const char *format, char color, unsigned char x, unsign // Write single char to character RAM and colour RAM void write_char(unsigned char c, char color, unsigned char x, unsigned char y) { - unsigned int p = (y * chram_cols) + x; + unsigned short p = (y * chram_cols) + x; chram[p] = c; fgcolram[p] = color; } @@ -174,7 +172,7 @@ void write_char(unsigned char c, char color, unsigned char x, unsigned char y) // Write row of consecutive chars to character RAM and colour RAM void write_char_row(unsigned char c, char color, unsigned char x, unsigned char y, unsigned char count) { - unsigned int p = (y * chram_cols) + x; + unsigned short p = (y * chram_cols) + x; for (char b = 0; b < count; b++) { chram[p] = c; @@ -186,21 +184,21 @@ void write_char_row(unsigned char c, char color, unsigned char x, unsigned char // Set colour of single char void set_fgcolour(char color, char x, char y) { - unsigned int p = (y * chram_cols) + x; + unsigned short p = (y * chram_cols) + x; fgcolram[p] = color; } // Set background colour of single char void set_bgcolour(char color, char x, char y) { - unsigned int p = (y * chram_cols) + x; + unsigned short p = (y * chram_cols) + x; bgcolram[p] = color; } // Write row of consecutive chars to character RAM and colour RAM void write_bgcol_row(char color, unsigned char x, unsigned char y, unsigned char count) { - unsigned int p = (y * chram_cols) + x; + unsigned short p = (y * chram_cols) + x; for (char b = 0; b < count; b++) { bgcolram[p] = color; @@ -285,13 +283,6 @@ void fill(char tx, char ty, char bx, char by, char c, char color) write_char_row(c, color, tx, y, (bx - tx) + 1); } } -void fill_bgcolor(char tx, char ty, char bx, char by, char bgcolor) -{ - for (char y = ty; y <= by; y++) - { - write_bgcol_row(bgcolor, tx, y, (bx - tx) + 1); - } -} void fill_bgcol(char tx, char ty, char bx, char by, char color) { for (char y = ty; y <= by; y++) diff --git a/src/shared/ui.h b/src/shared/ui.h new file mode 100644 index 0000000..7da9320 --- /dev/null +++ b/src/shared/ui.h @@ -0,0 +1,100 @@ +/*============================================================================ + Aznable OS - User interface functions + + Author: Jim Gregory - https://github.com/JimmyStones/ + Version: 1.1 + Date: 2021-07-15 + + 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 3 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, see . +===========================================================================*/ +#ifndef UI_H +#define UI_H + +extern char asc_0; +extern char asc_1; + +#define char_corner_round_tl 149 +#define char_corner_round_tr 137 +#define char_corner_round_bl 138 +#define char_corner_round_br 139 +#define char_line_h 131 +#define char_line_v 130 +#define char_t_up 177 +#define char_dot 27 +#define char_cross 155 + +// Set all character RAM to specified character +extern void clear_chars(char c); + +// Set area of character RAM to specified character +extern void clear_char_area(char c, unsigned char tx, unsigned char ty, unsigned char bx, unsigned char by); + +// Set all character background colours to specified +extern void clear_bgcolor(char color); + +// Write string to character RAM +extern void write_string(const char *string, char color, unsigned char x, unsigned char y); + +// Write formatted string to character RAM (signed char data) +extern void write_stringfs(const char *format, char color, unsigned char x, unsigned char y, signed char data); + +// Write formatted string to character RAM (unsigned char data) +extern void write_stringf(const char *format, char color, unsigned char x, unsigned char y, unsigned char data); + +// Write formatted string to character RAM (unsigned short data) +extern void write_stringf_ushort(const char *format, char color, unsigned char x, unsigned char y, unsigned short data); + +// Write formatted string to character RAM (signed short data) +extern void write_stringf_short(const char *format, char color, unsigned char x, unsigned char y, signed short data); + +// Write formatted string to character RAM (unsigned long data) +extern void write_stringf_ulong(const char *format, char color, unsigned char x, unsigned char y, unsigned long data); + +// Write single char to character RAM and colour RAM +extern void write_char(unsigned char c, char color, unsigned char x, unsigned char y); + +// Write row of consecutive chars to character RAM and colour RAM +extern void write_char_row(unsigned char c, char color, unsigned char x, unsigned char y, unsigned char count); + +// Set colour of single char +extern void set_fgcolour(char color, char x, char y); + +// Set background colour of single char +extern void set_bgcolour(char color, char x, char y); + +// Write row of consecutive chars to character RAM and colour RAM +extern void write_bgcol_row(char color, unsigned char x, unsigned char y, unsigned char count); + +// Write grouped bits to character RAM +extern void write_bits(char bits[], char multi, unsigned char first, unsigned char length, char color, unsigned char x, unsigned char y); + +// Draw box outline with specified character +extern void box(unsigned char tx, unsigned char ty, unsigned char bx, unsigned char by, char c, char color); + +// Draw UI panel +extern void panel(char tx, char ty, char bx, char by, char color); + +// Shaded panel +extern void panel_shaded(char tx, char ty, char bx, char by, char color_high, char color1, char color2); + +extern void fill(char tx, char ty, char bx, char by, char c, char color); + +extern void fill_bgcol(char tx, char ty, char bx, char by, char color); + +// Draw page border +extern void page_border(char color); + +extern void draw_charactermap(); + +#endif \ No newline at end of file diff --git a/sys/ascal.vhd b/sys/ascal.vhd index f157e9f..bd4e238 100644 --- a/sys/ascal.vhd +++ b/sys/ascal.vhd @@ -151,6 +151,7 @@ ENTITY ascal IS o_vs : OUT std_logic; -- V sync o_de : OUT std_logic; -- Display Enable o_vbl : OUT std_logic; -- V blank + o_brd : OUT std_logic; -- border enable o_ce : IN std_logic; -- Clock Enable o_clk : IN std_logic; -- Output clock @@ -458,6 +459,7 @@ ARCHITECTURE rtl OF ascal IS SIGNAL o_hacc,o_hacc_ini,o_hacc_next,o_vacc,o_vacc_next,o_vacc_ini : natural RANGE 0 TO 4*OHRES-1; SIGNAL o_hsv,o_vsv,o_dev,o_pev,o_end : unsigned(0 TO 5); SIGNAL o_hsp,o_vss : std_logic; + SIGNAL o_vcarrym,o_prim : boolean; SIGNAL o_read,o_read_pre : std_logic; SIGNAL o_readlev,o_copylev : natural RANGE 0 TO 2; SIGNAL o_hburst,o_hbcpt : natural RANGE 0 TO 31; @@ -485,6 +487,7 @@ ARCHITECTURE rtl OF ascal IS SIGNAL o_divstart : std_logic; SIGNAL o_divrun : std_logic; SIGNAL o_hacpt,o_vacpt : unsigned(11 DOWNTO 0); + SIGNAL o_vacptl : unsigned(1 DOWNTO 0); ----------------------------------------------------------------------------- FUNCTION shift_ishift(shift : unsigned(0 TO 119); @@ -705,8 +708,10 @@ ARCHITECTURE rtl OF ascal IS RETURN x; END FUNCTION; - SIGNAL o_h_frac2,o_v_frac : unsigned(FRAC-1 DOWNTO 0); + SIGNAL o_h_near_frac,o_v_near_frac : unsigned(FRAC-1 DOWNTO 0); + SIGNAL o_h_bil_frac,o_v_bil_frac : unsigned(FRAC-1 DOWNTO 0); SIGNAL o_h_bil_pix,o_v_bil_pix : type_pix; + SIGNAL o_h_near_pix,o_v_near_pix : type_pix; ----------------------------------------------------------------------------- -- Nearest + Bilinear + Sharp Bilinear @@ -718,6 +723,7 @@ ARCHITECTURE rtl OF ascal IS TYPE type_bil_t IS RECORD r,g,b : unsigned(8+FRAC DOWNTO 0); END RECORD; + FUNCTION bil_calc(f : unsigned(FRAC-1 DOWNTO 0); p : arr_pix(0 TO 3)) RETURN type_bil_t IS VARIABLE fp,fn : unsigned(FRAC DOWNTO 0); @@ -725,7 +731,7 @@ ARCHITECTURE rtl OF ascal IS VARIABLE x : type_bil_t; CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0'); BEGIN - fp:='0' & f; + fp:=('0' & f) + (Z & f(FRAC-1)); fn:=('1' & Z) - fp; u:=p(2).r * fp + p(1).r * fn; x.r:=u; @@ -735,7 +741,27 @@ ARCHITECTURE rtl OF ascal IS x.b:=u; RETURN x; END FUNCTION; + + FUNCTION near_calc(f : unsigned(FRAC-1 DOWNTO 0); + p : arr_pix(0 TO 3)) RETURN type_bil_t IS + VARIABLE fp,fn : unsigned(FRAC DOWNTO 0); + VARIABLE u : unsigned(8+FRAC DOWNTO 0); + VARIABLE x : type_bil_t; + CONSTANT Z : unsigned(FRAC-1 DOWNTO 0):=(OTHERS =>'0'); + BEGIN + IF f(FRAC-1)='0' THEN + x.r := '0' & p(1).r & Z; + x.g := '0' & p(1).g & Z; + x.b := '0' & p(1).b & Z; + ELSE + x.r := '0' & p(2).r & Z; + x.g := '0' & p(2).g & Z; + x.b := '0' & p(2).b & Z; + END IF; + RETURN x; + END FUNCTION; SIGNAL o_h_bil_t,o_v_bil_t : type_bil_t; + SIGNAL o_h_near_t,o_v_near_t : type_bil_t; SIGNAL i_h_bil_t : type_bil_t; ----------------------------------------------------------------------------- @@ -1864,35 +1890,51 @@ BEGIN o_state<=sHSYNC; o_hsp<='0'; END IF; + o_prim<=true; + o_vcarrym<=false; -------------------------------------------------- WHEN sHSYNC => - dif_v:=(o_vacc_next - 2*o_vsize + 16384) MOD 16384; + dif_v :=(o_vacc_next - 2*o_vsize + 16384) MOD 16384; + IF o_prim THEN + IF dif_v>=8192 THEN + o_vacc <=o_vacc_next; + ELSE + o_vacc <=dif_v; + END IF; + END IF; IF dif_v>=8192 THEN - o_vacc <=o_vacc_next; o_vacc_next<=(o_vacc_next + 2*o_ivsize) MOD 8192; vcarry_v:=false; ELSE - o_vacc <=dif_v; - o_vacc_next<=(dif_v + 2*o_ivsize + 8192) MOD 8192; + o_vacc_next<=dif_v; vcarry_v:=true; END IF; - o_divstart<='1'; + IF o_vcpt_pre2=o_vmin THEN o_vacc <=o_vacc_ini; o_vacc_next<=o_vacc_ini + 2*o_ivsize; - o_vacpt<=x"001"; + o_vacpt <=x"001"; + o_vacptl<="01"; vcarry_v:=false; END IF; IF vcarry_v THEN o_vacpt<=o_vacpt+1; END IF; + IF vcarry_v AND o_prim THEN + o_vacptl<=o_vacptl+1; + END IF; + o_vcarrym <= o_vcarrym OR vcarry_v; + o_prim <= false; o_hbcpt<=0; -- Clear burst counter on line - IF (o_vpe='1' AND vcarry_v) OR o_fload>0 THEN - o_state<=sREAD; - ELSE - o_state<=sDISP; + o_divstart<=to_std_logic(NOT vcarry_v); + IF NOT vcarry_v OR o_fload>0 THEN + IF (o_vpe='1' AND o_vcarrym) OR o_fload>0 THEN + o_state<=sREAD; + ELSE + o_state<=sDISP; + END IF; END IF; WHEN sREAD => @@ -1942,7 +1984,7 @@ BEGIN o_alt<="0100"; ELSE o_adrs<=to_unsigned(o_adrs_pre + (o_hbcpt * N_BURST),32); - o_alt<=altx(o_vacpt(1 DOWNTO 0) + 1); + o_alt<=altx(o_vacptl + 1); END IF; END IF; @@ -2276,33 +2318,38 @@ BEGIN o_hpixq<=(o_hpix3,o_hpix2,o_hpix1,o_hpix0); - -- NEAREST / BILINEAR / SHARP BILINEAR --------------- + -- NEAREST ------------------------------------------- + -- C2 + o_h_near_frac<=near_frac(o_hfrac2); + + -- C3 + o_h_near_t<=near_calc(o_h_near_frac,o_hpixq); + + -- C4 : Nearest + o_h_near_pix.r<=o_h_near_t.r(7+FRAC DOWNTO FRAC); + o_h_near_pix.g<=o_h_near_t.g(7+FRAC DOWNTO FRAC); + o_h_near_pix.b<=o_h_near_t.b(7+FRAC DOWNTO FRAC); + + -- BILINEAR / SHARP BILINEAR --------------- -- C1 : Pre-calc Sharp Bilinear o_h_sbil_t<=sbil_frac1(o_hfrac1); -- C2 : Select - o_h_frac2<=(OTHERS =>'0'); - CASE o_hmode(1 DOWNTO 0) IS - WHEN "00" => -- Nearest - IF MASK(MASK_NEAREST)='1' THEN - o_h_frac2<=near_frac(o_hfrac2); - END IF; - WHEN "01" => -- Bilinear - IF MASK(MASK_BILINEAR)='1' THEN - o_h_frac2<=bil_frac(o_hfrac2); - END IF; - WHEN "10" => -- Sharp Bilinear - IF MASK(MASK_SHARP_BILINEAR)='1' THEN - o_h_frac2<=sbil_frac2(o_hfrac2,o_h_sbil_t); - END IF; - WHEN OTHERS => - NULL; - END CASE; - + o_h_bil_frac<=(OTHERS =>'0'); + IF o_hmode(0)='1' THEN -- Bilinear + IF MASK(MASK_BILINEAR)='1' THEN + o_h_bil_frac<=bil_frac(o_hfrac2); + END IF; + ELSE -- Sharp Bilinear + IF MASK(MASK_SHARP_BILINEAR)='1' THEN + o_h_bil_frac<=sbil_frac2(o_hfrac2,o_h_sbil_t); + END IF; + END IF; + -- C3 : Opposite frac - o_h_bil_t<=bil_calc(o_h_frac2,o_hpixq); + o_h_bil_t<=bil_calc(o_h_bil_frac,o_hpixq); - -- C4 : Nearest / Bilinear / Sharp Bilinear + -- C4 : Bilinear / Sharp Bilinear o_h_bil_pix.r<=bound(o_h_bil_t.r,8+FRAC); o_h_bil_pix.g<=bound(o_h_bil_t.g,8+FRAC); o_h_bil_pix.b<=bound(o_h_bil_t.b,8+FRAC); @@ -2340,9 +2387,12 @@ BEGIN o_ldw<=(x"00",x"00",x"00"); CASE o_hmode(2 DOWNTO 0) IS - WHEN "000" | "001" | "010" => -- Nearest | Bilinear | Sharp Bilinear - IF MASK(MASK_NEAREST)='1' OR - MASK(MASK_BILINEAR)='1' OR + WHEN "000" => -- Nearest + IF MASK(MASK_NEAREST)='1' THEN + o_ldw<=o_h_near_pix; + END IF; + WHEN "001" | "010" => -- Bilinear | Sharp Bilinear + IF MASK(MASK_BILINEAR)='1' OR MASK(MASK_SHARP_BILINEAR)='1' THEN o_ldw<=o_h_bil_pix; END IF; @@ -2441,7 +2491,7 @@ BEGIN -- CYCLE 2 ----------------------------------------- -- Lines reordering - CASE o_vacpt(1 DOWNTO 0) IS + CASE o_vacptl IS WHEN "10" => pixq_v:=(o_ldr0,o_ldr1,o_ldr2,o_ldr3); WHEN "11" => pixq_v:=(o_ldr1,o_ldr2,o_ldr3,o_ldr0); WHEN "00" => pixq_v:=(o_ldr2,o_ldr3,o_ldr0,o_ldr1); @@ -2461,31 +2511,37 @@ BEGIN o_vpixq1<=o_vpixq; - -- NEAREST / BILINEAR / SHARP BILINEAR ------------- + -- NEAREST ----------------------------------------- + -- C4 + o_v_near_frac<=near_frac(o_vfrac); + + -- C5 + o_v_near_t<=near_calc(o_v_near_frac,o_vpixq1); + + -- C6 : Nearest + o_v_near_pix.r<=o_v_near_t.r(7+FRAC DOWNTO FRAC); + o_v_near_pix.g<=o_v_near_t.g(7+FRAC DOWNTO FRAC); + o_v_near_pix.b<=o_v_near_t.b(7+FRAC DOWNTO FRAC); + + -- BILINEAR / SHARP BILINEAR ----------------------- -- C3 : Pre-calc Sharp Bilinear o_v_sbil_t<=sbil_frac1(o_vfrac); -- C4 : Select - o_v_frac<=(OTHERS =>'0'); - CASE o_vmode(1 DOWNTO 0) IS - WHEN "00" => -- Nearest - IF MASK(MASK_NEAREST)='1' THEN - o_v_frac<=near_frac(o_vfrac); - END IF; - WHEN "01" => -- Bilinear - IF MASK(MASK_BILINEAR)='1' THEN - o_v_frac<=bil_frac(o_vfrac); - END IF; - WHEN "10" => -- Sharp Bilinear - IF MASK(MASK_SHARP_BILINEAR)='1' THEN - o_v_frac<=sbil_frac2(o_vfrac,o_v_sbil_t); - END IF; - WHEN OTHERS => NULL; - END CASE; + o_v_bil_frac<=(OTHERS =>'0'); + IF o_vmode(0)='1' THEN -- Bilinear + IF MASK(MASK_BILINEAR)='1' THEN + o_v_bil_frac<=bil_frac(o_vfrac); + END IF; + ELSE -- Sharp Bilinear + IF MASK(MASK_SHARP_BILINEAR)='1' THEN + o_v_bil_frac<=sbil_frac2(o_vfrac,o_v_sbil_t); + END IF; + END IF; - o_v_bil_t<=bil_calc(o_v_frac,o_vpixq1); + o_v_bil_t<=bil_calc(o_v_bil_frac,o_vpixq1); - -- C6 : Nearest / Bilinear / Sharp Bilinear + -- C6 : Bilinear / Sharp Bilinear o_v_bil_pix.r<=bound(o_v_bil_t.r,8+FRAC); o_v_bil_pix.g<=bound(o_v_bil_t.g,8+FRAC); o_v_bil_pix.b<=bound(o_v_bil_t.b,8+FRAC); @@ -2524,11 +2580,17 @@ BEGIN o_r<=x"00"; o_g<=x"00"; o_b<=x"00"; + o_brd<= not o_pev(5); CASE o_vmode(2 DOWNTO 0) IS - WHEN "000" | "001" | "010" => -- Nearest | Bilinear | Sharp Bilinear - IF MASK(MASK_NEAREST)='1' OR - MASK(MASK_BILINEAR)='1' OR + WHEN "000" => -- Nearest + IF MASK(MASK_NEAREST)='1' THEN + o_r<=o_v_near_pix.r; + o_g<=o_v_near_pix.g; + o_b<=o_v_near_pix.b; + END IF; + WHEN "001" | "010" => -- Bilinear | Sharp Bilinear + IF MASK(MASK_BILINEAR)='1' OR MASK(MASK_SHARP_BILINEAR)='1' THEN o_r<=o_v_bil_pix.r; o_g<=o_v_bil_pix.g; diff --git a/sys/hps_io.sv b/sys/hps_io.sv index 6b13941..0e015c8 100644 --- a/sys/hps_io.sv +++ b/sys/hps_io.sv @@ -24,13 +24,13 @@ // Use buffer to access SD card. It's time-critical part. // // WIDE=1 for 16 bit file I/O -// VDNUM 1..4 +// VDNUM 1..10 // BLKSZ 0..7: 0 = 128, 1 = 256, 2 = 512(default), .. 7 = 16384 // module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1, BLKSZ=2, PS2WE=0) ( input clk_sys, - inout [45:0] HPS_BUS, + inout [47:0] HPS_BUS, // buttons up to 32 output reg [31:0] joystick_0, @@ -316,7 +316,7 @@ always@(posedge clk_sys) begin : uio_block 'h0X17, 'h0X18: begin sd_ack <= disk[VD:0]; sdn_ack <= io_din[11:8]; end 'h29: io_dout <= {4'hA, stflg}; - 'h2B: io_dout <= 1; + 'h2B: io_dout <= {HPS_BUS[47:46],4'b0010}; 'h2F: io_dout <= 1; 'h32: io_dout <= gamma_bus[21]; 'h36: begin io_dout <= info_n; info_n <= 0; end diff --git a/sys/shadowmask.sv b/sys/shadowmask.sv index 3d2a071..572679c 100644 --- a/sys/shadowmask.sv +++ b/sys/shadowmask.sv @@ -1,144 +1,136 @@ module shadowmask ( - input clk, - input clk_sys, - - input cmd_wr, - input [15:0] cmd_in, + input clk, + input clk_sys, - input [23:0] din, - input hs_in,vs_in, - input de_in, + input cmd_wr, + input [15:0] cmd_in, - output reg [23:0] dout, - output reg hs_out,vs_out, - output reg de_out + input [23:0] din, + input hs_in,vs_in, + input de_in, + input brd_in, + input enable, + + output reg [23:0] dout, + output reg hs_out,vs_out, + output reg de_out ); -//These are unused right now -parameter MaxPatternWidth = 8; -parameter MaxPatternHeight = 4; - -reg [3:0] hcount; -reg [3:0] vcount; - -reg [3:0] hmax; -reg [3:0] vmax; -reg [3:0] hmax2; -reg [3:0] vmax2; - -reg [2:0] hindex; -reg [2:0] vindex; -reg [2:0] hindex2; -reg [2:0] vindex2; - -reg mask_2x; -reg mask_rotate; -reg mask_enable; +reg [4:0] hmax; +reg [4:0] vmax; +reg [7:0] mask_idx; +reg mask_2x; +reg mask_rotate; +reg mask_enable; +reg [10:0] mask_lut[256]; always @(posedge clk) begin + reg [4:0] hcount; + reg [4:0] vcount; + reg [3:0] hindex; + reg [3:0] vindex; + reg [4:0] hmax2; + reg [4:0] vmax2; + reg [11:0] pcnt,pde; + reg old_hs, old_vs, old_brd; + reg next_v; - reg old_hs, old_vs; - old_hs <= hs_in; - old_vs <= vs_in; - hcount <= hcount + 4'b1; + old_hs <= hs_in; + old_vs <= vs_in; + old_brd<= brd_in; - // hcount and vcount counts pixel rows and columns - // hindex and vindex half the value of the counters for double size patterns - // hindex2, vindex2 swap the h and v counters for drawing rotated masks - hindex <= mask_2x ? hcount[3:1] : hcount[2:0]; - vindex <= mask_2x ? vcount[3:1] : vcount[2:0]; - hindex2 <= mask_rotate ? vindex : hindex; - vindex2 <= mask_rotate ? hindex : vindex; + // hcount and vcount counts pixel rows and columns + // hindex and vindex half the value of the counters for double size patterns + // hindex2, vindex2 swap the h and v counters for drawing rotated masks + hindex <= mask_2x ? hcount[4:1] : hcount[3:0]; + vindex <= mask_2x ? vcount[4:1] : vcount[3:0]; + mask_idx <= mask_rotate ? {hindex,vindex} : {vindex,hindex}; - // hmax and vmax store these sizes - // hmax2 and vmax2 swap the values to handle rotation - hmax2 <= mask_rotate ? ( vmax << mask_2x ) : ( hmax << mask_2x ); - vmax2 <= mask_rotate ? ( hmax << mask_2x ) : ( vmax << mask_2x ); + // hmax and vmax store these sizes + // hmax2 and vmax2 swap the values to handle rotation + hmax2 <= ((mask_rotate ? vmax : hmax) << mask_2x) | mask_2x; + vmax2 <= ((mask_rotate ? hmax : vmax) << mask_2x) | mask_2x; - if((old_vs && ~vs_in)) vcount <= 4'b0; - if(old_hs && ~hs_in) begin - vcount <= vcount + 4'b1; - hcount <= 4'b0; - if (vcount == (vmax2 + mask_2x)) vcount <= 4'b0; - end + pcnt <= pcnt+1'd1; + if(old_brd && ~brd_in) pde <= pcnt-4'd3; - if (hcount == (hmax2 + mask_2x)) hcount <= 4'b0; + hcount <= hcount+1'b1; + if(hcount == hmax2 || pde == pcnt) hcount <= 0; + + if(~old_brd && brd_in) next_v <= 1; + if(old_vs && ~vs_in) vcount <= 0; + if(old_hs && ~hs_in) begin + vcount <= vcount + next_v; + next_v <= 0; + pcnt <= 0; + if (vcount == vmax2) vcount <= 0; + end end -wire [7:0] r,g,b; -assign {r,g,b} = din; +reg [4:0] r_mul, g_mul, b_mul; // 1.4 fixed point multipliers +always @(posedge clk) begin + reg [10:0] lut; -reg [23:0] d; + lut <= mask_lut[mask_idx]; -// Each element of mask_lut is 3 bits. 1 each for R,G,B -// Red is 100 = 4 -// Green is 010 = 2 -// Blue is 001 = 1 -// Magenta is 101 = 5 -// Gray is 000 = 0 -// White is 111 = 7 -// Yellow is 110 = 6 -// Cyan is 011 = 3 - -// So the Pattern -// r,r,g,g,b,b -// r,r,g,g,b,b -// g,b,b,r,r,g -// g,b,b,r,r,g -// -// is -// 4,4,2,2,1,1,5,3 -// 4,4,2,2,1,1,0,0, -// 2,1,1,4,4,2,0,0 -// 2,1,1,4,4,2,0,0 -// -// note that all rows are padded to 8 numbers although every pattern is 6 pixels wide -// The last two entries of the top row "5,3" are the size of the mask. In this case -// "5,3," means this pattern is 6x4 pixels. - - -reg [2:0] mask_lut[64]; + r_mul <= 5'b10000; g_mul <= 5'b10000; b_mul <= 5'b10000; // default 100% to all channels + if (mask_enable) begin + r_mul <= lut[10] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]}; + g_mul <= lut[9] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]}; + b_mul <= lut[8] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]}; + end +end always @(posedge clk) begin + reg [11:0] vid; + reg [7:0] r1, g1, b1; + reg [7:0] r2, g2, b2; + reg [7:0] r3_x, g3_x, b3_x; // 6.25% + 12.5% + reg [8:0] r3_y, g3_y, b3_y; // 25% + 50% + 100% + reg [8:0] r4, g4, b4; - reg rbit, gbit, bbit; - reg [23:0] dout1, dout2; - reg de1,de2,vs1,vs2,hs1,hs2; - reg [8:0] r2, g2, b2; //9 bits to handle overflow when we add to bright colors. - reg [7:0] r3, g3, b3; //These are the final colors. + // C1 - data input + {r1,g1,b1} <= din; + vid <= {vid[8:0],vs_in, hs_in, de_in}; - {rbit,gbit, bbit} = mask_lut[{vindex2[2:0],hindex2[2:0]}]; + // C2 - relax timings + {r2,g2,b2} <= {r1,g1,b1}; - // I add 12.5% of the Color value and then subrtact 50% if the mask should be dark - r2 <= r + {3'b0, r[7:3]} - (rbit ? 9'b0 : {2'b0, r[7:1]}); - g2 <= g + {3'b0, g[7:3]} - (gbit ? 9'b0 : {2'b0, g[7:1]}); - b2 <= b + {3'b0, b[7:3]} - (bbit ? 9'b0 : {2'b0, b[7:1]}); + // C3 - perform multiplications + r3_x <= ({4{r_mul[0]}} & r2[7:4]) + ({8{r_mul[1]}} & r2[7:3]); + r3_y <= ({6{r_mul[2]}} & r2[7:2]) + ({7{r_mul[3]}} & r2[7:1]) + ({9{r_mul[4]}} & r2[7:0]); + g3_x <= ({4{g_mul[0]}} & g2[7:4]) + ({8{g_mul[1]}} & g2[7:3]); + g3_y <= ({6{g_mul[2]}} & g2[7:2]) + ({7{g_mul[3]}} & g2[7:1]) + ({9{g_mul[4]}} & g2[7:0]); + b3_x <= ({4{b_mul[0]}} & b2[7:4]) + ({8{b_mul[1]}} & b2[7:3]); + b3_y <= ({6{b_mul[2]}} & b2[7:2]) + ({7{b_mul[3]}} & b2[7:1]) + ({9{b_mul[4]}} & b2[7:0]); - // Because a pixel can be brighter than 255 we have to clamp the value to 255. - r3 <= r2[8] ? 8'd255 : r2[7:0]; - g3 <= g2[8] ? 8'd255 : g2[7:0]; - b3 <= b2[8] ? 8'd255 : b2[7:0]; + // C4 - combine results + r4 <= r3_x + r3_y; + g4 <= g3_x + g3_y; + b4 <= b3_x + b3_y; - // I don't know how to keep the color aligned with the sync to avoid a shift. - // This code is left over from the original hdmi scanlines code. - dout <= ~mask_enable ? {r,g,b} : {r3 ,g3, b3}; - vs_out <= mask_enable ? vs2 : vs_in; vs2 <= vs1; vs1 <= vs_in; - hs_out <= mask_enable ? hs2 : hs_in; hs2 <= hs1; hs1 <= hs_in; - de_out <= mask_enable ? de2 : de_in; de2 <= de1; de1 <= de_in; + // C5 - clamp and output + dout <= {{8{r4[8]}} | r4[7:0], {8{g4[8]}} | g4[7:0], {8{b4[8]}} | b4[7:0]}; + {vs_out,hs_out,de_out} <= vid[11:9]; end -// 000_000_000_000_000_ +// clock in mask commands always @(posedge clk_sys) begin - if (cmd_wr) begin - case(cmd_in[15:13]) - 3'b000: {mask_rotate, mask_2x, mask_enable} <= cmd_in[2:0]; - 3'b001: vmax <= cmd_in[3:0]; - 3'b010: hmax <= cmd_in[3:0]; - 3'b011: mask_lut[cmd_in[9:4]] <= cmd_in[2:0]; - endcase - end + reg m_enable; + reg [7:0] idx; + + if (cmd_wr) begin + case(cmd_in[15:13]) + 3'b000: begin {m_enable, mask_rotate, mask_2x} <= cmd_in[3:1]; idx <= 0; end + 3'b001: vmax <= cmd_in[3:0]; + 3'b010: hmax <= cmd_in[3:0]; + 3'b011: begin mask_lut[idx] <= cmd_in[10:0]; idx <= idx + 1'd1; end + endcase + end + + mask_enable <= m_enable & enable; end endmodule diff --git a/sys/sys_top.v b/sys/sys_top.v index 2038cbb..5275d0b 100644 --- a/sys/sys_top.v +++ b/sys/sys_top.v @@ -295,7 +295,7 @@ reg [31:0] cfg_custom_p2; reg [4:0] vol_att; initial vol_att = 5'b11111; -reg [6:0] coef_addr; +reg [8:0] coef_addr; reg [8:0] coef_data; reg coef_wr = 0; @@ -335,7 +335,10 @@ always@(posedge clk_sys) begin old_strobe <= io_strobe; coef_wr <= 0; + +`ifndef MISTER_DEBUG_NOHDMI shadowmask_wr <= 0; +`endif if(~io_uio) begin has_cmd <= 0; @@ -364,6 +367,7 @@ always@(posedge clk_sys) begin end end else begin + cnt <= cnt + 1'd1; if(cmd == 1) begin cfg <= io_din; cfg_set <= 1; @@ -371,7 +375,6 @@ always@(posedge clk_sys) begin end if(cmd == 'h20) begin cfg_set <= 0; - cnt <= cnt + 1'd1; if(cnt<8) begin case(cnt[2:0]) 0: if(WIDTH != io_din[11:0]) WIDTH <= io_din[11:0]; @@ -403,7 +406,6 @@ always@(posedge clk_sys) begin end end if(cmd == 'h2F) begin - cnt <= cnt + 1'd1; case(cnt[3:0]) 0: {LFB_EN,LFB_FLT,LFB_FMT} <= {io_din[15], io_din[14], io_din[5:0]}; 1: LFB_BASE[15:0] <= io_din[15:0]; @@ -420,12 +422,14 @@ always@(posedge clk_sys) begin if(cmd == 'h25) {led_overtake, led_state} <= io_din; if(cmd == 'h26) vol_att <= io_din[4:0]; if(cmd == 'h27) VSET <= io_din[11:0]; - if(cmd == 'h2A) {coef_wr,coef_addr,coef_data} <= {1'b1,io_din}; + if(cmd == 'h2A) begin + if(cnt[0]) {coef_wr,coef_data} <= {1'b1,io_din[8:0]}; + else coef_addr <= io_din[8:0]; + end if(cmd == 'h2B) scaler_flt <= io_din[2:0]; if(cmd == 'h37) {FREESCALE,HSET} <= {io_din[15],io_din[11:0]}; if(cmd == 'h38) vs_line <= io_din[11:0]; if(cmd == 'h39) begin - cnt <= cnt + 1'd1; case(cnt[3:0]) 0: acx_att <= io_din[4:0]; 1: aflt_rate[15:0] <= io_din; @@ -445,7 +449,6 @@ always@(posedge clk_sys) begin endcase end if(cmd == 'h3A) begin - cnt <= cnt + 1'd1; case(cnt[3:0]) 0: arc1x <= io_din[12:0]; 1: arc1y <= io_din[12:0]; @@ -453,7 +456,9 @@ always@(posedge clk_sys) begin 3: arc2y <= io_din[12:0]; endcase end +`ifndef MISTER_DEBUG_NOHDMI if(cmd == 'h3E) {shadowmask_wr,shadowmask_data} <= {1'b1, io_din}; +`endif end end @@ -620,7 +625,7 @@ wire [15:0] vbuf_byteenable; wire vbuf_write; wire [23:0] hdmi_data; -wire hdmi_vs, hdmi_hs, hdmi_de, hdmi_vbl; +wire hdmi_vs, hdmi_hs, hdmi_de, hdmi_vbl, hdmi_brd; wire freeze; `ifndef MISTER_DEBUG_NOHDMI @@ -636,6 +641,7 @@ ascal .PALETTE2("false"), `endif `endif + .FRAC(6), .N_DW(128), .N_AW(28) ) @@ -669,6 +675,7 @@ ascal .o_vs (hdmi_vs), .o_de (hdmi_de), .o_vbl (hdmi_vbl), + .o_brd (hdmi_brd), .o_lltune (lltune), .htotal (WIDTH + HFP + HBP + HS), .hsstart (WIDTH + HFP), @@ -1051,36 +1058,18 @@ cyclonev_hps_interface_peripheral_i2c hdmi_i2c ); `ifndef MISTER_DEBUG_NOHDMI -wire [23:0] hdmi_data_sl; -wire hdmi_de_sl, hdmi_vs_sl, hdmi_hs_sl; `ifdef MISTER_FB reg dis_output; always @(posedge clk_hdmi) begin reg dis; - dis <= fb_force_blank; + dis <= fb_force_blank & ~LFB_EN; dis_output <= dis; end `else wire dis_output = 0; `endif -scanlines #(1) HDMI_scanlines -( - .clk(clk_hdmi), - - .scanlines(scanlines), - .din(dis_output ? 24'd0 : hdmi_data), - .hs_in(hdmi_hs), - .vs_in(hdmi_vs), - .de_in(hdmi_de), - - .dout(hdmi_data_sl), - .hs_out(hdmi_hs_sl), - .vs_out(hdmi_vs_sl), - .de_out(hdmi_de_sl) -); - wire [23:0] hdmi_data_mask; wire hdmi_de_mask, hdmi_vs_mask, hdmi_hs_mask; @@ -1095,11 +1084,13 @@ shadowmask HDMI_shadowmask .cmd_wr(shadowmask_wr), .cmd_in(shadowmask_data), - .din(hdmi_data_sl), - .hs_in(hdmi_hs_sl), - .vs_in(hdmi_vs_sl), - .de_in(hdmi_de_sl), - + .din(dis_output ? 24'd0 : hdmi_data), + .hs_in(hdmi_hs), + .vs_in(hdmi_vs), + .de_in(hdmi_de), + .brd_in(hdmi_brd), + .enable(~LFB_EN), + .dout(hdmi_data_mask), .hs_out(hdmi_hs_mask), .vs_out(hdmi_vs_mask), @@ -1489,12 +1480,12 @@ wire [6:0] user_out, user_in; assign clk_ihdmi= clk_vid; assign ce_hpix = ce_pix; -assign hr_out = r_out; -assign hg_out = g_out; -assign hb_out = b_out; -assign hhs_fix = hs_fix; -assign hvs_fix = vs_fix; -assign hde_emu = de_emu; +assign hr_out = vga_data_sl[23:16]; +assign hg_out = vga_data_sl[15:8]; +assign hb_out = vga_data_sl[7:0]; +assign hhs_fix = vga_hs_sl; +assign hvs_fix = vga_vs_sl; +assign hde_emu = vga_de_sl; wire uart_dtr; wire uart_dsr; @@ -1535,7 +1526,7 @@ emu emu ( .CLK_50M(FPGA_CLK2_50), .RESET(reset), - .HPS_BUS({f1, HDMI_TX_VS, + .HPS_BUS({scanlines,f1, HDMI_TX_VS, clk_100m, clk_ihdmi, ce_hpix, hde_emu, hhs_fix, hvs_fix, io_wait, clk_sys, io_fpga, io_uio, io_strobe, io_wide, io_din, io_dout}), diff --git a/verilator/Makefile b/verilator/Makefile index a667f05..ad745e0 100644 --- a/verilator/Makefile +++ b/verilator/Makefile @@ -1,10 +1,4 @@ -# -# -# - V = verilator -#V = /usr/local/bin/verilator -#V = /usr/local/src/verilator-3.876/bin/verilator COSIM = n TOP = --top-module emu @@ -49,27 +43,30 @@ LDFLAGS = $(LIBS) EXE = ./obj_dir/Vemu V_OPT = -O3 --x-assign fast --x-initial fast --noassert CC_OPT = -O -#V_OPT = -#CC_OPT = V_SRC = \ sim.v \ $(RTL)/system.v \ + $(RTL)/charmap.v \ + $(RTL)/sprite_engine.v \ + $(RTL)/generic_timer.v \ $(RTL)/dpram.v \ + $(RTL)/dpram_w1r2.v \ $(RTL)/spram.v \ $(RTL)/JTFRAME/jtframe_vtimer.v \ $(RTL)/JTFRAME/jtframe_cen24.v \ -../rtl/tv80/tv80_core.v \ -../rtl/tv80/tv80_alu.v \ -../rtl/tv80/tv80_mcode.v \ -../rtl/tv80/tv80_reg.v \ -../rtl/tv80/tv80n.v \ -../rtl/tv80/tv80s.v + $(RTL)/tv80/tv80_core.v \ + $(RTL)/tv80/tv80_alu.v \ + $(RTL)/tv80/tv80_mcode.v \ + $(RTL)/tv80/tv80_reg.v \ + $(RTL)/tv80/tv80n.v \ + $(RTL)/tv80/tv80s.v C_SRC = \ sim_main.cpp \ -sim/sim_bus.cpp sim/sim_clock.cpp sim/sim_console.cpp sim/sim_video.cpp sim/sim_input.cpp \ - sim/imgui/imgui_impl_sdl.cpp sim/imgui/imgui_impl_opengl2.cpp sim/imgui/imgui_draw.cpp sim/imgui/imgui_widgets.cpp sim/imgui/imgui_tables.cpp sim/imgui/imgui.cpp sim/imgui/ImGuiFileDialog.cpp + sim/sim_bus.cpp sim/sim_clock.cpp sim/sim_console.cpp sim/sim_video.cpp sim/sim_input.cpp \ + sim/imgui/imgui_impl_sdl.cpp sim/imgui/imgui_impl_opengl2.cpp sim/imgui/imgui_draw.cpp sim/imgui/imgui_widgets.cpp sim/imgui/imgui_tables.cpp sim/imgui/imgui.cpp sim/imgui/ImGuiFileDialog.cpp + VOUT = obj_dir/Vemu.cpp all: $(EXE) diff --git a/verilator/imgui.ini b/verilator/imgui.ini index ad83525..9cc21df 100644 --- a/verilator/imgui.ini +++ b/verilator/imgui.ini @@ -44,8 +44,8 @@ Size=553,169 Collapsed=0 [Window][WKRAM Editor] -Pos=5,624 -Size=549,372 +Pos=508,580 +Size=502,445 Collapsed=0 [Window][CHRAM Editor] @@ -63,6 +63,86 @@ Pos=60,60 Size=639,314 Collapsed=0 +[Window][Simulation control] +Pos=0,0 +Size=500,150 +Collapsed=0 + +[Window][Debug log] +Pos=0,160 +Size=500,700 +Collapsed=0 + +[Window][Trace/VCD control] +Pos=0,870 +Size=500,150 +Collapsed=0 + +[Window][VGA output] +Pos=550,0 +Size=984,834 +Collapsed=0 + +[Window][BGCOLRAM Editor] +Pos=1007,573 +Size=552,444 +Collapsed=0 + +[Window][Palette ROM] +Pos=1031,593 +Size=550,120 +Collapsed=0 + +[Window][Sprite ROM] +Pos=554,746 +Size=472,313 +Collapsed=0 + +[Window][Character ROM] +Pos=1025,313 +Size=565,266 +Collapsed=0 + +[Window][Sprite RAM] +Pos=-40,867 +Size=536,203 +Collapsed=0 + +[Window][Sprite Linebuffer RAM] +Pos=1029,720 +Size=586,345 +Collapsed=0 + +[Window][Sprite Collision Buffer RAM] +Pos=533,609 +Size=795,414 +Collapsed=0 + +[Window][Sprite Collision Buffer RAM A] +Pos=557,837 +Size=429,170 +Collapsed=0 + +[Window][Sprite Collision Buffer RAM B] +Pos=-14,894 +Size=411,493 +Collapsed=0 + +[Window][Sprite Collision RAM ] +Pos=995,857 +Size=549,150 +Collapsed=0 + +[Window][Sprite Debug RAM] +Pos=972,32 +Size=598,698 +Collapsed=0 + +[Window][Sound ROM] +Pos=550,840 +Size=780,231 +Collapsed=0 + [Table][0x5E7B4F09,4] RefScale=13 Column 0 Sort=0v diff --git a/verilator/sim.v b/verilator/sim.v index 8ba5cd9..fbd5b09 100644 --- a/verilator/sim.v +++ b/verilator/sim.v @@ -1,10 +1,10 @@ `timescale 1ns / 1ps /*============================================================================ - Input Test - Verilator emu module + Aznable (custom 8-bit computer system) - Verilator emu module Author: Jim Gregory - https://github.com/JimmyStones/ - Version: 1.0 - Date: 2021-07-12 + Version: 1.1 + Date: 2021-10-17 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 @@ -24,6 +24,7 @@ module emu ( input clk_sys, input reset, + input menu, input [31:0] joystick_0, input [31:0] joystick_1, @@ -80,8 +81,11 @@ module emu ( output VGA_HB, output VGA_VB, - input ioctl_download, - input ioctl_wr, + output [15:0] AUDIO_L, + output [15:0] AUDIO_R, + + input ioctl_download, + input ioctl_wr, input [24:0] ioctl_addr, input [7:0] ioctl_dout, input [7:0] ioctl_index, @@ -89,28 +93,52 @@ module emu ( ); // Clock divider from JTFRAME -wire ce_pix; +wire ce_6; +wire ce_2; /* verilator lint_off PINMISSING */ jtframe_cen24 divider ( .clk(clk_sys), - .cen12(ce_pix), // <-- dodgy video speed for faster simulation, will cause bearable char map corruption - //.cen4(ce_pix) // <-- correct video speed + .cen12(ce_6), // <-- dodgy video speed for faster simulation, will cause graphical corruption + //.cen6(ce_6), // <-- correct video speed + .cen2(ce_2) ); /* verilator lint_on PINMISSING */ +// Debug defines +`define DEBUG_SIMULATION + +wire m_pause = joystick_0[8]; +// PAUSE SYSTEM +wire pause_cpu; +wire [7:0] r,g,b; +wire [23:0] rgb_out; +assign VGA_R = rgb_out[23:16]; +assign VGA_G = rgb_out[15:8]; +assign VGA_B = rgb_out[7:0]; +pause #(8,8,8,24) pause ( + .*, + .OSD_STATUS(), + .user_button(m_pause), + .pause_request(), + .options(2'b0) +); + system system( - .clk_sys(clk_sys), - .ce_pix(ce_pix), + .clk_24(clk_sys), + .ce_6(ce_6), + .ce_2(ce_2), .reset(reset | ioctl_download), + .pause(pause_cpu), + .menu(menu), .VGA_HS(VGA_HS), .VGA_VS(VGA_VS), - .VGA_R(VGA_R), - .VGA_G(VGA_G), - .VGA_B(VGA_B), + .VGA_R(r), + .VGA_G(g), + .VGA_B(b), .VGA_HB(VGA_HB), .VGA_VB(VGA_VB), - .dn_addr(ioctl_addr[13:0]), + .dn_addr(ioctl_addr[16:0]), .dn_data(ioctl_dout), .dn_wr(ioctl_wr), .dn_index(ioctl_index), @@ -122,7 +150,9 @@ system system( .spinner({7'b0,spinner_5,7'b0,spinner_4,7'b0,spinner_3,7'b0,spinner_2,7'b0,spinner_1,7'b0,spinner_0}), .ps2_key(ps2_key), .ps2_mouse({ps2_mouse_ext,7'b0,ps2_mouse}), - .timestamp(timestamp) + .timestamp(timestamp), + .AUDIO_L(AUDIO_L), + .AUDIO_R(AUDIO_R) ); endmodule diff --git a/verilator/sim.vcxproj b/verilator/sim.vcxproj index c4fef73..2634058 100644 --- a/verilator/sim.vcxproj +++ b/verilator/sim.vcxproj @@ -20,12 +20,12 @@ Application true - v142 + v143 Application false - v142 + v143 @@ -68,18 +68,19 @@ - - - - - + + + + + + @@ -99,6 +100,14 @@ + + + true + + + true + + diff --git a/verilator/sim.vcxproj.filters b/verilator/sim.vcxproj.filters index c66dd21..3d4e6e7 100644 --- a/verilator/sim.vcxproj.filters +++ b/verilator/sim.vcxproj.filters @@ -66,6 +66,18 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + @@ -114,4 +126,12 @@ Header Files + + + Resource Files + + + Resource Files + + \ No newline at end of file diff --git a/verilator/sim/imgui/imgui.cpp b/verilator/sim/imgui/imgui.cpp index 18364c7..3b4c98e 100644 --- a/verilator/sim/imgui/imgui.cpp +++ b/verilator/sim/imgui/imgui.cpp @@ -3724,14 +3724,14 @@ void ImGui::UpdateMouseWheel() { StartLockWheelingWindow(window); const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); - const float scale = new_font_scale / window->FontWindowScale; + const float vga_scale = new_font_scale / window->FontWindowScale; window->FontWindowScale = new_font_scale; if (window == window->RootWindow) { - const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size; + const ImVec2 offset = window->Size * (1.0f - vga_scale) * (g.IO.MousePos - window->Pos) / window->Size; SetWindowPos(window, window->Pos + offset, 0); - window->Size = ImFloor(window->Size * scale); - window->SizeFull = ImFloor(window->SizeFull * scale); + window->Size = ImFloor(window->Size * vga_scale); + window->SizeFull = ImFloor(window->SizeFull * vga_scale); } return; } @@ -6929,12 +6929,12 @@ ImVec2 ImGui::GetFontTexUvWhitePixel() return GImGui->DrawListSharedData.TexUvWhitePixel; } -void ImGui::SetWindowFontScale(float scale) +void ImGui::SetWindowFontScale(float vga_scale) { - IM_ASSERT(scale > 0.0f); + IM_ASSERT(vga_scale > 0.0f); ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - window->FontWindowScale = scale; + window->FontWindowScale = vga_scale; g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize(); } @@ -10826,8 +10826,8 @@ void ImGui::DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - ImVec2 scale = bb.GetSize() / viewport->Size; - ImVec2 off = bb.Min - viewport->Pos * scale; + ImVec2 vga_scale = bb.GetSize() / viewport->Size; + ImVec2 off = bb.Min - viewport->Pos * vga_scale; float alpha_mul = 1.0f; window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul * 0.40f)); for (int i = 0; i != g.Windows.Size; i++) @@ -10838,8 +10838,8 @@ void ImGui::DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* ImRect thumb_r = thumb_window->Rect(); ImRect title_r = thumb_window->TitleBarRect(); - thumb_r = ImRect(ImFloor(off + thumb_r.Min * scale), ImFloor(off + thumb_r.Max * scale)); - title_r = ImRect(ImFloor(off + title_r.Min * scale), ImFloor(off + ImVec2(title_r.Max.x, title_r.Min.y) * scale) + ImVec2(0,5)); // Exaggerate title bar height + thumb_r = ImRect(ImFloor(off + thumb_r.Min * vga_scale), ImFloor(off + thumb_r.Max * vga_scale)); + title_r = ImRect(ImFloor(off + title_r.Min * vga_scale), ImFloor(off + ImVec2(title_r.Max.x, title_r.Min.y) * vga_scale) + ImVec2(0,5)); // Exaggerate title bar height thumb_r.ClipWithFull(bb); title_r.ClipWithFull(bb); const bool window_is_focused = (g.NavWindow && thumb_window->RootWindowForTitleBarHighlight == g.NavWindow->RootWindowForTitleBarHighlight); diff --git a/verilator/sim/imgui/imgui.h b/verilator/sim/imgui/imgui.h index a72ed3f..68802fa 100644 --- a/verilator/sim/imgui/imgui.h +++ b/verilator/sim/imgui/imgui.h @@ -340,7 +340,7 @@ namespace ImGui IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0, 0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / top-most. prefer using SetNextWindowFocus(). - IMGUI_API void SetWindowFontScale(float scale); // set font scale. Adjust IO.FontGlobalScale if you want to scale all windows. This is an old API! For correct scaling, prefer to reload font + rebuild ImFontAtlas + call style.ScaleAllSizes(). + IMGUI_API void SetWindowFontScale(float vga_scale); // set font scale. Adjust IO.FontGlobalScale if you want to scale all windows. This is an old API! For correct scaling, prefer to reload font + rebuild ImFontAtlas + call style.ScaleAllSizes(). IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond = 0); // set named window position. IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis. IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0); // set named window collapsed state @@ -2705,7 +2705,7 @@ struct ImFont // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable. // 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable. IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end = NULL, const char** remaining = NULL) const; // utf8 - IMGUI_API const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const; + IMGUI_API const char* CalcWordWrapPositionA(float vga_scale, const char* text, const char* text_end, float wrap_width) const; IMGUI_API void RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, ImWchar c) const; IMGUI_API void RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, bool cpu_fine_clip = false) const; diff --git a/verilator/sim/imgui/imgui_draw.cpp b/verilator/sim/imgui/imgui_draw.cpp index 8bebc6b..1a13b68 100644 --- a/verilator/sim/imgui/imgui_draw.cpp +++ b/verilator/sim/imgui/imgui_draw.cpp @@ -1863,7 +1863,7 @@ void ImGui::ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int ve { const ImVec2 size = b - a; const ImVec2 uv_size = uv_b - uv_a; - const ImVec2 scale = ImVec2( + const ImVec2 vga_scale = ImVec2( size.x != 0.0f ? (uv_size.x / size.x) : 0.0f, size.y != 0.0f ? (uv_size.y / size.y) : 0.0f); @@ -1874,12 +1874,12 @@ void ImGui::ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int ve const ImVec2 min = ImMin(uv_a, uv_b); const ImVec2 max = ImMax(uv_a, uv_b); for (ImDrawVert* vertex = vert_start; vertex < vert_end; ++vertex) - vertex->uv = ImClamp(uv_a + ImMul(ImVec2(vertex->pos.x, vertex->pos.y) - a, scale), min, max); + vertex->uv = ImClamp(uv_a + ImMul(ImVec2(vertex->pos.x, vertex->pos.y) - a, vga_scale), min, max); } else { for (ImDrawVert* vertex = vert_start; vertex < vert_end; ++vertex) - vertex->uv = uv_a + ImMul(ImVec2(vertex->pos.x, vertex->pos.y) - a, scale); + vertex->uv = uv_a + ImMul(ImVec2(vertex->pos.x, vertex->pos.y) - a, vga_scale); } } @@ -2445,14 +2445,14 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) src_tmp.PackRange.v_oversample = (unsigned char)cfg.OversampleV; // Gather the sizes of all rectangles we will need to pack (this loop is based on stbtt_PackFontRangesGatherRects) - const float scale = (cfg.SizePixels > 0) ? stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, cfg.SizePixels) : stbtt_ScaleForMappingEmToPixels(&src_tmp.FontInfo, -cfg.SizePixels); + const float vga_scale = (cfg.SizePixels > 0) ? stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, cfg.SizePixels) : stbtt_ScaleForMappingEmToPixels(&src_tmp.FontInfo, -cfg.SizePixels); const int padding = atlas->TexGlyphPadding; for (int glyph_i = 0; glyph_i < src_tmp.GlyphsList.Size; glyph_i++) { int x0, y0, x1, y1; const int glyph_index_in_font = stbtt_FindGlyphIndex(&src_tmp.FontInfo, src_tmp.GlyphsList[glyph_i]); IM_ASSERT(glyph_index_in_font != 0); - stbtt_GetGlyphBitmapBoxSubpixel(&src_tmp.FontInfo, glyph_index_in_font, scale * cfg.OversampleH, scale * cfg.OversampleV, 0, 0, &x0, &y0, &x1, &y1); + stbtt_GetGlyphBitmapBoxSubpixel(&src_tmp.FontInfo, glyph_index_in_font, vga_scale * cfg.OversampleH, vga_scale * cfg.OversampleV, 0, 0, &x0, &y0, &x1, &y1); src_tmp.Rects[glyph_i].w = (stbrp_coord)(x1 - x0 + padding + cfg.OversampleH - 1); src_tmp.Rects[glyph_i].h = (stbrp_coord)(y1 - y0 + padding + cfg.OversampleV - 1); total_surface += src_tmp.Rects[glyph_i].w * src_tmp.Rects[glyph_i].h; @@ -3292,7 +3292,7 @@ const ImFontGlyph* ImFont::FindGlyphNoFallback(ImWchar c) const return &Glyphs.Data[i]; } -const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const +const char* ImFont::CalcWordWrapPositionA(float vga_scale, const char* text, const char* text_end, float wrap_width) const { // Simple word-wrapping for English, not full-featured. Please submit failing cases! // FIXME: Much possible improvements (don't cut things like "word !", "word!!!" but cut within "word,,,,", more sensible support for punctuations, support for Unicode punctuations, etc.) @@ -3312,7 +3312,7 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c float line_width = 0.0f; float word_width = 0.0f; float blank_width = 0.0f; - wrap_width /= scale; // We work with unscaled widths to avoid scaling every characters + wrap_width /= vga_scale; // We work with unscaled widths to avoid scaling every characters const char* word_end = text; const char* prev_word_end = NULL; @@ -3397,7 +3397,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons text_end = text_begin + strlen(text_begin); // FIXME-OPT: Need to avoid this. const float line_height = size; - const float scale = size / FontSize; + const float vga_scale = size / FontSize; ImVec2 text_size = ImVec2(0, 0); float line_width = 0.0f; @@ -3413,7 +3413,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature. if (!word_wrap_eol) { - word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - line_width); + word_wrap_eol = CalcWordWrapPositionA(vga_scale, s, text_end, wrap_width - line_width); if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity. word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below } @@ -3463,7 +3463,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons continue; } - const float char_width = ((int)c < IndexAdvanceX.Size ? IndexAdvanceX.Data[c] : FallbackAdvanceX) * scale; + const float char_width = ((int)c < IndexAdvanceX.Size ? IndexAdvanceX.Data[c] : FallbackAdvanceX) * vga_scale; if (line_width + char_width >= max_width) { s = prev_s; @@ -3493,11 +3493,11 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col return; if (glyph->Colored) col |= ~IM_COL32_A_MASK; - float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f; + float vga_scale = (size >= 0.0f) ? (size / FontSize) : 1.0f; pos.x = IM_FLOOR(pos.x); pos.y = IM_FLOOR(pos.y); draw_list->PrimReserve(6, 4); - draw_list->PrimRectUV(ImVec2(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale), ImVec2(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col); + draw_list->PrimRectUV(ImVec2(pos.x + glyph->X0 * vga_scale, pos.y + glyph->Y0 * vga_scale), ImVec2(pos.x + glyph->X1 * vga_scale, pos.y + glyph->Y1 * vga_scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col); } // Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound. @@ -3514,8 +3514,8 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col if (y > clip_rect.w) return; - const float scale = size / FontSize; - const float line_height = FontSize * scale; + const float vga_scale = size / FontSize; + const float line_height = FontSize * vga_scale; const bool word_wrap_enabled = (wrap_width > 0.0f); const char* word_wrap_eol = NULL; @@ -3565,7 +3565,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature. if (!word_wrap_eol) { - word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - (x - pos.x)); + word_wrap_eol = CalcWordWrapPositionA(vga_scale, s, text_end, wrap_width - (x - pos.x)); if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity. word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below } @@ -3617,14 +3617,14 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col if (glyph == NULL) continue; - float char_width = glyph->AdvanceX * scale; + float char_width = glyph->AdvanceX * vga_scale; if (glyph->Visible) { // We don't do a second finer clipping test on the Y axis as we've already skipped anything before clip_rect.y and exit once we pass clip_rect.w - float x1 = x + glyph->X0 * scale; - float x2 = x + glyph->X1 * scale; - float y1 = y + glyph->Y0 * scale; - float y2 = y + glyph->Y1 * scale; + float x1 = x + glyph->X0 * vga_scale; + float x2 = x + glyph->X1 * vga_scale; + float y1 = y + glyph->Y0 * vga_scale; + float y2 = y + glyph->Y1 * vga_scale; if (x1 <= clip_rect.z && x2 >= clip_rect.x) { // Render a character @@ -3708,11 +3708,11 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col //----------------------------------------------------------------------------- // Render an arrow aimed to be aligned with text (p_min is a position in the same space text would be positioned). To e.g. denote expanded/collapsed state -void ImGui::RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale) +void ImGui::RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float vga_scale) { const float h = draw_list->_Data->FontSize * 1.00f; - float r = h * 0.40f * scale; - ImVec2 center = pos + ImVec2(h * 0.50f, h * 0.50f * scale); + float r = h * 0.40f * vga_scale; + ImVec2 center = pos + ImVec2(h * 0.50f, h * 0.50f * vga_scale); ImVec2 a, b, c; switch (dir) @@ -3759,7 +3759,7 @@ void ImGui::RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float draw_list->PathStroke(col, 0, thickness); } -void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow) +void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float vga_scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow) { if (mouse_cursor == ImGuiMouseCursor_None) return; @@ -3772,10 +3772,10 @@ void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, Im pos -= offset; ImTextureID tex_id = font_atlas->TexID; draw_list->PushTextureID(tex_id); - draw_list->AddImage(tex_id, pos + ImVec2(1, 0) * scale, pos + (ImVec2(1, 0) + size) * scale, uv[2], uv[3], col_shadow); - draw_list->AddImage(tex_id, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow); - draw_list->AddImage(tex_id, pos, pos + size * scale, uv[2], uv[3], col_border); - draw_list->AddImage(tex_id, pos, pos + size * scale, uv[0], uv[1], col_fill); + draw_list->AddImage(tex_id, pos + ImVec2(1, 0) * vga_scale, pos + (ImVec2(1, 0) + size) * vga_scale, uv[2], uv[3], col_shadow); + draw_list->AddImage(tex_id, pos + ImVec2(2, 0) * vga_scale, pos + (ImVec2(2, 0) + size) * vga_scale, uv[2], uv[3], col_shadow); + draw_list->AddImage(tex_id, pos, pos + size * vga_scale, uv[2], uv[3], col_border); + draw_list->AddImage(tex_id, pos, pos + size * vga_scale, uv[0], uv[1], col_fill); draw_list->PopTextureID(); } } diff --git a/verilator/sim/imgui/imgui_impl_dx11.cpp b/verilator/sim/imgui/imgui_impl_dx11.cpp index 0690b97..227f2a7 100644 --- a/verilator/sim/imgui/imgui_impl_dx11.cpp +++ b/verilator/sim/imgui/imgui_impl_dx11.cpp @@ -324,12 +324,12 @@ static void ImGui_ImplDX11_CreateFontsTexture() { D3D11_SAMPLER_DESC desc; ZeroMemory(&desc, sizeof(desc)); - desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; desc.MipLODBias = 0.f; - desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.ComparisonFunc = D3D11_COMPARISON_NEVER; desc.MinLOD = 0.f; desc.MaxLOD = 0.f; g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); diff --git a/verilator/sim/imgui/imgui_internal.h b/verilator/sim/imgui/imgui_internal.h index 4dab8ec..9dc4fc8 100644 --- a/verilator/sim/imgui/imgui_internal.h +++ b/verilator/sim/imgui/imgui_internal.h @@ -1856,7 +1856,7 @@ public: // We don't use g.FontSize because the window may be != g.CurrentWidow. ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); } - float CalcFontSize() const { ImGuiContext& g = *GImGui; float scale = g.FontBaseSize * FontWindowScale; if (ParentWindow) scale *= ParentWindow->FontWindowScale; return scale; } + float CalcFontSize() const { ImGuiContext& g = *GImGui; float vga_scale = g.FontBaseSize * FontWindowScale; if (ParentWindow) vga_scale *= ParentWindow->FontWindowScale; return vga_scale; } float TitleBarHeight() const { ImGuiContext& g = *GImGui; return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + g.Style.FramePadding.y * 2.0f; } ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); } float MenuBarHeight() const { ImGuiContext& g = *GImGui; return (Flags & ImGuiWindowFlags_MenuBar) ? DC.MenuBarOffset.y + CalcFontSize() + g.Style.FramePadding.y * 2.0f : 0.0f; } @@ -2452,17 +2452,17 @@ namespace ImGui IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. // Render helpers (those functions don't access any ImGui state!) - IMGUI_API void RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale = 1.0f); + IMGUI_API void RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float vga_scale = 1.0f); IMGUI_API void RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col); IMGUI_API void RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz); - IMGUI_API void RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow); + IMGUI_API void RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float vga_scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow); IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col); IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding); IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect inner, ImU32 col, float rounding); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // [1.71: 2019/06/07: Updating prototypes of some of the internal functions. Leaving those for reference for a short while] - inline void RenderArrow(ImVec2 pos, ImGuiDir dir, float scale=1.0f) { ImGuiWindow* window = GetCurrentWindow(); RenderArrow(window->DrawList, pos, GetColorU32(ImGuiCol_Text), dir, scale); } + inline void RenderArrow(ImVec2 pos, ImGuiDir dir, float vga_scale=1.0f) { ImGuiWindow* window = GetCurrentWindow(); RenderArrow(window->DrawList, pos, GetColorU32(ImGuiCol_Text), dir, vga_scale); } inline void RenderBullet(ImVec2 pos) { ImGuiWindow* window = GetCurrentWindow(); RenderBullet(window->DrawList, pos, GetColorU32(ImGuiCol_Text)); } #endif diff --git a/verilator/sim/imgui/imgui_plot.cpp b/verilator/sim/imgui/imgui_plot.cpp new file mode 100644 index 0000000..772b2ce --- /dev/null +++ b/verilator/sim/imgui/imgui_plot.cpp @@ -0,0 +1,263 @@ +#include +#include +#ifndef IMGUI_DEFINE_MATH_OPERATORS +#define IMGUI_DEFINE_MATH_OPERATORS +#endif +#include + +namespace ImGui { +// [0..1] -> [0..1] +static float rescale(float t, float min, float max, PlotConfig::Scale::Type type) { + switch (type) { + case PlotConfig::Scale::Linear: + return t; + case PlotConfig::Scale::Log10: + return log10(ImLerp(min, max, t) / min) / log10(max / min); + } + return 0; +} + +// [0..1] -> [0..1] +static float rescale_inv(float t, float min, float max, PlotConfig::Scale::Type type) { + switch (type) { + case PlotConfig::Scale::Linear: + return t; + case PlotConfig::Scale::Log10: + return (pow(max/min, t) * min - min) / (max - min); + } + return 0; +} + +static int cursor_to_idx(const ImVec2& pos, const ImRect& bb, const PlotConfig& conf, float x_min, float x_max) { + const float t = ImClamp((pos.x - bb.Min.x) / (bb.Max.x - bb.Min.x), 0.0f, 0.9999f); + const int v_idx = (int)(rescale_inv(t, x_min, x_max, conf.scale.type) * (conf.values.count - 1)); + IM_ASSERT(v_idx >= 0 && v_idx < conf.values.count); + + return v_idx; +} + +PlotStatus Plot(const char* label, const PlotConfig& conf) { + PlotStatus status = PlotStatus::nothing; + + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return status; + + const float* const* ys_list = conf.values.ys_list; + int ys_count = conf.values.ys_count; + const ImU32* colors = conf.values.colors; + if (conf.values.ys != nullptr) { // draw only a single plot + ys_list = &conf.values.ys; + ys_count = 1; + colors = &conf.values.color; + } + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + const ImGuiID id = window->GetID(label); + + const ImRect frame_bb( + window->DC.CursorPos, + window->DC.CursorPos + conf.frame_size); + const ImRect inner_bb( + frame_bb.Min + style.FramePadding, + frame_bb.Max - style.FramePadding); + const ImRect total_bb = frame_bb; + ItemSize(total_bb, style.FramePadding.y); + if (!ItemAdd(total_bb, 0, &frame_bb)) + return status; + const bool hovered = ItemHoverable(frame_bb, id); + + RenderFrame( + frame_bb.Min, + frame_bb.Max, + GetColorU32(ImGuiCol_FrameBg), + true, + style.FrameRounding); + + if (conf.values.count > 0) { + int res_w; + if (conf.skip_small_lines) + res_w = ImMin((int)conf.frame_size.x, conf.values.count); + else + res_w = conf.values.count; + res_w -= 1; + int item_count = conf.values.count - 1; + + float x_min = conf.values.offset; + float x_max = conf.values.offset + conf.values.count - 1; + if (conf.values.xs) { + x_min = conf.values.xs[size_t(x_min)]; + x_max = conf.values.xs[size_t(x_max)]; + } + + // Tooltip on hover + int v_hovered = -1; + if (conf.tooltip.show && hovered && inner_bb.Contains(g.IO.MousePos)) { + const int v_idx = cursor_to_idx(g.IO.MousePos, inner_bb, conf, x_min, x_max); + const size_t data_idx = conf.values.offset + (v_idx % conf.values.count); + const float x0 = conf.values.xs ? conf.values.xs[data_idx] : v_idx; + const float y0 = ys_list[0][data_idx]; // TODO: tooltip is only shown for the first y-value! + SetTooltip(conf.tooltip.format, x0, y0); + v_hovered = v_idx; + } + + const float t_step = 1.0f / (float)res_w; + const float inv_scale = (conf.scale.min == conf.scale.max) ? + 0.0f : (1.0f / (conf.scale.max - conf.scale.min)); + + if (conf.grid_x.show) { + int y0 = inner_bb.Min.y; + int y1 = inner_bb.Max.y; + switch (conf.scale.type) { + case PlotConfig::Scale::Linear: { + float cnt = conf.values.count / (conf.grid_x.size / conf.grid_x.subticks); + float inc = 1.f / cnt; + for (int i = 0; i <= cnt; ++i) { + int x0 = ImLerp(inner_bb.Min.x, inner_bb.Max.x, i * inc); + window->DrawList->AddLine( + ImVec2(x0, y0), + ImVec2(x0, y1), + IM_COL32(200, 200, 200, (i % conf.grid_x.subticks) ? 128 : 255)); + } + break; + } + case PlotConfig::Scale::Log10: { + float start = 1.f; + while (start < x_max) { + for (int i = 1; i < 10; ++i) { + float x = start * i; + if (x < x_min) continue; + if (x > x_max) break; + float t = log10(x / x_min) / log10(x_max / x_min); + int x0 = ImLerp(inner_bb.Min.x, inner_bb.Max.x, t); + window->DrawList->AddLine( + ImVec2(x0, y0), + ImVec2(x0, y1), + IM_COL32(200, 200, 200, (i > 1) ? 128 : 255)); + } + start *= 10.f; + } + break; + } + } + } + if (conf.grid_y.show) { + int x0 = inner_bb.Min.x; + int x1 = inner_bb.Max.x; + float cnt = (conf.scale.max - conf.scale.min) / (conf.grid_y.size / conf.grid_y.subticks); + float inc = 1.f / cnt; + for (int i = 0; i <= cnt; ++i) { + int y0 = ImLerp(inner_bb.Min.y, inner_bb.Max.y, i * inc); + window->DrawList->AddLine( + ImVec2(x0, y0), + ImVec2(x1, y0), + IM_COL32(0, 0, 0, (i % conf.grid_y.subticks) ? 16 : 64)); + } + } + + const ImU32 col_hovered = GetColorU32(ImGuiCol_PlotLinesHovered); + ImU32 col_base = GetColorU32(ImGuiCol_PlotLines); + + for (int i = 0; i < ys_count; ++i) { + if (colors) { + if (colors[i]) col_base = colors[i]; + else col_base = GetColorU32(ImGuiCol_PlotLines); + } + float v0 = ys_list[i][conf.values.offset]; + float t0 = 0.0f; + // Point in the normalized space of our target rectangle + ImVec2 tp0 = ImVec2(t0, 1.0f - ImSaturate((v0 - conf.scale.min) * inv_scale)); + + for (int n = 0; n < res_w; n++) + { + const float t1 = t0 + t_step; + const int v1_idx = (int)(t0 * item_count + 0.5f); + IM_ASSERT(v1_idx >= 0 && v1_idx < conf.values.count); + const float v1 = ys_list[i][conf.values.offset + (v1_idx + 1) % conf.values.count]; + const ImVec2 tp1 = ImVec2( + rescale(t1, x_min, x_max, conf.scale.type), + 1.0f - ImSaturate((v1 - conf.scale.min) * inv_scale)); + + // NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU. + ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0); + ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, tp1); + + if (v1_idx == v_hovered) { + window->DrawList->AddCircleFilled(pos0, 3, col_hovered); + } + + window->DrawList->AddLine( + pos0, + pos1, + col_base, + conf.line_thickness); + + t0 = t1; + tp0 = tp1; + } + } + + if (conf.v_lines.show) { + for (size_t i = 0; i < conf.v_lines.count; ++i) { + const size_t idx = conf.v_lines.indices[i]; + const float t1 = rescale(idx * t_step, x_min, x_max, conf.scale.type); + ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, ImVec2(t1, 0.f)); + ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, ImVec2(t1, 1.f)); + window->DrawList->AddLine(pos0, pos1, IM_COL32(0xff, 0, 0, 0x88)); + } + } + + if (conf.selection.show) { + if (hovered) { + if (g.IO.MouseClicked[0]) { + SetActiveID(id, window); + FocusWindow(window); + + const int v_idx = cursor_to_idx(g.IO.MousePos, inner_bb, conf, x_min, x_max); + uint32_t start = conf.values.offset + (v_idx % conf.values.count); + uint32_t end = start; + if (conf.selection.sanitize_fn) + end = conf.selection.sanitize_fn(end - start) + start; + if (end < conf.values.offset + conf.values.count) { + *conf.selection.start = start; + *conf.selection.length = end - start; + status = PlotStatus::selection_updated; + } + } + } + + if (g.ActiveId == id) { + if (g.IO.MouseDown[0]) { + const int v_idx = cursor_to_idx(g.IO.MousePos, inner_bb, conf, x_min, x_max); + const uint32_t start = *conf.selection.start; + uint32_t end = conf.values.offset + (v_idx % conf.values.count); + if (end > start) { + if (conf.selection.sanitize_fn) + end = conf.selection.sanitize_fn(end - start) + start; + if (end < conf.values.offset + conf.values.count) { + *conf.selection.length = end - start; + status = PlotStatus::selection_updated; + } + } + } else { + ClearActiveID(); + } + } + float fSelectionStep = 1.0 / item_count; + ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, + ImVec2(fSelectionStep * *conf.selection.start, 0.f)); + ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, + ImVec2(fSelectionStep * (*conf.selection.start + *conf.selection.length), 1.f)); + window->DrawList->AddRectFilled(pos0, pos1, IM_COL32(128, 128, 128, 32)); + window->DrawList->AddRect(pos0, pos1, IM_COL32(128, 128, 128, 128)); + } + } + + // Text overlay + if (conf.overlay_text) + RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, conf.overlay_text, NULL, NULL, ImVec2(0.5f,0.0f)); + + return status; +} +} \ No newline at end of file diff --git a/verilator/sim/imgui/imgui_plot.h b/verilator/sim/imgui/imgui_plot.h new file mode 100644 index 0000000..b4d57f5 --- /dev/null +++ b/verilator/sim/imgui/imgui_plot.h @@ -0,0 +1,75 @@ +#pragma once +#include +#include + +namespace ImGui { +// Use this structure to pass the plot data and settings into the Plot function +struct PlotConfig { + struct Values { + // if necessary, you can provide x-axis values + const float *xs = nullptr; + // array of y values. If null, use ys_list (below) + const float *ys = nullptr; + // the number of values in each array + int count; + // at which offset to start plotting. + // Warning: count+offset must be <= length of array! + int offset = 0; + // Plot color. If 0, use ImGuiCol_PlotLines. + ImU32 color = 0; + + // in case you need to draw multiple plots at once, use this instead of ys + const float **ys_list = nullptr; + // the number of plots to draw + int ys_count = 0; + // colors for each plot + const ImU32* colors = nullptr; + } values; + struct Scale { + // Minimum plot value + float min; + // Maximum plot value + float max; + enum Type { + Linear, + Log10, + }; + // How to scale the x-axis + Type type = Linear; + } scale; + struct Tooltip { + bool show = false; + const char* format = "%g: %8.4g"; + } tooltip; + struct Grid { + bool show = false; + float size = 100; // at which intervals to draw the grid + int subticks = 10; // how many subticks in each tick + } grid_x, grid_y; + struct Selection { + bool show = false; + uint32_t* start = nullptr; + uint32_t* length = nullptr; + // "Sanitize" function. Give it selection length, and it will return + // the "allowed" length. Useful for FFT, where selection must be + // of power of two + uint32_t(*sanitize_fn)(uint32_t) = nullptr; + } selection; + struct VerticalLines { + bool show = false; + const size_t* indices = nullptr; // at which indices to draw the lines + size_t count = 0; + } v_lines; + ImVec2 frame_size = ImVec2(0.f, 0.f); + float line_thickness = 1.f; + bool skip_small_lines = true; + const char* overlay_text = nullptr; +}; + +enum class PlotStatus { + nothing, + selection_updated, +}; + +IMGUI_API PlotStatus Plot(const char* label, const PlotConfig& conf); +} \ No newline at end of file diff --git a/verilator/sim/imgui/imgui_widgets.cpp b/verilator/sim/imgui/imgui_widgets.cpp index fcf1155..01b325c 100644 --- a/verilator/sim/imgui/imgui_widgets.cpp +++ b/verilator/sim/imgui/imgui_widgets.cpp @@ -3538,7 +3538,7 @@ static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* t ImGuiContext& g = *GImGui; ImFont* font = g.Font; const float line_height = g.FontSize; - const float scale = line_height / font->FontSize; + const float vga_scale = line_height / font->FontSize; ImVec2 text_size = ImVec2(0, 0); float line_width = 0.0f; @@ -3559,7 +3559,7 @@ static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* t if (c == '\r') continue; - const float char_width = font->GetCharAdvance((ImWchar)c) * scale; + const float char_width = font->GetCharAdvance((ImWchar)c) * vga_scale; line_width += char_width; } diff --git a/verilator/sim/imgui/imstb_truetype.h b/verilator/sim/imgui/imstb_truetype.h index fc815d7..d45081b 100644 --- a/verilator/sim/imgui/imstb_truetype.h +++ b/verilator/sim/imgui/imstb_truetype.h @@ -928,8 +928,8 @@ STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); // frees the SDF bitmap allocated below -STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); -STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float vga_scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float vga_scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); // These functions compute a discretized SDF field for a single character, suitable for storing // in a single-channel texture, sampling with bilinear filtering, and testing against // larger than some threshold to produce scalable fonts. @@ -3534,10 +3534,10 @@ error: STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) { - float scale = scale_x > scale_y ? scale_y : scale_x; + float vga_scale = scale_x > scale_y ? scale_y : scale_x; int winding_count = 0; int *winding_lengths = NULL; - stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); + stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / vga_scale, &winding_lengths, &winding_count, userdata); if (windings) { stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); STBTT_free(winding_lengths, userdata); @@ -3656,7 +3656,7 @@ static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // fo int first_char, int num_chars, // characters to bake stbtt_bakedchar *chardata) { - float scale; + float vga_scale; int x,y,bottom_y, i; stbtt_fontinfo f; f.userdata = NULL; @@ -3666,13 +3666,13 @@ static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // fo x=y=1; bottom_y = 1; - scale = stbtt_ScaleForPixelHeight(&f, pixel_height); + vga_scale = stbtt_ScaleForPixelHeight(&f, pixel_height); for (i=0; i < num_chars; ++i) { int advance, lsb, x0,y0,x1,y1,gw,gh; int g = stbtt_FindGlyphIndex(&f, first_char + i); stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); - stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); + stbtt_GetGlyphBitmapBox(&f, g, vga_scale,vga_scale, &x0,&y0,&x1,&y1); gw = x1-x0; gh = y1-y0; if (x + gw + 1 >= pw) @@ -3681,12 +3681,12 @@ static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // fo return -i; STBTT_assert(x+gw < pw); STBTT_assert(y+gh < ph); - stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); + stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, vga_scale,vga_scale, g); chardata[i].x0 = (stbtt_int16) x; chardata[i].y0 = (stbtt_int16) y; chardata[i].x1 = (stbtt_int16) (x + gw); chardata[i].y1 = (stbtt_int16) (y + gh); - chardata[i].xadvance = scale * advance; + chardata[i].xadvance = vga_scale * advance; chardata[i].xoff = (float) x0; chardata[i].yoff = (float) y0; x = x + gw + 1; @@ -3993,7 +3993,7 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb k=0; for (i=0; i < num_ranges; ++i) { float fh = ranges[i].font_size; - float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + float vga_scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); ranges[i].h_oversample = (unsigned char) spc->h_oversample; ranges[i].v_oversample = (unsigned char) spc->v_oversample; for (j=0; j < ranges[i].num_chars; ++j) { @@ -4004,8 +4004,8 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb rects[k].w = rects[k].h = 0; } else { stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, - scale * spc->h_oversample, - scale * spc->v_oversample, + vga_scale * spc->h_oversample, + vga_scale * spc->v_oversample, 0,0, &x0,&y0,&x1,&y1); rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); @@ -4053,7 +4053,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const k = 0; for (i=0; i < num_ranges; ++i) { float fh = ranges[i].font_size; - float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + float vga_scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); float recip_h,recip_v,sub_x,sub_y; spc->h_oversample = ranges[i].h_oversample; spc->v_oversample = ranges[i].v_oversample; @@ -4077,16 +4077,16 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const r->h -= pad; stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); stbtt_GetGlyphBitmapBox(info, glyph, - scale * spc->h_oversample, - scale * spc->v_oversample, + vga_scale * spc->h_oversample, + vga_scale * spc->v_oversample, &x0,&y0,&x1,&y1); stbtt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes, r->w - spc->h_oversample+1, r->h - spc->v_oversample+1, spc->stride_in_bytes, - scale * spc->h_oversample, - scale * spc->v_oversample, + vga_scale * spc->h_oversample, + vga_scale * spc->v_oversample, 0,0, glyph); @@ -4104,7 +4104,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const bc->y0 = (stbtt_int16) r->y; bc->x1 = (stbtt_int16) (r->x + r->w); bc->y1 = (stbtt_int16) (r->y + r->h); - bc->xadvance = scale * advance; + bc->xadvance = vga_scale * advance; bc->xoff = (float) x0 * recip_h + sub_x; bc->yoff = (float) y0 * recip_v + sub_y; bc->xoff2 = (x0 + r->w) * recip_h + sub_x; @@ -4180,14 +4180,14 @@ STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char * STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap) { int i_ascent, i_descent, i_lineGap; - float scale; + float vga_scale; stbtt_fontinfo info; stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index)); - scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size); + vga_scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size); stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap); - *ascent = (float) i_ascent * scale; - *descent = (float) i_descent * scale; - *lineGap = (float) i_lineGap * scale; + *ascent = (float) i_ascent * vga_scale; + *descent = (float) i_descent * vga_scale; + *lineGap = (float) i_lineGap * vga_scale; } STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) @@ -4403,9 +4403,9 @@ static int stbtt__solve_cubic(float a, float b, float c, float* r) } } -STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float vga_scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) { - float scale_x = scale, scale_y = scale; + float scale_x = vga_scale, scale_y = vga_scale; int ix0,iy0,ix1,iy1; int w,h; unsigned char *data; @@ -4417,7 +4417,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc scale_y = scale_x; } - stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, vga_scale, vga_scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); // if empty, return NULL if (ix0 == ix1 || iy0 == iy1) @@ -4589,9 +4589,9 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc return data; } -STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float vga_scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) { - return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); + return stbtt_GetGlyphSDF(info, vga_scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); } STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) diff --git a/verilator/sim/sim_console.cpp b/verilator/sim/sim_console.cpp index 1535a43..c649d79 100644 --- a/verilator/sim/sim_console.cpp +++ b/verilator/sim/sim_console.cpp @@ -17,7 +17,6 @@ bool ScrollToBottom; ImVector Items; static char* Strdup(const char* str) { size_t len = strlen(str) + 1; void* buf = malloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)str, len); } - void DebugConsole::AddLog(const char* fmt, ...) IM_FMTARGS(2) { // FIXME-OPT @@ -63,9 +62,9 @@ void DebugConsole::ClearLog() Items.clear(); } -void DebugConsole::Draw(const char* title, bool* p_open) +void DebugConsole::Draw(const char* title, bool* p_open, ImVec2 size) { - ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver); + ImGui::SetWindowSize(title, size, ImGuiCond_Once); if (!ImGui::Begin(title, p_open)) { ImGui::End(); diff --git a/verilator/sim/sim_console.h b/verilator/sim/sim_console.h index a9a2b66..96f5ee7 100644 --- a/verilator/sim/sim_console.h +++ b/verilator/sim/sim_console.h @@ -7,7 +7,7 @@ public: DebugConsole(); ~DebugConsole(); void ClearLog(); - void Draw(const char* title, bool* p_open); + void Draw(const char* title, bool* p_open, ImVec2 size); void ExecCommand(const char* command_line); int TextEditCallback(ImGuiInputTextCallbackData* data); }; diff --git a/verilator/sim/sim_input.cpp b/verilator/sim/sim_input.cpp index ec7b5d6..b328417 100644 --- a/verilator/sim/sim_input.cpp +++ b/verilator/sim/sim_input.cpp @@ -19,6 +19,10 @@ unsigned char m_keyboardState_last[256]; #endif #include +#include "sim_console.h" + +static DebugConsole console; + #ifdef WIN32 static const unsigned int ev2ps2[] = { @@ -648,9 +652,10 @@ void SimInput::BeforeEval() } } -SimInput::SimInput(int count) +SimInput::SimInput(int count, DebugConsole c) { inputCount = count; + console = c; } SimInput::~SimInput() diff --git a/verilator/sim/sim_input.h b/verilator/sim/sim_input.h index 484433c..dea6743 100644 --- a/verilator/sim/sim_input.h +++ b/verilator/sim/sim_input.h @@ -12,11 +12,11 @@ struct SimInput_PS2KeyEvent { public: - unsigned char code; + char code; bool pressed; bool extended; - SimInput_PS2KeyEvent(unsigned char code, bool pressed, bool extended) { + SimInput_PS2KeyEvent(char code, bool pressed, bool extended) { this->code = code; this->pressed = pressed; this->extended = extended; @@ -33,7 +33,7 @@ public: SData* ps2_key = NULL; std::queue keyEvents; unsigned int keyEventTimer = 0; - unsigned int keyEventWait = 500; + unsigned int keyEventWait = 50000; #define NONE 0xFF #define LCTRL 0x000100 @@ -58,6 +58,6 @@ public: void CleanUp(); void SetMapping(int index, int code); void BeforeEval(void); - SimInput(int count); + SimInput(int count, DebugConsole c); ~SimInput(); }; diff --git a/verilator/sim/sim_video.cpp b/verilator/sim/sim_video.cpp index ea220ed..faecf85 100644 --- a/verilator/sim/sim_video.cpp +++ b/verilator/sim/sim_video.cpp @@ -25,6 +25,7 @@ int output_width = 512; int output_height = 512; int output_rotate = 0; bool output_vflip = false; +bool output_usevsync = 1; uint32_t* output_ptr = NULL; unsigned int output_size; @@ -48,6 +49,7 @@ bool last_hblank; bool last_vblank; bool last_hsync; bool last_vsync; +bool frame_ready = 1; // Statistics #ifdef WIN32 @@ -308,12 +310,12 @@ int SimVideo::Initialise(const char* windowTitle) { { D3D11_SAMPLER_DESC desc; ZeroMemory(&desc, sizeof(desc)); - desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; desc.MipLODBias = 0.f; - desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.ComparisonFunc = D3D11_COMPARISON_NEVER; desc.MinLOD = 0.f; desc.MaxLOD = 0.f; g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); @@ -337,19 +339,19 @@ void SimVideo::UpdateTexture() { // Update the texture! // D3D11_USAGE_DEFAULT MUST be set in the texture description (somewhere above) for this to work. // (D3D11_USAGE_DYNAMIC is for use with map / unmap.) ElectronAsh. - - g_pd3dDeviceContext->UpdateSubresource(texture, 0, NULL, output_ptr, output_width * 4, 0); - + if (frame_ready) { + g_pd3dDeviceContext->UpdateSubresource(texture, 0, NULL, output_ptr, output_width * 4, 0); + } // Rendering ImGui::Render(); g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL); g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, (float*)&clear_color); ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); - g_pSwapChain->Present(1, 0); // Present without vsync + g_pSwapChain->Present(output_usevsync, 0); // Present without vsync #else - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, output_width, output_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, output_ptr); - + if (frame_ready) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, output_width, output_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, output_ptr); + } // Rendering ImGui::Render(); glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); @@ -360,7 +362,7 @@ void SimVideo::UpdateTexture() { SDL_GL_SwapWindow(window); #endif - + frame_ready = 0; } @@ -418,6 +420,7 @@ void SimVideo::Clock(bool hblank, bool vblank, bool hsync, bool vsync, uint32_t // Reset on rising vsync if (last_vsync && !vsync) { + frame_ready = 1; count_frame++; count_line = 0; #ifdef WIN32 diff --git a/verilator/sim/vinc/verilated.cpp b/verilator/sim/vinc/verilated.cpp index f50c301..b612293 100644 --- a/verilator/sim/vinc/verilated.cpp +++ b/verilator/sim/vinc/verilated.cpp @@ -2143,37 +2143,37 @@ void VL_WRITEMEM_N(bool hex, // Hex format, else binary // Helper function for conversion of timescale strings // Converts (1|10|100)(s|ms|us|ns|ps|fs) to power of then int VL_TIME_STR_CONVERT(const char* strp) VL_PURE { - int scale = 0; + int vga_scale = 0; if (!strp) return 0; if (*strp++ != '1') return 0; while (*strp == '0') { - scale++; + vga_scale++; strp++; } switch (*strp++) { case 's': break; - case 'm': scale -= 3; break; - case 'u': scale -= 6; break; - case 'n': scale -= 9; break; - case 'p': scale -= 12; break; - case 'f': scale -= 15; break; + case 'm': vga_scale -= 3; break; + case 'u': vga_scale -= 6; break; + case 'n': vga_scale -= 9; break; + case 'p': vga_scale -= 12; break; + case 'f': vga_scale -= 15; break; default: return 0; } - if ((scale < 0) && (*strp++ != 's')) return 0; + if ((vga_scale < 0) && (*strp++ != 's')) return 0; if (*strp) return 0; - return scale; + return vga_scale; } -static const char* vl_time_str(int scale) VL_PURE { +static const char* vl_time_str(int vga_scale) VL_PURE { static const char* const names[] = {"100s", "10s", "1s", "100ms", "10ms", "1ms", "100us", "10us", "1us", "100ns", "10ns", "1ns", "100ps", "10ps", "1ps", "100fs", "10fs", "1fs"}; - if (VL_UNLIKELY(scale > 2 || scale < -15)) scale = 0; - return names[2 - scale]; + if (VL_UNLIKELY(vga_scale > 2 || vga_scale < -15)) vga_scale = 0; + return names[2 - vga_scale]; } -double vl_time_multiplier(int scale) VL_PURE { +double vl_time_multiplier(int vga_scale) VL_PURE { // Return timescale multipler -18 to +18 // For speed, this does not check for illegal values - if (scale < 0) { + if (vga_scale < 0) { static const double neg10[] = {1.0, 0.1, 0.01, @@ -2193,7 +2193,7 @@ double vl_time_multiplier(int scale) VL_PURE { 0.0000000000000001, 0.00000000000000001, 0.000000000000000001}; - return neg10[-scale]; + return neg10[-vga_scale]; } else { static const double pow10[] = {1.0, 10.0, @@ -2214,7 +2214,7 @@ double vl_time_multiplier(int scale) VL_PURE { 10000000000000000.0, 100000000000000000.0, 1000000000000000000.0}; - return pow10[scale]; + return pow10[vga_scale]; } } vluint64_t vl_time_pow10(int n) { @@ -2244,7 +2244,7 @@ vluint64_t vl_time_pow10(int n) { void VL_PRINTTIMESCALE(const char* namep, const char* timeunitp, const VerilatedContext* contextp) VL_MT_SAFE { - VL_PRINTF_MT("Time scale of %s is %s / %s\n", namep, timeunitp, + VL_PRINTF_MT("Time vga_scale of %s is %s / %s\n", namep, timeunitp, contextp->timeprecisionString()); } void VL_TIMEFORMAT_IINI(int units, int precision, const std::string& suffix, int width, diff --git a/verilator/sim/vinc/verilated.h b/verilator/sim/vinc/verilated.h index 2ec9c8a..3610206 100644 --- a/verilator/sim/vinc/verilated.h +++ b/verilator/sim/vinc/verilated.h @@ -1186,11 +1186,11 @@ inline vluint64_t VerilatedContext::time() const VL_MT_SAFE { // Time scaled from 1-per-precision into a module's time units ("Unit"-ed, not "United") // Optimized assuming scale is always constant. // Can't use multiply in Q flavor, as might lose precision -#define VL_TIME_UNITED_Q(scale) (VL_TIME_Q() / static_cast(scale)) -#define VL_TIME_UNITED_D(scale) (VL_TIME_D() / static_cast(scale)) +#define VL_TIME_UNITED_Q(vga_scale) (VL_TIME_Q() / static_cast(vga_scale)) +#define VL_TIME_UNITED_D(vga_scale) (VL_TIME_D() / static_cast(vga_scale)) // Return time precision as multiplier of time units -double vl_time_multiplier(int scale) VL_PURE; +double vl_time_multiplier(int vga_scale) VL_PURE; // Return power of 10. e.g. returns 100 if n==2 vluint64_t vl_time_pow10(int n) VL_PURE; diff --git a/verilator/sim/vinc/verilatedos.h b/verilator/sim/vinc/verilatedos.h index 06d07d3..9629499 100644 --- a/verilator/sim/vinc/verilatedos.h +++ b/verilator/sim/vinc/verilatedos.h @@ -513,7 +513,8 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type #ifdef __MINGW32__ # define VL_LOCALTIME_R(timep, tmp) localtime_s((tmp), (timep)) #elif defined(_MSC_VER) -# define VL_LOCALTIME_R(timep, tmp) localtime_c((tmp), (timep)) +//# define VL_LOCALTIME_R(timep, tmp) localtime_c((tmp), (timep)) +# define VL_LOCALTIME_R(timep, tmp) localtime_s((tmp), (timep)) #else # define VL_LOCALTIME_R(timep, tmp) localtime_r((timep), (tmp)) #endif diff --git a/verilator/sim_main.cpp b/verilator/sim_main.cpp index a939933..a580d01 100644 --- a/verilator/sim_main.cpp +++ b/verilator/sim_main.cpp @@ -10,7 +10,6 @@ #define WIN32 #include #endif -#include #include "sim_console.h" #include "sim_bus.h" @@ -21,22 +20,36 @@ #include "../imgui/imgui_memory_editor.h" #include "../imgui/ImGuiFileDialog.h" +#include +#include +using namespace std; + +// Simulation control +// ------------------ +int initialReset = 48; +bool run_enable = 1; +int batchSize = 150000; +bool single_step = 0; +bool multi_step = 0; +int multi_step_amount = 1024; + // Debug GUI // --------- -const char* windowTitle = "Verilator Sim: InputTest"; -bool showDebugWindow = true; -const char* debugWindowTitle = "Virtual Dev Board v1.0"; +const char* windowTitle = "Verilator Sim: Aznable"; +const char* windowTitle_Control = "Simulation control"; +const char* windowTitle_DebugLog = "Debug log"; +const char* windowTitle_Video = "VGA output"; +bool showDebugLog = true; DebugConsole console; -MemoryEditor mem_edit_1; -MemoryEditor mem_edit_2; -MemoryEditor mem_edit_3; +MemoryEditor mem_edit; + // HPS emulator // ------------ SimBus bus(console); // Input handling // -------------- -SimInput input(12); +SimInput input(13, console); const int input_right = 0; const int input_left = 1; const int input_down = 2; @@ -49,53 +62,46 @@ const int input_l = 8; const int input_r = 9; const int input_select = 10; const int input_start = 11; +const int input_menu = 12; // Video // ----- #define VGA_WIDTH 320 #define VGA_HEIGHT 240 #define VGA_ROTATE 0 // 90 degrees anti-clockwise +#define VGA_SCALE_X vga_scale +#define VGA_SCALE_Y vga_scale SimVideo video(VGA_WIDTH, VGA_HEIGHT, VGA_ROTATE); - -// Simulation control -// ------------------ -int initialReset = 48; -bool run_enable = 1; -int batchSize = 150000; -bool single_step = 0; -bool multi_step = 0; -int multi_step_amount = 1024; +float vga_scale = 3.0; // Verilog module // -------------- Vemu* top = NULL; -vluint64_t main_time = 0; // Current simulation time. -vluint32_t timestamp = 0; // Simulated Unix timestamp. -vluint16_t timestamp_ticksperms = 24000; // Number of simulation ticks per simulated millisecond -vluint16_t timestamp_ticks = 0; // Ticks left until next ms -unsigned short timestamp_updatefreq = 5000; // Only update sim every 5 seconds -unsigned short timestamp_update = 0; // Ms to next update. -bool timestamp_clock = 1; // Timestamp update clock - -double sc_time_stamp() { // Called by $time in Verilog. +vluint64_t main_time = 0; // Current simulation time. +double sc_time_stamp() { // Called by $time in Verilog. return main_time; } SimClock clk_sys(1); +//#define DEBUG_AUDIO + +#ifdef DEBUG_AUDIO +// Audio +SimClock clk_audio(2205); +ofstream audioFile; +#endif - -long GetTime() { - return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); -} - +// Reset simulation variables and clocks void resetSim() { main_time = 0; - timestamp = GetTime(); top->reset = 1; clk_sys.Reset(); +#ifdef DEBUG_AUDIO + clk_audio.Reset(); +#endif } int verilate() { @@ -110,24 +116,6 @@ int verilate() { // Clock dividers clk_sys.Tick(); - // Increment timestamp - timestamp_ticks ++; - if (timestamp_ticks >= timestamp_ticksperms) { - timestamp_ticks -= timestamp_ticksperms; - timestamp++; - - top->timestamp = timestamp; - timestamp_clock = !timestamp_clock; - - if (timestamp_clock) { - timestamp_update--; - if (timestamp_update <= 0) { - top->timestamp |= ((uint64_t)1) << 32; - timestamp_update = timestamp_updatefreq; - } - } - } - // Set system clock in core top->clk_sys = clk_sys.clk; @@ -141,16 +129,31 @@ int verilate() { if (clk_sys.clk) { bus.AfterEval(); } } +#ifdef DEBUG_AUDIO + clk_audio.Tick(); + if (clk_audio.IsRising()) { + // Output audio + unsigned short audio_l = top->AUDIO_L; + unsigned char audio_8 = audio_l; + if (audio_l > 0) { + audio_8 = audio_l >> 8; + //console.AddLog("%d %d",audio_l, audio_8); + } + //audioFile.write((const char*)&audio_8, 1); + audioFile.write((const char*)&audio_l, 2); + } +#endif + // Output pixels on rising edge of pixel clock - if (clk_sys.IsRising() && top->emu__DOT__ce_pix) { + if (clk_sys.IsRising() && top->emu__DOT__ce_6) { uint32_t colour = 0xFF000000 | top->VGA_B << 16 | top->VGA_G << 8 | top->VGA_R; video.Clock(top->VGA_HB, top->VGA_VB, top->VGA_HS, top->VGA_VS, colour); } main_time++; - return 1; } + // Stop verilating and cleanup top->final(); delete top; @@ -159,7 +162,8 @@ int verilate() { } unsigned char mouse_clock = 0; -unsigned char mouse_buttons= 0; +unsigned char mouse_clock_reduce = 0; +unsigned char mouse_buttons = 0; unsigned char mouse_x = 0; unsigned char mouse_y = 0; @@ -187,6 +191,11 @@ int main(int argc, char** argv, char** env) { //bus.ioctl_din = &top->ioctl_din; input.ps2_key = &top->ps2_key; +#ifdef DEBUG_AUDIO + // Setup Audio output stream + audioFile.open("audio.wav", ios::binary); +#endif + // Set up input module input.Initialise(); #ifdef WIN32 @@ -202,27 +211,24 @@ int main(int argc, char** argv, char** env) { input.SetMapping(input_r, DIK_W); // R input.SetMapping(input_select, DIK_1); // Select input.SetMapping(input_start, DIK_2); // Start + input.SetMapping(input_menu, DIK_M); // System menu trigger #else input.SetMapping(input_up, SDL_SCANCODE_UP); input.SetMapping(input_right, SDL_SCANCODE_RIGHT); input.SetMapping(input_down, SDL_SCANCODE_DOWN); input.SetMapping(input_left, SDL_SCANCODE_LEFT); - input.SetMapping(input_a, SDL_SCANCODE_A); - input.SetMapping(input_b, SDL_SCANCODE_B); - input.SetMapping(input_x, SDL_SCANCODE_X); - input.SetMapping(input_y, SDL_SCANCODE_Y); - input.SetMapping(input_l, SDL_SCANCODE_L); - input.SetMapping(input_r, SDL_SCANCODE_R); - input.SetMapping(input_select, SDL_SCANCODE_1); - input.SetMapping(input_start, SDL_SCANCODE_2); + input.SetMapping(input_fire1, SDL_SCANCODE_SPACE); + input.SetMapping(input_start_1, SDL_SCANCODE_1); + input.SetMapping(input_start_2, SDL_SCANCODE_2); + input.SetMapping(input_coin_1, SDL_SCANCODE_3); + input.SetMapping(input_coin_2, SDL_SCANCODE_4); + input.SetMapping(input_coin_3, SDL_SCANCODE_5); + input.SetMapping(input_pause, SDL_SCANCODE_P); #endif // Setup video output if (video.Initialise(windowTitle) == 1) { return 1; } - // Initial reset - resetSim(); - #ifdef WIN32 MSG msg; ZeroMemory(&msg, sizeof(msg)); @@ -255,81 +261,111 @@ int main(int argc, char** argv, char** env) { // -------- ImGui::NewFrame(); - console.Draw("Debug Log", &showDebugWindow); - ImGui::Begin(debugWindowTitle); - ImGui::SetWindowPos(debugWindowTitle, ImVec2(580, 10), ImGuiCond_Once); - ImGui::SetWindowSize(debugWindowTitle, ImVec2(1000, 1000), ImGuiCond_Once); - - if (ImGui::Button("RESET")) { resetSim(); } ImGui::SameLine(); - if (ImGui::Button("START")) { run_enable = 1; } ImGui::SameLine(); - if (ImGui::Button("STOP")) { run_enable = 0; } ImGui::SameLine(); - if (ImGui::Button("LOAD")) - ImGuiFileDialog::Instance()->OpenDialog("ChooseFileDlgKey", "Choose File", ".bin", "."); + // Simulation control window + ImGui::Begin(windowTitle_Control); + ImGui::SetWindowPos(windowTitle_Control, ImVec2(0, 0), ImGuiCond_Once); + ImGui::SetWindowSize(windowTitle_Control, ImVec2(500, 150), ImGuiCond_Once); + if (ImGui::Button("Reset simulation")) { resetSim(); } ImGui::SameLine(); + if (ImGui::Button("Start running")) { run_enable = 1; } ImGui::SameLine(); + if (ImGui::Button("Stop running")) { run_enable = 0; } ImGui::SameLine(); ImGui::Checkbox("RUN", &run_enable); - ImGui::SliderInt("Batch size", &batchSize, 1, 250000); - + //ImGui::PopItemWidth(); + ImGui::SliderInt("Run batch size", &batchSize, 1, 250000); if (single_step == 1) { single_step = 0; } if (ImGui::Button("Single Step")) { run_enable = 0; single_step = 1; } ImGui::SameLine(); if (multi_step == 1) { multi_step = 0; } if (ImGui::Button("Multi Step")) { run_enable = 0; multi_step = 1; } - ImGui::SameLine(); + //ImGui::SameLine(); + ImGui::SliderInt("Multi step amount", &multi_step_amount, 8, 1024); - ImGui::SliderInt("Step amount", &multi_step_amount, 8, 1024); + ImGui::End(); + // Debug log window + console.Draw(windowTitle_DebugLog, &showDebugLog, ImVec2(500, 700)); + ImGui::SetWindowPos(windowTitle_DebugLog, ImVec2(0, 160), ImGuiCond_Once); + + // Memory debug + //ImGui::Begin("PGROM Editor"); + //mem_edit.DrawContents(top->emu__DOT__system__DOT__pgrom__DOT__mem, 32768, 0); + //ImGui::End(); + //ImGui::Begin("CHROM Editor"); + //mem_edit.DrawContents(top->emu__DOT__system__DOT__chrom__DOT__mem, 2048, 0); + //ImGui::End(); + //ImGui::Begin("WKRAM Editor"); + //mem_edit.DrawContents(&top->emu__DOT__system__DOT__wkram__DOT__mem, 16384, 0); + //ImGui::End(); + //ImGui::Begin("CHRAM Editor"); + //mem_edit.DrawContents(&top->emu__DOT__system__DOT__chram__DOT__mem, 2048, 0); + //ImGui::End(); + //ImGui::Begin("FGCOLRAM Editor"); + //mem_edit.DrawContents(&top->emu__DOT__system__DOT__fgcolram__DOT__mem, 2048, 0); + //ImGui::End(); + //ImGui::Begin("BGCOLRAM Editor"); + //mem_edit.DrawContents(&top->emu__DOT__system__DOT__bgcolram__DOT__mem, 2048, 0); + //ImGui::End(); + //ImGui::Begin("Sprite RAM"); + //mem_edit.DrawContents(&top->emu__DOT__system__DOT__spriteram__DOT__mem, 96, 0); + //ImGui::End(); + //ImGui::Begin("Sprite Linebuffer RAM"); + //mem_edit.DrawContents(&top->emu__DOT__system__DOT__spritelbram__DOT__mem, 1024, 0); + //ImGui::End(); + //ImGui::Begin("Sprite Collision Buffer RAM A"); + //mem_edit.DrawContents(&top->emu__DOT__system__DOT__comet__DOT__spritecollisionbufferram_a__DOT__mem, 512, 0); + //ImGui::End(); + //ImGui::Begin("Sprite Collision Buffer RAM B"); + //mem_edit.DrawContents(&top->emu__DOT__system__DOT__comet__DOT__spritecollisionbufferram_b__DOT__mem, 512, 0); + //ImGui::End(); + //ImGui::Begin("Sprite Collision RAM "); + //mem_edit.DrawContents(&top->emu__DOT__system__DOT__spritecollisionram__DOT__mem, 32, 0); + //ImGui::End(); + //ImGui::Begin("Sprite Debug RAM"); + //mem_edit.DrawContents(&top->emu__DOT__system__DOT__spritedebugram__DOT__mem, 128000, 0); + //ImGui::End(); + //ImGui::Begin("Palette ROM"); + //mem_edit.DrawContents(&top->emu__DOT__system__DOT__palrom__DOT__mem, 64, 0); + //ImGui::End(); + //ImGui::Begin("Sprite ROM"); + //mem_edit.DrawContents(&top->emu__DOT__system__DOT__spriterom__DOT__mem, 2048, 0); + //ImGui::End(); + //ImGui::Begin("Tilemap ROM"); + //mem_edit.DrawContents(&top->emu__DOT__system__DOT__tilemaprom__DOT__mem, 8192, 0); + //ImGui::End(); + //ImGui::Begin("Tilemap RAM"); + // mem_edit.DrawContents(&top->emu__DOT__system__DOT__tilemapram__DOT__mem, 768, 0); + //ImGui::End(); + //ImGui::Begin("Sound ROM"); + //mem_edit.DrawContents(&top->emu__DOT__system__DOT__soundrom__DOT__mem, 64000, 0); + //ImGui::End(); + + // Video window + ImGui::Begin(windowTitle_Video); + ImGui::SetWindowPos(windowTitle_Video, ImVec2(550, 0), ImGuiCond_Once); + ImGui::SetWindowSize(windowTitle_Video, ImVec2((VGA_WIDTH * VGA_SCALE_X) + 24, (VGA_HEIGHT * VGA_SCALE_Y) + 114), ImGuiCond_Once); + + ImGui::SliderFloat("Zoom", &vga_scale, 1, 8); ImGui::SliderInt("Rotate", &video.output_rotate, -1, 1); ImGui::SameLine(); ImGui::Checkbox("Flip V", &video.output_vflip); - ImGui::Text("main_time: %d frame_count: %d sim FPS: %f", main_time, video.count_frame, video.stats_fps); - ImGui::Text("timestamp: %d actual ms: %d frame_ms: %d ", timestamp, timestamp/1000, video.count_frame * 1000); - ImGui::Text("minx: %d maxx: %d miny: %d maxy: %d", video.stats_xMin, video.stats_xMax, video.stats_yMin, video.stats_yMax); + //ImGui::Text("pixel: %06d line: %03d", video.count_pixel, video.count_line); + +#ifdef DEBUG_AUDIO + float vol_l = ((signed short)(top->AUDIO_L) / 256.0f) / 256.0f; + float vol_r = ((signed short)(top->AUDIO_R) / 256.0f) / 256.0f; + ImGui::ProgressBar(vol_l + 0.5, ImVec2(200, 16), 0); ImGui::SameLine(); + ImGui::ProgressBar(vol_r + 0.5, ImVec2(200, 16), 0); +#endif // Draw VGA output - float m = 2.0; - ImGui::Image(video.texture_id, ImVec2(video.output_width * m, video.output_height * m)); - ImGui::End(); - - /*ImGui::Begin("PGROM Editor"); - mem_edit_1.DrawContents(top->emu__DOT__system__DOT__pgrom__DOT__mem, 16384, 0); - ImGui::End(); - ImGui::Begin("CHROM Editor"); - mem_edit_1.DrawContents(top->emu__DOT__system__DOT__chrom__DOT__mem, 2048, 0); - ImGui::End();*/ - ImGui::Begin("WKRAM Editor"); - mem_edit_2.DrawContents(&top->emu__DOT__system__DOT__wkram__DOT__mem, 16384, 0); - ImGui::End(); - //ImGui::Begin("CHRAM Editor"); - //mem_edit_3.DrawContents(top->emu__DOT__system__DOT__chram__DOT__mem, 2048, 0); - //ImGui::End(); - //ImGui::Begin("COLRAM Editor"); - //mem_edit_3.DrawContents(top->emu__DOT__system__DOT__colram__DOT__mem, 2048, 0); - //ImGui::End(); - - // File Dialog to load rom - if (ImGuiFileDialog::Instance()->Display("ChooseFileDlgKey")) - { - // action if OK - if (ImGuiFileDialog::Instance()->IsOk()) - { - std::string filePathName = ImGuiFileDialog::Instance()->GetFilePathName(); - std::string filePath = ImGuiFileDialog::Instance()->GetCurrentPath(); - // action - bus.QueueDownload(filePathName, 0, true); - } - - // close - ImGuiFileDialog::Instance()->Close(); - } - - ImGui::Begin("CPU Registers"); - ImGui::Spacing(); - ImGui::Text("PC 0x%04X", top->emu__DOT__system__DOT__T80x__DOT__i_tv80_core__DOT__PC); - ImGui::Text("ACC 0x%04X", top->emu__DOT__system__DOT__T80x__DOT__i_tv80_core__DOT__ACC); + ImGui::Image(video.texture_id, ImVec2(video.output_width * VGA_SCALE_X, video.output_height * VGA_SCALE_Y)); ImGui::End(); video.UpdateTexture(); // Pass inputs to sim + + top->menu = input.inputs[input_menu]; + top->joystick_0 = 0; for (int i = 0; i < input.inputCount; i++) { @@ -337,56 +373,34 @@ int main(int argc, char** argv, char** env) { } top->joystick_1 = top->joystick_0; - top->joystick_l_analog_0 += 1; - top->joystick_l_analog_0 -= 256; - top->joystick_r_analog_0 += 1; - top->joystick_r_analog_0 -= 256; + /*top->joystick_analog_0 += 1; + top->joystick_analog_0 -= 256;*/ + //top->paddle_0 += 1; + //if (input.inputs[0] || input.inputs[1]) { + // spinner_toggle = !spinner_toggle; + // top->spinner_0 = (input.inputs[0]) ? 16 : -16; + // for (char b = 8; b < 16; b++) { + // top->spinner_0 &= ~(1UL << b); + // } + // if (spinner_toggle) { top->spinner_0 |= 1UL << 8; } + //} - top->joystick_l_analog_1 += 1; - top->joystick_l_analog_1 -= 256; - top->joystick_r_analog_1 += 1; - top->joystick_r_analog_1 -= 256; + mouse_buttons = 0; + mouse_x = 0; + mouse_y = 0; + if (input.inputs[input_left]) { mouse_x = -2; } + if (input.inputs[input_right]) { mouse_x = 2; } + if (input.inputs[input_up]) { mouse_y = 2; } + if (input.inputs[input_down]) { mouse_y = -2; } - top->joystick_l_analog_2 = 40; - top->joystick_l_analog_2 += 1024; - top->joystick_r_analog_2 = 50; - top->joystick_r_analog_2 += 1024; + if (input.inputs[input_a]) { mouse_buttons |= (1UL << 0); } + if (input.inputs[input_b]) { mouse_buttons |= (1UL << 1); } - top->joystick_l_analog_3 = 60; - top->joystick_l_analog_3 += 2048; - top->joystick_r_analog_3 = 70; - top->joystick_r_analog_3 += 2048; - - top->joystick_l_analog_4 = 80; - top->joystick_l_analog_4 += 4096; - top->joystick_r_analog_4 = 90; - top->joystick_r_analog_4 += 4096; - - top->joystick_l_analog_5 = 100; - top->joystick_l_analog_5 += 8192; - top->joystick_r_analog_5 = 110; - top->joystick_r_analog_5 += 8192; - - top->paddle_0 += 1; - - if (input.inputs[0] || input.inputs[1]) { - spinner_toggle = !spinner_toggle; - top->spinner_0 = (input.inputs[0]) ? 4 : -4; - for (char b = 8; b < 16; b++) { - top->spinner_0 &= ~(1UL << b); - } - if (spinner_toggle) { top->spinner_0 |= 1UL << 8; } - } - - mouse_buttons += 1; - mouse_x += 1; - mouse_y -= 1; unsigned long mouse_temp = mouse_buttons; mouse_temp += (mouse_x << 8); mouse_temp += (mouse_y << 16); if (mouse_clock) { mouse_temp |= (1UL << 24); } - - mouse_clock = !mouse_clock; + mouse_clock = !mouse_clock; top->ps2_mouse = mouse_temp; top->ps2_mouse_ext = mouse_x + (mouse_buttons << 8); @@ -403,13 +417,15 @@ int main(int argc, char** argv, char** env) { } } - // Clean up before exit // -------------------- +#ifdef DEBUG_AUDIO + audioFile.close(); +#endif + video.CleanUp(); input.CleanUp(); return 0; } - \ No newline at end of file diff --git a/verilator/verilate.sh b/verilator/verilate.sh index 4ab75f3..ffe7fd6 100755 --- a/verilator/verilate.sh +++ b/verilator/verilate.sh @@ -1,16 +1,19 @@ - -set -e -if grep -qEi "(Microsoft|WSL)" /proc/version &> /dev/null ; then -verilator \ ---cc \ ---compiler msvc +define+SIMULATION=1 \ --O3 --x-assign fast --x-initial fast --noassert \ --Wno-TIMESCALEMOD \ +OPTIMIZE="-O3 --x-assign fast --x-initial fast --noassert" +WARNINGS="-Wno-TIMESCALEMOD" +DEFINES="+define+SIMULATION=1 " +readarray -t DEFINE_LINES < ../src/$1/.define +for i in "${DEFINE_LINES[@]}" +do + if ! [[ $i == //* ]]; then + DEFINES+="+define+$i=1 " + fi +done +echo "verilator -cc --compiler msvc $DEFINES $WARNINGS $OPTIMIZE" +verilator -cc --compiler msvc $DEFINES $WARNINGS $OPTIMIZE \ --converge-limit 6000 \ --top-module emu sim.v \ -I../rtl \ -I../rtl/JTFRAME \ +-I../rtl/jt49 \ +-I../rtl/jt5205 \ -I../rtl/tv80 - else - echo "not running on windows" -fi