aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <yalhcru@gmail.com>2019-03-13 02:50:42 -0400
committerB. Watson <yalhcru@gmail.com>2019-03-13 02:50:42 -0400
commit2973d0c78e9b8eed3c5af239927c6bd36af64604 (patch)
treea0fdfe7201303edd11c6d86015ef4f79796fcf0f
downloadfujichat-2973d0c78e9b8eed3c5af239927c6bd36af64604.tar.gz
initial commit
-rw-r--r--README191
-rw-r--r--doc/Compatibility.txt33
-rw-r--r--doc/HOWTO161
-rw-r--r--doc/README396
-rw-r--r--doc/about.txt35
-rw-r--r--doc/newdesign.txt81
-rw-r--r--doc/notes.txt281
-rw-r--r--src/ChangeLog349
-rw-r--r--src/Makefile102
-rw-r--r--src/Makefile.include47
-rw-r--r--src/Makefile.webclient.ok50
-rw-r--r--src/about.c53
-rw-r--r--src/aexec.dasm206
-rw-r--r--src/aexec.h7
-rw-r--r--src/aextest.dasm52
-rw-r--r--src/aextest2.dasm27
-rw-r--r--src/atari850.serbin0 -> 88 bytes
-rwxr-xr-xsrc/atariserver.sh33
-rwxr-xr-xsrc/atariserver_slip.sh70
-rwxr-xr-xsrc/atariserver_slirp.sh48
-rw-r--r--src/bobvert.combin0 -> 1369 bytes
-rwxr-xr-xsrc/clear_rtsbin0 -> 11016 bytes
-rw-r--r--src/clear_rts.c42
-rw-r--r--src/clock-arch.c49
-rw-r--r--src/clock-arch.h41
-rw-r--r--src/col64/autorun.sysbin0 -> 1039 bytes
-rw-r--r--src/col64/col64.binbin0 -> 1039 bytes
-rw-r--r--src/col64/col64.dasm1194
-rw-r--r--src/col64/col64_ext.inc48
-rw-r--r--src/col64/cruft/col64.dasm1194
-rw-r--r--src/col64/cruft/col64.dasm.works731
-rw-r--r--src/col64/cruft/col64.sh6
-rw-r--r--src/col64/cruft/col64_ext.inc48
-rw-r--r--src/col64/cruft/col64font.bdf11993
-rw-r--r--src/col64/cruft/col64font.hex920
-rw-r--r--src/col64/cruft/col64font_almost.bdf11994
-rw-r--r--src/col64/cruft/col64font_ext.bdf11994
-rw-r--r--src/col64/cruft/col64font_ext.hex920
-rw-r--r--src/col64/cruft/col64font_new.bdf11994
-rw-r--r--src/col64/cruft/coltbl.pl17
-rw-r--r--src/col64/equates.inc1386
-rw-r--r--src/col64/font4x5.inc48
-rw-r--r--src/col64/test.atrbin0 -> 92176 bytes
-rw-r--r--src/col80_modified/Makefile15
-rw-r--r--src/col80_modified/autorun.sysbin0 -> 1152 bytes
-rw-r--r--src/col80_modified/col80_hacked.dasm906
-rw-r--r--src/col80_modified/col80_hacked.xexbin0 -> 1152 bytes
-rw-r--r--src/col80_modified/cruft/Makefile45
-rw-r--r--src/col80_modified/cruft/README.txt89
-rw-r--r--src/col80_modified/cruft/autorun.sysbin0 -> 1095 bytes
-rw-r--r--src/col80_modified/cruft/col80.atasm6
-rw-r--r--src/col80_modified/cruft/col80.dasm10
-rw-r--r--src/col80_modified/cruft/col80.info152
-rw-r--r--src/col80_modified/cruft/col80.s21
-rw-r--r--src/col80_modified/cruft/col80.xexbin0 -> 1163 bytes
-rw-r--r--src/col80_modified/cruft/col80_cc65_hack.cfg41
-rw-r--r--src/col80_modified/cruft/col80_dosini_seg.s12
-rw-r--r--src/col80_modified/cruft/col80_entry.s61
-rw-r--r--src/col80_modified/cruft/col80_header_seg.s6
-rw-r--r--src/col80_modified/cruft/col80_include.s50
-rw-r--r--src/col80_modified/cruft/col80_init.s35
-rw-r--r--src/col80_modified/cruft/col80_main.s824
-rw-r--r--src/col80_modified/cruft/col80_main.s.orig895
-rw-r--r--src/col80_modified/cruft/col80_main.xexbin0 -> 1047 bytes
-rw-r--r--src/col80_modified/cruft/col80_orig.xexbin0 -> 1429 bytes
-rw-r--r--src/col80_modified/cruft/col80_runad_seg.s13
-rw-r--r--src/col80_modified/cruft/col80_startaddr.s7
-rw-r--r--src/col80_modified/cruft/col80_startup.s4
-rwxr-xr-xsrc/col80_modified/cruft/dasm2atasm362
-rwxr-xr-xsrc/col80_modified/cruft/dos_20s.atrbin0 -> 92176 bytes
-rw-r--r--src/col80_modified/cruft/font.binbin0 -> 384 bytes
-rw-r--r--src/col80_modified/cruft/font.s54
-rw-r--r--src/col80_modified/cruft/font2xbm.pl47
-rw-r--r--src/col80_modified/cruft/new_font.s48
-rw-r--r--src/col80_modified/cruft/new_font.xbm35
-rwxr-xr-xsrc/col80_modified/cruft/test.atrbin0 -> 92176 bytes
-rw-r--r--src/col80_modified/cruft/xbm2font.pl29
-rwxr-xr-xsrc/col80_modified/dos_20s.atrbin0 -> 92176 bytes
-rw-r--r--src/col80_modified/font2xbm.pl48
-rw-r--r--src/col80_modified/icet.xbm43
-rw-r--r--src/col80_modified/icet_packed.fntbin0 -> 512 bytes
-rwxr-xr-xsrc/col80_modified/icet_to_col80bin0 -> 8996 bytes
-rw-r--r--src/col80_modified/icet_to_col80.c26
-rw-r--r--src/col80_modified/icet_vt.fntbin0 -> 1024 bytes
-rw-r--r--src/col80_modified/icetmod.rawbin0 -> 384 bytes
-rw-r--r--src/col80_modified/icetmod.s48
-rw-r--r--src/col80_modified/icetmod.xbm35
-rw-r--r--src/col80_modified/icetmod_maybe.xbm35
-rw-r--r--src/col80_modified/icetmod_old.xbm35
-rw-r--r--src/col80_modified/lsr.pl29
-rw-r--r--src/col80_modified/new_font.s48
-rw-r--r--src/col80_modified/t.dasm3
-rwxr-xr-xsrc/col80_modified/test.atrbin0 -> 92176 bytes
-rw-r--r--src/col80_modified/xbm2font.pl29
-rw-r--r--src/commands.c206
-rw-r--r--src/common.c255
-rw-r--r--src/common.h27
-rw-r--r--src/dns.c130
-rw-r--r--src/dos25_4drives.atrbin0 -> 92176 bytes
-rw-r--r--src/dos_20s.atrbin0 -> 92176 bytes
-rw-r--r--src/env.sh10
-rw-r--r--src/equates.inc1386
-rw-r--r--src/features.h102
-rw-r--r--src/fuji6432.atrbin0 -> 92176 bytes
-rw-r--r--src/fuji80.atrbin0 -> 92176 bytes
-rw-r--r--src/fuji_asm.s3016
-rw-r--r--src/fujichat-0.1.atrbin0 -> 92176 bytes
-rw-r--r--src/fujichat-0.3.atrbin0 -> 92176 bytes
-rw-r--r--src/fujichat.atrbin0 -> 92176 bytes
-rw-r--r--src/fujichat.atr.okbin0 -> 92176 bytes
-rw-r--r--src/fujichat.c1054
-rw-r--r--src/fujichat.cfgbin0 -> 173 bytes
-rw-r--r--src/fujichat.h136
-rw-r--r--src/fujiconf.c359
-rw-r--r--src/fujimenu.c90
-rw-r--r--src/fujiput.s21
-rw-r--r--src/fujitest.atrbin0 -> 92176 bytes
-rw-r--r--src/getsmess.c66
-rw-r--r--src/hex2inc.pl31
-rw-r--r--src/irc_notes95
-rw-r--r--src/keybuf.h26
-rw-r--r--src/keybuf.s94
-rw-r--r--src/keybuftest.c51
-rw-r--r--src/loadchat.dasm54
-rw-r--r--src/loadmenu.dasm69
-rw-r--r--src/loadmkau.dasm69
-rw-r--r--src/loadtest.c12
-rw-r--r--src/logcomptest.pl229
-rw-r--r--src/logtest.c53
-rw-r--r--src/main.c1184
-rw-r--r--src/makeauto.c177
-rw-r--r--src/mkdisk.sh48
-rw-r--r--src/mkfuji64.sh4
-rw-r--r--src/mkfuji80.sh4
-rw-r--r--src/new_format_ip.s54
-rw-r--r--src/notes.64x34176
-rw-r--r--src/prconn.serbin0 -> 94 bytes
-rw-r--r--src/put.c12
-rw-r--r--src/rs232dev.c299
-rw-r--r--src/rs232dev.h54
-rw-r--r--src/rvert.combin0 -> 1369 bytes
-rw-r--r--src/slattach_rts.diff26
-rw-r--r--src/slirp_debug2
-rw-r--r--src/start_getty.sh19
-rwxr-xr-xsrc/start_slip.sh56
-rw-r--r--src/start_slirp.sh29
-rw-r--r--src/test.atrbin0 -> 92176 bytes
-rw-r--r--src/testip.c10
-rw-r--r--src/uip-conf.h180
-rw-r--r--src/uip_arch.h0
-rw-r--r--src/uip_asm_output.s5253
-rw-r--r--uip/README.uIP13
-rw-r--r--uip/apps/README2
-rw-r--r--uip/apps/dhcpc/Makefile.dhcpc1
-rw-r--r--uip/apps/dhcpc/dhcpc.c356
-rw-r--r--uip/apps/dhcpc/dhcpc.h68
-rw-r--r--uip/apps/hello-world/Makefile.hello-world1
-rw-r--r--uip/apps/hello-world/hello-world.c100
-rw-r--r--uip/apps/hello-world/hello-world.h52
-rw-r--r--uip/apps/resolv/Makefile.resolv1
-rw-r--r--uip/apps/resolv/resolv.c464
-rw-r--r--uip/apps/resolv/resolv.h75
-rw-r--r--uip/apps/smtp/Makefile.smtp1
-rwxr-xr-xuip/apps/smtp/makestrings40
-rw-r--r--uip/apps/smtp/smtp-strings11
-rw-r--r--uip/apps/smtp/smtp-strings.c70
-rw-r--r--uip/apps/smtp/smtp-strings.h46
-rw-r--r--uip/apps/smtp/smtp.c262
-rw-r--r--uip/apps/smtp/smtp.h103
-rw-r--r--uip/apps/telnet/Makefile.telnet1
-rw-r--r--uip/apps/telnet/telnet.c151
-rw-r--r--uip/apps/telnet/telnet.h67
-rw-r--r--uip/apps/telnetd/Makefile.telnetd1
-rw-r--r--uip/apps/telnetd/shell.c123
-rw-r--r--uip/apps/telnetd/shell.h104
-rw-r--r--uip/apps/telnetd/telnetd.c350
-rw-r--r--uip/apps/telnetd/telnetd.h63
-rw-r--r--uip/apps/webclient/Makefile.webclient1
-rwxr-xr-xuip/apps/webclient/makestrings40
-rw-r--r--uip/apps/webclient/webclient-strings31
-rw-r--r--uip/apps/webclient/webclient-strings.c93
-rw-r--r--uip/apps/webclient/webclient-strings.h31
-rw-r--r--uip/apps/webclient/webclient.c439
-rw-r--r--uip/apps/webclient/webclient.h228
-rw-r--r--uip/apps/webserver/Makefile.webserver1
-rw-r--r--uip/apps/webserver/http-strings35
-rw-r--r--uip/apps/webserver/http-strings.c102
-rw-r--r--uip/apps/webserver/http-strings.h34
-rw-r--r--uip/apps/webserver/httpd-cgi.c203
-rw-r--r--uip/apps/webserver/httpd-cgi.h84
-rw-r--r--uip/apps/webserver/httpd-fs.c132
-rw-r--r--uip/apps/webserver/httpd-fs.h57
-rw-r--r--uip/apps/webserver/httpd-fs/404.html8
-rw-r--r--uip/apps/webserver/httpd-fs/fade.pngbin0 -> 196 bytes
-rw-r--r--uip/apps/webserver/httpd-fs/files.shtml35
-rw-r--r--uip/apps/webserver/httpd-fs/footer.html2
-rw-r--r--uip/apps/webserver/httpd-fs/header.html18
-rw-r--r--uip/apps/webserver/httpd-fs/index.html29
-rw-r--r--uip/apps/webserver/httpd-fs/processes.shtml5
-rw-r--r--uip/apps/webserver/httpd-fs/stats.shtml31
-rw-r--r--uip/apps/webserver/httpd-fs/style.css92
-rw-r--r--uip/apps/webserver/httpd-fs/tcp.shtml5
-rw-r--r--uip/apps/webserver/httpd-fsdata.c607
-rw-r--r--uip/apps/webserver/httpd-fsdata.h64
-rw-r--r--uip/apps/webserver/httpd.c338
-rw-r--r--uip/apps/webserver/httpd.h62
-rwxr-xr-xuip/apps/webserver/makefsdata78
-rwxr-xr-xuip/apps/webserver/makestrings40
-rw-r--r--uip/apps/webserver/webserver.h49
-rw-r--r--uip/lib/memb.c104
-rw-r--r--uip/lib/memb.h142
-rw-r--r--uip/uip-1.0-changelog.txt98
-rw-r--r--uip/uip/Makefile.include47
-rw-r--r--uip/uip/clock.h88
-rw-r--r--uip/uip/lc-addrlabels.h83
-rw-r--r--uip/uip/lc-switch.h76
-rw-r--r--uip/uip/lc.h131
-rw-r--r--uip/uip/psock.c338
-rw-r--r--uip/uip/psock.h380
-rw-r--r--uip/uip/pt.h323
-rw-r--r--uip/uip/timer.c127
-rw-r--r--uip/uip/timer.h86
-rw-r--r--uip/uip/uip-fw.c532
-rw-r--r--uip/uip/uip-fw.h176
-rw-r--r--uip/uip/uip-neighbor.c159
-rw-r--r--uip/uip/uip-neighbor.h61
-rw-r--r--uip/uip/uip-split.c136
-rw-r--r--uip/uip/uip-split.h96
-rw-r--r--uip/uip/uip.c1912
-rw-r--r--uip/uip/uip.h1603
-rw-r--r--uip/uip/uip_arch.h138
-rw-r--r--uip/uip/uip_arp.c423
-rw-r--r--uip/uip/uip_arp.h144
-rw-r--r--uip/uip/uiplib.c74
-rw-r--r--uip/uip/uiplib.h71
-rw-r--r--uip/uip/uipopt.h544
-rw-r--r--uip/unix/Makefile44
-rw-r--r--uip/unix/clock-arch.c55
-rw-r--r--uip/unix/clock-arch.h40
-rw-r--r--uip/unix/main.c218
-rw-r--r--uip/unix/tapdev.c152
-rw-r--r--uip/unix/tapdev.h45
-rw-r--r--uip/unix/uip-conf.h157
243 files changed, 90518 insertions, 0 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..25ef2cb
--- /dev/null
+++ b/README
@@ -0,0 +1,191 @@
+FujiChat - an Atari 8-bit IRC client.
+
+Features:
+
+- Join and chat in an IRC channel (only one at a time, for now).
+- Send and receive private messages to/from other users.
+- Runs a TCP/IP stack on the Atari, including TCP, DNS, and SLIP.
+- Works with all Atari 8-bit computers (400/800/XL/XE) provided they
+ have at least 48K of RAM and a supported RS232 port.
+- Works with SIO2PC, Atari 850, or ICD P:R: Connection RS232 ports.
+- Supports up to 9600 baud serial connection (depending on hardware used).
+- Fully open source (BSD licensed).
+- Ready-to-boot ATR image also supplied (fujichat.atr).
+
+Contents:
+
+README - you're reading it now.
+doc/ - documentation, including (possibly obsolete) design notes.
+src/ - FujiChat source, excluding uIP library.
+uip/ - Modified/hacked-up version of Adam Dunkels' uIP, used as a library.
+
+To compile FujiChat:
+
+- First, install cc65. Needs to be a snapshot or release later than the
+ 2.11.0 release, but older than about December, 2015. Version 2.13.3 is
+ what the author currently uses. The code uses the old cc65 rs232.h API,
+ which was replaced with a new serial.h API sometime in 2015. This will
+ be rectified eventually.
+
+- Next, install axe. This can be found at http://urchlay.naptime.net/repos/axe/
+ or use the clone URL git://urchlay.naptime.net/axe.git
+
+Make sure cc65 and axe are both found in your $PATH, then:
+
+$ cd src
+$ make
+$ make disk
+
+This will build an ATR image called fujichat.atr. This is a bootable image
+with DOS 2.0S and everything you need to run FujiChat. See doc/README
+for more detail.
+
+Running FujiChat:
+
+fujichat.atr is a bootable DOS 2.0S floppy disk. It must be booted with
+BASIC disabled (remove cartridge on 400/800/1200XL, hold Option down
+on XL/XE).
+
+The first time FujiChat boots, it'll ask what serial port driver you
+want to use. Once you've selected this, you'll be prompted to reboot.
+It's not recommended to choose 1 (no driver/manual setup); this option
+exists mainly for testing.
+
+After the serial driver has been selected, FujiChat will boot into
+its main menu. The first thing you'll want to do is choose S for Setup.
+You'll be prompted for all the settings. The main ones are:
+
+- Baud rate. 4800 is the "safe" choice here, and works on most hardware.
+ 9600 baud may or may not work for you. 19200 baud probably won't work
+ for anyone (yet?)
+
+- Local IP address and Peer IP address. You shouldn't have to change
+ these (just press Enter for the defaults), *unless* your LAN is
+ already using the 192.168.0/24 net block! If this is the case, try
+ 10.0.0.1 and 10.0.0.2 for these.
+
+- DNS server. Most people will enter their ISP-assigned DNS server here.
+ In a pinch, you might try 8.8.8.8 (Google's public DNS server).
+ If you run DNS service on your local Linux/whatever system, you can
+ use the same IP as you entered for Peer IP address here.
+
+- IRC server. You can choose one of the listed servers, or enter any
+ hostname or IP address instead.
+
+- Server port. Normally 6667. Some servers may support other port numbers,
+ but there doesn't seem to be any real advantage to using them. Do NOT
+ enter the port number for secure IRC here; FujiChat does NOT support
+ SSL/TLS encryption (and never will: the Atari would take a week to
+ do the math needed to initiate a secure connection).
+
+- Your nickname. The name you want to be known by, on IRC. This should
+ be a short name, and different IRC networks allow different lengths. All
+ networks allow at least 9 characters here, and FujiChat is limited to
+ 20. If you're new to IRC, you should know that spaces are not allowed
+ here, and only some punctuation is allowed. Best bet is to stick with
+ alphanumerics. Mixed case is allowed (you could be johnsmith, Johnsmith,
+ or JohnSmith). Try to choose a name unlikely to already be in use.
+
+- Your 'real' name. This is visible to all users on IRC, so you probably
+ don't want to put your *real* name. The default is "FujiChat User", which
+ is fine. Unlike the nickname, this doesn't have to be unique.
+
+- Autojoin channel. If you enter 0 here, FujiChat won't automatically join
+ any channel (you would use the /join command after connecting, instead).
+ Normally channel names are prefixed with a # (e.g. #atari), but on
+ Freenode, some channels have two # instead (e.g. ##atari). If the
+ channel you want to join requires a NickServ login or similar, don't
+ try to autojoin it. You'll have to connect, then manually authenticate
+ (e.g. /m NickServ id <username> <password>), then manually join
+ the channel.
+
+- Background and foreground colors. Standard decimal Atari color register
+ values (hue * 16 + luminance). The defaults are 192 and 12, which gives
+ a dark green background with very bright green text.
+
+- Disable bell. FujiChat is capable of using either the regular Atari
+ "buzzer" audio bell, or a visible "bell" that briefly flashes the
+ border color. Saying Y here disables both visual and audio bells.
+
+- Visual bell. When you say Y here, you'll get the visual bell described
+ above, and no audio bell. If you say N, you'll get the audio bell.
+
+- Bell on msg. If you like to be notified when you get a private message,
+ say Y here. If you find this annoying or distracting, say N.
+
+- Show ping/pong. Default is N, and most people will want to leave it this
+ way. Every few minutes, the IRC server sends a "ping" to FujiChat (or
+ any other IRC client), and FujiChat responds with a "pong" to let the
+ server know it's still "alive". If the pong never arrives, the server
+ assumes the client is dead, and drops the connection. Showing the
+ ping/pong messages is probably only useful for development/testing; in
+ normal use they just waste screen space.
+
+- Hide MOTD. Every time you connect to an IRC server, it sends you a
+ "message of the day", which contains lots of general info about the
+ IRC network. Unfortunately, on some networks, the MOTD is really
+ long and verbose, and takes several minutes to receive and display
+ on the Atari. There's no way to prevent the server sending the MOTD,
+ and the server won't respond to commands (such as joining a channel)
+ until it's done sending the MOTD. However, hiding the MOTD (not
+ printing it) will speed up connection times, because the Atari isn't
+ very fast at printing text and scrolling its sreen. Leave this option
+ enabled, unless you're very curious about what's in the MOTD (and
+ also very patient).
+
+- Is this correct [Y/n]. If you made a mistake entering one of the
+ settings, say N here and you'll get a chance to re-enter them.
+
+- Save this config [Y/n]. Normally you'll say Y here, to save the config
+ to D:FUJICHAT.CFG. If you're just testing a different config, you can
+ say N. The config will remain in memory and FujiChat will use it. If
+ you reload the setup/config program from within FujiChat, the settings
+ from memory will be used as defaults for the prompts.
+
+- Start FujiChat now [Y/n]. Does just what it says. If you're using the
+ SIO2PC for both disk emulation and RS232, wait for FujiChat to finish
+ loading (it'll show a "connect to server" prompt), then exit your disk
+ emulation software (or e.g. "stop emulation" in Respeqt), then run the
+ start_slip.sh script (or whatever else you use to start SLIP service
+ on your PC/Mac/whatever). Press Enter to connect to the IRC server,
+ and if you did everything just right, it should Just Work...
+
+Notes:
+
+Docs for uIP have been removed from this distribution, partly to save
+space, and partly because the included version of uIP has been modified.
+If you want to write a new app using uIP, you're better off starting
+with the original sources, not my hacked-up mess.
+
+Limitations:
+
+As said before, FujiChat is only able to join one IRC channel at a time.
+
+If your channel requires authentication with e.g. Freenode's NickServ
+before being allowed to join it, you'll have to configure FujiChat
+*not* to auto-join the channel. Once connected, you'll have to manually
+authenticate, then manually /join the channel.
+
+A lot of features found on IRC clients for more modern systems just
+don't exist, either because of limited memory on the Atari, or because
+the author just hasn't gotten around to adding them yet. There's no nick
+list, logging, multiple windows, scrollback, triggers... channel text
+from channel operators doesn't show an @ next to their nick... nick
+completion (tab completion) doesn't exist, although you *can* use the
+Tab key to respond to the most recent user who sent you a PM.
+
+There are known bugs in FujiChat:
+
+The /msg command (and several others) doesn't correctly quote its
+argument, which means if you say "/msg somebody Hello, I'm on my Atari",
+they'll receive only the first word (the "Hello,"). Temporary workaround:
+say "/msg somebody :Hello, I'm on my Atari" (in other words prefix your
+message with a colon).
+
+The /ping command doesn't play nice with modern FreeNode servers, meaning
+you get either no ping responses, or else it prints a ping time >= 2500
+seconds.
+
+Not really a bug, but a missing feature: non-ASCII characters (accented
+letters, British pound symbol, etc) are printed as inverse video
+gibberish. At some point these will be handled more gracefully.
diff --git a/doc/Compatibility.txt b/doc/Compatibility.txt
new file mode 100644
index 0000000..cc47ab5
--- /dev/null
+++ b/doc/Compatibility.txt
@@ -0,0 +1,33 @@
+FujiChat has so far been tested with:
+
+Serial Interfaces:
+
+SIO2PC + Bob-Verter driver [*]
+ATR8000 serial port [*]
+Atari 850 (Atari driver) [!]
+Black Box [!]
+P:R: Connection
+
+[*] = hardware handshaking not supported or not tested; requires patched
+slattach binary for higher baud rates; probably limited to 4800 baud.
+
+[!] = hardware handshaking tested and working (with unpatched slattach)
+
+DOSes:
+
+Atari DOS 2.0S
+SpartaDOS X 4.x (use 'X' command)
+MyDOS 4.5
+
+Display drivers:
+
+XEP-80 (ABBUC driver)
+CON80.SYS and CON64.SYS (Sparta X)
+Omniview 80
+
+FujiChat is known not to work with ClausB's old E80 driver, and probably
+won't work with ACE-80 either (untested).
+
+Misc:
+
+Atari CX-85 (numeric keypad)
diff --git a/doc/HOWTO b/doc/HOWTO
new file mode 100644
index 0000000..53bbe5c
--- /dev/null
+++ b/doc/HOWTO
@@ -0,0 +1,161 @@
+How to run a TCP/IP stack on an Atari 8-bit
+-------------------------------------------
+
+You will need:
+
+1. An Atari 8-bit computer with at least 48K of RAM
+2. A Linux box with:
+3. A recent snapshot of cc65. 2.12.0 won't work. I used 2.12.9.20080831.
+4. SLIP support in your Linux kernel (try "modprobe slip")
+5. Some way to get an Atari program from your Linux box to your Atari, so
+ you can run it. I use an SIO2PC cable and AtariSIO, and "axe" for
+ writing files into an ATR image.
+6. An RS232 serial interface for your Atari. I use the same SIO2PC cable
+ as (5) for this. Other possibilities are an 850, P:R: Connection,
+ R-Verter, etc.
+
+
+Before building the Atari program, you should get a copy of the R:
+handler (device driver) that's needed for your Atari to talk over the
+serial port, and copy it to rhandler.xex in the source directory. In
+general, whatever R: handler you use with Bobterm or Ice-T will work
+fine. The shipped copy of rhandler.xex is the Bob-Verter driver, which
+works great with an SIO2PC cable.
+
+Run "make" to compile and "make disk" to build the ATR image uiptest.atr.
+This is a bootable disk with DOS 2.0S and the uIP demo program as
+AUTORUN.SYS (with R: handler prepended to it).
+
+Boot the disk, wait for it to finish loading. You should see "Press Return
+to connect". At this point, you should start SLIP on your serial port,
+then press Return on the Atari. If you've done everything right, the Atari
+should connect to the remote host!
+
+What you have to do to start a SLIP interface depends on what you're
+using as a serial interface on the Atari, and whether it's the same
+device as you'll use to load the code into the Atari. Most motherboards
+these days have only one serial port (if any), so if you're doing drive
+emulation, you'll have to switch between the drive emulator software
+(e.g. atariserver) and SLIP mode on the same serial port (or run drive
+emulation on one machine and SLIP mode on a second). If you're lucky
+enough to have two serial ports on your Linux box, and own an SIO2PC
+and an 850 or other Atari RS232 interface, you can run SLIP on one Linux
+serial port all the time and atariserver on the other all the time.
+
+Note: atariserver will NOT work with USB-to-RS232 adaptors. sio2linux
+theoretically might, but in practice usually doesn't. It *should* be
+possible to run SLIP over a USB adaptor though (but I haven't tried it).
+
+Another note: For some reason, the uIP code doesn't run if it's loaded
+from MyPicoDOS (the built-in loader in atariserver). This is why you
+need to create an actual DOS ATR image for use with atariserver.
+
+
+850, P:R: Connection, R-Verter, or "dumb" SIO2PC as serial device
+-----------------------------------------------------------------
+
+To start SLIP mode on your Linux machine's serial port, you should be able
+to use the "slattach" that came with your system. If you don't have this
+program installed, you'll have to find out what package it belongs to
+(on Slackware and Debian, that's the net-tools package, and it's highly
+unlikely that it wouldn't already be installed).
+
+Actually, slattach won't work if your R: device doesn't have the hardware
+handshaking lines connected (this is true of the SIO2PC, and for most
+other devices it depends on how your cable was made). From slattach's
+documentation, it looks like the -L option (local mode, no HW handshake)
+should work, but it won't due to a bug in slattach. You can use the
+patched version (see next section) if you don't have HW handshaking.
+
+The start_slip.sh script does everything that's needed to fire up a SLIP
+connection for uIP to use. There are some config options at the top of
+the script (to set the port, baud rate, etc), make sure these are correct.
+
+If you've got working hardware handshaking, you should be able to do
+9600 baud. This has been tested on the 850 and works well. 19200 may
+even work, if your device & driver support it. Without handshaking,
+the maximum reliable speed seems to be 4800 baud (you could try 9600,
+but it probably won't work). Speed isn't really *that* important for
+IRC anyway.
+
+
+Auto-sensing SIO2PC as serial device
+------------------------------------
+
+If using a Steve Tucker SIO2PC (the auto-sensing kind), slattach has to
+be patched slightly. Get net-tools-1.60, patch it up to 1.60-19, then
+apply slattach_rts.diff. Compile net-tools, copy slattach to someplace on
+your PATH (don't overwrite the one in /sbin or /usr/sbin! I renamed my
+patched version to a8_slattach). You can find the net-tools-1.60 source
+and the 1.60.19 patch here:
+
+ftp://ftp.slackware.com/pub/slackware/slackware-12.1/source/n/net-tools
+
+(Note: you don't have to be running Slackware to use the sources,
+that's just a handy place to download them from)
+
+Run "make" to build. It'll ask you a lot of questions about what protocols
+& hardware your system supports; the answers are not too important,
+so long as you say yes to SLIP support and TCP/IP. Don't do a "make
+install", just copy slattach somewhere like /usr/local/bin/a8_slattach
+
+
+Using the same serial port for drive emulation and SLIP
+-------------------------------------------------------
+
+If using atariserver, you have to load & unload the atarisio module,
+it won't play nice with SLIP. Use atariserver_slip.sh (which can be
+configured a bit by changing the variables at the top). If you prefer, you
+could use sio2linux instead of atariserver, but it's slow and occasionally
+just fails to work on my system. If sio2linux works OK for you, it's
+easier to deal with because it just uses the serial port device instead of
+loading a kernel module that "takes over" the port the way atarisio does.
+
+
+Other hardware
+--------------
+
+If you've got some other way to get the code to your Atari that doesn't
+involve a serial port (such as a MyIDE or S-Drive, or maybe a Black Box
+with removable media, or just another Linux box with its own serial port),
+you can run start up SLIP on your serial port with start_slip.sh and
+leave it running forever. Unlike PPP, the SLIP protocol doesn't really
+"connect" to the other side of the serial line, so there's no need to
+restart SLIP if you reboot the Atari.
+
+
+Other OS
+--------
+
+If you aren't running Linux, you can still use SLIP.
+
+- Free/Net/OpenBSD: follow the Handbook for setting up a SLIP connection,
+ plus NAT or Masquerading (whatever the BSD terminology is).
+ Unknown whether it'll work without hardware handshaking.
+
+- Mac OS X: has slattach, which appears to be the same as the Linux version.
+ Unknown whether it'll work without hardware handshaking. No idea whether
+ OSX supports NAT/masquerade (bet it does though).
+
+- Windows: in theory it's possible to either use SLIrP with Cygwin, or
+ else the built-in "Direct Cable Connection" (which exists in at least
+ Windows 98 through XP, but has been dropped in Vista). You'd want to
+ enable "Internet Connection Sharing", too.
+
+ It also should be possible to run SLIrP on a TCP port on either your
+ Windows machine or some other host, and configure APE's R: TCP/IP
+ emulation to connect to this host and port. In effect you'd be running
+ SLIP over TCP.
+
+ Yet another way to use uIP with Windows would be to use a virtual (emulated)
+ machine running Linux (e.g. using qemu or possibly VirtualBox). At least
+ one user has successfully done this.
+
+- Some "serial terminal server" devices may support SLIP. I'm pretty sure
+ at least one model made by Lantronix does. If you have one of these,
+ let me know how (or if) it works.
+
+NOTE: If your OS has "Compressed SLIP", "CSLIP", "VJ Compression", or any
+SLIP-related option named similarly, DISABLE it. uIP does not support
+compressed SLIP.
+
diff --git a/doc/README b/doc/README
new file mode 100644
index 0000000..24d40b0
--- /dev/null
+++ b/doc/README
@@ -0,0 +1,396 @@
+FujiChat v0.1: An IRC client for the Atari 8-bit
+-------------------------------------------
+
+FujiChat is a simple IRC (Internet Relay Chat) client for Atari 8-bit
+(400/800/XL/XE) computers, based on the uIP TCP/IP stack. It uses a SLIP
+connection to talk to the outside world, and supports a subset of the IRC
+commands available in full-featured clients. 48K of memory is required
+(and extended memory is not used, so it can coexist with RAMdisk drivers
+and such).
+
+Capabilities:
+
+- Can connect to an IRC server, and:
+- Join a channel
+- Send and receive channel and private messages
+- Actions (/me does whatever) are supported
+- Part the channel and join a new channel
+- Most IRC slash-commands are available
+- Client responds to CTCP PING and VERSION requests
+- Client can send CTCP PING and VERSION requests
+- Client responds correctly to server PINGs (with PONG)
+
+Limitations:
+
+These are listed approximately in order of severity, and will be addressed
+in future versions in approximately the order shown here.
+
+
+- The user interface is extremely crude (almost non-existent)
+- Try not to accidentally hit the Break key. It may result in weird
+ behaviour (though it usually doesn't)
+- Editing is extremely crude: only backspace, delete line, and delete
+ word are supported
+ (future versions will probably support emacs-like key bindings)
+- Currently, the client can only join one channel at a time. Attempts
+ to join a second channel before parting the first will fail. (future
+ versions may allow joining multiple channels, but probably no windowing, so
+ the channels' text will appear mixed together on the screen)
+- Many client features like logging, scrollback, nick highlighting, DCC,
+ multiple windows, nick completion, etc are missing. Some of these will
+ be added in future versions, but some would just take too much memory
+ to fit in 48K. (future versions are planned to have at least tab-completion
+ of nicks, and possibly a small scrollback buffer. A limited number of
+ multiple channel/msg windows is not out of the question)
+- There is no nick list displayed. At any time you can use /names #channel
+ or /who #channel to see who else is in the channel (or press ctrl-N
+ or ctrl-W), but the client doesn't attempt to track other users'
+ joins/parts/quits. (future versions may track the nick list and display
+ it as a separate screen, e.g. you press Option to see it)
+- The characters {, }, `, and ~ are not printable on the Atari. Instead they
+ are rendered as inverse-video [, ], ', and ^, respectively (future versions
+ will probably use a custom font to display these characters)
+- mIRC-style color and bold codes are not interpreted at all. They will
+ be displayed as ATASCII graphics characters (future versions will strip
+ color codes and may display bold as inverse video)
+- Most CTCP commands are unsupported (and DCC will likely never be supported)
+- Private messages from other users appear mixed in with channel text
+- Text is displayed in GRAPHICS 0, meaning it's 40 columns by 24 lines,
+ with no support for multi-colored text or anything fancy like italics
+ or underlines. It might be possible to do an Ice-T style 80 column
+ display, but it's a pig (8K for the graphics mode, plus at least 1K
+ for the font, plus rendering/scrolling is slow and might result in
+ serial buffer overruns if I'm not careful). It might instead be possible
+ to do a 40-column display with 4 or 8 character colors, using P/M overlays,
+ which would result in some visible flicker, but the overall effect isn't
+ too painful. This would require a lot less RAM and CPU cycles than the
+ 80-column mode.
+
+As you can see, FujiChat is more defined by what it can't do than what it
+can, at the moment :)
+
+Configuration:
+
+The default config is stored in the file FUJICHAT.CFG in a binary format
+(not human readable). If the config file is missing at startup, FujiChat
+will start up in its config menu. If the config file was loaded, you
+will be asked "Use defaults [Y/n]?"; answering N will take you to the
+config menu.
+
+The first step in the config menu is to choose an IRC server. FujiChat
+comes with a short list of server IP addresses, which you may select
+from by entering the number of the server. You may also enter any IP
+address at the prompt, to use a server not in the built-in list. (As
+soon as I've debugged the DNS code, you'll be able to use hostnames, but
+for this release we're stuck with IP addresses only)
+
+The next step is to choose your IRC nickname. The different IRC networks
+have different limits on the maximum length of a nick, but all networks
+support at least 9 characters. FujiChat limits your nick to 20 characters.
+
+IRC forbids certain characters in a nickname: they may not start with
+a hyphen, and must consist of letters, numbers, or the characters:
+- [ ] { } ` _ \ ^
+Note that FujiChat does NO checking for invalid characters in your nick!
+
+The next two options are the background and foreground colors. These are
+standard Atari color register values (chroma/luma) to be used for the
+GRAPHICS 0 text background and foreground registers. Try not to set
+them to the same thing; you won't be able to see any text if you do!
+
+When you're done, you'll be asked whether or not you want to save the
+config. If you answer N, the options you just entered will be used for
+the current session only.
+
+Connecting to IRC:
+
+To set up a SLIP connection between your Atari and another host on your
+network, see the file HOWTO.
+
+The following instructions assume you have a properly configured SLIP
+connection, including NAT/Masquerade if required.
+
+The default IRC server is in the US, and is known not to work well for
+users in Europe. FujiChat has a short list of NewNet IRC servers built
+in (accessible from the "IRC Server" config menu), or you can enter any
+other IP address. To find the IP address of a server, you can use a tool
+such as "nslookup" or "dig", or simply ping the host from your Linux box.
+
+To connect to the IRC server, choose "Connect" from the main config menu.
+At this point, FujiChat will open a TCP connection to the server. Within
+a few seconds, you should start seeing messages from the IRC server.
+
+Once the connection is made, FujiChat will attempt to register
+your nickname and host. If your primary nickname is already in use,
+registration will fail, and you will see a server message informing you
+of this. If this happens, choose a different nickname and type "/nick
+<nickname>" (and press Return).
+
+After your nickname is registered, the server will send its "message of
+the day" (the MOTD). On NewNet, the MOTD tends to be very long, and there's
+no way to skip or abort it, so be patient.
+
+Once the MOTD has finished, the connection is ready to use. At this point,
+you can use the /join command to join a channel and start chatting!
+
+[Note: There's no way to tell the server not to send the MOTD. I could
+add an option to FujiChat to make it not *display* the MOTD, but your
+serial port's bandwidth would still be starved, and you wouldn't be able
+to get much chatting done]
+
+How to use IRC:
+
+[This section is written as an intro for someone who's completely new
+to IRC. Apologies if it seems condescending...]
+
+Before you can chat with other users, you must find some users to chat to.
+The normal place to do this is in an IRC "channel". Think of the IRC network
+as a giant building (a castle, or maybe a convention center). Each channel
+is like a room within the larger building.
+
+Channels have names that usually start with a # character. The rest of
+the name usually describes the usual topic of conversation on the
+channel. For instance, the channel #atari is about (you can guess this
+but...) Atari computers and video games.
+
+The act of entering a channel (room) is known as "joining" the channel.
+To do this, you connect to the IRC server, then type "/join" followed
+by the channel name. Example:
+
+/join #atari
+
+[FujiChat only allows joining one channel at a time, in the current
+version. Future versions may support multiple channels]
+
+Unlike a real room, the IRC channel will be created if it doesn't already
+exist. You'll know this happened if the channel's names list only shows
+your nickname.
+
+It's possible to get a complete list of channels from the IRC server, but
+this is really time-consuming (there are thousands on a typical network),
+and FujiChat doesn't provide a way to scroll through them. You can search
+for channels by name by using wildcards with the /list command. Example:
+you want to talk about cars. Try the following command:
+
+/list *cars*
+
+(Also, /list *auto*, since a car channel might be called something with
+"automobile" or "automotive" in its name).
+
+Also, for many common topics, you can just try using the topic name as
+the channel name (/join #music, /join #beer, /join #unix). Chances are
+it exists, and no harm is done if it doesn't.
+
+Once you've joined a channel, you'll be presented with a list of all
+the users in the channel, and anything you type (other than commands
+beginning with a slash (/)) will be sent to everyone in the channel.
+
+Text from other users will appear like this:
+
+<Bob> Hi there!
+
+Text you type will appear in inverse video. It will only be sent to the
+server when you press Return. You can use the backspace key to correct
+typos, or press shift-backspace to delete the entire message without
+sending it. (Future FujiChat versions will support the other Atari
+editing keys)
+
+IRC also supports private messages, which are sent to only one user.
+To send someone a private message, use the /msg (or /m) command:
+
+/msg Bob Hello
+
+When you receive a private message, it looks like this:
+
+MSG: <Bob> Howdy
+
+To reply, you would type "/msg Bob whatever you want to say".
+
+When you receive a private message, you can press the Tab key at the
+start of a new message to insert "/msg <nick> ", where <nick> is the user
+who last sent you a private message. This is handy for carrying on long
+private conversations, though you should be careful: Tab always sends
+to the last person who messaged you. If you unexpectedly get a message
+from a third party during a private conversation, you might accidentally
+send to the wrong person! Future versions of FujiChat will track more
+than one conversation, using Tab to cycle through all recent message
+recipients.
+
+IRC also supports the concept of channel operators (known as "ops"). These
+are people who "own" the channel, and have the power to kick other users
+out, ban them from the channel, set the channel topic, and a few other
+things. Channel operators' nicknames will be display in the nick list
+with an @ in front of them. Most channel operators are friendly folk
+who will help you out and answer "newbie" IRC questions, unless you're
+rude or repeatedly break the channel rules.
+
+Higher up on the food chain are IRC server operators (known as "opers").
+These godlike entities shouldn't be bothered with everyday mortal
+concerns, but sometimes you have a real problem and they're the only ones
+who can help. Most IRC networks have a channel where the opers hang out
+(usually listed in the MOTD text).
+
+IRC commands:
+
+[This is far from a complete list. Actually, different IRC servers/networks
+may have their own custom commands, so it would be very difficult to
+give a 100% complete list]
+
+IRC commands begin with a slash (/) character, and may take zero or more
+parameters. In the list the following conventions are used:
+
+<channel> represents a channel name, including the leading # character.
+IRC channel names generally always start with a #, but some servers may
+support special types of channels that begin with a different character.
+
+<nick> represents a user's nickname.
+
+<message> represents chat message text (whatever you want to say). This
+is free-form and generally should only include printable characters. IRC
+limits the length of a message to 510 characters. FujiChat further limits
+outgoing messages to 256 bytes, and will ring the Atari's "bell" if you
+try to type a message longer than this.
+
+If any of the above are shown in [] (square brackets), suck as [<nick>],
+this means the parameter is optional.
+
+/join <channel>
+
+Join a channel. You may only chat in one channel at a time in the current
+version of FujiChat. If you attempt to join a channel that does not already
+exist, most IRC servers will create the channel for you. The /join
+command may be abbreviated "/j".
+
+/part
+
+Leave the current channel. You must do this before joining a different
+channel. If you want to leave IRC (disconnect from the server), you
+don't have the /part the channel (simply use the /quit command)
+
+/nick <nick>
+
+Change your nickname. The server will respond with an error message if
+you try to use an invalid nick, or one that's already in use. If the
+command succeeds, there will be no response.
+
+/me <message>
+
+Send an "action". Other users will see your nick prefixed to the message,
+so that it looks like a sentence.
+
+Example: If your nick is Bob, and you type "/me is using FujiChat",
+it will appear to other users as something like:
+
+* Bob is using FujiChat
+
+/msg <nick> <message>
+
+Send a private message to another user. The /msg command may be abbreviated
+as "/m" or spelled the long way as "/privmsg".
+
+/quit <message>
+
+Quit IRC. The server will disconnect you, and FujiChat will give you
+the option to reconnect or return to the main menu. The <message>
+is optional. All users in the current channel will see the <message>,
+which could be something like "Nice talking to everyone", or give the
+reason why you're leaving IRC ("Wife needs to play M.U.L.E."). If you
+don't supply <message>, the server will just use your nick in place of it.
+
+/ping <nick>
+
+Send a CTCP PING request to a user. When the user's client receives the
+request, it will respond with a "pong". This is useful for determining
+whether the user is still connected to the IRC network. Also, if the
+response takes a long time to show up, you'll know there's a lot of
+network lag between you and the other user. (Future versions of FujiChat
+may calculate & display the lag time for you)
+
+/version <nick>
+
+Send a CTCP VERSION request to a user. The user's client will usually
+respond with the name of the client software and its version, although
+most clients can be set up to say anything the user wants, or nothing
+at all. FujiChat responds to other users' version requests with
+"FujiChat 0.1 (Atari 8-bit)".
+
+/ignore <nick>
+
+Ignore (don't print) any and all messages from <nick>. If no <nick>
+is given, /ignore shows the list of nicks that are being ignored.
+Up to 10 nicks can be ignored in the current version of FujiChat.
+When you ignore someone, they don't have any way to know that you're
+ignoring them (they don't get a message telling them).
+
+/unignore <nick>
+
+Stop ignoring a user. To clear the entire list (stop ignoring all ignored
+users at once), use "/unignore -a".
+
+/quote <message>
+
+Send a string directly to the server, verbatim, instead of to the current
+channel you've joined. If you don't know what this command is good for,
+don't worry about it: it's mostly used by the author as a debugging tool.
+
+Keyboard Macros:
+
+These are only active at the beginning of a line (in other words, you
+can't send them when you're in the middle of typing a message). The
+macros are:
+
+Control-N: performs a "/names #channel" for the currently joined channel.
+Control-W: performs a "/who #channel" for the currently joined channel.
+Tab: inserts the text "/msg nick" at the beginning of the line, where
+ the nick is that of the last user who sent you a private message.
+
+There may be a user-definable keyboard macro facility in a future version
+of FujiChat (or maybe not, if it'd make the client too bloated).
+
+Other IRC commands:
+
+Most other commands are supported in a dumb kind of way. Anything you
+type that starts with a slash, and isn't one of the recognized commands
+listed above, will be sent to the server with the slash removed and
+the command name converted to uppercase. This works pretty well for
+commands like /away, /kick, /mode, /topic, etc:
+
+Kick a user from a channel (if you're a channel operator):
+/kick <channel> <nick> [<message>]
+
+Ban a user from a channel (again, you must be a chanop):
+/mode <channel> +b <nick>
+
+Get a list of who's in a channel:
+/names <channel>
+
+Get a fancier list:
+/who <channel>
+
+NewNet-specific command: log in to NickServ
+/ns id <password>
+
+See RFC1459 for a complete protocol specification. Any of the commands
+shown there can be sent by prefixing them with a / character.
+
+RFC1459 on the web:
+http://www.rfc-editor.org/cgi-bin/rfcdoctype.pl?loc=RFC&letsgo=1459&type=http&file_format=txt
+
+Credits:
+
+FujiChat is written by B. Watson (aka Urchlay on NewNet).
+
+FujiChat includes software (the uIP TCP/IP) stack by Adam Dunkels. Without
+Mr. Dunkels' excellent and well-documented software, FujiChat probably
+would never have been more than a pipe dream.
+
+FujiChat also includes the Bob-Verter driver by Bob Puff.
+
+Special thanks to SteveS and Beetle for being my guinea pigs (erm, I mean,
+beta testers)
+
+You're invited to come hang out in #atari on NewNet any time. You can
+usually find me there, although I may be asleep at the keyboard. If you
+have trouble getting FujiChat to work, or have a bug report or feature
+request, or if you just use FujiChat, I'd like to hear from you.
+
diff --git a/doc/about.txt b/doc/about.txt
new file mode 100644
index 0000000..28f5a73
--- /dev/null
+++ b/doc/about.txt
@@ -0,0 +1,35 @@
+# Try to keep the lines <= 39 chars,
+# but the reader can handler up to 199 char/line.
+# Comment lines (like this one) are ignored.
+FujiChat: an Atari 8-bit IRC client
+(c) 2008 B. Watson (aka Urchlay)
+
+Version 0.4, 20081019
+
+This program includes the uIP TCP/IP
+stack, (c) Adam Dunkels.
+
+Bob-Verter driver (c) 1989, Bob Puff
+
+[insert legalese krap here]
+[more legalese]
+[it's going to take up a few lines]
+[...]
+[...]
+[I hate legalese]
+
+[Long line that should be handled correctly by the line-counting logic. It's 3 screen lines.]
+
+Special thanks to the FujiChat alpha
+testers:
+
+- Beetle
+- charliec
+- SteveS
+
+...and the rest of the NewNet #atari
+crowd.
+
+Stop by #atari sometime and say hi,
+everyone's welcome!
+
diff --git a/doc/newdesign.txt b/doc/newdesign.txt
new file mode 100644
index 0000000..8e45fab
--- /dev/null
+++ b/doc/newdesign.txt
@@ -0,0 +1,81 @@
+/* TODO: move the non-IRC-related config to a separate SETUP program,
+ and a separate UIP.CFG file. This will be shared by all apps that
+ use uIP, such as the planned telnet and FTP clients. Also it means
+ we don't have to bloat each program with a complete config UI
+ for things like the local/peer/DNS IP addresses.
+
+ In fact the SETUP utility might resolve IP addresses for us, so
+ each app might not need its own copy of the resolver... though
+ that's maybe a bit clumsy to use for FTP, since you generally want
+ to easily be able to connect to arbitrary servers (unlike, say, IRC
+ where you usually use the same server all the time). Perhaps SETUP
+ could resolve arbitrary hostnames, then write them to a /etc/hosts
+ type of file. Parsing /etc/hosts entries is fairly lightweight,
+ could be done in all the client programs...
+
+ ...or maybe what should happen is that there should be a RESOLV
+ program that can resolve hostnames, and read/write them in text
+ form to a HOSTS.TXT file... and also parses the HOSTS file and
+ stores the hostname strings and 4-byte IP addresses in a fixed
+ area of memory. The app programs could just look up hostnames in
+ this memory area, without having to open & parse HOSTS themselves.
+ cc65 programs by default start at $2E00. The Bob-verter driver ends
+ around $2200 (other R: drivers should be comparable), which gives
+ us around 3K of unallocated memory. Assuming the average hostname/IP
+ pair is 50 bytes, that'd give us about 60 of them. The RESOLV program
+ would stop the user from adding more hostnames when there's no space
+ for them (and let them delete some to make room, maybe commenting them
+ out so they remain in the HOSTS file for future uncommenting).
+
+ Ultimately there should be a master AUTORUN.SYS file with a menu
+ that runs the other sub-apps (or lets you exit to DUP). Menu would
+ have options like "DNS", "IRC", "FTP", "Telnet", and "Network
+ Setup". Of course I need to write a program loader, there's no
+ exec* functions in cc65! The Network Setup option would let you
+ specify the R: driver you want to load, so it wouldn't have to
+ be prepended to any of the executables, and would be auto-loaded
+ the first time you try to run any of the apps that need it. It'd
+ be nice if the main menu program had at least a few DOS functions
+ as well (delete/copy/rename/lock/unlock, format too?)
+
+ Probably, FujiChat's 1.0 release will be as a standalone IRC client,
+ with the current config UI stuff as-is. The other stuff would be
+ released months from now, under the label "FujiNet" or something, and
+ include a new version of FujiChat as one of several apps.
+
+ The final distibution disk will need at least some documentation in
+ Atari-readable text format, plus a doc-reader program.
+
+ All the subprograms need to end with RTS to the menu program, which
+ shold be small and stay resident in addresses not touched by cc65
+ (I've got 128 bytes each in the cassette buffer and page 5, also
+ 256 more in page 6. Should be easy to squeeze into 512 bytes, no?)
+
+ So a disk directory would contain:
+
+ DOS.SYS, DUP.SYS
+ AUTORUN.SYS - the main menu and subprogram loader
+ BOBVERT.XEX - the Bob-verter R: driver
+ A850.XEX - the 850 R: driver (from DOS 2.0S I guess)
+ MIO.XEX, BLACKBOX.XEX, etc, drivers for other serial ports
+ HOSTS.TXT - the /etc/hosts file, human-readable and -editable
+ README.TXT - docs
+ MORE.XEX - doc reader (should handle ASCII or ATASCII EOLs)
+ SETUP.XEX - set up global network settings (local/remote/dns IPs, also
+ things like screen colors, key-repeat rate, etc).
+ DNS.XEX - lookup hostnames, maintain and parse HOSTS.TXT
+ FTP.XEX, TELNET.XEX, IRC.XEX, PING.XEX - the apps
+ FTP.CFG, TELNET.CFG, IRC.CFG, etc - app-specific settings
+ FUJINET.CFG - global settings
+ ...if there's room on the disk, a small text editor might be nice
+ to include.
+
+ The whole thing should be distributed as a bootable, single-density
+ DOS disk (undecided which DOS, either 2.0S or MyDOS 4.5).
+
+ Alternatively, all the XEX files might be named COM, and the whole
+ thing could run under a CLI DOS like Sparta (if it'll actually
+ run). The apps could take optional CLI arguments, also... and the
+ AUTORUN.SYS would actually be unnecessary!
+
+ */
diff --git a/doc/notes.txt b/doc/notes.txt
new file mode 100644
index 0000000..3f25388
--- /dev/null
+++ b/doc/notes.txt
@@ -0,0 +1,281 @@
+Definitely need to rewrite huge swathes of code in asm.
+Candidates are:
+
+fujichat.c: main(), handle_keystroke(), and the protocol parsing
+routines
+
+rs232dev.c: the whole thing could be rewritten in asm for speed,
+but the size isn't so bad.
+
+uIP itself: have to investigate. Some of the code is pretty
+hairy. Before rewriting in asm, should make it so we can
+compile without TCP listen support, since we don't use it.
+
+
+Need to re-do the R: handler stuff. At least one driver (the
+plain Atari 850 one) actually crashes when loaded from either
+the DOS menu or aexec. Apparently it *only* works if it's
+loaded as autorun.sys. So, something like this:
+
+- Initial autorun.sys on disk loads a program called makeauto.
+[done]
+
+- makeauto asks for the serial driver, then concatenates the
+driver + menu.com into a new autorun.sys (renaming the old
+one to autorun.old or something), then asks user to reboot.
+[done]
+
+- Any time fujiconf loads and can't find an R: handler, it tells the
+user and runs makeauto for him (or anyway asks, with default Yes). The
+"set R: driver" stuff in fujiconf needs to move to makeauto (and be
+changed so it appends files instead copy).
+
+- FujiChat itself still won't contain any R: detection or
+anything, beyond the RS232 Not Initialized error message
+[done]
+
+- While I'm at it, fix the filename paths so they *all* begin with
+the D: prefix.
+[done]
+
+- Possibly menu.com has a new menu item, "RS232 Setup", and warns
+the user "You must run RS232 Setup before using FujiChat"
+
+20081124 bkw: Add /peek, /poke, /fgcolor, /bgcolor commands.
+
+Also, now that we're parsing numerics from the server, it'd be
+nice to do the alternate-nick thing, for when the nick is in use.
+
+20081124 bkw: Keep a time-of-day clock (don't use RTCLOK to store
+it though). At connect, send /TIME to the server, parse the results.
+The config file will need a timezone setting.
+
+20081121 bkw: Feature idea: auto-away when attract mode kicks in,
+with default away message (but don't announce to channel). Un-away
+as soon as a key is hit. Possibly let the user set a timeout
+instead of letting the OS default to 9 minutes.
+[done, using default OS timeout only]
+
+Ideas for logging:
+
+Will anyone give a shit about logging to disk? If so, it wouldn't
+be impossible... but we'd likely drop packets (or does uip_stop()
+gracefully handle this, maybe with a callback?)
+
+/log [on|off|flush|file filename|search <term>]
+
+Keep the disk file open? Log stuff to memory, then just before
+the buffer fills, write it out to disk.
+
+Logging to memory, looks like we have a little over 5K for this.
+When we get ready to log a message that would put us past the end
+of the buffer, memmove() the buffer down by some amount (say 1/4
+of its size).
+
+Log viewing is a mode. While enabled, handle_keystroke() will do
+the --more-- thing. Traffic indicator's still active, and we
+still log stuff to memory, but *don't* print it. If the log
+has to be shifted down, also shift down the currently-viewing
+pointer. If the view pointer points too low to move, set it
+to the bottom of the log buffer if it isn't already (user will
+get confused, but what you gonna do?). Forward/backward searches
+should work. Filtering by nick should work.
+
+When entering logviewer mode, save the current end-of-log address.
+Any time the log moves while viewing, also subtract from this
+address. More stuff can be coming in & being logged above this
+address... on exiting logviewer mode, anything aboved the saved
+address should be printed to the screen immediately.
+
+In this model of "scrollback" support, we actually don't scroll
+per se, we're *still* using stdio to print stuff. It might be
+that on entering logviewer mode, we should run through the log,
+counting characters, so we'll know where each screens' worth
+starts (for going back/up in the viewer). Either that, or we
+could print the damn thing backwards?
+
+At a price of 3 bytes per message, we can store timestamps. Not
+sure if it's worth it. Actually maybe we can just store a single
+byte in the buffer every N minutes, to give a rough guide to
+how long ago the next bunch of messages were.
+
+How bout this for a lightly compressed format: we're only storing
+7-bit printable ascii, in 8-bit bytes, so...
+
+1st byte:
+
+0-31 - No message, just timestamp. Next message starts at
+next byte in buffer. The value is the minutes-1 since the
+last timestamp. Basically, every minute of wall-clock time,
+a timestamp of 0 is added to the buffer if someone has said
+something in the past minute. If not, there will already
+be a timestamp at the end of buffer, so just increment it
+(unless it's at the max value, in which case add a zero
+timestamp after it). We can use these to e.g. print
+"(42 minutes silence)" or such. I'd like to be able to
+do "N minutes ago" type messages, but to do that I have to
+run through the buffer backwards to calculate what they
+should be (then forwards to actually read messages from it).
+
+Anything else: 1st char of nick, or 0x80 meaning "same nick as last
+message" (or 0x81 meaning "my nick"?). Some care has to be taken when
+memmoving the buffer: blocks of messages from the same user need to be
+treated as a unit (kept entirely, or disposed of entirely). For this
+to make sense, such blocks have to be kept short (say, less than the
+move-amount).
+
+Next bytes are the rest of the nick, with bit 7 set for the last
+one. In case of a 1-char nick, 1st and only char has bit 7 set.
+
+After last nick char comes the message.
+For the first byte, if the top bit is set, the bottom 7 bits are:
+
+0 - empty message
+1-31 - stuff like join/quit/part (don't bother to store part,
+quit, or kick messages? or store normally?)
+Anything else - normal message character (the only one, if the
+top bit is set).
+
+Further message bytes are stored with the top bit of the last byte
+being set.
+
+So if someone joins, says hello, and parts (<c> means 'c' with high
+bit set:
+
+Use<r>\x01\x80Hello\x80\x02
+
+(Assuming \x01 is the join code and \x02 is the part code)
+
+This is 13 bytes. If we stored what a normal client stores in its
+log, it might look like:
+
+User has joined\n
+<User> Hello\n
+User has left\n
+
+Which is 16+13+14 = 43 bytes. Most clients would actually store the
+channel name with the joins/parts; I left them out to make the
+comparison more fair (we don't penalize them for storing info that
+we don't store, only for storing the same info less densely).
+
+
+20081120 bkw: smallest 0.4 binary, with all FEAT_* turned off except
+for FEAT_LOW_RAM_BUFFERS, the BSS ends at $920E. With COL80E relocated
+to $9A00, that gives us 1K for stack. Not great, but might work. It's
+still too big to use with E80 (by about 3K, counting the stack).
+
+COL80E loads at $7A00-$7F80, but doesn't really seem to use any RAM
+from $8000-A000 with BASIC disabled. If the code could be relocated so
+it loads at $9A00, we'd have a fighting chance of squeezing fujichat to
+fit. Currently fujichat loads $2E00-8D3B... meaning there'd be a little
+over 3K for stack & data/bss variables. Need to examine cc65's map file,
+see how high the data/bss stuff goes. Moving the input and output buffers
+to low RAM is going to help a lot. It also might be possible to move
+the stack to low RAM (it's supposed to sit right above the heap, but
+fujichat isn't using malloc(), which unless I'm mistaken means no heap
+usage... though some of the libraries it links with might be using it).
+
+Try compiling uip without UDP checksums, with fewer TCP/UDP conns,
+asm optimize anything that doesn't compile efficiently?
+
+It looks like TCP listen support could be made a compile-time option
+that could be disabled. IRC doesn't need to listen on ports except
+for DCCs, and we probably can't ever make those work anyway. It
+won't save much (guesstimate is 50-75 bytes)...
+
+Each TCP conn is supposed to take 30 bytes. For now we only need one,
+but we have 5, so wasting 120 bytes there.
+
+[so far, changing max. tcp conns, listen ports, and udp conns to 1,
+and disabling udp cksums, has saved 325 bytes. Worth it, but need to
+make sure the app still works!]
+
+[also, make some of FujiChat's features able to be removed at
+compile-time. Removing them all saves 963 bytes, and makes the BSS
+end at $96cb! If COL80E were relocated to $9A00, we'd have 800-odd
+bytes for the heap/stack, which still ain't enough... Possibly
+the stack could be shrunk by 256 bytes and relocated to $2700?]
+
+E80 is probably a lost cause. It seems to take 12K, which seems like an
+awful lot. Screen is hard-wired to $6E70, but it seems to not use any
+RAM from $A000-BFFF with BASIC disabled. moving the whole thing up 8K
+(assuming I can relocate the code) gives us a start address of $8E70,
+or 3K lower than COL80E, or 130-odd bytes(!) above the end of cc65's
+code segment (ouch!)... however maybe I could leave it unrelocated, and
+use a linker script to move all the data/bss/heap/stack/etc (everything
+but the code, and maybe some of the code too) to the $A000-BFFF area
+(8K seems like a good bit, the stack is 2K).
+
+Fast E40 driver doesn't have to be a full E: replacement! Instead, we only
+need to hook the "put 1 byte" routine, and do the following:
+
+Check & see if byte-to-print is printable or an EOL. If it's neither,
+jump to the OS's print-one-byte routine.
+
+If the screen is about to scroll (if we're on bottom line and byte is
+0x9b, or if we're on bottom line + last column and byte is printable),
+we capture the top line (first 40 bytes) of screen RAM and store in
+scrollback buffer. We can probably detect when the line ends in >1
+spaces, and not store those.
+
+If a screen scroll is needed, do it ourselves, *fast*. This may turn
+out to be too messy or bloated to deal with, but I think it might not
+be so bad.
+
+If the char is printable, print it, *fast*. Fast E40 doesn't have to
+support margins other than 0 and 39, which should help. Also we can
+make assumptions about where the screen RAM is if need be, and use
+multiple ZP pointers into it (using the FP zero page area).
+
+However much scrollback RAM we have, we have to subtract 1K from it for
+a viewing buffer. This allows us to keep printing to the main screen
+RAM while it's not showing, and buffering it as it scrolls, without the
+viewing buffer changing while we look at it... also when done viewing,
+we toggle back to displaying main screen RAM instantly.
+
+I'm thinking there have to be separate builds for Fast E40 and whatever
+80-col driver I get working. The 80 version won't have any support for
+scrollback at all, not least because there's no RAM for the buffer!
+
+Also if there's ever going to be a separate edit buffer "window",
+or multiple channel windows, fast E40 is where they'll live.
+
+It might also be possible to do word-wrap. Not sure whether that's better
+done in the driver or in the app. Doing it in the app means it'll work
+in 80-column mode, too.
+
+...potential new feature: should be able to do ping times by sending the
+low 2 RTCLOK bytes in numeric form, then when the response comes back,
+decode back into 2 bytes, subtract from current RTCLOK, convert to
+10ths of a second, and print.
+
+I *really* wish I could do CSLIP. Maybe later. Not delved too deeply
+into the guts of uIP... maybe the serial driver could transparently
+do the comp/decomp, and speak plain SLIP to uIP? (would this be
+too slow, cause drops? Even if it doesn't make us drop packets, would
+the CPU overhead negate any benefit to be gained from it?)
+
+Also on the drawing board, keyboard buffering during rs232 I/O. Fairly
+straightforward, I think. Don't actually cgetc() or anything, just
+save the contents of CH in a buffer if it's not $FF, and set it
+to $FF to clear the keystroke. In fact, there's a prototype of it
+in keybuftest.c (just needs to be integrated).
+
+Another idea: a status line wouldn't be so hard to do, even without a
+fancy E: driver. Could write directly into the first 40 bytes of screen
+RAM. I don't want to give up a line of display though... but instead of
+a full status line, it'd be cool to display a little up or down arrow
+in the upper-right corner during rs232 sends/receives (save & restore
+the character that really goes there). The screen codes for the up
+and down arrows are $5C and $5D ($DC and $DD for inverse).
+
+/j or /join without a channel should rejoin the current channel, if
+FujiChat thinks it's in a channel. This would give us an easy way
+to rejoin the channel if kicked.
+
+There needs to be an extra-dumb terminal program for use with manual
+login systems. It should fit in 1K or so, load on top of fujichat's
+input/output/msg buffer space, and RTS back to fujichat when it's
+done. Later on there should be a chatscript engine that loads in
+the same space and works the same way.
+
diff --git a/src/ChangeLog b/src/ChangeLog
new file mode 100644
index 0000000..6b95059
--- /dev/null
+++ b/src/ChangeLog
@@ -0,0 +1,349 @@
+- 20190313 bkw:
+
+FujiChat is back!
+
+The source is now developed using git, meaning you'll find low-level
+details about changes in the git log. I'll try to remember to update
+this ChangeLog to document major new features and such.
+
+- 20081201 bkw:
+
+Rewrote & reorganized handle_command(). It now lives in commands.c,
+and loops over a table of commands (cmd_list), rather than the old
+messy chain of if/else/if. Moved all the logic for each command into
+their own cmd_whatever() functions (the addresses of which are in the
+table). Not only did this save a couple hundred bytes of object code,
+it also means adding new commands is less expensive.
+
+Instead of telnet_send(tstate, serv_msg_buf, strlen(serv_msg_buf)) strewn
+about the code, there's now a send_serv_msg_buf(void) function. Rather
+than use strlen() to calculate, we set the new serv_msg_buf_len variable
+to the length... which works out great as almost all the telnet_send()
+instances were preceded by a sprintf(), which already returns the length
+(was just throwing away the return value! Old habits...)
+
+Added /fgcolor and /bgcolor commands (enable with FEAT_COLOR_COMMAND).
+These don't change the colors in the config, and they get reset before
+every new IRC connection, but it does mean you don't have to reload the
+config menu to try out new colors. Especially important for COL80 users,
+since it takes some fiddling to find a color set that looks good on your
+monitor (if you can!)
+
+Completely removed all attempts to do a software cursor when
+FEAT_COL80_HACK is enabled. It wasn't working anyway, and needs further
+thought before hacking away at it any more (should the COL80 driver
+respond to CRSINH at 752, like the real E: does?)... Actually it's
+perfectly usable without the cursor anyway, you always know where you
+are because you're always at the bottom of the screen. When/if arrow
+key editing is supported, there will have to be a cursor...
+
+
+- 20081130 bkw:
+
+More major surgery: there's now a hacked-up, cut-down version of the
+old COL80 driver, and Fujichat support for it. FEAT_COL80_HACK, which
+defines its own set of features. Currently the code is a mess of #ifdefs,
+but working (still some issues with the cursor not working right in 80
+cols). The 4x8 font is a slightly modified version of Itay Chamiel's
+Ice-T font (characters 32-127 only, I made the ampersand and the capital
+N look more like I expect them to). Current version of col80 uses the
+cassette buffer for a private input buffer for CIO get calls, but
+it could just as well use input_buf (though it can't know where that
+is, unless FEAT_LOW_RAM_BUFFERS is also enabled). So far, COL80 hack
+only tested with Bob-verter. Scroll speed is slower than Ice-T or
+E80/ACE80, but TCP has those pauses built into it... someone needs
+to try it at 9600 baud. An interesting thing about COL80 is that
+it's not limited to 128-char fonts (neither is Ice-T, Itay does a
+full 256-char set)... unicode anyone? SW underlining?
+
+Got rid of redraw_buf (was at $2800), calling fuji_putchar() in a loop
+is about as fast as fputs() a whole string. Allows user an extra page
+in low memory, unless I find a burning need to use it for something
+else...
+
+- 20081127 bkw:
+
+Expunged putchar() and cgetc(), from fujichat.c, gained over 200 bytes
+(replaced with "indirect JSR" technique using put/get address-minus-one
+in OS ROM). BSS now ends at $9515. We almost have enough room for an
+80-column software driver (the stack is 2K, so MEMTOP needs to be $9d15
+or higher since we don't use the heap). Default GR.0 setup, MEMTOP
+is $bc1f, which is where the stack starts (and grows downward for 2K,
+ending at $b41f). $B41F minus $9515 is 7946 bytes, almost 8K. In GR.8
+mode, MEMTOP is $A04F. Subtract $9515 (end of BSS), add 2K ($9D15,
+end of stack). Subtract from $A04F and we get $33a, or 826 bytes. This
+is not enough room for a GR.8 software 80-column driver's code + font
+(COL80E uses more like twice that), but it's a whole lot closer than
+FujiChat 0.4 was.
+
+Strip leading colons from the text of server messages.
+
+BSS at $977E (got rid of cursor() and replaced cgetc() with version
+that doesn't contain setcursor junk (we don't want to ever disable
+the cursor). In fact conio.h is gone now.
+
+Expunged fread() from common.c (replaced with read()), gained over
+1/2K.
+
+Made TCP listen support optional in uIP, and turned it off for
+FujiChat. This save about 1200 bytes in the binary.
+
+Starting to rewrite bits in asm. I've got the end of the BSS
+down to $97ED now, and I've barely started...
+
+Fixed bug in config_is_valid() that made fujichat always use
+built-in defaults. Thanks to Beetle for spotting this.
+
+- 20081126 bkw:
+
+Renamed menu.com to fujimenu.com (apparently on SpartaDOS X,
+trying to load D:MENU.COM ends up loading CAR:MENU.COM instead).
+Thanks to Beetle for spotting this.
+
+makeauto.com now cats the serial driver and loadmenu.com (instead
+of menu.com) to make autorun.sys. Saves like 70 sectors on the
+disk image.
+
+Added some test code (FEAT_UNICODE_TEST) that converts an input ctrl-P
+(clubs symbol) into the UTF-8 sequence for a Unicode "card suit clubs"
+symbol. It looked fine in irssi with univga font, but for some reason 3
+other people saw it as a spades symbol... Eventually it'd be possible to
+have a little table to convert all the ATASCII graphics chars into UTF-8
+on keyboard input, and convert the UTF-8 versions back into the ATASCII
+chars on screen output. Thanks to Redb3ard for coming up with the idea
+and doing the research on this... though it can't be fully implemented
+any time soon (FujiChat needs to go on a major diet before I add any
+more features, I'm running out of RAM).
+
+
+- 20081125 bkw:
+
+Added keyboard buffer. Needs lots of testing, but initially appears
+to work OK (FEAT_KEYBOARD_BUFFER)
+
+Added autojoin to fujichat.
+
+Rearranging things. The Atari 850 driver *crashes* if it's loaded
+from the DOS menu even (it *has* to be autorun.sys), so instead
+of the default.ser and such, the RS232 driver + menu now get
+catted together to create an autorun.sys (and the user is asked
+to reboot, to load it).
+
+Added auto-away on attract mode
+
+Added alt_nick and timezone fields to cfg file (not used yet),
+bumped CONF_VERSION.
+
+Rearrange fujichat numeric server message stuff, add autojoin capability.
+Also add autojoin prompt to fujiconf.
+
+Change the leading character for local message from * to > (e.g.
+"> Registering Nick"), and privmsgs to us now show up as
+"-> <nick> message"
+
+- 20081120 bkw:
+
+Fixed bug in conf menu (IRC server was getting reset to the first in the
+list if the user hit Return, instead of keeping his existing one). Thanks
+to Slor for spotting this.
+
+Added (attempted) 19200 baud support. cc65 doesn't define RS_BAUD_19200 in
+rs232.h. Slor suggested defining it as 0x0f (since the baud rate constants
+run 0x00 to 0x0e). It almost works: FujiChat is able to send & receive,
+but even with hardware handshaking, it can't keep up (lots of incoming
+packets get dropped, and the connection eventually stalls). Since Slor's
+HW handshaking is known to work (he can do 9600 baud reliably, and runs
+unpatched slattach without -L), I assume the trouble is that the loop
+in rs232dev.c is too slow. Recoding it in asm may help. It may have to
+use SIO instead of CIO though... or would that make it HW-specific?
+Guess it would.
+
+Added (bloated implementation of) ping time calculation. In the ping
+request, we send the contents of the 3 bytes of RTCLOK, and when we get
+them back, we subtract them from the current RTCLOK value and format
+as number of seconds + 10ths of seconds. Code uses CLOCKS_PER_SECOND,
+which means it auto-adjusts for PAL vs. NTSC timing. If RTCLOK rolled over
+between request & response, it'll appear to be a huge negative number...
+but I think uIP fails when RTCLOK rolls over anyway. Most people won't
+leave their Atari up for 3+ days anyway I guess.
+
+Clean up the raw IRC protocol server messages. We now strip the server
+hostname, parse numerics, and (for a few numerics) print meaningful
+message like "Topic". This could use a lot more work, but it does save
+our limited screen space.
+
+Implemented UIFLAG_HIDE_MOTD in fujichat.c. The traffic indicator still
+appears, to let the user know something's going on. Initial pre-MOTD
+server messages are not suppressed.
+
+- 20081119 bkw:
+
+*Major* surgery! The patient's vitals are strong, and the operation
+is a tentative success.
+
+fujichat's config menu has been split off into a separate executable.
+This keeps the menu from sitting around taking up memory while we're
+actually chatting. Also it paves the way for a fancier config menu with
+more options and a nice UI.
+
+While I was at it, I added a top-level menu program and an "about"
+option, with a separate viewer program that's a simple version of "more"
+from UNIX.
+
+All the programs (fujichat, fujiconf, menu) are able to load & run
+each other thanks to aexec (aka atari_exec()). This is a teensy little
+binary-file loader that fits into page 6, and gets prepended to
+all the other programs.
+
+Also, the Bob-verter driver is no longer baked into fujichat. Instead,
+we've got a tiny little loader called "loadchat", which does this:
+
+- Check for the existence of an R: device in HATABS
+- If not found, load the file DEFAULT.SER (ignoring "file not found")
+- Load fujichat.com
+
+DEFAULT.SER is just a binary load file. By default it'll be a copy
+of Bob-verter (also there's a copy called BOBVERT.SER).
+
+The config menu (fujiconf) allows the user to choose which serial
+device he has (by user-friendly name), and copies the appropriate
+driver (named something.SER) to DEFAULT.SER. Nota bene:
+
+- The driver is only loaded when the user chooses to run FujiChat
+itself, from either menu.com or fujiconf.com
+
+- If the driver setting gets changed before any R: driver is loaded,
+loadchat will load the new driver.
+
+- The menu allows the user to type a filename, to use a driver not
+in the built-in list (which is good as it's not a very complete
+list yet)
+
+- The menu also allows "none" as a choice, meaning he's taking
+responsibility for providing an R: handler himself (e.g. as an
+AUTORUN.SYS, or loaded from a SpartaDOS batch file or whatever).
+In this case, DEFAULT.SER will be deleted, and loadchat will
+silently fail to load it, and then FujiChat will just use the
+preloaded R: handler (or if it's missing, it'll give an error
+and let the user go back & reconfigure).
+
+- The way this is set up, it means the user can just use fujichat.com
+as a standalone executable, without the presence of menu.com, loadchat.com,
+fijuconf.com, or any other stuff from the disk. He can prepend his
+R: handler to it and load it from anywhere. It'll use the default
+config, but that's OK (most people would set up their SLIP host
+with the defaults anyway). He'll have to enter his server every
+time, and use /nick, but the program will *work*.
+
+- It's also possible to run fujiconf once to create a config file, then
+copy fujichat.com and fujichat.cfg to some other disk or directory
+or whatever, and run it without having the menu/loadchat/fujiconf/etc.
+The only missing capability is that he can't create a new config file.
+
+- The de luxe option: it should be fully possible to copy the contents
+of the FujiChat floppy image to a MyDOS or SpartaDOS subdirectory
+(obviously don't copy autorun.sys, dos.sys, dup.sys). All the filenames
+used by the program begin with D:, not D1:, so they should use the
+current drive and directory. (Eventually I'll write an INSTALL.COM
+that makes the directory & copies the stuff for you!)
+
+Other changes:
+
+Break key is now disabled. No more accidentally sending a line when
+you meant to hit Backspace.
+
+There's now a tiny AUTORUN.SYS that finishes the DOS boot stuff, then
+runs MENU.COM (the main menu) for us.
+
+MENU.COM, FUJICONF.COM, and FUJICHAT.COM all look in page 5 for the
+config, which stays resident when switching between programs. If it's
+not there, they all try to load it from FUJICHAT.CFG. If that fails,
+they use built-in defaults.
+
+FujiChat (FUJICHAT.COM) *can not* create FUJICHAT.CFG itself.
+
+Had to use memcpy() instead of Adam's uip_sethostaddr() and
+uip_setdraddr() macros (they have trouble when their arguments are
+dereferenced pointers; probably this is a deficiency in cc65).
+
+The config menu is a lot more user-friendly. It stops the user from
+setting unreadable colors (where fg/bg have equal luma values), and
+the long, long list of questions is broken up into sections.
+
+rs232dev_init() now returns a status. If it's not RS_ERR_OK, something
+went wrong. If this happens, FujiChat allows the user to retry,
+run fujiconf, or exit to DOS.
+
+I won't be providing single-file .xex downloads any more. The ATR image
+will be the main distribution (possibly I'll also offer the contents
+in a zip file, for S-Drive or MyIDE users). The main executable still
+works standalone, but is not fully functional, so I'd rather discourage
+'noobs' from running it that way (non-noobs know how to extract the
+.xex from the .atr image themselves).
+
+Changed uip-conf.h, now uIP is compiled with support for only one
+TCP conn, one UDP conn, and one TCP listen port (TCP listen support
+isn't disable-able in uIP; I'll change that later). Also disabled
+UDP checksums.
+
+Added FEAT_* macros to remove some FujiChat features at compile time.
+See fujichat.c for the list of features and how much code space they
+take up.
+
+Added network traffic indicator in upper right corner of screen:
+up arrow for transmit, down arrow for receive. FEAT_TRAFFIC_INDICATOR
+
+/j or /join with no argument now tries to rejoin the current channel
+(use if you get kicked). Also, fixed bug where /j with no argument
+tried to join a bogus (null) channel.
+
+/nick now tracks your nick changes. This fixes the bug where, after
+a nick change, private messages to your new nick appear to be
+channel traffic.
+
+
+- 20081116 bkw:
+Fixed bug in 0.3.0 (ctcp responses didn't work when a ctcp request came
+back in the middle of typing a line)
+Made baud rate selectable in the UI (there was already a config file entry
+for it)
+0.3.0 released
+Added ^W and ^U (delete last word, delete-line, emacs-style)
+Added simulated edit buffer using delete-line and cursor controls. This
+isn't as nice as a custom display list, but it stays compatible with (most)
+80-column drivers.
+Added option to run config menu from the "return to connect" prompt, got rid
+of "Use defaults [y/n]" prompt.
+Added support for selecting the server port (default still 6667)
+Added support for real name field
+We now close the serial port when disconnected (needed for the config menu
+to be able to save to disk, at least with bob-verter driver)
+
+- 20081115 bkw:
+Changed uIP packet buffer size to 576. This will help with those DNS aliases
+that return 15 hostnames + aliases (like irc.freenode.org). TCP MSS is still
+set to 160 - header_len, to keep it feeling like an interactive app.
+
+strcmp against config.nick changed to strcasecmp, so we can correctly
+handle messages/ctcps to the lowercase (or whatever) version of our nick.
+
+Added option to enter an IRC server instead of just "press return
+to connect". The default is the config file server, or last server
+connected to.
+
+- 20081113 bkw:
+0.2 released
+Added option to exit to DOS
+FujiChat now works with FreeNode (mostly)
+Made local/peer/DNS IP configurable
+Server hostname now configurable
+UI flags configurable: visual bell, no bell, msg bell, show ping
+Default server list is now hostnames
+Consolidate some UI I/O code
+Initial support for DNS resolution
+
+- 20081112 bkw:
+Added visual bell support
+Added ` (backtick) support (prints as inverse single quote)
+
+- 20081105: 0.1 released
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..a942af8
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,102 @@
+# Copyright (c) 2001, Adam Dunkels.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote
+# products derived from this software without specific prior
+# written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# This file is part of the uIP TCP/IP stack.
+#
+# $Id: Makefile,v 1.13 2006/06/11 21:55:03 adam Exp $
+#
+
+all: uip fujiconf.xex aexec.xex fujimenu.xex makeauto.xex about.xex loadmkau.xex loadmenu.xex keybuf.o clear_rts
+
+CC = cl65
+AR = ar65
+APPS = telnet resolv
+CFLAGS = -t atari -I../uip/uip -I. -O
+
+-include Makefile.include
+
+uip: $(addprefix $(OBJECTDIR)/, fujichat.o common.o commands.o rs232dev.o clock-arch.o) keybuf.o apps.a uip.a fujiput.s
+
+#fujichat.o: common.h features.h fujichat.h # no worky?
+
+keybuf.o: keybuf.s
+ ca65 -t atari -l -o keybuf.o keybuf.s
+
+common.o: common.c common.h
+ $(CC) $(CFLAGS) -c -o common.o common.c
+
+fujiconf.xex: fujiconf.c fujichat.h common.o
+ $(CC) $(CFLAGS) -o fujiconf.xex fujiconf.c common.o obj/uiplib.o
+
+fujimenu.xex: fujimenu.c fujichat.h aexec.xex common.o
+ $(CC) $(CFLAGS) -o fujimenu.xex fujimenu.c common.o
+
+about.xex: about.c fujichat.h aexec.xex common.o
+ $(CC) $(CFLAGS) -o about.xex about.c common.o
+
+#loadchat.xex: loadchat.c fujichat.h
+# $(CC) $(CFLAGS) -o loadchat.xex loadchat.c
+
+#loadchat.xex: loadchat.dasm
+#dasm loadchat.dasm -f3 -oloadchat.xex
+
+makeauto.xex: makeauto.c
+ $(CC) $(CFLAGS) -o makeauto.xex makeauto.c common.o
+
+loadmenu.xex: loadmenu.dasm
+ dasm loadmenu.dasm -f3 -oloadmenu.xex
+
+loadmkau.xex: loadmkau.dasm
+ dasm loadmkau.dasm -f3 -oloadmkau.xex
+
+aexec.xex: aexec.dasm
+ dasm aexec.dasm -f3 -oaexec.xex
+
+test: newdisk
+ atariserver fujitest.atr
+ sudo sh ./start_slip.sh
+
+disk: newdisk
+
+newdisk: all
+ sh mkdisk.sh
+
+old_disk: uip
+ cat rvert.com uip > autorun.sys
+ axe -w autorun.sys uiptest.atr
+ #xterm -e atariserver uiptest.atr
+
+clean:
+ rm -fr *.xex obj/ *.o *~ *core uip $(OBJECTDIR) *.a
+ mkdir obj
+
+keybuftest.xex: keybuftest.c keybuf.o
+ $(CC) $(CFLAGS) -o keybuftest.xex keybuftest.c keybuf.o
+
+# native, not Atari!
+clear_rts: clear_rts.c
+ cc -o clear_rts clear_rts.c
diff --git a/src/Makefile.include b/src/Makefile.include
new file mode 100644
index 0000000..05ce291
--- /dev/null
+++ b/src/Makefile.include
@@ -0,0 +1,47 @@
+
+
+ifdef APPS
+ APPDIRS = $(foreach APP, $(APPS), ../uip/apps/$(APP))
+ -include $(foreach APP, $(APPS), ../uip/apps/$(APP)/Makefile.$(APP))
+ CFLAGS += $(addprefix -I../uip/apps/,$(APPS))
+endif
+
+ifndef CCDEP
+ CCDEP = $(CC)
+endif
+ifndef CCDEPCFLAGS
+ CCDEPCFLAGS = $(CFLAGS)
+endif
+ifndef OBJECTDIR
+ OBJECTDIR = obj
+endif
+
+ifeq (${wildcard $(OBJECTDIR)},)
+ DUMMY := ${shell mkdir $(OBJECTDIR)}
+endif
+
+
+vpath %.c . ../uip/uip ../uip/lib $(APPDIRS)
+
+$(OBJECTDIR)/%.o: %.c
+ $(CC) $(CFLAGS) -o $@ -c $<
+
+$(OBJECTDIR)/%.d: %.c
+ @set -e; rm -f $@; \
+ $(CCDEP) -MM $(CCDEPCFLAGS) $< > $@.$$$$; \
+ sed 's,\($*\)\.o[ :]*,$(OBJECTDIR)/\1.o $@ : ,g' < $@.$$$$ > $@; \
+ rm -f $@.$$$$
+
+UIP_SOURCES=uip.c uip_arp.c uiplib.c psock.c timer.c uip-neighbor.c
+
+
+ifneq ($(MAKECMDGOALS),clean)
+-include $(addprefix $(OBJECTDIR)/,$(UIP_SOURCES:.c=.d) \
+ $(APP_SOURCES:.c=.d))
+endif
+
+uip.a: ${addprefix $(OBJECTDIR)/, $(UIP_SOURCES:.c=.o)}
+ $(AR) a $@ $^
+
+apps.a: ${addprefix $(OBJECTDIR)/, $(APP_SOURCES:.c=.o)}
+ $(AR) a $@ $^
diff --git a/src/Makefile.webclient.ok b/src/Makefile.webclient.ok
new file mode 100644
index 0000000..24f4746
--- /dev/null
+++ b/src/Makefile.webclient.ok
@@ -0,0 +1,50 @@
+# Copyright (c) 2001, Adam Dunkels.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote
+# products derived from this software without specific prior
+# written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# This file is part of the uIP TCP/IP stack.
+#
+# $Id: Makefile,v 1.13 2006/06/11 21:55:03 adam Exp $
+#
+
+all: uip
+
+CC = cl65
+AR = ar65
+APPS = webclient resolv
+CFLAGS = -t atari -I../uip -I. -O
+
+-include Makefile.include
+
+uip: $(addprefix $(OBJECTDIR)/, main.o rs232dev.o clock-arch.o) apps.a uip.a
+
+test: uip
+ cat rvert.com uip > autorun.sys
+ axe -w autorun.sys uiptest.atr
+ #xterm -e atariserver uiptest.atr
+
+clean:
+ rm -fr *.o *~ *core uip $(OBJECTDIR) *.a
diff --git a/src/about.c b/src/about.c
new file mode 100644
index 0000000..01d6fcb
--- /dev/null
+++ b/src/about.c
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <conio.h>
+#include <string.h>
+#include "fujichat.h"
+#include "common.h"
+
+/* TODO: rewrite in asm. This does NOT need to
+ be 7K of object code. */
+
+void more(char *file) {
+ char c, line = 0;
+ char buf[200];
+ FILE *f = fopen(file, "r");
+
+ putchar(0x7d);
+
+ if(!f) {
+ printf("%s not found\n", file);
+ cgetc();
+ return;
+ }
+
+ while(fgets(buf, 200, f)) {
+ if(*buf == '#') continue;
+
+ line += (strlen(buf) / 40 + 1);
+ if(line > 23) {
+ fputs("--more--", stdout);
+ fflush(stdout);
+
+ c = cgetc();
+ if(c == 27)
+ break;
+
+ putchar(A_DEL);
+ line = 0;
+ }
+
+ fputs(buf, stdout);
+ }
+
+ fclose(f);
+
+ fputs("--any key--", stdout);
+ fflush(stdout);
+
+ c = cgetc();
+}
+
+int main(int, char **) {
+ more("D:ABOUT.TXT");
+ atari_exec(MENU_FILENAME);
+}
diff --git a/src/aexec.dasm b/src/aexec.dasm
new file mode 100644
index 0000000..9338c4c
--- /dev/null
+++ b/src/aexec.dasm
@@ -0,0 +1,206 @@
+
+; Load an Atari DOS executable, including support for init and run vectors
+; Parameters: nul-terminated filename pointer in A/X (lo/hi)
+; Return value: 0 for success, nonzero on error, never returns if exe has
+; a run address.
+
+; TODO: learn ca65 syntax better, port this to ca65
+
+; Usage: build with "dasm aexec.dasm -f3 -oaexec.xex"
+; "Link" to your program with "cat aexec.xex yourprog.xex > newprog.xex"
+
+; int __fastcall__ (*atari_exec_p)(char *) = (int __fastcall__ (*)(char *))0x600;
+; #define atari_exec(x) ((*atari_exec_p)(x))
+; then call with: atari_exec("D:PROGRAM.XEX");
+
+; If the file can't be opened for whatever reason, atari_exec() returns a
+; nonzero result (the Atari error number).
+
+; If the file loads OK and has a run address, atari_exec() never returns
+; (runs the loaded program, then exits to DOS if/when the program exits).
+; This means there's no memory conflict between caller and callee.
+
+; If there was no run address, atari_exec returns 0 to the caller.
+; The caller is responsible for making sure the loaded program doesn't
+; step on the memory used by the caller or atari_exec itself!
+
+; If the file is openable but invalid (not a XEX, or truncated), current
+; atari_exec() implementation hangs the machine with a red screen, since
+; there's no way to know whether the partially-loaded program overwrote
+; the caller...
+
+
+ processor 6502
+ include "equates.inc"
+
+tmp = $d4 ; aka FR0
+loadaddr = $d6
+
+main = $0600
+
+ org main-6
+ word $FFFF
+ word main
+ word endmain-1
+
+ org main
+ pha
+ txa
+ pha
+ jsr fclose
+ pla
+ tax
+ pla
+
+ sta ICBAL+16
+ stx ICBAH+16
+ sta tmp
+ stx tmp+1
+ ldy #0
+
+; do an OPEN #1,4,0,$filename
+
+; get length of filename
+fnameloop:
+ lda (tmp),y
+ beq fndone
+ iny
+ bne fnameloop
+
+ ; set IOCB #1 buffer addr, buffer len, etc
+fndone:
+ sty ICBLL+$10
+ lda #0
+ sta ICBLH+$10
+ sta ICAX2+$10
+
+ ; init these to 0 so we can tell if they change
+ sta RUNAD
+ sta RUNAD+1
+ sta INITAD
+ sta INITAD+1
+
+ ldx #4
+ stx ICAX1+$10
+ dex
+ stx ICCOM+$10 ; cmd #3 = OPEN
+
+ ldx #$10
+ jsr CIOV ; do the OPEN
+ bpl readheader
+
+ tya ; CIO returns error code in Y reg
+ ldx #0
+ rts
+
+fail:
+ lda #$48
+ sta 710
+hang bne hang
+
+readheader:
+; read 2 bytes into local buffer
+ jsr read2bytes
+ bpl ok
+ cpy #136 ; EOF
+ bne fail
+ beq close_file ; if at EOF, close the file
+
+; if they're $ffff, try again
+ok:
+ lda tmp
+ tax
+ and tmp+1
+ cmp #$ff
+ beq readheader
+
+; store those 2 bytes in loadaddr
+ lda tmp+1
+ sta loadaddr+1
+ stx loadaddr
+
+; read 2 more bytes into local buffer (end addr)
+ jsr read2bytes
+ bmi fail
+; subtract loadaddr from end addr, add 1, to get length
+; store length into IOCB
+ lda loadaddr
+ sta ICBAL+$10
+ lda loadaddr+1
+ sta ICBAH+$10
+
+ sec
+ lda tmp
+ sbc loadaddr
+ sta ICBLL+$10
+ lda tmp+1
+ sbc loadaddr+1
+ sta ICBLH+$10
+ inc ICBLL+$10
+ bne noinc
+ inc ICBLH+$10
+noinc:
+ jsr read_segment
+ bmi fail
+
+; if INITAD modified, JSR there
+ lda INITAD
+ ora INITAD+1
+ beq readheader
+
+ jsr do_init
+
+ lda #0
+ sta INITAD
+ sta INITAD+1
+ beq readheader ; branch always
+
+do_init
+ jmp (INITAD)
+
+close_file:
+ jsr fclose
+
+; JSR through RUNAD if it's not zero
+ lda RUNAD
+ ora RUNAD+1
+ beq norun
+
+ jsr do_run
+ jmp (DOSVEC) ; does not return
+
+; If there was no run address, we were probably loading an R: driver, so
+; our caller is safe to return to
+norun
+ lda #0 ; return 0
+ tax
+ rts
+
+read2bytes:
+ lda #tmp
+ sta ICBAL+$10
+ lda #2
+ sta ICBLL+$10
+ lda #0
+ sta ICBAH+$10
+ sta ICBLH+$10
+read_segment:
+ lda #C_GETCHR
+ sta ICCOM+$10
+ ldx #$10
+ jmp CIOV
+
+do_run
+ jmp (RUNAD)
+
+fclose
+ lda #C_CLOSE
+ sta ICCOM+$10
+ ldx #$10
+ jmp CIOV
+
+endmain
+
+; word RUNAD
+; word RUNAD+1
+; word main
diff --git a/src/aexec.h b/src/aexec.h
new file mode 100644
index 0000000..41cc9fd
--- /dev/null
+++ b/src/aexec.h
@@ -0,0 +1,7 @@
+#ifndef AEXEC_H
+#define AEXEC_H
+
+extern int __fastcall__ (*atari_exec_p)(char *);
+#define atari_exec(x) ((*atari_exec_p)(x))
+
+#endif
diff --git a/src/aextest.dasm b/src/aextest.dasm
new file mode 100644
index 0000000..da4522b
--- /dev/null
+++ b/src/aextest.dasm
@@ -0,0 +1,52 @@
+
+ processor 6502
+ include equates.inc
+
+init_routine = $2E00
+
+ org init_routine-6
+ word $FFFF
+ word init_routine
+ word end_init_routine-1
+
+ org init_routine
+
+ lda #0
+ sta COLOR2
+
+ lda RTCLOK+2
+iloop:
+ cmp RTCLOK+2
+ beq iloop
+
+ rts
+
+end_init_routine:
+
+ word INITAD
+ word INITAD+1
+ word init_routine
+
+main_routine = $2F00
+ rorg main_routine-6
+ word main_routine
+ word end_main_routine-1
+
+ rorg main_routine
+
+ lda #$0F
+ sta COLOR2
+
+ lda RTCLOK+2
+mloop:
+ cmp RTCLOK+2
+ beq mloop
+
+ rts
+
+end_main_routine:
+
+ word RUNAD
+ word RUNAD+1
+ word main_routine
+
diff --git a/src/aextest2.dasm b/src/aextest2.dasm
new file mode 100644
index 0000000..fa897c6
--- /dev/null
+++ b/src/aextest2.dasm
@@ -0,0 +1,27 @@
+
+ processor 6502
+ include equates.inc
+
+main = $6000
+
+ org main-6
+ word $FFFF
+ word main
+ word end_main-1
+
+ org main
+
+ lda #<filename
+ ldx #>filename
+ jsr $0600
+ lda #$08
+ sta COLOR2
+ rts
+
+filename: byte "D:AEXTEST.XEX", $00
+
+end_main:
+
+ word RUNAD
+ word RUNAD+1
+ word main
diff --git a/src/atari850.ser b/src/atari850.ser
new file mode 100644
index 0000000..57eee3f
--- /dev/null
+++ b/src/atari850.ser
Binary files differ
diff --git a/src/atariserver.sh b/src/atariserver.sh
new file mode 100755
index 0000000..5a1d838
--- /dev/null
+++ b/src/atariserver.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+# Configurable stuff:
+
+# Name of the disk image (default: command line arg, or fujichat.atr)
+ATR_IMAGE=${1-fujichat.atr}
+
+TTY=/dev/ttyS0 # serial port to use
+
+# No delay:
+#DELAY="true"
+
+# 1 second:
+#DELAY="sleep 1"
+
+# 1/4 second (may not work on old Linux installs):
+DELAY="usleep 250000"
+
+# End of config section, start of code:
+
+ifconfig $SLIP_IFACE down 2&>/dev/null
+killall $SLATTACH 2&>/dev/null
+fuser -k $TTY 2&>/dev/null # make sure nobody's using the port...
+$DELAY
+fuser -k -9 $TTY 2&>/dev/null # Just in case...
+$DELAY
+modprobe atarisio port=$TTY
+$DELAY
+atariserver $ATR_IMAGE
+#atariserver autorun.sys # fails when run from MyPicoDOS, why?
+$DELAY
+rmmod atarisio
+$DELAY
diff --git a/src/atariserver_slip.sh b/src/atariserver_slip.sh
new file mode 100755
index 0000000..42b37cd
--- /dev/null
+++ b/src/atariserver_slip.sh
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+# This script is for use with the uIP test programs and AtariSIO.
+# Before running this, run "make disk" to create the disk image.
+# This script needs to be run with root privileges (e.g. with sudo)
+
+# Configurable stuff:
+
+ATR_IMAGE=${1-fujichat.atr}
+
+#ATR_IMAGE=fujitest.atr # Name of the disk image
+TTY=/dev/ttyS0 # serial port to use
+BAUD=4800 # must match compiled-in value in rs232dev.c
+SLATTACH=a8_slattach # slattach binary (possibly patched)
+SLIP_IFACE=sl0 # probably no need to change this
+LOCAL_IP=192.168.0.1 # SLIP IP address for Linux host
+REMOTE_IP=192.168.0.2 # SLIP IP address for Atari host
+IP_FORWARD=yes # Route packets for the Atari?
+IP_MASQUERADE=yes # NAT for the Atari?
+MASQ_IFACE=ra0 # if NATing, our main (LAM or internet) interface
+DUMP_PACKETS=yes # Run tcpdump on sl0 interface?
+
+# DELAY is needed on some (most?) systems because e.g. atariserver tries
+# to run before the atarisio module is fully initialized. Choose one:
+
+# No delay:
+#DELAY="true"
+
+# 1 second:
+#DELAY="sleep 1"
+
+# 1/4 second (may not work on old Linux installs):
+DELAY="usleep 250000"
+
+# End of config section, start of code:
+
+ifconfig $SLIP_IFACE down 2&>/dev/null
+killall $SLATTACH 2&>/dev/null
+fuser -k $TTY 2&>/dev/null # make sure nobody's using the port...
+$DELAY
+fuser -k -9 $TTY 2&>/dev/null # Just in case...
+$DELAY
+modprobe atarisio port=$TTY
+$DELAY
+atariserver $ATR_IMAGE
+#atariserver autorun.sys # fails when run from MyPicoDOS, why?
+$DELAY
+rmmod atarisio
+$DELAY
+echo "Starting SLIP on $SLIP_IFACE, local $LOCAL_IP, remote $REMOTE_IP"
+$SLATTACH -L -p slip -s $BAUD $TTY &
+$DELAY
+ifconfig $SLIP_IFACE $LOCAL_IP mtu 576
+ifconfig $SLIP_IFACE $LOCAL_IP pointopoint $REMOTE_IP
+
+if [ "$IP_MASQUERADE" = "yes" ]; then
+ echo "IP Masquerading enabled"
+ iptables -F
+ iptables -t nat -F
+ iptables -t nat -A POSTROUTING -o $MASQ_IFACE -j MASQUERADE
+fi
+
+if [ "$IP_FORWARD" = "yes" ]; then
+ echo "IP Forwarding enabled"
+ echo "1" > /proc/sys/net/ipv4/ip_forward
+fi
+
+if [ "$DUMP_PACKETS" = "yes" ]; then
+ tcpdump -i $SLIP_IFACE -X -n -vvv -s 0
+fi
diff --git a/src/atariserver_slirp.sh b/src/atariserver_slirp.sh
new file mode 100755
index 0000000..c6ba620
--- /dev/null
+++ b/src/atariserver_slirp.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+# Configurable stuff:
+
+# Name of the disk image (default: command line arg, or fujichat.atr)
+ATR_IMAGE=${1-fujichat.atr}
+
+TTY=/dev/ttyS0 # serial port to use
+BAUD=4800 # must match FujiChat conf
+
+# This setting is only needed if you're using an AtariMax (Steve Tucker)
+# auto-sensing SIO2PC as your serial device.
+TUCKER_SIO2PC_HACK="yes"
+
+# DELAY is needed on some (most?) systems because e.g. atariserver tries
+# to run before the atarisio module is fully initialized. Choose one:
+
+# No delay:
+#DELAY="true"
+
+# 1 second:
+#DELAY="sleep 1"
+
+# 1/4 second (may not work on old Linux installs):
+DELAY="usleep 250000"
+
+# End of config section, start of code:
+
+ifconfig $SLIP_IFACE down 2&>/dev/null
+killall $SLATTACH 2&>/dev/null
+fuser -k $TTY 2&>/dev/null # make sure nobody's using the port...
+$DELAY
+fuser -k -9 $TTY 2&>/dev/null # Just in case...
+$DELAY
+modprobe atarisio port=$TTY
+$DELAY
+atariserver $ATR_IMAGE
+#atariserver autorun.sys # fails when run from MyPicoDOS, why?
+$DELAY
+rmmod atarisio
+$DELAY
+
+slirp "tty $TTY" "mru 576" "mtu 576" "baudrate $BAUD" &
+
+if [ "$TUCKER_SIO2PC_HACK" = "yes" ]; then
+ sleep 1
+ ./clear_rts
+fi
diff --git a/src/bobvert.com b/src/bobvert.com
new file mode 100644
index 0000000..b5aeccc
--- /dev/null
+++ b/src/bobvert.com
Binary files differ
diff --git a/src/clear_rts b/src/clear_rts
new file mode 100755
index 0000000..e855ca0
--- /dev/null
+++ b/src/clear_rts
Binary files differ
diff --git a/src/clear_rts.c b/src/clear_rts.c
new file mode 100644
index 0000000..52da3f5
--- /dev/null
+++ b/src/clear_rts.c
@@ -0,0 +1,42 @@
+/* Compile with:
+ gcc -o toggle_rts toggle_rts.c
+
+ Change PORT if necessary.
+ */
+#define PORT "/dev/ttyS0"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <linux/serial.h>
+
+int main() {
+ int fd, status;
+
+ fd = open(PORT, O_RDWR);
+ if(fd < 0) {
+ perror(PORT);
+ return 1;
+ }
+
+ // fprintf(stderr, "ioctl(fd, TIOCMGET, &status);\n");
+ ioctl(fd, TIOCMGET, &status);
+ /*
+ if(status & TIOCM_RTS) {
+ fprintf(stderr, "RTS set\n");
+ } else {
+ fprintf(stderr, "RTS clear\n");
+ }
+ */
+ status &= ~TIOCM_RTS;
+ ioctl(fd, TIOCMSET, &status);
+ // fprintf(stderr, "ioctl(fd, TIOCMSET, &status);\n");
+ fprintf(stderr, "RTS forced off (Tucker SIO2PC)\n");
+ return 0;
+}
diff --git a/src/clock-arch.c b/src/clock-arch.c
new file mode 100644
index 0000000..8cff850
--- /dev/null
+++ b/src/clock-arch.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2006, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: clock-arch.c,v 1.2 2006/06/12 08:00:31 adam Exp $
+ */
+
+/**
+ * \file
+ * Implementation of architecture-specific clock functionality
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ */
+
+#include "clock-arch.h"
+
+/*---------------------------------------------------------------------------*/
+clock_time_t
+clock_time(void)
+{
+ return clock();
+}
+/*---------------------------------------------------------------------------*/
diff --git a/src/clock-arch.h b/src/clock-arch.h
new file mode 100644
index 0000000..8ea4edc
--- /dev/null
+++ b/src/clock-arch.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2006, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: clock-arch.h,v 1.2 2006/06/12 08:00:31 adam Exp $
+ */
+
+#ifndef __CLOCK_ARCH_H__
+#define __CLOCK_ARCH_H__
+
+#include <time.h>
+typedef int clock_time_t;
+#define CLOCK_CONF_SECOND (_clocks_per_sec())
+
+#endif /* __CLOCK_ARCH_H__ */
diff --git a/src/col64/autorun.sys b/src/col64/autorun.sys
new file mode 100644
index 0000000..956e404
--- /dev/null
+++ b/src/col64/autorun.sys
Binary files differ
diff --git a/src/col64/col64.bin b/src/col64/col64.bin
new file mode 100644
index 0000000..956e404
--- /dev/null
+++ b/src/col64/col64.bin
Binary files differ
diff --git a/src/col64/col64.dasm b/src/col64/col64.dasm
new file mode 100644
index 0000000..aca1259
--- /dev/null
+++ b/src/col64/col64.dasm
@@ -0,0 +1,1194 @@
+
+; ----------------------------------------------------------------------------
+; 64x32 software text driver
+; Uses 4x5 font in 5x6 character cells
+; Based on disassembled COL80 driver
+
+; This driver is missing quite a few things a full E: driver should have:
+
+; - Does not work with BASIC or any other cart! Though if START_ADDRESS_1
+; is changed to $7Cxx, a BASIC-able version could be assembled
+
+; - No support for cursor controls, insert/delete, or even clear screen
+; (instead the control-codes are printed as normal characters, if they're
+; above 31 decimal). This is a feature: our intended application is an
+; IRC client, where ASCII codes 125 and 126 represent } and ~ chars,
+; not clear-screen and backspace.
+
+; - Backspace key is supported during get-byte, but printing a backspace
+; with put-byte prints a tilde instead. Again, a feature.
+
+; - No support for low ASCII at all: any attempt to input or print a character
+; in the range 0-31 decimal is just ignored (this includes the arrow keys).
+; This is done to keep the font size at 96 characters, so it'll fit in a
+; page. Also IRC doesn't use low-ASCII.
+
+; - Does not attempt to survive a warmstart
+
+; - Will fail disastrously if an application sets COLCRS/ROWCRS to any
+; out-of-range values
+
+; - Only displays the cursor during get-byte operations
+
+; On the other hand, this driver is tiny (font is 240 bytes, code 718, not
+; counting 100 bytes of throwaway init code in the tape buffer), and plays
+; nice with cc65's stdio support (though NOT conio, don't even go there)
+
+; Theory of operation:
+
+; This is an Atari OS-compliant device driver. On load, the init routine
+; replaces the E: entry in HATABS with a pointer to our vector table,
+; col64_vector_tab.
+
+; We implement the CIO commands OPEN, CLOSE, GETBYTE, and PUTBYTE. The
+; GET-STATUS and SPECIAL commands are not implemented, and the CLOSE
+; command simply returns success (it doesn't need to do anything else).
+
+; When a channel is OPENed to our new E: device, the col64_open routine
+; calls part of the OS's S: handler to switch to GRAPHICS 8 (320x192 mono)
+; mode.
+
+; When the CIO PUT-BYTES or PUT-RECORD calls are made on our channel, CIO
+; calls our PUTBYTE routine (col64_putbyte) as needed to write (print)
+; characters to the screen. col64_putbyte keeps track of the current
+; cursor position (using COLCRS and ROWCRS), and either renders a glyph
+; at the current location, or (when the EOL character $9B is printed)
+; moves the cursor to the beginning of the next line, scrolling the
+; display RAM if necessary.
+
+; When the CIO GET-BYTES or GET-RECORD calls are made on our channel, CIO
+; calls our GETBYTE routine (col64_getbyte). This routine maintains its
+; own buffer of user-input characters. When first called (or any call when
+; the buffer is empty), col64_getbyte reads a complete line of input using
+; the OS's K: handler, echoing typed characters to the screen using our
+; own col64_putbyte. Only the backspace key is supported for editing. Once
+; the user presses Return, the first byte in the buffer is returned to
+; the caller. On subsequent calls, characters are returned from the buffer
+; until the buffer is empty. At this point, the next call to col64_getbyte
+; will result in a new line of input being read.
+
+; col64_putbyte calls render_glyph to draw a character in display RAM.
+; The font consists of 96 characters (low ASCII not supported), each 4 pixels
+; wide and 5 tall [*]. These are rendered into 5x6 character cells, with the
+; extra pixels being left blank to provide padding between characters.
+; Since 5 pixel wide cells don't line up evenly on display RAM byte
+; boundaries, render_glyph has to shift each 4-pixel line of glyph
+; data the appropriate number of times, and combine the result with the
+; rest of each screen byte (that portion that's outside of the 5-pixel
+; cell we're currently writing to). Surprisingly, this is accomplished
+; slightly faster than the standard OS E: driver prints a single character.
+; (unfortunately, scrolling the screen is *much* slower than the OS E:
+; driver's scrolling...)
+
+; [*] ...except the lowercase q j p q y, which have true descenders. The
+; glyphs for these are still 4x5, but the 6th row of pixels for all 5
+; get stored together in the last glyph in the set (ASCII code $7F,
+; which should be considered an unprintable character).
+
+ processor 6502 ; DASM-specific
+
+; ----------------------------------------------------------------------------
+ include equates.inc
+
+; "backdoor" vectors into the S: and K: ROM drivers. These are addres-minus-1,
+; called by PHA/PHA/RTS.
+s_dev_open_lo = $E410 ; (not named in OS sources)
+s_dev_open_hi = $E411 ; ""
+k_dev_get_lo = $E424 ; ""
+k_dev_get_hi = $E425 ; ""
+
+; ----------------------------------------------------------------------------
+; Constants
+
+LAST_ROW = $1F ; last valid cursor row on screen, 31 decimal (we count from 0)
+EOL = $9B ; Atari ASCII end-of-line (aka the Return key)
+INVERTED_MASK = $F8 ; stored in inverse_mask when rendering in inverse video
+
+; ----------------------------------------------------------------------------
+; Defaults
+
+DEFAULT_TEXT_COLOR = $00
+DEFAULT_BG_COLOR = $C8
+DEFAULT_RMARGN = $3F
+
+; ----------------------------------------------------------------------------
+; ZP storage
+; Reuse some of the E:/S: devices' storage
+; These all get recalculated on col64_putbyte entry,
+; so it's probably OK to mix with GR.8 PLOT/DRAWTO stuff
+
+ seg.u "data"
+ org $A0 ; (used to be $90 aka OLDROW)
+mask_lo ds 1 ; Holds the 16-bit mask, used by render_glyph
+mask_hi ds 1
+screen_ptr_lo ds 1 ; Pointer to display RAM: render_glyph and scroll_screen
+screen_ptr_hi ds 1 ; both use this.
+font_index ds 1 ; index into font: TMPCHR * 5
+shift_amount ds 1 ; How many times to right-shift during render_glyph
+
+ ;org $63 ; aka LOGCOL
+glyph_data_lo ds 1 ; render_glyph stores (possibly shifted) glyph data
+glyph_data_hi ds 1 ; here. Also a 2nd display RAM pointer in scroll_screen
+lo_nybble_flag ds 1 ; non-zero if glyph data in top 4 bits of font
+
+ ;org $68 ; aka SAVADR
+inverse_mask ds 1 ; 0 for normal video, INVERTED_MASK for inverse
+line_buffer_index ds 1 ; used by col64_getbyte
+descender ds 1 ; offset-1 of true descender byte, into font_data
+
+; We also use several other ZP locations, normally used by the OS E: driver:
+; COLCRS ROWCRS TMPCHR BUFCNT RMARGN SAVMSC are used for the same purpose as
+; the OS uses them for.
+
+; ----------------------------------------------------------------------------
+; Non-ZP storage (cassette buffer for now)
+
+ org CASBUF
+line_buffer ds $80
+
+ seg "code"
+; ----------------------------------------------------------------------------
+; XEX segment header
+
+;START_ADDRESS_1 = $9C78
+START_ADDRESS_1 = $9C00 ; should end at $A036; subtract 2K to use with BASIC
+ org START_ADDRESS_1-6
+
+ word $FFFF
+ word START_ADDRESS_1
+ word END_ADDR_1
+
+; ----------------------------------------------------------------------------
+; Font data should be aligned on a page boundary
+; (for speed; still works unaligned). Each 5 bytes stores 2 glyphs
+; side-by-side. When rendering into 5x6 cells, the bottom line and
+; the left column are set to all 0 (or all 1 for inverse video) for padding,
+; so the glyphs can take up the entire 4x5 space.
+; Only character codes 32 through 127 are supported; this is 96
+; characters. At 2 glyphs per 5 bytes, that's 96/2*5=240 bytes,
+; which means the whole font fits into one page and can be
+; accessed with X or Y indexed mode rather than (indirect),Y.
+
+font_data:
+ ;include font4x5.inc
+ include col64_ext.inc
+
+DESCENDERS = $EB ; g j p q y descender bytes, offset from font_data
+
+; ----------------------------------------------------------------------------
+; Mask tables, used by setup_mask. Indexed by (COLCRS % 8), since they
+; would repeat every 8 bytes anyway. Each mask is 16 bits, and contains
+; a 1 for each pixel in screen RAM that we *don't* want to change when
+; writing pixels (because they're not part of the current character cell),
+; but see below...
+
+mask_lo_tab:
+ byte $07, $F8, $C1, $FE, $F0, $83, $FC, $E0
+
+; In mask_hi_tab, $00 is never a valid mask, while $FF means "don't touch any
+; bits in 2nd byte". As a minor optimization, $00 appears in the table in
+; place of $FF. This allows us to just test the Z flag after loading the mask
+; hi byte, instead of needing to compare against $FF.
+; (Actually, on further thought, the $FF's could have been left in, and the
+; test could have been made on the N flag: any hi mask with bit 7 set won't have
+; any other bits clear. *Shrug*)
+
+mask_hi_tab:
+ byte $00, $3F, $00, $0F, $7F, $00, $1F, $00
+
+; ----------------------------------------------------------------------------
+; Indexed by COLCRS%8, how many bits to shift the font data right
+; The mask_*_tab stuff above could be calculated at runtime from this,
+; the tables are only there for speed.
+
+shift_amount_tab:
+ byte $00, $05, $02, $07, $04, $01, $06, $03
+
+; ----------------------------------------------------------------------------
+; Line address tables, used by setup_screen_ptr. Indexed by ROWCRS. Used by
+; setup_screen_ptr
+
+line_addr_tab_lo:
+ byte $00, $f0, $e0, $d0, $c0, $b0, $a0, $90
+ byte $80, $70, $60, $50, $40, $30, $20, $10
+ byte $00, $f0, $e0, $d0, $c0, $b0, $a0, $90
+ byte $80, $70, $60, $50, $40, $30, $20, $10
+
+line_addr_tab_hi:
+ byte $00, $00, $01, $02, $03, $04, $05, $06
+ byte $07, $08, $09, $0a, $0b, $0c, $0d, $0e
+ byte $0f, $0f, $10, $11, $12, $13, $14, $15
+ byte $16, $17, $18, $19, $1a, $1b, $1c, $1d
+
+; ----------------------------------------------------------------------------
+; Byte offset within scanline, indexed by COLCRS & $1F value
+; Used by setup_screen_ptr.
+
+column_byte_tab:
+ byte $00, $00, $01, $01, $02, $03, $03, $04
+ byte $05, $05, $06, $06, $07, $08, $08, $09
+ byte $0A, $0A, $0B, $0B, $0C, $0D, $0D, $0E
+ byte $0F, $0F, $10, $10, $11, $12, $12, $13
+
+; Used to be indexed by COLCRS, rest of the table was:
+ ;byte $14, $14, $15, $15, $16, $17, $17, $18
+ ;byte $19, $19, $1A, $1A, $1B, $1C, $1C, $1D
+ ;byte $1E, $1E, $1F, $1F, $20, $21, $21, $22
+ ;byte $23, $23, $24, $24, $25, $26, $26, $27
+
+; ----------------------------------------------------------------------------
+; Handler table (HATABS will point to this).
+; See the HATABS and EDITRV entries in Mapping the Atari for details.
+
+col64_vector_tab:
+ word col64_open-1 ; OPEN vector
+ word col64_close-1 ; CLOSE vector
+ word col64_getbyte-1 ; GET BYTE vector
+ word col64_putbyte-1 ; PUT BYTE vector
+ word col64_close-1 ; GET STATUS vector
+ word col64_close-1 ; SPECIAL vector
+ ;jmp col64_init ; Jump to initialization code (JMP LSB/MSB)
+ ; (Note: the OS really only ever calls the JMP init
+ ; routines for handlers in ROM, this could be empty)
+
+; ----------------------------------------------------------------------------
+; Assembly version of GRAPHICS 8+16 command.
+
+init_graphics_8:
+ lda #$08 ; graphics mode 8
+ sta ICAX2Z
+ lda #$0C ; R/W access
+ sta ICAX1Z
+ jsr open_s_dev
+
+ ; Set default colors
+ lda #DEFAULT_BG_COLOR
+ sta COLOR2
+ sta COLOR4
+ lda #DEFAULT_TEXT_COLOR
+ sta COLOR1
+
+ ; Protect ourselves from the OS
+ lda #<START_ADDRESS_1
+ sta MEMTOP
+ lda #>START_ADDRESS_1
+ sta MEMTOP+1
+ rts
+
+; ----------------------------------------------------------------------------
+; Call the OPEN vector for the S: device, using the ROM vector table
+; at $E410. The table stores address-minus-one of each routine, which is
+; meant to actually be called via the RTS instruction (standard 6502
+; technique, but confusing the first time you encounter it)
+
+open_s_dev:
+ lda s_dev_open_hi
+ pha
+ lda s_dev_open_lo
+ pha
+ rts
+
+; ----------------------------------------------------------------------------
+; Callback for the internal get-one-byte, used by the OS to implement the
+; CIO GET RECORD and GET BYTES commands. This routine takes no arguments,
+; and returns the read byte in the accumulator.
+
+; Internally, COL64 maintains a line buffer. Each time col64_getbyte is
+; called, it returns the next character in the buffer. If the buffer's
+; empty (or if the last call returned the last character), a new line
+; of input is read from the user (and the first character is returned).
+; This is not exactly how the OS E: device works: it reads keystrokes but
+; doesn't buffer them, until Return is hit; then it reads from screen
+; memory, at the current cursor line (and the line(s) before/after,
+; depending on its map of logical => physical lines). We can't do that
+; because we don't store character codes in screen memory... although
+; we *could* support insert/delete character, delete-line, and left/right
+; arrows. We don't, to save driver code size...
+
+; This code was borrowed from COL80, then big chunks of it were diked out
+; and/or optimized.
+
+col64_getbyte:
+ lda BUFCNT
+ beq get_line ; See if there are bytes left in the buffer
+
+get_next_byte: ; Yes: return next byte from the buffer
+ ldx line_buffer_index
+ lda line_buffer,x
+ dec BUFCNT
+ inc line_buffer_index
+ jmp return_success
+
+; Buffer is empty.
+; Get a line of input from the user, terminated by the Return key.
+get_line:
+ lda #$00
+ sta BUFCNT
+ sta line_buffer_index
+
+show_cursor:
+ jsr print_inv_space
+ jsr get_keystroke
+
+; code meant to deal with BREAK key, left out 'cause FujiChat disables BREAK
+; cpy #$01
+; beq keystroke_ok
+; ldy #0
+; sty line_buffer_index
+; sty BUFCNT
+
+keystroke_ok:
+ cmp #$20
+ bcc show_cursor ; ignore low ASCII
+ cmp #EOL
+ beq return_key_hit
+
+check_backs_key:
+ cmp #$7E
+ beq backs_key_hit
+
+;check_clear_key: ; don't bother, don't need
+ ; (if we did want this, it should check delete-line instead!)
+ ;;cmp #$7D
+ ;;beq clear_key_hit
+
+normal_key_hit:
+ ldx BUFCNT
+ bmi show_cursor
+
+buffer_character:
+ sta line_buffer,x
+ jsr col64_putbyte
+ inc BUFCNT
+ bne show_cursor
+
+return_key_hit:
+ jsr print_space
+ lda #EOL
+ ldx BUFCNT
+ sta line_buffer,x
+ inc BUFCNT
+ jsr col64_putbyte
+ bne get_next_byte ; col64_putbyte always clears Z flag!
+
+;;clear_key_hit:
+; jsr clear_screen ; if we implemented it...
+;; lda #$00
+;; sta line_buffer_index
+;; sta BUFCNT
+;; beq get_line
+
+backs_key_hit:
+ jsr print_space
+ lda BUFCNT
+ beq backs_key_done
+ dec COLCRS
+ lda COLCRS
+ clc
+ adc #$01
+ cmp LMARGN
+ bne backs_same_line
+ lda RMARGN
+ sta COLCRS
+ dec ROWCRS
+
+backs_same_line:
+ dec BUFCNT
+
+backs_key_done:
+ jmp show_cursor
+
+; ----------------------------------------------------------------------------
+; Print a space or inverse space character at the current cursor position.
+; Does not update the cursor position.
+
+print_inv_space:
+ lda #INVERTED_MASK
+ byte $2C
+
+print_space:
+ lda #$00
+ sta inverse_mask
+ lda #$00
+ sta TMPCHR
+ jmp render_glyph
+
+; ----------------------------------------------------------------------------
+; Get a keystroke (blocking). Just calls the OS K: get-one-byte routine
+; (call by pushing address-minus-one then doing an RTS)
+
+get_keystroke:
+ lda k_dev_get_hi
+ pha
+ lda k_dev_get_lo
+ pha
+ ;rts ; fall through to return_success
+
+
+; ----------------------------------------------------------------------------
+; Unimplemented CIO callbacks here. Also various other routines jump here
+; to return success to the caller.
+
+col64_close:
+return_success:
+ ldy #$01
+ rts
+
+; ----------------------------------------------------------------------------
+; CIO OPEN command callback
+
+col64_open:
+ jsr init_graphics_8
+ lda #$00
+ sta ROWCRS
+ sta COLCRS
+ sta BUFCNT
+ sta LMARGN
+ lda #DEFAULT_RMARGN
+ sta RMARGN
+ rts
+
+; ----------------------------------------------------------------------------
+; CIO PUT BYTE command callback
+; The byte to put is passed to us in the accumulator.
+
+col64_putbyte:
+ ; EOL (decimal 155)?
+ cmp #EOL
+;;; bne check_clear
+ bne regular_char
+ lda RMARGN
+ sta COLCRS
+ jmp skip_write
+
+;;;check_clear:
+;;; ; save memory by not including clear_screen
+;;; ; (also, this lets us print the } character)
+;;; ; Clear (decimal 125)?
+;;; cmp #$7D
+;;; bne regular_char
+;;; jmp clear_screen
+;;; .endif
+;;;
+
+; See if this is an inverse video char (code >= 128)
+regular_char:
+ tax
+ bpl not_inverse
+ lda #INVERTED_MASK
+ .byte $2C ; aka BIT abs, skip the LDA
+not_inverse:
+ lda #$00
+ sta inverse_mask
+
+ txa
+ and #$7F
+ sec
+ sbc #$20 ; subtract $20 because we only handle codes $20 to $7F
+ bcs not_low_ascii
+ jmp return_success ; ignore any chr codes $00-$1F or $80-$9F
+
+not_low_ascii:
+ sta TMPCHR
+
+ lda DINDEX ; OS stores current graphics mode here
+ cmp #$08
+ beq graphics_ok
+ ; If we're not in GRAPHICS 8 mode, reinitialize ourselves
+ jsr col64_open
+
+graphics_ok:
+ jsr render_glyph
+
+skip_write:
+ ; Move the cursor 1 space to the right. This will
+ ; advance us to the next line if we're at the margin,
+ ; and scroll the screen if needed
+ jsr advance_cursor
+
+; Could implement SSFLAG logic here
+;check_ssflag:
+ ; The OS keyboard interrupt handler will toggle SSFLAG (start/stop fla
+ ; any time the user presses ctrl-1
+ ;lda SSFLAG
+ ;bne check_ssflag
+ jmp return_success
+
+; ----------------------------------------------------------------------------
+; Call the routines that actually print the character.
+; render_glyph prints the character in TMPCHR at the current
+; COLCRS and ROWCRS, and does NOT advance the cursor.
+; TMPCHR should already have bit 7 stripped; render_glyph will
+; use inverse_mask, so the caller should have set that up as well.
+
+; Note: The 4 subroutines were only ever called from render_glyph,
+; so to save a tiny bit of time and space, they're now inline code.
+
+render_glyph:
+ ;jsr setup_mask
+ ;jsr setup_screen_ptr
+ ;jsr setup_font_index
+ ;jmp write_font_data
+
+; ----------------------------------------------------------------------------
+; mask is used to avoid overwriting pixels outside the character cell
+; we're currently writing. Since 5 pixel wide cells don't align on byte
+; boundaries in screen RAM, we have to read/modify/write 2 bytes, and
+; the mask also has to be 2 bytes wide.
+; Also we set up shift_amount here.
+
+setup_mask:
+ lda COLCRS
+ and #$07
+ tax
+ lda mask_lo_tab,x
+ sta mask_lo
+ lda mask_hi_tab,x
+ sta mask_hi
+ lda shift_amount_tab,x
+ sta shift_amount
+ ;rts
+
+
+; ----------------------------------------------------------------------------
+; Make (screen_ptr_lo) point to the first byte of screen RAM on the top line
+; of the current char cell. Assumes COLCRS/ROWCRS are never out of range!
+setup_screen_ptr:
+ ; first the row... table lookup quicker than mult by 240
+ ldx ROWCRS ; +3 = 3
+ clc ; +2 = 5
+ lda SAVMSC ; +3 = 8
+ adc line_addr_tab_lo,x ; +4 = 12
+ sta screen_ptr_lo ; +3 = 15
+ lda SAVMSC+1 ; +3 = 18
+ adc line_addr_tab_hi,x ; +4 = 22
+ sta screen_ptr_hi ; +3 = 25
+
+ ; now do the column. column_byte_tab is only a half-table, so do lookup
+ ; on bits 0-4 of COLCRS, then add 20 decimal if bit 5 of COLCRS was set.
+ lda COLCRS
+ tay
+ and #$1F
+ tax
+ lda column_byte_tab,x
+ cpy #$20
+ bcc ssp_noadd
+ adc #$13 ; +1 because C set = 20 dec
+
+ssp_noadd:
+ clc
+ adc screen_ptr_lo
+ sta screen_ptr_lo
+ lda #0
+ adc screen_ptr_hi
+ sta screen_ptr_hi
+
+ ;rts
+
+; ----------------------------------------------------------------------------
+; Set up font_index to point to the font_data bitmap for the character in
+; TMPCHR. Also sets lo_nybble_flag to let the caller know whether the
+; bitmap is in the upper or lower 4 bits of the bytes pointed to.
+
+; Calculation is:
+; lo_nybble_flag = (TMPCHR & 1) ? $FF : $00;
+; font_index = (TMPCHR >> 1) * 5;
+
+setup_font_index:
+ lda #$00
+ sta lo_nybble_flag
+ lda TMPCHR
+ lsr ; a = (TMPCHR >> 1)
+ tay ; y = a
+ bcc font_hi_nybble
+ dec lo_nybble_flag ; = $FF
+
+font_hi_nybble:
+ clc
+ asl ; a *= 2
+ asl ; a *= 2
+ sta font_index
+ tya
+ adc font_index
+ sta font_index
+
+ ; rts
+
+
+; ----------------------------------------------------------------------------
+; True descender support: we've got a hard-coded list of 5 characters
+; (g j p q y) that have them. All the descender graphics are stored in the
+; bottom nybble of the last glyph in the font, which means we can only have
+; 5 characters that have descenders.
+; TODO: tighten up this code some (faster/smaller)
+
+ lda TMPCHR
+ ldx #$FF
+
+ cmp #'g-$20
+ bne chk_j
+ ldx #DESCENDERS-1
+chk_j:
+ cmp #'j-$20
+ bne chk_p
+ ldx #DESCENDERS
+chk_p:
+ cmp #'p-$20
+ bne chk_q
+ ldx #DESCENDERS+1
+chk_q:
+ cmp #'q-$20
+ bne chk_y
+ ldx #DESCENDERS+2
+chk_y:
+ cmp #'y-$20
+ bne not_y
+ ldx #DESCENDERS+3
+
+not_y:
+ stx descender
+
+; ----------------------------------------------------------------------------
+; When write_font_data is called, all this stuff must be set up:
+; - font_index is the 1-byte index into font_data where the current glyph is
+; - lo_nybble_flag is 0 for high nybble of glyph data, $FF for low
+; - mask_lo/hi is our 16-bit pixel mask (1's are "leave original data")
+; - shift_amount is # of times to shift glyph data right
+; - screen_ptr_lo/hi points to the 1st byte on the top line
+; - inverse_mask is 0 for normal or INVERTED_MASK for inverse
+; - descender is the offset *minus one* of the byte holding the bottom 4
+; pixels in the 4x6 character. Most of the time this will be $FF,
+; AKA the the offset from font_data of the first byte of the space glyph
+; (minus one), which has 0000 in its top nybble. The rest of the time,
+; the descenders are taken from the bottom nybble of the last character
+; glyph (which would be the unprintable code $7F). The logic that does
+; the descenders is hard-coded to use the top nybble for $FF and the
+; bottom nybble for anything else.
+
+; Loop 5 times, each time thru the loop:
+; - extract 4-bit glyph data, store in glyph_data_lo
+; - apply inverse_mask
+; - shift right shift_amount times
+; ...write data...
+; - add 40 to 16-bit screen_ptr_lo/hi (to get to next line)
+; ...then one more loop with font_index and lo_nybble_flag set
+; to a byte in the space glyph, to handle the bottom row (which
+; is always 0 for normal or all 1's for inverse)
+
+write_font_data:
+ ldx #$05 ; outer loop counter, aye
+
+wfont_line_loop:
+ lda #$00
+ sta glyph_data_hi
+
+ ldy font_index
+ lda font_data,y ; note: entire font must fit in one page!
+
+ bit lo_nybble_flag
+ beq use_hi_nybble
+
+ asl ; the pixels we want are in the low nybble of the font data byte.
+ asl ; shift them up to the top nybble
+ asl
+ asl
+
+use_hi_nybble: ; 4-bit glyph data now in hi nybble
+ and #$F0
+ eor inverse_mask
+ sta glyph_data_lo
+
+ ldy shift_amount
+ beq wfont_no_shift
+
+wfont_shift_loop: ; right-shift 16-bit glyph data shift_amount times
+ lsr glyph_data_lo
+ ror glyph_data_hi
+ dey
+ bne wfont_shift_loop
+
+wfont_no_shift: ; Y always zero when we get here
+ lda mask_lo
+ and (screen_ptr_lo),y
+ ora glyph_data_lo
+ sta (screen_ptr_lo),y
+
+ lda mask_hi
+ beq wfont_skip_hi ; don't bother with 2nd screen byte if we don't need to
+ iny
+ and (screen_ptr_lo),y
+ ora glyph_data_hi
+ sta (screen_ptr_lo),y
+
+wfont_skip_hi:
+ dex
+ bmi wfont_done
+ bne wfont_not_bottom
+
+ ;stx font_index
+ ;stx lo_nybble_flag
+
+; X always 0 here: for last line, use the descender (if there's no
+; descender for this char, that's $FF. font_index will get inc'ed,
+; meaning non-decender chars use the first byte of the space glyph
+; as their "descender")
+ lda descender
+ sta font_index
+ cmp #$FF
+ beq wfont_not_bottom
+ sta lo_nybble_flag
+
+wfont_not_bottom:
+ lda #$28 ; add 40 bytes to point to next line of screen RAM
+ clc
+ adc screen_ptr_lo
+ sta screen_ptr_lo
+ bcc wfont_noinc
+ inc screen_ptr_hi
+
+wfont_noinc:
+ inc font_index
+ bne wfont_line_loop ; branch always
+
+wfont_done:
+ rts
+
+; ----------------------------------------------------------------------------
+; Not the fastest scroller in the west... TODO: make faster :)
+
+; lda_operand points to line N (minus one byte)
+; sta_operand points to line N+1 (minus one byte)
+; Y ranges 240 to 1 in the loop, hence the -1 byte
+; CAUTION: Self-modifying code! Proceed with caution.
+
+; This version gives us overall driver speed almost 20% faster
+; than the original scroll_screen (last commented-out one below)
+; Also just scrolling 250 times is slightly faster than COL80
+; (1505 jiffies; setting CRITIC saves 48 jiffies)
+; (makes it 17% the speed of the OS E: driver, where COL80 is 15%)
+; Note that E80 is slightly over twice as fast at this as the OS!
+
+; Note about performance where scrolling is *not* concerned:
+; Printing 914 non-control characters on a freshly-cleared screen:
+; OS E: - 172 jiffies (subtract 12 = 160 jiffies if cursor disabled)
+; E80 - 168 jiffies (about same as OS E:)
+; COL80 - 116 jiffies (yes, it's fastest!)
+; CON64 from SDX 4.41 - 227 jiffies first time I tried, crashed next time!
+; COL64 - 142 jiffies (still faster than OS E:)
+
+scroll_screen:
+; lda SDMCTL
+; pha
+; lda #0
+; sta SDMCTL
+
+; lda CRITIC
+; pha
+; lda #1
+; sta CRITIC
+
+ lda SAVMSC
+ sec
+ sbc #1
+ sta lda_operand
+ lda SAVMSC+1
+ sbc #0
+ sta lda_operand+1
+ ldx #LAST_ROW
+
+scroll_line_loop:
+ ldy #$F0
+
+ lda lda_operand+1
+ sta sta_operand+1
+ lda lda_operand
+ sta sta_operand
+ clc
+ adc #$F0
+ sta lda_operand
+ bcc ss_noinc
+ inc lda_operand+1
+ss_noinc:
+
+scroll_byte_loop:
+lda_operand = *+1
+ lda 0,y
+sta_operand = *+1
+ sta 0,y
+ dey
+ bne scroll_byte_loop
+ dex
+ bne scroll_line_loop
+
+scroll_blank:
+ lda lda_operand
+ sta sta2_operand
+ lda lda_operand+1
+ sta sta2_operand+1
+ lda #0
+ ldy #$F0
+sblank_loop:
+sta2_operand = *+1
+ sta 0,y
+ dey
+ bne sblank_loop
+
+; pla
+; sta SDMCTL
+; pla
+; sta CRITIC
+ rts
+
+;; This version is faster and fully functional
+;; (overall driver speed is 10% faster than with the
+;; one below)
+; glyph_data_lo points to line N (minus one byte)
+; screen_ptr_lo points to line N+1 (minus one byte)
+; Y ranges 240 to 1 in the loop, hence the -1 byte
+
+;;scroll_screen:
+;; lda SAVMSC
+;; sec
+;; sbc #1
+;; sta screen_ptr_lo
+;; lda SAVMSC+1
+;; sbc #0
+;; sta screen_ptr_hi
+;; ldx #LAST_ROW
+;;
+;;scroll_line_loop:
+;; ldy #$F0
+;;
+;; lda screen_ptr_hi
+;; sta glyph_data_hi
+;; lda screen_ptr_lo
+;; sta glyph_data_lo
+;; clc
+;; adc #$F0
+;; sta screen_ptr_lo
+;; bcc ss_noinc
+;; inc screen_ptr_hi
+;;ss_noinc:
+;;
+;;scroll_byte_loop:
+;; lda (screen_ptr_lo),y
+;; sta (glyph_data_lo),y
+;; dey
+;; bne scroll_byte_loop
+;; dex
+;; bne scroll_line_loop
+;;
+;;scroll_blank:
+;; lda #0
+;; ldy #$F0
+;;sblank_loop:
+;; sta (screen_ptr_lo),y
+;; dey
+;; bne sblank_loop
+;;
+;; rts
+
+; Clock cycle timings:
+; 1792080 CPU cycles per second (or is it 1789773?)
+; 29868 per jiffy on NTSC (1/60 sec)
+; DL = 174 bytes @ 1 cycle each
+; Screen RAM = 7680 bytes @ 1 ea
+; Refresh = 262 * 9 = 2358
+; so ANTIC steals 10212 (34.2%) cycles, leaves 19656 (65.8%)
+; Of that time, the OS steals some doing VBLANK processing.
+; It may be that I can set CRITIC here and get a little of
+; that back (depends on what, if anything, that does to
+; the RS232 driver and/or custom keybuffer stuff in FujiChat).
+
+; Now if I could actually do a 100% unrolled scroller, simply
+; LDA blah:STA blah-1 7680 times, with NMI/VBI/ANTIC disabled,
+; that would be 4+4=8 cycles times 7680 = 61440, or 3.12 frames
+; (or 0.052 sec, call it 1/20 sec). Obviously can't do it that way.
+
+; Did some tests of overall performance (not just scrolling: print
+; 24 lines of 35 chars, then 24 newlines, repeat in a loop 10x)
+; Turning off ANTIC DMA seems to save 25% time. Setting CRITIC only
+; saves 3% or so. Disabling IRQs/NMIs entirely is probably not an
+; option.
+
+;; old (slower, but working) version:
+;; scroll_screen:
+;; lda #0 ; +2 = 2
+;; sta COLCRS ; +3 = 5
+;; sta ROWCRS ; +3 = 8
+;; jsr setup_screen_ptr ; +6 = 14, +54 = 68
+;;
+;; scroll_line_loop:
+;; lda screen_ptr_lo ; +3 = 3
+;; sta glyph_data_lo ; +3 = 6
+;; lda screen_ptr_hi ; +3 = 12
+;; sta glyph_data_hi ; +3 = 15
+;; ldx ROWCRS ; +3 = 18
+;; cpx #LAST_ROW ; +2 = 20
+;; beq scroll_blank ; +2 = 22 (+1 more last time thru)
+;; inx ; +2 = 24
+;; stx ROWCRS ; +3 = 27
+;; jsr setup_screen_ptr ; +6+54 = 87
+;; ldy #0 ; +2 = 89
+;; ; times 31 is 2759, +1 = 2760
+;;
+;; scroll_byte_loop:
+;; lda (screen_ptr_lo),y ; +5 = 5
+;; sta (glyph_data_lo),y ; +6 = 11
+;; iny ; +2 = 13
+;; cpy #$F0 ; +2 = 15
+;; bne scroll_byte_loop ; +3 = 18 (-1 last time thru)
+;; ; ...times 31 times 240 - 1 = 133919 (!)
+;; beq scroll_line_loop ; +3*31-1 (92)
+;;
+;; scroll_blank:
+;; jsr setup_screen_ptr ; +6+54 = 60
+;; ldy #0 ; +2 = 62
+;; tya ; +2 = 64
+;; sblank_loop:
+;; sta (screen_ptr_lo),y ; +6 = 6
+;; iny ; +2 = 8
+;; cpy #$F0 ; +2 = 10
+;; bne sblank_loop ; +3 = 13 (-1 last time)
+;; ; times 240, minus 1 = 3119
+;;
+;; rts ; +6
+;;
+;; Total routine time is 68 + 2760 + 133919 + 92 + 64 + 3119 + 6 = 140028
+;; Divide by free cyc/frame: 140028/19656 = 7.12 frames, or 0.11 sec,
+;; not counting VBLANK overhead. 95% of the time is of course in the
+;; inner loop. Every cycle saved in the inner loop is worth about
+;; 5% of the runtime! So switching from incrementing to decrementing
+;; Y will save 10% of the time (from not having the CPY). Using self-
+;; modifying code for the lda/sta saves 2 more cycles (10% more), but
+;; adds a small bit of overhead in the outer loop.
+;; The scroll_blank loop is only 2.2% of the total time. Every cycle
+;; shaved off its loop is worth only 1/3 of a percent of the total
+;; time (switching to dey is worth 2/3 of 1%).
+;; Replace jsr setup_screen_ptr in scroll_line_loop with loading from
+;; the tables directly will save approx. 35 cycles per outer loop,
+;; or only about 0.8%.
+;; So total savings is 20% + 0.6% + 0.8% = 21.4%, meaning real time
+;; drops to approx 0.085 sec, or approx 5.5 NTSC frames (another way
+;; to look at it: 11.75 scrolled lines/sec instead of the original 9)
+;; Yet another way: 2 1/3 seconds to scroll the whole screen, vs
+;; the original 3 1/2. Still abysmal.
+
+;; One possibility would be to borrow a page from the ACE-80 book and
+;; update LMSes within the DL. This would bloat the display list by
+;; 64 bytes (not so bad). We'd basically treat screen RAM as a circular
+;; buffer of 32 lines. Every scroll, update the LMS operands to point
+;; to the next line-buffer, and whichever buffer is the last visible
+;; line needs to be blanked. Got to see how much code this will add
+;; (possibly the routine that does this might not be longer than the
+;; scroll_screen I've been using). ACE-80 (or anyway E80) uses way
+;; more screen RAM than it looks like it needs, plus DLIs.
+
+; ----------------------------------------------------------------------------
+; Move the cursor one space to the right (to the next line if at the margin,
+; and scroll screen if on the last row)
+
+advance_cursor:
+ inc COLCRS
+ lda RMARGN
+ cmp COLCRS
+ bcs same_line
+ lda LMARGN
+ sta COLCRS
+ lda ROWCRS
+ cmp #LAST_ROW
+ bcc no_scroll
+ jsr scroll_screen
+ ; Move to last row after scrolling
+ lda #LAST_ROW-1
+ sta ROWCRS
+
+no_scroll:
+ inc ROWCRS
+
+same_line:
+ rts
+
+END_ADDR_1 = *-1
+
+
+; ----------------------------------------------------------------------------
+; Initialization. If we don't want the handler to survive a warmstart, we
+; can load this bit into e.g. the cassette buffer (throw away after running)
+
+START_ADDRESS_2 = CASBUF
+
+; XEX segment header for throwaway init code
+ rorg START_ADDRESS_2-4
+ word START_ADDRESS_2
+ word END_ADDR_2
+
+col64_init:
+ ldy #$00
+
+next_hatab_slot:
+ lda HATABS,y
+ beq register_x_handler
+ iny
+ iny
+ iny
+ cpy #$20
+ bcc next_hatab_slot
+ jmp return_success
+
+register_x_handler:
+ lda #$58
+ sta HATABS,y
+ lda #<col64_vector_tab
+ iny
+ sta HATABS,y
+ lda #>col64_vector_tab
+ iny
+ sta HATABS,y
+ jmp return_success
+
+main_entry_point:
+ jsr col64_init
+ lda #$0C
+ sta ICCOM
+ ldx #$00
+ jsr CIOV
+ lda #$58
+ sta font_index
+ lda #$03
+ sta ICCOM
+ lda #font_index
+ sta ICBAL
+ lda #$00
+ sta ICBAH
+ ldx #$00
+ jsr CIOV
+ ldy #$07
+ lda #<col64_vector_tab
+ sta HATABS,y
+ lda #>col64_vector_tab
+ iny
+ sta HATABS,y
+no_e_handler:
+ lda #<START_ADDRESS_1
+ sta MEMTOP
+ lda #>START_ADDRESS_1
+ sta MEMTOP+1
+ jmp return_success
+
+END_ADDR_2 = *-1
+
+; XEX segment (run address)
+ word INITAD
+ word INITAD+1
+ word main_entry_point
+
+; That's all, folks...
+
+; Rest of file is me rambling & meandering, ignore or not as you choose
+
+; Possible improvements, some of which may apply to this driver only,
+; some of which may apply to a (to be written) 40-column renderer.
+; Redb3ard has designed really nice 8x8 normal, bold, italic fonts,
+; including a bunch of Unicode normal characters... the 40-column
+; driver would include UTF-8 support. Of course there's not enough
+; RAM for an IRC client, TCP/IP stack, screen/DL memory, driver,
+; UTF-8 tables, and 3 or 4 fonts... will have to wait until after
+; the 1.0 FujiChat release (my roadmap for 1.0 is that everything
+; needs to work on a 48K unmodded 800; 2.0 will have new features
+; that may only work on an XL or even require 130XE banks, though
+; it will still be as functional as 1.0, on an 800).
+
+; True descenders and 5-bit-wide characters.
+
+; For descenders, could simply leave the top row of pixels blank on
+; the screen, and draw the 5 rows of character in the bottom 5 of
+; the 6-scanline block. They'd possibly touch the character on the
+; next line...
+
+; 5-bit-wide characters should be used sparingly: only M W m w T
+; and maybe Y V v # need them. The "extra" bit could go on the left,
+; and just be a copy of the rightmost bit, since these characters
+; are symmetrical... but these would often touch the character on
+; the left. Capital letters, it's less of a big deal in normal English
+; text, since a capital letter should be preceded by a space (or at
+; least punctuation), and it won't touch the character on the right
+; unless it's another 5-bit-wide one (few words in English are going
+; to have that problem; maybe the name AMY in all caps). Unfortunately
+; I can't think of a good way to encode the bits of information that
+; say a character needs the extra pixel (or a descender either) other
+; than a hard-coded set of compares against specific char codes, or
+; else a loop over a table of them. Either way there's a loss of
+; performance: most characters will fail all the compares...
+; It'd be possible to do a 5x5 font, or even 5x6, but 5 bits wide
+; means we can't pack the pixel data 2 rows per byte (so the
+; font won't fit in a page any more, plus we have to use (zp),y
+; or something to access it...)
+
+; Multiple font support. Since it's an IRC-specific driver, could just
+; have _putbyte directly interpret the IRC protocol formatting codes,
+; render e.g. bold as inverse, italic as underline if I implement it,
+; or else do up a separate italic font (if it's possible to make one
+; look good in 4x5). _putbyte could at least strip out the codes it
+; can't render (e.g. color).
+
+; I've thought of doing underline (either a separate mode, or instead
+; of inverse video), but a lot of the glyphs will look like crap with
+; the underline, because there's no room for spacing: the underline
+; will touch the bottom pixels of most characters (and overwrite the
+; descenders if we add true descender support...)
+
+; Obviously, making it a fully-functional E: replacement would be nice.
+; I'm not doing this because I'm only wanting to use the driver for
+; text-only cc65 programs (specifically FujiChat), though possibly
+; I'll come back to col64 and do a proper version later.
+
+; Also nice: user-adjustable number of rows. Most peoples' monitors can
+; display something above 200 scanlines (particularly if they're in PAL
+; countries). As-is, we're using 192 scanlines to get 32 rows (of 6 lines
+; each). Most people could easily display 34 rows (204 scanlines), and
+; not a few could display 35 (210), particularly if the blanking
+; instructions at the start of the display list are user-adjustable too
+; (to move the picture up or down). Memory usage for video RAM would
+; grow by 240 byte per row of characters, and of course we'd need code
+; to set up the custom display list (which would be longer than a
+; normal one for GR.8). Probably would put a limit of 36 or 40 rows
+; since the various tables are fixed-size...
+
+; If there were RAM enough for it, or if we decide to use XE extra
+; banks (or XL/XE under-OS RAM), could have _putbyte also store
+; every output character in a buffer, for FujiChat to use as
+; scrollback/log buffer (or any other program to use as it sees
+; fit, of course).
+
+; User-loadable font isn't a bad idea: the init code can look for a
+; file D:COL64.FNT and load it into font_data if found.
+
+; Could implement standard ASCII backspace/tab/linefeed/CR/etc codes,
+; using low ASCII codes. This would be suitable for a telnet or terminal
+; client (not needed for IRC)
+
+; I really would like to do auto-relocation. Program could load itself
+; wherever, and relocate itself (using a table of offsets, for absolute
+; addresses within the program) to either MEMLO or MEMTOP. This would
+; mean more init code only.
+
+; It'd be nice to speed up scrolling. One dumb trick would be to use
+; self-modifying code: instead of (zp),y addressing, use abs,y
+; in the inner loop, and the outer loop modifies the operands in
+; the inner. Would mean the code can't be burned to ROM, but who
+; was planning to do that anyway? Also simply moving more than one
+; chunk per outer-loop iteration would be a small speedup, and so
+; would moving 256 bytes per, instead of 240.
+; Since the inner loop does lda (zp),y [5+cyc] and sta (zp),y [6cyc]
+; 7440 times, replacing them with lda abs,y [4+cyc] and sta abs,y
+; [5cyc] should save 7440*2 = almost 15K cycles.
+; which may not be noticeable... Unrolling the loop is even less of a
+; gain: the outer loop only runs 32 times. Could set CRITIC during the
+; move (not sure that helps much). No matter how you slice it,
+; moving 8K on a 6502 is *slow*.
+
+; One slightly cool idea would be to do a proper OPEN of channel #6
+; to S:, like the BASIC GR. command does, instead of the "shortcut"
+; using ZIOCB and calling the S: open routine directly. Doing this
+; would allow PLOT, DRAWTO, and XIO 18 (fill).
diff --git a/src/col64/col64_ext.inc b/src/col64/col64_ext.inc
new file mode 100644
index 0000000..81e7660
--- /dev/null
+++ b/src/col64/col64_ext.inc
@@ -0,0 +1,48 @@
+ byte $04, $04, $04, $00, $04 ; [0] 32,33 ,!
+ byte $AA, $AF, $0A, $0F, $0A ; [5] 34,35 ",#
+ byte $70, $A9, $62, $54, $E9 ; [10] 36,37 $,%
+ byte $42, $A2, $44, $A0, $D0 ; [15] 38,39 &,'
+ byte $24, $42, $42, $42, $24 ; [20] 40,41 (,)
+ byte $A4, $44, $EE, $44, $A4 ; [25] 42,43 *,+
+ byte $00, $00, $0F, $20, $40 ; [30] 44,45 ,,-
+ byte $02, $02, $04, $08, $48 ; [35] 46,47 .,/
+ byte $64, $9C, $B4, $D4, $6E ; [40] 48,49 0,1
+ byte $6E, $91, $26, $41, $FE ; [45] 50,51 2,3
+ byte $2F, $68, $AE, $F1, $2E ; [50] 52,53 4,5
+ byte $7F, $81, $E2, $94, $64 ; [55] 54,55 6,7
+ byte $66, $99, $67, $91, $6E ; [60] 56,57 8,9
+ byte $00, $42, $00, $02, $44 ; [65] 58,59 :,;
+ byte $20, $4F, $80, $4F, $20 ; [70] 60,61 <,=
+ byte $87, $49, $22, $40, $82 ; [75] 62,63 >,?
+ byte $66, $B9, $BF, $89, $69 ; [80] 64,65 @,A
+ byte $E6, $99, $E8, $99, $E6 ; [85] 66,67 B,C
+ byte $EF, $98, $9E, $98, $EF ; [90] 68,69 D,E
+ byte $F7, $88, $EB, $89, $86 ; [95] 70,71 F,G
+ byte $9E, $94, $F4, $94, $9E ; [100] 72,73 H,I
+ byte $39, $1A, $1C, $9A, $69 ; [105] 74,75 J,K
+ byte $8A, $8F, $8D, $89, $F9 ; [110] 76,77 L,M
+ byte $96, $D9, $B9, $99, $96 ; [115] 78,79 N,O
+ byte $E6, $99, $E9, $8A, $85 ; [120] 80,81 P,Q
+ byte $E7, $98, $E6, $A1, $9E ; [125] 82,83 R,S
+ byte $F9, $49, $49, $49, $46 ; [130] 84,85 T,U
+ byte $99, $99, $9D, $AF, $4A ; [135] 86,87 V,W
+ byte $99, $99, $66, $92, $94 ; [140] 88,89 X,Y
+ byte $F6, $24, $44, $84, $F6 ; [145] 90,91 Z,[
+ byte $86, $82, $42, $22, $26 ; [150] 92,93 \,]
+ byte $40, $A0, $00, $00, $0F ; [155] 94,95 ^,_
+ byte $40, $47, $29, $0B, $05 ; [160] 96,97 `,a
+ byte $80, $87, $E8, $98, $E7 ; [165] 98,99 b,c
+ byte $10, $16, $79, $9E, $77 ; [170] 100,101 d,e
+ byte $60, $47, $E9, $47, $41 ; [175] 102,103 f,g
+ byte $84, $80, $EC, $94, $9E ; [180] 104,105 h,i
+ byte $28, $0A, $6C, $2A, $29 ; [185] 106,107 j,k
+ byte $C0, $4A, $4F, $4D, $E9 ; [190] 108,109 l,m
+ byte $00, $E6, $99, $99, $96 ; [195] 110,111 n,o
+ byte $00, $E7, $99, $E7, $81 ; [200] 112,113 p,q
+ byte $00, $A7, $DC, $83, $8E ; [205] 114,115 r,s
+ byte $40, $E9, $49, $49, $26 ; [210] 116,117 t,u
+ byte $00, $99, $9D, $AF, $4A ; [215] 118,119 v,w
+ byte $00, $99, $69, $66, $92 ; [220] 120,121 x,y
+ byte $06, $F4, $28, $44, $F6 ; [225] 122,123 z,{
+ byte $4C, $44, $42, $44, $4C ; [230] 124,125 |,}
+ byte $06, $5C, $A8, $01, $0C ; [235] 126,127 ~,
diff --git a/src/col64/cruft/col64.dasm b/src/col64/cruft/col64.dasm
new file mode 100644
index 0000000..aca1259
--- /dev/null
+++ b/src/col64/cruft/col64.dasm
@@ -0,0 +1,1194 @@
+
+; ----------------------------------------------------------------------------
+; 64x32 software text driver
+; Uses 4x5 font in 5x6 character cells
+; Based on disassembled COL80 driver
+
+; This driver is missing quite a few things a full E: driver should have:
+
+; - Does not work with BASIC or any other cart! Though if START_ADDRESS_1
+; is changed to $7Cxx, a BASIC-able version could be assembled
+
+; - No support for cursor controls, insert/delete, or even clear screen
+; (instead the control-codes are printed as normal characters, if they're
+; above 31 decimal). This is a feature: our intended application is an
+; IRC client, where ASCII codes 125 and 126 represent } and ~ chars,
+; not clear-screen and backspace.
+
+; - Backspace key is supported during get-byte, but printing a backspace
+; with put-byte prints a tilde instead. Again, a feature.
+
+; - No support for low ASCII at all: any attempt to input or print a character
+; in the range 0-31 decimal is just ignored (this includes the arrow keys).
+; This is done to keep the font size at 96 characters, so it'll fit in a
+; page. Also IRC doesn't use low-ASCII.
+
+; - Does not attempt to survive a warmstart
+
+; - Will fail disastrously if an application sets COLCRS/ROWCRS to any
+; out-of-range values
+
+; - Only displays the cursor during get-byte operations
+
+; On the other hand, this driver is tiny (font is 240 bytes, code 718, not
+; counting 100 bytes of throwaway init code in the tape buffer), and plays
+; nice with cc65's stdio support (though NOT conio, don't even go there)
+
+; Theory of operation:
+
+; This is an Atari OS-compliant device driver. On load, the init routine
+; replaces the E: entry in HATABS with a pointer to our vector table,
+; col64_vector_tab.
+
+; We implement the CIO commands OPEN, CLOSE, GETBYTE, and PUTBYTE. The
+; GET-STATUS and SPECIAL commands are not implemented, and the CLOSE
+; command simply returns success (it doesn't need to do anything else).
+
+; When a channel is OPENed to our new E: device, the col64_open routine
+; calls part of the OS's S: handler to switch to GRAPHICS 8 (320x192 mono)
+; mode.
+
+; When the CIO PUT-BYTES or PUT-RECORD calls are made on our channel, CIO
+; calls our PUTBYTE routine (col64_putbyte) as needed to write (print)
+; characters to the screen. col64_putbyte keeps track of the current
+; cursor position (using COLCRS and ROWCRS), and either renders a glyph
+; at the current location, or (when the EOL character $9B is printed)
+; moves the cursor to the beginning of the next line, scrolling the
+; display RAM if necessary.
+
+; When the CIO GET-BYTES or GET-RECORD calls are made on our channel, CIO
+; calls our GETBYTE routine (col64_getbyte). This routine maintains its
+; own buffer of user-input characters. When first called (or any call when
+; the buffer is empty), col64_getbyte reads a complete line of input using
+; the OS's K: handler, echoing typed characters to the screen using our
+; own col64_putbyte. Only the backspace key is supported for editing. Once
+; the user presses Return, the first byte in the buffer is returned to
+; the caller. On subsequent calls, characters are returned from the buffer
+; until the buffer is empty. At this point, the next call to col64_getbyte
+; will result in a new line of input being read.
+
+; col64_putbyte calls render_glyph to draw a character in display RAM.
+; The font consists of 96 characters (low ASCII not supported), each 4 pixels
+; wide and 5 tall [*]. These are rendered into 5x6 character cells, with the
+; extra pixels being left blank to provide padding between characters.
+; Since 5 pixel wide cells don't line up evenly on display RAM byte
+; boundaries, render_glyph has to shift each 4-pixel line of glyph
+; data the appropriate number of times, and combine the result with the
+; rest of each screen byte (that portion that's outside of the 5-pixel
+; cell we're currently writing to). Surprisingly, this is accomplished
+; slightly faster than the standard OS E: driver prints a single character.
+; (unfortunately, scrolling the screen is *much* slower than the OS E:
+; driver's scrolling...)
+
+; [*] ...except the lowercase q j p q y, which have true descenders. The
+; glyphs for these are still 4x5, but the 6th row of pixels for all 5
+; get stored together in the last glyph in the set (ASCII code $7F,
+; which should be considered an unprintable character).
+
+ processor 6502 ; DASM-specific
+
+; ----------------------------------------------------------------------------
+ include equates.inc
+
+; "backdoor" vectors into the S: and K: ROM drivers. These are addres-minus-1,
+; called by PHA/PHA/RTS.
+s_dev_open_lo = $E410 ; (not named in OS sources)
+s_dev_open_hi = $E411 ; ""
+k_dev_get_lo = $E424 ; ""
+k_dev_get_hi = $E425 ; ""
+
+; ----------------------------------------------------------------------------
+; Constants
+
+LAST_ROW = $1F ; last valid cursor row on screen, 31 decimal (we count from 0)
+EOL = $9B ; Atari ASCII end-of-line (aka the Return key)
+INVERTED_MASK = $F8 ; stored in inverse_mask when rendering in inverse video
+
+; ----------------------------------------------------------------------------
+; Defaults
+
+DEFAULT_TEXT_COLOR = $00
+DEFAULT_BG_COLOR = $C8
+DEFAULT_RMARGN = $3F
+
+; ----------------------------------------------------------------------------
+; ZP storage
+; Reuse some of the E:/S: devices' storage
+; These all get recalculated on col64_putbyte entry,
+; so it's probably OK to mix with GR.8 PLOT/DRAWTO stuff
+
+ seg.u "data"
+ org $A0 ; (used to be $90 aka OLDROW)
+mask_lo ds 1 ; Holds the 16-bit mask, used by render_glyph
+mask_hi ds 1
+screen_ptr_lo ds 1 ; Pointer to display RAM: render_glyph and scroll_screen
+screen_ptr_hi ds 1 ; both use this.
+font_index ds 1 ; index into font: TMPCHR * 5
+shift_amount ds 1 ; How many times to right-shift during render_glyph
+
+ ;org $63 ; aka LOGCOL
+glyph_data_lo ds 1 ; render_glyph stores (possibly shifted) glyph data
+glyph_data_hi ds 1 ; here. Also a 2nd display RAM pointer in scroll_screen
+lo_nybble_flag ds 1 ; non-zero if glyph data in top 4 bits of font
+
+ ;org $68 ; aka SAVADR
+inverse_mask ds 1 ; 0 for normal video, INVERTED_MASK for inverse
+line_buffer_index ds 1 ; used by col64_getbyte
+descender ds 1 ; offset-1 of true descender byte, into font_data
+
+; We also use several other ZP locations, normally used by the OS E: driver:
+; COLCRS ROWCRS TMPCHR BUFCNT RMARGN SAVMSC are used for the same purpose as
+; the OS uses them for.
+
+; ----------------------------------------------------------------------------
+; Non-ZP storage (cassette buffer for now)
+
+ org CASBUF
+line_buffer ds $80
+
+ seg "code"
+; ----------------------------------------------------------------------------
+; XEX segment header
+
+;START_ADDRESS_1 = $9C78
+START_ADDRESS_1 = $9C00 ; should end at $A036; subtract 2K to use with BASIC
+ org START_ADDRESS_1-6
+
+ word $FFFF
+ word START_ADDRESS_1
+ word END_ADDR_1
+
+; ----------------------------------------------------------------------------
+; Font data should be aligned on a page boundary
+; (for speed; still works unaligned). Each 5 bytes stores 2 glyphs
+; side-by-side. When rendering into 5x6 cells, the bottom line and
+; the left column are set to all 0 (or all 1 for inverse video) for padding,
+; so the glyphs can take up the entire 4x5 space.
+; Only character codes 32 through 127 are supported; this is 96
+; characters. At 2 glyphs per 5 bytes, that's 96/2*5=240 bytes,
+; which means the whole font fits into one page and can be
+; accessed with X or Y indexed mode rather than (indirect),Y.
+
+font_data:
+ ;include font4x5.inc
+ include col64_ext.inc
+
+DESCENDERS = $EB ; g j p q y descender bytes, offset from font_data
+
+; ----------------------------------------------------------------------------
+; Mask tables, used by setup_mask. Indexed by (COLCRS % 8), since they
+; would repeat every 8 bytes anyway. Each mask is 16 bits, and contains
+; a 1 for each pixel in screen RAM that we *don't* want to change when
+; writing pixels (because they're not part of the current character cell),
+; but see below...
+
+mask_lo_tab:
+ byte $07, $F8, $C1, $FE, $F0, $83, $FC, $E0
+
+; In mask_hi_tab, $00 is never a valid mask, while $FF means "don't touch any
+; bits in 2nd byte". As a minor optimization, $00 appears in the table in
+; place of $FF. This allows us to just test the Z flag after loading the mask
+; hi byte, instead of needing to compare against $FF.
+; (Actually, on further thought, the $FF's could have been left in, and the
+; test could have been made on the N flag: any hi mask with bit 7 set won't have
+; any other bits clear. *Shrug*)
+
+mask_hi_tab:
+ byte $00, $3F, $00, $0F, $7F, $00, $1F, $00
+
+; ----------------------------------------------------------------------------
+; Indexed by COLCRS%8, how many bits to shift the font data right
+; The mask_*_tab stuff above could be calculated at runtime from this,
+; the tables are only there for speed.
+
+shift_amount_tab:
+ byte $00, $05, $02, $07, $04, $01, $06, $03
+
+; ----------------------------------------------------------------------------
+; Line address tables, used by setup_screen_ptr. Indexed by ROWCRS. Used by
+; setup_screen_ptr
+
+line_addr_tab_lo:
+ byte $00, $f0, $e0, $d0, $c0, $b0, $a0, $90
+ byte $80, $70, $60, $50, $40, $30, $20, $10
+ byte $00, $f0, $e0, $d0, $c0, $b0, $a0, $90
+ byte $80, $70, $60, $50, $40, $30, $20, $10
+
+line_addr_tab_hi:
+ byte $00, $00, $01, $02, $03, $04, $05, $06
+ byte $07, $08, $09, $0a, $0b, $0c, $0d, $0e
+ byte $0f, $0f, $10, $11, $12, $13, $14, $15
+ byte $16, $17, $18, $19, $1a, $1b, $1c, $1d
+
+; ----------------------------------------------------------------------------
+; Byte offset within scanline, indexed by COLCRS & $1F value
+; Used by setup_screen_ptr.
+
+column_byte_tab:
+ byte $00, $00, $01, $01, $02, $03, $03, $04
+ byte $05, $05, $06, $06, $07, $08, $08, $09
+ byte $0A, $0A, $0B, $0B, $0C, $0D, $0D, $0E
+ byte $0F, $0F, $10, $10, $11, $12, $12, $13
+
+; Used to be indexed by COLCRS, rest of the table was:
+ ;byte $14, $14, $15, $15, $16, $17, $17, $18
+ ;byte $19, $19, $1A, $1A, $1B, $1C, $1C, $1D
+ ;byte $1E, $1E, $1F, $1F, $20, $21, $21, $22
+ ;byte $23, $23, $24, $24, $25, $26, $26, $27
+
+; ----------------------------------------------------------------------------
+; Handler table (HATABS will point to this).
+; See the HATABS and EDITRV entries in Mapping the Atari for details.
+
+col64_vector_tab:
+ word col64_open-1 ; OPEN vector
+ word col64_close-1 ; CLOSE vector
+ word col64_getbyte-1 ; GET BYTE vector
+ word col64_putbyte-1 ; PUT BYTE vector
+ word col64_close-1 ; GET STATUS vector
+ word col64_close-1 ; SPECIAL vector
+ ;jmp col64_init ; Jump to initialization code (JMP LSB/MSB)
+ ; (Note: the OS really only ever calls the JMP init
+ ; routines for handlers in ROM, this could be empty)
+
+; ----------------------------------------------------------------------------
+; Assembly version of GRAPHICS 8+16 command.
+
+init_graphics_8:
+ lda #$08 ; graphics mode 8
+ sta ICAX2Z
+ lda #$0C ; R/W access
+ sta ICAX1Z
+ jsr open_s_dev
+
+ ; Set default colors
+ lda #DEFAULT_BG_COLOR
+ sta COLOR2
+ sta COLOR4
+ lda #DEFAULT_TEXT_COLOR
+ sta COLOR1
+
+ ; Protect ourselves from the OS
+ lda #<START_ADDRESS_1
+ sta MEMTOP
+ lda #>START_ADDRESS_1
+ sta MEMTOP+1
+ rts
+
+; ----------------------------------------------------------------------------
+; Call the OPEN vector for the S: device, using the ROM vector table
+; at $E410. The table stores address-minus-one of each routine, which is
+; meant to actually be called via the RTS instruction (standard 6502
+; technique, but confusing the first time you encounter it)
+
+open_s_dev:
+ lda s_dev_open_hi
+ pha
+ lda s_dev_open_lo
+ pha
+ rts
+
+; ----------------------------------------------------------------------------
+; Callback for the internal get-one-byte, used by the OS to implement the
+; CIO GET RECORD and GET BYTES commands. This routine takes no arguments,
+; and returns the read byte in the accumulator.
+
+; Internally, COL64 maintains a line buffer. Each time col64_getbyte is
+; called, it returns the next character in the buffer. If the buffer's
+; empty (or if the last call returned the last character), a new line
+; of input is read from the user (and the first character is returned).
+; This is not exactly how the OS E: device works: it reads keystrokes but
+; doesn't buffer them, until Return is hit; then it reads from screen
+; memory, at the current cursor line (and the line(s) before/after,
+; depending on its map of logical => physical lines). We can't do that
+; because we don't store character codes in screen memory... although
+; we *could* support insert/delete character, delete-line, and left/right
+; arrows. We don't, to save driver code size...
+
+; This code was borrowed from COL80, then big chunks of it were diked out
+; and/or optimized.
+
+col64_getbyte:
+ lda BUFCNT
+ beq get_line ; See if there are bytes left in the buffer
+
+get_next_byte: ; Yes: return next byte from the buffer
+ ldx line_buffer_index
+ lda line_buffer,x
+ dec BUFCNT
+ inc line_buffer_index
+ jmp return_success
+
+; Buffer is empty.
+; Get a line of input from the user, terminated by the Return key.
+get_line:
+ lda #$00
+ sta BUFCNT
+ sta line_buffer_index
+
+show_cursor:
+ jsr print_inv_space
+ jsr get_keystroke
+
+; code meant to deal with BREAK key, left out 'cause FujiChat disables BREAK
+; cpy #$01
+; beq keystroke_ok
+; ldy #0
+; sty line_buffer_index
+; sty BUFCNT
+
+keystroke_ok:
+ cmp #$20
+ bcc show_cursor ; ignore low ASCII
+ cmp #EOL
+ beq return_key_hit
+
+check_backs_key:
+ cmp #$7E
+ beq backs_key_hit
+
+;check_clear_key: ; don't bother, don't need
+ ; (if we did want this, it should check delete-line instead!)
+ ;;cmp #$7D
+ ;;beq clear_key_hit
+
+normal_key_hit:
+ ldx BUFCNT
+ bmi show_cursor
+
+buffer_character:
+ sta line_buffer,x
+ jsr col64_putbyte
+ inc BUFCNT
+ bne show_cursor
+
+return_key_hit:
+ jsr print_space
+ lda #EOL
+ ldx BUFCNT
+ sta line_buffer,x
+ inc BUFCNT
+ jsr col64_putbyte
+ bne get_next_byte ; col64_putbyte always clears Z flag!
+
+;;clear_key_hit:
+; jsr clear_screen ; if we implemented it...
+;; lda #$00
+;; sta line_buffer_index
+;; sta BUFCNT
+;; beq get_line
+
+backs_key_hit:
+ jsr print_space
+ lda BUFCNT
+ beq backs_key_done
+ dec COLCRS
+ lda COLCRS
+ clc
+ adc #$01
+ cmp LMARGN
+ bne backs_same_line
+ lda RMARGN
+ sta COLCRS
+ dec ROWCRS
+
+backs_same_line:
+ dec BUFCNT
+
+backs_key_done:
+ jmp show_cursor
+
+; ----------------------------------------------------------------------------
+; Print a space or inverse space character at the current cursor position.
+; Does not update the cursor position.
+
+print_inv_space:
+ lda #INVERTED_MASK
+ byte $2C
+
+print_space:
+ lda #$00
+ sta inverse_mask
+ lda #$00
+ sta TMPCHR
+ jmp render_glyph
+
+; ----------------------------------------------------------------------------
+; Get a keystroke (blocking). Just calls the OS K: get-one-byte routine
+; (call by pushing address-minus-one then doing an RTS)
+
+get_keystroke:
+ lda k_dev_get_hi
+ pha
+ lda k_dev_get_lo
+ pha
+ ;rts ; fall through to return_success
+
+
+; ----------------------------------------------------------------------------
+; Unimplemented CIO callbacks here. Also various other routines jump here
+; to return success to the caller.
+
+col64_close:
+return_success:
+ ldy #$01
+ rts
+
+; ----------------------------------------------------------------------------
+; CIO OPEN command callback
+
+col64_open:
+ jsr init_graphics_8
+ lda #$00
+ sta ROWCRS
+ sta COLCRS
+ sta BUFCNT
+ sta LMARGN
+ lda #DEFAULT_RMARGN
+ sta RMARGN
+ rts
+
+; ----------------------------------------------------------------------------
+; CIO PUT BYTE command callback
+; The byte to put is passed to us in the accumulator.
+
+col64_putbyte:
+ ; EOL (decimal 155)?
+ cmp #EOL
+;;; bne check_clear
+ bne regular_char
+ lda RMARGN
+ sta COLCRS
+ jmp skip_write
+
+;;;check_clear:
+;;; ; save memory by not including clear_screen
+;;; ; (also, this lets us print the } character)
+;;; ; Clear (decimal 125)?
+;;; cmp #$7D
+;;; bne regular_char
+;;; jmp clear_screen
+;;; .endif
+;;;
+
+; See if this is an inverse video char (code >= 128)
+regular_char:
+ tax
+ bpl not_inverse
+ lda #INVERTED_MASK
+ .byte $2C ; aka BIT abs, skip the LDA
+not_inverse:
+ lda #$00
+ sta inverse_mask
+
+ txa
+ and #$7F
+ sec
+ sbc #$20 ; subtract $20 because we only handle codes $20 to $7F
+ bcs not_low_ascii
+ jmp return_success ; ignore any chr codes $00-$1F or $80-$9F
+
+not_low_ascii:
+ sta TMPCHR
+
+ lda DINDEX ; OS stores current graphics mode here
+ cmp #$08
+ beq graphics_ok
+ ; If we're not in GRAPHICS 8 mode, reinitialize ourselves
+ jsr col64_open
+
+graphics_ok:
+ jsr render_glyph
+
+skip_write:
+ ; Move the cursor 1 space to the right. This will
+ ; advance us to the next line if we're at the margin,
+ ; and scroll the screen if needed
+ jsr advance_cursor
+
+; Could implement SSFLAG logic here
+;check_ssflag:
+ ; The OS keyboard interrupt handler will toggle SSFLAG (start/stop fla
+ ; any time the user presses ctrl-1
+ ;lda SSFLAG
+ ;bne check_ssflag
+ jmp return_success
+
+; ----------------------------------------------------------------------------
+; Call the routines that actually print the character.
+; render_glyph prints the character in TMPCHR at the current
+; COLCRS and ROWCRS, and does NOT advance the cursor.
+; TMPCHR should already have bit 7 stripped; render_glyph will
+; use inverse_mask, so the caller should have set that up as well.
+
+; Note: The 4 subroutines were only ever called from render_glyph,
+; so to save a tiny bit of time and space, they're now inline code.
+
+render_glyph:
+ ;jsr setup_mask
+ ;jsr setup_screen_ptr
+ ;jsr setup_font_index
+ ;jmp write_font_data
+
+; ----------------------------------------------------------------------------
+; mask is used to avoid overwriting pixels outside the character cell
+; we're currently writing. Since 5 pixel wide cells don't align on byte
+; boundaries in screen RAM, we have to read/modify/write 2 bytes, and
+; the mask also has to be 2 bytes wide.
+; Also we set up shift_amount here.
+
+setup_mask:
+ lda COLCRS
+ and #$07
+ tax
+ lda mask_lo_tab,x
+ sta mask_lo
+ lda mask_hi_tab,x
+ sta mask_hi
+ lda shift_amount_tab,x
+ sta shift_amount
+ ;rts
+
+
+; ----------------------------------------------------------------------------
+; Make (screen_ptr_lo) point to the first byte of screen RAM on the top line
+; of the current char cell. Assumes COLCRS/ROWCRS are never out of range!
+setup_screen_ptr:
+ ; first the row... table lookup quicker than mult by 240
+ ldx ROWCRS ; +3 = 3
+ clc ; +2 = 5
+ lda SAVMSC ; +3 = 8
+ adc line_addr_tab_lo,x ; +4 = 12
+ sta screen_ptr_lo ; +3 = 15
+ lda SAVMSC+1 ; +3 = 18
+ adc line_addr_tab_hi,x ; +4 = 22
+ sta screen_ptr_hi ; +3 = 25
+
+ ; now do the column. column_byte_tab is only a half-table, so do lookup
+ ; on bits 0-4 of COLCRS, then add 20 decimal if bit 5 of COLCRS was set.
+ lda COLCRS
+ tay
+ and #$1F
+ tax
+ lda column_byte_tab,x
+ cpy #$20
+ bcc ssp_noadd
+ adc #$13 ; +1 because C set = 20 dec
+
+ssp_noadd:
+ clc
+ adc screen_ptr_lo
+ sta screen_ptr_lo
+ lda #0
+ adc screen_ptr_hi
+ sta screen_ptr_hi
+
+ ;rts
+
+; ----------------------------------------------------------------------------
+; Set up font_index to point to the font_data bitmap for the character in
+; TMPCHR. Also sets lo_nybble_flag to let the caller know whether the
+; bitmap is in the upper or lower 4 bits of the bytes pointed to.
+
+; Calculation is:
+; lo_nybble_flag = (TMPCHR & 1) ? $FF : $00;
+; font_index = (TMPCHR >> 1) * 5;
+
+setup_font_index:
+ lda #$00
+ sta lo_nybble_flag
+ lda TMPCHR
+ lsr ; a = (TMPCHR >> 1)
+ tay ; y = a
+ bcc font_hi_nybble
+ dec lo_nybble_flag ; = $FF
+
+font_hi_nybble:
+ clc
+ asl ; a *= 2
+ asl ; a *= 2
+ sta font_index
+ tya
+ adc font_index
+ sta font_index
+
+ ; rts
+
+
+; ----------------------------------------------------------------------------
+; True descender support: we've got a hard-coded list of 5 characters
+; (g j p q y) that have them. All the descender graphics are stored in the
+; bottom nybble of the last glyph in the font, which means we can only have
+; 5 characters that have descenders.
+; TODO: tighten up this code some (faster/smaller)
+
+ lda TMPCHR
+ ldx #$FF
+
+ cmp #'g-$20
+ bne chk_j
+ ldx #DESCENDERS-1
+chk_j:
+ cmp #'j-$20
+ bne chk_p
+ ldx #DESCENDERS
+chk_p:
+ cmp #'p-$20
+ bne chk_q
+ ldx #DESCENDERS+1
+chk_q:
+ cmp #'q-$20
+ bne chk_y
+ ldx #DESCENDERS+2
+chk_y:
+ cmp #'y-$20
+ bne not_y
+ ldx #DESCENDERS+3
+
+not_y:
+ stx descender
+
+; ----------------------------------------------------------------------------
+; When write_font_data is called, all this stuff must be set up:
+; - font_index is the 1-byte index into font_data where the current glyph is
+; - lo_nybble_flag is 0 for high nybble of glyph data, $FF for low
+; - mask_lo/hi is our 16-bit pixel mask (1's are "leave original data")
+; - shift_amount is # of times to shift glyph data right
+; - screen_ptr_lo/hi points to the 1st byte on the top line
+; - inverse_mask is 0 for normal or INVERTED_MASK for inverse
+; - descender is the offset *minus one* of the byte holding the bottom 4
+; pixels in the 4x6 character. Most of the time this will be $FF,
+; AKA the the offset from font_data of the first byte of the space glyph
+; (minus one), which has 0000 in its top nybble. The rest of the time,
+; the descenders are taken from the bottom nybble of the last character
+; glyph (which would be the unprintable code $7F). The logic that does
+; the descenders is hard-coded to use the top nybble for $FF and the
+; bottom nybble for anything else.
+
+; Loop 5 times, each time thru the loop:
+; - extract 4-bit glyph data, store in glyph_data_lo
+; - apply inverse_mask
+; - shift right shift_amount times
+; ...write data...
+; - add 40 to 16-bit screen_ptr_lo/hi (to get to next line)
+; ...then one more loop with font_index and lo_nybble_flag set
+; to a byte in the space glyph, to handle the bottom row (which
+; is always 0 for normal or all 1's for inverse)
+
+write_font_data:
+ ldx #$05 ; outer loop counter, aye
+
+wfont_line_loop:
+ lda #$00
+ sta glyph_data_hi
+
+ ldy font_index
+ lda font_data,y ; note: entire font must fit in one page!
+
+ bit lo_nybble_flag
+ beq use_hi_nybble
+
+ asl ; the pixels we want are in the low nybble of the font data byte.
+ asl ; shift them up to the top nybble
+ asl
+ asl
+
+use_hi_nybble: ; 4-bit glyph data now in hi nybble
+ and #$F0
+ eor inverse_mask
+ sta glyph_data_lo
+
+ ldy shift_amount
+ beq wfont_no_shift
+
+wfont_shift_loop: ; right-shift 16-bit glyph data shift_amount times
+ lsr glyph_data_lo
+ ror glyph_data_hi
+ dey
+ bne wfont_shift_loop
+
+wfont_no_shift: ; Y always zero when we get here
+ lda mask_lo
+ and (screen_ptr_lo),y
+ ora glyph_data_lo
+ sta (screen_ptr_lo),y
+
+ lda mask_hi
+ beq wfont_skip_hi ; don't bother with 2nd screen byte if we don't need to
+ iny
+ and (screen_ptr_lo),y
+ ora glyph_data_hi
+ sta (screen_ptr_lo),y
+
+wfont_skip_hi:
+ dex
+ bmi wfont_done
+ bne wfont_not_bottom
+
+ ;stx font_index
+ ;stx lo_nybble_flag
+
+; X always 0 here: for last line, use the descender (if there's no
+; descender for this char, that's $FF. font_index will get inc'ed,
+; meaning non-decender chars use the first byte of the space glyph
+; as their "descender")
+ lda descender
+ sta font_index
+ cmp #$FF
+ beq wfont_not_bottom
+ sta lo_nybble_flag
+
+wfont_not_bottom:
+ lda #$28 ; add 40 bytes to point to next line of screen RAM
+ clc
+ adc screen_ptr_lo
+ sta screen_ptr_lo
+ bcc wfont_noinc
+ inc screen_ptr_hi
+
+wfont_noinc:
+ inc font_index
+ bne wfont_line_loop ; branch always
+
+wfont_done:
+ rts
+
+; ----------------------------------------------------------------------------
+; Not the fastest scroller in the west... TODO: make faster :)
+
+; lda_operand points to line N (minus one byte)
+; sta_operand points to line N+1 (minus one byte)
+; Y ranges 240 to 1 in the loop, hence the -1 byte
+; CAUTION: Self-modifying code! Proceed with caution.
+
+; This version gives us overall driver speed almost 20% faster
+; than the original scroll_screen (last commented-out one below)
+; Also just scrolling 250 times is slightly faster than COL80
+; (1505 jiffies; setting CRITIC saves 48 jiffies)
+; (makes it 17% the speed of the OS E: driver, where COL80 is 15%)
+; Note that E80 is slightly over twice as fast at this as the OS!
+
+; Note about performance where scrolling is *not* concerned:
+; Printing 914 non-control characters on a freshly-cleared screen:
+; OS E: - 172 jiffies (subtract 12 = 160 jiffies if cursor disabled)
+; E80 - 168 jiffies (about same as OS E:)
+; COL80 - 116 jiffies (yes, it's fastest!)
+; CON64 from SDX 4.41 - 227 jiffies first time I tried, crashed next time!
+; COL64 - 142 jiffies (still faster than OS E:)
+
+scroll_screen:
+; lda SDMCTL
+; pha
+; lda #0
+; sta SDMCTL
+
+; lda CRITIC
+; pha
+; lda #1
+; sta CRITIC
+
+ lda SAVMSC
+ sec
+ sbc #1
+ sta lda_operand
+ lda SAVMSC+1
+ sbc #0
+ sta lda_operand+1
+ ldx #LAST_ROW
+
+scroll_line_loop:
+ ldy #$F0
+
+ lda lda_operand+1
+ sta sta_operand+1
+ lda lda_operand
+ sta sta_operand
+ clc
+ adc #$F0
+ sta lda_operand
+ bcc ss_noinc
+ inc lda_operand+1
+ss_noinc:
+
+scroll_byte_loop:
+lda_operand = *+1
+ lda 0,y
+sta_operand = *+1
+ sta 0,y
+ dey
+ bne scroll_byte_loop
+ dex
+ bne scroll_line_loop
+
+scroll_blank:
+ lda lda_operand
+ sta sta2_operand
+ lda lda_operand+1
+ sta sta2_operand+1
+ lda #0
+ ldy #$F0
+sblank_loop:
+sta2_operand = *+1
+ sta 0,y
+ dey
+ bne sblank_loop
+
+; pla
+; sta SDMCTL
+; pla
+; sta CRITIC
+ rts
+
+;; This version is faster and fully functional
+;; (overall driver speed is 10% faster than with the
+;; one below)
+; glyph_data_lo points to line N (minus one byte)
+; screen_ptr_lo points to line N+1 (minus one byte)
+; Y ranges 240 to 1 in the loop, hence the -1 byte
+
+;;scroll_screen:
+;; lda SAVMSC
+;; sec
+;; sbc #1
+;; sta screen_ptr_lo
+;; lda SAVMSC+1
+;; sbc #0
+;; sta screen_ptr_hi
+;; ldx #LAST_ROW
+;;
+;;scroll_line_loop:
+;; ldy #$F0
+;;
+;; lda screen_ptr_hi
+;; sta glyph_data_hi
+;; lda screen_ptr_lo
+;; sta glyph_data_lo
+;; clc
+;; adc #$F0
+;; sta screen_ptr_lo
+;; bcc ss_noinc
+;; inc screen_ptr_hi
+;;ss_noinc:
+;;
+;;scroll_byte_loop:
+;; lda (screen_ptr_lo),y
+;; sta (glyph_data_lo),y
+;; dey
+;; bne scroll_byte_loop
+;; dex
+;; bne scroll_line_loop
+;;
+;;scroll_blank:
+;; lda #0
+;; ldy #$F0
+;;sblank_loop:
+;; sta (screen_ptr_lo),y
+;; dey
+;; bne sblank_loop
+;;
+;; rts
+
+; Clock cycle timings:
+; 1792080 CPU cycles per second (or is it 1789773?)
+; 29868 per jiffy on NTSC (1/60 sec)
+; DL = 174 bytes @ 1 cycle each
+; Screen RAM = 7680 bytes @ 1 ea
+; Refresh = 262 * 9 = 2358
+; so ANTIC steals 10212 (34.2%) cycles, leaves 19656 (65.8%)
+; Of that time, the OS steals some doing VBLANK processing.
+; It may be that I can set CRITIC here and get a little of
+; that back (depends on what, if anything, that does to
+; the RS232 driver and/or custom keybuffer stuff in FujiChat).
+
+; Now if I could actually do a 100% unrolled scroller, simply
+; LDA blah:STA blah-1 7680 times, with NMI/VBI/ANTIC disabled,
+; that would be 4+4=8 cycles times 7680 = 61440, or 3.12 frames
+; (or 0.052 sec, call it 1/20 sec). Obviously can't do it that way.
+
+; Did some tests of overall performance (not just scrolling: print
+; 24 lines of 35 chars, then 24 newlines, repeat in a loop 10x)
+; Turning off ANTIC DMA seems to save 25% time. Setting CRITIC only
+; saves 3% or so. Disabling IRQs/NMIs entirely is probably not an
+; option.
+
+;; old (slower, but working) version:
+;; scroll_screen:
+;; lda #0 ; +2 = 2
+;; sta COLCRS ; +3 = 5
+;; sta ROWCRS ; +3 = 8
+;; jsr setup_screen_ptr ; +6 = 14, +54 = 68
+;;
+;; scroll_line_loop:
+;; lda screen_ptr_lo ; +3 = 3
+;; sta glyph_data_lo ; +3 = 6
+;; lda screen_ptr_hi ; +3 = 12
+;; sta glyph_data_hi ; +3 = 15
+;; ldx ROWCRS ; +3 = 18
+;; cpx #LAST_ROW ; +2 = 20
+;; beq scroll_blank ; +2 = 22 (+1 more last time thru)
+;; inx ; +2 = 24
+;; stx ROWCRS ; +3 = 27
+;; jsr setup_screen_ptr ; +6+54 = 87
+;; ldy #0 ; +2 = 89
+;; ; times 31 is 2759, +1 = 2760
+;;
+;; scroll_byte_loop:
+;; lda (screen_ptr_lo),y ; +5 = 5
+;; sta (glyph_data_lo),y ; +6 = 11
+;; iny ; +2 = 13
+;; cpy #$F0 ; +2 = 15
+;; bne scroll_byte_loop ; +3 = 18 (-1 last time thru)
+;; ; ...times 31 times 240 - 1 = 133919 (!)
+;; beq scroll_line_loop ; +3*31-1 (92)
+;;
+;; scroll_blank:
+;; jsr setup_screen_ptr ; +6+54 = 60
+;; ldy #0 ; +2 = 62
+;; tya ; +2 = 64
+;; sblank_loop:
+;; sta (screen_ptr_lo),y ; +6 = 6
+;; iny ; +2 = 8
+;; cpy #$F0 ; +2 = 10
+;; bne sblank_loop ; +3 = 13 (-1 last time)
+;; ; times 240, minus 1 = 3119
+;;
+;; rts ; +6
+;;
+;; Total routine time is 68 + 2760 + 133919 + 92 + 64 + 3119 + 6 = 140028
+;; Divide by free cyc/frame: 140028/19656 = 7.12 frames, or 0.11 sec,
+;; not counting VBLANK overhead. 95% of the time is of course in the
+;; inner loop. Every cycle saved in the inner loop is worth about
+;; 5% of the runtime! So switching from incrementing to decrementing
+;; Y will save 10% of the time (from not having the CPY). Using self-
+;; modifying code for the lda/sta saves 2 more cycles (10% more), but
+;; adds a small bit of overhead in the outer loop.
+;; The scroll_blank loop is only 2.2% of the total time. Every cycle
+;; shaved off its loop is worth only 1/3 of a percent of the total
+;; time (switching to dey is worth 2/3 of 1%).
+;; Replace jsr setup_screen_ptr in scroll_line_loop with loading from
+;; the tables directly will save approx. 35 cycles per outer loop,
+;; or only about 0.8%.
+;; So total savings is 20% + 0.6% + 0.8% = 21.4%, meaning real time
+;; drops to approx 0.085 sec, or approx 5.5 NTSC frames (another way
+;; to look at it: 11.75 scrolled lines/sec instead of the original 9)
+;; Yet another way: 2 1/3 seconds to scroll the whole screen, vs
+;; the original 3 1/2. Still abysmal.
+
+;; One possibility would be to borrow a page from the ACE-80 book and
+;; update LMSes within the DL. This would bloat the display list by
+;; 64 bytes (not so bad). We'd basically treat screen RAM as a circular
+;; buffer of 32 lines. Every scroll, update the LMS operands to point
+;; to the next line-buffer, and whichever buffer is the last visible
+;; line needs to be blanked. Got to see how much code this will add
+;; (possibly the routine that does this might not be longer than the
+;; scroll_screen I've been using). ACE-80 (or anyway E80) uses way
+;; more screen RAM than it looks like it needs, plus DLIs.
+
+; ----------------------------------------------------------------------------
+; Move the cursor one space to the right (to the next line if at the margin,
+; and scroll screen if on the last row)
+
+advance_cursor:
+ inc COLCRS
+ lda RMARGN
+ cmp COLCRS
+ bcs same_line
+ lda LMARGN
+ sta COLCRS
+ lda ROWCRS
+ cmp #LAST_ROW
+ bcc no_scroll
+ jsr scroll_screen
+ ; Move to last row after scrolling
+ lda #LAST_ROW-1
+ sta ROWCRS
+
+no_scroll:
+ inc ROWCRS
+
+same_line:
+ rts
+
+END_ADDR_1 = *-1
+
+
+; ----------------------------------------------------------------------------
+; Initialization. If we don't want the handler to survive a warmstart, we
+; can load this bit into e.g. the cassette buffer (throw away after running)
+
+START_ADDRESS_2 = CASBUF
+
+; XEX segment header for throwaway init code
+ rorg START_ADDRESS_2-4
+ word START_ADDRESS_2
+ word END_ADDR_2
+
+col64_init:
+ ldy #$00
+
+next_hatab_slot:
+ lda HATABS,y
+ beq register_x_handler
+ iny
+ iny
+ iny
+ cpy #$20
+ bcc next_hatab_slot
+ jmp return_success
+
+register_x_handler:
+ lda #$58
+ sta HATABS,y
+ lda #<col64_vector_tab
+ iny
+ sta HATABS,y
+ lda #>col64_vector_tab
+ iny
+ sta HATABS,y
+ jmp return_success
+
+main_entry_point:
+ jsr col64_init
+ lda #$0C
+ sta ICCOM
+ ldx #$00
+ jsr CIOV
+ lda #$58
+ sta font_index
+ lda #$03
+ sta ICCOM
+ lda #font_index
+ sta ICBAL
+ lda #$00
+ sta ICBAH
+ ldx #$00
+ jsr CIOV
+ ldy #$07
+ lda #<col64_vector_tab
+ sta HATABS,y
+ lda #>col64_vector_tab
+ iny
+ sta HATABS,y
+no_e_handler:
+ lda #<START_ADDRESS_1
+ sta MEMTOP
+ lda #>START_ADDRESS_1
+ sta MEMTOP+1
+ jmp return_success
+
+END_ADDR_2 = *-1
+
+; XEX segment (run address)
+ word INITAD
+ word INITAD+1
+ word main_entry_point
+
+; That's all, folks...
+
+; Rest of file is me rambling & meandering, ignore or not as you choose
+
+; Possible improvements, some of which may apply to this driver only,
+; some of which may apply to a (to be written) 40-column renderer.
+; Redb3ard has designed really nice 8x8 normal, bold, italic fonts,
+; including a bunch of Unicode normal characters... the 40-column
+; driver would include UTF-8 support. Of course there's not enough
+; RAM for an IRC client, TCP/IP stack, screen/DL memory, driver,
+; UTF-8 tables, and 3 or 4 fonts... will have to wait until after
+; the 1.0 FujiChat release (my roadmap for 1.0 is that everything
+; needs to work on a 48K unmodded 800; 2.0 will have new features
+; that may only work on an XL or even require 130XE banks, though
+; it will still be as functional as 1.0, on an 800).
+
+; True descenders and 5-bit-wide characters.
+
+; For descenders, could simply leave the top row of pixels blank on
+; the screen, and draw the 5 rows of character in the bottom 5 of
+; the 6-scanline block. They'd possibly touch the character on the
+; next line...
+
+; 5-bit-wide characters should be used sparingly: only M W m w T
+; and maybe Y V v # need them. The "extra" bit could go on the left,
+; and just be a copy of the rightmost bit, since these characters
+; are symmetrical... but these would often touch the character on
+; the left. Capital letters, it's less of a big deal in normal English
+; text, since a capital letter should be preceded by a space (or at
+; least punctuation), and it won't touch the character on the right
+; unless it's another 5-bit-wide one (few words in English are going
+; to have that problem; maybe the name AMY in all caps). Unfortunately
+; I can't think of a good way to encode the bits of information that
+; say a character needs the extra pixel (or a descender either) other
+; than a hard-coded set of compares against specific char codes, or
+; else a loop over a table of them. Either way there's a loss of
+; performance: most characters will fail all the compares...
+; It'd be possible to do a 5x5 font, or even 5x6, but 5 bits wide
+; means we can't pack the pixel data 2 rows per byte (so the
+; font won't fit in a page any more, plus we have to use (zp),y
+; or something to access it...)
+
+; Multiple font support. Since it's an IRC-specific driver, could just
+; have _putbyte directly interpret the IRC protocol formatting codes,
+; render e.g. bold as inverse, italic as underline if I implement it,
+; or else do up a separate italic font (if it's possible to make one
+; look good in 4x5). _putbyte could at least strip out the codes it
+; can't render (e.g. color).
+
+; I've thought of doing underline (either a separate mode, or instead
+; of inverse video), but a lot of the glyphs will look like crap with
+; the underline, because there's no room for spacing: the underline
+; will touch the bottom pixels of most characters (and overwrite the
+; descenders if we add true descender support...)
+
+; Obviously, making it a fully-functional E: replacement would be nice.
+; I'm not doing this because I'm only wanting to use the driver for
+; text-only cc65 programs (specifically FujiChat), though possibly
+; I'll come back to col64 and do a proper version later.
+
+; Also nice: user-adjustable number of rows. Most peoples' monitors can
+; display something above 200 scanlines (particularly if they're in PAL
+; countries). As-is, we're using 192 scanlines to get 32 rows (of 6 lines
+; each). Most people could easily display 34 rows (204 scanlines), and
+; not a few could display 35 (210), particularly if the blanking
+; instructions at the start of the display list are user-adjustable too
+; (to move the picture up or down). Memory usage for video RAM would
+; grow by 240 byte per row of characters, and of course we'd need code
+; to set up the custom display list (which would be longer than a
+; normal one for GR.8). Probably would put a limit of 36 or 40 rows
+; since the various tables are fixed-size...
+
+; If there were RAM enough for it, or if we decide to use XE extra
+; banks (or XL/XE under-OS RAM), could have _putbyte also store
+; every output character in a buffer, for FujiChat to use as
+; scrollback/log buffer (or any other program to use as it sees
+; fit, of course).
+
+; User-loadable font isn't a bad idea: the init code can look for a
+; file D:COL64.FNT and load it into font_data if found.
+
+; Could implement standard ASCII backspace/tab/linefeed/CR/etc codes,
+; using low ASCII codes. This would be suitable for a telnet or terminal
+; client (not needed for IRC)
+
+; I really would like to do auto-relocation. Program could load itself
+; wherever, and relocate itself (using a table of offsets, for absolute
+; addresses within the program) to either MEMLO or MEMTOP. This would
+; mean more init code only.
+
+; It'd be nice to speed up scrolling. One dumb trick would be to use
+; self-modifying code: instead of (zp),y addressing, use abs,y
+; in the inner loop, and the outer loop modifies the operands in
+; the inner. Would mean the code can't be burned to ROM, but who
+; was planning to do that anyway? Also simply moving more than one
+; chunk per outer-loop iteration would be a small speedup, and so
+; would moving 256 bytes per, instead of 240.
+; Since the inner loop does lda (zp),y [5+cyc] and sta (zp),y [6cyc]
+; 7440 times, replacing them with lda abs,y [4+cyc] and sta abs,y
+; [5cyc] should save 7440*2 = almost 15K cycles.
+; which may not be noticeable... Unrolling the loop is even less of a
+; gain: the outer loop only runs 32 times. Could set CRITIC during the
+; move (not sure that helps much). No matter how you slice it,
+; moving 8K on a 6502 is *slow*.
+
+; One slightly cool idea would be to do a proper OPEN of channel #6
+; to S:, like the BASIC GR. command does, instead of the "shortcut"
+; using ZIOCB and calling the S: open routine directly. Doing this
+; would allow PLOT, DRAWTO, and XIO 18 (fill).
diff --git a/src/col64/cruft/col64.dasm.works b/src/col64/cruft/col64.dasm.works
new file mode 100644
index 0000000..1e02921
--- /dev/null
+++ b/src/col64/cruft/col64.dasm.works
@@ -0,0 +1,731 @@
+
+; ----------------------------------------------------------------------------
+; 64x32 software text driver
+; Uses 4x5 font in 5x6 character cells
+; Based on disassembled COL80 driver
+
+; This driver is missing quite a few things a full E: driver should have:
+
+; - No support for cursor controls, insert/delete, or even clear screen
+; (instead the control-codes are printed as normal characters, if they're
+; above 31 decimal)
+
+; - No support for low ASCII at all: any attempt to input or print a character
+; in the range 0-31 decimal is just ignored (this includes the arrow keys)
+
+; - Does not attempt to survive a warmstart
+
+; - Will fail disastrously if an application sets COLCRS/ROWCRS to any
+; out-of-range values
+
+; - Only displays the cursor during get-byte operations
+
+; - Backspace key is supported during get-byte, but printing a backspace
+; with put-byte prints a tilde instead
+
+; On the other hand, this driver is tiny, and plays nice with cc65's stdio
+; support (though NOT conio!)
+
+ processor 6502 ; DASM-specific
+
+; ----------------------------------------------------------------------------
+ include equates.inc
+s_dev_open_lo = $E410 ; (not named in OS sources)
+s_dev_open_hi = $E411 ; ""
+k_dev_get_lo = $E424 ; ""
+k_dev_get_hi = $E425 ; ""
+
+; ----------------------------------------------------------------------------
+; Constants
+
+LAST_ROW = $1F
+EOL = $9B
+INVERTED_MASK = $F8
+
+; ----------------------------------------------------------------------------
+; Defaults
+
+DEFAULT_TEXT_COLOR = $00
+DEFAULT_BG_COLOR = $08
+;DEFAULT_LMARGN = $00 ; not used
+DEFAULT_RMARGN = $3F
+
+; ----------------------------------------------------------------------------
+; ZP storage
+; Reuse some of the E:/S: devices' storage
+; These all get recalculated on col64_putbyte entry,
+; so it's OK to mix with GR.8 PLOT/DRAWTO stuff
+
+ seg.u "data"
+ org $5A ; aka OLDROW
+mask_lo ds 1
+mask_hi ds 1
+screen_ptr_lo ds 1
+screen_ptr_hi ds 1
+font_index ds 1
+shift_amount ds 1
+line_count ds 1
+glyph_data_lo ds 1
+glyph_data_hi ds 1
+
+; ----------------------------------------------------------------------------
+; Non-ZP storage (cassette buffer for now)
+
+ org CASBUF
+lo_nybble_flag ds 1
+inverse_mask ds 1
+line_buffer_index ds 1
+line_buffer ds $80
+
+ seg "code"
+; ----------------------------------------------------------------------------
+; XEX segment header
+START_ADDRESS_1 = $9A00
+ org START_ADDRESS_1-6
+
+ word $FFFF
+ word START_ADDRESS_1
+ word END_ADDR_1
+
+; ----------------------------------------------------------------------------
+; Font data should be aligned on a page boundary
+; (for speed; still works unaligned). Each 5 bytes stores 2 glyphs
+; side-by-side. When rendering into 5x6 cells, the bottom line and
+; the left column are set to all 0, so the glyphs can take up the
+; entire 4x5 space.
+; Only character codes 32 through 127 are supported; this is 96
+; characters. At 2 glyphs per 5 bytes, that's 96/2*5=240 bytes,
+; which means the whole font fits into one page and can be
+; accessed with X or Y indexed mode rather than (indirect),Y.
+
+font_data:
+ include font4x5.inc
+
+; ----------------------------------------------------------------------------
+; Mask tables, used by setup_mask. Indexed by (COLCRS % 8), since they
+; would repeat every 8 bytes anyway.
+
+mask_lo_tab:
+ byte $07, $F8, $C1, $FE, $F0, $83, $FC, $E0
+
+; In mask_hi_tab, $00 is never a valid mask, while $FF means "don't touch any
+; bits in 2nd byte". As a minor optimization, $00 appears in the table in
+; place of $FF. This allows us to just test the Z flag after loading the mask
+; hi byte, instead of needing to compare against $FF.
+
+mask_hi_tab:
+ byte $00, $3F, $00, $0F, $7F, $00, $1F, $00
+
+; ----------------------------------------------------------------------------
+; Indexed by COLCRS%8, how many bits to shift the font data right
+; The mask_*_tab stuff above could be calculated at runtime from this,
+; the tables are only there for speed.
+shift_amount_tab:
+ byte $00, $05, $02, $07, $04, $01, $06, $03
+
+; ----------------------------------------------------------------------------
+; Line address tables, used by setup_screen_ptr.
+
+line_addr_tab_hi:
+ byte $00, $00, $01, $02, $03, $04, $05, $06
+ byte $07, $08, $09, $0a, $0b, $0c, $0d, $0e
+ byte $0f, $0f, $10, $11, $12, $13, $14, $15
+ byte $16, $17, $18, $19, $1a, $1b, $1c, $1d
+
+line_addr_tab_lo:
+ byte $00, $f0, $e0, $d0, $c0, $b0, $a0, $90
+ byte $80, $70, $60, $50, $40, $30, $20, $10
+ byte $00, $f0, $e0, $d0, $c0, $b0, $a0, $90
+ byte $80, $70, $60, $50, $40, $30, $20, $10
+
+; ----------------------------------------------------------------------------
+; Byte offset within scanline, indexed by COLCRS value
+; Used by setup_screen_ptr
+
+column_byte_tab:
+ byte $00, $00, $01, $01, $02, $03, $03, $04
+ byte $05, $05, $06, $06, $07, $08, $08, $09
+ byte $0A, $0A, $0B, $0B, $0C, $0D, $0D, $0E
+ byte $0F, $0F, $10, $10, $11, $12, $12, $13
+ byte $14, $14, $15, $15, $16, $17, $17, $18
+ byte $19, $19, $1A, $1A, $1B, $1C, $1C, $1D
+ byte $1E, $1E, $1F, $1F, $20, $21, $21, $22
+ byte $23, $23, $24, $24, $25, $26, $26, $27
+
+; ----------------------------------------------------------------------------
+; Handler table (HATABS will point to this).
+; See the HATABS and EDITRV entries in Mapping the Atari for details.
+
+col64_vector_tab:
+ word col64_open-1 ; OPEN vector
+ word col64_close-1 ; CLOSE vector
+ word col64_getbyte-1 ; GET BYTE vector
+ word col64_putbyte-1 ; PUT BYTE vector
+ word col64_close-1 ; GET STATUS vector
+ word col64_close-1 ; SPECIAL vector
+ jmp col64_init ; Jump to initialization code (JMP LSB/MSB)
+
+; ----------------------------------------------------------------------------
+; Assembly version of GRAPHICS 8+16 command.
+
+init_graphics_8:
+ lda #$08 ; graphics mode 8
+ sta ICAX2Z
+ lda #$0C ; R/W access
+ sta ICAX1Z
+ jsr open_s_dev
+
+ ; Set default colors
+ lda #DEFAULT_BG_COLOR
+ sta COLOR2
+ sta COLOR4
+ lda #DEFAULT_TEXT_COLOR
+ sta COLOR1
+
+ ; Protect ourselves from the OS
+ lda #<START_ADDRESS_1
+ sta MEMTOP
+ lda #>START_ADDRESS_1
+ sta MEMTOP+1
+ rts
+
+; ----------------------------------------------------------------------------
+; Call the OPEN vector for the S: device, using the ROM vector table
+; at $E410. The table stores address-minus-one of each routine, which is
+; meant to actually be called via the RTS instruction (standard 6502
+; technique, but confusing the first time you encounter it)
+
+open_s_dev:
+ lda s_dev_open_hi
+ pha
+ lda s_dev_open_lo
+ pha
+ rts
+
+; ----------------------------------------------------------------------------
+; Callback for the internal get-one-byte, used by the OS to implement the
+; CIO GET RECORD and GET BYTES commands. This routine takes no arguments,
+; and returns the read byte in the accumulator.
+
+; Internally, COL64 maintains a line buffer. Each time col64_getbyte is
+; called, it returns the next character in the buffer. If the buffer's
+; empty (or if the last call returned the last character), a new line
+; of input is read from the user (and the first character is returned).
+; This is exactly how the OS E: device works.
+
+col64_getbyte:
+ lda BUFCNT
+ beq get_line
+
+get_next_byte:
+ ldx line_buffer_index
+ lda line_buffer,x
+ dec BUFCNT
+ inc line_buffer_index
+ jmp return_success
+
+; ----------------------------------------------------------------------------
+; Get a line of input from the user, terminated by the Return key.
+
+get_line:
+ lda #$00
+ sta BUFCNT
+ sta line_buffer_index
+
+show_cursor:
+ lda #$00
+ sta TMPCHR
+ lda #INVERTED_MASK
+ sta inverse_mask
+ jsr render_glyph
+ jsr get_keystroke
+ cpy #$01
+ beq keystroke_ok
+ dey ; yes, we really care about 1-byte optimizations
+ sty line_buffer_index
+ sty BUFCNT
+
+keystroke_ok:
+ cmp #$20
+ bcc show_cursor ; ignore low ASCII
+ cmp #EOL
+ bne check_backs_key
+ jmp return_key_hit
+
+check_backs_key:
+ cmp #$7E
+ bne check_clear_key
+ jmp backs_key_hit
+
+check_clear_key:
+ cmp #$7D
+ bne normal_key_hit
+ jmp clear_key_hit
+
+normal_key_hit:
+ ldx BUFCNT
+ bpl buffer_character
+; jmp beep ; if we implemented it...
+ jmp show_cursor
+
+buffer_character:
+ sta line_buffer,x
+ jsr col64_putbyte
+ inc BUFCNT
+ jmp show_cursor
+
+return_key_hit:
+ jsr print_space
+ lda #EOL
+ ldx BUFCNT
+ sta line_buffer,x
+ inc BUFCNT
+ jsr col64_putbyte
+ jmp get_next_byte
+
+clear_key_hit:
+; jsr clear_screen ; if we implemented it...
+ lda #$00
+ sta line_buffer_index
+ sta BUFCNT
+ jmp get_line
+
+backs_key_hit:
+ jsr print_space
+ lda BUFCNT
+ beq backs_key_done
+ dec COLCRS
+ lda COLCRS
+ clc
+ adc #$01
+ cmp LMARGN
+ bne backs_same_line
+ lda RMARGN
+ sta COLCRS
+ dec ROWCRS
+
+backs_same_line:
+ dec BUFCNT
+
+backs_key_done:
+ jmp show_cursor
+
+; ----------------------------------------------------------------------------
+; Print a space character at the current cursor position. Does not
+; update the cursor position.
+print_space:
+ lda #$00
+ sta inverse_mask
+
+ sta TMPCHR
+ jsr render_glyph
+ rts
+
+; ----------------------------------------------------------------------------
+; Get a keystroke (blocking). Just calls the OS K: get-one-byte routine
+; (call by pushing address-minus-one then doing an RTS)
+
+get_keystroke:
+ lda k_dev_get_hi
+ pha
+ lda k_dev_get_lo
+ pha
+ rts
+
+
+; ----------------------------------------------------------------------------
+; Unimplemented CIO callbacks here. Also various other routines jump here
+; to return success to the caller.
+
+col64_close:
+return_success:
+ ldy #$01
+ rts
+
+; ----------------------------------------------------------------------------
+; CIO OPEN command callback
+
+col64_open:
+ jsr init_graphics_8
+ lda #$00
+ sta ROWCRS
+ sta COLCRS
+ sta BUFCNT
+ sta LMARGN
+ lda #DEFAULT_RMARGN
+ sta RMARGN
+ rts
+
+; ----------------------------------------------------------------------------
+; CIO PUT BYTE command callback
+; The byte to put is passed to us in the accumulator.
+
+col64_putbyte:
+ ; EOL (decimal 155)?
+ cmp #EOL
+;;; bne check_clear
+ bne regular_char
+ lda RMARGN
+ sta COLCRS
+ jmp skip_write
+
+;;;check_clear:
+;;; ; save memory by not including clear_screen
+;;; ; (also, this lets us print the } character)
+;;; ; Clear (decimal 125)?
+;;; cmp #$7D
+;;; bne regular_char
+;;; jmp clear_screen
+;;; .endif
+;;;
+
+; See if this is an inverse video char (code >= 128)
+regular_char:
+ tax
+ bpl not_inverse
+ lda #INVERTED_MASK
+ sta inverse_mask
+ bne skip_ninv
+
+not_inverse:
+ lda #$00
+ sta inverse_mask
+
+skip_ninv:
+ txa
+ and #$7F
+ sec
+ sbc #$20
+ bcs not_low_ascii
+ jmp return_success
+
+not_low_ascii:
+ sta TMPCHR
+
+ lda DINDEX ; OS stores current graphics mode here
+ cmp #$08
+ beq graphics_ok
+ ; If we're not in GRAPHICS 8 mode, reinitialize ourselves
+ jsr col64_open
+
+graphics_ok:
+ jsr render_glyph
+
+skip_write:
+ ; Move the cursor 1 space to the right. This will
+ ; advance us to the next line if we're at the margin,
+ ; and scroll the screen if needed
+ jsr advance_cursor
+
+; Could implement SSFLAG logic here
+;check_ssflag:
+ ; The OS keyboard interrupt handler will toggle SSFLAG (start/stop fla
+ ; any time the user presses ctrl-1
+ ;lda SSFLAG
+ ;bne check_ssflag
+ jmp return_success
+
+; ----------------------------------------------------------------------------
+; Call the routines that actually print the character.
+; render_glyph prints the character in TMPCHR at the current
+; COLCRS and ROWCRS, and does NOT advance the cursor.
+; TMPCHR should already have bit 7 stripped; render_glyph will
+; use inverse_mask, so the caller should have set that up as well.
+render_glyph:
+ jsr setup_mask
+ jsr setup_screen_ptr
+ jsr setup_font_index
+ jmp write_font_data
+
+; ----------------------------------------------------------------------------
+; mask is used to avoid overwriting pixels outside the character cell
+; we're currently writing. Since 5 pixel wide cells don't align on byte
+; boundaries in screen RAM, we have to read/modify/write 2 bytes, and
+; the mask also has to be 2 bytes wide.
+; Also we set up shift_amount here.
+
+setup_mask:
+ lda COLCRS
+ and #$07
+ tax
+ lda mask_lo_tab,x
+ sta mask_lo
+ lda mask_hi_tab,x
+ sta mask_hi
+ lda shift_amount_tab,x
+ sta shift_amount
+ rts
+
+
+; ----------------------------------------------------------------------------
+; Make (screen_ptr_lo) point to the first byte of screen RAM on the top scanline
+; of the current char cell. Assumes COLCRS/ROWCRS are never out of range!
+setup_screen_ptr:
+ ; first the row... table lookup quicker than mult by 240
+ ldx ROWCRS
+ clc
+ lda SAVMSC
+ adc line_addr_tab_lo,x
+ sta screen_ptr_lo
+ lda SAVMSC+1
+ adc line_addr_tab_hi,x
+ sta screen_ptr_hi
+
+ ; now do the column
+ ldx COLCRS
+ lda screen_ptr_lo
+ clc
+ adc column_byte_tab,x
+ sta screen_ptr_lo
+ lda #0
+ adc screen_ptr_hi
+ sta screen_ptr_hi
+
+ rts
+
+; ----------------------------------------------------------------------------
+; Set up font_index to point to the font_data bitmap for the character in
+; TMPCHR. Also sets lo_nybble_flag to let the caller know whether the
+; bitmap is in the upper or lower 4 bits of the bytes pointed to.
+
+; Calculation is:
+; lo_nybble_flag = (TMPCHR & 1) ? $FF : $00;
+; font_index = (TMPCHR >> 1) * 5;
+
+setup_font_index:
+ lda #$00
+ sta lo_nybble_flag
+ lda TMPCHR
+ lsr ; a = (TMPCHR >> 1)
+ tay ; y = a
+ bcc font_hi_nybble
+ dec lo_nybble_flag ; = $FF
+
+font_hi_nybble:
+ clc
+ asl ; a *= 2
+ asl ; a *= 2
+ sta font_index
+ tya
+ adc font_index
+ sta font_index
+
+ rts
+
+
+; ----------------------------------------------------------------------------
+; When write_font_data is called:
+; - font_index is the 1-byte index into font_data where the current glyph is
+; - lo_nybble_flag is 0 for high nybble of glyph data, $FF for low
+; - mask_lo/hi is our 16-bit pixel mask (1's are "leave original data")
+; - shift_amount is # of times to shift glyph data right
+; - screen_ptr_lo/hi points to the 1st byte on the top line
+
+; Loop 5 times, each time thru the loop:
+; - extract 4-bit glyph data, store in glyph_data_lo
+; - shift right shift_amount times
+; ...write data...
+; - add 40 to 16-bit screen_ptr_lo/hi (to get to next line)
+
+write_font_data:
+ lda #$05
+ sta line_count
+
+wfont_line_loop:
+ lda #$00
+ tay
+ sta glyph_data_hi
+
+ ldx font_index
+ lda font_data,x
+
+ bit lo_nybble_flag
+ beq use_hi_nybble
+
+ asl
+ asl
+ asl
+ asl
+
+use_hi_nybble: ; 4-bit glyph data now in hi nybble
+ and #$F0
+ eor inverse_mask
+ sta glyph_data_lo
+
+ ldx shift_amount
+ beq wfont_no_shift
+
+wfont_shift_loop:
+ lsr glyph_data_lo
+ ror glyph_data_hi
+ dex
+ bne wfont_shift_loop
+
+wfont_no_shift:
+ lda mask_lo
+ and (screen_ptr_lo),y
+ ora glyph_data_lo
+ sta (screen_ptr_lo),y
+
+ lda mask_hi
+ beq wfont_skip_hi
+ iny
+ and (screen_ptr_lo),y
+ ora glyph_data_hi
+ sta (screen_ptr_lo),y
+
+wfont_skip_hi:
+ dec line_count
+ bmi wfont_done
+ bne wfont_not_bottom
+
+ stx font_index ; X always 0: for last line, cheat and use the space glyph
+ stx lo_nybble_flag
+
+wfont_not_bottom:
+ lda #$28 ; 40 bytes to next line
+ clc
+ adc screen_ptr_lo
+ sta screen_ptr_lo
+ bcc wfont_noinc
+ inc screen_ptr_hi
+
+wfont_noinc:
+ inc font_index
+ bne wfont_line_loop ; branch always
+
+wfont_done:
+ rts
+
+; ----------------------------------------------------------------------------
+; Not the fastest scroller in the west... TODO: make faster :)
+
+; glyph_data_lo points to line N
+; screen_ptr_lo points to line N+1
+scroll_screen:
+ lda #0
+ sta COLCRS
+ sta ROWCRS
+ jsr setup_screen_ptr
+
+scroll_line_loop:
+ lda screen_ptr_lo
+ sta glyph_data_lo
+ lda screen_ptr_hi
+ sta glyph_data_hi
+ ldx ROWCRS
+ cpx #LAST_ROW
+ beq scroll_blank
+ inx
+ stx ROWCRS
+ jsr setup_screen_ptr
+ ldy #0
+
+scroll_byte_loop:
+ lda (screen_ptr_lo),y
+ sta (glyph_data_lo),y
+ iny
+ cpy #$F0
+ bne scroll_byte_loop
+ beq scroll_line_loop
+
+scroll_blank:
+ jsr setup_screen_ptr
+ ldy #0
+ tya
+sblank_loop:
+ sta (screen_ptr_lo),y
+ iny
+ cpy #$F0
+ bne sblank_loop
+
+ rts
+
+; ----------------------------------------------------------------------------
+; Move the cursor one space to the right (to the next line if at the margin,
+; and scroll screen if on the last row)
+
+advance_cursor:
+ inc COLCRS
+ lda RMARGN
+ cmp COLCRS
+ bcs same_line
+ lda LMARGN
+ sta COLCRS
+ lda ROWCRS
+ cmp #LAST_ROW
+ bcc no_scroll
+ jsr scroll_screen
+ ; Move to last row after scrolling
+ lda #LAST_ROW-1
+ sta ROWCRS
+
+no_scroll:
+ inc ROWCRS
+
+same_line:
+ rts
+
+; ----------------------------------------------------------------------------
+; Initialization. If we don't want the handler to survive a warmstart, we
+; can load this bit into e.g. the cassette buffer (throw away after running)
+
+col64_init:
+ ldy #$00
+
+next_hatab_slot:
+ lda HATABS,y
+ beq register_x_handler
+ iny
+ iny
+ iny
+ cpy #$20
+ bcc next_hatab_slot
+ jmp return_success
+
+register_x_handler:
+ lda #$58
+ sta HATABS,y
+ lda #<col64_vector_tab
+ iny
+ sta HATABS,y
+ lda #>col64_vector_tab
+ iny
+ sta HATABS,y
+ jmp return_success
+
+main_entry_point:
+ jsr col64_init
+ lda #$0C
+ sta ICCOM
+ ldx #$00
+ jsr CIOV
+ lda #$58
+ sta font_index
+ lda #$03
+ sta ICCOM
+ lda #font_index
+ sta ICBAL
+ lda #$00
+ sta ICBAH
+ ldx #$00
+ jsr CIOV
+ ldy #$07
+ lda #<col64_vector_tab
+ sta HATABS,y
+ lda #>col64_vector_tab
+ iny
+ sta HATABS,y
+no_e_handler:
+ lda #<START_ADDRESS_1
+ sta MEMTOP
+ lda #>START_ADDRESS_1
+ sta MEMTOP+1
+ jmp return_success
+
+END_ADDR_1 = *-1
+
+; XEX segment (run address)
+ word INITAD
+ word INITAD+1
+ word main_entry_point
diff --git a/src/col64/cruft/col64.sh b/src/col64/cruft/col64.sh
new file mode 100644
index 0000000..cc49b07
--- /dev/null
+++ b/src/col64/cruft/col64.sh
@@ -0,0 +1,6 @@
+dasm col64.dasm -f3 -otest -llist
+cp test col64.xex
+axe -w test test.atr
+cat test hello.xex > test2
+axe -w test2 test.atr
+atari800 -atari test.atr
diff --git a/src/col64/cruft/col64_ext.inc b/src/col64/cruft/col64_ext.inc
new file mode 100644
index 0000000..81e7660
--- /dev/null
+++ b/src/col64/cruft/col64_ext.inc
@@ -0,0 +1,48 @@
+ byte $04, $04, $04, $00, $04 ; [0] 32,33 ,!
+ byte $AA, $AF, $0A, $0F, $0A ; [5] 34,35 ",#
+ byte $70, $A9, $62, $54, $E9 ; [10] 36,37 $,%
+ byte $42, $A2, $44, $A0, $D0 ; [15] 38,39 &,'
+ byte $24, $42, $42, $42, $24 ; [20] 40,41 (,)
+ byte $A4, $44, $EE, $44, $A4 ; [25] 42,43 *,+
+ byte $00, $00, $0F, $20, $40 ; [30] 44,45 ,,-
+ byte $02, $02, $04, $08, $48 ; [35] 46,47 .,/
+ byte $64, $9C, $B4, $D4, $6E ; [40] 48,49 0,1
+ byte $6E, $91, $26, $41, $FE ; [45] 50,51 2,3
+ byte $2F, $68, $AE, $F1, $2E ; [50] 52,53 4,5
+ byte $7F, $81, $E2, $94, $64 ; [55] 54,55 6,7
+ byte $66, $99, $67, $91, $6E ; [60] 56,57 8,9
+ byte $00, $42, $00, $02, $44 ; [65] 58,59 :,;
+ byte $20, $4F, $80, $4F, $20 ; [70] 60,61 <,=
+ byte $87, $49, $22, $40, $82 ; [75] 62,63 >,?
+ byte $66, $B9, $BF, $89, $69 ; [80] 64,65 @,A
+ byte $E6, $99, $E8, $99, $E6 ; [85] 66,67 B,C
+ byte $EF, $98, $9E, $98, $EF ; [90] 68,69 D,E
+ byte $F7, $88, $EB, $89, $86 ; [95] 70,71 F,G
+ byte $9E, $94, $F4, $94, $9E ; [100] 72,73 H,I
+ byte $39, $1A, $1C, $9A, $69 ; [105] 74,75 J,K
+ byte $8A, $8F, $8D, $89, $F9 ; [110] 76,77 L,M
+ byte $96, $D9, $B9, $99, $96 ; [115] 78,79 N,O
+ byte $E6, $99, $E9, $8A, $85 ; [120] 80,81 P,Q
+ byte $E7, $98, $E6, $A1, $9E ; [125] 82,83 R,S
+ byte $F9, $49, $49, $49, $46 ; [130] 84,85 T,U
+ byte $99, $99, $9D, $AF, $4A ; [135] 86,87 V,W
+ byte $99, $99, $66, $92, $94 ; [140] 88,89 X,Y
+ byte $F6, $24, $44, $84, $F6 ; [145] 90,91 Z,[
+ byte $86, $82, $42, $22, $26 ; [150] 92,93 \,]
+ byte $40, $A0, $00, $00, $0F ; [155] 94,95 ^,_
+ byte $40, $47, $29, $0B, $05 ; [160] 96,97 `,a
+ byte $80, $87, $E8, $98, $E7 ; [165] 98,99 b,c
+ byte $10, $16, $79, $9E, $77 ; [170] 100,101 d,e
+ byte $60, $47, $E9, $47, $41 ; [175] 102,103 f,g
+ byte $84, $80, $EC, $94, $9E ; [180] 104,105 h,i
+ byte $28, $0A, $6C, $2A, $29 ; [185] 106,107 j,k
+ byte $C0, $4A, $4F, $4D, $E9 ; [190] 108,109 l,m
+ byte $00, $E6, $99, $99, $96 ; [195] 110,111 n,o
+ byte $00, $E7, $99, $E7, $81 ; [200] 112,113 p,q
+ byte $00, $A7, $DC, $83, $8E ; [205] 114,115 r,s
+ byte $40, $E9, $49, $49, $26 ; [210] 116,117 t,u
+ byte $00, $99, $9D, $AF, $4A ; [215] 118,119 v,w
+ byte $00, $99, $69, $66, $92 ; [220] 120,121 x,y
+ byte $06, $F4, $28, $44, $F6 ; [225] 122,123 z,{
+ byte $4C, $44, $42, $44, $4C ; [230] 124,125 |,}
+ byte $06, $5C, $A8, $01, $0C ; [235] 126,127 ~,
diff --git a/src/col64/cruft/col64font.bdf b/src/col64/cruft/col64font.bdf
new file mode 100644
index 0000000..b15f724
--- /dev/null
+++ b/src/col64/cruft/col64font.bdf
@@ -0,0 +1,11993 @@
+STARTFONT 2.1
+COMMENT Contributed by Janne V. Kujala <jvk@iki.fi>
+COMMENT $Id: 4x6.bdf,v 1.5 2002-08-26 18:05:49+01 mgk25 Rel $
+COMMENT Send bug reports to Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
+FONT -Misc-Fixed-Medium-R-Normal--6-60-75-75-C-40-ISO10646-1
+SIZE 6 75 75
+FONTBOUNDINGBOX 4 6 0 -1
+STARTPROPERTIES 23
+FONTNAME_REGISTRY ""
+FOUNDRY "Misc"
+FAMILY_NAME "Fixed"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 6
+POINT_SIZE 60
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "C"
+AVERAGE_WIDTH 40
+CHARSET_REGISTRY "ISO10646"
+CHARSET_ENCODING "1"
+FONT_ASCENT 5
+FONT_DESCENT 1
+DESTINATION 1
+COPYRIGHT "Public domain font. Share and enjoy."
+CAP_HEIGHT 5
+X_HEIGHT 4
+DEFAULT_CHAR 0
+_GBDFED_INFO "Edited with gbdfed 1.4."
+ENDPROPERTIES
+CHARS 920
+STARTCHAR char0
+ENCODING 0
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+00
+A0
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 32
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+F0
+A0
+F0
+A0
+00
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+60
+50
+E0
+00
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+20
+40
+90
+00
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+A0
+D0
+00
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+20
+20
+20
+40
+00
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+A0
+00
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+20
+40
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 45
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+40
+00
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+40
+80
+80
+00
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+B0
+D0
+60
+00
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+20
+40
+F0
+00
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+10
+60
+10
+E0
+00
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+A0
+F0
+20
+00
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+80
+E0
+10
+E0
+00
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+80
+E0
+90
+60
+00
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+10
+20
+40
+40
+00
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+60
+90
+60
+00
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+70
+10
+E0
+00
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+00
+00
+40
+00
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+00
+20
+40
+00
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+80
+40
+20
+00
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F0
+00
+F0
+00
+00
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+20
+40
+80
+00
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+90
+20
+00
+20
+00
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+B0
+B0
+80
+60
+00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+F0
+90
+90
+00
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+90
+E0
+90
+E0
+00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+80
+90
+60
+00
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+90
+90
+90
+E0
+00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+80
+E0
+80
+F0
+00
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+80
+E0
+80
+80
+00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+80
+B0
+90
+60
+00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+F0
+90
+90
+00
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+30
+10
+10
+90
+60
+00
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+A0
+C0
+A0
+90
+00
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+80
+F0
+00
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+F0
+D0
+90
+90
+00
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+D0
+B0
+90
+90
+00
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+90
+E0
+80
+80
+00
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+90
+A0
+50
+00
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+90
+E0
+A0
+90
+00
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+80
+60
+10
+E0
+00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+90
+A0
+40
+00
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+D0
+F0
+A0
+00
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+60
+90
+90
+00
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+60
+20
+40
+00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+20
+40
+80
+F0
+00
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+40
+40
+60
+00
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+40
+20
+20
+00
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+20
+20
+20
+60
+00
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+F0
+00
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+30
+50
+90
+70
+00
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+E0
+90
+E0
+00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+80
+80
+70
+00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+10
+70
+90
+70
+00
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+90
+A0
+70
+00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+90
+70
+10
+60
+00
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+E0
+90
+90
+00
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+60
+20
+C0
+00
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+C0
+A0
+90
+00
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+F0
+D0
+90
+00
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+90
+E0
+80
+00
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+90
+70
+10
+00
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+D0
+80
+80
+00
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+C0
+30
+E0
+00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+90
+A0
+40
+00
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+D0
+F0
+A0
+00
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+60
+60
+90
+00
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+60
+20
+C0
+00
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F0
+20
+40
+F0
+00
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+80
+40
+60
+00
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+20
+40
+C0
+00
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+00
+00
+00
+ENDCHAR
+STARTCHAR char127
+ENCODING 127
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B0
+90
+00
+90
+D0
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 160
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+80
+E0
+40
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+60
+40
+A0
+00
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+60
+60
+90
+00
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+00
+40
+40
+00
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR dieresis
+ENCODING 168
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+D0
+D0
+90
+60
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+60
+00
+E0
+00
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+50
+00
+00
+ENDCHAR
+STARTCHAR logicalnot
+ENCODING 172
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+20
+00
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+F0
+D0
+60
+00
+00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+00
+E0
+00
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+80
+C0
+00
+00
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+80
+40
+80
+00
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+D0
+D0
+50
+50
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+20
+40
+00
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+40
+40
+00
+00
+ENDCHAR
+STARTCHAR ordmasculine
+ENCODING 186
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+00
+E0
+00
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+50
+A0
+00
+00
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+50
+70
+10
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+B0
+10
+20
+30
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+80
+50
+B0
+10
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+80
+60
+00
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Adieresis
+ENCODING 196
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+F0
+A0
+B0
+00
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+80
+A0
+40
+80
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Edieresis
+ENCODING 203
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Idieresis
+ENCODING 207
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Eth
+ENCODING 208
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+50
+D0
+50
+E0
+00
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+E0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+E0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Odieresis
+ENCODING 214
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+40
+A0
+00
+00
+ENDCHAR
+STARTCHAR Oslash
+ENCODING 216
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+E0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Udieresis
+ENCODING 220
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR Thorn
+ENCODING 222
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+C0
+A0
+C0
+80
+00
+ENDCHAR
+STARTCHAR germandbls
+ENCODING 223
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+C0
+A0
+E0
+80
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR adieresis
+ENCODING 228
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+B0
+A0
+70
+00
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+80
+60
+40
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR edieresis
+ENCODING 235
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR idieresis
+ENCODING 239
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+60
+A0
+40
+00
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR odieresis
+ENCODING 246
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR divide
+ENCODING 247
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+40
+00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR udieresis
+ENCODING 252
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+E0
+20
+C0
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+C0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR ydieresis
+ENCODING 255
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+E0
+20
+C0
+ENDCHAR
+STARTCHAR Amacron
+ENCODING 256
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR amacron
+ENCODING 257
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR Abreve
+ENCODING 258
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR abreve
+ENCODING 259
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR Aogonek
+ENCODING 260
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+E0
+A0
+20
+ENDCHAR
+STARTCHAR aogonek
+ENCODING 261
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+60
+A0
+60
+20
+ENDCHAR
+STARTCHAR Cacute
+ENCODING 262
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR cacute
+ENCODING 263
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+80
+60
+00
+ENDCHAR
+STARTCHAR Ccircumflex
+ENCODING 264
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR ccircumflex
+ENCODING 265
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+60
+80
+60
+00
+ENDCHAR
+STARTCHAR Cdotaccent
+ENCODING 266
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR cdotaccent
+ENCODING 267
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+60
+80
+60
+00
+ENDCHAR
+STARTCHAR Ccaron
+ENCODING 268
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR ccaron
+ENCODING 269
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+60
+80
+60
+00
+ENDCHAR
+STARTCHAR Dcaron
+ENCODING 270
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+C0
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR dcaron
+ENCODING 271
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+30
+20
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR Dcroat
+ENCODING 272
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+E0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR dcroat
+ENCODING 273
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+20
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR Emacron
+ENCODING 274
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR emacron
+ENCODING 275
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR Ebreve
+ENCODING 276
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR ebreve
+ENCODING 277
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR Edotaccent
+ENCODING 278
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR edotaccent
+ENCODING 279
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR Eogonek
+ENCODING 280
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+80
+E0
+20
+ENDCHAR
+STARTCHAR eogonek
+ENCODING 281
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+C0
+60
+40
+ENDCHAR
+STARTCHAR Ecaron
+ENCODING 282
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR ecaron
+ENCODING 283
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR Gcircumflex
+ENCODING 284
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+80
+A0
+60
+00
+ENDCHAR
+STARTCHAR gcircumflex
+ENCODING 285
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR Gbreve
+ENCODING 286
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+60
+80
+A0
+60
+00
+ENDCHAR
+STARTCHAR gbreve
+ENCODING 287
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR Gdotaccent
+ENCODING 288
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+80
+A0
+60
+00
+ENDCHAR
+STARTCHAR gdotaccent
+ENCODING 289
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR Gcommaaccent
+ENCODING 290
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+A0
+A0
+40
+40
+ENDCHAR
+STARTCHAR gcommaaccent
+ENCODING 291
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR Hcircumflex
+ENCODING 292
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR hcircumflex
+ENCODING 293
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Hbar
+ENCODING 294
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR hbar
+ENCODING 295
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+C0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Itilde
+ENCODING 296
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR itilde
+ENCODING 297
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Imacron
+ENCODING 298
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR imacron
+ENCODING 299
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Ibreve
+ENCODING 300
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR ibreve
+ENCODING 301
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Iogonek
+ENCODING 302
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+E0
+20
+ENDCHAR
+STARTCHAR iogonek
+ENCODING 303
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+C0
+40
+E0
+20
+ENDCHAR
+STARTCHAR Idotaccent
+ENCODING 304
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR dotlessi
+ENCODING 305
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR IJ
+ENCODING 306
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+A0
+A0
+20
+60
+ENDCHAR
+STARTCHAR ij
+ENCODING 307
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+20
+40
+ENDCHAR
+STARTCHAR Jcircumflex
+ENCODING 308
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+20
+A0
+40
+00
+ENDCHAR
+STARTCHAR jcircumflex
+ENCODING 309
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+20
+20
+C0
+ENDCHAR
+STARTCHAR Kcommaaccent
+ENCODING 310
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+C0
+A0
+20
+40
+ENDCHAR
+STARTCHAR kcommaaccent
+ENCODING 311
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+C0
+A0
+20
+40
+ENDCHAR
+STARTCHAR kgreenlandic
+ENCODING 312
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR Lacute
+ENCODING 313
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+80
+80
+80
+E0
+00
+ENDCHAR
+STARTCHAR lacute
+ENCODING 314
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Lcommaaccent
+ENCODING 315
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+80
+E0
+20
+ENDCHAR
+STARTCHAR lcommaaccent
+ENCODING 316
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+40
+40
+E0
+20
+ENDCHAR
+STARTCHAR Lcaron
+ENCODING 317
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+C0
+80
+80
+E0
+00
+ENDCHAR
+STARTCHAR lcaron
+ENCODING 318
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Ldot
+ENCODING 319
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+A0
+80
+E0
+00
+ENDCHAR
+STARTCHAR ldot
+ENCODING 320
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+50
+40
+E0
+00
+ENDCHAR
+STARTCHAR Lslash
+ENCODING 321
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR lslash
+ENCODING 322
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+60
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Nacute
+ENCODING 323
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+E0
+A0
+80
+00
+ENDCHAR
+STARTCHAR nacute
+ENCODING 324
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Ncommaaccent
+ENCODING 325
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+E0
+A0
+80
+20
+ENDCHAR
+STARTCHAR ncommaaccent
+ENCODING 326
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+A0
+00
+40
+ENDCHAR
+STARTCHAR Ncaron
+ENCODING 327
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+E0
+A0
+80
+00
+ENDCHAR
+STARTCHAR ncaron
+ENCODING 328
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR napostrophe
+ENCODING 329
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+00
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Eng
+ENCODING 330
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+E0
+A0
+20
+40
+ENDCHAR
+STARTCHAR eng
+ENCODING 331
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+A0
+20
+40
+ENDCHAR
+STARTCHAR Omacron
+ENCODING 332
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR omacron
+ENCODING 333
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR Obreve
+ENCODING 334
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR obreve
+ENCODING 335
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR Ohungarumlaut
+ENCODING 336
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR ohungarumlaut
+ENCODING 337
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR OE
+ENCODING 338
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+B0
+A0
+70
+00
+ENDCHAR
+STARTCHAR oe
+ENCODING 339
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+B0
+A0
+70
+00
+ENDCHAR
+STARTCHAR Racute
+ENCODING 340
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR racute
+ENCODING 341
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+A0
+C0
+80
+00
+ENDCHAR
+STARTCHAR Rcommaaccent
+ENCODING 342
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+A0
+00
+40
+ENDCHAR
+STARTCHAR rcommaaccent
+ENCODING 343
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+C0
+80
+80
+20
+ENDCHAR
+STARTCHAR Rcaron
+ENCODING 344
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR rcaron
+ENCODING 345
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+A0
+C0
+80
+00
+ENDCHAR
+STARTCHAR Sacute
+ENCODING 346
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR sacute
+ENCODING 347
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR Scircumflex
+ENCODING 348
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR scircumflex
+ENCODING 349
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR Scedilla
+ENCODING 350
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+40
+20
+C0
+40
+ENDCHAR
+STARTCHAR scedilla
+ENCODING 351
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+20
+E0
+40
+ENDCHAR
+STARTCHAR Scaron
+ENCODING 352
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+C0
+20
+E0
+00
+ENDCHAR
+STARTCHAR scaron
+ENCODING 353
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 354
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+20
+40
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 355
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+20
+40
+ENDCHAR
+STARTCHAR Tcaron
+ENCODING 356
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR tcaron
+ENCODING 357
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+20
+00
+ENDCHAR
+STARTCHAR Tbar
+ENCODING 358
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR tbar
+ENCODING 359
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+E0
+40
+20
+00
+ENDCHAR
+STARTCHAR Utilde
+ENCODING 360
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+20
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR utilde
+ENCODING 361
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+00
+A0
+60
+00
+ENDCHAR
+STARTCHAR Umacron
+ENCODING 362
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR umacron
+ENCODING 363
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR Ubreve
+ENCODING 364
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR ubreve
+ENCODING 365
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+A0
+60
+00
+ENDCHAR
+STARTCHAR Uring
+ENCODING 366
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR uring
+ENCODING 367
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR Uhungarumlaut
+ENCODING 368
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR uhungarumlaut
+ENCODING 369
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR Uogonek
+ENCODING 370
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+40
+20
+ENDCHAR
+STARTCHAR uogonek
+ENCODING 371
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+60
+40
+ENDCHAR
+STARTCHAR Wcircumflex
+ENCODING 372
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR wcircumflex
+ENCODING 373
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR Ycircumflex
+ENCODING 374
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR ycircumflex
+ENCODING 375
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+40
+80
+00
+ENDCHAR
+STARTCHAR Ydieresis
+ENCODING 376
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR Zacute
+ENCODING 377
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR zacute
+ENCODING 378
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR Zdotaccent
+ENCODING 379
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR zdotaccent
+ENCODING 380
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR Zcaron
+ENCODING 381
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR zcaron
+ENCODING 382
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR longs
+ENCODING 383
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+C0
+40
+40
+00
+ENDCHAR
+STARTCHAR uni018F
+ENCODING 399
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+60
+A0
+40
+00
+ENDCHAR
+STARTCHAR florin
+ENCODING 402
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+40
+40
+80
+ENDCHAR
+STARTCHAR Scommaaccent
+ENCODING 536
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+40
+20
+C0
+40
+ENDCHAR
+STARTCHAR scommaaccent
+ENCODING 537
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+20
+E0
+40
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 538
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+00
+40
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 539
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+20
+40
+ENDCHAR
+STARTCHAR uni0259
+ENCODING 601
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+60
+A0
+40
+00
+ENDCHAR
+STARTCHAR circumflex
+ENCODING 710
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR caron
+ENCODING 711
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR macron
+ENCODING 713
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR breve
+ENCODING 728
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dotaccent
+ENCODING 729
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ring
+ENCODING 730
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR ogonek
+ENCODING 731
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+40
+80
+C0
+ENDCHAR
+STARTCHAR tilde
+ENCODING 732
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR hungarumlaut
+ENCODING 733
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0374
+ENCODING 884
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0375
+ENCODING 885
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+40
+80
+ENDCHAR
+STARTCHAR uni037A
+ENCODING 890
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+40
+60
+ENDCHAR
+STARTCHAR uni037E
+ENCODING 894
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+00
+00
+40
+80
+ENDCHAR
+STARTCHAR tonos
+ENCODING 900
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dieresistonos
+ENCODING 901
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B0
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Alphatonos
+ENCODING 902
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR anoteleia
+ENCODING 903
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR Epsilontonos
+ENCODING 904
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+C0
+60
+40
+60
+00
+ENDCHAR
+STARTCHAR Etatonos
+ENCODING 905
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+20
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Iotatonos
+ENCODING 906
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+C0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Omicrontonos
+ENCODING 908
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Upsilontonos
+ENCODING 910
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+C0
+40
+40
+00
+ENDCHAR
+STARTCHAR Omegatonos
+ENCODING 911
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+A0
+40
+A0
+00
+ENDCHAR
+STARTCHAR iotadieresistonos
+ENCODING 912
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B0
+40
+00
+40
+20
+00
+ENDCHAR
+STARTCHAR Alpha
+ENCODING 913
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Beta
+ENCODING 914
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR Gamma
+ENCODING 915
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR Delta
+ENCODING 916
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Epsilon
+ENCODING 917
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Zeta
+ENCODING 918
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+20
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR Eta
+ENCODING 919
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Theta
+ENCODING 920
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+E0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Iota
+ENCODING 921
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Kappa
+ENCODING 922
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Lambda
+ENCODING 923
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Mu
+ENCODING 924
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Nu
+ENCODING 925
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+E0
+A0
+80
+00
+ENDCHAR
+STARTCHAR Xi
+ENCODING 926
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+40
+00
+E0
+00
+ENDCHAR
+STARTCHAR Omicron
+ENCODING 927
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Pi
+ENCODING 928
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Rho
+ENCODING 929
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+80
+80
+00
+ENDCHAR
+STARTCHAR Sigma
+ENCODING 931
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR Tau
+ENCODING 932
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR Upsilon
+ENCODING 933
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR Phi
+ENCODING 934
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+A0
+E0
+40
+00
+ENDCHAR
+STARTCHAR Chi
+ENCODING 935
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Psi
+ENCODING 936
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR Omega
+ENCODING 937
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+40
+A0
+00
+ENDCHAR
+STARTCHAR Iotadieresis
+ENCODING 938
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Upsilondieresis
+ENCODING 939
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR alphatonos
+ENCODING 940
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+80
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR epsilontonos
+ENCODING 941
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+40
+80
+60
+00
+ENDCHAR
+STARTCHAR etatonos
+ENCODING 942
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+C0
+A0
+20
+40
+ENDCHAR
+STARTCHAR iotatonos
+ENCODING 943
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR upsilondieresistonos
+ENCODING 944
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B0
+40
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR alpha
+ENCODING 945
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+A0
+50
+00
+ENDCHAR
+STARTCHAR beta
+ENCODING 946
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR gamma
+ENCODING 947
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+60
+40
+40
+00
+ENDCHAR
+STARTCHAR delta
+ENCODING 948
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR epsilon
+ENCODING 949
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+C0
+80
+60
+00
+ENDCHAR
+STARTCHAR zeta
+ENCODING 950
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+80
+E0
+20
+40
+ENDCHAR
+STARTCHAR eta
+ENCODING 951
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+A0
+20
+40
+ENDCHAR
+STARTCHAR theta
+ENCODING 952
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+E0
+A0
+40
+00
+ENDCHAR
+STARTCHAR iota
+ENCODING 953
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR kappa
+ENCODING 954
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR lambda
+ENCODING 955
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+60
+A0
+A0
+00
+ENDCHAR
+STARTCHAR mu
+ENCODING 956
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR nu
+ENCODING 957
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+60
+40
+00
+ENDCHAR
+STARTCHAR xi
+ENCODING 958
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+40
+80
+60
+00
+ENDCHAR
+STARTCHAR omicron
+ENCODING 959
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR pi
+ENCODING 960
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR rho
+ENCODING 961
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR sigma1
+ENCODING 962
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+80
+40
+C0
+00
+ENDCHAR
+STARTCHAR sigma
+ENCODING 963
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+A0
+40
+00
+ENDCHAR
+STARTCHAR tau
+ENCODING 964
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR upsilon
+ENCODING 965
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+80
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR phi
+ENCODING 966
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+A0
+40
+40
+ENDCHAR
+STARTCHAR chi
+ENCODING 967
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+40
+60
+A0
+00
+ENDCHAR
+STARTCHAR psi
+ENCODING 968
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+40
+00
+ENDCHAR
+STARTCHAR omega
+ENCODING 969
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR iotadieresis
+ENCODING 970
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR upsilondieresis
+ENCODING 971
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR omicrontonos
+ENCODING 972
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR upsilontonos
+ENCODING 973
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR omegatonos
+ENCODING 974
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR afii10023
+ENCODING 1025
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR afii10051
+ENCODING 1026
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10052
+ENCODING 1027
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10053
+ENCODING 1028
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+C0
+80
+60
+00
+ENDCHAR
+STARTCHAR afii10054
+ENCODING 1029
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+40
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10055
+ENCODING 1030
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR afii10056
+ENCODING 1031
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR afii10057
+ENCODING 1032
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+20
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10058
+ENCODING 1033
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+60
+A0
+B0
+B0
+00
+ENDCHAR
+STARTCHAR afii10059
+ENCODING 1034
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+B0
+B0
+00
+ENDCHAR
+STARTCHAR afii10060
+ENCODING 1035
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+80
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10061
+ENCODING 1036
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+80
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii10062
+ENCODING 1038
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+A0
+40
+80
+ENDCHAR
+STARTCHAR afii10145
+ENCODING 1039
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+E0
+40
+ENDCHAR
+STARTCHAR afii10017
+ENCODING 1040
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10018
+ENCODING 1041
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10019
+ENCODING 1042
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10020
+ENCODING 1043
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10021
+ENCODING 1044
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+60
+A0
+A0
+E0
+A0
+ENDCHAR
+STARTCHAR afii10022
+ENCODING 1045
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR afii10024
+ENCODING 1046
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+40
+E0
+A0
+00
+ENDCHAR
+STARTCHAR afii10025
+ENCODING 1047
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+40
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10026
+ENCODING 1048
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+E0
+A0
+20
+00
+ENDCHAR
+STARTCHAR afii10027
+ENCODING 1049
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+A0
+E0
+A0
+20
+ENDCHAR
+STARTCHAR afii10028
+ENCODING 1050
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10029
+ENCODING 1051
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10030
+ENCODING 1052
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10031
+ENCODING 1053
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10032
+ENCODING 1054
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10033
+ENCODING 1055
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10034
+ENCODING 1056
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10035
+ENCODING 1057
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10036
+ENCODING 1058
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR afii10037
+ENCODING 1059
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+40
+40
+80
+ENDCHAR
+STARTCHAR afii10038
+ENCODING 1060
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+A0
+E0
+40
+00
+ENDCHAR
+STARTCHAR afii10039
+ENCODING 1061
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10040
+ENCODING 1062
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR afii10041
+ENCODING 1063
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+60
+20
+20
+00
+ENDCHAR
+STARTCHAR afii10042
+ENCODING 1064
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR afii10043
+ENCODING 1065
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+E0
+F0
+10
+ENDCHAR
+STARTCHAR afii10044
+ENCODING 1066
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+60
+50
+60
+00
+ENDCHAR
+STARTCHAR afii10045
+ENCODING 1067
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+D0
+B0
+D0
+00
+ENDCHAR
+STARTCHAR afii10046
+ENCODING 1068
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10047
+ENCODING 1069
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+60
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10048
+ENCODING 1070
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+D0
+D0
+D0
+A0
+00
+ENDCHAR
+STARTCHAR afii10049
+ENCODING 1071
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+60
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10065
+ENCODING 1072
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR afii10066
+ENCODING 1073
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+E0
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10067
+ENCODING 1074
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10068
+ENCODING 1075
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10069
+ENCODING 1076
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+A0
+E0
+A0
+ENDCHAR
+STARTCHAR afii10070
+ENCODING 1077
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR afii10072
+ENCODING 1078
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+B0
+60
+60
+B0
+00
+ENDCHAR
+STARTCHAR afii10073
+ENCODING 1079
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+40
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10074
+ENCODING 1080
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR afii10075
+ENCODING 1081
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR afii10076
+ENCODING 1082
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii10077
+ENCODING 1083
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10078
+ENCODING 1084
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10079
+ENCODING 1085
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10080
+ENCODING 1086
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10081
+ENCODING 1087
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10082
+ENCODING 1088
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+C0
+80
+80
+ENDCHAR
+STARTCHAR afii10083
+ENCODING 1089
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+80
+80
+60
+00
+ENDCHAR
+STARTCHAR afii10084
+ENCODING 1090
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR afii10085
+ENCODING 1091
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR afii10086
+ENCODING 1092
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+40
+40
+ENDCHAR
+STARTCHAR afii10087
+ENCODING 1093
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+40
+40
+A0
+00
+ENDCHAR
+STARTCHAR afii10088
+ENCODING 1094
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+E0
+20
+ENDCHAR
+STARTCHAR afii10089
+ENCODING 1095
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+60
+20
+00
+ENDCHAR
+STARTCHAR afii10090
+ENCODING 1096
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR afii10091
+ENCODING 1097
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+F0
+10
+ENDCHAR
+STARTCHAR afii10092
+ENCODING 1098
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+60
+50
+60
+00
+ENDCHAR
+STARTCHAR afii10093
+ENCODING 1099
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+D0
+B0
+D0
+00
+ENDCHAR
+STARTCHAR afii10094
+ENCODING 1100
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+80
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10095
+ENCODING 1101
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+60
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10096
+ENCODING 1102
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+D0
+D0
+A0
+00
+ENDCHAR
+STARTCHAR afii10097
+ENCODING 1103
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+60
+A0
+00
+ENDCHAR
+STARTCHAR afii10071
+ENCODING 1105
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR afii10099
+ENCODING 1106
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+C0
+80
+C0
+A0
+20
+ENDCHAR
+STARTCHAR afii10100
+ENCODING 1107
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10101
+ENCODING 1108
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+80
+60
+00
+ENDCHAR
+STARTCHAR afii10102
+ENCODING 1109
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10103
+ENCODING 1110
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR afii10104
+ENCODING 1111
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR afii10105
+ENCODING 1112
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+20
+20
+20
+C0
+ENDCHAR
+STARTCHAR afii10106
+ENCODING 1113
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+B0
+B0
+00
+ENDCHAR
+STARTCHAR afii10107
+ENCODING 1114
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+B0
+B0
+00
+ENDCHAR
+STARTCHAR afii10108
+ENCODING 1115
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+C0
+80
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii10109
+ENCODING 1116
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+80
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii10110
+ENCODING 1118
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+A0
+40
+80
+ENDCHAR
+STARTCHAR afii10193
+ENCODING 1119
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+E0
+40
+ENDCHAR
+STARTCHAR afii10050
+ENCODING 1168
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10098
+ENCODING 1169
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+E0
+80
+80
+00
+ENDCHAR
+STARTCHAR uni0492
+ENCODING 1170
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR uni0493
+ENCODING 1171
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR afii57664
+ENCODING 1488
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+60
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii57665
+ENCODING 1489
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+20
+F0
+00
+ENDCHAR
+STARTCHAR afii57666
+ENCODING 1490
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+40
+40
+A0
+00
+ENDCHAR
+STARTCHAR afii57667
+ENCODING 1491
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR afii57668
+ENCODING 1492
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+20
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii57669
+ENCODING 1493
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+20
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR afii57670
+ENCODING 1494
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR afii57671
+ENCODING 1495
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii57672
+ENCODING 1496
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii57673
+ENCODING 1497
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57674
+ENCODING 1498
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR afii57675
+ENCODING 1499
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii57676
+ENCODING 1500
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+20
+20
+40
+00
+ENDCHAR
+STARTCHAR afii57677
+ENCODING 1501
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR afii57678
+ENCODING 1502
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii57679
+ENCODING 1503
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR afii57680
+ENCODING 1504
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+20
+20
+20
+60
+00
+ENDCHAR
+STARTCHAR afii57681
+ENCODING 1505
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii57682
+ENCODING 1506
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+60
+C0
+00
+ENDCHAR
+STARTCHAR afii57683
+ENCODING 1507
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+20
+20
+20
+ENDCHAR
+STARTCHAR afii57684
+ENCODING 1508
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+20
+E0
+00
+ENDCHAR
+STARTCHAR afii57685
+ENCODING 1509
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+C0
+80
+80
+ENDCHAR
+STARTCHAR afii57686
+ENCODING 1510
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+40
+20
+E0
+00
+ENDCHAR
+STARTCHAR afii57687
+ENCODING 1511
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+C0
+80
+80
+ENDCHAR
+STARTCHAR afii57688
+ENCODING 1512
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR afii57689
+ENCODING 1513
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F0
+D0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR afii57690
+ENCODING 1514
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR uni1E02
+ENCODING 7682
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR uni1E03
+ENCODING 7683
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+80
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR uni1E0A
+ENCODING 7690
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR uni1E0B
+ENCODING 7691
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+20
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR uni1E1E
+ENCODING 7710
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+80
+C0
+80
+00
+ENDCHAR
+STARTCHAR uni1E1F
+ENCODING 7711
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR uni1E40
+ENCODING 7744
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR uni1E41
+ENCODING 7745
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR uni1E56
+ENCODING 7766
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+A0
+C0
+80
+00
+ENDCHAR
+STARTCHAR uni1E57
+ENCODING 7767
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+C0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR uni1E60
+ENCODING 7776
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR uni1E61
+ENCODING 7777
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR uni1E6A
+ENCODING 7786
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR uni1E6B
+ENCODING 7787
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+E0
+40
+20
+ENDCHAR
+STARTCHAR Wgrave
+ENCODING 7808
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR wgrave
+ENCODING 7809
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Wacute
+ENCODING 7810
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+80
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR wacute
+ENCODING 7811
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Wdieresis
+ENCODING 7812
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR wdieresis
+ENCODING 7813
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR Ygrave
+ENCODING 7922
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR ygrave
+ENCODING 7923
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+60
+20
+40
+ENDCHAR
+STARTCHAR uni2010
+ENCODING 8208
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2011
+ENCODING 8209
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR figuredash
+ENCODING 8210
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR endash
+ENCODING 8211
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR emdash
+ENCODING 8212
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii00208
+ENCODING 8213
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2016
+ENCODING 8214
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+A0
+A0
+ENDCHAR
+STARTCHAR underscoredbl
+ENCODING 8215
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 'UÂ?-1
+BITMAP
+00
+00
+00
+F0
+00
+F0
+ENDCHAR
+STARTCHAR quoteleft
+ENCODING 8216
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR quoteright
+ENCODING 8217
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+20
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR quotesinglbase
+ENCODING 8218
+SWIDTH 640 01¥VDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+60
+20
+40
+ENDCHAR
+STARTCHAR quotereversed
+ENCODING 8219
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblleft
+ENCODING 8220
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+A0
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblright
+ENCODING 8221
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+50
+A0
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblbase
+ENCODING1MÀ-2
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+50
+50
+A0
+ENDCHAR
+STARTCHAR uni201F
+ENCODING 8223
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR dagger
+ENCODING 8224
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR daggerdbl
+ENCODING 8225
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR bullet
+ENCODING 8226
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+40
+00
+00
+ENDCHAR
+STARTCHAR uni2023
+ENCODING 8227
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+E0
+C0
+00
+00
+ENDCHAR
+STARTCHAR onedotenleader
+ENCODING 8228
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+40
+00
+ENDCHAR
+STARTCHAR twodotenleader
+ENCODING 8229
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+A0
+00
+ENDCHAR
+STARTCHAR ellipsis
+ENCODING 8230
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+B0
+00
+ENDCHAR
+STARTCHAR uni2027
+ENCODING 8231
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR perthousand
+ENCODX;µ?8240
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+40
+80
+30
+00
+ENDCHAR
+STARTCHAR guilsinglleft
+ENCODING 8249
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+80
+40
+00
+00
+ENDCHAR
+STARTCHAR guilsinglright
+ENCODING 8250
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+20
+40
+00
+00
+ENDCHAR
+STARTCHAR uni203E
+ENCODING 8254
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR nsuperior
+ENCODING 8319
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+A0
+00
+00
+ENDCHAR
+STARTCHAR peseta
+ENCODING 8359
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+F0
+60
+40
+40
+00
+ENDCHAR
+SE4 KCHAR Euro
+ENCODING 8364
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+40
+20
+00
+ENDCHAR
+STARTCHAR afii61352
+ENCODING 8470
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+B0
+B0
+A0
+B0
+00
+ENDCHAR
+STARTCHAR trademark
+ENCODING 8482
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+00
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Omega
+ENCODING 8486
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+40
+A0
+00
+ENDCHAR
+STARTCHAR uni2127
+ENCODING 8487
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR oneeighth
+ENCODING 8539
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 'UÂ?-1
+BITMAP
+80
+80
+B0
+20
+50
+20
+ENDCHAR
+STARTCHAR threeeighths
+ENCODING 8540
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+B0
+60
+D0
+20
+ENDCHAR
+STARTCHAR fiveeighths
+ENCODING 8541
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+80
+70
+A0
+50
+20
+ENDCHAR
+STARTCHAR seveneighths
+ENCODING 8542
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+B0
+A0
+50
+20
+ENDCHAR
+STARTCHAR arrowleft
+ENCODING 8592
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+F0
+40
+00
+00
+ENDCHAR
+STARTCHAR arrowup
+ENCODING 8593
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR arrowright
+ENCODING 8594
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+F0
+20
+00
+00
+ENDCHAR
+STARTCHAR arrowdown
+ENCODING 8595
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR arrowboth
+ENCODING 8596
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+F0
+50
+00
+00
+ENDCHAR
+STARTCHAR arrowupdn
+ENCODING 8597
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR universal
+ENCODING 8704
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+A0
+40
+00
+ENDCHAR
+STARTCHAR uni2201
+ENCODING 8705
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR partialdiff
+ENCODING 8706
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+60
+A0
+40
+00
+ENDCHAR
+STARTCHAR existential
+ENCODING 8707
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+20
+E0
+20
+E0
+00
+ENDCHAR
+STARTCHAR uni2204
+ENCODING 8708
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+20
+E0
+60
+E0
+80
+ENDCHAR
+STARTCHAR emptyset
+ENCODING 8709
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+A0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR Delta
+ENCODING 8710
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR gradient
+ENCODING 8711
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR element
+ENCODING 8712
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+E0
+80
+60
+00
+ENDCHAR
+STARTCHAR notelement
+ENCODING 8713
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+E0
+A0
+60
+40
+ENDCHAR
+STARTCHAR uni220A
+ENCODING 8714
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+80
+C0
+80
+40
+00
+ENDCHAR
+STARTCHAR suchthat
+ENCODING 8715
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+E0
+20
+C0
+00
+ENDCHAR
+STARTCHAR uni220C
+ENCODING 8716
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+20
+E0
+60
+C0
+80
+ENDCHAR
+STARTCHAR uni220D
+ENCODING 8717
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+C0
+40
+80
+00
+ENDCHAR
+STARTCHAR uni220E
+ENCODING 8718
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+C0
+C0
+C0
+C0
+00
+ENDCHAR
+STARTCHAR product
+ENCODING 8719
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR uni2210
+ENCODING 8720
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR summation
+ENCODING 8721
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR minus
+ENCODING 8722
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2213
+ENCODING 8723
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR uni2214
+ENCODING 8724
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR fraction
+ENCODING 8725
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+40
+80
+80
+00
+ENDCHAR
+STARTCHAR uni2216
+ENCODING 8726
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+40
+20
+20
+00
+ENDCHAR
+STARTCHAR asteriskmath
+ENCODING 8727
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+70
+E0
+50
+40
+ENDCHAR
+STARTCHAR uni2218
+ENCODING 8728
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+40
+00
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 8729
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+40
+00
+00
+ENDCHAR
+STARTCHAR radical
+ENCODING 8730
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+30
+20
+20
+A0
+60
+00
+ENDCHAR
+STARTCHAR uni221B
+ENCODING 8731
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+50
+D0
+10
+50
+30
+ENDCHAR
+STARTCHAR uni221C
+ENCODING 8732
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+D0
+50
+10
+50
+30
+ENDCHAR
+STARTCHAR proportional
+ENCODING 8733
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+50
+E0
+50
+00
+ENDCHAR
+STARTCHAR infinity
+ENCODING 8734
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+D0
+B0
+40
+00
+ENDCHAR
+STARTCHAR orthogonal
+ENCODING 8735
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+80
+80
+E0
+00
+ENDCHAR
+STARTCHAR angle
+ENCODING 8736
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR uni2221
+ENCODING 8737
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+A0
+40
+A0
+F0
+20
+ENDCHAR
+STARTCHAR uni2222
+ENCODING 8738
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+60
+A0
+A0
+60
+90
+ENDCHAR
+STARTCHAR uni2223
+ENCODING 8739
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR uni2224
+ENCODING 8740
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+40
+C0
+40
+00
+ENDCHAR
+STARTCHAR uni2225
+ENCODING 8741
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR uni2226
+ENCODING 8742
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+B0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR logicaland
+ENCODING 8743
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+40
+A0
+A0
+00
+ENDCHAR
+STARTCHAR logicalor
+ENCODING 8744
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR intersection
+ENCODING 8745
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR union
+ENCODING 8746
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR integral
+ENCODING 8747
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR uni222C
+ENCODING 8748
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+A0
+A0
+A0
+80
+ENDCHAR
+STARTCHAR uni222D
+ENCODING 8749
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+D0
+D0
+D0
+D0
+A0
+ENDCHAR
+STARTCHAR uni222E
+ENCODING 8750
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+E0
+40
+80
+ENDCHAR
+STARTCHAR uni222F
+ENCODING 8751
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+E0
+E0
+A0
+80
+ENDCHAR
+STARTCHAR uni2230
+ENCODING 8752
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+D0
+F0
+F0
+D0
+A0
+ENDCHAR
+STARTCHAR uni2231
+ENCODING 8753
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+50
+40
+80
+ENDCHAR
+STARTCHAR uni2232
+ENCODING 8754
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+C0
+40
+80
+ENDCHAR
+STARTCHAR uni2233
+ENCODING 8755
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+C0
+E0
+40
+80
+ENDCHAR
+STARTCHAR therefore
+ENCODING 8756
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+A0
+00
+ENDCHAR
+STARTCHAR uni2235
+ENCODING 8757
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A0
+00
+40
+00
+ENDCHAR
+STARTCHAR uni2236
+ENCODING 8758
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR uni2237
+ENCODING 8759
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A0
+00
+A0
+00
+ENDCHAR
+STARTCHAR uni2238
+ENCODING 8760
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2239
+ENCODING 8761
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+20
+C0
+20
+00
+ENDCHAR
+STARTCHAR uni223A
+ENCODING 8762
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+E0
+00
+A0
+00
+ENDCHAR
+STARTCHAR uni223B
+ENCODING 8763
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+50
+A0
+00
+40
+ENDCHAR
+STARTCHAR similar
+ENCODING 8764
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+50
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni223D
+ENCODING 8765
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A0
+50
+00
+00
+ENDCHAR
+STARTCHAR uni223E
+ENCODING 8766
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+D0
+B0
+00
+00
+ENDCHAR
+STARTCHAR uni223F
+ENCODING 8767
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+50
+A0
+20
+00
+ENDCHAR
+STARTCHAR uni2240
+ENCODING 8768
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+20
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR uni2241
+ENCODING 8769
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+20
+B0
+D0
+40
+80
+ENDCHAR
+STARTCHAR uni2242
+ENCODING 8770
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+00
+A0
+50
+00
+ENDCHAR
+STARTCHAR uni2243
+ENCODING 8771
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2244
+ENCODING 8772
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+D0
+B0
+40
+F0
+40
+ENDCHAR
+STARTCHAR congruent
+ENCODING 8773
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+00
+E0
+00
+E0
+ENDCHAR
+STARTCHAR uni2246
+ENCODING 8774
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+20
+F0
+40
+F0
+ENDCHAR
+STARTCHAR uni2247
+ENCODING 8775
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+20
+F0
+40
+F0
+ENDCHAR
+STARTCHAR approxequal
+ENCODING 8776
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+00
+50
+A0
+00
+ENDCHAR
+STARTCHAR uni2249
+ENCODING 8777
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+40
+50
+E0
+80
+ENDCHAR
+STARTCHAR uni224A
+ENCODING 8778
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+B0
+40
+B0
+00
+F0
+ENDCHAR
+STARTCHAR uni224B
+ENCODING 8779
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+B0
+40
+B0
+40
+B0
+ENDCHAR
+STARTCHAR uni224C
+ENCODING 8780
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+50
+00
+E0
+00
+E0
+ENDCHAR
+STARTCHAR uni224D
+ENCODING 8781
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+40
+A0
+00
+ENDCHAR
+STARTCHAR uni224E
+ENCODING 8782
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+A0
+40
+00
+ENDCHAR
+STARTCHAR uni224F
+ENCODING 8783
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2250
+ENCODING 8784
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2251
+ENCODING 8785
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+40
+ENDCHAR
+STARTCHAR uni2252
+ENCODING 8786
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+00
+E0
+00
+20
+ENDCHAR
+STARTCHAR uni2253
+ENCODING 8787
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+00
+E0
+00
+80
+ENDCHAR
+STARTCHAR uni2254
+ENCODING 8788
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+B0
+00
+B0
+00
+00
+ENDCHAR
+STARTCHAR uni2255
+ENCODING 8789
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+D0
+00
+D0
+00
+00
+ENDCHAR
+STARTCHAR uni2256
+ENCODING 8790
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+40
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2257
+ENCODING 8791
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2258
+ENCODING 8792
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2259
+ENCODING 8793
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni225A
+ENCODING 8794
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni225B
+ENCODING 8795
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni225C
+ENCODING 8796
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni225D
+ENCODING 8797
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni225E
+ENCODING 8798
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni225F
+ENCODING 8799
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR notequal
+ENCODING 8800
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+40
+E0
+80
+00
+ENDCHAR
+STARTCHAR equivalence
+ENCODING 8801
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2262
+ENCODING 8802
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+20
+E0
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni2263
+ENCODING 8803
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR lessequal
+ENCODING 8804
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR greaterequal
+ENCODING 8805
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2266
+ENCODING 8806
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2267
+ENCODING 8807
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2268
+ENCODING 8808
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+40
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2269
+ENCODING 8809
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+80
+40
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni226A
+ENCODING 8810
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+50
+00
+00
+ENDCHAR
+STARTCHAR uni226B
+ENCODING 8811
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+50
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni226C
+ENCODING 8812
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+40
+A0
+00
+ENDCHAR
+STARTCHAR uni226D
+ENCODING 8813
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+40
+E0
+80
+00
+ENDCHAR
+STARTCHAR uni226E
+ENCODING 8814
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+C0
+60
+80
+00
+ENDCHAR
+STARTCHAR uni226F
+ENCODING 8815
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+60
+C0
+80
+00
+ENDCHAR
+STARTCHAR uni2270
+ENCODING 8816
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni2271
+ENCODING 8817
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+60
+E0
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni2272
+ENCODING 8818
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+00
+50
+A0
+ENDCHAR
+STARTCHAR uni2273
+ENCODING 8819
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+E0
+00
+A0
+50
+ENDCHAR
+STARTCHAR uni2276
+ENCODING 8822
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+20
+80
+60
+C0
+ENDCHAR
+STARTCHAR uni2277
+ENCODING 8823
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+60
+80
+20
+C0
+60
+ENDCHAR
+STARTCHAR uni2278
+ENCODING 8824
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+60
+C0
+60
+C0
+ENDCHAR
+STARTCHAR uni2279
+ENCODING 8825
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+60
+C0
+60
+C0
+60
+ENDCHAR
+STARTCHAR uni227A
+ENCODING 8826
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+C0
+20
+00
+00
+ENDCHAR
+STARTCHAR uni227B
+ENCODING 8827
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+80
+60
+80
+00
+00
+ENDCHAR
+STARTCHAR uni227C
+ENCODING 8828
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+20
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni227D
+ENCODING 8829
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+80
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni227E
+ENCODING 8830
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+20
+00
+A0
+50
+ENDCHAR
+STARTCHAR uni227F
+ENCODING 8831
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+20
+00
+A0
+50
+ENDCHAR
+STARTCHAR uni2280
+ENCODING 8832
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+C0
+60
+40
+00
+ENDCHAR
+STARTCHAR uni2281
+ENCODING 8833
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+60
+C0
+40
+00
+ENDCHAR
+STARTCHAR propersubset
+ENCODING 8834
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+80
+60
+00
+00
+ENDCHAR
+STARTCHAR propersuperset
+ENCODING 8835
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+20
+C0
+00
+00
+ENDCHAR
+STARTCHAR notsubset
+ENCODING 8836
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+C0
+60
+40
+00
+ENDCHAR
+STARTCHAR uni2285
+ENCODING 8837
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+60
+C0
+40
+00
+ENDCHAR
+STARTCHAR reflexsubset
+ENCODING 8838
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+60
+00
+E0
+00
+ENDCHAR
+STARTCHAR reflexsuperset
+ENCODING 8839
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+C0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2288
+ENCODING 8840
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+60
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni2289
+ENCODING 8841
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+60
+C0
+40
+E0
+40
+ENDCHAR
+STARTCHAR uni228A
+ENCODING 8842
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+60
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni228B
+ENCODING 8843
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+C0
+40
+E0
+80
+ENDCHAR
+STARTCHAR revlogicalnot
+ENCODING 8976
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+80
+00
+00
+ENDCHAR
+STARTCHAR integraltp
+ENCODING 8992
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR integralbt
+ENCODING 8993
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+20
+20
+20
+40
+ENDCHAR
+STARTCHAR uni23BA
+ENCODING 9146
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BB
+ENCODING 9147
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BC
+ENCODING 9148
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni23BD
+ENCODING 9149
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+F0
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 9225
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+70
+20
+20
+ENDCHAR
+STARTCHAR uni240A
+ENCODING 9226
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+E0
+60
+40
+40
+ENDCHAR
+STARTCHAR uni240B
+ENCODING 9227
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+70
+20
+20
+ENDCHAR
+STARTCHAR uni240C
+ENCODING 9228
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+C0
+80
+60
+60
+40
+ENDCHAR
+STARTCHAR uni240D
+ENCODING 9229
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+E0
+50
+60
+50
+ENDCHAR
+STARTCHAR uni2423
+ENCODING 9251
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+90
+F0
+ENDCHAR
+STARTCHAR uni2424
+ENCODING 9252
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+B0
+90
+20
+20
+30
+ENDCHAR
+STARTCHAR SF100000
+ENCODING 9472
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2501
+ENCODING 9473
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F8
+F8
+00
+00
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9474
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR uni2503
+ENCODING 9475
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR uni2504
+ENCODING 9476
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni2505
+ENCODING 9477
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A8
+A8
+00
+00
+ENDCHAR
+STARTCHAR uni2506
+ENCODING 9478
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR uni2507
+ENCODING 9479
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+60
+00
+60
+00
+ENDCHAR
+STARTCHAR uni2508
+ENCODING 9480
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni2509
+ENCODING 9481
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A8
+A8
+00
+00
+ENDCHAR
+STARTCHAR uni250A
+ENCODING 9482
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR uni250B
+ENCODING 9483
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+60
+00
+60
+00
+ENDCHAR
+STARTCHAR SF010000
+ENCODING 9484
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+70
+40
+40
+ENDCHAR
+STARTCHAR uni250D
+ENCODING 9485
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+70
+40
+40
+ENDCHAR
+STARTCHAR uni250E
+ENCODING 9486
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+70
+60
+60
+ENDCHAR
+STARTCHAR uni250F
+ENCODING 9487
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+70
+60
+60
+ENDCHAR
+STARTCHAR SF030000
+ENCODING 9488
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+C0
+40
+40
+ENDCHAR
+STARTCHAR uni2511
+ENCODING 9489
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+C0
+40
+40
+ENDCHAR
+STARTCHAR uni2512
+ENCODING 9490
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+E0
+60
+60
+ENDCHAR
+STARTCHAR uni2513
+ENCODING 9491
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+E0
+60
+60
+ENDCHAR
+STARTCHAR SF020000
+ENCODING 9492
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+70
+00
+00
+ENDCHAR
+STARTCHAR uni2515
+ENCODING 9493
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+70
+00
+00
+ENDCHAR
+STARTCHAR uni2516
+ENCODING 9494
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+00
+00
+ENDCHAR
+STARTCHAR uni2517
+ENCODING 9495
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+70
+00
+00
+ENDCHAR
+STARTCHAR SF040000
+ENCODING 9496
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+C0
+00
+00
+ENDCHAR
+STARTCHAR uni2519
+ENCODING 9497
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+C0
+00
+00
+ENDCHAR
+STARTCHAR uni251A
+ENCODING 9498
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni251B
+ENCODING 9499
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+E0
+00
+00
+ENDCHAR
+STARTCHAR SF080000
+ENCODING 9500
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+70
+40
+40
+ENDCHAR
+STARTCHAR uni251D
+ENCODING 9501
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+70
+40
+40
+ENDCHAR
+STARTCHAR uni251E
+ENCODING 9502
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+40
+40
+ENDCHAR
+STARTCHAR uni251F
+ENCODING 9503
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+70
+60
+60
+ENDCHAR
+STARTCHAR uni2520
+ENCODING 9504
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+60
+60
+ENDCHAR
+STARTCHAR uni2521
+ENCODING 9505
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+70
+40
+40
+ENDCHAR
+STARTCHAR uni2522
+ENCODING 9506
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+70
+60
+60
+ENDCHAR
+STARTCHAR uni2523
+ENCODING 9507
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+70
+60
+60
+ENDCHAR
+STARTCHAR SF090000
+ENCODING 9508
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+C0
+40
+40
+ENDCHAR
+STARTCHAR uni2525
+ENCODING 9509
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+C0
+40
+40
+ENDCHAR
+STARTCHAR uni2526
+ENCODING 9510
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+40
+40
+ENDCHAR
+STARTCHAR uni2527
+ENCODING 9511
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+E0
+60
+60
+ENDCHAR
+STARTCHAR uni2528
+ENCODING 9512
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+60
+60
+ENDCHAR
+STARTCHAR uni2529
+ENCODING 9513
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+E0
+40
+40
+ENDCHAR
+STARTCHAR uni252A
+ENCODING 9514
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+E0
+E0
+60
+60
+ENDCHAR
+STARTCHAR uni252B
+ENCODING 9515
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+E0
+60
+60
+ENDCHAR
+STARTCHAR SF060000
+ENCODING 9516
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni252D
+ENCODING 9517
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni252E
+ENCODING 9518
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni252F
+ENCODING 9519
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2530
+ENCODING 9520
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2531
+ENCODING 9521
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2532
+ENCODING 9522
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2533
+ENCODING 9523
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+F0
+60
+60
+ENDCHAR
+STARTCHAR SF070000
+ENCODING 9524
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2535
+ENCODING 9525
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2536
+ENCODING 9526
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2537
+ENCODING 9527
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2538
+ENCODING 9528
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2539
+ENCODING 9529
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni253A
+ENCODING 9530
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni253B
+ENCODING 9531
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+F0
+00
+00
+ENDCHAR
+STARTCHAR SF050000
+ENCODING 9532
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni253D
+ENCODING 9533
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni253E
+ENCODING 9534
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni253F
+ENCODING 9535
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2540
+ENCODING 9536
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2541
+ENCODING 9537
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2542
+ENCODING 9538
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2543
+ENCODING 9539
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2544
+ENCODING 9540
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2545
+ENCODING 9541
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+E0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2546
+ENCODING 9542
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2547
+ENCODING 9543
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2548
+ENCODING 9544
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2549
+ENCODING 9545
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni254A
+ENCODING 9546
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni254B
+ENCODING 9547
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni254C
+ENCODING 9548
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni254D
+ENCODING 9549
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A0
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni254E
+ENCODING 9550
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+40
+00
+40
+40
+ENDCHAR
+STARTCHAR uni254F
+ENCODING 9551
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+60
+00
+60
+60
+ENDCHAR
+STARTCHAR SF430000
+ENCODING 9552
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+F0
+00
+ENDCHAR
+STARTCHAR SF240000
+ENCODING 9553
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR SF510000
+ENCODING 9554
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+40
+70
+40
+ENDCHAR
+STARTCHAR SF520000
+ENCODING 9555
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+70
+60
+60
+ENDCHAR
+STARTCHAR SF390000
+ENCODING 9556
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+40
+70
+60
+ENDCHAR
+STARTCHAR SF220000
+ENCODING 9557
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+40
+C0
+40
+ENDCHAR
+STARTCHAR SF210000
+ENCODING 9558
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+E0
+60
+60
+ENDCHAR
+STARTCHAR SF250000
+ENCODING 9559
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+20
+E0
+60
+ENDCHAR
+STARTCHAR SF500000
+ENCODING 9560
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+40
+70
+00
+ENDCHAR
+STARTCHAR SF490000
+ENCODING 9561
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+00
+00
+ENDCHAR
+STARTCHAR SF380000
+ENCODING 9562
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+40
+70
+00
+ENDCHAR
+STARTCHAR SF280000
+ENCODING 9563
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+40
+C0
+00
+ENDCHAR
+STARTCHAR SF270000
+ENCODING 9564
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+00
+00
+ENDCHAR
+STARTCHAR SF260000
+ENCODING 9565
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+20
+E0
+00
+ENDCHAR
+STARTCHAR SF360000
+ENCODING 9566
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+40
+70
+40
+ENDCHAR
+STARTCHAR SF370000
+ENCODING 9567
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+60
+60
+ENDCHAR
+STARTCHAR SF420000
+ENCODING 9568
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+40
+70
+60
+ENDCHAR
+STARTCHAR SF190000
+ENCODING 9569
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+40
+C0
+40
+ENDCHAR
+STARTCHAR SF200000
+ENCODING 9570
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+60
+60
+ENDCHAR
+STARTCHAR SF230000
+ENCODING 9571
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+20
+E0
+60
+ENDCHAR
+STARTCHAR SF470000
+ENCODING 9572
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+F0
+40
+ENDCHAR
+STARTCHAR SF480000
+ENCODING 9573
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+60
+60
+ENDCHAR
+STARTCHAR SF410000
+ENCODING 9574
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+F0
+60
+ENDCHAR
+STARTCHAR SF450000
+ENCODING 9575
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+00
+F0
+00
+ENDCHAR
+STARTCHAR SF460000
+ENCODING 9576
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+00
+00
+ENDCHAR
+STARTCHAR SF400000
+ENCODING 9577
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+00
+F0
+00
+ENDCHAR
+STARTCHAR SF540000
+ENCODING 9578
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+40
+F0
+40
+ENDCHAR
+STARTCHAR SF530000
+ENCODING 9579
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+60
+60
+ENDCHAR
+STARTCHAR SF440000
+ENCODING 9580
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+00
+F0
+60
+ENDCHAR
+STARTCHAR uni256D
+ENCODING 9581
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+30
+40
+40
+ENDCHAR
+STARTCHAR uni256E
+ENCODING 9582
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+80
+40
+40
+ENDCHAR
+STARTCHAR uni256F
+ENCODING 9583
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+80
+00
+00
+ENDCHAR
+STARTCHAR uni2570
+ENCODING 9584
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+30
+00
+00
+ENDCHAR
+STARTCHAR uni2571
+ENCODING 9585
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR uni2572
+ENCODING 9586
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+40
+20
+20
+10
+ENDCHAR
+STARTCHAR uni2573
+ENCODING 9587
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+60
+60
+90
+90
+ENDCHAR
+STARTCHAR uni2574
+ENCODING 9588
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+C0
+00
+00
+ENDCHAR
+STARTCHAR uni2575
+ENCODING 9589
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+40
+00
+00
+ENDCHAR
+STARTCHAR uni2576
+ENCODING 9590
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+70
+00
+00
+ENDCHAR
+STARTCHAR uni2577
+ENCODING 9591
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+40
+40
+40
+ENDCHAR
+STARTCHAR uni2578
+ENCODING 9592
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+C0
+00
+00
+ENDCHAR
+STARTCHAR uni2579
+ENCODING 9593
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+60
+00
+00
+ENDCHAR
+STARTCHAR uni257A
+ENCODING 9594
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+70
+00
+00
+ENDCHAR
+STARTCHAR uni257B
+ENCODING 9595
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+60
+60
+60
+ENDCHAR
+STARTCHAR uni257C
+ENCODING 9596
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+30
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni257D
+ENCODING 9597
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+60
+60
+60
+ENDCHAR
+STARTCHAR uni257E
+ENCODING 9598
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni257F
+ENCODING 9599
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+60
+40
+40
+ENDCHAR
+STARTCHAR upblock
+ENCODING 9600
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F8
+F8
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2581
+ENCODING 9601
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+F0
+ENDCHAR
+STARTCHAR uni2582
+ENCODING 9602
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+F8
+ENDCHAR
+STARTCHAR uni2583
+ENCODING 9603
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+F8
+F8
+ENDCHAR
+STARTCHAR dnblock
+ENCODING 9604
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR uni2585
+ENCODING 9605
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR uni2586
+ENCODING 9606
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F8
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR uni2587
+ENCODING 9607
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F8
+F8
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR block
+ENCODING 9608
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F8
+F8
+F8
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR uni2589
+ENCODING 9609
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+F0
+F0
+F0
+F0
+F0
+ENDCHAR
+STARTCHAR uni258A
+ENCODING 9610
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+E0
+E0
+E0
+E0
+E0
+ENDCHAR
+STARTCHAR uni258B
+ENCODING 9611
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+E0
+E0
+E0
+E0
+E0
+ENDCHAR
+STARTCHAR lfblock
+ENCODING 9612
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni258D
+ENCODING 9613
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni258E
+ENCODING 9614
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR uni258F
+ENCODING 9615
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR rtblock
+ENCODING 9616
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR ltshade
+ENCODING 9617
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+80
+20
+80
+20
+ENDCHAR
+STARTCHAR shade
+ENCODING 9618
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A8
+50
+A8
+50
+A8
+50
+ENDCHAR
+STARTCHAR dkshade
+ENCODING 9619
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B8
+E8
+B8
+E8
+B8
+E8
+ENDCHAR
+STARTCHAR uni2594
+ENCODING 9620
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2595
+ENCODING 9621
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR filledbox
+ENCODING 9632
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR H22073
+ENCODING 9633
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR uni25C6
+ENCODING 9670
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+E0
+40
+00
+ENDCHAR
+STARTCHAR spade
+ENCODING 9824
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR club
+ENCODING 9827
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+40
+E0
+00
+ENDCHAR
+STARTCHAR heart
+ENCODING 9829
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+40
+00
+ENDCHAR
+STARTCHAR diamond
+ENCODING 9830
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+40
+00
+00
+ENDCHAR
+STARTCHAR uni2669
+ENCODING 9833
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+C0
+80
+00
+ENDCHAR
+STARTCHAR musicalnote
+ENCODING 9834
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+40
+C0
+80
+00
+ENDCHAR
+STARTCHAR musicalnotedbl
+ENCODING 9835
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+50
+50
+50
+A0
+00
+ENDCHAR
+STARTCHAR uni266C
+ENCODING 9836
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+70
+50
+50
+A0
+00
+ENDCHAR
+STARTCHAR uni266D
+ENCODING 9837
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+E0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR uni266E
+ENCODING 9838
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+A0
+E0
+20
+00
+ENDCHAR
+STARTCHAR uni266F
+ENCODING 9839
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR uniFFFD
+ENCODING 65533
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+90
+D0
+F0
+D0
+F0
+ENDCHAR
+ENDFONT
diff --git a/src/col64/cruft/col64font.hex b/src/col64/cruft/col64font.hex
new file mode 100644
index 0000000..6b88e9b
--- /dev/null
+++ b/src/col64/cruft/col64font.hex
@@ -0,0 +1,920 @@
+0000:A000A000A000
+0020:000000000000
+0021:404040004000
+0022:A0A000000000
+0023:A0F0A0F0A000
+0024:70A06050E000
+0025:009020409000
+0026:40A040A0D000
+0027:202040000000
+0028:204040402000
+0029:402020204000
+002A:A040E040A000
+002B:4040E0404000
+002C:000000204000
+002D:0000F0000000
+002E:000000004000
+002F:202040808000
+0030:6090B0D06000
+0031:40C04040E000
+0032:60902040F000
+0033:E0106010E000
+0034:2060A0F02000
+0035:F080E010E000
+0036:7080E0906000
+0037:F01020404000
+0038:609060906000
+0039:60907010E000
+003A:004000004000
+003B:002000204000
+003C:204080402000
+003D:00F000F00000
+003E:804020408000
+003F:709020002000
+0040:60B0B0806000
+0041:6090F0909000
+0042:E090E090E000
+0043:609080906000
+0044:E0909090E000
+0045:F080E080F000
+0046:F080E0808000
+0047:7080B0906000
+0048:9090F0909000
+0049:E0404040E000
+004A:301010906000
+004B:90A0C0A09000
+004C:80808080F000
+004D:A0F0D0909000
+004E:90D0B0909000
+004F:609090906000
+0050:E090E0808000
+0051:609090A05000
+0052:E090E0A09000
+0053:70806010E000
+0054:F04040404000
+0055:909090906000
+0056:909090A04000
+0057:9090D0F0A000
+0058:909060909000
+0059:909060204000
+005A:F0204080F000
+005B:604040406000
+005C:808040202000
+005D:602020206000
+005E:40A000000000
+005F:00000000F000
+0060:404020000000
+0061:003050907000
+0062:8080E090E000
+0063:007080807000
+0064:101070907000
+0065:006090A07000
+0066:6040E0404000
+0067:709070106000
+0068:8080E0909000
+0069:4000C040E000
+006A:20006020C000
+006B:80A0C0A09000
+006C:C0404040E000
+006D:00A0F0D09000
+006E:00E090909000
+006F:006090906000
+0070:00E090E08000
+0071:007090701000
+0072:00A0D0808000
+0073:0070C030E000
+0074:40E040402000
+0075:009090906000
+0076:009090A04000
+0077:0090D0F0A000
+0078:009060609000
+0079:00906020C000
+007A:00F02040F000
+007B:604080406000
+007C:404040404000
+007D:C0402040C000
+007E:0050A0000000
+007F:B0900090D000
+00A0:000000000000
+00A1:400040404000
+00A2:40E080E04000
+00A3:20406040A000
+00A4:009060609000
+00A5:A040E0404000
+00A6:404000404000
+00A7:60C0A06020C0
+00A8:A00000000000
+00A9:6090D0D09060
+00AA:60A06000E000
+00AB:0050A0500000
+00AC:0000E0200000
+00AD:0000E0000000
+00AE:60F0D0600000
+00AF:E00000000000
+00B0:40A040000000
+00B1:40E04000E000
+00B2:C04080C00000
+00B3:C04080408000
+00B4:204000000000
+00B5:00A0A0A0C080
+00B6:70D0D0505000
+00B7:000040000000
+00B8:000000204000
+00B9:40C040400000
+00BA:40A04000E000
+00BB:00A050A00000
+00BC:808080507010
+00BD:8080B0102030
+00BE:C0408050B010
+00BF:400040806000
+00C0:8040A0E0A000
+00C1:2040A0E0A000
+00C2:C040A0E0A000
+00C3:60C0A0E0A000
+00C4:A040A0E0A000
+00C5:4040A0E0A000
+00C6:70A0F0A0B000
+00C7:40A080A04080
+00C8:80E0C080E000
+00C9:20E0C080E000
+00CA:60E0C080E000
+00CB:A0E0C080E000
+00CC:80E04040E000
+00CD:20E04040E000
+00CE:40E04040E000
+00CF:A0404040E000
+00D0:E050D050E000
+00D1:50A0E0E0A000
+00D2:8040A0A04000
+00D3:2040A0A04000
+00D4:4040A0A04000
+00D5:70E0A0A04000
+00D6:A040A0A04000
+00D7:00A040A00000
+00D8:60A0E0A0C000
+00D9:8040A0A0E000
+00DA:2040A0A0E000
+00DB:4000A0A0E000
+00DC:A000A0A0E000
+00DD:2000A0404000
+00DE:80C0A0C08000
+00DF:40A0C0A0E080
+00E0:804060A06000
+00E1:204060A06000
+00E2:600060A06000
+00E3:50A060A06000
+00E4:A00060A06000
+00E5:400060A06000
+00E6:0070B0A07000
+00E7:0040A0806040
+00E8:8040A0C06000
+00E9:2040A0C06000
+00EA:C040A0C06000
+00EB:A040A0C06000
+00EC:80404040E000
+00ED:20C04040E000
+00EE:40A04040E000
+00EF:A000C040E000
+00F0:A04060A04000
+00F1:50A0C0A0A000
+00F2:804040A04000
+00F3:204040A04000
+00F4:400040A04000
+00F5:E00040A04000
+00F6:A00040A04000
+00F7:4000E0004000
+00F8:0060A0A0C000
+00F9:8040A0A06000
+00FA:2040A0A06000
+00FB:4000A0A06000
+00FC:A000A0A06000
+00FD:2040A0E020C0
+00FE:8080C0A0C080
+00FF:A000A0E020C0
+0100:E040A0E0A000
+0101:E00060A06000
+0102:A040A0E0A000
+0103:A04060A06000
+0104:0040A0E0A020
+0105:000060A06020
+0106:60A080A04000
+0107:2040A0806000
+0108:E0A080A04000
+0109:600060806000
+010A:40E080A04000
+010B:400060806000
+010C:E0A080A04000
+010D:A04060806000
+010E:E0C0A0A0C000
+010F:302060A06000
+0110:C0A0E0A0C000
+0111:602060A06000
+0112:E0E0C080E000
+0113:E040A0C06000
+0114:A0E0C080E000
+0115:A040A0C06000
+0116:40E0C080E000
+0117:4040A0C06000
+0118:E080C080E020
+0119:0040A0C06040
+011A:A0E0C080E000
+011B:A040A0C06000
+011C:606080A06000
+011D:6060A06020C0
+011E:A06080A06000
+011F:A040A06020C0
+0120:406080A06000
+0121:4060A06020C0
+0122:6080A0A04040
+0123:4060A06020C0
+0124:6000A0E0A000
+0125:40A0C0A0A000
+0126:A0E0A0E0A000
+0127:80C0C0A0A000
+0128:50A04040E000
+0129:50A0C040E000
+012A:E000E040E000
+012B:E000C040E000
+012C:A040E040E000
+012D:A040C040E000
+012E:E0404040E020
+012F:4000C040E020
+0130:4000E040E000
+0131:0000C040E000
+0132:80A0A0A02060
+0133:A000A0A02040
+0134:60A020A04000
+0135:40A0002020C0
+0136:A0A0C0A02040
+0137:80A0C0A02040
+0138:00A0A0C0A000
+0139:40808080E000
+013A:20C04040E000
+013B:80808080E020
+013C:C0404040E020
+013D:A0C08080E000
+013E:D0404040E000
+013F:8080A080E000
+0140:C0405040E000
+0141:80A0C080E000
+0142:C060C040E000
+0143:20A0E0A08000
+0144:2040C0A0A000
+0145:20A0E0A08020
+0146:00C0A0A00040
+0147:20A0E0A08000
+0148:A040C0A0A000
+0149:8000C0A0A000
+014A:A0E0E0A02040
+014B:00C0A0A02040
+014C:E040A0A04000
+014D:E00040A04000
+014E:A040A0A04000
+014F:A04040A04000
+0150:A040A0A04000
+0151:A0A040A04000
+0152:50A0B0A07000
+0153:0070B0A07000
+0154:20C0A0C0A000
+0155:2000A0C08000
+0156:C0A0C0A00040
+0157:00A0C0808020
+0158:60C0A0C0A000
+0159:6000A0C08000
+015A:2060C020C000
+015B:2060C020C000
+015C:6060C020C000
+015D:6060C020C000
+015E:60804020C040
+015F:0060C020E040
+0160:6060C020E000
+0161:6060C020C000
+0162:E04040402040
+0163:40E040402040
+0164:A040E0404000
+0165:A040E0402000
+0166:E040E0404000
+0167:E040E0402000
+0168:D020A0A0E000
+0169:50A000A06000
+016A:E000A0A0E000
+016B:E000A0A06000
+016C:A040A0A0E000
+016D:A04000A06000
+016E:4000A0A0E000
+016F:4000A0A06000
+0170:A000A0A0E000
+0171:A000A0A06000
+0172:00A0A0A04020
+0173:00A0A0A06040
+0174:40A0A0E0A000
+0175:4000A0E0E000
+0176:6000A0404000
+0177:4000A0408000
+0178:A000A0404000
+0179:40E04080E000
+017A:40E04080E000
+017B:40E04080E000
+017C:40E04080E000
+017D:A0E04080E000
+017E:A0E04080E000
+017F:2040C0404000
+018F:00C060A04000
+0192:2040E0404080
+0218:60804020C040
+0219:0060C020E040
+021A:E04040400040
+021B:40E040402040
+0259:00C060A04000
+02C6:40A000000000
+02C7:A04000000000
+02C9:E00000000000
+02D8:906000000000
+02D9:400000000000
+02DA:40A040000000
+02DB:0000004080C0
+02DC:50A000000000
+02DD:A0A000000000
+0374:204000000000
+0375:000000004080
+037A:000000004060
+037E:004000004080
+0384:204000000000
+0385:B04000000000
+0386:C0A0E0A0A000
+0387:000040000000
+0388:E0C060406000
+0389:A020E0A0A000
+038A:E0C04040E000
+038C:C0A0A0A04000
+038E:A0A0C0404000
+038F:C0A0A040A000
+0390:B04000402000
+0391:40A0E0A0A000
+0392:C0A0C0A0C000
+0393:E08080808000
+0394:4040A0A0E000
+0395:E080C080E000
+0396:E0204080E000
+0397:A0A0E0A0A000
+0398:40A0E0A04000
+0399:E0404040E000
+039A:A0A0C0A0A000
+039B:4040A0A0A000
+039C:A0E0A0A0A000
+039D:20A0E0A08000
+039E:E0004000E000
+039F:40A0A0A04000
+03A0:E0A0A0A0A000
+03A1:C0A0C0808000
+03A3:E0804080E000
+03A4:E04040404000
+03A5:A0A040404000
+03A6:40E0A0E04000
+03A7:A0A040A0A000
+03A8:A0E0E0404000
+03A9:40A0A040A000
+03AA:A000E040E000
+03AB:A000A0404000
+03AC:408060A06000
+03AD:20C040806000
+03AE:2040C0A02040
+03AF:200040402000
+03B0:B040A0A0C000
+03B1:0050A0A05000
+03B2:40A0C0A0C000
+03B3:00A060404000
+03B4:608040A04000
+03B5:00E0C0806000
+03B6:E04080E02040
+03B7:00C0A0A02040
+03B8:40A0E0A04000
+03B9:004040402000
+03BA:00A0A0C0A000
+03BB:C02060A0A000
+03BC:00A0A0A0C080
+03BD:00A0A0604000
+03BE:60A040806000
+03BF:0040A0A04000
+03C0:00E0A0A0A000
+03C1:0040A0A0C080
+03C2:00608040C000
+03C3:0060C0A04000
+03C4:00E040402000
+03C5:0080A0A0C000
+03C6:0040E0A04040
+03C7:00A04060A000
+03C8:00A0E0E04000
+03C9:00A0A0E0E000
+03CA:A00040402000
+03CB:A000A0A0C000
+03CC:204040A04000
+03CD:2000A0A0C000
+03CE:2000A0E0E000
+0401:A0E0C080E000
+0402:E080C0A0A000
+0403:20E080808000
+0404:6080C0806000
+0405:60804020C000
+0406:E0404040E000
+0407:A0E04040E000
+0408:202020A04000
+0409:E060A0B0B000
+040A:A0A0E0B0B000
+040B:C080C0A0A000
+040C:2080A0C0A000
+040E:A04000A04080
+040F:A0A0A0A0E040
+0410:40A0E0A0A000
+0411:E080C0A0C000
+0412:C0A0C0A0C000
+0413:E08080808000
+0414:E060A0A0E0A0
+0415:E080C080E000
+0416:A0E040E0A000
+0417:C0204020C000
+0418:80A0E0A02000
+0419:6080A0E0A020
+041A:A0A0C0A0A000
+041B:60A0A0A0A000
+041C:A0E0A0A0A000
+041D:A0A0E0A0A000
+041E:40A0A0A04000
+041F:E0A0A0A0A000
+0420:C0A0C0808000
+0421:40A080A04000
+0422:E04040404000
+0423:A0A0A0404080
+0424:40E0A0E04000
+0425:A0A040A0A000
+0426:A0A0A0A0E000
+0427:A0A060202000
+0428:A0A0E0E0E000
+0429:A0A0E0E0F010
+042A:C04060506000
+042B:9090D0B0D000
+042C:8080C0A0C000
+042D:C0206020C000
+042E:A0D0D0D0A000
+042F:60A060A0A000
+0430:0060A0A06000
+0431:6080E0A04000
+0432:00E0C0A0C000
+0433:00E080808000
+0434:0060A0A0E0A0
+0435:0040A0C06000
+0436:00B06060B000
+0437:00E04020C000
+0438:00A0E0E0A000
+0439:A040A0E0A000
+043A:00A0A0C0A000
+043B:0060A0A0A000
+043C:00A0E0A0A000
+043D:00A0E0A0A000
+043E:0040A0A04000
+043F:00E0A0A0A000
+0440:00C0A0C08080
+0441:006080806000
+0442:00E040404000
+0443:00A0A06020C0
+0444:4040A0A04040
+0445:00A04040A000
+0446:00A0A0A0E020
+0447:00A0A0602000
+0448:00A0E0E0E000
+0449:00A0E0E0F010
+044A:00C060506000
+044B:0090D0B0D000
+044C:0080C0A0C000
+044D:00C06020C000
+044E:00A0D0D0A000
+044F:0060A060A000
+0451:A040A0C06000
+0452:80C080C0A020
+0453:2040E0808000
+0454:0060C0806000
+0455:0060C020C000
+0456:4000C040E000
+0457:A000C040E000
+0458:2000202020C0
+0459:0060A0B0B000
+045A:00A0E0B0B000
+045B:80C080C0A000
+045C:2080A0C0A000
+045E:A04000A04080
+045F:00A0A0A0E040
+0490:20E080808000
+0491:0020E0808000
+0492:6040E0404000
+0493:006040E04000
+05D0:00A060C0A000
+05D1:00E02020F000
+05D2:80404040A000
+05D3:00E020202000
+05D4:80E020A0A000
+05D5:402020202000
+05D6:806040404000
+05D7:00E0A0A0A000
+05D8:A0A0A0A0C000
+05D9:C02020000000
+05DA:00E020202020
+05DB:00E02020C000
+05DC:80E020204000
+05DD:8060A0A0E000
+05DE:8060A0A0A000
+05DF:806020202000
+05E0:402020206000
+05E1:8060A0A04000
+05E2:A0A0A060C000
+05E3:00E0A0202020
+05E4:00E0A020E000
+05E5:00A0A0C08080
+05E6:00A04020E000
+05E7:00E020C08080
+05E8:00C020202000
+05E9:00F0D0A0E000
+05EA:8060A0A0A000
+1E02:40E0C0A0C000
+1E03:A080C0A0C000
+1E0A:40C0A0A0C000
+1E0B:A02060A06000
+1E1E:40E080C08000
+1E1F:802040E04000
+1E40:4000E0A0A000
+1E41:4000A0E0A000
+1E56:40C0A0C08000
+1E57:4000C0A0C080
+1E60:40E0C020C000
+1E61:4060C020C000
+1E6A:40E040404000
+1E6B:400040E04020
+1E80:8020A0E0E000
+1E81:8040A0A0E000
+1E82:2080A0E0E000
+1E83:2040A0A0E000
+1E84:A000A0E0E000
+1E85:A000A0E0E000
+1EF2:8020A0404000
+1EF3:8040A0602040
+2010:000060000000
+2011:000060000000
+2012:0000E0000000
+2013:0000E0000000
+2014:0000F0000000
+2015:0000F0000000
+2016:A0A0A0A0A0A0
+2017:000000F000F0
+2018:204060000000
+2019:602040000000
+201A:000000602040
+201B:604020000000
+201C:50A0A0000000
+201D:5050A0000000
+201E:0000005050A0
+201F:A0A050000000
+2020:40E040404000
+2021:40E040E04000
+2022:0040E0400000
+2023:00C0E0C00000
+2024:000000004000
+2025:00000000A000
+2026:00000000B000
+2027:000040000000
+2030:802040803000
+2039:004080400000
+203A:004020400000
+203E:F80000000000
+207F:00C0A0A00000
+20A7:60F060404000
+20AC:2040E0402000
+2116:C0B0B0A0B000
+2122:E04000E0A000
+2126:40A0A040A000
+2127:A040A0A04000
+215B:8080B0205020
+215C:C040B060D020
+215D:C08070A05020
+215E:C040B0A05020
+2190:0040F0400000
+2191:0040E0404000
+2192:0020F0200000
+2193:004040E04000
+2194:0050F0500000
+2195:40E040E04000
+2200:A0A0E0A04000
+2201:40A080A04000
+2202:C02060A04000
+2203:E020E020E000
+2204:F020E060E080
+2205:2060A0A0C080
+2206:4040A0A0E000
+2207:E0A0A0404000
+2208:6080E0806000
+2209:70A0E0A06040
+220A:4080C0804000
+220B:C020E020C000
+220C:D020E060C080
+220D:8040C0408000
+220E:C0C0C0C0C000
+220F:E0A0A0A0A000
+2210:A0A0A0A0E000
+2211:E0804080E000
+2212:0000E0000000
+2213:E00040E04000
+2214:400040E04000
+2215:202040808000
+2216:808040202000
+2217:20A070E05040
+2218:0040A0400000
+2219:0040E0400000
+221A:302020A06000
+221B:D050D0105030
+221C:D0D050105030
+221D:000050E05000
+221E:0020D0B04000
+221F:00008080E000
+2220:00204080E000
+2221:10A040A0F020
+2222:9060A0A06090
+2223:404040404000
+2224:406040C04000
+2225:A0A0A0A0A000
+2226:A0B0E0A0A000
+2227:004040A0A000
+2228:00A0A0404000
+2229:0040A0A0A000
+222A:00A0A0A04000
+222B:204040404080
+222C:50A0A0A0A080
+222D:50D0D0D0D0A0
+222E:2040E0E04080
+222F:50A0E0E0A080
+2230:50D0F0F0D0A0
+2231:2040E0504080
+2232:2040E0C04080
+2233:2040C0E04080
+2234:00004000A000
+2235:0000A0004000
+2236:000040004000
+2237:0000A000A000
+2238:004000E00000
+2239:000020C02000
+223A:A000E000A000
+223B:200050A00040
+223C:000050A00000
+223D:0000A0500000
+223E:0000D0B00000
+223F:004050A02000
+2240:402040402000
+2241:1020B0D04080
+2242:00E000A05000
+2243:0050A000E000
+2244:20D0B040F040
+2245:50A000E000E0
+2246:50A020F040F0
+2247:70A020F040F0
+2248:50A00050A000
+2249:70A04050E080
+224A:40B040B000F0
+224B:40B040B040B0
+224C:A05000E000E0
+224D:A0400040A000
+224E:40A000A04000
+224F:40A000E00000
+2250:4000E000E000
+2251:40E000E00040
+2252:80E000E00020
+2253:20E000E00080
+2254:00B000B00000
+2255:00D000D00000
+2256:00E040E00000
+2257:40E000E00000
+2258:40E000E00000
+2259:40E000E00000
+225A:A0E000E00000
+225B:40E000E00000
+225C:40E000E00000
+225D:4000E000E000
+225E:4000E000E000
+225F:4000E000E000
+2260:20E040E08000
+2261:E000E000E000
+2262:E020E040E080
+2263:E000E000E000
+2264:2040E000E000
+2265:8040E000E000
+2266:2040E000E000
+2267:8040E000E000
+2268:002040E00000
+2269:008040E00000
+226A:0050A0500000
+226B:00A050A00000
+226C:A040A040A000
+226D:20E040E08000
+226E:2060C0608000
+226F:20C060C08000
+2270:2040E040E080
+2271:A060E040E080
+2272:2040E00050A0
+2273:8040E000A050
+2276:60C0208060C0
+2277:C0608020C060
+2278:60C060C060C0
+2279:C060C060C060
+227A:0020C0200000
+227B:008060800000
+227C:20C02000E000
+227D:80608000E000
+227E:20C02000A050
+227F:20C02000A050
+2280:4060C0604000
+2281:40C060C04000
+2282:006080600000
+2283:00C020C00000
+2284:4060C0604000
+2285:40C060C04000
+2286:60806000E000
+2287:C020C000E000
+2288:60A06040E080
+2289:C060C040E040
+228A:60806040E080
+228B:C020C040E080
+2310:0000E0800000
+2320:204040404040
+2321:202020202040
+23BA:F00000000000
+23BB:00F000000000
+23BC:000000F00000
+23BD:0000000000F0
+2409:A0E0A0702020
+240A:8080E0604040
+240B:A0A040702020
+240C:C0C080606040
+240D:E080E0506050
+2423:0000000090F0
+2424:D0B090202030
+2500:000000F00000
+2501:0000F8F80000
+2502:404040404040
+2503:606060606060
+2504:000000A00000
+2505:0000A8A80000
+2506:400040004000
+2507:600060006000
+2508:000000A00000
+2509:0000A8A80000
+250A:400040004000
+250B:600060006000
+250C:000000704040
+250D:000070704040
+250E:000000706060
+250F:000070706060
+2510:000000C04040
+2511:0000C0C04040
+2512:000000E06060
+2513:0000E0E06060
+2514:404040700000
+2515:404070700000
+2516:606060700000
+2517:606070700000
+2518:404040C00000
+2519:4040C0C00000
+251A:606060E00000
+251B:6060E0E00000
+251C:404040704040
+251D:404070704040
+251E:606060704040
+251F:404040706060
+2520:606060706060
+2521:606070704040
+2522:404070706060
+2523:606070706060
+2524:404040C04040
+2525:4040C0C04040
+2526:606060E04040
+2527:404040E06060
+2528:606060E06060
+2529:6060E0E04040
+252A:4040E0E06060
+252B:6060E0E06060
+252C:000000F04040
+252D:0000C0F04040
+252E:000070F04040
+252F:0000F0F04040
+2530:000000F06060
+2531:0000E0F06060
+2532:000070F06060
+2533:0000F0F06060
+2534:404040F00000
+2535:4040C0F00000
+2536:404070F00000
+2537:4040F0F00000
+2538:606060F00000
+2539:6060E0F00000
+253A:606070F00000
+253B:6060F0F00000
+253C:404040F04040
+253D:4040C0F04040
+253E:404070F04040
+253F:4040F0F04040
+2540:606060F04040
+2541:404040F06060
+2542:606060F06060
+2543:6060E0F04040
+2544:606070F04040
+2545:4040E0F06060
+2546:404070F06060
+2547:6060F0F04040
+2548:4040F0F06060
+2549:6060E0F06060
+254A:606070F06060
+254B:6060F0F06060
+254C:000000A00000
+254D:0000A0A00000
+254E:004040004040
+254F:006060006060
+2550:0000F000F000
+2551:606060606060
+2552:000070407040
+2553:000000706060
+2554:000070407060
+2555:0000C040C040
+2556:000000E06060
+2557:0000E020E060
+2558:404070407000
+2559:606060700000
+255A:606070407000
+255B:4040C040C000
+255C:606060E00000
+255D:6060E020E000
+255E:404070407040
+255F:606060706060
+2560:606070407060
+2561:4040C040C040
+2562:606060E06060
+2563:6060E020E060
+2564:0000F000F040
+2565:000000F06060
+2566:0000F000F060
+2567:4040F000F000
+2568:606060F00000
+2569:6060F000F000
+256A:4040F040F040
+256B:606060F06060
+256C:6060F000F060
+256D:000000304040
+256E:000000804040
+256F:404040800000
+2570:404040300000
+2571:102020404080
+2572:804040202010
+2573:909060609090
+2574:000000C00000
+2575:404040400000
+2576:000000700000
+2577:000000404040
+2578:0000C0C00000
+2579:606060600000
+257A:000070700000
+257B:000000606060
+257C:000030F00000
+257D:404040606060
+257E:0000C0F00000
+257F:606060604040
+2580:F8F8F8000000
+2581:0000000000F0
+2582:0000000000F8
+2583:00000000F8F8
+2584:000000F8F8F8
+2585:000000F8F8F8
+2586:0000F8F8F8F8
+2587:00F8F8F8F8F8
+2588:F8F8F8F8F8F8
+2589:F0F0F0F0F0F0
+258A:E0E0E0E0E0E0
+258B:E0E0E0E0E0E0
+258C:C0C0C0C0C0C0
+258D:C0C0C0C0C0C0
+258E:808080808080
+258F:808080808080
+2590:303030303030
+2591:802080208020
+2592:A850A850A850
+2593:B8E8B8E8B8E8
+2594:F80000000000
+2595:101010101010
+25A0:0000E0E0E000
+25A1:0000E0A0E000
+25C6:0040E0E04000
+2660:40E0E040E000
+2663:0040A040E000
+2665:00A0E0E04000
+2666:0040E0400000
+2669:404040C08000
+266A:406040C08000
+266B:70505050A000
+266C:70705050A000
+266D:8080E0A0C000
+266E:80E0A0E02000
+266F:A0E0A0E0A000
+FFFD:F090D0F0D0F0
diff --git a/src/col64/cruft/col64font_almost.bdf b/src/col64/cruft/col64font_almost.bdf
new file mode 100644
index 0000000..9ff776c
--- /dev/null
+++ b/src/col64/cruft/col64font_almost.bdf
@@ -0,0 +1,11994 @@
+STARTFONT 2.1
+COMMENT Contributed by Janne V. Kujala <jvk@iki.fi>
+COMMENT $Id: 4x6.bdf,v 1.5 2002-08-26 18:05:49+01 mgk25 Rel $
+COMMENT Send bug reports to Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
+FONT -Misc-Fixed-Medium-R-Normal--6-60-75-75-C-40-ISO10646-1
+SIZE 6 75 75
+FONTBOUNDINGBOX 4 6 0 -1
+STARTPROPERTIES 23
+FONTNAME_REGISTRY ""
+FOUNDRY "Misc"
+FAMILY_NAME "Fixed"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 6
+POINT_SIZE 60
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "C"
+AVERAGE_WIDTH 40
+CHARSET_REGISTRY "ISO10646"
+CHARSET_ENCODING "1"
+FONT_ASCENT 5
+FONT_DESCENT 1
+DESTINATION 1
+COPYRIGHT "Public domain font. Share and enjoy."
+CAP_HEIGHT 5
+X_HEIGHT 4
+DEFAULT_CHAR 0
+_GBDFED_INFO "Edited with gbdfed 1.4."
+ENDPROPERTIES
+CHARS 920
+STARTCHAR char0
+ENCODING 0
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+00
+A0
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 32
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+F0
+A0
+F0
+A0
+00
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+60
+50
+E0
+00
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+20
+40
+90
+00
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+A0
+D0
+00
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+20
+20
+20
+40
+00
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+A0
+00
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+20
+40
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 45
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+40
+00
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+40
+80
+80
+00
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+B0
+D0
+60
+00
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+20
+40
+F0
+00
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+10
+60
+10
+E0
+00
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+A0
+F0
+20
+00
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+80
+E0
+10
+E0
+00
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+80
+E0
+90
+60
+00
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+10
+20
+40
+40
+00
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+60
+90
+60
+00
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+70
+10
+E0
+00
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+00
+00
+40
+00
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+00
+20
+40
+00
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+80
+40
+20
+00
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F0
+00
+F0
+00
+00
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+20
+40
+80
+00
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+90
+20
+00
+20
+00
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+B0
+B0
+80
+60
+00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+F0
+90
+90
+00
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+90
+E0
+90
+E0
+00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+80
+90
+60
+00
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+90
+90
+90
+E0
+00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+80
+E0
+80
+F0
+00
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+80
+E0
+80
+80
+00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+80
+B0
+90
+60
+00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+F0
+90
+90
+00
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+30
+10
+10
+90
+60
+00
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+A0
+C0
+A0
+90
+00
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+80
+F0
+00
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+F0
+D0
+90
+90
+00
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+D0
+B0
+90
+90
+00
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+90
+E0
+80
+80
+00
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+90
+A0
+50
+00
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+90
+E0
+A0
+90
+00
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+80
+60
+10
+E0
+00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+90
+A0
+40
+00
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+D0
+F0
+A0
+00
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+60
+90
+90
+00
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+60
+40
+40
+00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+20
+40
+80
+F0
+00
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+40
+40
+60
+00
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+40
+20
+20
+00
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+20
+20
+20
+60
+00
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+F0
+00
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+10
+70
+90
+70
+00
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+E0
+90
+E0
+00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+80
+80
+70
+00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+10
+70
+90
+70
+00
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+90
+A0
+70
+00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+90
+70
+10
+60
+00
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+E0
+90
+90
+00
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+60
+20
+C0
+00
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+C0
+A0
+90
+00
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+F0
+D0
+90
+00
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+90
+E0
+80
+00
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+90
+70
+10
+00
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+D0
+80
+80
+00
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+C0
+30
+E0
+00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+90
+A0
+40
+00
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+D0
+F0
+A0
+00
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+60
+60
+90
+00
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+60
+20
+C0
+00
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F0
+20
+40
+F0
+00
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+80
+40
+60
+00
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+20
+40
+C0
+00
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+00
+00
+00
+ENDCHAR
+STARTCHAR char127
+ENCODING 127
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B0
+90
+00
+90
+D0
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 160
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+80
+E0
+40
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+60
+40
+A0
+00
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+60
+60
+90
+00
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+00
+40
+40
+00
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR dieresis
+ENCODING 168
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+D0
+D0
+90
+60
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+60
+00
+E0
+00
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+50
+00
+00
+ENDCHAR
+STARTCHAR logicalnot
+ENCODING 172
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+20
+00
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+F0
+D0
+60
+00
+00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+00
+E0
+00
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+80
+C0
+00
+00
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+80
+40
+80
+00
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+D0
+D0
+50
+50
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+20
+40
+00
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+40
+40
+00
+00
+ENDCHAR
+STARTCHAR ordmasculine
+ENCODING 186
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+00
+E0
+00
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+50
+A0
+00
+00
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+50
+70
+10
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+B0
+10
+20
+30
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+80
+50
+B0
+10
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+80
+60
+00
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Adieresis
+ENCODING 196
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+F0
+A0
+B0
+00
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+80
+A0
+40
+80
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Edieresis
+ENCODING 203
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Idieresis
+ENCODING 207
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Eth
+ENCODING 208
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+50
+D0
+50
+E0
+00
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+E0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+E0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Odieresis
+ENCODING 214
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+40
+A0
+00
+00
+ENDCHAR
+STARTCHAR Oslash
+ENCODING 216
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+E0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Udieresis
+ENCODING 220
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR Thorn
+ENCODING 222
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+C0
+A0
+C0
+80
+00
+ENDCHAR
+STARTCHAR germandbls
+ENCODING 223
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+C0
+A0
+E0
+80
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR adieresis
+ENCODING 228
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+B0
+A0
+70
+00
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+80
+60
+40
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR edieresis
+ENCODING 235
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR idieresis
+ENCODING 239
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+60
+A0
+40
+00
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR odieresis
+ENCODING 246
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR divide
+ENCODING 247
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+40
+00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR udieresis
+ENCODING 252
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+E0
+20
+C0
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+C0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR ydieresis
+ENCODING 255
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+E0
+20
+C0
+ENDCHAR
+STARTCHAR Amacron
+ENCODING 256
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR amacron
+ENCODING 257
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR Abreve
+ENCODING 258
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR abreve
+ENCODING 259
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR Aogonek
+ENCODING 260
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+E0
+A0
+20
+ENDCHAR
+STARTCHAR aogonek
+ENCODING 261
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+60
+A0
+60
+20
+ENDCHAR
+STARTCHAR Cacute
+ENCODING 262
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR cacute
+ENCODING 263
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+80
+60
+00
+ENDCHAR
+STARTCHAR Ccircumflex
+ENCODING 264
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR ccircumflex
+ENCODING 265
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+60
+80
+60
+00
+ENDCHAR
+STARTCHAR Cdotaccent
+ENCODING 266
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR cdotaccent
+ENCODING 267
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+60
+80
+60
+00
+ENDCHAR
+STARTCHAR Ccaron
+ENCODING 268
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR ccaron
+ENCODING 269
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+60
+80
+60
+00
+ENDCHAR
+STARTCHAR Dcaron
+ENCODING 270
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+C0
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR dcaron
+ENCODING 271
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+30
+20
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR Dcroat
+ENCODING 272
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+E0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR dcroat
+ENCODING 273
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+20
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR Emacron
+ENCODING 274
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR emacron
+ENCODING 275
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR Ebreve
+ENCODING 276
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR ebreve
+ENCODING 277
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR Edotaccent
+ENCODING 278
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR edotaccent
+ENCODING 279
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR Eogonek
+ENCODING 280
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+80
+E0
+20
+ENDCHAR
+STARTCHAR eogonek
+ENCODING 281
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+C0
+60
+40
+ENDCHAR
+STARTCHAR Ecaron
+ENCODING 282
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR ecaron
+ENCODING 283
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR Gcircumflex
+ENCODING 284
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+80
+A0
+60
+00
+ENDCHAR
+STARTCHAR gcircumflex
+ENCODING 285
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR Gbreve
+ENCODING 286
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+60
+80
+A0
+60
+00
+ENDCHAR
+STARTCHAR gbreve
+ENCODING 287
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR Gdotaccent
+ENCODING 288
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+80
+A0
+60
+00
+ENDCHAR
+STARTCHAR gdotaccent
+ENCODING 289
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR Gcommaaccent
+ENCODING 290
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+A0
+A0
+40
+40
+ENDCHAR
+STARTCHAR gcommaaccent
+ENCODING 291
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR Hcircumflex
+ENCODING 292
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR hcircumflex
+ENCODING 293
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Hbar
+ENCODING 294
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR hbar
+ENCODING 295
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+C0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Itilde
+ENCODING 296
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR itilde
+ENCODING 297
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Imacron
+ENCODING 298
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR imacron
+ENCODING 299
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Ibreve
+ENCODING 300
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR ibreve
+ENCODING 301
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Iogonek
+ENCODING 302
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+E0
+20
+ENDCHAR
+STARTCHAR iogonek
+ENCODING 303
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+C0
+40
+E0
+20
+ENDCHAR
+STARTCHAR Idotaccent
+ENCODING 304
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR dotlessi
+ENCODING 305
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR IJ
+ENCODING 306
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+A0
+A0
+20
+60
+ENDCHAR
+STARTCHAR ij
+ENCODING 307
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+20
+40
+ENDCHAR
+STARTCHAR Jcircumflex
+ENCODING 308
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+20
+A0
+40
+00
+ENDCHAR
+STARTCHAR jcircumflex
+ENCODING 309
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+20
+20
+C0
+ENDCHAR
+STARTCHAR Kcommaaccent
+ENCODING 310
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+C0
+A0
+20
+40
+ENDCHAR
+STARTCHAR kcommaaccent
+ENCODING 311
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+C0
+A0
+20
+40
+ENDCHAR
+STARTCHAR kgreenlandic
+ENCODING 312
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR Lacute
+ENCODING 313
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+80
+80
+80
+E0
+00
+ENDCHAR
+STARTCHAR lacute
+ENCODING 314
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Lcommaaccent
+ENCODING 315
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+80
+E0
+20
+ENDCHAR
+STARTCHAR lcommaaccent
+ENCODING 316
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+40
+40
+E0
+20
+ENDCHAR
+STARTCHAR Lcaron
+ENCODING 317
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+C0
+80
+80
+E0
+00
+ENDCHAR
+STARTCHAR lcaron
+ENCODING 318
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Ldot
+ENCODING 319
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+A0
+80
+E0
+00
+ENDCHAR
+STARTCHAR ldot
+ENCODING 320
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+50
+40
+E0
+00
+ENDCHAR
+STARTCHAR Lslash
+ENCODING 321
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR lslash
+ENCODING 322
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+60
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Nacute
+ENCODING 323
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+E0
+A0
+80
+00
+ENDCHAR
+STARTCHAR nacute
+ENCODING 324
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Ncommaaccent
+ENCODING 325
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+E0
+A0
+80
+20
+ENDCHAR
+STARTCHAR ncommaaccent
+ENCODING 326
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+A0
+00
+40
+ENDCHAR
+STARTCHAR Ncaron
+ENCODING 327
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+E0
+A0
+80
+00
+ENDCHAR
+STARTCHAR ncaron
+ENCODING 328
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR napostrophe
+ENCODING 329
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+00
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Eng
+ENCODING 330
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+E0
+A0
+20
+40
+ENDCHAR
+STARTCHAR eng
+ENCODING 331
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+A0
+20
+40
+ENDCHAR
+STARTCHAR Omacron
+ENCODING 332
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR omacron
+ENCODING 333
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR Obreve
+ENCODING 334
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR obreve
+ENCODING 335
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR Ohungarumlaut
+ENCODING 336
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR ohungarumlaut
+ENCODING 337
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR OE
+ENCODING 338
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+B0
+A0
+70
+00
+ENDCHAR
+STARTCHAR oe
+ENCODING 339
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+B0
+A0
+70
+00
+ENDCHAR
+STARTCHAR Racute
+ENCODING 340
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR racute
+ENCODING 341
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+A0
+C0
+80
+00
+ENDCHAR
+STARTCHAR Rcommaaccent
+ENCODING 342
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+A0
+00
+40
+ENDCHAR
+STARTCHAR rcommaaccent
+ENCODING 343
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+C0
+80
+80
+20
+ENDCHAR
+STARTCHAR Rcaron
+ENCODING 344
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR rcaron
+ENCODING 345
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+A0
+C0
+80
+00
+ENDCHAR
+STARTCHAR Sacute
+ENCODING 346
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR sacute
+ENCODING 347
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR Scircumflex
+ENCODING 348
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR scircumflex
+ENCODING 349
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR Scedilla
+ENCODING 350
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+40
+20
+C0
+40
+ENDCHAR
+STARTCHAR scedilla
+ENCODING 351
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+20
+E0
+40
+ENDCHAR
+STARTCHAR Scaron
+ENCODING 352
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+C0
+20
+E0
+00
+ENDCHAR
+STARTCHAR scaron
+ENCODING 353
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 354
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+20
+40
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 355
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+20
+40
+ENDCHAR
+STARTCHAR Tcaron
+ENCODING 356
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR tcaron
+ENCODING 357
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+20
+00
+ENDCHAR
+STARTCHAR Tbar
+ENCODING 358
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR tbar
+ENCODING 359
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+E0
+40
+20
+00
+ENDCHAR
+STARTCHAR Utilde
+ENCODING 360
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+20
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR utilde
+ENCODING 361
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+00
+A0
+60
+00
+ENDCHAR
+STARTCHAR Umacron
+ENCODING 362
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR umacron
+ENCODING 363
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR Ubreve
+ENCODING 364
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR ubreve
+ENCODING 365
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+A0
+60
+00
+ENDCHAR
+STARTCHAR Uring
+ENCODING 366
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR uring
+ENCODING 367
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR Uhungarumlaut
+ENCODING 368
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR uhungarumlaut
+ENCODING 369
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR Uogonek
+ENCODING 370
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+40
+20
+ENDCHAR
+STARTCHAR uogonek
+ENCODING 371
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+60
+40
+ENDCHAR
+STARTCHAR Wcircumflex
+ENCODING 372
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR wcircumflex
+ENCODING 373
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR Ycircumflex
+ENCODING 374
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR ycircumflex
+ENCODING 375
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+40
+80
+00
+ENDCHAR
+STARTCHAR Ydieresis
+ENCODING 376
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR Zacute
+ENCODING 377
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR zacute
+ENCODING 378
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR Zdotaccent
+ENCODING 379
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR zdotaccent
+ENCODING 380
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR Zcaron
+ENCODING 381
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR zcaron
+ENCODING 382
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR longs
+ENCODING 383
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+C0
+40
+40
+00
+ENDCHAR
+STARTCHAR uni018F
+ENCODING 399
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+60
+A0
+40
+00
+ENDCHAR
+STARTCHAR florin
+ENCODING 402
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+40
+40
+80
+ENDCHAR
+STARTCHAR Scommaaccent
+ENCODING 536
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+40
+20
+C0
+40
+ENDCHAR
+STARTCHAR scommaaccent
+ENCODING 537
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+20
+E0
+40
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 538
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+00
+40
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 539
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+20
+40
+ENDCHAR
+STARTCHAR uni0259
+ENCODING 601
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+60
+A0
+40
+00
+ENDCHAR
+STARTCHAR circumflex
+ENCODING 710
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR caron
+ENCODING 711
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR macron
+ENCODING 713
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR breve
+ENCODING 728
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dotaccent
+ENCODING 729
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ring
+ENCODING 730
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR ogonek
+ENCODING 731
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+40
+80
+C0
+ENDCHAR
+STARTCHAR tilde
+ENCODING 732
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR hungarumlaut
+ENCODING 733
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0374
+ENCODING 884
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0375
+ENCODING 885
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+40
+80
+ENDCHAR
+STARTCHAR uni037A
+ENCODING 890
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+40
+60
+ENDCHAR
+STARTCHAR uni037E
+ENCODING 894
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+00
+00
+40
+80
+ENDCHAR
+STARTCHAR tonos
+ENCODING 900
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dieresistonos
+ENCODING 901
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B0
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Alphatonos
+ENCODING 902
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR anoteleia
+ENCODING 903
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR Epsilontonos
+ENCODING 904
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+C0
+60
+40
+60
+00
+ENDCHAR
+STARTCHAR Etatonos
+ENCODING 905
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+20
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Iotatonos
+ENCODING 906
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+C0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Omicrontonos
+ENCODING 908
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Upsilontonos
+ENCODING 910
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+C0
+40
+40
+00
+ENDCHAR
+STARTCHAR Omegatonos
+ENCODING 911
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+A0
+40
+A0
+00
+ENDCHAR
+STARTCHAR iotadieresistonos
+ENCODING 912
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B0
+40
+00
+40
+20
+00
+ENDCHAR
+STARTCHAR Alpha
+ENCODING 913
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Beta
+ENCODING 914
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR Gamma
+ENCODING 915
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR Delta
+ENCODING 916
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Epsilon
+ENCODING 917
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Zeta
+ENCODING 918
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+20
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR Eta
+ENCODING 919
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Theta
+ENCODING 920
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+E0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Iota
+ENCODING 921
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Kappa
+ENCODING 922
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Lambda
+ENCODING 923
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Mu
+ENCODING 924
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Nu
+ENCODING 925
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+E0
+A0
+80
+00
+ENDCHAR
+STARTCHAR Xi
+ENCODING 926
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+40
+00
+E0
+00
+ENDCHAR
+STARTCHAR Omicron
+ENCODING 927
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Pi
+ENCODING 928
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Rho
+ENCODING 929
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+80
+80
+00
+ENDCHAR
+STARTCHAR Sigma
+ENCODING 931
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR Tau
+ENCODING 932
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR Upsilon
+ENCODING 933
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR Phi
+ENCODING 934
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+A0
+E0
+40
+00
+ENDCHAR
+STARTCHAR Chi
+ENCODING 935
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Psi
+ENCODING 936
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR Omega
+ENCODING 937
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+40
+A0
+00
+ENDCHAR
+STARTCHAR Iotadieresis
+ENCODING 938
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Upsilondieresis
+ENCODING 939
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR alphatonos
+ENCODING 940
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+80
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR epsilontonos
+ENCODING 941
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+40
+80
+60
+00
+ENDCHAR
+STARTCHAR etatonos
+ENCODING 942
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+C0
+A0
+20
+40
+ENDCHAR
+STARTCHAR iotatonos
+ENCODING 943
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR upsilondieresistonos
+ENCODING 944
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B0
+40
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR alpha
+ENCODING 945
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+A0
+50
+00
+ENDCHAR
+STARTCHAR beta
+ENCODING 946
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR gamma
+ENCODING 947
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+60
+40
+40
+00
+ENDCHAR
+STARTCHAR delta
+ENCODING 948
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR epsilon
+ENCODING 949
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+C0
+80
+60
+00
+ENDCHAR
+STARTCHAR zeta
+ENCODING 950
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+80
+E0
+20
+40
+ENDCHAR
+STARTCHAR eta
+ENCODING 951
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+A0
+20
+40
+ENDCHAR
+STARTCHAR theta
+ENCODING 952
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+E0
+A0
+40
+00
+ENDCHAR
+STARTCHAR iota
+ENCODING 953
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR kappa
+ENCODING 954
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR lambda
+ENCODING 955
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+60
+A0
+A0
+00
+ENDCHAR
+STARTCHAR mu
+ENCODING 956
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR nu
+ENCODING 957
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+60
+40
+00
+ENDCHAR
+STARTCHAR xi
+ENCODING 958
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+40
+80
+60
+00
+ENDCHAR
+STARTCHAR omicron
+ENCODING 959
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR pi
+ENCODING 960
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR rho
+ENCODING 961
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR sigma1
+ENCODING 962
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+80
+40
+C0
+00
+ENDCHAR
+STARTCHAR sigma
+ENCODING 963
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+A0
+40
+00
+ENDCHAR
+STARTCHAR tau
+ENCODING 964
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR upsilon
+ENCODING 965
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+80
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR phi
+ENCODING 966
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+A0
+40
+40
+ENDCHAR
+STARTCHAR chi
+ENCODING 967
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+40
+60
+A0
+00
+ENDCHAR
+STARTCHAR psi
+ENCODING 968
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+40
+00
+ENDCHAR
+STARTCHAR omega
+ENCODING 969
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR iotadieresis
+ENCODING 970
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR upsilondieresis
+ENCODING 971
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR omicrontonos
+ENCODING 972
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR upsilontonos
+ENCODING 973
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR omegatonos
+ENCODING 974
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR afii10023
+ENCODING 1025
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR afii10051
+ENCODING 1026
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10052
+ENCODING 1027
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10053
+ENCODING 1028
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+C0
+80
+60
+00
+ENDCHAR
+STARTCHAR afii10054
+ENCODING 1029
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+40
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10055
+ENCODING 1030
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR afii10056
+ENCODING 1031
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR afii10057
+ENCODING 1032
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+20
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10058
+ENCODING 1033
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+60
+A0
+B0
+B0
+00
+ENDCHAR
+STARTCHAR afii10059
+ENCODING 1034
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+B0
+B0
+00
+ENDCHAR
+STARTCHAR afii10060
+ENCODING 1035
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+80
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10061
+ENCODING 1036
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+80
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii10062
+ENCODING 1038
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+A0
+40
+80
+ENDCHAR
+STARTCHAR afii10145
+ENCODING 1039
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+E0
+40
+ENDCHAR
+STARTCHAR afii10017
+ENCODING 1040
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10018
+ENCODING 1041
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10019
+ENCODING 1042
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10020
+ENCODING 1043
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10021
+ENCODING 1044
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+60
+A0
+A0
+E0
+A0
+ENDCHAR
+STARTCHAR afii10022
+ENCODING 1045
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR afii10024
+ENCODING 1046
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+40
+E0
+A0
+00
+ENDCHAR
+STARTCHAR afii10025
+ENCODING 1047
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+40
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10026
+ENCODING 1048
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+E0
+A0
+20
+00
+ENDCHAR
+STARTCHAR afii10027
+ENCODING 1049
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+A0
+E0
+A0
+20
+ENDCHAR
+STARTCHAR afii10028
+ENCODING 1050
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10029
+ENCODING 1051
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10030
+ENCODING 1052
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10031
+ENCODING 1053
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10032
+ENCODING 1054
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10033
+ENCODING 1055
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10034
+ENCODING 1056
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10035
+ENCODING 1057
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10036
+ENCODING 1058
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR afii10037
+ENCODING 1059
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+40
+40
+80
+ENDCHAR
+STARTCHAR afii10038
+ENCODING 1060
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+A0
+E0
+40
+00
+ENDCHAR
+STARTCHAR afii10039
+ENCODING 1061
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10040
+ENCODING 1062
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR afii10041
+ENCODING 1063
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+60
+20
+20
+00
+ENDCHAR
+STARTCHAR afii10042
+ENCODING 1064
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR afii10043
+ENCODING 1065
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+E0
+F0
+10
+ENDCHAR
+STARTCHAR afii10044
+ENCODING 1066
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+60
+50
+60
+00
+ENDCHAR
+STARTCHAR afii10045
+ENCODING 1067
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+D0
+B0
+D0
+00
+ENDCHAR
+STARTCHAR afii10046
+ENCODING 1068
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10047
+ENCODING 1069
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+60
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10048
+ENCODING 1070
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+D0
+D0
+D0
+A0
+00
+ENDCHAR
+STARTCHAR afii10049
+ENCODING 1071
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+60
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10065
+ENCODING 1072
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR afii10066
+ENCODING 1073
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+E0
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10067
+ENCODING 1074
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10068
+ENCODING 1075
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10069
+ENCODING 1076
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+A0
+E0
+A0
+ENDCHAR
+STARTCHAR afii10070
+ENCODING 1077
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR afii10072
+ENCODING 1078
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+B0
+60
+60
+B0
+00
+ENDCHAR
+STARTCHAR afii10073
+ENCODING 1079
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+40
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10074
+ENCODING 1080
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR afii10075
+ENCODING 1081
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR afii10076
+ENCODING 1082
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii10077
+ENCODING 1083
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10078
+ENCODING 1084
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10079
+ENCODING 1085
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10080
+ENCODING 1086
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10081
+ENCODING 1087
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10082
+ENCODING 1088
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+C0
+80
+80
+ENDCHAR
+STARTCHAR afii10083
+ENCODING 1089
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+80
+80
+60
+00
+ENDCHAR
+STARTCHAR afii10084
+ENCODING 1090
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR afii10085
+ENCODING 1091
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR afii10086
+ENCODING 1092
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+40
+40
+ENDCHAR
+STARTCHAR afii10087
+ENCODING 1093
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+40
+40
+A0
+00
+ENDCHAR
+STARTCHAR afii10088
+ENCODING 1094
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+E0
+20
+ENDCHAR
+STARTCHAR afii10089
+ENCODING 1095
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+60
+20
+00
+ENDCHAR
+STARTCHAR afii10090
+ENCODING 1096
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR afii10091
+ENCODING 1097
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+F0
+10
+ENDCHAR
+STARTCHAR afii10092
+ENCODING 1098
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+60
+50
+60
+00
+ENDCHAR
+STARTCHAR afii10093
+ENCODING 1099
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+D0
+B0
+D0
+00
+ENDCHAR
+STARTCHAR afii10094
+ENCODING 1100
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+80
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10095
+ENCODING 1101
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+60
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10096
+ENCODING 1102
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+D0
+D0
+A0
+00
+ENDCHAR
+STARTCHAR afii10097
+ENCODING 1103
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+60
+A0
+00
+ENDCHAR
+STARTCHAR afii10071
+ENCODING 1105
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR afii10099
+ENCODING 1106
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+C0
+80
+C0
+A0
+20
+ENDCHAR
+STARTCHAR afii10100
+ENCODING 1107
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10101
+ENCODING 1108
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+80
+60
+00
+ENDCHAR
+STARTCHAR afii10102
+ENCODING 1109
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10103
+ENCODING 1110
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR afii10104
+ENCODING 1111
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR afii10105
+ENCODING 1112
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+20
+20
+20
+C0
+ENDCHAR
+STARTCHAR afii10106
+ENCODING 1113
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+B0
+B0
+00
+ENDCHAR
+STARTCHAR afii10107
+ENCODING 1114
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+B0
+B0
+00
+ENDCHAR
+STARTCHAR afii10108
+ENCODING 1115
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+C0
+80
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii10109
+ENCODING 1116
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+80
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii10110
+ENCODING 1118
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+A0
+40
+80
+ENDCHAR
+STARTCHAR afii10193
+ENCODING 1119
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+E0
+40
+ENDCHAR
+STARTCHAR afii10050
+ENCODING 1168
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10098
+ENCODING 1169
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+E0
+80
+80
+00
+ENDCHAR
+STARTCHAR uni0492
+ENCODING 1170
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR uni0493
+ENCODING 1171
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR afii57664
+ENCODING 1488
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+60
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii57665
+ENCODING 1489
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+20
+F0
+00
+ENDCHAR
+STARTCHAR afii57666
+ENCODING 1490
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+40
+40
+A0
+00
+ENDCHAR
+STARTCHAR afii57667
+ENCODING 1491
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR afii57668
+ENCODING 1492
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+20
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii57669
+ENCODING 1493
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+20
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR afii57670
+ENCODING 1494
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR afii57671
+ENCODING 1495
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii57672
+ENCODING 1496
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii57673
+ENCODING 1497
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57674
+ENCODING 1498
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR afii57675
+ENCODING 1499
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii57676
+ENCODING 1500
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+20
+20
+40
+00
+ENDCHAR
+STARTCHAR afii57677
+ENCODING 1501
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR afii57678
+ENCODING 1502
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii57679
+ENCODING 1503
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR afii57680
+ENCODING 1504
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+20
+20
+20
+60
+00
+ENDCHAR
+STARTCHAR afii57681
+ENCODING 1505
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii57682
+ENCODING 1506
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+60
+C0
+00
+ENDCHAR
+STARTCHAR afii57683
+ENCODING 1507
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+20
+20
+20
+ENDCHAR
+STARTCHAR afii57684
+ENCODING 1508
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+20
+E0
+00
+ENDCHAR
+STARTCHAR afii57685
+ENCODING 1509
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+C0
+80
+80
+ENDCHAR
+STARTCHAR afii57686
+ENCODING 1510
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+40
+20
+E0
+00
+ENDCHAR
+STARTCHAR afii57687
+ENCODING 1511
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+C0
+80
+80
+ENDCHAR
+STARTCHAR afii57688
+ENCODING 1512
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR afii57689
+ENCODING 1513
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F0
+D0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR afii57690
+ENCODING 1514
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR uni1E02
+ENCODING 7682
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR uni1E03
+ENCODING 7683
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+80
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR uni1E0A
+ENCODING 7690
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR uni1E0B
+ENCODING 7691
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+20
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR uni1E1E
+ENCODING 7710
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+80
+C0
+80
+00
+ENDCHAR
+STARTCHAR uni1E1F
+ENCODING 7711
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR uni1E40
+ENCODING 7744
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR uni1E41
+ENCODING 7745
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR uni1E56
+ENCODING 7766
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+A0
+C0
+80
+00
+ENDCHAR
+STARTCHAR uni1E57
+ENCODING 7767
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+C0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR uni1E60
+ENCODING 7776
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR uni1E61
+ENCODING 7777
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR uni1E6A
+ENCODING 7786
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR uni1E6B
+ENCODING 7787
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+E0
+40
+20
+ENDCHAR
+STARTCHAR Wgrave
+ENCODING 7808
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR wgrave
+ENCODING 7809
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Wacute
+ENCODING 7810
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+80
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR wacute
+ENCODING 7811
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Wdieresis
+ENCODING 7812
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR wdieresis
+ENCODING 7813
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR Ygrave
+ENCODING 7922
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR ygrave
+ENCODING 7923
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+60
+20
+40
+ENDCHAR
+STARTCHAR uni2010
+ENCODING 8208
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2011
+ENCODING 8209
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR figuredash
+ENCODING 8210
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR endash
+ENCODING 8211
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR emdash
+ENCODING 8212
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii00208
+ENCODING 8213
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2016
+ENCODING 8214
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+A0
+A0
+ENDCHAR
+STARTCHAR underscoredbl
+ENCODING 8215
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+00
+F0
+ENDCHAR
+STARTCHAR quoteleft
+ENCODING 8216
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR quoteright
+ENCODING 8217
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+20
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR quotesinglbase
+ENCODING 8218
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+60
+20
+40
+ENDCHAR
+STARTCHAR quotereversed
+ENCODING 8219
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblleft
+ENCODING 8220
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+A0
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblright
+ENCODING 8221
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+50
+A0
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblbase
+ENCODING 8222
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+50
+50
+A0
+ENDCHAR
+STARTCHAR uni201F
+ENCODING 8223
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR dagger
+ENCODING 8224
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR daggerdbl
+ENCODING 8225
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR bullet
+ENCODING 8226
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+40
+00
+00
+ENDCHAR
+STARTCHAR uni2023
+ENCODING 8227
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+E0
+C0
+00
+00
+ENDCHAR
+STARTCHAR onedotenleader
+ENCODING 8228
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+40
+00
+ENDCHAR
+STARTCHAR twodotenleader
+ENCODING 8229
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+A0
+00
+ENDCHAR
+STARTCHAR ellipsis
+ENCODING 8230
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+B0
+00
+ENDCHAR
+STARTCHAR uni2027
+ENCODING 8231
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR perthousand
+ENCODING 8240
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+40
+80
+30
+00
+ENDCHAR
+STARTCHAR guilsinglleft
+ENCODING 8249
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+80
+40
+00
+00
+ENDCHAR
+STARTCHAR guilsinglright
+ENCODING 8250
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+20
+40
+00
+00
+ENDCHAR
+STARTCHAR uni203E
+ENCODING 8254
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR nsuperior
+ENCODING 8319
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+A0
+00
+00
+ENDCHAR
+STARTCHAR peseta
+ENCODING 8359
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+F0
+60
+40
+40
+00
+ENDCHAR
+STARTCHAR Euro
+ENCODING 8364
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+40
+20
+00
+ENDCHAR
+STARTCHAR afii61352
+ENCODING 8470
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+B0
+B0
+A0
+B0
+00
+ENDCHAR
+STARTCHAR trademark
+ENCODING 8482
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+00
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Omega
+ENCODING 8486
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+40
+A0
+00
+ENDCHAR
+STARTCHAR uni2127
+ENCODING 8487
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR oneeighth
+ENCODING 8539
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+B0
+20
+50
+20
+ENDCHAR
+STARTCHAR threeeighths
+ENCODING 8540
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+B0
+60
+D0
+20
+ENDCHAR
+STARTCHAR fiveeighths
+ENCODING 8541
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+80
+70
+A0
+50
+20
+ENDCHAR
+STARTCHAR seveneighths
+ENCODING 8542
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+B0
+A0
+50
+20
+ENDCHAR
+STARTCHAR arrowleft
+ENCODING 8592
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+F0
+40
+00
+00
+ENDCHAR
+STARTCHAR arrowup
+ENCODING 8593
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR arrowright
+ENCODING 8594
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+F0
+20
+00
+00
+ENDCHAR
+STARTCHAR arrowdown
+ENCODING 8595
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR arrowboth
+ENCODING 8596
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+F0
+50
+00
+00
+ENDCHAR
+STARTCHAR arrowupdn
+ENCODING 8597
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR universal
+ENCODING 8704
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+A0
+40
+00
+ENDCHAR
+STARTCHAR uni2201
+ENCODING 8705
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR partialdiff
+ENCODING 8706
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+60
+A0
+40
+00
+ENDCHAR
+STARTCHAR existential
+ENCODING 8707
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+20
+E0
+20
+E0
+00
+ENDCHAR
+STARTCHAR uni2204
+ENCODING 8708
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+20
+E0
+60
+E0
+80
+ENDCHAR
+STARTCHAR emptyset
+ENCODING 8709
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+A0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR Delta
+ENCODING 8710
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR gradient
+ENCODING 8711
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR element
+ENCODING 8712
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+E0
+80
+60
+00
+ENDCHAR
+STARTCHAR notelement
+ENCODING 8713
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+E0
+A0
+60
+40
+ENDCHAR
+STARTCHAR uni220A
+ENCODING 8714
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+80
+C0
+80
+40
+00
+ENDCHAR
+STARTCHAR suchthat
+ENCODING 8715
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+E0
+20
+C0
+00
+ENDCHAR
+STARTCHAR uni220C
+ENCODING 8716
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+20
+E0
+60
+C0
+80
+ENDCHAR
+STARTCHAR uni220D
+ENCODING 8717
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+C0
+40
+80
+00
+ENDCHAR
+STARTCHAR uni220E
+ENCODING 8718
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+C0
+C0
+C0
+C0
+00
+ENDCHAR
+STARTCHAR product
+ENCODING 8719
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR uni2210
+ENCODING 8720
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR summation
+ENCODING 8721
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR minus
+ENCODING 8722
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2213
+ENCODING 8723
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR uni2214
+ENCODING 8724
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR fraction
+ENCODING 8725
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+40
+80
+80
+00
+ENDCHAR
+STARTCHAR uni2216
+ENCODING 8726
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+40
+20
+20
+00
+ENDCHAR
+STARTCHAR asteriskmath
+ENCODING 8727
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+70
+E0
+50
+40
+ENDCHAR
+STARTCHAR uni2218
+ENCODING 8728
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+40
+00
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 8729
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+40
+00
+00
+ENDCHAR
+STARTCHAR radical
+ENCODING 8730
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+30
+20
+20
+A0
+60
+00
+ENDCHAR
+STARTCHAR uni221B
+ENCODING 8731
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+50
+D0
+10
+50
+30
+ENDCHAR
+STARTCHAR uni221C
+ENCODING 8732
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+D0
+50
+10
+50
+30
+ENDCHAR
+STARTCHAR proportional
+ENCODING 8733
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+50
+E0
+50
+00
+ENDCHAR
+STARTCHAR infinity
+ENCODING 8734
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+D0
+B0
+40
+00
+ENDCHAR
+STARTCHAR orthogonal
+ENCODING 8735
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+80
+80
+E0
+00
+ENDCHAR
+STARTCHAR angle
+ENCODING 8736
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR uni2221
+ENCODING 8737
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+A0
+40
+A0
+F0
+20
+ENDCHAR
+STARTCHAR uni2222
+ENCODING 8738
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+60
+A0
+A0
+60
+90
+ENDCHAR
+STARTCHAR uni2223
+ENCODING 8739
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR uni2224
+ENCODING 8740
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+40
+C0
+40
+00
+ENDCHAR
+STARTCHAR uni2225
+ENCODING 8741
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR uni2226
+ENCODING 8742
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+B0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR logicaland
+ENCODING 8743
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+40
+A0
+A0
+00
+ENDCHAR
+STARTCHAR logicalor
+ENCODING 8744
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR intersection
+ENCODING 8745
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR union
+ENCODING 8746
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR integral
+ENCODING 8747
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR uni222C
+ENCODING 8748
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+A0
+A0
+A0
+80
+ENDCHAR
+STARTCHAR uni222D
+ENCODING 8749
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+D0
+D0
+D0
+D0
+A0
+ENDCHAR
+STARTCHAR uni222E
+ENCODING 8750
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+E0
+40
+80
+ENDCHAR
+STARTCHAR uni222F
+ENCODING 8751
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+E0
+E0
+A0
+80
+ENDCHAR
+STARTCHAR uni2230
+ENCODING 8752
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+D0
+F0
+F0
+D0
+A0
+ENDCHAR
+STARTCHAR uni2231
+ENCODING 8753
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+50
+40
+80
+ENDCHAR
+STARTCHAR uni2232
+ENCODING 8754
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+C0
+40
+80
+ENDCHAR
+STARTCHAR uni2233
+ENCODING 8755
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+C0
+E0
+40
+80
+ENDCHAR
+STARTCHAR therefore
+ENCODING 8756
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+A0
+00
+ENDCHAR
+STARTCHAR uni2235
+ENCODING 8757
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A0
+00
+40
+00
+ENDCHAR
+STARTCHAR uni2236
+ENCODING 8758
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR uni2237
+ENCODING 8759
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A0
+00
+A0
+00
+ENDCHAR
+STARTCHAR uni2238
+ENCODING 8760
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2239
+ENCODING 8761
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+20
+C0
+20
+00
+ENDCHAR
+STARTCHAR uni223A
+ENCODING 8762
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+E0
+00
+A0
+00
+ENDCHAR
+STARTCHAR uni223B
+ENCODING 8763
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+50
+A0
+00
+40
+ENDCHAR
+STARTCHAR similar
+ENCODING 8764
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+50
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni223D
+ENCODING 8765
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A0
+50
+00
+00
+ENDCHAR
+STARTCHAR uni223E
+ENCODING 8766
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+D0
+B0
+00
+00
+ENDCHAR
+STARTCHAR uni223F
+ENCODING 8767
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+50
+A0
+20
+00
+ENDCHAR
+STARTCHAR uni2240
+ENCODING 8768
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+20
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR uni2241
+ENCODING 8769
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+20
+B0
+D0
+40
+80
+ENDCHAR
+STARTCHAR uni2242
+ENCODING 8770
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+00
+A0
+50
+00
+ENDCHAR
+STARTCHAR uni2243
+ENCODING 8771
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2244
+ENCODING 8772
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+D0
+B0
+40
+F0
+40
+ENDCHAR
+STARTCHAR congruent
+ENCODING 8773
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+00
+E0
+00
+E0
+ENDCHAR
+STARTCHAR uni2246
+ENCODING 8774
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+20
+F0
+40
+F0
+ENDCHAR
+STARTCHAR uni2247
+ENCODING 8775
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+20
+F0
+40
+F0
+ENDCHAR
+STARTCHAR approxequal
+ENCODING 8776
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+00
+50
+A0
+00
+ENDCHAR
+STARTCHAR uni2249
+ENCODING 8777
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+40
+50
+E0
+80
+ENDCHAR
+STARTCHAR uni224A
+ENCODING 8778
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+B0
+40
+B0
+00
+F0
+ENDCHAR
+STARTCHAR uni224B
+ENCODING 8779
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+B0
+40
+B0
+40
+B0
+ENDCHAR
+STARTCHAR uni224C
+ENCODING 8780
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+50
+00
+E0
+00
+E0
+ENDCHAR
+STARTCHAR uni224D
+ENCODING 8781
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+40
+A0
+00
+ENDCHAR
+STARTCHAR uni224E
+ENCODING 8782
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+A0
+40
+00
+ENDCHAR
+STARTCHAR uni224F
+ENCODING 8783
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2250
+ENCODING 8784
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2251
+ENCODING 8785
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+40
+ENDCHAR
+STARTCHAR uni2252
+ENCODING 8786
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+00
+E0
+00
+20
+ENDCHAR
+STARTCHAR uni2253
+ENCODING 8787
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+00
+E0
+00
+80
+ENDCHAR
+STARTCHAR uni2254
+ENCODING 8788
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+B0
+00
+B0
+00
+00
+ENDCHAR
+STARTCHAR uni2255
+ENCODING 8789
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+D0
+00
+D0
+00
+00
+ENDCHAR
+STARTCHAR uni2256
+ENCODING 8790
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+40
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2257
+ENCODING 8791
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2258
+ENCODING 8792
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2259
+ENCODING 8793
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni225A
+ENCODING 8794
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni225B
+ENCODING 8795
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni225C
+ENCODING 8796
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni225D
+ENCODING 8797
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni225E
+ENCODING 8798
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni225F
+ENCODING 8799
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR notequal
+ENCODING 8800
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+40
+E0
+80
+00
+ENDCHAR
+STARTCHAR equivalence
+ENCODING 8801
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2262
+ENCODING 8802
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+20
+E0
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni2263
+ENCODING 8803
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR lessequal
+ENCODING 8804
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR greaterequal
+ENCODING 8805
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2266
+ENCODING 8806
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2267
+ENCODING 8807
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2268
+ENCODING 8808
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+40
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2269
+ENCODING 8809
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+80
+40
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni226A
+ENCODING 8810
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+50
+00
+00
+ENDCHAR
+STARTCHAR uni226B
+ENCODING 8811
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+50
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni226C
+ENCODING 8812
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+40
+A0
+00
+ENDCHAR
+STARTCHAR uni226D
+ENCODING 8813
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+40
+E0
+80
+00
+ENDCHAR
+STARTCHAR uni226E
+ENCODING 8814
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+C0
+60
+80
+00
+ENDCHAR
+STARTCHAR uni226F
+ENCODING 8815
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+60
+C0
+80
+00
+ENDCHAR
+STARTCHAR uni2270
+ENCODING 8816
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni2271
+ENCODING 8817
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+60
+E0
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni2272
+ENCODING 8818
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+00
+50
+A0
+ENDCHAR
+STARTCHAR uni2273
+ENCODING 8819
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+E0
+00
+A0
+50
+ENDCHAR
+STARTCHAR uni2276
+ENCODING 8822
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+20
+80
+60
+C0
+ENDCHAR
+STARTCHAR uni2277
+ENCODING 8823
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+60
+80
+20
+C0
+60
+ENDCHAR
+STARTCHAR uni2278
+ENCODING 8824
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+60
+C0
+60
+C0
+ENDCHAR
+STARTCHAR uni2279
+ENCODING 8825
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+60
+C0
+60
+C0
+60
+ENDCHAR
+STARTCHAR uni227A
+ENCODING 8826
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+C0
+20
+00
+00
+ENDCHAR
+STARTCHAR uni227B
+ENCODING 8827
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+80
+60
+80
+00
+00
+ENDCHAR
+STARTCHAR uni227C
+ENCODING 8828
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+20
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni227D
+ENCODING 8829
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+80
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni227E
+ENCODING 8830
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+20
+00
+A0
+50
+ENDCHAR
+STARTCHAR uni227F
+ENCODING 8831
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+20
+00
+A0
+50
+ENDCHAR
+STARTCHAR uni2280
+ENCODING 8832
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+C0
+60
+40
+00
+ENDCHAR
+STARTCHAR uni2281
+ENCODING 8833
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+60
+C0
+40
+00
+ENDCHAR
+STARTCHAR propersubset
+ENCODING 8834
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+80
+60
+00
+00
+ENDCHAR
+STARTCHAR propersuperset
+ENCODING 8835
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+20
+C0
+00
+00
+ENDCHAR
+STARTCHAR notsubset
+ENCODING 8836
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+C0
+60
+40
+00
+ENDCHAR
+STARTCHAR uni2285
+ENCODING 8837
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+60
+C0
+40
+00
+ENDCHAR
+STARTCHAR reflexsubset
+ENCODING 8838
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+60
+00
+E0
+00
+ENDCHAR
+STARTCHAR reflexsuperset
+ENCODING 8839
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+C0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2288
+ENCODING 8840
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+60
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni2289
+ENCODING 8841
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+60
+C0
+40
+E0
+40
+ENDCHAR
+STARTCHAR uni228A
+ENCODING 8842
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+60
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni228B
+ENCODING 8843
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+C0
+40
+E0
+80
+ENDCHAR
+STARTCHAR revlogicalnot
+ENCODING 8976
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+80
+00
+00
+ENDCHAR
+STARTCHAR integraltp
+ENCODING 8992
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR integralbt
+ENCODING 8993
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+20
+20
+20
+40
+ENDCHAR
+STARTCHAR uni23BA
+ENCODING 9146
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BB
+ENCODING 9147
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BC
+ENCODING 9148
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni23BD
+ENCODING 9149
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+F0
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 9225
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+70
+20
+20
+ENDCHAR
+STARTCHAR uni240A
+ENCODING 9226
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+E0
+60
+40
+40
+ENDCHAR
+STARTCHAR uni240B
+ENCODING 9227
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+70
+20
+20
+ENDCHAR
+STARTCHAR uni240C
+ENCODING 9228
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+C0
+80
+60
+60
+40
+ENDCHAR
+STARTCHAR uni240D
+ENCODING 9229
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+E0
+50
+60
+50
+ENDCHAR
+STARTCHAR uni2423
+ENCODING 9251
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+90
+F0
+ENDCHAR
+STARTCHAR uni2424
+ENCODING 9252
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+B0
+90
+20
+20
+30
+ENDCHAR
+STARTCHAR SF100000
+ENCODING 9472
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2501
+ENCODING 9473
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F8
+F8
+00
+00
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9474
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR uni2503
+ENCODING 9475
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR uni2504
+ENCODING 9476
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni2505
+ENCODING 9477
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A8
+A8
+00
+00
+ENDCHAR
+STARTCHAR uni2506
+ENCODING 9478
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR uni2507
+ENCODING 9479
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+60
+00
+60
+00
+ENDCHAR
+STARTCHAR uni2508
+ENCODING 9480
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni2509
+ENCODING 9481
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A8
+A8
+00
+00
+ENDCHAR
+STARTCHAR uni250A
+ENCODING 9482
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR uni250B
+ENCODING 9483
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+60
+00
+60
+00
+ENDCHAR
+STARTCHAR SF010000
+ENCODING 9484
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+70
+40
+40
+ENDCHAR
+STARTCHAR uni250D
+ENCODING 9485
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+70
+40
+40
+ENDCHAR
+STARTCHAR uni250E
+ENCODING 9486
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+70
+60
+60
+ENDCHAR
+STARTCHAR uni250F
+ENCODING 9487
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+70
+60
+60
+ENDCHAR
+STARTCHAR SF030000
+ENCODING 9488
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+C0
+40
+40
+ENDCHAR
+STARTCHAR uni2511
+ENCODING 9489
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+C0
+40
+40
+ENDCHAR
+STARTCHAR uni2512
+ENCODING 9490
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+E0
+60
+60
+ENDCHAR
+STARTCHAR uni2513
+ENCODING 9491
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+E0
+60
+60
+ENDCHAR
+STARTCHAR SF020000
+ENCODING 9492
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+70
+00
+00
+ENDCHAR
+STARTCHAR uni2515
+ENCODING 9493
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+70
+00
+00
+ENDCHAR
+STARTCHAR uni2516
+ENCODING 9494
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+00
+00
+ENDCHAR
+STARTCHAR uni2517
+ENCODING 9495
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+70
+00
+00
+ENDCHAR
+STARTCHAR SF040000
+ENCODING 9496
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+C0
+00
+00
+ENDCHAR
+STARTCHAR uni2519
+ENCODING 9497
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+C0
+00
+00
+ENDCHAR
+STARTCHAR uni251A
+ENCODING 9498
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni251B
+ENCODING 9499
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+E0
+00
+00
+ENDCHAR
+STARTCHAR SF080000
+ENCODING 9500
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+70
+40
+40
+ENDCHAR
+STARTCHAR uni251D
+ENCODING 9501
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+70
+40
+40
+ENDCHAR
+STARTCHAR uni251E
+ENCODING 9502
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+40
+40
+ENDCHAR
+STARTCHAR uni251F
+ENCODING 9503
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+70
+60
+60
+ENDCHAR
+STARTCHAR uni2520
+ENCODING 9504
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+60
+60
+ENDCHAR
+STARTCHAR uni2521
+ENCODING 9505
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+70
+40
+40
+ENDCHAR
+STARTCHAR uni2522
+ENCODING 9506
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+70
+60
+60
+ENDCHAR
+STARTCHAR uni2523
+ENCODING 9507
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+70
+60
+60
+ENDCHAR
+STARTCHAR SF090000
+ENCODING 9508
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+C0
+40
+40
+ENDCHAR
+STARTCHAR uni2525
+ENCODING 9509
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+C0
+40
+40
+ENDCHAR
+STARTCHAR uni2526
+ENCODING 9510
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+40
+40
+ENDCHAR
+STARTCHAR uni2527
+ENCODING 9511
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+E0
+60
+60
+ENDCHAR
+STARTCHAR uni2528
+ENCODING 9512
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+60
+60
+ENDCHAR
+STARTCHAR uni2529
+ENCODING 9513
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+E0
+40
+40
+ENDCHAR
+STARTCHAR uni252A
+ENCODING 9514
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+E0
+E0
+60
+60
+ENDCHAR
+STARTCHAR uni252B
+ENCODING 9515
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+E0
+60
+60
+ENDCHAR
+STARTCHAR SF060000
+ENCODING 9516
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni252D
+ENCODING 9517
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni252E
+ENCODING 9518
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni252F
+ENCODING 9519
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2530
+ENCODING 9520
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2531
+ENCODING 9521
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2532
+ENCODING 9522
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2533
+ENCODING 9523
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+F0
+60
+60
+ENDCHAR
+STARTCHAR SF070000
+ENCODING 9524
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2535
+ENCODING 9525
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2536
+ENCODING 9526
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2537
+ENCODING 9527
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2538
+ENCODING 9528
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2539
+ENCODING 9529
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni253A
+ENCODING 9530
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni253B
+ENCODING 9531
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+F0
+00
+00
+ENDCHAR
+STARTCHAR SF050000
+ENCODING 9532
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni253D
+ENCODING 9533
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni253E
+ENCODING 9534
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni253F
+ENCODING 9535
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2540
+ENCODING 9536
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2541
+ENCODING 9537
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2542
+ENCODING 9538
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2543
+ENCODING 9539
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2544
+ENCODING 9540
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2545
+ENCODING 9541
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+E0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2546
+ENCODING 9542
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2547
+ENCODING 9543
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2548
+ENCODING 9544
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2549
+ENCODING 9545
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni254A
+ENCODING 9546
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni254B
+ENCODING 9547
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni254C
+ENCODING 9548
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni254D
+ENCODING 9549
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A0
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni254E
+ENCODING 9550
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+40
+00
+40
+40
+ENDCHAR
+STARTCHAR uni254F
+ENCODING 9551
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+60
+00
+60
+60
+ENDCHAR
+STARTCHAR SF430000
+ENCODING 9552
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+F0
+00
+ENDCHAR
+STARTCHAR SF240000
+ENCODING 9553
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR SF510000
+ENCODING 9554
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+40
+70
+40
+ENDCHAR
+STARTCHAR SF520000
+ENCODING 9555
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+70
+60
+60
+ENDCHAR
+STARTCHAR SF390000
+ENCODING 9556
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+40
+70
+60
+ENDCHAR
+STARTCHAR SF220000
+ENCODING 9557
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+40
+C0
+40
+ENDCHAR
+STARTCHAR SF210000
+ENCODING 9558
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+E0
+60
+60
+ENDCHAR
+STARTCHAR SF250000
+ENCODING 9559
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+20
+E0
+60
+ENDCHAR
+STARTCHAR SF500000
+ENCODING 9560
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+40
+70
+00
+ENDCHAR
+STARTCHAR SF490000
+ENCODING 9561
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+00
+00
+ENDCHAR
+STARTCHAR SF380000
+ENCODING 9562
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+40
+70
+00
+ENDCHAR
+STARTCHAR SF280000
+ENCODING 9563
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+40
+C0
+00
+ENDCHAR
+STARTCHAR SF270000
+ENCODING 9564
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+00
+00
+ENDCHAR
+STARTCHAR SF260000
+ENCODING 9565
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+20
+E0
+00
+ENDCHAR
+STARTCHAR SF360000
+ENCODING 9566
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+40
+70
+40
+ENDCHAR
+STARTCHAR SF370000
+ENCODING 9567
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+60
+60
+ENDCHAR
+STARTCHAR SF420000
+ENCODING 9568
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+40
+70
+60
+ENDCHAR
+STARTCHAR SF190000
+ENCODING 9569
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+40
+C0
+40
+ENDCHAR
+STARTCHAR SF200000
+ENCODING 9570
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+60
+60
+ENDCHAR
+STARTCHAR SF230000
+ENCODING 9571
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+20
+E0
+60
+ENDCHAR
+STARTCHAR SF470000
+ENCODING 9572
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+F0
+40
+ENDCHAR
+STARTCHAR SF480000
+ENCODING 9573
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+60
+60
+ENDCHAR
+STARTCHAR SF410000
+ENCODING 9574
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+F0
+60
+ENDCHAR
+STARTCHAR SF450000
+ENCODING 9575
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+00
+F0
+00
+ENDCHAR
+STARTCHAR SF460000
+ENCODING 9576
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+00
+00
+ENDCHAR
+STARTCHAR SF400000
+ENCODING 9577
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+00
+F0
+00
+ENDCHAR
+STARTCHAR SF540000
+ENCODING 9578
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+40
+F0
+40
+ENDCHAR
+STARTCHAR SF530000
+ENCODING 9579
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+60
+60
+ENDCHAR
+STARTCHAR SF440000
+ENCODING 9580
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+00
+F0
+60
+ENDCHAR
+STARTCHAR uni256D
+ENCODING 9581
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+30
+40
+40
+ENDCHAR
+STARTCHAR uni256E
+ENCODING 9582
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+80
+40
+40
+ENDCHAR
+STARTCHAR uni256F
+ENCODING 9583
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+80
+00
+00
+ENDCHAR
+STARTCHAR uni2570
+ENCODING 9584
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+30
+00
+00
+ENDCHAR
+STARTCHAR uni2571
+ENCODING 9585
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR uni2572
+ENCODING 9586
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+40
+20
+20
+10
+ENDCHAR
+STARTCHAR uni2573
+ENCODING 9587
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+60
+60
+90
+90
+ENDCHAR
+STARTCHAR uni2574
+ENCODING 9588
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+C0
+00
+00
+ENDCHAR
+STARTCHAR uni2575
+ENCODING 9589
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+40
+00
+00
+ENDCHAR
+STARTCHAR uni2576
+ENCODING 9590
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+70
+00
+00
+ENDCHAR
+STARTCHAR uni2577
+ENCODING 9591
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+40
+40
+40
+ENDCHAR
+STARTCHAR uni2578
+ENCODING 9592
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+C0
+00
+00
+ENDCHAR
+STARTCHAR uni2579
+ENCODING 9593
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+60
+00
+00
+ENDCHAR
+STARTCHAR uni257A
+ENCODING 9594
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+70
+00
+00
+ENDCHAR
+STARTCHAR uni257B
+ENCODING 9595
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+60
+60
+60
+ENDCHAR
+STARTCHAR uni257C
+ENCODING 9596
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+30
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni257D
+ENCODING 9597
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+60
+60
+60
+ENDCHAR
+STARTCHAR uni257E
+ENCODING 9598
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni257F
+ENCODING 9599
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+60
+40
+40
+ENDCHAR
+STARTCHAR upblock
+ENCODING 9600
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F8
+F8
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2581
+ENCODING 9601
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+F0
+ENDCHAR
+STARTCHAR uni2582
+ENCODING 9602
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+F8
+ENDCHAR
+STARTCHAR uni2583
+ENCODING 9603
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+F8
+F8
+ENDCHAR
+STARTCHAR dnblock
+ENCODING 9604
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR uni2585
+ENCODING 9605
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR uni2586
+ENCODING 9606
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F8
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR uni2587
+ENCODING 9607
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F8
+F8
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR block
+ENCODING 9608
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F8
+F8
+F8
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR uni2589
+ENCODING 9609
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+F0
+F0
+F0
+F0
+F0
+ENDCHAR
+STARTCHAR uni258A
+ENCODING 9610
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+E0
+E0
+E0
+E0
+E0
+ENDCHAR
+STARTCHAR uni258B
+ENCODING 9611
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+E0
+E0
+E0
+E0
+E0
+ENDCHAR
+STARTCHAR lfblock
+ENCODING 9612
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni258D
+ENCODING 9613
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni258E
+ENCODING 9614
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR uni258F
+ENCODING 9615
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR rtblock
+ENCODING 9616
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR ltshade
+ENCODING 9617
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+80
+20
+80
+20
+ENDCHAR
+STARTCHAR shade
+ENCODING 9618
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A8
+50
+A8
+50
+A8
+50
+ENDCHAR
+STARTCHAR dkshade
+ENCODING 9619
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B8
+E8
+B8
+E8
+B8
+E8
+ENDCHAR
+STARTCHAR uni2594
+ENCODING 9620
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2595
+ENCODING 9621
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR filledbox
+ENCODING 9632
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR H22073
+ENCODING 9633
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR uni25C6
+ENCODING 9670
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+E0
+40
+00
+ENDCHAR
+STARTCHAR spade
+ENCODING 9824
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR club
+ENCODING 9827
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+40
+E0
+00
+ENDCHAR
+STARTCHAR heart
+ENCODING 9829
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+40
+00
+ENDCHAR
+STARTCHAR diamond
+ENCODING 9830
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+40
+00
+00
+ENDCHAR
+STARTCHAR uni2669
+ENCODING 9833
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+C0
+80
+00
+ENDCHAR
+STARTCHAR musicalnote
+ENCODING 9834
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+40
+C0
+80
+00
+ENDCHAR
+STARTCHAR musicalnotedbl
+ENCODING 9835
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+50
+50
+50
+A0
+00
+ENDCHAR
+STARTCHAR uni266C
+ENCODING 9836
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+70
+50
+50
+A0
+00
+ENDCHAR
+STARTCHAR uni266D
+ENCODING 9837
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+E0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR uni266E
+ENCODING 9838
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+A0
+E0
+20
+00
+ENDCHAR
+STARTCHAR uni266F
+ENCODING 9839
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR uniFFFD
+ENCODING 65533
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+90
+D0
+F0
+D0
+F0
+ENDCHAR
+ENDFONT
diff --git a/src/col64/cruft/col64font_ext.bdf b/src/col64/cruft/col64font_ext.bdf
new file mode 100644
index 0000000..c6cc5f0
--- /dev/null
+++ b/src/col64/cruft/col64font_ext.bdf
@@ -0,0 +1,11994 @@
+STARTFONT 2.1
+COMMENT Contributed by Janne V. Kujala <jvk@iki.fi>
+COMMENT $Id: 4x6.bdf,v 1.5 2002-08-26 18:05:49+01 mgk25 Rel $
+COMMENT Send bug reports to Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
+FONT -Misc-Fixed-Medium-R-Normal--6-60-75-75-C-40-ISO10646-1
+SIZE 6 75 75
+FONTBOUNDINGBOX 4 6 0 -1
+STARTPROPERTIES 23
+FONTNAME_REGISTRY ""
+FOUNDRY "Misc"
+FAMILY_NAME "Fixed"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 6
+POINT_SIZE 60
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "C"
+AVERAGE_WIDTH 40
+CHARSET_REGISTRY "ISO10646"
+CHARSET_ENCODING "1"
+FONT_ASCENT 5
+FONT_DESCENT 1
+DESTINATION 1
+COPYRIGHT "Public domain font. Share and enjoy."
+CAP_HEIGHT 5
+X_HEIGHT 4
+DEFAULT_CHAR 0
+_GBDFED_INFO "Edited with gbdfed 1.4."
+ENDPROPERTIES
+CHARS 920
+STARTCHAR char0
+ENCODING 0
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+00
+A0
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 32
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+F0
+A0
+F0
+A0
+00
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+60
+50
+E0
+00
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+20
+40
+90
+00
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+A0
+D0
+00
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+20
+20
+20
+40
+00
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+A0
+00
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+20
+40
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 45
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+40
+00
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+40
+80
+80
+00
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+B0
+D0
+60
+00
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+20
+40
+F0
+00
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+10
+60
+10
+E0
+00
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+A0
+F0
+20
+00
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+80
+E0
+10
+E0
+00
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+80
+E0
+90
+60
+00
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+10
+20
+40
+40
+00
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+60
+90
+60
+00
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+70
+10
+E0
+00
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+00
+00
+40
+00
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+00
+20
+40
+00
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+80
+40
+20
+00
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F0
+00
+F0
+00
+00
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+20
+40
+80
+00
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+90
+20
+00
+20
+00
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+B0
+B0
+80
+60
+00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+F0
+90
+90
+00
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+90
+E0
+90
+E0
+00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+80
+90
+60
+00
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+90
+90
+90
+E0
+00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+80
+E0
+80
+F0
+00
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+80
+E0
+80
+80
+00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+80
+B0
+90
+60
+00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+F0
+90
+90
+00
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+30
+10
+10
+90
+60
+00
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+A0
+C0
+A0
+90
+00
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+80
+F0
+00
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+F0
+D0
+90
+90
+00
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+D0
+B0
+90
+90
+00
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+90
+E0
+80
+80
+00
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+90
+A0
+50
+00
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+90
+E0
+A0
+90
+00
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+80
+60
+10
+E0
+00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+90
+A0
+40
+00
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+D0
+F0
+A0
+00
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+60
+90
+90
+00
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+60
+20
+40
+00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+20
+40
+80
+F0
+00
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+40
+40
+60
+00
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+40
+20
+20
+00
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+20
+20
+20
+60
+00
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+F0
+00
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+90
+B0
+50
+00
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+E0
+90
+E0
+00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+80
+80
+70
+00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+10
+70
+90
+70
+00
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+90
+E0
+70
+00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+90
+70
+10
+00
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+E0
+90
+90
+00
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+60
+20
+20
+00
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+C0
+A0
+90
+00
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+F0
+D0
+90
+00
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+90
+E0
+80
+00
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+90
+70
+10
+00
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+D0
+80
+80
+00
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+C0
+30
+E0
+00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+90
+A0
+40
+00
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+D0
+F0
+A0
+00
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+60
+60
+90
+00
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+90
+60
+20
+00
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F0
+20
+40
+F0
+00
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+80
+40
+60
+00
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+20
+40
+C0
+00
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+00
+00
+00
+ENDCHAR
+STARTCHAR char127
+ENCODING 127
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+80
+10
+C0
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 160
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+80
+E0
+40
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+60
+40
+A0
+00
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+60
+60
+90
+00
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+00
+40
+40
+00
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR dieresis
+ENCODING 168
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+D0
+D0
+90
+60
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+60
+00
+E0
+00
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+50
+00
+00
+ENDCHAR
+STARTCHAR logicalnot
+ENCODING 172
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+20
+00
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+F0
+D0
+60
+00
+00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+00
+E0
+00
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+80
+C0
+00
+00
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+80
+40
+80
+00
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+D0
+D0
+50
+50
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+20
+40
+00
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+40
+40
+00
+00
+ENDCHAR
+STARTCHAR ordmasculine
+ENCODING 186
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+00
+E0
+00
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+50
+A0
+00
+00
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+50
+70
+10
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+B0
+10
+20
+30
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+80
+50
+B0
+10
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+80
+60
+00
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Adieresis
+ENCODING 196
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+F0
+A0
+B0
+00
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+80
+A0
+40
+80
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Edieresis
+ENCODING 203
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Idieresis
+ENCODING 207
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Eth
+ENCODING 208
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+50
+D0
+50
+E0
+00
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+E0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+E0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Odieresis
+ENCODING 214
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+40
+A0
+00
+00
+ENDCHAR
+STARTCHAR Oslash
+ENCODING 216
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+E0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Udieresis
+ENCODING 220
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR Thorn
+ENCODING 222
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+C0
+A0
+C0
+80
+00
+ENDCHAR
+STARTCHAR germandbls
+ENCODING 223
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+C0
+A0
+E0
+80
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR adieresis
+ENCODING 228
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+B0
+A0
+70
+00
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+80
+60
+40
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR edieresis
+ENCODING 235
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR idieresis
+ENCODING 239
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+60
+A0
+40
+00
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR odieresis
+ENCODING 246
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR divide
+ENCODING 247
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+40
+00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR udieresis
+ENCODING 252
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+E0
+20
+C0
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+C0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR ydieresis
+ENCODING 255
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+E0
+20
+C0
+ENDCHAR
+STARTCHAR Amacron
+ENCODING 256
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR amacron
+ENCODING 257
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR Abreve
+ENCODING 258
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR abreve
+ENCODING 259
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR Aogonek
+ENCODING 260
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+E0
+A0
+20
+ENDCHAR
+STARTCHAR aogonek
+ENCODING 261
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+60
+A0
+60
+20
+ENDCHAR
+STARTCHAR Cacute
+ENCODING 262
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR cacute
+ENCODING 263
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+80
+60
+00
+ENDCHAR
+STARTCHAR Ccircumflex
+ENCODING 264
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR ccircumflex
+ENCODING 265
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+60
+80
+60
+00
+ENDCHAR
+STARTCHAR Cdotaccent
+ENCODING 266
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR cdotaccent
+ENCODING 267
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+60
+80
+60
+00
+ENDCHAR
+STARTCHAR Ccaron
+ENCODING 268
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR ccaron
+ENCODING 269
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+60
+80
+60
+00
+ENDCHAR
+STARTCHAR Dcaron
+ENCODING 270
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+C0
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR dcaron
+ENCODING 271
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+30
+20
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR Dcroat
+ENCODING 272
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+E0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR dcroat
+ENCODING 273
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+20
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR Emacron
+ENCODING 274
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR emacron
+ENCODING 275
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR Ebreve
+ENCODING 276
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR ebreve
+ENCODING 277
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR Edotaccent
+ENCODING 278
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR edotaccent
+ENCODING 279
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR Eogonek
+ENCODING 280
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+80
+E0
+20
+ENDCHAR
+STARTCHAR eogonek
+ENCODING 281
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+C0
+60
+40
+ENDCHAR
+STARTCHAR Ecaron
+ENCODING 282
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR ecaron
+ENCODING 283
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR Gcircumflex
+ENCODING 284
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+80
+A0
+60
+00
+ENDCHAR
+STARTCHAR gcircumflex
+ENCODING 285
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR Gbreve
+ENCODING 286
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+60
+80
+A0
+60
+00
+ENDCHAR
+STARTCHAR gbreve
+ENCODING 287
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR Gdotaccent
+ENCODING 288
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+80
+A0
+60
+00
+ENDCHAR
+STARTCHAR gdotaccent
+ENCODING 289
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR Gcommaaccent
+ENCODING 290
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+A0
+A0
+40
+40
+ENDCHAR
+STARTCHAR gcommaaccent
+ENCODING 291
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR Hcircumflex
+ENCODING 292
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR hcircumflex
+ENCODING 293
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Hbar
+ENCODING 294
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR hbar
+ENCODING 295
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+C0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Itilde
+ENCODING 296
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR itilde
+ENCODING 297
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Imacron
+ENCODING 298
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR imacron
+ENCODING 299
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Ibreve
+ENCODING 300
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR ibreve
+ENCODING 301
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Iogonek
+ENCODING 302
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+E0
+20
+ENDCHAR
+STARTCHAR iogonek
+ENCODING 303
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+C0
+40
+E0
+20
+ENDCHAR
+STARTCHAR Idotaccent
+ENCODING 304
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR dotlessi
+ENCODING 305
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR IJ
+ENCODING 306
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+A0
+A0
+20
+60
+ENDCHAR
+STARTCHAR ij
+ENCODING 307
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+20
+40
+ENDCHAR
+STARTCHAR Jcircumflex
+ENCODING 308
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+20
+A0
+40
+00
+ENDCHAR
+STARTCHAR jcircumflex
+ENCODING 309
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+20
+20
+C0
+ENDCHAR
+STARTCHAR Kcommaaccent
+ENCODING 310
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+C0
+A0
+20
+40
+ENDCHAR
+STARTCHAR kcommaaccent
+ENCODING 311
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+C0
+A0
+20
+40
+ENDCHAR
+STARTCHAR kgreenlandic
+ENCODING 312
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR Lacute
+ENCODING 313
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+80
+80
+80
+E0
+00
+ENDCHAR
+STARTCHAR lacute
+ENCODING 314
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Lcommaaccent
+ENCODING 315
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+80
+E0
+20
+ENDCHAR
+STARTCHAR lcommaaccent
+ENCODING 316
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+40
+40
+E0
+20
+ENDCHAR
+STARTCHAR Lcaron
+ENCODING 317
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+C0
+80
+80
+E0
+00
+ENDCHAR
+STARTCHAR lcaron
+ENCODING 318
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Ldot
+ENCODING 319
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+A0
+80
+E0
+00
+ENDCHAR
+STARTCHAR ldot
+ENCODING 320
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+50
+40
+E0
+00
+ENDCHAR
+STARTCHAR Lslash
+ENCODING 321
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR lslash
+ENCODING 322
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+60
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Nacute
+ENCODING 323
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+E0
+A0
+80
+00
+ENDCHAR
+STARTCHAR nacute
+ENCODING 324
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Ncommaaccent
+ENCODING 325
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+E0
+A0
+80
+20
+ENDCHAR
+STARTCHAR ncommaaccent
+ENCODING 326
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+A0
+00
+40
+ENDCHAR
+STARTCHAR Ncaron
+ENCODING 327
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+E0
+A0
+80
+00
+ENDCHAR
+STARTCHAR ncaron
+ENCODING 328
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR napostrophe
+ENCODING 329
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+00
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Eng
+ENCODING 330
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+E0
+A0
+20
+40
+ENDCHAR
+STARTCHAR eng
+ENCODING 331
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+A0
+20
+40
+ENDCHAR
+STARTCHAR Omacron
+ENCODING 332
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR omacron
+ENCODING 333
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR Obreve
+ENCODING 334
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR obreve
+ENCODING 335
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR Ohungarumlaut
+ENCODING 336
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR ohungarumlaut
+ENCODING 337
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR OE
+ENCODING 338
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+B0
+A0
+70
+00
+ENDCHAR
+STARTCHAR oe
+ENCODING 339
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+B0
+A0
+70
+00
+ENDCHAR
+STARTCHAR Racute
+ENCODING 340
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR racute
+ENCODING 341
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+A0
+C0
+80
+00
+ENDCHAR
+STARTCHAR Rcommaaccent
+ENCODING 342
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+A0
+00
+40
+ENDCHAR
+STARTCHAR rcommaaccent
+ENCODING 343
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+C0
+80
+80
+20
+ENDCHAR
+STARTCHAR Rcaron
+ENCODING 344
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR rcaron
+ENCODING 345
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+A0
+C0
+80
+00
+ENDCHAR
+STARTCHAR Sacute
+ENCODING 346
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR sacute
+ENCODING 347
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR Scircumflex
+ENCODING 348
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR scircumflex
+ENCODING 349
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR Scedilla
+ENCODING 350
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+40
+20
+C0
+40
+ENDCHAR
+STARTCHAR scedilla
+ENCODING 351
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+20
+E0
+40
+ENDCHAR
+STARTCHAR Scaron
+ENCODING 352
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+C0
+20
+E0
+00
+ENDCHAR
+STARTCHAR scaron
+ENCODING 353
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 354
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+20
+40
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 355
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+20
+40
+ENDCHAR
+STARTCHAR Tcaron
+ENCODING 356
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR tcaron
+ENCODING 357
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+20
+00
+ENDCHAR
+STARTCHAR Tbar
+ENCODING 358
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR tbar
+ENCODING 359
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+E0
+40
+20
+00
+ENDCHAR
+STARTCHAR Utilde
+ENCODING 360
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+20
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR utilde
+ENCODING 361
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+00
+A0
+60
+00
+ENDCHAR
+STARTCHAR Umacron
+ENCODING 362
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR umacron
+ENCODING 363
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR Ubreve
+ENCODING 364
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR ubreve
+ENCODING 365
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+A0
+60
+00
+ENDCHAR
+STARTCHAR Uring
+ENCODING 366
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR uring
+ENCODING 367
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR Uhungarumlaut
+ENCODING 368
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR uhungarumlaut
+ENCODING 369
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR Uogonek
+ENCODING 370
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+40
+20
+ENDCHAR
+STARTCHAR uogonek
+ENCODING 371
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+60
+40
+ENDCHAR
+STARTCHAR Wcircumflex
+ENCODING 372
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR wcircumflex
+ENCODING 373
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR Ycircumflex
+ENCODING 374
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR ycircumflex
+ENCODING 375
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+40
+80
+00
+ENDCHAR
+STARTCHAR Ydieresis
+ENCODING 376
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR Zacute
+ENCODING 377
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR zacute
+ENCODING 378
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR Zdotaccent
+ENCODING 379
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR zdotaccent
+ENCODING 380
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR Zcaron
+ENCODING 381
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR zcaron
+ENCODING 382
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR longs
+ENCODING 383
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+C0
+40
+40
+00
+ENDCHAR
+STARTCHAR uni018F
+ENCODING 399
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+60
+A0
+40
+00
+ENDCHAR
+STARTCHAR florin
+ENCODING 402
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+40
+40
+80
+ENDCHAR
+STARTCHAR Scommaaccent
+ENCODING 536
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+40
+20
+C0
+40
+ENDCHAR
+STARTCHAR scommaaccent
+ENCODING 537
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+20
+E0
+40
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 538
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+00
+40
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 539
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+20
+40
+ENDCHAR
+STARTCHAR uni0259
+ENCODING 601
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+60
+A0
+40
+00
+ENDCHAR
+STARTCHAR circumflex
+ENCODING 710
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR caron
+ENCODING 711
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR macron
+ENCODING 713
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR breve
+ENCODING 728
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dotaccent
+ENCODING 729
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ring
+ENCODING 730
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR ogonek
+ENCODING 731
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+40
+80
+C0
+ENDCHAR
+STARTCHAR tilde
+ENCODING 732
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR hungarumlaut
+ENCODING 733
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0374
+ENCODING 884
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0375
+ENCODING 885
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+40
+80
+ENDCHAR
+STARTCHAR uni037A
+ENCODING 890
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+40
+60
+ENDCHAR
+STARTCHAR uni037E
+ENCODING 894
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+00
+00
+40
+80
+ENDCHAR
+STARTCHAR tonos
+ENCODING 900
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dieresistonos
+ENCODING 901
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B0
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Alphatonos
+ENCODING 902
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR anoteleia
+ENCODING 903
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR Epsilontonos
+ENCODING 904
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+C0
+60
+40
+60
+00
+ENDCHAR
+STARTCHAR Etatonos
+ENCODING 905
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+20
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Iotatonos
+ENCODING 906
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+C0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Omicrontonos
+ENCODING 908
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Upsilontonos
+ENCODING 910
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+C0
+40
+40
+00
+ENDCHAR
+STARTCHAR Omegatonos
+ENCODING 911
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+A0
+40
+A0
+00
+ENDCHAR
+STARTCHAR iotadieresistonos
+ENCODING 912
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B0
+40
+00
+40
+20
+00
+ENDCHAR
+STARTCHAR Alpha
+ENCODING 913
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Beta
+ENCODING 914
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR Gamma
+ENCODING 915
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR Delta
+ENCODING 916
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Epsilon
+ENCODING 917
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Zeta
+ENCODING 918
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+20
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR Eta
+ENCODING 919
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Theta
+ENCODING 920
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+E0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Iota
+ENCODING 921
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Kappa
+ENCODING 922
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Lambda
+ENCODING 923
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Mu
+ENCODING 924
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Nu
+ENCODING 925
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+E0
+A0
+80
+00
+ENDCHAR
+STARTCHAR Xi
+ENCODING 926
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+40
+00
+E0
+00
+ENDCHAR
+STARTCHAR Omicron
+ENCODING 927
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Pi
+ENCODING 928
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Rho
+ENCODING 929
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+80
+80
+00
+ENDCHAR
+STARTCHAR Sigma
+ENCODING 931
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR Tau
+ENCODING 932
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR Upsilon
+ENCODING 933
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR Phi
+ENCODING 934
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+A0
+E0
+40
+00
+ENDCHAR
+STARTCHAR Chi
+ENCODING 935
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Psi
+ENCODING 936
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR Omega
+ENCODING 937
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+40
+A0
+00
+ENDCHAR
+STARTCHAR Iotadieresis
+ENCODING 938
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Upsilondieresis
+ENCODING 939
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR alphatonos
+ENCODING 940
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+80
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR epsilontonos
+ENCODING 941
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+40
+80
+60
+00
+ENDCHAR
+STARTCHAR etatonos
+ENCODING 942
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+C0
+A0
+20
+40
+ENDCHAR
+STARTCHAR iotatonos
+ENCODING 943
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR upsilondieresistonos
+ENCODING 944
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B0
+40
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR alpha
+ENCODING 945
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+A0
+50
+00
+ENDCHAR
+STARTCHAR beta
+ENCODING 946
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR gamma
+ENCODING 947
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+60
+40
+40
+00
+ENDCHAR
+STARTCHAR delta
+ENCODING 948
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR epsilon
+ENCODING 949
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+C0
+80
+60
+00
+ENDCHAR
+STARTCHAR zeta
+ENCODING 950
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+80
+E0
+20
+40
+ENDCHAR
+STARTCHAR eta
+ENCODING 951
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+A0
+20
+40
+ENDCHAR
+STARTCHAR theta
+ENCODING 952
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+E0
+A0
+40
+00
+ENDCHAR
+STARTCHAR iota
+ENCODING 953
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR kappa
+ENCODING 954
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR lambda
+ENCODING 955
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+60
+A0
+A0
+00
+ENDCHAR
+STARTCHAR mu
+ENCODING 956
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR nu
+ENCODING 957
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+60
+40
+00
+ENDCHAR
+STARTCHAR xi
+ENCODING 958
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+40
+80
+60
+00
+ENDCHAR
+STARTCHAR omicron
+ENCODING 959
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR pi
+ENCODING 960
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR rho
+ENCODING 961
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR sigma1
+ENCODING 962
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+80
+40
+C0
+00
+ENDCHAR
+STARTCHAR sigma
+ENCODING 963
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+A0
+40
+00
+ENDCHAR
+STARTCHAR tau
+ENCODING 964
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR upsilon
+ENCODING 965
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+80
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR phi
+ENCODING 966
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+A0
+40
+40
+ENDCHAR
+STARTCHAR chi
+ENCODING 967
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+40
+60
+A0
+00
+ENDCHAR
+STARTCHAR psi
+ENCODING 968
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+40
+00
+ENDCHAR
+STARTCHAR omega
+ENCODING 969
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR iotadieresis
+ENCODING 970
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR upsilondieresis
+ENCODING 971
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR omicrontonos
+ENCODING 972
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR upsilontonos
+ENCODING 973
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR omegatonos
+ENCODING 974
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR afii10023
+ENCODING 1025
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR afii10051
+ENCODING 1026
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10052
+ENCODING 1027
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10053
+ENCODING 1028
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+C0
+80
+60
+00
+ENDCHAR
+STARTCHAR afii10054
+ENCODING 1029
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+40
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10055
+ENCODING 1030
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR afii10056
+ENCODING 1031
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR afii10057
+ENCODING 1032
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+20
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10058
+ENCODING 1033
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+60
+A0
+B0
+B0
+00
+ENDCHAR
+STARTCHAR afii10059
+ENCODING 1034
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+B0
+B0
+00
+ENDCHAR
+STARTCHAR afii10060
+ENCODING 1035
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+80
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10061
+ENCODING 1036
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+80
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii10062
+ENCODING 1038
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+A0
+40
+80
+ENDCHAR
+STARTCHAR afii10145
+ENCODING 1039
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+E0
+40
+ENDCHAR
+STARTCHAR afii10017
+ENCODING 1040
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10018
+ENCODING 1041
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10019
+ENCODING 1042
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10020
+ENCODING 1043
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10021
+ENCODING 1044
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+60
+A0
+A0
+E0
+A0
+ENDCHAR
+STARTCHAR afii10022
+ENCODING 1045
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR afii10024
+ENCODING 1046
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+40
+E0
+A0
+00
+ENDCHAR
+STARTCHAR afii10025
+ENCODING 1047
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+40
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10026
+ENCODING 1048
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+E0
+A0
+20
+00
+ENDCHAR
+STARTCHAR afii10027
+ENCODING 1049
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+A0
+E0
+A0
+20
+ENDCHAR
+STARTCHAR afii10028
+ENCODING 1050
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10029
+ENCODING 1051
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10030
+ENCODING 1052
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10031
+ENCODING 1053
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10032
+ENCODING 1054
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10033
+ENCODING 1055
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10034
+ENCODING 1056
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10035
+ENCODING 1057
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10036
+ENCODING 1058
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR afii10037
+ENCODING 1059
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+40
+40
+80
+ENDCHAR
+STARTCHAR afii10038
+ENCODING 1060
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+A0
+E0
+40
+00
+ENDCHAR
+STARTCHAR afii10039
+ENCODING 1061
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10040
+ENCODING 1062
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR afii10041
+ENCODING 1063
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+60
+20
+20
+00
+ENDCHAR
+STARTCHAR afii10042
+ENCODING 1064
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR afii10043
+ENCODING 1065
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+E0
+F0
+10
+ENDCHAR
+STARTCHAR afii10044
+ENCODING 1066
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+60
+50
+60
+00
+ENDCHAR
+STARTCHAR afii10045
+ENCODING 1067
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+D0
+B0
+D0
+00
+ENDCHAR
+STARTCHAR afii10046
+ENCODING 1068
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10047
+ENCODING 1069
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+60
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10048
+ENCODING 1070
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+D0
+D0
+D0
+A0
+00
+ENDCHAR
+STARTCHAR afii10049
+ENCODING 1071
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+60
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10065
+ENCODING 1072
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR afii10066
+ENCODING 1073
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+E0
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10067
+ENCODING 1074
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10068
+ENCODING 1075
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10069
+ENCODING 1076
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+A0
+E0
+A0
+ENDCHAR
+STARTCHAR afii10070
+ENCODING 1077
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR afii10072
+ENCODING 1078
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+B0
+60
+60
+B0
+00
+ENDCHAR
+STARTCHAR afii10073
+ENCODING 1079
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+40
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10074
+ENCODING 1080
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR afii10075
+ENCODING 1081
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR afii10076
+ENCODING 1082
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii10077
+ENCODING 1083
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10078
+ENCODING 1084
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10079
+ENCODING 1085
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10080
+ENCODING 1086
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10081
+ENCODING 1087
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10082
+ENCODING 1088
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+C0
+80
+80
+ENDCHAR
+STARTCHAR afii10083
+ENCODING 1089
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+80
+80
+60
+00
+ENDCHAR
+STARTCHAR afii10084
+ENCODING 1090
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR afii10085
+ENCODING 1091
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR afii10086
+ENCODING 1092
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+40
+40
+ENDCHAR
+STARTCHAR afii10087
+ENCODING 1093
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+40
+40
+A0
+00
+ENDCHAR
+STARTCHAR afii10088
+ENCODING 1094
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+E0
+20
+ENDCHAR
+STARTCHAR afii10089
+ENCODING 1095
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+60
+20
+00
+ENDCHAR
+STARTCHAR afii10090
+ENCODING 1096
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR afii10091
+ENCODING 1097
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+F0
+10
+ENDCHAR
+STARTCHAR afii10092
+ENCODING 1098
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+60
+50
+60
+00
+ENDCHAR
+STARTCHAR afii10093
+ENCODING 1099
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+D0
+B0
+D0
+00
+ENDCHAR
+STARTCHAR afii10094
+ENCODING 1100
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+80
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10095
+ENCODING 1101
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+60
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10096
+ENCODING 1102
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+D0
+D0
+A0
+00
+ENDCHAR
+STARTCHAR afii10097
+ENCODING 1103
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+60
+A0
+00
+ENDCHAR
+STARTCHAR afii10071
+ENCODING 1105
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR afii10099
+ENCODING 1106
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+C0
+80
+C0
+A0
+20
+ENDCHAR
+STARTCHAR afii10100
+ENCODING 1107
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10101
+ENCODING 1108
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+80
+60
+00
+ENDCHAR
+STARTCHAR afii10102
+ENCODING 1109
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10103
+ENCODING 1110
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR afii10104
+ENCODING 1111
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR afii10105
+ENCODING 1112
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+20
+20
+20
+C0
+ENDCHAR
+STARTCHAR afii10106
+ENCODING 1113
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+B0
+B0
+00
+ENDCHAR
+STARTCHAR afii10107
+ENCODING 1114
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+B0
+B0
+00
+ENDCHAR
+STARTCHAR afii10108
+ENCODING 1115
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+C0
+80
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii10109
+ENCODING 1116
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+80
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii10110
+ENCODING 1118
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+A0
+40
+80
+ENDCHAR
+STARTCHAR afii10193
+ENCODING 1119
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+E0
+40
+ENDCHAR
+STARTCHAR afii10050
+ENCODING 1168
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10098
+ENCODING 1169
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+E0
+80
+80
+00
+ENDCHAR
+STARTCHAR uni0492
+ENCODING 1170
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR uni0493
+ENCODING 1171
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR afii57664
+ENCODING 1488
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+60
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii57665
+ENCODING 1489
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+20
+F0
+00
+ENDCHAR
+STARTCHAR afii57666
+ENCODING 1490
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+40
+40
+A0
+00
+ENDCHAR
+STARTCHAR afii57667
+ENCODING 1491
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR afii57668
+ENCODING 1492
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+20
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii57669
+ENCODING 1493
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+20
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR afii57670
+ENCODING 1494
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR afii57671
+ENCODING 1495
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii57672
+ENCODING 1496
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii57673
+ENCODING 1497
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57674
+ENCODING 1498
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR afii57675
+ENCODING 1499
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii57676
+ENCODING 1500
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+20
+20
+40
+00
+ENDCHAR
+STARTCHAR afii57677
+ENCODING 1501
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR afii57678
+ENCODING 1502
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii57679
+ENCODING 1503
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR afii57680
+ENCODING 1504
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+20
+20
+20
+60
+00
+ENDCHAR
+STARTCHAR afii57681
+ENCODING 1505
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii57682
+ENCODING 1506
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+60
+C0
+00
+ENDCHAR
+STARTCHAR afii57683
+ENCODING 1507
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+20
+20
+20
+ENDCHAR
+STARTCHAR afii57684
+ENCODING 1508
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+20
+E0
+00
+ENDCHAR
+STARTCHAR afii57685
+ENCODING 1509
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+C0
+80
+80
+ENDCHAR
+STARTCHAR afii57686
+ENCODING 1510
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+40
+20
+E0
+00
+ENDCHAR
+STARTCHAR afii57687
+ENCODING 1511
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+C0
+80
+80
+ENDCHAR
+STARTCHAR afii57688
+ENCODING 1512
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR afii57689
+ENCODING 1513
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F0
+D0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR afii57690
+ENCODING 1514
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR uni1E02
+ENCODING 7682
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR uni1E03
+ENCODING 7683
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+80
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR uni1E0A
+ENCODING 7690
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR uni1E0B
+ENCODING 7691
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+20
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR uni1E1E
+ENCODING 7710
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+80
+C0
+80
+00
+ENDCHAR
+STARTCHAR uni1E1F
+ENCODING 7711
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR uni1E40
+ENCODING 7744
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR uni1E41
+ENCODING 7745
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR uni1E56
+ENCODING 7766
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+A0
+C0
+80
+00
+ENDCHAR
+STARTCHAR uni1E57
+ENCODING 7767
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+C0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR uni1E60
+ENCODING 7776
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR uni1E61
+ENCODING 7777
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR uni1E6A
+ENCODING 7786
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR uni1E6B
+ENCODING 7787
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+E0
+40
+20
+ENDCHAR
+STARTCHAR Wgrave
+ENCODING 7808
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR wgrave
+ENCODING 7809
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Wacute
+ENCODING 7810
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+80
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR wacute
+ENCODING 7811
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Wdieresis
+ENCODING 7812
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR wdieresis
+ENCODING 7813
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR Ygrave
+ENCODING 7922
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR ygrave
+ENCODING 7923
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+60
+20
+40
+ENDCHAR
+STARTCHAR uni2010
+ENCODING 8208
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2011
+ENCODING 8209
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR figuredash
+ENCODING 8210
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR endash
+ENCODING 8211
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR emdash
+ENCODING 8212
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii00208
+ENCODING 8213
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2016
+ENCODING 8214
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+A0
+A0
+ENDCHAR
+STARTCHAR underscoredbl
+ENCODING 8215
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+00
+F0
+ENDCHAR
+STARTCHAR quoteleft
+ENCODING 8216
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR quoteright
+ENCODING 8217
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+20
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR quotesinglbase
+ENCODING 8218
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+60
+20
+40
+ENDCHAR
+STARTCHAR quotereversed
+ENCODING 8219
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblleft
+ENCODING 8220
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+A0
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblright
+ENCODING 8221
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+50
+A0
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblbase
+ENCODING 8222
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+50
+50
+A0
+ENDCHAR
+STARTCHAR uni201F
+ENCODING 8223
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR dagger
+ENCODING 8224
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR daggerdbl
+ENCODING 8225
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR bullet
+ENCODING 8226
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+40
+00
+00
+ENDCHAR
+STARTCHAR uni2023
+ENCODING 8227
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+E0
+C0
+00
+00
+ENDCHAR
+STARTCHAR onedotenleader
+ENCODING 8228
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+40
+00
+ENDCHAR
+STARTCHAR twodotenleader
+ENCODING 8229
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+A0
+00
+ENDCHAR
+STARTCHAR ellipsis
+ENCODING 8230
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+B0
+00
+ENDCHAR
+STARTCHAR uni2027
+ENCODING 8231
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR perthousand
+ENCODING 8240
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+40
+80
+30
+00
+ENDCHAR
+STARTCHAR guilsinglleft
+ENCODING 8249
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+80
+40
+00
+00
+ENDCHAR
+STARTCHAR guilsinglright
+ENCODING 8250
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+20
+40
+00
+00
+ENDCHAR
+STARTCHAR uni203E
+ENCODING 8254
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR nsuperior
+ENCODING 8319
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+A0
+00
+00
+ENDCHAR
+STARTCHAR peseta
+ENCODING 8359
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+F0
+60
+40
+40
+00
+ENDCHAR
+STARTCHAR Euro
+ENCODING 8364
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+40
+20
+00
+ENDCHAR
+STARTCHAR afii61352
+ENCODING 8470
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+B0
+B0
+A0
+B0
+00
+ENDCHAR
+STARTCHAR trademark
+ENCODING 8482
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+00
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Omega
+ENCODING 8486
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+40
+A0
+00
+ENDCHAR
+STARTCHAR uni2127
+ENCODING 8487
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR oneeighth
+ENCODING 8539
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+B0
+20
+50
+20
+ENDCHAR
+STARTCHAR threeeighths
+ENCODING 8540
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+B0
+60
+D0
+20
+ENDCHAR
+STARTCHAR fiveeighths
+ENCODING 8541
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+80
+70
+A0
+50
+20
+ENDCHAR
+STARTCHAR seveneighths
+ENCODING 8542
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+B0
+A0
+50
+20
+ENDCHAR
+STARTCHAR arrowleft
+ENCODING 8592
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+F0
+40
+00
+00
+ENDCHAR
+STARTCHAR arrowup
+ENCODING 8593
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR arrowright
+ENCODING 8594
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+F0
+20
+00
+00
+ENDCHAR
+STARTCHAR arrowdown
+ENCODING 8595
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR arrowboth
+ENCODING 8596
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+F0
+50
+00
+00
+ENDCHAR
+STARTCHAR arrowupdn
+ENCODING 8597
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR universal
+ENCODING 8704
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+A0
+40
+00
+ENDCHAR
+STARTCHAR uni2201
+ENCODING 8705
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR partialdiff
+ENCODING 8706
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+60
+A0
+40
+00
+ENDCHAR
+STARTCHAR existential
+ENCODING 8707
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+20
+E0
+20
+E0
+00
+ENDCHAR
+STARTCHAR uni2204
+ENCODING 8708
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+20
+E0
+60
+E0
+80
+ENDCHAR
+STARTCHAR emptyset
+ENCODING 8709
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+A0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR Delta
+ENCODING 8710
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR gradient
+ENCODING 8711
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR element
+ENCODING 8712
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+E0
+80
+60
+00
+ENDCHAR
+STARTCHAR notelement
+ENCODING 8713
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+E0
+A0
+60
+40
+ENDCHAR
+STARTCHAR uni220A
+ENCODING 8714
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+80
+C0
+80
+40
+00
+ENDCHAR
+STARTCHAR suchthat
+ENCODING 8715
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+E0
+20
+C0
+00
+ENDCHAR
+STARTCHAR uni220C
+ENCODING 8716
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+20
+E0
+60
+C0
+80
+ENDCHAR
+STARTCHAR uni220D
+ENCODING 8717
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+C0
+40
+80
+00
+ENDCHAR
+STARTCHAR uni220E
+ENCODING 8718
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+C0
+C0
+C0
+C0
+00
+ENDCHAR
+STARTCHAR product
+ENCODING 8719
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR uni2210
+ENCODING 8720
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR summation
+ENCODING 8721
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR minus
+ENCODING 8722
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2213
+ENCODING 8723
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR uni2214
+ENCODING 8724
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR fraction
+ENCODING 8725
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+40
+80
+80
+00
+ENDCHAR
+STARTCHAR uni2216
+ENCODING 8726
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+40
+20
+20
+00
+ENDCHAR
+STARTCHAR asteriskmath
+ENCODING 8727
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+70
+E0
+50
+40
+ENDCHAR
+STARTCHAR uni2218
+ENCODING 8728
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+40
+00
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 8729
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+40
+00
+00
+ENDCHAR
+STARTCHAR radical
+ENCODING 8730
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+30
+20
+20
+A0
+60
+00
+ENDCHAR
+STARTCHAR uni221B
+ENCODING 8731
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+50
+D0
+10
+50
+30
+ENDCHAR
+STARTCHAR uni221C
+ENCODING 8732
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+D0
+50
+10
+50
+30
+ENDCHAR
+STARTCHAR proportional
+ENCODING 8733
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+50
+E0
+50
+00
+ENDCHAR
+STARTCHAR infinity
+ENCODING 8734
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+D0
+B0
+40
+00
+ENDCHAR
+STARTCHAR orthogonal
+ENCODING 8735
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+80
+80
+E0
+00
+ENDCHAR
+STARTCHAR angle
+ENCODING 8736
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR uni2221
+ENCODING 8737
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+A0
+40
+A0
+F0
+20
+ENDCHAR
+STARTCHAR uni2222
+ENCODING 8738
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+60
+A0
+A0
+60
+90
+ENDCHAR
+STARTCHAR uni2223
+ENCODING 8739
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR uni2224
+ENCODING 8740
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+40
+C0
+40
+00
+ENDCHAR
+STARTCHAR uni2225
+ENCODING 8741
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR uni2226
+ENCODING 8742
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+B0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR logicaland
+ENCODING 8743
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+40
+A0
+A0
+00
+ENDCHAR
+STARTCHAR logicalor
+ENCODING 8744
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR intersection
+ENCODING 8745
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR union
+ENCODING 8746
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR integral
+ENCODING 8747
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR uni222C
+ENCODING 8748
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+A0
+A0
+A0
+80
+ENDCHAR
+STARTCHAR uni222D
+ENCODING 8749
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+D0
+D0
+D0
+D0
+A0
+ENDCHAR
+STARTCHAR uni222E
+ENCODING 8750
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+E0
+40
+80
+ENDCHAR
+STARTCHAR uni222F
+ENCODING 8751
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+E0
+E0
+A0
+80
+ENDCHAR
+STARTCHAR uni2230
+ENCODING 8752
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+D0
+F0
+F0
+D0
+A0
+ENDCHAR
+STARTCHAR uni2231
+ENCODING 8753
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+50
+40
+80
+ENDCHAR
+STARTCHAR uni2232
+ENCODING 8754
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+C0
+40
+80
+ENDCHAR
+STARTCHAR uni2233
+ENCODING 8755
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+C0
+E0
+40
+80
+ENDCHAR
+STARTCHAR therefore
+ENCODING 8756
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+A0
+00
+ENDCHAR
+STARTCHAR uni2235
+ENCODING 8757
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A0
+00
+40
+00
+ENDCHAR
+STARTCHAR uni2236
+ENCODING 8758
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR uni2237
+ENCODING 8759
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A0
+00
+A0
+00
+ENDCHAR
+STARTCHAR uni2238
+ENCODING 8760
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2239
+ENCODING 8761
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+20
+C0
+20
+00
+ENDCHAR
+STARTCHAR uni223A
+ENCODING 8762
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+E0
+00
+A0
+00
+ENDCHAR
+STARTCHAR uni223B
+ENCODING 8763
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+50
+A0
+00
+40
+ENDCHAR
+STARTCHAR similar
+ENCODING 8764
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+50
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni223D
+ENCODING 8765
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A0
+50
+00
+00
+ENDCHAR
+STARTCHAR uni223E
+ENCODING 8766
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+D0
+B0
+00
+00
+ENDCHAR
+STARTCHAR uni223F
+ENCODING 8767
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+50
+A0
+20
+00
+ENDCHAR
+STARTCHAR uni2240
+ENCODING 8768
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+20
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR uni2241
+ENCODING 8769
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+20
+B0
+D0
+40
+80
+ENDCHAR
+STARTCHAR uni2242
+ENCODING 8770
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+00
+A0
+50
+00
+ENDCHAR
+STARTCHAR uni2243
+ENCODING 8771
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2244
+ENCODING 8772
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+D0
+B0
+40
+F0
+40
+ENDCHAR
+STARTCHAR congruent
+ENCODING 8773
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+00
+E0
+00
+E0
+ENDCHAR
+STARTCHAR uni2246
+ENCODING 8774
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+20
+F0
+40
+F0
+ENDCHAR
+STARTCHAR uni2247
+ENCODING 8775
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+20
+F0
+40
+F0
+ENDCHAR
+STARTCHAR approxequal
+ENCODING 8776
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+00
+50
+A0
+00
+ENDCHAR
+STARTCHAR uni2249
+ENCODING 8777
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+40
+50
+E0
+80
+ENDCHAR
+STARTCHAR uni224A
+ENCODING 8778
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+B0
+40
+B0
+00
+F0
+ENDCHAR
+STARTCHAR uni224B
+ENCODING 8779
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+B0
+40
+B0
+40
+B0
+ENDCHAR
+STARTCHAR uni224C
+ENCODING 8780
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+50
+00
+E0
+00
+E0
+ENDCHAR
+STARTCHAR uni224D
+ENCODING 8781
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+40
+A0
+00
+ENDCHAR
+STARTCHAR uni224E
+ENCODING 8782
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+A0
+40
+00
+ENDCHAR
+STARTCHAR uni224F
+ENCODING 8783
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2250
+ENCODING 8784
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2251
+ENCODING 8785
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+40
+ENDCHAR
+STARTCHAR uni2252
+ENCODING 8786
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+00
+E0
+00
+20
+ENDCHAR
+STARTCHAR uni2253
+ENCODING 8787
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+00
+E0
+00
+80
+ENDCHAR
+STARTCHAR uni2254
+ENCODING 8788
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+B0
+00
+B0
+00
+00
+ENDCHAR
+STARTCHAR uni2255
+ENCODING 8789
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+D0
+00
+D0
+00
+00
+ENDCHAR
+STARTCHAR uni2256
+ENCODING 8790
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+40
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2257
+ENCODING 8791
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2258
+ENCODING 8792
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2259
+ENCODING 8793
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni225A
+ENCODING 8794
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni225B
+ENCODING 8795
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni225C
+ENCODING 8796
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni225D
+ENCODING 8797
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni225E
+ENCODING 8798
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni225F
+ENCODING 8799
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR notequal
+ENCODING 8800
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+40
+E0
+80
+00
+ENDCHAR
+STARTCHAR equivalence
+ENCODING 8801
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2262
+ENCODING 8802
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+20
+E0
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni2263
+ENCODING 8803
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR lessequal
+ENCODING 8804
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR greaterequal
+ENCODING 8805
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2266
+ENCODING 8806
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2267
+ENCODING 8807
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2268
+ENCODING 8808
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+40
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2269
+ENCODING 8809
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+80
+40
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni226A
+ENCODING 8810
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+50
+00
+00
+ENDCHAR
+STARTCHAR uni226B
+ENCODING 8811
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+50
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni226C
+ENCODING 8812
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+40
+A0
+00
+ENDCHAR
+STARTCHAR uni226D
+ENCODING 8813
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+40
+E0
+80
+00
+ENDCHAR
+STARTCHAR uni226E
+ENCODING 8814
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+C0
+60
+80
+00
+ENDCHAR
+STARTCHAR uni226F
+ENCODING 8815
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+60
+C0
+80
+00
+ENDCHAR
+STARTCHAR uni2270
+ENCODING 8816
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni2271
+ENCODING 8817
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+60
+E0
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni2272
+ENCODING 8818
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+00
+50
+A0
+ENDCHAR
+STARTCHAR uni2273
+ENCODING 8819
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+E0
+00
+A0
+50
+ENDCHAR
+STARTCHAR uni2276
+ENCODING 8822
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+20
+80
+60
+C0
+ENDCHAR
+STARTCHAR uni2277
+ENCODING 8823
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+60
+80
+20
+C0
+60
+ENDCHAR
+STARTCHAR uni2278
+ENCODING 8824
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+60
+C0
+60
+C0
+ENDCHAR
+STARTCHAR uni2279
+ENCODING 8825
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+60
+C0
+60
+C0
+60
+ENDCHAR
+STARTCHAR uni227A
+ENCODING 8826
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+C0
+20
+00
+00
+ENDCHAR
+STARTCHAR uni227B
+ENCODING 8827
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+80
+60
+80
+00
+00
+ENDCHAR
+STARTCHAR uni227C
+ENCODING 8828
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+20
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni227D
+ENCODING 8829
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+80
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni227E
+ENCODING 8830
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+20
+00
+A0
+50
+ENDCHAR
+STARTCHAR uni227F
+ENCODING 8831
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+20
+00
+A0
+50
+ENDCHAR
+STARTCHAR uni2280
+ENCODING 8832
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+C0
+60
+40
+00
+ENDCHAR
+STARTCHAR uni2281
+ENCODING 8833
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+60
+C0
+40
+00
+ENDCHAR
+STARTCHAR propersubset
+ENCODING 8834
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+80
+60
+00
+00
+ENDCHAR
+STARTCHAR propersuperset
+ENCODING 8835
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+20
+C0
+00
+00
+ENDCHAR
+STARTCHAR notsubset
+ENCODING 8836
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+C0
+60
+40
+00
+ENDCHAR
+STARTCHAR uni2285
+ENCODING 8837
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+60
+C0
+40
+00
+ENDCHAR
+STARTCHAR reflexsubset
+ENCODING 8838
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+60
+00
+E0
+00
+ENDCHAR
+STARTCHAR reflexsuperset
+ENCODING 8839
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+C0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2288
+ENCODING 8840
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+60
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni2289
+ENCODING 8841
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+60
+C0
+40
+E0
+40
+ENDCHAR
+STARTCHAR uni228A
+ENCODING 8842
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+60
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni228B
+ENCODING 8843
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+C0
+40
+E0
+80
+ENDCHAR
+STARTCHAR revlogicalnot
+ENCODING 8976
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+80
+00
+00
+ENDCHAR
+STARTCHAR integraltp
+ENCODING 8992
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR integralbt
+ENCODING 8993
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+20
+20
+20
+40
+ENDCHAR
+STARTCHAR uni23BA
+ENCODING 9146
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BB
+ENCODING 9147
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BC
+ENCODING 9148
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni23BD
+ENCODING 9149
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+F0
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 9225
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+70
+20
+20
+ENDCHAR
+STARTCHAR uni240A
+ENCODING 9226
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+E0
+60
+40
+40
+ENDCHAR
+STARTCHAR uni240B
+ENCODING 9227
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+70
+20
+20
+ENDCHAR
+STARTCHAR uni240C
+ENCODING 9228
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+C0
+80
+60
+60
+40
+ENDCHAR
+STARTCHAR uni240D
+ENCODING 9229
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+E0
+50
+60
+50
+ENDCHAR
+STARTCHAR uni2423
+ENCODING 9251
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+90
+F0
+ENDCHAR
+STARTCHAR uni2424
+ENCODING 9252
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+B0
+90
+20
+20
+30
+ENDCHAR
+STARTCHAR SF100000
+ENCODING 9472
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2501
+ENCODING 9473
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F8
+F8
+00
+00
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9474
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR uni2503
+ENCODING 9475
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR uni2504
+ENCODING 9476
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni2505
+ENCODING 9477
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A8
+A8
+00
+00
+ENDCHAR
+STARTCHAR uni2506
+ENCODING 9478
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR uni2507
+ENCODING 9479
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+60
+00
+60
+00
+ENDCHAR
+STARTCHAR uni2508
+ENCODING 9480
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni2509
+ENCODING 9481
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A8
+A8
+00
+00
+ENDCHAR
+STARTCHAR uni250A
+ENCODING 9482
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR uni250B
+ENCODING 9483
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+60
+00
+60
+00
+ENDCHAR
+STARTCHAR SF010000
+ENCODING 9484
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+70
+40
+40
+ENDCHAR
+STARTCHAR uni250D
+ENCODING 9485
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+70
+40
+40
+ENDCHAR
+STARTCHAR uni250E
+ENCODING 9486
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+70
+60
+60
+ENDCHAR
+STARTCHAR uni250F
+ENCODING 9487
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+70
+60
+60
+ENDCHAR
+STARTCHAR SF030000
+ENCODING 9488
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+C0
+40
+40
+ENDCHAR
+STARTCHAR uni2511
+ENCODING 9489
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+C0
+40
+40
+ENDCHAR
+STARTCHAR uni2512
+ENCODING 9490
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+E0
+60
+60
+ENDCHAR
+STARTCHAR uni2513
+ENCODING 9491
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+E0
+60
+60
+ENDCHAR
+STARTCHAR SF020000
+ENCODING 9492
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+70
+00
+00
+ENDCHAR
+STARTCHAR uni2515
+ENCODING 9493
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+70
+00
+00
+ENDCHAR
+STARTCHAR uni2516
+ENCODING 9494
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+00
+00
+ENDCHAR
+STARTCHAR uni2517
+ENCODING 9495
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+70
+00
+00
+ENDCHAR
+STARTCHAR SF040000
+ENCODING 9496
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+C0
+00
+00
+ENDCHAR
+STARTCHAR uni2519
+ENCODING 9497
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+C0
+00
+00
+ENDCHAR
+STARTCHAR uni251A
+ENCODING 9498
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni251B
+ENCODING 9499
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+E0
+00
+00
+ENDCHAR
+STARTCHAR SF080000
+ENCODING 9500
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+70
+40
+40
+ENDCHAR
+STARTCHAR uni251D
+ENCODING 9501
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+70
+40
+40
+ENDCHAR
+STARTCHAR uni251E
+ENCODING 9502
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+40
+40
+ENDCHAR
+STARTCHAR uni251F
+ENCODING 9503
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+70
+60
+60
+ENDCHAR
+STARTCHAR uni2520
+ENCODING 9504
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+60
+60
+ENDCHAR
+STARTCHAR uni2521
+ENCODING 9505
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+70
+40
+40
+ENDCHAR
+STARTCHAR uni2522
+ENCODING 9506
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+70
+60
+60
+ENDCHAR
+STARTCHAR uni2523
+ENCODING 9507
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+70
+60
+60
+ENDCHAR
+STARTCHAR SF090000
+ENCODING 9508
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+C0
+40
+40
+ENDCHAR
+STARTCHAR uni2525
+ENCODING 9509
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+C0
+40
+40
+ENDCHAR
+STARTCHAR uni2526
+ENCODING 9510
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+40
+40
+ENDCHAR
+STARTCHAR uni2527
+ENCODING 9511
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+E0
+60
+60
+ENDCHAR
+STARTCHAR uni2528
+ENCODING 9512
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+60
+60
+ENDCHAR
+STARTCHAR uni2529
+ENCODING 9513
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+E0
+40
+40
+ENDCHAR
+STARTCHAR uni252A
+ENCODING 9514
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+E0
+E0
+60
+60
+ENDCHAR
+STARTCHAR uni252B
+ENCODING 9515
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+E0
+60
+60
+ENDCHAR
+STARTCHAR SF060000
+ENCODING 9516
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni252D
+ENCODING 9517
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni252E
+ENCODING 9518
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni252F
+ENCODING 9519
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2530
+ENCODING 9520
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2531
+ENCODING 9521
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2532
+ENCODING 9522
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2533
+ENCODING 9523
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+F0
+60
+60
+ENDCHAR
+STARTCHAR SF070000
+ENCODING 9524
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2535
+ENCODING 9525
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2536
+ENCODING 9526
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2537
+ENCODING 9527
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2538
+ENCODING 9528
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2539
+ENCODING 9529
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni253A
+ENCODING 9530
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni253B
+ENCODING 9531
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+F0
+00
+00
+ENDCHAR
+STARTCHAR SF050000
+ENCODING 9532
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni253D
+ENCODING 9533
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni253E
+ENCODING 9534
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni253F
+ENCODING 9535
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2540
+ENCODING 9536
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2541
+ENCODING 9537
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2542
+ENCODING 9538
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2543
+ENCODING 9539
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2544
+ENCODING 9540
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2545
+ENCODING 9541
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+E0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2546
+ENCODING 9542
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2547
+ENCODING 9543
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2548
+ENCODING 9544
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2549
+ENCODING 9545
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni254A
+ENCODING 9546
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni254B
+ENCODING 9547
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni254C
+ENCODING 9548
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni254D
+ENCODING 9549
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A0
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni254E
+ENCODING 9550
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+40
+00
+40
+40
+ENDCHAR
+STARTCHAR uni254F
+ENCODING 9551
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+60
+00
+60
+60
+ENDCHAR
+STARTCHAR SF430000
+ENCODING 9552
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+F0
+00
+ENDCHAR
+STARTCHAR SF240000
+ENCODING 9553
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR SF510000
+ENCODING 9554
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+40
+70
+40
+ENDCHAR
+STARTCHAR SF520000
+ENCODING 9555
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+70
+60
+60
+ENDCHAR
+STARTCHAR SF390000
+ENCODING 9556
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+40
+70
+60
+ENDCHAR
+STARTCHAR SF220000
+ENCODING 9557
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+40
+C0
+40
+ENDCHAR
+STARTCHAR SF210000
+ENCODING 9558
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+E0
+60
+60
+ENDCHAR
+STARTCHAR SF250000
+ENCODING 9559
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+20
+E0
+60
+ENDCHAR
+STARTCHAR SF500000
+ENCODING 9560
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+40
+70
+00
+ENDCHAR
+STARTCHAR SF490000
+ENCODING 9561
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+00
+00
+ENDCHAR
+STARTCHAR SF380000
+ENCODING 9562
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+40
+70
+00
+ENDCHAR
+STARTCHAR SF280000
+ENCODING 9563
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+40
+C0
+00
+ENDCHAR
+STARTCHAR SF270000
+ENCODING 9564
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+00
+00
+ENDCHAR
+STARTCHAR SF260000
+ENCODING 9565
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+20
+E0
+00
+ENDCHAR
+STARTCHAR SF360000
+ENCODING 9566
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+40
+70
+40
+ENDCHAR
+STARTCHAR SF370000
+ENCODING 9567
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+60
+60
+ENDCHAR
+STARTCHAR SF420000
+ENCODING 9568
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+40
+70
+60
+ENDCHAR
+STARTCHAR SF190000
+ENCODING 9569
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+40
+C0
+40
+ENDCHAR
+STARTCHAR SF200000
+ENCODING 9570
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+60
+60
+ENDCHAR
+STARTCHAR SF230000
+ENCODING 9571
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+20
+E0
+60
+ENDCHAR
+STARTCHAR SF470000
+ENCODING 9572
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+F0
+40
+ENDCHAR
+STARTCHAR SF480000
+ENCODING 9573
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+60
+60
+ENDCHAR
+STARTCHAR SF410000
+ENCODING 9574
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+F0
+60
+ENDCHAR
+STARTCHAR SF450000
+ENCODING 9575
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+00
+F0
+00
+ENDCHAR
+STARTCHAR SF460000
+ENCODING 9576
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+00
+00
+ENDCHAR
+STARTCHAR SF400000
+ENCODING 9577
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+00
+F0
+00
+ENDCHAR
+STARTCHAR SF540000
+ENCODING 9578
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+40
+F0
+40
+ENDCHAR
+STARTCHAR SF530000
+ENCODING 9579
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+60
+60
+ENDCHAR
+STARTCHAR SF440000
+ENCODING 9580
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+00
+F0
+60
+ENDCHAR
+STARTCHAR uni256D
+ENCODING 9581
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+30
+40
+40
+ENDCHAR
+STARTCHAR uni256E
+ENCODING 9582
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+80
+40
+40
+ENDCHAR
+STARTCHAR uni256F
+ENCODING 9583
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+80
+00
+00
+ENDCHAR
+STARTCHAR uni2570
+ENCODING 9584
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+30
+00
+00
+ENDCHAR
+STARTCHAR uni2571
+ENCODING 9585
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR uni2572
+ENCODING 9586
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+40
+20
+20
+10
+ENDCHAR
+STARTCHAR uni2573
+ENCODING 9587
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+60
+60
+90
+90
+ENDCHAR
+STARTCHAR uni2574
+ENCODING 9588
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+C0
+00
+00
+ENDCHAR
+STARTCHAR uni2575
+ENCODING 9589
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+40
+00
+00
+ENDCHAR
+STARTCHAR uni2576
+ENCODING 9590
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+70
+00
+00
+ENDCHAR
+STARTCHAR uni2577
+ENCODING 9591
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+40
+40
+40
+ENDCHAR
+STARTCHAR uni2578
+ENCODING 9592
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+C0
+00
+00
+ENDCHAR
+STARTCHAR uni2579
+ENCODING 9593
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+60
+00
+00
+ENDCHAR
+STARTCHAR uni257A
+ENCODING 9594
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+70
+00
+00
+ENDCHAR
+STARTCHAR uni257B
+ENCODING 9595
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+60
+60
+60
+ENDCHAR
+STARTCHAR uni257C
+ENCODING 9596
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+30
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni257D
+ENCODING 9597
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+60
+60
+60
+ENDCHAR
+STARTCHAR uni257E
+ENCODING 9598
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni257F
+ENCODING 9599
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+60
+40
+40
+ENDCHAR
+STARTCHAR upblock
+ENCODING 9600
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F8
+F8
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2581
+ENCODING 9601
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+F0
+ENDCHAR
+STARTCHAR uni2582
+ENCODING 9602
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+F8
+ENDCHAR
+STARTCHAR uni2583
+ENCODING 9603
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+F8
+F8
+ENDCHAR
+STARTCHAR dnblock
+ENCODING 9604
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR uni2585
+ENCODING 9605
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR uni2586
+ENCODING 9606
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F8
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR uni2587
+ENCODING 9607
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F8
+F8
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR block
+ENCODING 9608
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F8
+F8
+F8
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR uni2589
+ENCODING 9609
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+F0
+F0
+F0
+F0
+F0
+ENDCHAR
+STARTCHAR uni258A
+ENCODING 9610
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+E0
+E0
+E0
+E0
+E0
+ENDCHAR
+STARTCHAR uni258B
+ENCODING 9611
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+E0
+E0
+E0
+E0
+E0
+ENDCHAR
+STARTCHAR lfblock
+ENCODING 9612
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni258D
+ENCODING 9613
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni258E
+ENCODING 9614
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR uni258F
+ENCODING 9615
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR rtblock
+ENCODING 9616
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR ltshade
+ENCODING 9617
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+80
+20
+80
+20
+ENDCHAR
+STARTCHAR shade
+ENCODING 9618
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A8
+50
+A8
+50
+A8
+50
+ENDCHAR
+STARTCHAR dkshade
+ENCODING 9619
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B8
+E8
+B8
+E8
+B8
+E8
+ENDCHAR
+STARTCHAR uni2594
+ENCODING 9620
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2595
+ENCODING 9621
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR filledbox
+ENCODING 9632
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR H22073
+ENCODING 9633
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR uni25C6
+ENCODING 9670
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+E0
+40
+00
+ENDCHAR
+STARTCHAR spade
+ENCODING 9824
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR club
+ENCODING 9827
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+40
+E0
+00
+ENDCHAR
+STARTCHAR heart
+ENCODING 9829
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+40
+00
+ENDCHAR
+STARTCHAR diamond
+ENCODING 9830
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+40
+00
+00
+ENDCHAR
+STARTCHAR uni2669
+ENCODING 9833
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+C0
+80
+00
+ENDCHAR
+STARTCHAR musicalnote
+ENCODING 9834
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+40
+C0
+80
+00
+ENDCHAR
+STARTCHAR musicalnotedbl
+ENCODING 9835
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+50
+50
+50
+A0
+00
+ENDCHAR
+STARTCHAR uni266C
+ENCODING 9836
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+70
+50
+50
+A0
+00
+ENDCHAR
+STARTCHAR uni266D
+ENCODING 9837
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+E0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR uni266E
+ENCODING 9838
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+A0
+E0
+20
+00
+ENDCHAR
+STARTCHAR uni266F
+ENCODING 9839
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR uniFFFD
+ENCODING 65533
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+90
+D0
+F0
+D0
+F0
+ENDCHAR
+ENDFONT
diff --git a/src/col64/cruft/col64font_ext.hex b/src/col64/cruft/col64font_ext.hex
new file mode 100644
index 0000000..2fefbf5
--- /dev/null
+++ b/src/col64/cruft/col64font_ext.hex
@@ -0,0 +1,920 @@
+0000:A000A000A000
+0020:000000000000
+0021:404040004000
+0022:A0A000000000
+0023:A0F0A0F0A000
+0024:70A06050E000
+0025:009020409000
+0026:40A040A0D000
+0027:202040000000
+0028:204040402000
+0029:402020204000
+002A:A040E040A000
+002B:4040E0404000
+002C:000000204000
+002D:0000F0000000
+002E:000000004000
+002F:202040808000
+0030:6090B0D06000
+0031:40C04040E000
+0032:60902040F000
+0033:E0106010E000
+0034:2060A0F02000
+0035:F080E010E000
+0036:7080E0906000
+0037:F01020404000
+0038:609060906000
+0039:60907010E000
+003A:004000004000
+003B:002000204000
+003C:204080402000
+003D:00F000F00000
+003E:804020408000
+003F:709020002000
+0040:60B0B0806000
+0041:6090F0909000
+0042:E090E090E000
+0043:609080906000
+0044:E0909090E000
+0045:F080E080F000
+0046:F080E0808000
+0047:7080B0906000
+0048:9090F0909000
+0049:E0404040E000
+004A:301010906000
+004B:90A0C0A09000
+004C:80808080F000
+004D:A0F0D0909000
+004E:90D0B0909000
+004F:609090906000
+0050:E090E0808000
+0051:609090A05000
+0052:E090E0A09000
+0053:70806010E000
+0054:F04040404000
+0055:909090906000
+0056:909090A04000
+0057:9090D0F0A000
+0058:909060909000
+0059:909060204000
+005A:F0204080F000
+005B:604040406000
+005C:808040202000
+005D:602020206000
+005E:40A000000000
+005F:00000000F000
+0060:404020000000
+0061:007090B05000
+0062:8080E090E000
+0063:007080807000
+0064:101070907000
+0065:006090E07000
+0066:6040E0404000
+0067:007090701000
+0068:8080E0909000
+0069:4000C040E000
+006A:200060202000
+006B:80A0C0A09000
+006C:C0404040E000
+006D:00A0F0D09000
+006E:00E090909000
+006F:006090906000
+0070:00E090E08000
+0071:007090701000
+0072:00A0D0808000
+0073:0070C030E000
+0074:40E040402000
+0075:009090906000
+0076:009090A04000
+0077:0090D0F0A000
+0078:009060609000
+0079:009090602000
+007A:00F02040F000
+007B:604080406000
+007C:404040404000
+007D:C0402040C000
+007E:0050A0000000
+007F:60C08010C000
+00A0:000000000000
+00A1:400040404000
+00A2:40E080E04000
+00A3:20406040A000
+00A4:009060609000
+00A5:A040E0404000
+00A6:404000404000
+00A7:60C0A06020C0
+00A8:A00000000000
+00A9:6090D0D09060
+00AA:60A06000E000
+00AB:0050A0500000
+00AC:0000E0200000
+00AD:0000E0000000
+00AE:60F0D0600000
+00AF:E00000000000
+00B0:40A040000000
+00B1:40E04000E000
+00B2:C04080C00000
+00B3:C04080408000
+00B4:204000000000
+00B5:00A0A0A0C080
+00B6:70D0D0505000
+00B7:000040000000
+00B8:000000204000
+00B9:40C040400000
+00BA:40A04000E000
+00BB:00A050A00000
+00BC:808080507010
+00BD:8080B0102030
+00BE:C0408050B010
+00BF:400040806000
+00C0:8040A0E0A000
+00C1:2040A0E0A000
+00C2:C040A0E0A000
+00C3:60C0A0E0A000
+00C4:A040A0E0A000
+00C5:4040A0E0A000
+00C6:70A0F0A0B000
+00C7:40A080A04080
+00C8:80E0C080E000
+00C9:20E0C080E000
+00CA:60E0C080E000
+00CB:A0E0C080E000
+00CC:80E04040E000
+00CD:20E04040E000
+00CE:40E04040E000
+00CF:A0404040E000
+00D0:E050D050E000
+00D1:50A0E0E0A000
+00D2:8040A0A04000
+00D3:2040A0A04000
+00D4:4040A0A04000
+00D5:70E0A0A04000
+00D6:A040A0A04000
+00D7:00A040A00000
+00D8:60A0E0A0C000
+00D9:8040A0A0E000
+00DA:2040A0A0E000
+00DB:4000A0A0E000
+00DC:A000A0A0E000
+00DD:2000A0404000
+00DE:80C0A0C08000
+00DF:40A0C0A0E080
+00E0:804060A06000
+00E1:204060A06000
+00E2:600060A06000
+00E3:50A060A06000
+00E4:A00060A06000
+00E5:400060A06000
+00E6:0070B0A07000
+00E7:0040A0806040
+00E8:8040A0C06000
+00E9:2040A0C06000
+00EA:C040A0C06000
+00EB:A040A0C06000
+00EC:80404040E000
+00ED:20C04040E000
+00EE:40A04040E000
+00EF:A000C040E000
+00F0:A04060A04000
+00F1:50A0C0A0A000
+00F2:804040A04000
+00F3:204040A04000
+00F4:400040A04000
+00F5:E00040A04000
+00F6:A00040A04000
+00F7:4000E0004000
+00F8:0060A0A0C000
+00F9:8040A0A06000
+00FA:2040A0A06000
+00FB:4000A0A06000
+00FC:A000A0A06000
+00FD:2040A0E020C0
+00FE:8080C0A0C080
+00FF:A000A0E020C0
+0100:E040A0E0A000
+0101:E00060A06000
+0102:A040A0E0A000
+0103:A04060A06000
+0104:0040A0E0A020
+0105:000060A06020
+0106:60A080A04000
+0107:2040A0806000
+0108:E0A080A04000
+0109:600060806000
+010A:40E080A04000
+010B:400060806000
+010C:E0A080A04000
+010D:A04060806000
+010E:E0C0A0A0C000
+010F:302060A06000
+0110:C0A0E0A0C000
+0111:602060A06000
+0112:E0E0C080E000
+0113:E040A0C06000
+0114:A0E0C080E000
+0115:A040A0C06000
+0116:40E0C080E000
+0117:4040A0C06000
+0118:E080C080E020
+0119:0040A0C06040
+011A:A0E0C080E000
+011B:A040A0C06000
+011C:606080A06000
+011D:6060A06020C0
+011E:A06080A06000
+011F:A040A06020C0
+0120:406080A06000
+0121:4060A06020C0
+0122:6080A0A04040
+0123:4060A06020C0
+0124:6000A0E0A000
+0125:40A0C0A0A000
+0126:A0E0A0E0A000
+0127:80C0C0A0A000
+0128:50A04040E000
+0129:50A0C040E000
+012A:E000E040E000
+012B:E000C040E000
+012C:A040E040E000
+012D:A040C040E000
+012E:E0404040E020
+012F:4000C040E020
+0130:4000E040E000
+0131:0000C040E000
+0132:80A0A0A02060
+0133:A000A0A02040
+0134:60A020A04000
+0135:40A0002020C0
+0136:A0A0C0A02040
+0137:80A0C0A02040
+0138:00A0A0C0A000
+0139:40808080E000
+013A:20C04040E000
+013B:80808080E020
+013C:C0404040E020
+013D:A0C08080E000
+013E:D0404040E000
+013F:8080A080E000
+0140:C0405040E000
+0141:80A0C080E000
+0142:C060C040E000
+0143:20A0E0A08000
+0144:2040C0A0A000
+0145:20A0E0A08020
+0146:00C0A0A00040
+0147:20A0E0A08000
+0148:A040C0A0A000
+0149:8000C0A0A000
+014A:A0E0E0A02040
+014B:00C0A0A02040
+014C:E040A0A04000
+014D:E00040A04000
+014E:A040A0A04000
+014F:A04040A04000
+0150:A040A0A04000
+0151:A0A040A04000
+0152:50A0B0A07000
+0153:0070B0A07000
+0154:20C0A0C0A000
+0155:2000A0C08000
+0156:C0A0C0A00040
+0157:00A0C0808020
+0158:60C0A0C0A000
+0159:6000A0C08000
+015A:2060C020C000
+015B:2060C020C000
+015C:6060C020C000
+015D:6060C020C000
+015E:60804020C040
+015F:0060C020E040
+0160:6060C020E000
+0161:6060C020C000
+0162:E04040402040
+0163:40E040402040
+0164:A040E0404000
+0165:A040E0402000
+0166:E040E0404000
+0167:E040E0402000
+0168:D020A0A0E000
+0169:50A000A06000
+016A:E000A0A0E000
+016B:E000A0A06000
+016C:A040A0A0E000
+016D:A04000A06000
+016E:4000A0A0E000
+016F:4000A0A06000
+0170:A000A0A0E000
+0171:A000A0A06000
+0172:00A0A0A04020
+0173:00A0A0A06040
+0174:40A0A0E0A000
+0175:4000A0E0E000
+0176:6000A0404000
+0177:4000A0408000
+0178:A000A0404000
+0179:40E04080E000
+017A:40E04080E000
+017B:40E04080E000
+017C:40E04080E000
+017D:A0E04080E000
+017E:A0E04080E000
+017F:2040C0404000
+018F:00C060A04000
+0192:2040E0404080
+0218:60804020C040
+0219:0060C020E040
+021A:E04040400040
+021B:40E040402040
+0259:00C060A04000
+02C6:40A000000000
+02C7:A04000000000
+02C9:E00000000000
+02D8:906000000000
+02D9:400000000000
+02DA:40A040000000
+02DB:0000004080C0
+02DC:50A000000000
+02DD:A0A000000000
+0374:204000000000
+0375:000000004080
+037A:000000004060
+037E:004000004080
+0384:204000000000
+0385:B04000000000
+0386:C0A0E0A0A000
+0387:000040000000
+0388:E0C060406000
+0389:A020E0A0A000
+038A:E0C04040E000
+038C:C0A0A0A04000
+038E:A0A0C0404000
+038F:C0A0A040A000
+0390:B04000402000
+0391:40A0E0A0A000
+0392:C0A0C0A0C000
+0393:E08080808000
+0394:4040A0A0E000
+0395:E080C080E000
+0396:E0204080E000
+0397:A0A0E0A0A000
+0398:40A0E0A04000
+0399:E0404040E000
+039A:A0A0C0A0A000
+039B:4040A0A0A000
+039C:A0E0A0A0A000
+039D:20A0E0A08000
+039E:E0004000E000
+039F:40A0A0A04000
+03A0:E0A0A0A0A000
+03A1:C0A0C0808000
+03A3:E0804080E000
+03A4:E04040404000
+03A5:A0A040404000
+03A6:40E0A0E04000
+03A7:A0A040A0A000
+03A8:A0E0E0404000
+03A9:40A0A040A000
+03AA:A000E040E000
+03AB:A000A0404000
+03AC:408060A06000
+03AD:20C040806000
+03AE:2040C0A02040
+03AF:200040402000
+03B0:B040A0A0C000
+03B1:0050A0A05000
+03B2:40A0C0A0C000
+03B3:00A060404000
+03B4:608040A04000
+03B5:00E0C0806000
+03B6:E04080E02040
+03B7:00C0A0A02040
+03B8:40A0E0A04000
+03B9:004040402000
+03BA:00A0A0C0A000
+03BB:C02060A0A000
+03BC:00A0A0A0C080
+03BD:00A0A0604000
+03BE:60A040806000
+03BF:0040A0A04000
+03C0:00E0A0A0A000
+03C1:0040A0A0C080
+03C2:00608040C000
+03C3:0060C0A04000
+03C4:00E040402000
+03C5:0080A0A0C000
+03C6:0040E0A04040
+03C7:00A04060A000
+03C8:00A0E0E04000
+03C9:00A0A0E0E000
+03CA:A00040402000
+03CB:A000A0A0C000
+03CC:204040A04000
+03CD:2000A0A0C000
+03CE:2000A0E0E000
+0401:A0E0C080E000
+0402:E080C0A0A000
+0403:20E080808000
+0404:6080C0806000
+0405:60804020C000
+0406:E0404040E000
+0407:A0E04040E000
+0408:202020A04000
+0409:E060A0B0B000
+040A:A0A0E0B0B000
+040B:C080C0A0A000
+040C:2080A0C0A000
+040E:A04000A04080
+040F:A0A0A0A0E040
+0410:40A0E0A0A000
+0411:E080C0A0C000
+0412:C0A0C0A0C000
+0413:E08080808000
+0414:E060A0A0E0A0
+0415:E080C080E000
+0416:A0E040E0A000
+0417:C0204020C000
+0418:80A0E0A02000
+0419:6080A0E0A020
+041A:A0A0C0A0A000
+041B:60A0A0A0A000
+041C:A0E0A0A0A000
+041D:A0A0E0A0A000
+041E:40A0A0A04000
+041F:E0A0A0A0A000
+0420:C0A0C0808000
+0421:40A080A04000
+0422:E04040404000
+0423:A0A0A0404080
+0424:40E0A0E04000
+0425:A0A040A0A000
+0426:A0A0A0A0E000
+0427:A0A060202000
+0428:A0A0E0E0E000
+0429:A0A0E0E0F010
+042A:C04060506000
+042B:9090D0B0D000
+042C:8080C0A0C000
+042D:C0206020C000
+042E:A0D0D0D0A000
+042F:60A060A0A000
+0430:0060A0A06000
+0431:6080E0A04000
+0432:00E0C0A0C000
+0433:00E080808000
+0434:0060A0A0E0A0
+0435:0040A0C06000
+0436:00B06060B000
+0437:00E04020C000
+0438:00A0E0E0A000
+0439:A040A0E0A000
+043A:00A0A0C0A000
+043B:0060A0A0A000
+043C:00A0E0A0A000
+043D:00A0E0A0A000
+043E:0040A0A04000
+043F:00E0A0A0A000
+0440:00C0A0C08080
+0441:006080806000
+0442:00E040404000
+0443:00A0A06020C0
+0444:4040A0A04040
+0445:00A04040A000
+0446:00A0A0A0E020
+0447:00A0A0602000
+0448:00A0E0E0E000
+0449:00A0E0E0F010
+044A:00C060506000
+044B:0090D0B0D000
+044C:0080C0A0C000
+044D:00C06020C000
+044E:00A0D0D0A000
+044F:0060A060A000
+0451:A040A0C06000
+0452:80C080C0A020
+0453:2040E0808000
+0454:0060C0806000
+0455:0060C020C000
+0456:4000C040E000
+0457:A000C040E000
+0458:2000202020C0
+0459:0060A0B0B000
+045A:00A0E0B0B000
+045B:80C080C0A000
+045C:2080A0C0A000
+045E:A04000A04080
+045F:00A0A0A0E040
+0490:20E080808000
+0491:0020E0808000
+0492:6040E0404000
+0493:006040E04000
+05D0:00A060C0A000
+05D1:00E02020F000
+05D2:80404040A000
+05D3:00E020202000
+05D4:80E020A0A000
+05D5:402020202000
+05D6:806040404000
+05D7:00E0A0A0A000
+05D8:A0A0A0A0C000
+05D9:C02020000000
+05DA:00E020202020
+05DB:00E02020C000
+05DC:80E020204000
+05DD:8060A0A0E000
+05DE:8060A0A0A000
+05DF:806020202000
+05E0:402020206000
+05E1:8060A0A04000
+05E2:A0A0A060C000
+05E3:00E0A0202020
+05E4:00E0A020E000
+05E5:00A0A0C08080
+05E6:00A04020E000
+05E7:00E020C08080
+05E8:00C020202000
+05E9:00F0D0A0E000
+05EA:8060A0A0A000
+1E02:40E0C0A0C000
+1E03:A080C0A0C000
+1E0A:40C0A0A0C000
+1E0B:A02060A06000
+1E1E:40E080C08000
+1E1F:802040E04000
+1E40:4000E0A0A000
+1E41:4000A0E0A000
+1E56:40C0A0C08000
+1E57:4000C0A0C080
+1E60:40E0C020C000
+1E61:4060C020C000
+1E6A:40E040404000
+1E6B:400040E04020
+1E80:8020A0E0E000
+1E81:8040A0A0E000
+1E82:2080A0E0E000
+1E83:2040A0A0E000
+1E84:A000A0E0E000
+1E85:A000A0E0E000
+1EF2:8020A0404000
+1EF3:8040A0602040
+2010:000060000000
+2011:000060000000
+2012:0000E0000000
+2013:0000E0000000
+2014:0000F0000000
+2015:0000F0000000
+2016:A0A0A0A0A0A0
+2017:000000F000F0
+2018:204060000000
+2019:602040000000
+201A:000000602040
+201B:604020000000
+201C:50A0A0000000
+201D:5050A0000000
+201E:0000005050A0
+201F:A0A050000000
+2020:40E040404000
+2021:40E040E04000
+2022:0040E0400000
+2023:00C0E0C00000
+2024:000000004000
+2025:00000000A000
+2026:00000000B000
+2027:000040000000
+2030:802040803000
+2039:004080400000
+203A:004020400000
+203E:F80000000000
+207F:00C0A0A00000
+20A7:60F060404000
+20AC:2040E0402000
+2116:C0B0B0A0B000
+2122:E04000E0A000
+2126:40A0A040A000
+2127:A040A0A04000
+215B:8080B0205020
+215C:C040B060D020
+215D:C08070A05020
+215E:C040B0A05020
+2190:0040F0400000
+2191:0040E0404000
+2192:0020F0200000
+2193:004040E04000
+2194:0050F0500000
+2195:40E040E04000
+2200:A0A0E0A04000
+2201:40A080A04000
+2202:C02060A04000
+2203:E020E020E000
+2204:F020E060E080
+2205:2060A0A0C080
+2206:4040A0A0E000
+2207:E0A0A0404000
+2208:6080E0806000
+2209:70A0E0A06040
+220A:4080C0804000
+220B:C020E020C000
+220C:D020E060C080
+220D:8040C0408000
+220E:C0C0C0C0C000
+220F:E0A0A0A0A000
+2210:A0A0A0A0E000
+2211:E0804080E000
+2212:0000E0000000
+2213:E00040E04000
+2214:400040E04000
+2215:202040808000
+2216:808040202000
+2217:20A070E05040
+2218:0040A0400000
+2219:0040E0400000
+221A:302020A06000
+221B:D050D0105030
+221C:D0D050105030
+221D:000050E05000
+221E:0020D0B04000
+221F:00008080E000
+2220:00204080E000
+2221:10A040A0F020
+2222:9060A0A06090
+2223:404040404000
+2224:406040C04000
+2225:A0A0A0A0A000
+2226:A0B0E0A0A000
+2227:004040A0A000
+2228:00A0A0404000
+2229:0040A0A0A000
+222A:00A0A0A04000
+222B:204040404080
+222C:50A0A0A0A080
+222D:50D0D0D0D0A0
+222E:2040E0E04080
+222F:50A0E0E0A080
+2230:50D0F0F0D0A0
+2231:2040E0504080
+2232:2040E0C04080
+2233:2040C0E04080
+2234:00004000A000
+2235:0000A0004000
+2236:000040004000
+2237:0000A000A000
+2238:004000E00000
+2239:000020C02000
+223A:A000E000A000
+223B:200050A00040
+223C:000050A00000
+223D:0000A0500000
+223E:0000D0B00000
+223F:004050A02000
+2240:402040402000
+2241:1020B0D04080
+2242:00E000A05000
+2243:0050A000E000
+2244:20D0B040F040
+2245:50A000E000E0
+2246:50A020F040F0
+2247:70A020F040F0
+2248:50A00050A000
+2249:70A04050E080
+224A:40B040B000F0
+224B:40B040B040B0
+224C:A05000E000E0
+224D:A0400040A000
+224E:40A000A04000
+224F:40A000E00000
+2250:4000E000E000
+2251:40E000E00040
+2252:80E000E00020
+2253:20E000E00080
+2254:00B000B00000
+2255:00D000D00000
+2256:00E040E00000
+2257:40E000E00000
+2258:40E000E00000
+2259:40E000E00000
+225A:A0E000E00000
+225B:40E000E00000
+225C:40E000E00000
+225D:4000E000E000
+225E:4000E000E000
+225F:4000E000E000
+2260:20E040E08000
+2261:E000E000E000
+2262:E020E040E080
+2263:E000E000E000
+2264:2040E000E000
+2265:8040E000E000
+2266:2040E000E000
+2267:8040E000E000
+2268:002040E00000
+2269:008040E00000
+226A:0050A0500000
+226B:00A050A00000
+226C:A040A040A000
+226D:20E040E08000
+226E:2060C0608000
+226F:20C060C08000
+2270:2040E040E080
+2271:A060E040E080
+2272:2040E00050A0
+2273:8040E000A050
+2276:60C0208060C0
+2277:C0608020C060
+2278:60C060C060C0
+2279:C060C060C060
+227A:0020C0200000
+227B:008060800000
+227C:20C02000E000
+227D:80608000E000
+227E:20C02000A050
+227F:20C02000A050
+2280:4060C0604000
+2281:40C060C04000
+2282:006080600000
+2283:00C020C00000
+2284:4060C0604000
+2285:40C060C04000
+2286:60806000E000
+2287:C020C000E000
+2288:60A06040E080
+2289:C060C040E040
+228A:60806040E080
+228B:C020C040E080
+2310:0000E0800000
+2320:204040404040
+2321:202020202040
+23BA:F00000000000
+23BB:00F000000000
+23BC:000000F00000
+23BD:0000000000F0
+2409:A0E0A0702020
+240A:8080E0604040
+240B:A0A040702020
+240C:C0C080606040
+240D:E080E0506050
+2423:0000000090F0
+2424:D0B090202030
+2500:000000F00000
+2501:0000F8F80000
+2502:404040404040
+2503:606060606060
+2504:000000A00000
+2505:0000A8A80000
+2506:400040004000
+2507:600060006000
+2508:000000A00000
+2509:0000A8A80000
+250A:400040004000
+250B:600060006000
+250C:000000704040
+250D:000070704040
+250E:000000706060
+250F:000070706060
+2510:000000C04040
+2511:0000C0C04040
+2512:000000E06060
+2513:0000E0E06060
+2514:404040700000
+2515:404070700000
+2516:606060700000
+2517:606070700000
+2518:404040C00000
+2519:4040C0C00000
+251A:606060E00000
+251B:6060E0E00000
+251C:404040704040
+251D:404070704040
+251E:606060704040
+251F:404040706060
+2520:606060706060
+2521:606070704040
+2522:404070706060
+2523:606070706060
+2524:404040C04040
+2525:4040C0C04040
+2526:606060E04040
+2527:404040E06060
+2528:606060E06060
+2529:6060E0E04040
+252A:4040E0E06060
+252B:6060E0E06060
+252C:000000F04040
+252D:0000C0F04040
+252E:000070F04040
+252F:0000F0F04040
+2530:000000F06060
+2531:0000E0F06060
+2532:000070F06060
+2533:0000F0F06060
+2534:404040F00000
+2535:4040C0F00000
+2536:404070F00000
+2537:4040F0F00000
+2538:606060F00000
+2539:6060E0F00000
+253A:606070F00000
+253B:6060F0F00000
+253C:404040F04040
+253D:4040C0F04040
+253E:404070F04040
+253F:4040F0F04040
+2540:606060F04040
+2541:404040F06060
+2542:606060F06060
+2543:6060E0F04040
+2544:606070F04040
+2545:4040E0F06060
+2546:404070F06060
+2547:6060F0F04040
+2548:4040F0F06060
+2549:6060E0F06060
+254A:606070F06060
+254B:6060F0F06060
+254C:000000A00000
+254D:0000A0A00000
+254E:004040004040
+254F:006060006060
+2550:0000F000F000
+2551:606060606060
+2552:000070407040
+2553:000000706060
+2554:000070407060
+2555:0000C040C040
+2556:000000E06060
+2557:0000E020E060
+2558:404070407000
+2559:606060700000
+255A:606070407000
+255B:4040C040C000
+255C:606060E00000
+255D:6060E020E000
+255E:404070407040
+255F:606060706060
+2560:606070407060
+2561:4040C040C040
+2562:606060E06060
+2563:6060E020E060
+2564:0000F000F040
+2565:000000F06060
+2566:0000F000F060
+2567:4040F000F000
+2568:606060F00000
+2569:6060F000F000
+256A:4040F040F040
+256B:606060F06060
+256C:6060F000F060
+256D:000000304040
+256E:000000804040
+256F:404040800000
+2570:404040300000
+2571:102020404080
+2572:804040202010
+2573:909060609090
+2574:000000C00000
+2575:404040400000
+2576:000000700000
+2577:000000404040
+2578:0000C0C00000
+2579:606060600000
+257A:000070700000
+257B:000000606060
+257C:000030F00000
+257D:404040606060
+257E:0000C0F00000
+257F:606060604040
+2580:F8F8F8000000
+2581:0000000000F0
+2582:0000000000F8
+2583:00000000F8F8
+2584:000000F8F8F8
+2585:000000F8F8F8
+2586:0000F8F8F8F8
+2587:00F8F8F8F8F8
+2588:F8F8F8F8F8F8
+2589:F0F0F0F0F0F0
+258A:E0E0E0E0E0E0
+258B:E0E0E0E0E0E0
+258C:C0C0C0C0C0C0
+258D:C0C0C0C0C0C0
+258E:808080808080
+258F:808080808080
+2590:303030303030
+2591:802080208020
+2592:A850A850A850
+2593:B8E8B8E8B8E8
+2594:F80000000000
+2595:101010101010
+25A0:0000E0E0E000
+25A1:0000E0A0E000
+25C6:0040E0E04000
+2660:40E0E040E000
+2663:0040A040E000
+2665:00A0E0E04000
+2666:0040E0400000
+2669:404040C08000
+266A:406040C08000
+266B:70505050A000
+266C:70705050A000
+266D:8080E0A0C000
+266E:80E0A0E02000
+266F:A0E0A0E0A000
+FFFD:F090D0F0D0F0
diff --git a/src/col64/cruft/col64font_new.bdf b/src/col64/cruft/col64font_new.bdf
new file mode 100644
index 0000000..b28df9e
--- /dev/null
+++ b/src/col64/cruft/col64font_new.bdf
@@ -0,0 +1,11994 @@
+STARTFONT 2.1
+COMMENT Contributed by Janne V. Kujala <jvk@iki.fi>
+COMMENT $Id: 4x6.bdf,v 1.5 2002-08-26 18:05:49+01 mgk25 Rel $
+COMMENT Send bug reports to Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
+FONT -Misc-Fixed-Medium-R-Normal--6-60-75-75-C-40-ISO10646-1
+SIZE 6 75 75
+FONTBOUNDINGBOX 4 6 0 -1
+STARTPROPERTIES 23
+FONTNAME_REGISTRY ""
+FOUNDRY "Misc"
+FAMILY_NAME "Fixed"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 6
+POINT_SIZE 60
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "C"
+AVERAGE_WIDTH 40
+CHARSET_REGISTRY "ISO10646"
+CHARSET_ENCODING "1"
+FONT_ASCENT 5
+FONT_DESCENT 1
+DESTINATION 1
+COPYRIGHT "Public domain font. Share and enjoy."
+CAP_HEIGHT 5
+X_HEIGHT 4
+DEFAULT_CHAR 0
+_GBDFED_INFO "Edited with gbdfed 1.4."
+ENDPROPERTIES
+CHARS 920
+STARTCHAR char0
+ENCODING 0
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+00
+A0
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 32
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+F0
+A0
+F0
+A0
+00
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+60
+50
+E0
+00
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+20
+40
+90
+00
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+A0
+D0
+00
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+20
+20
+20
+40
+00
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+A0
+00
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+20
+40
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 45
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+40
+00
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+40
+80
+80
+00
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+B0
+D0
+60
+00
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+20
+40
+F0
+00
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+10
+60
+10
+E0
+00
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+A0
+F0
+20
+00
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+80
+E0
+10
+E0
+00
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+80
+E0
+90
+60
+00
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+10
+20
+40
+40
+00
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+60
+90
+60
+00
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+70
+10
+E0
+00
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+00
+00
+40
+00
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+00
+20
+40
+00
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+80
+40
+20
+00
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F0
+00
+F0
+00
+00
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+20
+40
+80
+00
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+90
+20
+00
+20
+00
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+B0
+B0
+80
+60
+00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+F0
+90
+90
+00
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+90
+E0
+90
+E0
+00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+80
+90
+60
+00
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+90
+90
+90
+E0
+00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+80
+E0
+80
+F0
+00
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+80
+E0
+80
+80
+00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+80
+B0
+90
+60
+00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+F0
+90
+90
+00
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+30
+10
+10
+90
+60
+00
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+A0
+C0
+A0
+90
+00
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+80
+F0
+00
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+F0
+D0
+90
+90
+00
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+D0
+B0
+90
+90
+00
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+90
+E0
+80
+80
+00
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+90
+A0
+50
+00
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+90
+E0
+A0
+90
+00
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+80
+60
+10
+E0
+00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+90
+A0
+40
+00
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+D0
+F0
+A0
+00
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+60
+90
+90
+00
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+60
+20
+40
+00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+20
+40
+80
+F0
+00
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+40
+40
+60
+00
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+40
+20
+20
+00
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+20
+20
+20
+60
+00
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+F0
+00
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+B0
+90
+70
+00
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+E0
+90
+E0
+00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+80
+80
+70
+00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+10
+70
+90
+70
+00
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+90
+E0
+70
+00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+90
+70
+10
+60
+00
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+E0
+90
+90
+00
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+60
+20
+C0
+00
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+C0
+A0
+90
+00
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+F0
+D0
+90
+00
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+90
+90
+90
+00
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+90
+E0
+80
+00
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+90
+70
+10
+00
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+D0
+80
+80
+00
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+C0
+30
+E0
+00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+90
+90
+60
+00
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+90
+A0
+40
+00
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+D0
+F0
+A0
+00
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+60
+60
+90
+00
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+60
+20
+C0
+00
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F0
+20
+40
+F0
+00
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+80
+40
+60
+00
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+20
+40
+C0
+00
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+00
+00
+00
+ENDCHAR
+STARTCHAR char127
+ENCODING 127
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B0
+90
+00
+90
+D0
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 160
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+80
+E0
+40
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+60
+40
+A0
+00
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+60
+60
+90
+00
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+00
+40
+40
+00
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR dieresis
+ENCODING 168
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+D0
+D0
+90
+60
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+60
+00
+E0
+00
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+50
+00
+00
+ENDCHAR
+STARTCHAR logicalnot
+ENCODING 172
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+20
+00
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+F0
+D0
+60
+00
+00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+00
+E0
+00
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+80
+C0
+00
+00
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+80
+40
+80
+00
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+D0
+D0
+50
+50
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+20
+40
+00
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+40
+40
+00
+00
+ENDCHAR
+STARTCHAR ordmasculine
+ENCODING 186
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+00
+E0
+00
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+50
+A0
+00
+00
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+50
+70
+10
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+B0
+10
+20
+30
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+80
+50
+B0
+10
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+80
+60
+00
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Adieresis
+ENCODING 196
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+F0
+A0
+B0
+00
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+80
+A0
+40
+80
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Edieresis
+ENCODING 203
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Idieresis
+ENCODING 207
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Eth
+ENCODING 208
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+50
+D0
+50
+E0
+00
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+E0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+E0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Odieresis
+ENCODING 214
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+40
+A0
+00
+00
+ENDCHAR
+STARTCHAR Oslash
+ENCODING 216
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+E0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Udieresis
+ENCODING 220
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR Thorn
+ENCODING 222
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+C0
+A0
+C0
+80
+00
+ENDCHAR
+STARTCHAR germandbls
+ENCODING 223
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+C0
+A0
+E0
+80
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR adieresis
+ENCODING 228
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+B0
+A0
+70
+00
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+80
+60
+40
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR edieresis
+ENCODING 235
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR idieresis
+ENCODING 239
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+60
+A0
+40
+00
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR odieresis
+ENCODING 246
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR divide
+ENCODING 247
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+40
+00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR udieresis
+ENCODING 252
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+E0
+20
+C0
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+C0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR ydieresis
+ENCODING 255
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+E0
+20
+C0
+ENDCHAR
+STARTCHAR Amacron
+ENCODING 256
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR amacron
+ENCODING 257
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR Abreve
+ENCODING 258
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR abreve
+ENCODING 259
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR Aogonek
+ENCODING 260
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+E0
+A0
+20
+ENDCHAR
+STARTCHAR aogonek
+ENCODING 261
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+60
+A0
+60
+20
+ENDCHAR
+STARTCHAR Cacute
+ENCODING 262
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR cacute
+ENCODING 263
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+80
+60
+00
+ENDCHAR
+STARTCHAR Ccircumflex
+ENCODING 264
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR ccircumflex
+ENCODING 265
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+60
+80
+60
+00
+ENDCHAR
+STARTCHAR Cdotaccent
+ENCODING 266
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR cdotaccent
+ENCODING 267
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+60
+80
+60
+00
+ENDCHAR
+STARTCHAR Ccaron
+ENCODING 268
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR ccaron
+ENCODING 269
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+60
+80
+60
+00
+ENDCHAR
+STARTCHAR Dcaron
+ENCODING 270
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+C0
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR dcaron
+ENCODING 271
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+30
+20
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR Dcroat
+ENCODING 272
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+E0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR dcroat
+ENCODING 273
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+20
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR Emacron
+ENCODING 274
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR emacron
+ENCODING 275
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR Ebreve
+ENCODING 276
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR ebreve
+ENCODING 277
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR Edotaccent
+ENCODING 278
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR edotaccent
+ENCODING 279
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR Eogonek
+ENCODING 280
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+80
+E0
+20
+ENDCHAR
+STARTCHAR eogonek
+ENCODING 281
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+C0
+60
+40
+ENDCHAR
+STARTCHAR Ecaron
+ENCODING 282
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR ecaron
+ENCODING 283
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR Gcircumflex
+ENCODING 284
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+80
+A0
+60
+00
+ENDCHAR
+STARTCHAR gcircumflex
+ENCODING 285
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR Gbreve
+ENCODING 286
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+60
+80
+A0
+60
+00
+ENDCHAR
+STARTCHAR gbreve
+ENCODING 287
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR Gdotaccent
+ENCODING 288
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+80
+A0
+60
+00
+ENDCHAR
+STARTCHAR gdotaccent
+ENCODING 289
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR Gcommaaccent
+ENCODING 290
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+A0
+A0
+40
+40
+ENDCHAR
+STARTCHAR gcommaaccent
+ENCODING 291
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR Hcircumflex
+ENCODING 292
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR hcircumflex
+ENCODING 293
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Hbar
+ENCODING 294
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR hbar
+ENCODING 295
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+C0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Itilde
+ENCODING 296
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR itilde
+ENCODING 297
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Imacron
+ENCODING 298
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR imacron
+ENCODING 299
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Ibreve
+ENCODING 300
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR ibreve
+ENCODING 301
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Iogonek
+ENCODING 302
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+E0
+20
+ENDCHAR
+STARTCHAR iogonek
+ENCODING 303
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+C0
+40
+E0
+20
+ENDCHAR
+STARTCHAR Idotaccent
+ENCODING 304
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR dotlessi
+ENCODING 305
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR IJ
+ENCODING 306
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+A0
+A0
+20
+60
+ENDCHAR
+STARTCHAR ij
+ENCODING 307
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+20
+40
+ENDCHAR
+STARTCHAR Jcircumflex
+ENCODING 308
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+20
+A0
+40
+00
+ENDCHAR
+STARTCHAR jcircumflex
+ENCODING 309
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+20
+20
+C0
+ENDCHAR
+STARTCHAR Kcommaaccent
+ENCODING 310
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+C0
+A0
+20
+40
+ENDCHAR
+STARTCHAR kcommaaccent
+ENCODING 311
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+C0
+A0
+20
+40
+ENDCHAR
+STARTCHAR kgreenlandic
+ENCODING 312
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR Lacute
+ENCODING 313
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+80
+80
+80
+E0
+00
+ENDCHAR
+STARTCHAR lacute
+ENCODING 314
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Lcommaaccent
+ENCODING 315
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+80
+E0
+20
+ENDCHAR
+STARTCHAR lcommaaccent
+ENCODING 316
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+40
+40
+E0
+20
+ENDCHAR
+STARTCHAR Lcaron
+ENCODING 317
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+C0
+80
+80
+E0
+00
+ENDCHAR
+STARTCHAR lcaron
+ENCODING 318
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Ldot
+ENCODING 319
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+A0
+80
+E0
+00
+ENDCHAR
+STARTCHAR ldot
+ENCODING 320
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+50
+40
+E0
+00
+ENDCHAR
+STARTCHAR Lslash
+ENCODING 321
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR lslash
+ENCODING 322
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+60
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Nacute
+ENCODING 323
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+E0
+A0
+80
+00
+ENDCHAR
+STARTCHAR nacute
+ENCODING 324
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Ncommaaccent
+ENCODING 325
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+E0
+A0
+80
+20
+ENDCHAR
+STARTCHAR ncommaaccent
+ENCODING 326
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+A0
+00
+40
+ENDCHAR
+STARTCHAR Ncaron
+ENCODING 327
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+E0
+A0
+80
+00
+ENDCHAR
+STARTCHAR ncaron
+ENCODING 328
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR napostrophe
+ENCODING 329
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+00
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Eng
+ENCODING 330
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+E0
+A0
+20
+40
+ENDCHAR
+STARTCHAR eng
+ENCODING 331
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+A0
+20
+40
+ENDCHAR
+STARTCHAR Omacron
+ENCODING 332
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR omacron
+ENCODING 333
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR Obreve
+ENCODING 334
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR obreve
+ENCODING 335
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR Ohungarumlaut
+ENCODING 336
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR ohungarumlaut
+ENCODING 337
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR OE
+ENCODING 338
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+B0
+A0
+70
+00
+ENDCHAR
+STARTCHAR oe
+ENCODING 339
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+70
+B0
+A0
+70
+00
+ENDCHAR
+STARTCHAR Racute
+ENCODING 340
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR racute
+ENCODING 341
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+A0
+C0
+80
+00
+ENDCHAR
+STARTCHAR Rcommaaccent
+ENCODING 342
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+A0
+00
+40
+ENDCHAR
+STARTCHAR rcommaaccent
+ENCODING 343
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+C0
+80
+80
+20
+ENDCHAR
+STARTCHAR Rcaron
+ENCODING 344
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR rcaron
+ENCODING 345
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+A0
+C0
+80
+00
+ENDCHAR
+STARTCHAR Sacute
+ENCODING 346
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR sacute
+ENCODING 347
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR Scircumflex
+ENCODING 348
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR scircumflex
+ENCODING 349
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR Scedilla
+ENCODING 350
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+40
+20
+C0
+40
+ENDCHAR
+STARTCHAR scedilla
+ENCODING 351
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+20
+E0
+40
+ENDCHAR
+STARTCHAR Scaron
+ENCODING 352
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+C0
+20
+E0
+00
+ENDCHAR
+STARTCHAR scaron
+ENCODING 353
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 354
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+20
+40
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 355
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+20
+40
+ENDCHAR
+STARTCHAR Tcaron
+ENCODING 356
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR tcaron
+ENCODING 357
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+E0
+40
+20
+00
+ENDCHAR
+STARTCHAR Tbar
+ENCODING 358
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR tbar
+ENCODING 359
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+E0
+40
+20
+00
+ENDCHAR
+STARTCHAR Utilde
+ENCODING 360
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+20
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR utilde
+ENCODING 361
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+00
+A0
+60
+00
+ENDCHAR
+STARTCHAR Umacron
+ENCODING 362
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR umacron
+ENCODING 363
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR Ubreve
+ENCODING 364
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR ubreve
+ENCODING 365
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+A0
+60
+00
+ENDCHAR
+STARTCHAR Uring
+ENCODING 366
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR uring
+ENCODING 367
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR Uhungarumlaut
+ENCODING 368
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR uhungarumlaut
+ENCODING 369
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR Uogonek
+ENCODING 370
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+40
+20
+ENDCHAR
+STARTCHAR uogonek
+ENCODING 371
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+60
+40
+ENDCHAR
+STARTCHAR Wcircumflex
+ENCODING 372
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR wcircumflex
+ENCODING 373
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR Ycircumflex
+ENCODING 374
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR ycircumflex
+ENCODING 375
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+40
+80
+00
+ENDCHAR
+STARTCHAR Ydieresis
+ENCODING 376
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR Zacute
+ENCODING 377
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR zacute
+ENCODING 378
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR Zdotaccent
+ENCODING 379
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR zdotaccent
+ENCODING 380
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR Zcaron
+ENCODING 381
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR zcaron
+ENCODING 382
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR longs
+ENCODING 383
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+C0
+40
+40
+00
+ENDCHAR
+STARTCHAR uni018F
+ENCODING 399
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+60
+A0
+40
+00
+ENDCHAR
+STARTCHAR florin
+ENCODING 402
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+40
+40
+80
+ENDCHAR
+STARTCHAR Scommaaccent
+ENCODING 536
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+40
+20
+C0
+40
+ENDCHAR
+STARTCHAR scommaaccent
+ENCODING 537
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+20
+E0
+40
+ENDCHAR
+STARTCHAR Tcommaaccent
+ENCODING 538
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+00
+40
+ENDCHAR
+STARTCHAR tcommaaccent
+ENCODING 539
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+20
+40
+ENDCHAR
+STARTCHAR uni0259
+ENCODING 601
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+60
+A0
+40
+00
+ENDCHAR
+STARTCHAR circumflex
+ENCODING 710
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR caron
+ENCODING 711
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR macron
+ENCODING 713
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR breve
+ENCODING 728
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dotaccent
+ENCODING 729
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ring
+ENCODING 730
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR ogonek
+ENCODING 731
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+40
+80
+C0
+ENDCHAR
+STARTCHAR tilde
+ENCODING 732
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR hungarumlaut
+ENCODING 733
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0374
+ENCODING 884
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni0375
+ENCODING 885
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+40
+80
+ENDCHAR
+STARTCHAR uni037A
+ENCODING 890
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+40
+60
+ENDCHAR
+STARTCHAR uni037E
+ENCODING 894
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+00
+00
+40
+80
+ENDCHAR
+STARTCHAR tonos
+ENCODING 900
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dieresistonos
+ENCODING 901
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B0
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Alphatonos
+ENCODING 902
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR anoteleia
+ENCODING 903
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR Epsilontonos
+ENCODING 904
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+C0
+60
+40
+60
+00
+ENDCHAR
+STARTCHAR Etatonos
+ENCODING 905
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+20
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Iotatonos
+ENCODING 906
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+C0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Omicrontonos
+ENCODING 908
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Upsilontonos
+ENCODING 910
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+C0
+40
+40
+00
+ENDCHAR
+STARTCHAR Omegatonos
+ENCODING 911
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+A0
+40
+A0
+00
+ENDCHAR
+STARTCHAR iotadieresistonos
+ENCODING 912
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B0
+40
+00
+40
+20
+00
+ENDCHAR
+STARTCHAR Alpha
+ENCODING 913
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Beta
+ENCODING 914
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR Gamma
+ENCODING 915
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR Delta
+ENCODING 916
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Epsilon
+ENCODING 917
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR Zeta
+ENCODING 918
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+20
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR Eta
+ENCODING 919
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Theta
+ENCODING 920
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+E0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Iota
+ENCODING 921
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR Kappa
+ENCODING 922
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Lambda
+ENCODING 923
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Mu
+ENCODING 924
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Nu
+ENCODING 925
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+E0
+A0
+80
+00
+ENDCHAR
+STARTCHAR Xi
+ENCODING 926
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+40
+00
+E0
+00
+ENDCHAR
+STARTCHAR Omicron
+ENCODING 927
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR Pi
+ENCODING 928
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Rho
+ENCODING 929
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+80
+80
+00
+ENDCHAR
+STARTCHAR Sigma
+ENCODING 931
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR Tau
+ENCODING 932
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR Upsilon
+ENCODING 933
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR Phi
+ENCODING 934
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+A0
+E0
+40
+00
+ENDCHAR
+STARTCHAR Chi
+ENCODING 935
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+A0
+A0
+00
+ENDCHAR
+STARTCHAR Psi
+ENCODING 936
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR Omega
+ENCODING 937
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+40
+A0
+00
+ENDCHAR
+STARTCHAR Iotadieresis
+ENCODING 938
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR Upsilondieresis
+ENCODING 939
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR alphatonos
+ENCODING 940
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+80
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR epsilontonos
+ENCODING 941
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+40
+80
+60
+00
+ENDCHAR
+STARTCHAR etatonos
+ENCODING 942
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+C0
+A0
+20
+40
+ENDCHAR
+STARTCHAR iotatonos
+ENCODING 943
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR upsilondieresistonos
+ENCODING 944
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B0
+40
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR alpha
+ENCODING 945
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+A0
+50
+00
+ENDCHAR
+STARTCHAR beta
+ENCODING 946
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR gamma
+ENCODING 947
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+60
+40
+40
+00
+ENDCHAR
+STARTCHAR delta
+ENCODING 948
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR epsilon
+ENCODING 949
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+C0
+80
+60
+00
+ENDCHAR
+STARTCHAR zeta
+ENCODING 950
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+80
+E0
+20
+40
+ENDCHAR
+STARTCHAR eta
+ENCODING 951
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+A0
+20
+40
+ENDCHAR
+STARTCHAR theta
+ENCODING 952
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+E0
+A0
+40
+00
+ENDCHAR
+STARTCHAR iota
+ENCODING 953
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR kappa
+ENCODING 954
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR lambda
+ENCODING 955
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+60
+A0
+A0
+00
+ENDCHAR
+STARTCHAR mu
+ENCODING 956
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR nu
+ENCODING 957
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+60
+40
+00
+ENDCHAR
+STARTCHAR xi
+ENCODING 958
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+40
+80
+60
+00
+ENDCHAR
+STARTCHAR omicron
+ENCODING 959
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR pi
+ENCODING 960
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR rho
+ENCODING 961
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR sigma1
+ENCODING 962
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+80
+40
+C0
+00
+ENDCHAR
+STARTCHAR sigma
+ENCODING 963
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+A0
+40
+00
+ENDCHAR
+STARTCHAR tau
+ENCODING 964
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR upsilon
+ENCODING 965
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+80
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR phi
+ENCODING 966
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+A0
+40
+40
+ENDCHAR
+STARTCHAR chi
+ENCODING 967
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+40
+60
+A0
+00
+ENDCHAR
+STARTCHAR psi
+ENCODING 968
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+40
+00
+ENDCHAR
+STARTCHAR omega
+ENCODING 969
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR iotadieresis
+ENCODING 970
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR upsilondieresis
+ENCODING 971
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR omicrontonos
+ENCODING 972
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+A0
+40
+00
+ENDCHAR
+STARTCHAR upsilontonos
+ENCODING 973
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR omegatonos
+ENCODING 974
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR afii10023
+ENCODING 1025
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR afii10051
+ENCODING 1026
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10052
+ENCODING 1027
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10053
+ENCODING 1028
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+C0
+80
+60
+00
+ENDCHAR
+STARTCHAR afii10054
+ENCODING 1029
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+40
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10055
+ENCODING 1030
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR afii10056
+ENCODING 1031
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+40
+40
+E0
+00
+ENDCHAR
+STARTCHAR afii10057
+ENCODING 1032
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+20
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10058
+ENCODING 1033
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+60
+A0
+B0
+B0
+00
+ENDCHAR
+STARTCHAR afii10059
+ENCODING 1034
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+B0
+B0
+00
+ENDCHAR
+STARTCHAR afii10060
+ENCODING 1035
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+80
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10061
+ENCODING 1036
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+80
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii10062
+ENCODING 1038
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+A0
+40
+80
+ENDCHAR
+STARTCHAR afii10145
+ENCODING 1039
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+E0
+40
+ENDCHAR
+STARTCHAR afii10017
+ENCODING 1040
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10018
+ENCODING 1041
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10019
+ENCODING 1042
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10020
+ENCODING 1043
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10021
+ENCODING 1044
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+60
+A0
+A0
+E0
+A0
+ENDCHAR
+STARTCHAR afii10022
+ENCODING 1045
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+C0
+80
+E0
+00
+ENDCHAR
+STARTCHAR afii10024
+ENCODING 1046
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+40
+E0
+A0
+00
+ENDCHAR
+STARTCHAR afii10025
+ENCODING 1047
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+40
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10026
+ENCODING 1048
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+A0
+E0
+A0
+20
+00
+ENDCHAR
+STARTCHAR afii10027
+ENCODING 1049
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+A0
+E0
+A0
+20
+ENDCHAR
+STARTCHAR afii10028
+ENCODING 1050
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+C0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10029
+ENCODING 1051
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10030
+ENCODING 1052
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10031
+ENCODING 1053
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10032
+ENCODING 1054
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10033
+ENCODING 1055
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10034
+ENCODING 1056
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+A0
+C0
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10035
+ENCODING 1057
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10036
+ENCODING 1058
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR afii10037
+ENCODING 1059
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+40
+40
+80
+ENDCHAR
+STARTCHAR afii10038
+ENCODING 1060
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+A0
+E0
+40
+00
+ENDCHAR
+STARTCHAR afii10039
+ENCODING 1061
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10040
+ENCODING 1062
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR afii10041
+ENCODING 1063
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+60
+20
+20
+00
+ENDCHAR
+STARTCHAR afii10042
+ENCODING 1064
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR afii10043
+ENCODING 1065
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+E0
+F0
+10
+ENDCHAR
+STARTCHAR afii10044
+ENCODING 1066
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+60
+50
+60
+00
+ENDCHAR
+STARTCHAR afii10045
+ENCODING 1067
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+D0
+B0
+D0
+00
+ENDCHAR
+STARTCHAR afii10046
+ENCODING 1068
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10047
+ENCODING 1069
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+60
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10048
+ENCODING 1070
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+D0
+D0
+D0
+A0
+00
+ENDCHAR
+STARTCHAR afii10049
+ENCODING 1071
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+60
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10065
+ENCODING 1072
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+A0
+60
+00
+ENDCHAR
+STARTCHAR afii10066
+ENCODING 1073
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+E0
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10067
+ENCODING 1074
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10068
+ENCODING 1075
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10069
+ENCODING 1076
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+A0
+E0
+A0
+ENDCHAR
+STARTCHAR afii10070
+ENCODING 1077
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR afii10072
+ENCODING 1078
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+B0
+60
+60
+B0
+00
+ENDCHAR
+STARTCHAR afii10073
+ENCODING 1079
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+40
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10074
+ENCODING 1080
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR afii10075
+ENCODING 1081
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR afii10076
+ENCODING 1082
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii10077
+ENCODING 1083
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10078
+ENCODING 1084
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10079
+ENCODING 1085
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10080
+ENCODING 1086
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii10081
+ENCODING 1087
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii10082
+ENCODING 1088
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+C0
+80
+80
+ENDCHAR
+STARTCHAR afii10083
+ENCODING 1089
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+80
+80
+60
+00
+ENDCHAR
+STARTCHAR afii10084
+ENCODING 1090
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR afii10085
+ENCODING 1091
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+60
+20
+C0
+ENDCHAR
+STARTCHAR afii10086
+ENCODING 1092
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+40
+40
+ENDCHAR
+STARTCHAR afii10087
+ENCODING 1093
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+40
+40
+A0
+00
+ENDCHAR
+STARTCHAR afii10088
+ENCODING 1094
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+E0
+20
+ENDCHAR
+STARTCHAR afii10089
+ENCODING 1095
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+60
+20
+00
+ENDCHAR
+STARTCHAR afii10090
+ENCODING 1096
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR afii10091
+ENCODING 1097
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+F0
+10
+ENDCHAR
+STARTCHAR afii10092
+ENCODING 1098
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+60
+50
+60
+00
+ENDCHAR
+STARTCHAR afii10093
+ENCODING 1099
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+90
+D0
+B0
+D0
+00
+ENDCHAR
+STARTCHAR afii10094
+ENCODING 1100
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+80
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii10095
+ENCODING 1101
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+60
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10096
+ENCODING 1102
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+D0
+D0
+A0
+00
+ENDCHAR
+STARTCHAR afii10097
+ENCODING 1103
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+60
+A0
+00
+ENDCHAR
+STARTCHAR afii10071
+ENCODING 1105
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+C0
+60
+00
+ENDCHAR
+STARTCHAR afii10099
+ENCODING 1106
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+C0
+80
+C0
+A0
+20
+ENDCHAR
+STARTCHAR afii10100
+ENCODING 1107
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10101
+ENCODING 1108
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+80
+60
+00
+ENDCHAR
+STARTCHAR afii10102
+ENCODING 1109
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii10103
+ENCODING 1110
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR afii10104
+ENCODING 1111
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+C0
+40
+E0
+00
+ENDCHAR
+STARTCHAR afii10105
+ENCODING 1112
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+20
+20
+20
+C0
+ENDCHAR
+STARTCHAR afii10106
+ENCODING 1113
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+A0
+B0
+B0
+00
+ENDCHAR
+STARTCHAR afii10107
+ENCODING 1114
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+B0
+B0
+00
+ENDCHAR
+STARTCHAR afii10108
+ENCODING 1115
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+C0
+80
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii10109
+ENCODING 1116
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+80
+A0
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii10110
+ENCODING 1118
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+A0
+40
+80
+ENDCHAR
+STARTCHAR afii10193
+ENCODING 1119
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+E0
+40
+ENDCHAR
+STARTCHAR afii10050
+ENCODING 1168
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR afii10098
+ENCODING 1169
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+E0
+80
+80
+00
+ENDCHAR
+STARTCHAR uni0492
+ENCODING 1170
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR uni0493
+ENCODING 1171
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR afii57664
+ENCODING 1488
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+60
+C0
+A0
+00
+ENDCHAR
+STARTCHAR afii57665
+ENCODING 1489
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+20
+F0
+00
+ENDCHAR
+STARTCHAR afii57666
+ENCODING 1490
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+40
+40
+A0
+00
+ENDCHAR
+STARTCHAR afii57667
+ENCODING 1491
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR afii57668
+ENCODING 1492
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+20
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii57669
+ENCODING 1493
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+20
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR afii57670
+ENCODING 1494
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR afii57671
+ENCODING 1495
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii57672
+ENCODING 1496
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR afii57673
+ENCODING 1497
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR afii57674
+ENCODING 1498
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR afii57675
+ENCODING 1499
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+20
+C0
+00
+ENDCHAR
+STARTCHAR afii57676
+ENCODING 1500
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+20
+20
+40
+00
+ENDCHAR
+STARTCHAR afii57677
+ENCODING 1501
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR afii57678
+ENCODING 1502
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR afii57679
+ENCODING 1503
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR afii57680
+ENCODING 1504
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+20
+20
+20
+60
+00
+ENDCHAR
+STARTCHAR afii57681
+ENCODING 1505
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR afii57682
+ENCODING 1506
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+60
+C0
+00
+ENDCHAR
+STARTCHAR afii57683
+ENCODING 1507
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+20
+20
+20
+ENDCHAR
+STARTCHAR afii57684
+ENCODING 1508
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+A0
+20
+E0
+00
+ENDCHAR
+STARTCHAR afii57685
+ENCODING 1509
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+C0
+80
+80
+ENDCHAR
+STARTCHAR afii57686
+ENCODING 1510
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+40
+20
+E0
+00
+ENDCHAR
+STARTCHAR afii57687
+ENCODING 1511
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+20
+C0
+80
+80
+ENDCHAR
+STARTCHAR afii57688
+ENCODING 1512
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+20
+20
+20
+00
+ENDCHAR
+STARTCHAR afii57689
+ENCODING 1513
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F0
+D0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR afii57690
+ENCODING 1514
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR uni1E02
+ENCODING 7682
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR uni1E03
+ENCODING 7683
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+80
+C0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR uni1E0A
+ENCODING 7690
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+A0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR uni1E0B
+ENCODING 7691
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+20
+60
+A0
+60
+00
+ENDCHAR
+STARTCHAR uni1E1E
+ENCODING 7710
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+80
+C0
+80
+00
+ENDCHAR
+STARTCHAR uni1E1F
+ENCODING 7711
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR uni1E40
+ENCODING 7744
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR uni1E41
+ENCODING 7745
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR uni1E56
+ENCODING 7766
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+A0
+C0
+80
+00
+ENDCHAR
+STARTCHAR uni1E57
+ENCODING 7767
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+C0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR uni1E60
+ENCODING 7776
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR uni1E61
+ENCODING 7777
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+C0
+20
+C0
+00
+ENDCHAR
+STARTCHAR uni1E6A
+ENCODING 7786
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR uni1E6B
+ENCODING 7787
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+E0
+40
+20
+ENDCHAR
+STARTCHAR Wgrave
+ENCODING 7808
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR wgrave
+ENCODING 7809
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Wacute
+ENCODING 7810
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+80
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR wacute
+ENCODING 7811
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR Wdieresis
+ENCODING 7812
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR wdieresis
+ENCODING 7813
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+A0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR Ygrave
+ENCODING 7922
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR ygrave
+ENCODING 7923
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+A0
+60
+20
+40
+ENDCHAR
+STARTCHAR uni2010
+ENCODING 8208
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2011
+ENCODING 8209
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR figuredash
+ENCODING 8210
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR endash
+ENCODING 8211
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR emdash
+ENCODING 8212
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR afii00208
+ENCODING 8213
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2016
+ENCODING 8214
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+A0
+A0
+ENDCHAR
+STARTCHAR underscoredbl
+ENCODING 8215
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+00
+F0
+ENDCHAR
+STARTCHAR quoteleft
+ENCODING 8216
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+60
+00
+00
+00
+ENDCHAR
+STARTCHAR quoteright
+ENCODING 8217
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+20
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR quotesinglbase
+ENCODING 8218
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+60
+20
+40
+ENDCHAR
+STARTCHAR quotereversed
+ENCODING 8219
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+40
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblleft
+ENCODING 8220
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+A0
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblright
+ENCODING 8221
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+50
+A0
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedblbase
+ENCODING 8222
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+50
+50
+A0
+ENDCHAR
+STARTCHAR uni201F
+ENCODING 8223
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+50
+00
+00
+00
+ENDCHAR
+STARTCHAR dagger
+ENCODING 8224
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR daggerdbl
+ENCODING 8225
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR bullet
+ENCODING 8226
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+40
+00
+00
+ENDCHAR
+STARTCHAR uni2023
+ENCODING 8227
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+E0
+C0
+00
+00
+ENDCHAR
+STARTCHAR onedotenleader
+ENCODING 8228
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+40
+00
+ENDCHAR
+STARTCHAR twodotenleader
+ENCODING 8229
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+A0
+00
+ENDCHAR
+STARTCHAR ellipsis
+ENCODING 8230
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+B0
+00
+ENDCHAR
+STARTCHAR uni2027
+ENCODING 8231
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+00
+00
+ENDCHAR
+STARTCHAR perthousand
+ENCODING 8240
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+40
+80
+30
+00
+ENDCHAR
+STARTCHAR guilsinglleft
+ENCODING 8249
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+80
+40
+00
+00
+ENDCHAR
+STARTCHAR guilsinglright
+ENCODING 8250
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+20
+40
+00
+00
+ENDCHAR
+STARTCHAR uni203E
+ENCODING 8254
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR nsuperior
+ENCODING 8319
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+A0
+A0
+00
+00
+ENDCHAR
+STARTCHAR peseta
+ENCODING 8359
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+F0
+60
+40
+40
+00
+ENDCHAR
+STARTCHAR Euro
+ENCODING 8364
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+40
+20
+00
+ENDCHAR
+STARTCHAR afii61352
+ENCODING 8470
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+B0
+B0
+A0
+B0
+00
+ENDCHAR
+STARTCHAR trademark
+ENCODING 8482
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+40
+00
+E0
+A0
+00
+ENDCHAR
+STARTCHAR Omega
+ENCODING 8486
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+A0
+40
+A0
+00
+ENDCHAR
+STARTCHAR uni2127
+ENCODING 8487
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR oneeighth
+ENCODING 8539
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+B0
+20
+50
+20
+ENDCHAR
+STARTCHAR threeeighths
+ENCODING 8540
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+B0
+60
+D0
+20
+ENDCHAR
+STARTCHAR fiveeighths
+ENCODING 8541
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+80
+70
+A0
+50
+20
+ENDCHAR
+STARTCHAR seveneighths
+ENCODING 8542
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+40
+B0
+A0
+50
+20
+ENDCHAR
+STARTCHAR arrowleft
+ENCODING 8592
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+F0
+40
+00
+00
+ENDCHAR
+STARTCHAR arrowup
+ENCODING 8593
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+40
+40
+00
+ENDCHAR
+STARTCHAR arrowright
+ENCODING 8594
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+F0
+20
+00
+00
+ENDCHAR
+STARTCHAR arrowdown
+ENCODING 8595
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR arrowboth
+ENCODING 8596
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+F0
+50
+00
+00
+ENDCHAR
+STARTCHAR arrowupdn
+ENCODING 8597
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR universal
+ENCODING 8704
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+E0
+A0
+40
+00
+ENDCHAR
+STARTCHAR uni2201
+ENCODING 8705
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+80
+A0
+40
+00
+ENDCHAR
+STARTCHAR partialdiff
+ENCODING 8706
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+60
+A0
+40
+00
+ENDCHAR
+STARTCHAR existential
+ENCODING 8707
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+20
+E0
+20
+E0
+00
+ENDCHAR
+STARTCHAR uni2204
+ENCODING 8708
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+20
+E0
+60
+E0
+80
+ENDCHAR
+STARTCHAR emptyset
+ENCODING 8709
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+A0
+A0
+C0
+80
+ENDCHAR
+STARTCHAR Delta
+ENCODING 8710
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR gradient
+ENCODING 8711
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR element
+ENCODING 8712
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+E0
+80
+60
+00
+ENDCHAR
+STARTCHAR notelement
+ENCODING 8713
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+E0
+A0
+60
+40
+ENDCHAR
+STARTCHAR uni220A
+ENCODING 8714
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+80
+C0
+80
+40
+00
+ENDCHAR
+STARTCHAR suchthat
+ENCODING 8715
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+E0
+20
+C0
+00
+ENDCHAR
+STARTCHAR uni220C
+ENCODING 8716
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+20
+E0
+60
+C0
+80
+ENDCHAR
+STARTCHAR uni220D
+ENCODING 8717
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+C0
+40
+80
+00
+ENDCHAR
+STARTCHAR uni220E
+ENCODING 8718
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+C0
+C0
+C0
+C0
+00
+ENDCHAR
+STARTCHAR product
+ENCODING 8719
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR uni2210
+ENCODING 8720
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR summation
+ENCODING 8721
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR minus
+ENCODING 8722
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2213
+ENCODING 8723
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR uni2214
+ENCODING 8724
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+E0
+40
+00
+ENDCHAR
+STARTCHAR fraction
+ENCODING 8725
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+40
+80
+80
+00
+ENDCHAR
+STARTCHAR uni2216
+ENCODING 8726
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+40
+20
+20
+00
+ENDCHAR
+STARTCHAR asteriskmath
+ENCODING 8727
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+A0
+70
+E0
+50
+40
+ENDCHAR
+STARTCHAR uni2218
+ENCODING 8728
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+40
+00
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 8729
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+40
+00
+00
+ENDCHAR
+STARTCHAR radical
+ENCODING 8730
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+30
+20
+20
+A0
+60
+00
+ENDCHAR
+STARTCHAR uni221B
+ENCODING 8731
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+50
+D0
+10
+50
+30
+ENDCHAR
+STARTCHAR uni221C
+ENCODING 8732
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+D0
+50
+10
+50
+30
+ENDCHAR
+STARTCHAR proportional
+ENCODING 8733
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+50
+E0
+50
+00
+ENDCHAR
+STARTCHAR infinity
+ENCODING 8734
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+D0
+B0
+40
+00
+ENDCHAR
+STARTCHAR orthogonal
+ENCODING 8735
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+80
+80
+E0
+00
+ENDCHAR
+STARTCHAR angle
+ENCODING 8736
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+40
+80
+E0
+00
+ENDCHAR
+STARTCHAR uni2221
+ENCODING 8737
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+A0
+40
+A0
+F0
+20
+ENDCHAR
+STARTCHAR uni2222
+ENCODING 8738
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+60
+A0
+A0
+60
+90
+ENDCHAR
+STARTCHAR uni2223
+ENCODING 8739
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR uni2224
+ENCODING 8740
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+40
+C0
+40
+00
+ENDCHAR
+STARTCHAR uni2225
+ENCODING 8741
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR uni2226
+ENCODING 8742
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+B0
+E0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR logicaland
+ENCODING 8743
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+40
+A0
+A0
+00
+ENDCHAR
+STARTCHAR logicalor
+ENCODING 8744
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+40
+40
+00
+ENDCHAR
+STARTCHAR intersection
+ENCODING 8745
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+A0
+A0
+00
+ENDCHAR
+STARTCHAR union
+ENCODING 8746
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+A0
+A0
+40
+00
+ENDCHAR
+STARTCHAR integral
+ENCODING 8747
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR uni222C
+ENCODING 8748
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+A0
+A0
+A0
+80
+ENDCHAR
+STARTCHAR uni222D
+ENCODING 8749
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+D0
+D0
+D0
+D0
+A0
+ENDCHAR
+STARTCHAR uni222E
+ENCODING 8750
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+E0
+40
+80
+ENDCHAR
+STARTCHAR uni222F
+ENCODING 8751
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+E0
+E0
+A0
+80
+ENDCHAR
+STARTCHAR uni2230
+ENCODING 8752
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+D0
+F0
+F0
+D0
+A0
+ENDCHAR
+STARTCHAR uni2231
+ENCODING 8753
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+50
+40
+80
+ENDCHAR
+STARTCHAR uni2232
+ENCODING 8754
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+C0
+40
+80
+ENDCHAR
+STARTCHAR uni2233
+ENCODING 8755
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+C0
+E0
+40
+80
+ENDCHAR
+STARTCHAR therefore
+ENCODING 8756
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+A0
+00
+ENDCHAR
+STARTCHAR uni2235
+ENCODING 8757
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A0
+00
+40
+00
+ENDCHAR
+STARTCHAR uni2236
+ENCODING 8758
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR uni2237
+ENCODING 8759
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A0
+00
+A0
+00
+ENDCHAR
+STARTCHAR uni2238
+ENCODING 8760
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2239
+ENCODING 8761
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+20
+C0
+20
+00
+ENDCHAR
+STARTCHAR uni223A
+ENCODING 8762
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+00
+E0
+00
+A0
+00
+ENDCHAR
+STARTCHAR uni223B
+ENCODING 8763
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+00
+50
+A0
+00
+40
+ENDCHAR
+STARTCHAR similar
+ENCODING 8764
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+50
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni223D
+ENCODING 8765
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A0
+50
+00
+00
+ENDCHAR
+STARTCHAR uni223E
+ENCODING 8766
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+D0
+B0
+00
+00
+ENDCHAR
+STARTCHAR uni223F
+ENCODING 8767
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+50
+A0
+20
+00
+ENDCHAR
+STARTCHAR uni2240
+ENCODING 8768
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+20
+40
+40
+20
+00
+ENDCHAR
+STARTCHAR uni2241
+ENCODING 8769
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+20
+B0
+D0
+40
+80
+ENDCHAR
+STARTCHAR uni2242
+ENCODING 8770
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+00
+A0
+50
+00
+ENDCHAR
+STARTCHAR uni2243
+ENCODING 8771
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2244
+ENCODING 8772
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+D0
+B0
+40
+F0
+40
+ENDCHAR
+STARTCHAR congruent
+ENCODING 8773
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+00
+E0
+00
+E0
+ENDCHAR
+STARTCHAR uni2246
+ENCODING 8774
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+20
+F0
+40
+F0
+ENDCHAR
+STARTCHAR uni2247
+ENCODING 8775
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+20
+F0
+40
+F0
+ENDCHAR
+STARTCHAR approxequal
+ENCODING 8776
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+50
+A0
+00
+50
+A0
+00
+ENDCHAR
+STARTCHAR uni2249
+ENCODING 8777
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+A0
+40
+50
+E0
+80
+ENDCHAR
+STARTCHAR uni224A
+ENCODING 8778
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+B0
+40
+B0
+00
+F0
+ENDCHAR
+STARTCHAR uni224B
+ENCODING 8779
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+B0
+40
+B0
+40
+B0
+ENDCHAR
+STARTCHAR uni224C
+ENCODING 8780
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+50
+00
+E0
+00
+E0
+ENDCHAR
+STARTCHAR uni224D
+ENCODING 8781
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+00
+40
+A0
+00
+ENDCHAR
+STARTCHAR uni224E
+ENCODING 8782
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+A0
+40
+00
+ENDCHAR
+STARTCHAR uni224F
+ENCODING 8783
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+A0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2250
+ENCODING 8784
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2251
+ENCODING 8785
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+40
+ENDCHAR
+STARTCHAR uni2252
+ENCODING 8786
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+00
+E0
+00
+20
+ENDCHAR
+STARTCHAR uni2253
+ENCODING 8787
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+00
+E0
+00
+80
+ENDCHAR
+STARTCHAR uni2254
+ENCODING 8788
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+B0
+00
+B0
+00
+00
+ENDCHAR
+STARTCHAR uni2255
+ENCODING 8789
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+D0
+00
+D0
+00
+00
+ENDCHAR
+STARTCHAR uni2256
+ENCODING 8790
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+E0
+40
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2257
+ENCODING 8791
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2258
+ENCODING 8792
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2259
+ENCODING 8793
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni225A
+ENCODING 8794
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni225B
+ENCODING 8795
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni225C
+ENCODING 8796
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+00
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni225D
+ENCODING 8797
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni225E
+ENCODING 8798
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni225F
+ENCODING 8799
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR notequal
+ENCODING 8800
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+40
+E0
+80
+00
+ENDCHAR
+STARTCHAR equivalence
+ENCODING 8801
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2262
+ENCODING 8802
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+20
+E0
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni2263
+ENCODING 8803
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+00
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR lessequal
+ENCODING 8804
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR greaterequal
+ENCODING 8805
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2266
+ENCODING 8806
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2267
+ENCODING 8807
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+E0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2268
+ENCODING 8808
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+40
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni2269
+ENCODING 8809
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+80
+40
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni226A
+ENCODING 8810
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+50
+A0
+50
+00
+00
+ENDCHAR
+STARTCHAR uni226B
+ENCODING 8811
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+50
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni226C
+ENCODING 8812
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+40
+A0
+40
+A0
+00
+ENDCHAR
+STARTCHAR uni226D
+ENCODING 8813
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+E0
+40
+E0
+80
+00
+ENDCHAR
+STARTCHAR uni226E
+ENCODING 8814
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+60
+C0
+60
+80
+00
+ENDCHAR
+STARTCHAR uni226F
+ENCODING 8815
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+60
+C0
+80
+00
+ENDCHAR
+STARTCHAR uni2270
+ENCODING 8816
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni2271
+ENCODING 8817
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+60
+E0
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni2272
+ENCODING 8818
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+E0
+00
+50
+A0
+ENDCHAR
+STARTCHAR uni2273
+ENCODING 8819
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+E0
+00
+A0
+50
+ENDCHAR
+STARTCHAR uni2276
+ENCODING 8822
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+20
+80
+60
+C0
+ENDCHAR
+STARTCHAR uni2277
+ENCODING 8823
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+60
+80
+20
+C0
+60
+ENDCHAR
+STARTCHAR uni2278
+ENCODING 8824
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+C0
+60
+C0
+60
+C0
+ENDCHAR
+STARTCHAR uni2279
+ENCODING 8825
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+60
+C0
+60
+C0
+60
+ENDCHAR
+STARTCHAR uni227A
+ENCODING 8826
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+20
+C0
+20
+00
+00
+ENDCHAR
+STARTCHAR uni227B
+ENCODING 8827
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+80
+60
+80
+00
+00
+ENDCHAR
+STARTCHAR uni227C
+ENCODING 8828
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+20
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni227D
+ENCODING 8829
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+60
+80
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni227E
+ENCODING 8830
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+20
+00
+A0
+50
+ENDCHAR
+STARTCHAR uni227F
+ENCODING 8831
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+C0
+20
+00
+A0
+50
+ENDCHAR
+STARTCHAR uni2280
+ENCODING 8832
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+C0
+60
+40
+00
+ENDCHAR
+STARTCHAR uni2281
+ENCODING 8833
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+60
+C0
+40
+00
+ENDCHAR
+STARTCHAR propersubset
+ENCODING 8834
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+80
+60
+00
+00
+ENDCHAR
+STARTCHAR propersuperset
+ENCODING 8835
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+C0
+20
+C0
+00
+00
+ENDCHAR
+STARTCHAR notsubset
+ENCODING 8836
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+C0
+60
+40
+00
+ENDCHAR
+STARTCHAR uni2285
+ENCODING 8837
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+C0
+60
+C0
+40
+00
+ENDCHAR
+STARTCHAR reflexsubset
+ENCODING 8838
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+60
+00
+E0
+00
+ENDCHAR
+STARTCHAR reflexsuperset
+ENCODING 8839
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+C0
+00
+E0
+00
+ENDCHAR
+STARTCHAR uni2288
+ENCODING 8840
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+A0
+60
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni2289
+ENCODING 8841
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+60
+C0
+40
+E0
+40
+ENDCHAR
+STARTCHAR uni228A
+ENCODING 8842
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+80
+60
+40
+E0
+80
+ENDCHAR
+STARTCHAR uni228B
+ENCODING 8843
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+20
+C0
+40
+E0
+80
+ENDCHAR
+STARTCHAR revlogicalnot
+ENCODING 8976
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+80
+00
+00
+ENDCHAR
+STARTCHAR integraltp
+ENCODING 8992
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR integralbt
+ENCODING 8993
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+20
+20
+20
+20
+20
+40
+ENDCHAR
+STARTCHAR uni23BA
+ENCODING 9146
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BB
+ENCODING 9147
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni23BC
+ENCODING 9148
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni23BD
+ENCODING 9149
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+F0
+ENDCHAR
+STARTCHAR uni2409
+ENCODING 9225
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+70
+20
+20
+ENDCHAR
+STARTCHAR uni240A
+ENCODING 9226
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+E0
+60
+40
+40
+ENDCHAR
+STARTCHAR uni240B
+ENCODING 9227
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+A0
+40
+70
+20
+20
+ENDCHAR
+STARTCHAR uni240C
+ENCODING 9228
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+C0
+80
+60
+60
+40
+ENDCHAR
+STARTCHAR uni240D
+ENCODING 9229
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+80
+E0
+50
+60
+50
+ENDCHAR
+STARTCHAR uni2423
+ENCODING 9251
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+90
+F0
+ENDCHAR
+STARTCHAR uni2424
+ENCODING 9252
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+D0
+B0
+90
+20
+20
+30
+ENDCHAR
+STARTCHAR SF100000
+ENCODING 9472
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2501
+ENCODING 9473
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F8
+F8
+00
+00
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9474
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR uni2503
+ENCODING 9475
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR uni2504
+ENCODING 9476
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni2505
+ENCODING 9477
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A8
+A8
+00
+00
+ENDCHAR
+STARTCHAR uni2506
+ENCODING 9478
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR uni2507
+ENCODING 9479
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+60
+00
+60
+00
+ENDCHAR
+STARTCHAR uni2508
+ENCODING 9480
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni2509
+ENCODING 9481
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A8
+A8
+00
+00
+ENDCHAR
+STARTCHAR uni250A
+ENCODING 9482
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+00
+40
+00
+40
+00
+ENDCHAR
+STARTCHAR uni250B
+ENCODING 9483
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+00
+60
+00
+60
+00
+ENDCHAR
+STARTCHAR SF010000
+ENCODING 9484
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+70
+40
+40
+ENDCHAR
+STARTCHAR uni250D
+ENCODING 9485
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+70
+40
+40
+ENDCHAR
+STARTCHAR uni250E
+ENCODING 9486
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+70
+60
+60
+ENDCHAR
+STARTCHAR uni250F
+ENCODING 9487
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+70
+60
+60
+ENDCHAR
+STARTCHAR SF030000
+ENCODING 9488
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+C0
+40
+40
+ENDCHAR
+STARTCHAR uni2511
+ENCODING 9489
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+C0
+40
+40
+ENDCHAR
+STARTCHAR uni2512
+ENCODING 9490
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+E0
+60
+60
+ENDCHAR
+STARTCHAR uni2513
+ENCODING 9491
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+E0
+60
+60
+ENDCHAR
+STARTCHAR SF020000
+ENCODING 9492
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+70
+00
+00
+ENDCHAR
+STARTCHAR uni2515
+ENCODING 9493
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+70
+00
+00
+ENDCHAR
+STARTCHAR uni2516
+ENCODING 9494
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+00
+00
+ENDCHAR
+STARTCHAR uni2517
+ENCODING 9495
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+70
+00
+00
+ENDCHAR
+STARTCHAR SF040000
+ENCODING 9496
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+C0
+00
+00
+ENDCHAR
+STARTCHAR uni2519
+ENCODING 9497
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+C0
+00
+00
+ENDCHAR
+STARTCHAR uni251A
+ENCODING 9498
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+00
+00
+ENDCHAR
+STARTCHAR uni251B
+ENCODING 9499
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+E0
+00
+00
+ENDCHAR
+STARTCHAR SF080000
+ENCODING 9500
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+70
+40
+40
+ENDCHAR
+STARTCHAR uni251D
+ENCODING 9501
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+70
+40
+40
+ENDCHAR
+STARTCHAR uni251E
+ENCODING 9502
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+40
+40
+ENDCHAR
+STARTCHAR uni251F
+ENCODING 9503
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+70
+60
+60
+ENDCHAR
+STARTCHAR uni2520
+ENCODING 9504
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+60
+60
+ENDCHAR
+STARTCHAR uni2521
+ENCODING 9505
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+70
+40
+40
+ENDCHAR
+STARTCHAR uni2522
+ENCODING 9506
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+70
+60
+60
+ENDCHAR
+STARTCHAR uni2523
+ENCODING 9507
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+70
+60
+60
+ENDCHAR
+STARTCHAR SF090000
+ENCODING 9508
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+C0
+40
+40
+ENDCHAR
+STARTCHAR uni2525
+ENCODING 9509
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+C0
+40
+40
+ENDCHAR
+STARTCHAR uni2526
+ENCODING 9510
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+40
+40
+ENDCHAR
+STARTCHAR uni2527
+ENCODING 9511
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+E0
+60
+60
+ENDCHAR
+STARTCHAR uni2528
+ENCODING 9512
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+60
+60
+ENDCHAR
+STARTCHAR uni2529
+ENCODING 9513
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+E0
+40
+40
+ENDCHAR
+STARTCHAR uni252A
+ENCODING 9514
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+E0
+E0
+60
+60
+ENDCHAR
+STARTCHAR uni252B
+ENCODING 9515
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+E0
+60
+60
+ENDCHAR
+STARTCHAR SF060000
+ENCODING 9516
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni252D
+ENCODING 9517
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni252E
+ENCODING 9518
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni252F
+ENCODING 9519
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2530
+ENCODING 9520
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2531
+ENCODING 9521
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2532
+ENCODING 9522
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2533
+ENCODING 9523
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+F0
+60
+60
+ENDCHAR
+STARTCHAR SF070000
+ENCODING 9524
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2535
+ENCODING 9525
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2536
+ENCODING 9526
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2537
+ENCODING 9527
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2538
+ENCODING 9528
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni2539
+ENCODING 9529
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni253A
+ENCODING 9530
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni253B
+ENCODING 9531
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+F0
+00
+00
+ENDCHAR
+STARTCHAR SF050000
+ENCODING 9532
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni253D
+ENCODING 9533
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni253E
+ENCODING 9534
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni253F
+ENCODING 9535
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2540
+ENCODING 9536
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2541
+ENCODING 9537
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2542
+ENCODING 9538
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2543
+ENCODING 9539
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2544
+ENCODING 9540
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2545
+ENCODING 9541
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+E0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2546
+ENCODING 9542
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2547
+ENCODING 9543
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+F0
+40
+40
+ENDCHAR
+STARTCHAR uni2548
+ENCODING 9544
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni2549
+ENCODING 9545
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni254A
+ENCODING 9546
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni254B
+ENCODING 9547
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+F0
+60
+60
+ENDCHAR
+STARTCHAR uni254C
+ENCODING 9548
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni254D
+ENCODING 9549
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+A0
+A0
+00
+00
+ENDCHAR
+STARTCHAR uni254E
+ENCODING 9550
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+40
+00
+40
+40
+ENDCHAR
+STARTCHAR uni254F
+ENCODING 9551
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+60
+60
+00
+60
+60
+ENDCHAR
+STARTCHAR SF430000
+ENCODING 9552
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+F0
+00
+ENDCHAR
+STARTCHAR SF240000
+ENCODING 9553
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR SF510000
+ENCODING 9554
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+40
+70
+40
+ENDCHAR
+STARTCHAR SF520000
+ENCODING 9555
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+70
+60
+60
+ENDCHAR
+STARTCHAR SF390000
+ENCODING 9556
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+40
+70
+60
+ENDCHAR
+STARTCHAR SF220000
+ENCODING 9557
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+40
+C0
+40
+ENDCHAR
+STARTCHAR SF210000
+ENCODING 9558
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+E0
+60
+60
+ENDCHAR
+STARTCHAR SF250000
+ENCODING 9559
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+20
+E0
+60
+ENDCHAR
+STARTCHAR SF500000
+ENCODING 9560
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+40
+70
+00
+ENDCHAR
+STARTCHAR SF490000
+ENCODING 9561
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+00
+00
+ENDCHAR
+STARTCHAR SF380000
+ENCODING 9562
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+40
+70
+00
+ENDCHAR
+STARTCHAR SF280000
+ENCODING 9563
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+40
+C0
+00
+ENDCHAR
+STARTCHAR SF270000
+ENCODING 9564
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+00
+00
+ENDCHAR
+STARTCHAR SF260000
+ENCODING 9565
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+20
+E0
+00
+ENDCHAR
+STARTCHAR SF360000
+ENCODING 9566
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+70
+40
+70
+40
+ENDCHAR
+STARTCHAR SF370000
+ENCODING 9567
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+70
+60
+60
+ENDCHAR
+STARTCHAR SF420000
+ENCODING 9568
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+70
+40
+70
+60
+ENDCHAR
+STARTCHAR SF190000
+ENCODING 9569
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+C0
+40
+C0
+40
+ENDCHAR
+STARTCHAR SF200000
+ENCODING 9570
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+E0
+60
+60
+ENDCHAR
+STARTCHAR SF230000
+ENCODING 9571
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+E0
+20
+E0
+60
+ENDCHAR
+STARTCHAR SF470000
+ENCODING 9572
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+F0
+40
+ENDCHAR
+STARTCHAR SF480000
+ENCODING 9573
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F0
+60
+60
+ENDCHAR
+STARTCHAR SF410000
+ENCODING 9574
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F0
+00
+F0
+60
+ENDCHAR
+STARTCHAR SF450000
+ENCODING 9575
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+00
+F0
+00
+ENDCHAR
+STARTCHAR SF460000
+ENCODING 9576
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+00
+00
+ENDCHAR
+STARTCHAR SF400000
+ENCODING 9577
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+00
+F0
+00
+ENDCHAR
+STARTCHAR SF540000
+ENCODING 9578
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+F0
+40
+F0
+40
+ENDCHAR
+STARTCHAR SF530000
+ENCODING 9579
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+F0
+60
+60
+ENDCHAR
+STARTCHAR SF440000
+ENCODING 9580
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+F0
+00
+F0
+60
+ENDCHAR
+STARTCHAR uni256D
+ENCODING 9581
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+30
+40
+40
+ENDCHAR
+STARTCHAR uni256E
+ENCODING 9582
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+80
+40
+40
+ENDCHAR
+STARTCHAR uni256F
+ENCODING 9583
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+80
+00
+00
+ENDCHAR
+STARTCHAR uni2570
+ENCODING 9584
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+30
+00
+00
+ENDCHAR
+STARTCHAR uni2571
+ENCODING 9585
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR uni2572
+ENCODING 9586
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+40
+40
+20
+20
+10
+ENDCHAR
+STARTCHAR uni2573
+ENCODING 9587
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+90
+90
+60
+60
+90
+90
+ENDCHAR
+STARTCHAR uni2574
+ENCODING 9588
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+C0
+00
+00
+ENDCHAR
+STARTCHAR uni2575
+ENCODING 9589
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+40
+00
+00
+ENDCHAR
+STARTCHAR uni2576
+ENCODING 9590
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+70
+00
+00
+ENDCHAR
+STARTCHAR uni2577
+ENCODING 9591
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+40
+40
+40
+ENDCHAR
+STARTCHAR uni2578
+ENCODING 9592
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+C0
+00
+00
+ENDCHAR
+STARTCHAR uni2579
+ENCODING 9593
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+60
+00
+00
+ENDCHAR
+STARTCHAR uni257A
+ENCODING 9594
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+70
+70
+00
+00
+ENDCHAR
+STARTCHAR uni257B
+ENCODING 9595
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+60
+60
+60
+ENDCHAR
+STARTCHAR uni257C
+ENCODING 9596
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+30
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni257D
+ENCODING 9597
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+60
+60
+60
+ENDCHAR
+STARTCHAR uni257E
+ENCODING 9598
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+C0
+F0
+00
+00
+ENDCHAR
+STARTCHAR uni257F
+ENCODING 9599
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+60
+60
+60
+40
+40
+ENDCHAR
+STARTCHAR upblock
+ENCODING 9600
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F8
+F8
+F8
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2581
+ENCODING 9601
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+F0
+ENDCHAR
+STARTCHAR uni2582
+ENCODING 9602
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+00
+F8
+ENDCHAR
+STARTCHAR uni2583
+ENCODING 9603
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+00
+F8
+F8
+ENDCHAR
+STARTCHAR dnblock
+ENCODING 9604
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR uni2585
+ENCODING 9605
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+00
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR uni2586
+ENCODING 9606
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+F8
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR uni2587
+ENCODING 9607
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+F8
+F8
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR block
+ENCODING 9608
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F8
+F8
+F8
+F8
+F8
+F8
+ENDCHAR
+STARTCHAR uni2589
+ENCODING 9609
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+F0
+F0
+F0
+F0
+F0
+ENDCHAR
+STARTCHAR uni258A
+ENCODING 9610
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+E0
+E0
+E0
+E0
+E0
+ENDCHAR
+STARTCHAR uni258B
+ENCODING 9611
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+E0
+E0
+E0
+E0
+E0
+E0
+ENDCHAR
+STARTCHAR lfblock
+ENCODING 9612
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni258D
+ENCODING 9613
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+C0
+C0
+C0
+C0
+C0
+C0
+ENDCHAR
+STARTCHAR uni258E
+ENCODING 9614
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR uni258F
+ENCODING 9615
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR rtblock
+ENCODING 9616
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR ltshade
+ENCODING 9617
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+20
+80
+20
+80
+20
+ENDCHAR
+STARTCHAR shade
+ENCODING 9618
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A8
+50
+A8
+50
+A8
+50
+ENDCHAR
+STARTCHAR dkshade
+ENCODING 9619
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+B8
+E8
+B8
+E8
+B8
+E8
+ENDCHAR
+STARTCHAR uni2594
+ENCODING 9620
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F8
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni2595
+ENCODING 9621
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR filledbox
+ENCODING 9632
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+E0
+E0
+00
+ENDCHAR
+STARTCHAR H22073
+ENCODING 9633
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+00
+E0
+A0
+E0
+00
+ENDCHAR
+STARTCHAR uni25C6
+ENCODING 9670
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+E0
+40
+00
+ENDCHAR
+STARTCHAR spade
+ENCODING 9824
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+E0
+E0
+40
+E0
+00
+ENDCHAR
+STARTCHAR club
+ENCODING 9827
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+A0
+40
+E0
+00
+ENDCHAR
+STARTCHAR heart
+ENCODING 9829
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+A0
+E0
+E0
+40
+00
+ENDCHAR
+STARTCHAR diamond
+ENCODING 9830
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+00
+40
+E0
+40
+00
+00
+ENDCHAR
+STARTCHAR uni2669
+ENCODING 9833
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+40
+40
+C0
+80
+00
+ENDCHAR
+STARTCHAR musicalnote
+ENCODING 9834
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+40
+60
+40
+C0
+80
+00
+ENDCHAR
+STARTCHAR musicalnotedbl
+ENCODING 9835
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+50
+50
+50
+A0
+00
+ENDCHAR
+STARTCHAR uni266C
+ENCODING 9836
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+70
+70
+50
+50
+A0
+00
+ENDCHAR
+STARTCHAR uni266D
+ENCODING 9837
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+80
+E0
+A0
+C0
+00
+ENDCHAR
+STARTCHAR uni266E
+ENCODING 9838
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+80
+E0
+A0
+E0
+20
+00
+ENDCHAR
+STARTCHAR uni266F
+ENCODING 9839
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+A0
+E0
+A0
+E0
+A0
+00
+ENDCHAR
+STARTCHAR uniFFFD
+ENCODING 65533
+SWIDTH 640 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+F0
+90
+D0
+F0
+D0
+F0
+ENDCHAR
+ENDFONT
diff --git a/src/col64/cruft/coltbl.pl b/src/col64/cruft/coltbl.pl
new file mode 100644
index 0000000..e933437
--- /dev/null
+++ b/src/col64/cruft/coltbl.pl
@@ -0,0 +1,17 @@
+#!/usr/bin/perl -w
+
+for(0..63) {
+ $pix = $_*5;
+ $byte = int($pix/8);
+ $mask = 0xf800;
+ $offs = $pix % 8;
+ $mask >>= $offs;
+ $mask = (~$mask) & 0xffff;
+ $mleft = sprintf "%02X", $mask >> 8;
+ $mright = sprintf "%02X", $mask & 0xff;
+ $m = sprintf("%016b", $mask);
+ printf "\$%02X, ", $offs;
+# print <<EOF;
+#$_ $pix $byte $offs $mleft $mright $m
+#EOF
+}
diff --git a/src/col64/equates.inc b/src/col64/equates.inc
new file mode 100644
index 0000000..9759a8a
--- /dev/null
+++ b/src/col64/equates.inc
@@ -0,0 +1,1386 @@
+;
+; ATARI 800 EQUATE LISTING
+;
+; (version 20070530_bkw)
+;
+; This is a heavily modified copy of Appendix A of the Atari System
+; Reference Manual (with much info added from Appendix B, and from
+; Mapping the Atari and other sources)
+;
+;
+;This listing is based on the original release of Operating System,
+;version A. The vectors shown here were not changed in version B.
+;New equates for XL and XE models are included and noted. Changes
+;from version B to XL/XE are also noted.
+;
+;Most of the equate names given below are the official Atari
+;names. They are in common use but are not mandatory.
+
+; This file can be included in your assembly source, but it's also
+; got a lot of useful human-readable comments. It's meant to serve as
+; a "quick reference" to Atari programmers, particularly ones who use
+; a cross-assembler on a UNIX-ish platform and a text editor that can
+; use "ctags":
+
+; $ ctags equates.inc
+; $ vim mystuff.dasm
+
+; While in vim, press ^] (control-right-bracket) while sitting on a label,
+; to jump to that label's definition in this file. (Also, you can type
+; :tag labelname). You can also do completion on the labels in vim by
+; typing part of a label and pressing ^N (or Tab, if you use the
+; CleverTab script from vimhelp.org)
+
+; GNU Emacs and XEmacs also support ctags, but I've never used them, so
+; I dunno how to do it. I do know that you need to use "Exuberant" ctags,
+; not the ctags that comes with emacs (which doesn't grok 6502 asm).
+
+; If you're using an Atari assembler instead of a cross-assembler, you
+; don't want to use this as-is: all the extra comments make it huge, and
+; it'll be either too large for the Atari's memory, or at least will take
+; a long time to assemble. You can make a comment-less, Atari-compatible
+; version like so:
+
+; perl -lne 's/;.*//; s/\s*$//; print if $_' < equates.inc > small.inc
+
+; ...then use a8eol to convert it to ATASCII format.
+
+; 20061028 bkw: Originally downloaded from:
+
+; http://atrey.karlin.mff.cuni.cz/~pavel/atari/atrb.html
+
+; ...and converted to DASM/ATASM/CA65 format. dasm, atasm, and ca65 use
+; similar enough syntax that this file can be used as-is with any of
+; them. Unfortunately, this means I can't do conditional assembly in this
+; file, since the two assemblers use different semantics... macros are
+; even less compatible :(
+
+; If you use ca65, you need this line in your source:
+
+;; .FEATURE labels_without_colons
+
+; before including this file, or else run ca65 with
+; "--feature labels_without_colons").
+
+; 20070529 bkw: updated, added missing GTIA/POKEY/ANTIC equates,
+; documented where the shadows are for those GTIA/POKEY/ANTIC/PIA
+; registers that have them. Also added a list of error messages and
+; explanation of the cassette buffer layout, and organized the C_*
+; CIO constants. Made minor modifications to get this file to assemble
+; with ATasm as well as DASM.
+
+; I have added a few missing equates: this file only
+; contained OS ROM locations when I got it.
+; I added a few from FMS/DOS as well (e.g. RUNAD and INITAD).
+
+; XL-specific locations in the original file were duplicate labels
+; (e.g. PTIMOT was defined as both $1C and $314), which keeps DASM
+; from being able to assemble the file. I prefixed the XL/XL versions
+; with "XL_"
+
+; Also, I've prefixed the CIO command and AUX1 constants with C_, since some
+; of them conflicted with other labels in the original version.
+
+; Areas listed as "unmapped" are literally not connected to anything.
+; Trying to read from unmapped address space results in reading whatever
+; garbage was on the data bus when the read happened. On my 1200XL, this
+; generally results in all 1's ($FF or 255).
+; In a 400, 600XL or other Atari with less than 48K of RAM, the missing
+; RAM address space is also unmapped.
+
+; Still TODO:
+; - Rest of the DOS/FMS equates
+; - Mark 800-ony locations with OSB_
+; - ifdef code, so the user can set the machine type (OSB or XL),
+; then refer to e.g. PTIMOT and get either OSB_PTIMOT or XL_PTIMOT
+; - Split into separate files? I'd rather not (it's only about 1000 lines)
+
+; This file's mostly intended for new development. It could also be
+; useful for porting old ASM/ED or Mac65 code to DASM, but such code
+; may need work... you can always assemble it with ATasm, in that case,
+; since it's 99.999% source code compatible with Mac65.
+
+; References to "APPENDIX C" and such are referring to the Atari System
+; Reference Manual, a version of which can be found at:
+
+; http://atrey.karlin.mff.cuni.cz/~pavel/atari/atrtblc.html
+
+; References to "Mapping" refer to "Mapping the Atari, Revised Edition",
+; which can be found at:
+
+; http://www.atariarchives.org/mapping/index.php
+
+; I've pasted a few quotes from Mapping into this file; I consider them
+; small enough to be covered under the "fair use" provisions of copyright law
+; (I am not a lawyer, though).
+
+;
+;
+; DEVICE NAMES
+;
+;
+;SCREDT = "E" SCREEN EDITOR
+;KBD = "K" KEYBOARD
+;DISPLY = "S" DISPLAY
+;PRINTR = "P" PRINTER
+;CASSET = "C" CASSETTE
+;DISK = "D" DISK DRIVE
+;
+;
+;
+; STATUS CODES
+;
+;
+
+; 20070529 bkw: These are returned as error codes, though various DOSes
+; also define their own codes (usually in the range 160-255).
+; Errors 2-21 are defined by BASIC.
+; Errors 150-154 are defined by the R: (850 or compatible, RS-232) handler.
+SUCCES = $01 ; 1
+BRKABT = $80 ; 128 BREAK KEY ABORT
+PRVOPN = $82 ; 130 IOCB ALREADY OPEN
+NONDEV = $82 ; 130 NONEXISTANT DEVICE
+WRONLY = $83 ; 131 OPENED FOR WRITE ONLY
+NVALID = $84 ; 132 INVALID COMMAND
+NOTOPN = $85 ; 133 DEVICE OR FILE NOT OPEN
+BADIOC = $86 ; 134 INVALID IOCB NUMBER
+RDONLY = $87 ; 135 OPENED FOR READ ONLY
+EOFERR = $88 ; 136 END OF FILE
+TRNRCD = $89 ; 137 TRUNCATED RECORD
+TIMOUT = $8A ; 138 PERIPHERAL TIME OUT
+DNACK = $8B ; 139 DEVICE DOES NOT ACKNOWLEDGE
+FRMERR = $8C ; 140 SERIAL BUS FRAMING ERROR
+CRSROR = $8D ; 141 CURSOR OUT OF RANGE
+OVRRUN = $8E ; 142 SERIAL BUS DATA OVERRUN
+CHKERR = $8F ; 143 SERIAL BUS CHECKSUM ERROR
+DERROR = $90 ; 144 PERIPHERAL DEVICE ERROR
+BADMOD = $91 ; 145 NON EXISTANT SCREEN MODE
+FNCNOT = $92 ; 146 FUNCTION NOT IMPLEMENTED
+SCRMEM = $93 ; 147 NOT ENOUGH MEMORY FOR SCREEN MODE
+
+; BASIC error codes (also used by e.g. Basic XL/XE and Turbo BASIC):
+;; 2: Insufficient Memory
+;; 3: Value Error
+;; 4: Too Many Variables
+;; 5: String Length Error
+;; 6: Out of Data Error
+;; 7: Number Greater than 32767
+;; 8: Input Statement Error
+;; 9: Array or String DIM Error
+;; 10: Argument Stack Overflow
+;; 11: Floating Point Overflow or Underflow Error
+;; 12: Line Not Found
+;; 13: No Matching FOR Statement
+;; 14: Line Too Long
+;; 15: GOSUB or FOR Line Deleted
+;; 16: RETURN Error
+;; 17: Garbage Error
+;; 18: Invalid String Character
+;; 19: LOAD Program Too Long
+;; 20: Bad Channel Number
+;; 21: LOAD File Error
+
+; 850/R: error codes:
+;; 150: Serial Port Already Open
+;; 151: Concurrent Mode Not Enabled
+;; 152: Illegal User-Supplied Buffer
+;; 153: Active Concurrent Mode Error
+;; 154: Concurrent Mode Not Active
+
+; DOS error codes (DOS 2.0S only; other DOSes may define other errors)
+;; 160: Device Number Error
+;; 161: Too Many OPEN Files
+;; 162: Disk Full
+;; 163: Fatal System Error
+;; 164: File Number Mismatch
+;; 165: Bad File Name
+;; 166: POINT Data Length Error
+;; 167: File Locked
+;; 168: Invalid XIO Command
+;; 169: Directory Full
+;; 170: File Not Found
+;; 171: POINT Invalid
+;; 172: DOS 1 File
+;; 173: Bad Sector
+;; 255: FORMATTING Error (DOS 2.5)
+
+;
+;
+;
+;
+; COMMAND CODES FOR CIO
+;
+;
+
+; Command byte goes in ICCOM,x
+
+;; General-purpose commands:
+C_OPEN = $03 ; 3 OPEN (BASIC OPEN)
+C_GETREC = $05 ; 5 GET RECORD
+C_GETCHR = $07 ; 7 GET BYTE
+C_PUTREC = $09 ; 9 WRITE RECORD
+C_PUTCHR = $0B ; 11 PUT-BYTE
+C_CLOSE = $0C ; 12
+C_STATUS = $0D ; 13
+C_SPECIL = $0E ; 14 BEGINNING OF SPECIAL COMMANDS (aka XIO)
+;; Commands for S: device:
+C_DRAWLN = $11 ; 17 SCREEN DRAW (BASIC DRAWTO)
+C_FILLIN = $12 ; 18 SCREEN FILL
+;; Commands for D: device (only when DOS is loaded):
+C_RENAME = $20 ; 32
+C_DELETE = $21 ; 33
+C_LOCK = $23 ; 35
+C_UNLOCK = $24 ; 36
+C_POINT = $25 ; 37
+C_NOTE = $26 ; 38
+
+; AUX1 modes (ICAX1,x or 2nd parameter of BASIC OPEN command):
+C_OPREAD = $04 ; 4 OPEN FOR INPUT
+C_OWRITE = $08 ; 8 OPEN FOR OUTPUT
+C_APPEND = $09 ; 9 OPEN TO APPEND TO END OF DISK FILE
+C_OUPDAT = $0C ; 12 OPEN FOR INPUT AND OUTPUT AT THE SAME TIME
+;; D: (DOS) only:
+C_OPDIR = $06 ; 6 OPEN TO DISK DIRECTORY
+;; S: only:
+C_MXDMOD = $10 ; 16 OPEN TO SPLIT SCREEN (MIXED MODE)
+C_INSCLR = $20 ; 32 OPEN TO SCREEN BUT DON'T ERASE
+;; C: only:
+C_NOIRG = $80 ; 128 NO GAP CASSETTE MODE
+
+;; Command bytes (ICCOM) for the RS-232 (R:) device:
+;;
+;; Output partial block 32 $20
+;; Control RTS,XMT,DTR 34 $22
+;; Baud, stop bits, word size 36 $24
+;; Translation mode 38 $26
+;; Concurrent mode 40 $28
+;;
+;; (see the 850 Interface Manual for details)
+
+
+; SIO command bytes (not part of CIO):
+S_DFRMAT = $21 ; 33 FORMAT DISK (RESIDENT DISK HANDLER (RDH))
+S_PTSECT = $50 ; 80 RDH PUT SECTOR
+S_GTSECT = $52 ; 82 RDH GET SECTOR
+S_DSTAT = $53 ; 83 RDH GET STATUS
+S_PSECTV = $57 ; 87 RDH PUT SECTOR AND VERIFY
+; Various other SIO commands are supported by different drives
+
+; 20061028 bkw: CR/EOL not really part of CIO, but useful:
+CR = $9B ; 155 CARRIAGE RETURN (EOL)
+EOL = CR ; defined in SYSEQU.ASM
+
+;
+IOCBSZ = $10 ; 16 IOCB SIZE
+MAXIOC = $80 ; 128 MAX IOCB BLOCK SIZE
+IOCBF = $FF ; 255 IOCB FREE
+;
+LEDGE = $02 ; 2 DEFAULT LEFT MARGIN
+REDGE = $27 ; 39 DEFAULT RIGHT MARGIN
+
+; OS VARIABLES
+;
+; PAGE 0
+;
+LINZBS = $00 ; 0 (800) FOR ORIGINAL DEBUGGER
+; $00 0 (XL) RESERVED
+NGFLAG = $01 ; 1 (XL) FOR POWER-UP SELF TEST
+CASINI = $02 ; 2
+RAMLO = $04 ; 4 POINTER FOR SELF TEST
+TRAMSZ = $06 ; 6 TEMPORARY RAM SIZE
+TSTDAT = $07 ; 7 TEST DATA
+WARMST = $08 ; 8
+BOOTQ = $09 ; 9 SUCCESSFUL BOOT FLAG
+; aka BOOT? in the OS source, but some assemblers don't support ? in labels
+DOSVEC = $0A ; 10 PROGRAM RUN VECTOR
+DOSINI = $0C ; 12 PROGRAM INITIALIZATION
+APPMHI = $0E ; 14 DISPLAY LOW LIMIT
+POKMSK = $10 ; 16 IRQ ENABLE FLAGS (shadow for IRQEN)
+BRKKEY = $11 ; 17 FLAG
+RTCLOK = $12 ; 18 3 BYTES, MSB FIRST
+BUFADR = $15 ; 21 INDIRECT BUFFER ADDRESS
+ICCOMT = $17 ; 23 COMMAND FOR VECTOR
+DSKFMS = $18 ; 24 DISK FILE MANAGER POINTER
+DSKUTL = $1A ; 26 DISK UTILITY POINTER (DUP.SYS)
+PTIMOT = $1C ; 28 (800) PRINTER TIME OUT REGISTER
+ABUFPT = $1C ; 28 (XL) RESERVED
+PBPNT = $1D ; 29 (800) PRINTER BUFFER POINTER
+; $1D ; 29 (XL) RESERVED
+PBUFSZ = $1E ; 30 (800) PRINTER BUFFER SIZE
+; $1E ; 30 (XL) RESERVED
+PTEMP = $1F ; 31 (800) TEMPORARY REGISTER (PTEMP deleted in XL OS)
+; $1F ; 31 (XL) RESERVED
+ZIOCB = $20 ; 32 ZERO PAGE IOCB
+ICHIDZ = $20 ; 32 HANDLER INDEX NUMBER (ID)
+ICDNOZ = $21 ; 33 DEVICE NUMBER
+ICCOMZ = $22 ; 34 COMMAND
+ICSTAZ = $23 ; 35 STATUS
+ICBALZ = $24 ; 36 BUFFER POINTER LOW BYTE
+ICBAHZ = $25 ; 37 BUFFER POINTER HIGH BYTE
+ICPTLZ = $26 ; 38 PUT ROUTINE POINTER LOW
+ICPTHZ = $27 ; 39 PUT ROUTINE POINTER HIGH
+ICBLLZ = $28 ; 40 BUFFER LENGTH LOW
+ICBLHZ = $29 ; 41
+ICAX1Z = $2A ; 42 AUXILIARY INFORMATION BYTE 1
+ICAX2Z = $2B ; 43
+ICSPRZ = $2C ; 44 TWO SPARE BYTES (CIO USE)
+ICIDNO = $2E ; 46 IOCB NUMBER X 16
+CIOCHR = $2F ; 47 CHARACTER BYTE FOR CURRENT OPERATION
+;
+STATUS = $30 ; 48 STATUS STORAGE
+CHKSUM = $31 ; 49 SUM WITH CARRY ADDED BACK
+BUFRLO = $32 ; 50 DATA BUFFER LOW BYTE
+BUFRHI = $33 ; 51
+BFENLO = $34 ; 52 ADDRESS OF LAST BUFFER BYTE +1 (LOW)
+BFENHI = $35 ; 53
+CRETRY = $36 ; 54 (800) NUMBER OF COMMAND FRAME RETRIES
+XL_LTEMP = $36 ; 54 (XL) LOADER TEMPORARY STORAGE, 2 BYTES
+DRETRY = $37 ; 55 (800) DEVICE RETRIES
+BUFRFL = $38 ; 56 BUFFER FULL FLAG
+RECVDN = $39 ; 57 RECEIVE DONE FLAG
+XMTDON = $3A ; 58 TRANSMISSION DONE FLAG
+CHKSNT = $3B ; 59 CHECKSUM-SENT FLAG
+NOCKSM = $3C ; 60 CHECKSUM-DOES-NOT-FOLLOW-DATA FLAG
+BPTR = $3D ; 61
+FTYPE = $3E ; 62
+FEOF = $3F ; 63
+FREQ = $40 ; 64
+;
+SOUNDR = $41 ; 65 0=QUIET I/O
+CRITIC = $42 ; 66 CRITICAL FUNCTION FLAG, NO DEFFERED VBI
+FMSZPG = $43 ; 67 DOS ZERO PAGE, 7 BYTES
+CKEY = $4A ; 74 (800) START KEY FLAG
+XL_ZCHAIN = $4A ; 74 (XL) HANDLER LOADER TEMP, 2 BYTES
+CASSBT = $4B ; 75 (800) CASSETTE BOOT FLAG
+DSTAT = $4C ; 76 DISPLAY STATUS
+;
+ATRACT = $4D ; 77
+DRKMSK = $4E ; 78 ATTRACT MASK
+COLRSH = $4F ; 79 ATTRACT COLOR SHIFTER (EORed WITH GRAPHICS)
+;
+TMPCHR = $50 ; 80
+HOLD1 = $51 ; 81
+LMARGN = $52 ; 82 SCREEN LEFT MARGIN REGISTER
+RMARGN = $53 ; 83 SCREEN RIGHT MARGIN
+ROWCRS = $54 ; 84 CURSOR ROW
+COLCRS = $55 ; 85 CURSOR COLUMN, 2 BYTES
+DINDEX = $57 ; 87 DISPLAY MODE
+SAVMSC = $58 ; 88 SCREEN ADDRESS
+OLDROW = $5A ; 90 CURSOR BEFORE DRAW OR FILL
+OLDCOL = $5B ; 91
+OLDCHR = $5D ; 93 DATA UNDER CURSOR
+OLDADR = $5E ; 94 CURSOR ADDRESS
+XL_FKDEF = $60 ; 96 (XL) FUNCTION KEY DEFINITION POINTER (LSB/MSB)
+NEWROW = $60 ; 96 (800) DRAWTO DESTINATION
+NEWCOL = $61 ; 97 (800) DRAWTO DESTINATION, 2 BYTES
+XL_PALNTS = $62 ; 98 (XL) EUROPE/NORTH AMERICA TV FLAG
+LOGCOL = $63 ; 99 LOGICAL LINE COLUMN POINTER
+MLTTMP = $66 ; 102
+OPNTMP = $66 ; 102 TEMPORARY STORAGE FOR CHANNEL OPEN
+SAVADR = $68 ; 104
+RAMTOP = $6A ; 106 START OF ROM (END OF RAM + 1), HIGH BYTE ONLY
+BUFCNT = $6B ; 107 BUFFER COUNT
+BUFSTR = $6C ; 108 POINTER USED BY EDITOR
+BITMSK = $6E ; 110 POINTER USED BY EDITOR
+SHFAMT = $6F ; 111
+ROWAC = $70 ; 112
+COLAC = $72 ; 114
+ENDPT = $74 ; 116
+DELTAR = $76 ; 118
+DELTAC = $77 ; 119
+ROWINC = $79 ; 121 (800)
+XL_KEYDEF = $79 ; 121 (XL) KEY DEFINITION POINTER, 2 BYTES
+COLINC = $7A ; 122 (800)
+SWPFLG = $7B ; 123 NON 0 IF TEXT AND REGULAR RAM IS SWAPPED
+HOLDCH = $7C ; 124 CH MOVED HERE BEFORE CTRL AND SHIFT
+INSDAT = $7D ; 125 used by S: handler, tmp for char under cursor
+COUNTR = $7E ; 126 used by XIO DRAW command (2 bytes)
+
+; $80 to $FF are free if BASIC and floating point are not used.
+; If BASIC is not used, but FP is, $80 to $D0 are still free.
+; There is no way to use BASIC without constantly using FP, as all BASIC
+; numbers are FP (even "integers" such as line numbers).
+ZROFRE = $80 ; 128 FREE ZERO PAGE, 84 BYTES
+
+; BASIC zero page variables:
+LOMEM = $80 ; 128 LSB, BASIC start-of-memory pointer
+; $81 ; 129 MSB, LOMEM (not to be confused with the OS's MEMLO!)
+VNTP = $82 ; 130 LSB, BASIC start of Variable Name Table pointer
+; $83 ; 131 MSB, VNTP
+VNTD = $84 ; 132 LSB, BASIC end of Variable Name Table pointer (+1 byte)
+; $85 ; 133 MSB, VNTP
+VVTP = $86 ; 134 LSB, BASIC start of Variable Value Table pointer
+; $87 ; 135 MSB, VVTP
+STMTAB = $88 ; 136 LSB, BASIC start of Statement Table pointer
+; $89 ; 137 MSB, STMTAB
+STMCUR = $8A ; 138 LSB, BASIC current statement pointer
+; $8B ; 139 MSB, STMCUR
+STARP = $8C ; 140 LSB, BASIC current string/array table pointer
+; $8D ; 141 MSB, STARP (also points to end of BASIC program)
+RUNSTK = $8E ; 142 LSB, BASIC runtime stack pointer
+; $8F ; 143 MSG, RUNSTK
+; BASIC and the OS both use the name MEMTOP; I've renamed the BASIC one.
+BAS_MEMTOP = $90 ; 144 LSB, pointer to top of BASIC memory
+; $91 ; 145 MSB, BAS_MEMTOP
+MEOLFLG = $92 ; 146 "modified EOL flag register", whatever that is
+; $93 ; 147 listed as "spare" by Mapping's Errata
+;COX = $94 ; 148 current output index (?)
+POKADR = $95 ; 149 LSB, address of last POKE location
+; ; 150 MSB, POKADR
+
+; Locations $96 to $B5 are used for various purposes by BASIC,
+; and most of them are of little or no interest, even for someone
+; writing assembly code meant to run as a USR() routine, so I haven't
+; bothered listing them all here. See Compute! Books' "Atari BASIC Sourcebook"
+; for the gory details. In fact, you can see it here:
+
+; http://users.telenet.be/kim1-6502/6502/absb.html
+
+; It's fascinating (at least it is to me)... includes full source code
+; to Atari BASIC!
+
+; DATAD and DATALN are reset to 0 by BASIC RESTORE command.
+DATAD = $B6 ; 182 the data element being read (e.g. 10 for 10th item
+ ; in a DATA statement)
+DATALN = $B7 ; 183 LSB current DATA statement line number
+; $B8 ; 184 MSB, DATALN
+;ERRNUM = $B9 ; 185 Most recent error number. Gets cleared before you
+ ; can PEEK it; use ERRSAVE instead.
+STOPLN = $BA ; 186 LSB, line where a program stopped by STOP/break/error
+; $BB ; 187 MSB, STOPLN
+; what are $BC and $BD for?
+SAVCUR = $BE ; 190 Saves the current line address (LSB?)
+; $BF ; 191 presumably, the MSB of SAVCUR?
+IOCMD = $C0 ; 192, I/O Command (Mapping Errata)
+IODVC = $C1 ; 193, I/O Device (Mapping Errata)
+PROMPT = $C2 ; 194, Prompt character (Mapping Errata, presumably INPUT?)
+ERRSAVE = $C3 ; 195 Error code that caused a stop or TRAP
+;TEMPA = $C4 ; 196 a 2-byte temp
+;ZTEMP2 = $C6 ; 198 a 2-byte temp
+COLOR = $C8 ; 200 Stores color from COLOR command
+PTABW = $C9 ; 201 Number of columns between tab stops
+ ; (for PRINT with commas, not the TAB key)
+LOADFLG = $CA ; 202 Load in progress flag. I can tell you from bitter
+ ; experience that BASIC clears this often.
+
+; $CB - $CF are unused by BASIC or the ASM/ED cart.
+; $D0 and $D1 are unused by BASIC (does that mean they *are* used by ASM/ED?)
+
+; $D2 and $D3 are used by BASIC. Mapping Errata calls them the "BASIC
+; floating-point work area". They get cleared to 0 by BASIC, probably
+; every time a FP number is used (e.g. "POKE 210,1:? PEEK(210)" prints 0).
+; The BASIC source code labels $D2 as TVTYPE and VTYPE, and $D3 as
+; TVNUM and VNUM.
+
+; Floating point zero page variables:
+FPZRO = $D4 ; 212 FLOATING POINT RAM, 43 BYTES
+ ; (20070530 bkw: pretty sure that comment is wrong, and
+ ; should read 44 bytes; see $FF below)
+FR0 = $D4 ; 212 FP REGISTER 0 (also used by BASIC for USR() return val)
+ ; (FR0/FRE/FR1/FR2 are each 6 bytes long)
+FRE = $DA ; 218
+FR1 = $E0 ; 224 FP REGISTER 1
+FR2 = $E6 ; 230 FP REGISTER 2
+FRX = $EC ; 236 SPARE
+EEXP = $ED ; 237 VALUE OF E
+NSIGN = $ED ; 237 SIGN OF FP NUMBER
+ESIGN = $EF ; 239 SIGN OF FP EXPONENT
+FCHFLG = $F0 ; 240 FIRST CHARACTER FLAG
+DIGRT = $F1 ; 241 NUMBER OF DIGITS RIGHT OF DECIMAL POINT
+CIX = $F2 ; 242 INPUT INDEX
+INBUFF = $F3 ; 243 POINTER TO ASCII FP NUMBER
+ZTEMP1 = $F5 ; 245
+ZTEMP4 = $F7 ; 247
+ZTEMP3 = $F9 ; 249
+DEGFLG = $FB ; 251
+RADFLG = $FB ; 251 0=RADIANS, 6=DEGREES
+FLPTR = $FC ; 252 POINTER TO BCD FP NUMBER (2 bytes)
+FPTR2 = $FE ; 254 maybe a 2nd pointer to an FP number? (2 bytes)
+; $FF ; 255 This *definitely* is used by the FP package
+ ; Try: POKE 255,0:? SIN(1):? PEEK(255)
+
+;
+; PAGE 1
+;
+; 65O2 STACK
+;
+;
+
+;
+;
+; PAGE 2
+;
+;
+; 20070529 bkw: Bytes listed as "spare" should NOT be used for your own
+; purposes. They may not really be unused (just undocumented), and/or they
+; may be unused on the 800 but not the XL (or vice versa).
+INTABS = $0200 ; 512 INTERRUPT RAM
+VDSLST = $0200 ; 512 NMI VECTOR
+VPRCED = $0202 ; 514 PROCEED LINE IRQ VECTOR
+VINTER = $0204 ; 516 INTERRUPT LINE IRQ VECTOR
+VBREAK = $0206 ; 518 break key IRQ vector (not in OS rev. A)
+VKEYBD = $0208 ; 520 keyboard IRQ vector (not break/console keys)
+VSERIN = $020A ; 522 SERIAL INPUT READY IRQ
+VSEROR = $020C ; 524 SERIAL OUTPUT READY IRQ
+VSEROC = $020E ; 526 SERIAL OUTPUT COMPLETE IRQ
+VTIMR1 = $0210 ; 528 TIMER 1 IRQ vector
+VTIMR2 = $0212 ; 530 TIMER 2 IRQ vector
+VTIMR4 = $0214 ; 532 TIMER 4 IRQ vector
+VIMIRQ = $0216 ; 534 IRQ VECTOR
+CDTMV1 = $0218 ; 536 COUNTDOWN TIMER 1 vector
+CDTMV2 = $021A ; 538 COUNTDOWN TIMER 2 vector
+CDTMV3 = $021C ; 540 COUNTDOWN TIMER 3 vector
+CDTMV4 = $021E ; 542 COUNTDOWN TIMER 4 vector
+CDTMV5 = $0220 ; 544 COUNTDOWN TIMER 5 vector
+VVBLKI = $0222 ; 546 immediate VBLANK vector
+VVBLKD = $0224 ; 548 deferred VBLANK vector (ignore if CRITIC != 0)
+CDTMA1 = $0226 ; 550 COUNTDOWN TIMER 1 JSR ADDRESS
+CDTMA2 = $0228 ; 552 COUNTDOWN TIMER 2 JSR ADDRESS
+CDTMF3 = $022A ; 554 COUNTDOWN TIMER 3 FLAG
+SRTIMR = $022B ; 555 REPEAT TIMER
+CDTMF4 = $022C ; 556 COUNTDOWN TIMER 4 FLAG
+INTEMP = $022D ; 557 IAN'S TEMP (used by SETVBL routine)
+CDTMF5 = $022E ; 558 COUNTDOWN TIMER FLAG 5
+SDMCTL = $022F ; 559 DMACTL SHADOW
+SDLSTL = $0230 ; 560 DISPLAY LIST POINTER, LSB (shadow for DLISTL)
+SDLSTH = $0231 ; 561 display list pointer, MSB (shadow for DLISTH)
+SSKCTL = $0232 ; 562 SKCTL SHADOW
+; $0233 ; 563 (800) UNLISTED (Mapping calls this SPARE)
+XL_LCOUNT = $0233 ; 563 (XL) LOADER TEMP
+LPENH = $0234 ; 564 LIGHT PEN HORIZONTAL (shadow for PENH)
+LPENV = $0235 ; 565 LIGHT PEN VERTICAL (shadow for PENV)
+; $0236 ; 566 2 SPARE BYTES on OS rev A
+VBRKKY = $0236 ; 566 Break key interrupt vector (OS rev B and XL)
+BRKKY = VBRKKY ; "OS rev 5" listing calls it this
+; $0238 ; 568 (800) SPARE, 2 BYTES
+;XL_RELADR = $0238 ; 568 (XL) relocatable loader relative addr, 1200XL only!
+XL_VPIRQ = $0238 ; 568 (XL) PBI IRQ vector (not on 1200XL!)
+CDEVIC = $023A ; 570 DEVICE COMMAND FRAME BUFFER
+CAUX1 = $023C ; 572 DEVICE COMMAND AUX 1
+CAUX2 = $023D ; 573 DEVICE COMMAND AUX 2
+TEMP = $023E ; 574 TEMPORARY STORAGE
+ERRFLG = $023F ; 575 DEVICE ERROR FLAG (EXCEPT TIMEOUT)
+DFLAGS = $0240 ; 576 FLAGS FROM DISK SECTOR 1
+DBSECT = $0241 ; 577 NUMBER OF BOOT DISK SECTORS
+BOOTAD = $0242 ; 578 BOOT LOAD ADDRESS POINTER
+COLDST = $0244 ; 580 COLD START FLAG, 1 = COLD START IN PROGRESS
+; $0245 ; 581 (800) SPARE
+XL_RECLEN = $0245 ; 581 (XL) LOADER
+DSKTIM = $0246 ; 582 (800) DISK TIME OUT REGISTER
+; $0246 ; 582 (XL) RESERVED, 39 BYTES
+LINBUF = $0247 ; 583 (800) CHARACTER LINE BUFFER, 40 BYTES
+ ; LINBUF was deleted from the XL OS and replaced with:
+
+; $0247 - $024D are "reserved" on the 1200XL. On other XL's they are:
+XL_PDVMSK = $0247 ; 583 shadow for PBI device selection register @ $D1FF
+XL_SHPDVS = $0248 ; 584 shadow for PBI register (where??)
+XL_PDMSK = $0249 ; 585 PBI interrupt mask
+XL_RELADR = $024A ; 586 (XL) LSB, relocatable loader relative addr (NOT 1200XL)
+; $024B ; 587 MSB, XL_RELADR
+XL_PPTMPA = $024C ; 588 temporaries for relocatable loader
+XL_PPTMPX = $024D ; 589 "
+
+; $024E - $026A are "spare" on all XL/XE's
+
+; More XL stuff:
+XL_CHSALT = $026B ; 619 (XL) CHARACTER SET POINTER (ctrl-F4 on 1200XL)
+XL_VSFLAG = $026C ; 620 (XL) FINE SCROLL TEMPORARY
+XL_KEYDIS = $026D ; 621 (XL) KEYBOARD DISABLE (ctrl-F1 on 1200XL)
+XL_FINE = $026E ; 622 (XL) FINE SCROLL FLAG (POKE 622,255:GR.0)
+
+GPRIOR = $026F ; 623 P/M PRIORITY AND GTIA MODES (shadow for PRIOR)
+;GTIA = $026F ; 623 ; 20070529 bkw: does anyone define this?
+
+; Game controller shadows (joysticks/paddles)
+; Joystick directions and paddle triggers (buttons) are wired to the PIA.
+; Joystick triggers (fire buttons) and the actual paddle potentiometers
+; are wired to the GTIA.
+; If this seems a little odd, that's because it is :)
+
+; Paddles (potentiometers):
+PADDL0 = $0270 ; 624 (XL) 3 MORE PADDLES, (800) 7 MORE PADDLES
+PADDL1 = $0271 ; 625 (these are read in BASIC with PADDLE(x)
+PADDL2 = $0272 ; 626 (PADDL0-7 are shadows for POT0-7)
+PADDL3 = $0273 ; 627
+PADDL4 = $0274 ; 628 (PADDL4-7 are copies of PADDL0-3 on the XL)
+PADDL5 = $0275 ; 629
+PADDL6 = $0276 ; 630
+PADDL7 = $0277 ; 631
+
+; Joysticks (directions only)
+STICK0 = $0278 ; 632 (XL) 1 MORE STICK, (800) 3 MORE STICKS
+STICK1 = $0279 ; 633 (these are read in BASIC with STICK(x)
+STICK2 = $027A ; 634 (STICK0/1 are shadows for PORTA; STICK2/3 shadows PORTB)
+STICK3 = $027B ; 635
+; STICK0 is a shadow for bits 4-7 of PORTA (shifted 4 bits right)
+; STICK1 is a shadow for bits 0-3 of PORTA
+
+; On the 800:
+; STICK2 is a shadow for bits 4-7 of PORTB (shifted 4 bits right)
+; STICK3 is a shadow for bits 0-3 of PORTB
+
+; On the XL/XE series:
+; STICK2 and STICK3 are copies of STICK0 and STICK1, respectively.
+
+; In the XL/XE machines, there are only 2 joystick ports, and PORTB
+; (formerly joystick ports) is now used to control the MMU.
+
+; joystick directions are active low (1=not pressed) and decode as:
+
+; bit direction
+; 0 or 4 up
+; 1 or 5 down
+; 2 or 6 left
+; 3 or 7 right
+
+; A value of $0F in a STICKx register means no direction is being pressed.
+; When a direction is pressed, its bit becomes a logic 0, so e.g. $0E means
+; someone's moving the joystick up.
+
+; (bits 4-7 are only used when reading directly from the HW registers,
+; PORTA and PORTB).
+
+; Paddle triggers (buttons)
+PTRIG0 = $027C ; 636 (XL) 3 MORE PADDLE TRIGGERS, (800) 7 MORE
+PTRIG1 = $027D ; 637 (these are read in BASIC with PTRIG(x))
+PTRIG2 = $027E ; 638 (PTRIG0-3 are shadows for PORTA)
+PTRIG3 = $027F ; 639
+PTRIG4 = $0280 ; 640 (PTRIG4-7 are shadows for PORTB on the 800)
+PTRIG5 = $0281 ; 641 (they are copies of PTRIG0-3 on the XL)
+PTRIG6 = $0282 ; 642
+PTRIG7 = $0283 ; 643
+; In case someone doesn't already know this: The paddle triggers are wired
+; to the same pins on the joystick port as the left/right joystick directions.
+; Each pair of paddles uses left for the first paddle's trigger and right
+; for the second (so PTRIG0/1 are also the left/right bits in STICK0,
+; PTRIG2/3 are STICK1, etc).
+
+; Joystick triggers (buttons)
+STRIG0 = $0284 ; 644 (XL) 1 MORE STICK TRIGGER, (800) 3 MORE
+STRIG1 = $0285 ; 645 (these are read in BASIC with STRIG(x))
+STRIG2 = $0286 ; 646 (STRIG0-3 are shadows for TRIG0-3)
+STRIG3 = $0287 ; 647
+
+; C: handler variables:
+CSTAT = $0288 ; 648 (800) Cassette status register
+; note that CSTAT was deleted from the XL OS, and replaced with:
+XL_HIBYTE = $0288 ; 648 (XL) used by relocatable loader
+WMODE = $0289 ; 649 used by C: handler (0=read, 128-write)
+BLIM = $028A ; 650 cassette buffer data record size
+; $028B ; 651 (800) 5 SPARE BYTES (to $028F)
+XL_IMASK = $028B ; 651 (XL) used by relocatable loader
+XL_JVECK = $028C ; 652 (XL) (Mapping says it's unused)
+ ; 653 (XL) Presumably the MSB of JVECK (unused?)
+XL_NEWADR = $028E ; 654 (XL) LOADER RAM (2 bytes)
+
+; Misc. S: and/or E: handler variables:
+TXTROW = $0290 ; 656
+TXTCOL = $0291 ; 657
+TINDEX = $0293 ; 659 TEXT INDEX
+TXTMSC = $0294 ; 660
+TXTOLD = $0296 ; 662 OLD ROW AND OLD COL FOR TEXT, 2 BYTES
+; $0298 ; 664 4 SPARE BYTES
+TMPX1 = $029C ; 668 (800)
+; note that TMPX1 was deleted from the XL OS, and replaced with:
+XL_CRETRY = $029C ; 668 (XL) NUMBER OF COMMAND FRAME RETRIES
+ ; (moved from CRETRY on 800)
+SUBTMP = $029E ; 670
+HOLD2 = $029F ; 671
+DMASK = $02A0 ; 672
+TMPLBT = $02A1 ; 673
+ESCFLG = $02A2 ; 674
+TABMAP = $02A3 ; 675 15 BYTE BIT MAP FOR TAB SETTINGS
+LOGMAP = $02B2 ; 690 4 BYTE LOGICAL LINE START BIT MAP
+INVFLG = $02B6 ; 694 mask for inverse video ($80=inverse, 0=normal)
+FILFLG = $02B7 ; 695 FILL DURING DRAW FLAG
+TMPROW = $02B8 ; 696
+TMPCOL = $02B9 ; 697
+SCRFLG = $02BB ; 699 SCROLL FLAG
+HOLD4 = $02BC ; 700
+HOLD5 = $02BD ; 701 (800)
+; note that HOLD5 was deleted from the XL OS, and replaced with:
+XL_DRETRY = $02BD ; 701 (XL) NUMBER OF DEVICE RETRIES
+ ; (moved from DRETRY on 800)
+SHFLOC = $02BE ; 702
+BOTSCR = $02BF ; 703 24 NORM, 4 SPLIT
+
+; Color register shadows (HW registers are in GTIA)
+PCOLR0 = $02C0 ; 704 3 MORE PLAYER COLOR REGISTERS (shadows for COLPM0-3)
+PCOLR1 = $02C1 ; 705 (missiles use same color regs as same-numbered players!)
+PCOLR2 = $02C2 ; 706
+PCOLR3 = $02C3 ; 707
+COLOR0 = $02C4 ; 708 4 MORE GRAPHICS COLOR REGISTERS (shadows for COLPF0-3)
+COLOR1 = $02C5 ; 709 (text luminance in GR.0)
+COLOR2 = $02C6 ; 710 (text background and chroma in GR.0)
+COLOR3 = $02C7 ; 711
+COLOR4 = $02C8 ; 712 (background, shadow for COLBK)
+; On boot, system reset, or any time S:/E: devices are opened:
+; PCOLR0-3 are initialzed to 0 ($00, black)
+; COLOR0 is initialized to 40 ($28, orange)
+; COLOR1 is initialized to 202 ($CA, green)
+; COLOR2 is initialized to 148 ($94, blue)
+; COLOR3 is initialized to 70 ($46, red)
+; COLOR4 is initialized to 0 ($00, black)
+
+; $02C9 713 (800) 23 SPARE BYTES
+; XL relocatable handler and other variables:
+XL_RUNADR = $02C9 ; 713 (XL) LOADER VECTOR
+XL_HIUSED = $02CB ; 715 (XL) LOADER VECTOR
+XL_ZHIUSE = $02CD ; 717 (XL) LOADER VECTOR
+XL_GBYTEA = $02CF ; 719 (XL) LOADER VECTOR
+XL_LOADAD = $02D1 ; 721 (XL) LOADER VECTOR
+XL_ZLOADA = $02D3 ; 723 (XL) LOADER VECTOR
+XL_DSCTLN = $02D5 ; 725 (XL) DISK SECTOR SIZ
+XL_ACMISR = $02D7 ; 727 (XL) RESERVED
+XL_KRPDER = $02D9 ; 729 (XL) KEY AUTO REPEAT DELAY
+XL_KEYREP = $02DA ; 730 (XL) KEY AUTO REPEAT RATE
+XL_NOCLIK = $02DB ; 731 (XL) KEY CLICK DISABLE (ctrl-F3 on 1200XL)
+XL_HELPFG = $02DC ; 732 (XL) HELP KEY FLAG
+XL_DMASAV = $02DD ; 733 (XL) SDMCTL (DMA) SAVE (ctrl-F2 on 1200XL)
+XL_PBPNT = $02DE ; 734 (XL) PRINTER BUFFER POINTER (moved from PBPNT on 800)
+XL_PBUFSZ = $02DF ; 735 (XL) PRINTER BUFFER SIZE (moved from PBUFSZ on 800)
+; note that PTEMP was deleted from the XL OS
+
+; DOS/FMS variables:
+GLBABS = $02E0 ; 736 GLOBAL VARIABLES, 4 SPARE BYTES (if DOS not loaded)
+ ; If DOS/FMS is loaded:
+RUNAD = $02E0 ; 736 (DOS) Run address for binary file (LSB/MSB)
+INITAD = $02E2 ; 736 (DOS) Init address for binary file (LSB/MSB)
+
+; SYSEQU.ASM defines these:
+GOADR = RUNAD
+INITADR = INITAD
+
+; OS variables:
+RAMSIZ = $02E4 ; 740 PERMANENT START OF ROM POINTER
+MEMTOP = $02E5 ; 741 END OF FREE RAM
+MEMLO = $02E7 ; 743 LSB, points to bottom of free memory ($0700 if DOS
+ ; not booted). Not to be confused with BASIC's LOMEM!
+; $02E8 ; 744 MSB of MEMLO
+
+; $02E9 ; 745 (800) SPARE
+XL_HNDLOD = $02E9 ; 745 (XL) HANDLER LOADER FLAG
+
+DVSTAT = $02EA ; 746 DEVICE STATUS BUFFER, 4 BYTES
+CBAUDL = $02EE ; 750 CASSETTE BAUD RATE, 2 BYTES
+CRSINH = $02F0 ; 752 1 = INHIBIT CURSOR
+KEYDEL = $02F1 ; 753 KEY DELAY AND RATE (aka debounce counter)
+CH1 = $02F2 ; 754 prior keyboard character code
+CHACT = $02F3 ; 755 (shadow for CHACTL)
+CHBAS = $02F4 ; 756 CHARACTER SET POINTER (shadow for CHBASE)
+
+; These next 4 are located elsewhere on the 800 OS:
+XL_NEWROW = $02F5 ; 757 (XL) DRAW DESTINATION
+XL_NEWCOL = $02F6 ; 758 (XL) DRAW DESTINATION
+XL_ROWINC = $02F8 ; 760 (XL)
+XL_COLINC = $02F9 ; 761 (XL)
+; $02F5 - $02F9 are "spare" on the 800.
+
+CHAR = $02FA ; 762 most recent character read/written (screen code)
+ATACHR = $02FB ; 763 ATASCII CHARACTER FOR CIO
+CH = $02FC ; 764 last key pressed (internal scan code)
+FILDAT = $02FC ; 764 COLOR FOR SCREEN FILL
+DSPFLG = $02FE ; 766 DISPLAY CONTROL CHARACTERS FLAG
+SSFLAG = $02FF ; 767 DISPLAY START/STOP FLAFG
+
+;
+; PAGE 3
+;
+;
+; RESIDENT DISK HANDLER/SIO INTERFACE
+;
+; The DCB is used for SIO (serial I/O).
+DCB = $0300 ; 768 DEVICE CONTROL BLOCK
+DDEVIC = $0300 ; 768 device ID ($31-$38 for D1:-D8:)
+DUNIT = $0301 ; 769 disk/device unit numder
+DCOMND = $0302 ; 770 device command
+DSTATS = $0303 ; 771 status code (set by OS)
+DBUFLO = $0304 ; 772 data buffer LSB (set by user)
+DBUFHI = $0305 ; 773 data buffer MSB (set by user)
+DTIMLO = $0306 ; 774 timeout (set by user, units of 60/64 seconds)
+DUNUSE = $0307 ; 775 unused
+DBYTLO = $0308 ; 776 number of bytes to transfer, LSB
+DBYTHI = $0309 ; 777 number of bytes to transfer, MSB
+DAUX1 = $030A ; 778 LSB of sector number (for disk) (set by user)
+DAUX2 = $030B ; 779 MSB of sector number (for disk)
+TIMER1 = $030C ; 780 INITIAL TIMER VALUE
+ADDCOR = $030E ; 782 (800) ADDITION CORRECTION
+; note that ADDCOR was deleted from the XL OS, and replaced with:
+XL_JMPERS = $030E ; 782 (XL) OPTION JUMPERS
+CASFLG = $030F ; 783 CASSETTE MODE WHEN SET
+TIMER2 = $0310 ; 784 FINAL VALUE, TIMERS 1 & 2 DETERMINE BAUD RATE
+TEMP1 = $0312 ; 786
+XL_TEMP2 = $0313 ; 787 (XL)
+TEMP2 = $0314 ; 788 (800)
+XL_PTIMOT = $0314 ; 788 (XL) PRINTER TIME OUT
+TEMP3 = $0315 ; 789
+SAVIO = $0316 ; 790 SAVE SERIAL IN DATA PORT
+TIMFLG = $0317 ; 791 TIME OUT FLAG FOR BAUD RATE CORRECTION
+STACKP = $0318 ; 792 SIO STACK POINTER SAVE
+TSTAT = $0319 ; 793 TEMPORARY STATUS HOLDER
+HATABS = $031A ; 794 HANDLER ADDRESS TABLE, 38 BYTES
+MAXDEV = $0321 ; 801 MAXIMUM HANDLER ADDRESS INDEX
+XL_PUPBT1 = $033D ; 829 (XL) POWER-UP/RESET
+XL_PUPBT2 = $033E ; 830 (XL) POWER-UP/RESET
+XL_PUPBT3 = $033F ; 831 (XL) POWER-UP/RESET
+
+; IOCB's, 8 of them, 16 bytes each.
+; Set X register to (IOCB number * 16), and use e.g. ICCOM,x
+;
+IOCB = $0340 ; 832 ; IOCB base address
+ICHID = $0340 ; 832 ; Handler ID (set by OS)
+ICDNO = $0341 ; 833 ; Device number (set by OS)
+ICCOM = $0342 ; 834 ; Command byte (see C_* constants) (set by user)
+ICCMD = ICCOM ; ; alternate name for ICCOM, according to Mapping.
+ICSTA = $0343 ; 835 ; Status (set by OS)
+ICBAL = $0344 ; 836 ; Buffer address, LSB (set by user)
+ICBAH = $0345 ; 837 ; Buffer address, MSB (set by user)
+ICPTL = $0346 ; 838 ; Put-one-byte address minus one, LSB (set by OS)
+ICPTH = $0347 ; 839 ; Put-one-byte address minus one, MSB (set by OS)
+ICBLL = $0348 ; 840 ; Buffer length, LSB (set by user)
+ICBLH = $0349 ; 841 ; Buffer length, MSB (set by user)
+ICAX1 = $034A ; 842 ; AUX1 byte (2nd param in BASIC OPEN) (set by user)
+ICAX2 = $034B ; 843 ; AUX2 byte (4rd param in BASIC OPEN) (set by user)
+ICAX3 = $034C ; 844 ; AUX3 byte (used by NOTE/POINT) (set by user)
+ICAX4 = $034D ; 845 ; AUX4 byte (used by NOTE/POINT) (set by user)
+ICAX5 = $034E ; 846 ; AUX5 byte (used by NOTE/POINT) (set by user)
+ICAX6 = $034F ; 847 ; Spare aux byte
+; OTHER IOCB's, 112 BYTES ($300 + $10 * channel)
+
+IOCBLEN = ICAX6-IOCB+1 ; length of one IOCB (from SYSEQU.ASM)
+
+; Alternative names for the above. I found these in SYSEQU.ASM, as
+; distributed with the disk version of Mac65.
+ICBADR = ICBAL
+ICPUT = ICPTL
+ICBLEN = ICBLL
+ICAUX1 = ICAX1
+ICAUX2 = ICAX2
+ICAUX3 = ICAX3
+ICAUX4 = ICAX4
+ICAUX5 = ICAX5
+ICAUX6 = ICAX6
+
+PRNBUF = $03C0 ; 960 PRINTER BUFFER, 40 BYTES
+; $03E8 ; 1000 (800) 21 SPARE BYTES
+XL_SUPERF = $03E8 ; 1000 (XL) SCREEN EDITOR
+XL_CKEY = $03E9 ; 1001 (XL) START KEY FLAG
+XL_CASSBT = $03EA ; 1002 (XL) CASSETTE BOOT FLAG
+XL_CARTCK = $03EB ; 1003 (XL) CARTRIDGE CHECKSUM
+XL_ACMVAR = $03ED ; 1005 (XL) RESERVED, 10 BYTES (to $03F7)
+XL_BASICF = $03F8 ; 1006 (XL) 0 if ROM-BASIC enabled, 1 if not
+XL_MINTLK = $03F9 ; 1017 (XL) RESERVED
+XL_GINTLK = $03FA ; 1018 (XL) CARTRIDGE INTERLOCK
+XL_CHLINK = $03FB ; 1019 (XL) HANDLER CHAIN, 2 BYTES
+CASBUF = $03FD ; 1021 CASSETTE BUFFER, 131 BYTES TO $047F
+
+; Layout of the cassette buffer after a cassette block is read:
+
+; Baud correction ($55 $55) bytes are located at offsets 0 and 1
+; Control byte is at offset 2 ($03FF):
+; Actual data (128 bytes) runs from offset 3 ($0400) to $047F.
+; Each cassette frame has a 1 byte checksum after the 128 data bytes, but
+; the checksum is NOT stored anywhere in the cassette buffer!
+
+; CONTROL BYTE VALUES
+; Value Meaning
+; 250 ($FA) Partial record follows. The actual number of bytes is stored
+; in the last byte of the record (CASBUF+130, or $047F).
+; 252 ($FC) Record full; 128 bytes follow.
+; 254 ($FE) End of File (EOF) record; followed by 128 zero bytes.
+
+; Boot tapes normally don't have partial or EOF records, but BASIC
+; CLOAD/LOAD/LIST and data file tapes do.
+
+; Mapping the Atari says the first disk boot sector is read into CASBUF also.
+
+;
+;
+; PAGE 4
+;
+;
+USAREA = $0480 ; 1152 128 SPARE BYTES (but used by BASIC)
+;
+; SEE APPENDIX C FOR PAGES 4 AND 5 USAGE
+
+;
+;
+;
+;
+; PAGE 5
+;
+PAGE5 = $0500 ; 1280 127 FREE BYTES
+; $057E 1406 129 FREE BYTES IF FLOATING POINT ROUTINES NOT USED
+;
+;FLOATING POINT NON-ZERO PAGE RAM, NEEDED ONLY IF FP IS USED
+; (20070529 bkw: BASIC constantly uses FP! Also, it uses some of these
+; addresses for its own purposes.)
+;
+LBPR1 = $057E ; 1406 LBUFF PREFIX 1
+LBPR2 = $05FE ; 1534 LBUFF PREFIX 2
+LBUFF = $0580 ; 1408 LINE BUFFER
+PLYARG = $05E0 ; 1504 POLYNOMIAL ARGUMENTS
+FPSCR = $05E6 ; 1510 PLYARG+FPREC
+FPSCR1 = $05EC ; 1516 FPSCR+FPREC
+FSCR = $05E6 ; 1510 =FPSCR
+FSCR1 = $05EC ; 1516 =FPSCR1
+LBFEND = $05FF ; 1535 END OF LBUFF
+
+;
+; PAGE 6
+;
+;
+PAGE6 = $0600 ; 1536 256 FREE BYTES
+
+;
+;
+; PAGE 7
+;
+;
+BOOTRG = $0700 ; 1792 PROGRAM AREA
+; Boot disks (including DOS) are generally loaded here. Also, BASIC RAM
+; (variables and program) starts here, if BASIC is booted without DOS.
+
+; Page 80 (XL): Self-test (aka diagnostic) ROM is mapped at $5000,
+; if enabled with bit 7 of PORTB. Normally only happens if you boot without
+; BASIC, cartridge, tape, or disk... or if the OS detects a memory error
+; during boot.
+
+;
+;
+; UPPER ADDRESSES
+;
+;
+RITCAR = $8000 ;32768 RAM IF NO CARTRIDGE (extends to $9FFF)
+LFTCAR = $A000 ;40960 RAM IF NO CARTRIDGE (extends to $BFFF)
+
+; These 2 are from the Atari System Reference Manual, chapter 12:
+CARTA = LFTCAR
+CARTB = RITCAR
+
+CARTLOC = $BFFA ;49146 cartridge run address (from SYSEQU.ASM)
+
+; Carts were originally 8K only when the 400/800 were first released.
+; There were plans to release 16K programs on two cartridges, but this
+; never happened (the price of 16K ROMs came down, I guess). 16K cartridges
+; go in the left slot, but they actually use the address space for both
+; the right and left slots.
+
+; Mapping the Atari has this to say about cartridges:
+;; Byte Purpose
+;; Left (A) Right(B)
+;; 49146 ($BFFA) 40954 ($9FFA) Cartridge start address (low byte)
+;;
+;; 49147 ($BFFB) 40955 ($9FFB) Cartridge start address (high byte)
+;;
+;; 49148 ($BFFC) 40956 ($9FFC) Reads zero if a cartridge is
+;; inserted, non-zero when no cartridge is present. This information
+;; is passed down to the page zero RAM: if the A cartridge is plugged
+;; in, then location 6 will read one; if the B cartridge is plugged in,
+;; then location 7 will read one; otherwise they will read zero.
+;;
+;; 49149 ($BFFD) 40957 ($9FFD) Option byte. If BIT 0 equals one,
+;; then boot the disk (else there is no disk boot). If BIT 2 equals one,
+;; then initialize and start the cartridge (else initialize but do not
+;; start). If BIT 7 equals one, then the cartridge is a diagnostic
+;; cartridge which will take control, but not initialize the OS (else
+;; non-diagnostic cartridge). Diagnostic cartridges were used by
+;; Atari in the development of the system and are not available to the
+;; public.
+;;
+;; 49150 ($BFFE) 40958 ($9FFE) Cartridge initialization address
+;; low byte.
+;;
+;; 49151 ($BFFF) 40959 ($9FFF) Cartridge initialization address
+;; high byte. This is the address to which the OS will jump during all
+;; powerup and RESETs.
+;;
+;; The OS makes temporary use of locations 36876 to 36896 ($900C to
+;; $9020) to set up vectors for the interrupt handler. See the OS
+;; listings pages 31 and 81. This code was only used in the
+;; development system used to design the Atari.
+
+
+; Page 192
+
+C0PAGE = $C000 ;49152 (800) EMPTY, 4K BYTES
+ ; 20070529 bkw: unmapped address space.
+ ; Mapping the Atari erroneously lists this as "unused ROM".
+ ; There are upgrades to the 800 to give 4K of RAM here
+ ; (for a total of 52K of RAM), or ROM (Omnimon?).
+ ; Also, there is RAM here if you boot the Translator
+ ; disk on an XL.
+
+; (XL) $C000 also contains info about the ROM revision. From Mapping:
+
+;Bytes 49152-49163 ($C000-$C00B) are used to identify the computer
+;and the ROM in the $C000-$DFFF block:
+;
+;Byte Use
+;49152-3/C000-1 Checksum (LSB/MSB) of all the bytes
+; in ROM except the checksum bytes
+; themselves.
+;49154/C002 Revision date, stored in the form
+; DDMMYY. This is DD, day, usually $10.
+;49155/C003 Revision date, month; usually $05.
+;49156/C004 Revision date, year; usually $83.
+;49157/C005 Reserved option byte; reads zero for
+; the 1200, 800XL, and 130XE.
+;49158/C006 Part number in the form AANNNNNN;
+; AA is an ASCII character and
+; NNNNNN is a four-bit BCD digit. This is
+; byte A1.
+;49159-62/C007-A Part number, bytes A2, N1-N6 (each
+; byte has two N values of four bits
+; each).
+;49163/C00B Revision number. Mapping author's 800XL and 130XE say 2.
+
+;C0PAGE = $C000 ;49152 (XL) OS ROM, mostly interrupt handlers
+; $C800 51200 (XL) START OF OS ROM
+CHORG2 = $CC00 ;52224 (XL) INTERNATIONAL CHARACTER SET
+
+
+
+;
+;
+; HARDWARE REGISTERS
+;
+;
+; SEE REGISTER LIST FOR MORE INFORMATION
+;
+;
+
+; GTIA
+GTIA = $D000
+HPOSP0 = $D000 ;53248 (W) ; P/M positions (no shadows)
+HPOSP1 = $D001 ;53249 (W)
+HPOSP2 = $D002 ;53250 (W)
+HPOSP3 = $D003 ;53251 (W)
+HPOSM0 = $D004 ;53252 (W)
+HPOSM1 = $D005 ;53253 (W)
+HPOSM2 = $D006 ;53254 (W)
+HPOSM3 = $D007 ;53255 (W)
+SIZEP0 = $D008 ;53256 (W) ; P/M size regs (no shadows)
+SIZEP1 = $D009 ;53257 (W)
+SIZEP2 = $D00A ;53258 (W)
+SIZEP3 = $D00B ;53259 (W)
+SIZEM = $D00C ;53260 (W)
+M0PF = $D000 ;53248 (R) ; collision regs (no shadows)
+M1PF = $D001 ;53249 (R)
+M2PF = $D002 ;53250 (R)
+M3PF = $D003 ;53251 (R)
+P0PF = $D004 ;53252 (R)
+P1PF = $D005 ;53253 (R)
+P2PF = $D006 ;53254 (R)
+P3PF = $D007 ;53255 (R)
+M0PL = $D008 ;53256 (R)
+M1PL = $D009 ;53257 (R)
+M2PL = $D00A ;53258 (R)
+M3PL = $D00B ;53259 (R)
+P0PL = $D00C ;53260 (R)
+P1PL = $D00D ;53261 (R)
+P2PL = $D00E ;53262 (R)
+P3PL = $D00F ;53263 (R)
+GRAFP0 = $D00D ;53261 (W) ; direct (non-DMA) P/M graphics regs (no shadows)
+GRAFP1 = $D00E ;53262 (W)
+GRAFP2 = $D00F ;53263 (W)
+GRAFP3 = $D010 ;53264 (W)
+GRAFM = $D011 ;53265 (W)
+TRIG0 = $D010 ;53264 (R) ; Joystick triggers (shadows @ STRIG0-3)
+TRIG1 = $D011 ;53265 (R)
+TRIG2 = $D012 ;53266 (R)
+TRIG3 = $D013 ;53267 (R)
+PAL = $D014 ;53268 (R) ; PAL/NTSC detect (no shadow)
+ ; PAL supposedly moved to XL_PALNTS on XL; what was it
+ ; replaced with?
+COLPM0 = $D012 ;53266 (W) ; P/M colors (shadows @ PCOLR0-3)
+COLPM1 = $D013 ;53267 (W)
+COLPM2 = $D014 ;53268 (W)
+COLPM3 = $D015 ;53269 (W)
+COLPF0 = $D016 ;53270 (W) ; Playfield colors (shadows @ COLOR0-3)
+COLPF1 = $D017 ;53271 (W)
+COLPF2 = $D018 ;53272 (W)
+COLPF3 = $D019 ;53273 (W)
+COLBK = $D01A ;53274 (W) ; Background color (shadow @ COLOR4)
+PRIOR = $D01B ;53275 (W) ; GTIA priority (shadow @ GPRIOR)
+GTIAR = $D01B ;53275 (R?)
+VDELAY = $D01C ;53276 (W)
+GRACTL = $D01D ;53277 (W)
+HITCLR = $D01E ;53278 (W), latch
+CONSOL = $D01F ;53279 (W=keyclick spkr, R=console keys)
+
+; $D020 - $D0FF are mirrors of GTIA address space
+; $D100 - $D1FF are supposed to be unused (unmapped) on the 800
+; On the XL, $D100 - $D1FF is switched to device memory during PBI I/O
+
+; POKEY
+POKEY = $D200
+; no shadows for AUDC/AUDF
+AUDF1 = $D200 ;53760 (W) ; Audio frequency 1
+AUDC1 = $D201 ;53761 (W) ; Audio control 1 (distortion/volume)
+AUDF2 = $D202 ;53762 (W)
+AUDC2 = $D203 ;53763 (W)
+AUDF3 = $D204 ;53764 (W)
+AUDC3 = $D205 ;53765 (W)
+AUDF4 = $D206 ;53766 (W)
+AUDC4 = $D207 ;53767 (W)
+
+; POT0-7 shadows at PADDL0-7
+POT0 = $D200 ;53760 (R) ; Paddle positions
+POT1 = $D201 ;53761 (R)
+POT2 = $D202 ;53762 (R)
+POT3 = $D203 ;53763 (R)
+POT4 = $D204 ;53764 (R) ; pots 3-7 don't exist on XL/XE
+POT5 = $D205 ;53765 (R)
+POT6 = $D206 ;53766 (R)
+POT7 = $D207 ;53767 (R)
+
+AUDCTL = $D208 ;53768 (W) ; Audio control (no shadow)
+ALLPOT = $D208 ;53768 (R) (no shadow)
+STIMER = $D209 ;53769 (W) (no shadow)
+KBCODE = $D209 ;53769 (R) (shadow @ CH)
+SKREST = $D20A ;53770 (W) (latch)
+RANDOM = $D20A ;53770 (R) (no shadow)
+POTGO = $D20B ;53771 (W) (latch)
+; $D20C (53772) is unused
+SEROUT = $D20D ;53773 (W) (no shadow)
+SERIN = $D20D ;53773 (R) (no shadow)
+IRQEN = $D20E ;53774 (W) (shadow @ POKMSK)
+IRQST = $D20E ;53774 (R)
+SKCTL = $D20F ;53775 (W) (shadow @ SSKCTL)
+SKSTAT = $D20F ;53775 (R)
+
+; $D210 - $D2FF are mirrors of POKEY address space. The "stereo POKEY"
+; modification adds a second POKEY chip, usually addressed at $D210.
+
+; PIA
+; No shadow regs for PIA regs
+PIA = $D300
+PORTA = $D300 ;54016
+PORTB = $D301 ;54017
+PACTL = $D302 ;54018
+PBCTL = $D303 ;54019
+
+; $D304 - $D3FF are mirrors of PIA address space
+
+; ANTIC
+ANTIC = $D400
+DMACTL = $D400 ;54272 (W) (shadow @ SDMCTL)
+CHACTL = $D401 ;54273 (W) (shadow @ CHACT)
+DLISTL = $D402 ;54274 (W) (shadow @ SDLSTL)
+DLISTH = $D403 ;54275 (W) (shadow @ SDLSTH)
+HSCROL = $D404 ;54276 (W) (no shadow)
+VSCROL = $D405 ;54277 (W) (no shadow)
+; $D406 (54278) is unused
+PMBASE = $D407 ;54279 (W) (no shadow)
+; $D408 (54280) is unused
+CHBASE = $D409 ;54281 (W) (shadow @ CHBAS)
+WSYNC = $D40A ;54282 (W), latch (data written doesn't matter)
+VCOUNT = $D40B ;54283 (R) (no shadow)
+PENH = $D40C ;54284 (R) (shadow @ LPENH)
+PENV = $D40D ;54285 (R) (shadow @ LPENV)
+NMIEN = $D40E ;54286 (W) (no shadow)
+NMIRES = $D40F ;54287 (W), latch?
+NMIST = $D40F ;54287 (R) (no shadow)
+
+; $D410 - $D4FF are mirrors of ANTIC address space
+
+CCNTL = $D500 ;54528 Cartridge control (sometimes used for bankswitching)
+; $D500 - $D5FF is supposed to be all be mapped to CCNTL
+
+; $D600 - $D7FF is unmapped? used by PBI on XL? seems to read all $FF
+
+;
+; FLOATING POINT MATH ROUTINES
+;
+; From Mapping:
+; These entry points are the same on 400/800 and XL OS, though the
+; routines themselves are different (bugfixed/optimized for XL)
+; Also, on the XL, the $D800 area is bankswitched to PBI device ROM,
+; during PBI I/O. Not sure if all of $D800 - $DFFF is switched out
+; or just part of it.
+AFP = $D800 ;55296 ASCII to Floating Point (FP) conversion.
+FASC = $D8E6 ;55526 FP value to ASCII conversion.
+IFP = $D9AA ;55722 Integer to FP conversion
+FPI = $D9D2 ;55762 FP to Integer conversion
+ZFR0 = $DA44 ;55876 Clear FR0 (set all bytes to 0)
+ZF1 = $DA46 ;55878 Clear FR1 (set all bytes to 0) (aka AF1 (De Re))
+FSUB = $DA60 ;55904 FP subtract: FR0 = FR0 - FR1
+FADD = $DA66 ;55910 FP add: FR0 = FR0 + FR1
+FMUL = $DADB ;56027 FP multiply: FR0 = FR0 * FR1
+FDIV = $DB28 ;56104 FP divide: FR0 = FR0 / FR1
+PLYEVL = $DD40 ;56640 FP polynomial evaluation
+FLD0R = $DD89 ;56713 Load FP number into FR0 from 6502 X/Y registers
+FLD0P = $DD8D ;56717 Load FP number into FR0 from FLPTR
+FLD1R = $DD98 ;56728 Load FP number into FR1 from 6502 X/Y registers
+FLD1P = $DD9C ;56732 Load FP number into FR1 from FLPTR
+FST0R = $DDA7 ;56743 Store FP number into 6502 X/Y regs from FR0
+FST0P = $DDAB ;56747 Store FP number from FR0, using FLPTR
+FMOVE = $DDB6 ;56758 Move FP number from FR0 into FR1 (FR1 = FR0)
+EXP = $DDC0 ;56768 FP base e exponentiation
+EXP10 = $DDCC ;56780 FP base 10 exponentiation
+LOG = $DECD ;57037 FP natural logarithm
+LOG10 = $DED1 ;57041 FP base 10 logarithm
+
+;
+;
+; OPERATING SYSTEM
+;
+;
+; MODULE ORIGIN TABLE
+;
+CHORG = $E000 ;57344 CHARACTER SET, 1K
+VECTBL = $E400 ;58368 VECTOR TABLE
+VCTABL = $E480 ;58496 RAM VECTOR INITIAL VALUE TABLE
+CIOORG = $E4A6 ;58534 CIO HANDLER
+INTORG = $E6D5 ;59093 INTERRUPT HANDLER
+SIOORG = $E944 ;59716 SIO DRIVER
+DSKORT = $EDEA ;60906 DISK HANDLER
+PRNORG = $EE78 ;61048 PRINTER HANDLER
+CASORG = $EE78 ;61048 CASSETTE HANDLER
+MONORG = $F0E3 ;61667 MONITOR/POWER UP MODULE
+KBDORG = $F3E4 ;62436 KEYBOARD/DISPLAY HANDLER
+;
+;
+; VECTOR TABLE, CONTAINS ADDRESSES OF CIO ROUTINES IN THE
+; FOLLOWING ORDER. THE ADDRESSES IN THE TABLE ARE TRUE ADDRESSES-1
+;
+; ADDRESS + 0 OPEN
+; + 2 CLOSE
+; + 4 GET
+; + 6 PUT
+; + 8 STATUS
+; + A SPECIAL
+; + C JMP TO INITIALIZATION
+; + F NOT USED
+;
+;
+
+; 20070529 bkw: why are they address minus one? because they are called
+; via RTS: a JSR actually pushes the return address minus one, and RTS
+; increments the address on the stack after popping it. The Atari OS
+; "pretends" to have done a JSR by pushing the address-1 on the stack,
+; then executes RTS, which "returns" to the correct address.
+
+EDITRV = $E400 ;58368 EDITOR
+SCRENV = $E410 ;58384 SCREEN
+KEYBDV = $E420 ;58400 KEYBOARD
+PRINTV = $E430 ;58416 PRINTER
+CASETV = $E440 ;58432 CASSETTE
+;
+; ROM VECTORS
+;
+; 20070529 bkw: These consist of a JMP xxxx instruction in the ROM.
+DSKINV = $E453 ;58451
+CIOV = $E456 ;58454 ; Main CIO entry point!
+SIOV = $E459 ;58457 ; Main SIO entry point!
+SETVBV = $E45C ;58460
+SYSVBV = $E45F ;58463
+VBIVAL = $E460 ;58464 ADR AT VVBLKI (operand of JMP @ $E45F)
+XITVBV = $E462 ;58466 EXIT VBI
+VBIXVL = $E463 ;58467 ADR AT VVBLKD (operand of JMP @ $E462)
+SIOINV = $E465 ;58469
+SENDEV = $E468 ;58472
+INTINV = $E46B ;58475
+CIOINV = $E46E ;58478
+BLKBDV = $E471 ;58481 MEMO PAD MODE (self-test in XL)
+WARMSV = $E474 ;58484 ; warmstart (RESET key jumps here)
+COLDSV = $E477 ;58487 ; coldstart (reboot) the Atari
+RBLOKV = $E47A ;58490
+CSOPIV = $E47D ;58493
+
+; SYSEQU.ASM defines this:
+CIO = CIOV
+
+; XL-only entry points:
+XL_SELFSV = BLKBDV ; self-test (same entry point as 800 memo pad)
+XL_SELFTST = BLKBDV ; alt. name (Mapping)
+XL_PUPDIV = $E480 ;58496 (XL) Power-up ATARI logo (1200XL only), or self-test
+XL_SLFTSV = $E483 ;58499 (XL) Self-test vector (points to $5000)
+XL_PENTV = $E486 ;58502 (XL) Entry to the handler uploaded from peripheral
+ ; or disk (is this for the PBI?)
+XL_PHUNLV = $E489 ;58505 (XL) Entry to uploaded handler unlink (PBI?)
+XL_PHINIV = $E48C ;58508 (XL) Entry to uploaded handler init (PBI?)
+XL_GPDVV = $E48F ;58511 (XL) General-purpose parallel device handler
+ ; (copy to HATABS to use)
+
+;;;;; Here endeth the list of official mnemonics
+
+; Mapping has this to say about the XL ROMs:
+;Byte Use
+;65518/FFEE Revision date D1 and D2 (four-bit BCD)
+;65519/FFEF Revision date M1 and M2
+;65520/FFF0 Revision date Y1 and Y2
+;65521/FFF1 Option byte; should read 1 for the
+; 1200XL (Mapping author's 800XL reads 2)
+;65522-26/FFF2-6 Part number in the form AANNNNNN
+;65527/FFF7 Revision number (again, mine reads 2)
+;65528-9/FFF8-9 Checksum, bytes (LSB/MSB)
+; There don't seem to be any known mnemonics for the above...
+
+; 20061120 bkw: display list stuff. These are not official Atari mnemonics,
+; but they *are* somewhat based on the "Checkers Demo" by Carol Shaw,
+; in the Atari Hardware Manual (she didn't define all these, and she didn't
+; use the "DL_" prefix, probably because her assembler was limited to
+; 6-character labels and/or didn't support the underscore).
+
+; blank lines, 1-8 scanlines high
+DL_BLANK1 = $00
+DL_BLANK2 = $10
+DL_BLANK3 = $20
+DL_BLANK4 = $30
+DL_BLANK5 = $40
+DL_BLANK6 = $50
+DL_BLANK7 = $60
+DL_BLANK8 = $70
+
+; modifier bits..
+DL_VSCROLL = $10
+DL_HSCROLL = $20
+DL_LMS = $40
+DL_DLI = $80
+
+; graphics modes (these are the BASIC modes)
+; If you're more familiar with the ANTIC modes, nobody's forcing you
+; to use these :)
+DL_GR0 = $02
+DL_GR1 = $06
+DL_GR2 = $07
+DL_GR3 = $08
+DL_GR4 = $09
+DL_GR5 = $0A
+DL_GR6 = $0B
+DL_GR7 = $0D
+DL_GR8 = $0F
+DL_GR12 = $04 ; GR. 12-15 only supported by GRAPHICS command on XL/XE,
+DL_GR13 = $05 ; but they exist on all ANTIC revisions
+DL_GR14 = $0C
+DL_GR15 = $0E ; AKA "graphics 7.5"
+; No GRAPHICS mode for ANTIC $03 (true descender) mode
+
+; jump instructions
+DL_JMP = $01 ; jump without vertical blank (used to skip over 1K boundary)
+DL_JVB = $41 ; jump & wait for VBLANK (end of display list)
+
+; How to use the above: here's a sample display list for GR.0, with a DLI
+; on screen line 10.
+
+; dlist:
+; ; 4*8 = 32 blank lines at start of display
+; byte DL_BLANK8, DL_BLANK8, DL_BLANK8, DL_BLANK8
+;
+; byte DL_GR0 | DL_LMS ; display GR.0 line, and load screen memory address..
+; word screen_ram ; ...from our screen memory (declared elsewhere)
+;
+; ; 8 more GR.0 lines
+; byte DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0
+;
+; byte DL_GR0 | DL_DLI ; another GR.0 line, with the DLI bit enabled
+;
+; ; lines 11-24 (14 more GR.0 bytes)
+; byte DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0
+; byte DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0
+;
+; ; that's 24 lines, so finish with a VBLANK
+; byte DL_JVB ; jump (and wait), to...
+; word dlist ; ...the beginning.
diff --git a/src/col64/font4x5.inc b/src/col64/font4x5.inc
new file mode 100644
index 0000000..739e85e
--- /dev/null
+++ b/src/col64/font4x5.inc
@@ -0,0 +1,48 @@
+ byte $04, $04, $04, $00, $04 ; [0] 32,33 ,!
+ byte $AA, $AF, $0A, $0F, $0A ; [5] 34,35 ",#
+ byte $70, $A9, $62, $54, $E9 ; [10] 36,37 $,%
+ byte $42, $A2, $44, $A0, $D0 ; [15] 38,39 &,'
+ byte $24, $42, $42, $42, $24 ; [20] 40,41 (,)
+ byte $A4, $44, $EE, $44, $A4 ; [25] 42,43 *,+
+ byte $00, $00, $0F, $20, $40 ; [30] 44,45 ,,-
+ byte $02, $02, $04, $08, $48 ; [35] 46,47 .,/
+ byte $64, $9C, $B4, $D4, $6E ; [40] 48,49 0,1
+ byte $6E, $91, $26, $41, $FE ; [45] 50,51 2,3
+ byte $2F, $68, $AE, $F1, $2E ; [50] 52,53 4,5
+ byte $7F, $81, $E2, $94, $64 ; [55] 54,55 6,7
+ byte $66, $99, $67, $91, $6E ; [60] 56,57 8,9
+ byte $00, $42, $00, $02, $44 ; [65] 58,59 :,;
+ byte $20, $4F, $80, $4F, $20 ; [70] 60,61 <,=
+ byte $87, $49, $22, $40, $82 ; [75] 62,63 >,?
+ byte $66, $B9, $BF, $89, $69 ; [80] 64,65 @,A
+ byte $E6, $99, $E8, $99, $E6 ; [85] 66,67 B,C
+ byte $EF, $98, $9E, $98, $EF ; [90] 68,69 D,E
+ byte $F7, $88, $EB, $89, $86 ; [95] 70,71 F,G
+ byte $9E, $94, $F4, $94, $9E ; [100] 72,73 H,I
+ byte $39, $1A, $1C, $9A, $69 ; [105] 74,75 J,K
+ byte $8A, $8F, $8D, $89, $F9 ; [110] 76,77 L,M
+ byte $96, $D9, $B9, $99, $96 ; [115] 78,79 N,O
+ byte $E6, $99, $E9, $8A, $85 ; [120] 80,81 P,Q
+ byte $E7, $98, $E6, $A1, $9E ; [125] 82,83 R,S
+ byte $F9, $49, $49, $49, $46 ; [130] 84,85 T,U
+ byte $99, $99, $9D, $AF, $4A ; [135] 86,87 V,W
+ byte $99, $99, $66, $92, $94 ; [140] 88,89 X,Y
+ byte $F6, $24, $44, $84, $F6 ; [145] 90,91 Z,[
+ byte $86, $82, $42, $22, $26 ; [150] 92,93 \,]
+ byte $40, $A0, $00, $00, $0F ; [155] 94,95 ^,_
+ byte $40, $43, $25, $09, $07 ; [160] 96,97 `,a
+ byte $80, $87, $E8, $98, $E7 ; [165] 98,99 b,c
+ byte $10, $16, $79, $9A, $77 ; [170] 100,101 d,e
+ byte $67, $49, $E7, $41, $46 ; [175] 102,103 f,g
+ byte $84, $80, $EC, $94, $9E ; [180] 104,105 h,i
+ byte $28, $0A, $6C, $2A, $C9 ; [185] 106,107 j,k
+ byte $C0, $4A, $4F, $4D, $E9 ; [190] 108,109 l,m
+ byte $00, $E6, $99, $99, $96 ; [195] 110,111 n,o
+ byte $00, $E7, $99, $E7, $81 ; [200] 112,113 p,q
+ byte $00, $A7, $DC, $83, $8E ; [205] 114,115 r,s
+ byte $40, $E9, $49, $49, $26 ; [210] 116,117 t,u
+ byte $00, $99, $9D, $AF, $4A ; [215] 118,119 v,w
+ byte $00, $99, $66, $62, $9C ; [220] 120,121 x,y
+ byte $06, $F4, $28, $44, $F6 ; [225] 122,123 z,{
+ byte $4C, $44, $42, $44, $4C ; [230] 124,125 |,}
+ byte $0B, $59, $A0, $09, $0D ; [235] 126,127 ~,
diff --git a/src/col64/test.atr b/src/col64/test.atr
new file mode 100644
index 0000000..5e5cd5a
--- /dev/null
+++ b/src/col64/test.atr
Binary files differ
diff --git a/src/col80_modified/Makefile b/src/col80_modified/Makefile
new file mode 100644
index 0000000..4f3a9c6
--- /dev/null
+++ b/src/col80_modified/Makefile
@@ -0,0 +1,15 @@
+
+all: col80_hacked.xex
+
+col80_hacked.xex: col80_hacked.dasm
+ dasm col80_hacked.dasm -ocol80_hacked.xex -f3
+ binload -h col80_hacked.xex
+
+clean:
+ rm -f col80_hacked.xex
+
+test:
+ cp dos_20s.atr test.atr
+ cp col80_hacked.xex autorun.sys
+ axe -w autorun.sys test.atr
+ atari800 -nobasic test.atr
diff --git a/src/col80_modified/autorun.sys b/src/col80_modified/autorun.sys
new file mode 100644
index 0000000..bb432dd
--- /dev/null
+++ b/src/col80_modified/autorun.sys
Binary files differ
diff --git a/src/col80_modified/col80_hacked.dasm b/src/col80_modified/col80_hacked.dasm
new file mode 100644
index 0000000..ef6c5ac
--- /dev/null
+++ b/src/col80_modified/col80_hacked.dasm
@@ -0,0 +1,906 @@
+; THIS IS A MODIFIED VERSION, for use with FujiChat
+
+; COL80.COM, aka COL80E.COM, aka COL80HND.COM
+; (and probably several other names)
+
+; Original author unknown
+; License unknown
+; Disassembly and comments by Urchlay
+
+; This is a widely-distributed software 80-column driver for the Atari
+; 8-bit computers. It replaces the OS's E: driver, and uses GRAPHICS 8
+; for display, with 4x8 pixel character cells.
+
+; Disassembly was done with da65, with many iterations of "edit the
+; .info file, disassemble again", and the results were tweaked by hand
+; into something assemblable by dasm (and fairly compatible with other
+; assemblers).
+
+
+ .processor 6502
+
+START_ADDRESS = $9C2D
+;START_ADDRESS = $7C28 ; works with BASIC
+
+; xex segment header #1
+ .org START_ADDRESS-6
+ .word $FFFF
+ .word START_ADDRESS
+ .word END_ADDRESS
+
+ .org START_ADDRESS
+
+; ----------------------------------------------------------------------------
+; Zero page labels (OS equates)
+
+DOSINI = $000C
+ICAX1Z = $002A
+ICAX2Z = $002B
+TMPCHR = $0050
+LMARGN = $0052
+ROWCRS = $0054
+COLCRS = $0055
+DINDEX = $0057
+SAVMSC = $0058
+BUFCNT = $006B
+
+; ----------------------------------------------------------------------------
+; Zero page labels (COL80 equates)
+
+screen_ptr_lo = $00CB
+screen_ptr_hi = $00CC
+font_ptr_lo = $00CD
+font_ptr_hi = $00CE
+
+; ----------------------------------------------------------------------------
+; Non-zeropage RAM labels (OS equates)
+
+COLOR1 = $02C5
+COLOR2 = $02C6
+RUNAD = $02E0
+INITAD = $02E2
+MEMTOP = $02E5
+SSFLAG = $02FF
+HATABS = $031A
+ICCOM = $0342
+ICBAL = $0344
+ICBAH = $0345
+
+; ----------------------------------------------------------------------------
+; Hardware (memory-mapped I/O, OS equates)
+
+CONSOL = $D01F
+AUDF1 = $D200
+AUDC1 = $D201
+
+; ----------------------------------------------------------------------------
+; OS ROM labels
+
+s_dev_open_lo = $E410 ; (not named in OS sources)
+s_dev_open_hi = $E411 ; ""
+k_dev_get_lo = $E424 ; ""
+k_dev_get_hi = $E425 ; ""
+CIOV = $E456 ; Central Input/Output entry point
+
+; ----------------------------------------------------------------------------
+; Start of COL80. The font is stored in packed form. Each group of 8 bytes
+; defines two glyphs: the upper 4 bits of the 8 bytes, taken together,
+; define the bitmap for the first glyph, and the lower 4 bits are the second.
+; Note that the bits that make up a single character are spread across 8
+; bytes, so it's hard to visualize these even if you're used to reading hex
+; dumps.
+
+; The first 2 characters look like:
+
+; .... .O.. ; $04
+; .... .O.. ; $04
+; O.O. .O.. ; $A4
+; OOO. .O.. ; $E4
+; OOO. .OOO ; $E7
+; .O.. .O.. ; $44
+; .... .O.. ; $04
+; .... .O.. ; $04
+
+; These are the ATASCII heart symbol (character code 0) and the ATASCII
+; control-A line-drawing symbol (code 1).
+
+; Note: unlike the ROM font, this font is stored in ATASCII order instead
+; of the standard Atari character order imposed by the hardware. Like
+; the ROM font, inverse characters are not stored here (the bitmaps get
+; inverted by the driver)
+
+font_data:
+ .include "new_font.s"
+ ;.include "icetmod.s"
+
+right_margin:
+ ; Default value is 79 decimal. Unsure why the author didn't use RMARGN at $53
+ .byte $4F
+
+; ----------------------------------------------------------------------------
+; Start of COL80 code.
+
+; Callback for CIO OPEN command.
+
+col80_open:
+ jsr init_graphics_8
+ lda #$00
+ sta ROWCRS
+ sta COLCRS
+ sta BUFCNT
+ lda #$4F
+ sta right_margin
+ rts
+
+; ----------------------------------------------------------------------------
+; Assembly version of GRAPHICS 8+16 command.
+
+init_graphics_8:
+ lda #$08
+ sta ICAX2Z
+ lda #$0C
+ sta ICAX1Z
+ jsr open_s_dev
+
+ ; Set COL80's default colors
+ lda #$08
+ sta COLOR2
+ lda #$00
+ sta COLOR1
+
+ ; Protect ourselves from BASIC and the OS
+ lda #<START_ADDRESS
+ sta MEMTOP
+ lda #>START_ADDRESS
+ sta MEMTOP+1
+ rts
+
+; ----------------------------------------------------------------------------
+; Call the OPEN vector for the S: device, using the ROM vector table
+; at $E410. The table stores address-minus-one of each routine, which is
+; meant to actually be called via the RTS instruction (standard 6502
+; technique, but confusing the first time you encounter it)
+
+open_s_dev:
+ lda s_dev_open_hi
+ pha
+ lda s_dev_open_lo
+ pha
+ rts
+
+; ----------------------------------------------------------------------------
+; Callback for CIO CLOSE command. Note that the routine does nothing, really
+; (the OS will mark the E: device as being closed, but COL80 doesn't do any
+; cleanup).
+; The SPECIAL and GET STATUS callbacks in col80_vector_tab also point here.
+
+col80_close:
+ jmp return_success
+
+; ----------------------------------------------------------------------------
+; Callback for the internal put-one-byte, used by the OS to implement the
+; CIO PUT RECORD and PUT BYTES commands. This routine's one argument is
+; the byte in the accumulator (the character to print).
+
+; First, the routine checks for the cursor control characters it supports.
+; COL80 only handles the EOL and clear-screen codes; trying to print
+; backspaces, arrows, deletes, inserts, etc just causes their ATASCII
+; graphics character to print instead.
+
+col80_putbyte:
+ ; EOL (decimal 155)?
+ cmp #$9B
+;;; bne check_clear
+ bne regular_char
+ lda right_margin
+ sta COLCRS
+ jmp skip_write
+
+;;;check_clear:
+;;; .ifndef FUJICHAT ; save memory by not including clear_screen
+;;; ; (also, this lets us print the } character)
+;;; ; Clear (decimal 125)?
+;;; cmp #$7D
+;;; bne regular_char
+;;; jmp clear_screen
+;;; .endif
+;;;
+ ; See if this is an inverse video char (code >= 128)
+regular_char:
+ tax
+ bpl not_inverse
+ lda #$FF
+ sta inverse_mask
+ bne skip_ninv
+
+not_inverse:
+ lda #$00
+ sta inverse_mask
+
+skip_ninv:
+ txa
+ and #$7F
+ ;.ifdef FUJICHAT ; mask out low ASCII
+ sec
+ sbc #$20
+ bcs not_low_ascii
+ jmp return_success
+not_low_ascii:
+ ;.endif
+ sta TMPCHR
+ lda DINDEX
+ cmp #$08
+ beq graphics_ok
+ ; If we're not in GRAPHICS 8 mode, reinitialize ourselves
+ jsr col80_open
+
+graphics_ok:
+ ; Call the routines that actually print the character
+ jsr setup_font_ptr
+ jsr setup_screen_ptr
+ jsr write_font_data
+
+skip_write:
+ ; Move the cursor 1 space to the right. This will
+ ; advance us to the next line if we're at the margin,
+ ; and scroll the screen if needed
+ jsr advance_cursor
+
+check_ssflag:
+ ; The OS keyboard interrupt handler will toggle SSFLAG (start/stop fla
+ ; any time the user presses ctrl-1
+ ;lda SSFLAG
+ ;bne check_ssflag
+ jmp return_success
+
+; ----------------------------------------------------------------------------
+; Scroll the screen up one line (8 scanlines). This has to move almost 8K of
+; data, so it's noticeably slower than scrolling the GR.0 text screen.
+
+scroll_screen:
+ lda SAVMSC
+ sta screen_ptr_lo
+ clc
+ adc #$40
+ ; font_ptr_lo is actually being used here as a second pointer into
+ ; screen RAM, instead of its usual use as a pointer into the
+ ; font_data table
+ sta font_ptr_lo
+ lda SAVMSC+1
+ sta screen_ptr_hi
+ adc #$01
+ sta font_ptr_hi
+ ldx #$1D
+ ldy #$00
+
+scroll_line_loop:
+ lda (font_ptr_lo),y
+ sta (screen_ptr_lo),y
+ dey
+ bne scroll_line_loop
+ inc font_ptr_hi
+ inc screen_ptr_hi
+ dex
+ bne scroll_line_loop
+
+blank_bottom_row:
+ lda SAVMSC
+ clc
+ adc #$C0
+ sta screen_ptr_lo
+ lda SAVMSC+1
+ adc #$1C
+ sta screen_ptr_hi
+ lda #$00
+ tay
+
+blank_loop:
+ sta (screen_ptr_lo),y
+ dey
+ bne blank_loop
+ inc screen_ptr_hi
+ ldy #$40
+
+blank_tail:
+ sta (screen_ptr_lo),y
+ dey
+ bpl blank_tail
+ rts
+
+; ----------------------------------------------------------------------------
+; Set up font_ptr_lo/hi to point to the font_data bitmap for the character in
+; TMPCHR. Also sets lo_nybble_flag to let the caller know whether the
+; bitmap is in the upper or lower 4 bits of the bytes pointed to.
+
+setup_font_ptr:
+ lda #$00
+ sta font_ptr_hi
+ sta lo_nybble_flag
+ lda TMPCHR
+ clc
+ ror
+ bcc font_hi_nybble
+ ldx #$FF
+ stx lo_nybble_flag
+
+font_hi_nybble:
+ clc
+ rol
+ rol
+ rol font_ptr_hi
+ rol
+ rol font_ptr_hi
+ adc #<font_data
+ sta font_ptr_lo
+ lda #>font_data
+ adc font_ptr_hi
+ sta font_ptr_hi
+ rts
+
+; ----------------------------------------------------------------------------
+; Move the cursor one space to the right (to the next line if at the margin,
+; and scroll screen if on the last row)
+
+advance_cursor:
+ inc COLCRS
+ lda right_margin
+ cmp COLCRS
+ bcs same_line
+ lda LMARGN
+ sta COLCRS
+ lda ROWCRS
+ ; $17 is 25 decimal, one row below the lowest on the screen
+ cmp #$17
+ bcc no_scroll
+ jsr scroll_screen
+ ; Move to row 24 after scrolling
+ lda #$16
+ sta ROWCRS
+
+no_scroll:
+ inc ROWCRS
+
+same_line:
+ rts
+
+; ----------------------------------------------------------------------------
+; Clear the screen by setting all screen RAM bytes to zero. Slow, but not
+; as slow as scrolling.
+
+;;; .ifndef FUJICHAT
+;;;clear_screen:
+;;; lda SAVMSC
+;;; sta screen_ptr_lo
+;;; lda SAVMSC+1
+;;; sta screen_ptr_hi
+;;; ldy #$00
+;;; ldx #$1D
+;;; lda #$00
+;;;
+;;;cls_loop:
+;;; sta (screen_ptr_lo),y
+;;; dey
+;;; bne cls_loop
+;;; inc screen_ptr_hi
+;;; dex
+;;; bne cls_loop
+;;; jsr blank_bottom_row
+;;; lda LMARGN
+;;; sta COLCRS
+;;; lda #$00
+;;; sta ROWCRS
+;;; ; redundant JMP
+;;; jmp return_success
+;;; .endif
+
+; ----------------------------------------------------------------------------
+; CIO expects the Y register to contain a status code.
+; 1 means success (no error). Lots of COL80's routines
+; jump here.
+
+return_success:
+ ldy #$01
+ rts
+
+; ----------------------------------------------------------------------------
+; Set screen_ptr_lo/hi to point to the address of the first byte of graphics
+; data at the current cursor position.
+
+setup_screen_ptr:
+ ldy ROWCRS
+ lda SAVMSC
+ clc
+ adc row_low_offset_tab,y
+ sta screen_ptr_lo
+ lda SAVMSC+1
+ adc row_high_offset_tab,y
+ sta screen_ptr_hi
+ lda COLCRS
+ lsr
+ clc
+ adc screen_ptr_lo
+ bcc hi_byte_ok
+ inc screen_ptr_hi
+
+hi_byte_ok:
+ sta screen_ptr_lo
+ rts
+
+; ----------------------------------------------------------------------------
+; Tables of offsets for setup_screen_ptr, to avoid doing multiplication at
+; runtime (the 6502 lacks a MUL instruction, so it's slow...)
+
+row_low_offset_tab:
+ .byte $00,$40,$80,$C0,$00,$40,$80,$C0
+ .byte $00,$40,$80,$C0,$00,$40,$80,$C0
+ .byte $00,$40,$80,$C0,$00,$40,$80,$C0
+
+row_high_offset_tab:
+ .byte $00,$01,$02,$03,$05,$06,$07,$08
+ .byte $0A,$0B,$0C,$0D,$0F,$10,$11,$12
+ .byte $14,$15,$16,$17,$19,$1A,$1B,$1C
+
+; ----------------------------------------------------------------------------
+; Copy pixel data from the font table to screen RAM.
+; font_ptr_lo/hi must point to the correct character, and screen_ptr_lo/hi
+; must point to the correct screen address for the current cursor position.
+; This routine has separate execution paths for even- and odd-numbered
+; cursor positions, since each byte of screen RAM holds data for two
+; adjacent characters (and when printing to one of them, the other needs
+; to be left undisturbed!)
+
+write_font_data:
+ lda COLCRS
+ clc
+ ror
+ bcc write_font_data_even
+ ldx #$00
+ ldy #$00
+
+get_font_nybble_odd:
+ lda (font_ptr_lo),y
+ bit lo_nybble_flag
+ bne lo_nybble_odd
+ ; glyph we want is stored in top 4 bits of font byte,
+ ; shift it down to the bottom 4 bits
+ lsr
+ lsr
+ lsr
+ lsr
+
+lo_nybble_odd:
+ eor inverse_mask
+ and #$0F
+ sta TMPCHR
+ ldy scanline_offset_tab,x
+ lda (screen_ptr_lo),y
+ and #$F0
+ ora TMPCHR
+ sta (screen_ptr_lo),y
+ inx
+ cpx #$07
+ bne screen_ptr_ok_odd
+ inc screen_ptr_hi
+
+screen_ptr_ok_odd:
+ cpx #$08
+ beq write_font_done_odd
+ txa
+ tay
+ bne get_font_nybble_odd
+
+write_font_done_odd:
+ rts
+
+; ----------------------------------------------------------------------------
+; Write data to even-numbered columns, very similar to the above
+
+write_font_data_even:
+ ldx #$00
+ ldy #$00
+
+get_font_nybble_even:
+ lda (font_ptr_lo),y
+ bit lo_nybble_flag
+ beq hi_nybble_even
+ asl
+ asl
+ asl
+ asl
+
+hi_nybble_even:
+ eor inverse_mask
+ and #$F0
+ sta TMPCHR
+ ldy scanline_offset_tab,x
+ lda (screen_ptr_lo),y
+ and #$0F
+ ora TMPCHR
+ sta (screen_ptr_lo),y
+ inx
+ cpx #$07
+ bne screen_ptr_ok_even
+ inc screen_ptr_hi
+
+screen_ptr_ok_even:
+ cpx #$08
+ beq write_font_done_even
+ txa
+ tay
+ bne get_font_nybble_even
+
+write_font_done_even:
+ rts
+
+; ----------------------------------------------------------------------------
+
+scanline_offset_tab:
+ .byte $00,$28,$50,$78,$A0,$C8,$F0,$18
+
+; ----------------------------------------------------------------------------
+; Callback for the internal get-one-byte, used by the OS to implement the
+; CIO GET RECORD and GET BYTES commands. This routine takes no arguments,
+; and returns the read byte in the accumulator.
+
+; Internally, COL80 maintains a line buffer. Each time col80_getbyte is
+; called, it returns the next character in the buffer. If the buffer's
+; empty (or if the last call returned the last character), a new line
+; of input is read from the user (and the first character is returned).
+; This is exactly how the OS E: device works.
+
+col80_getbyte:
+ lda BUFCNT
+ beq get_line
+
+get_next_byte:
+ ldx line_buffer_index
+ lda line_buffer,x
+ dec BUFCNT
+ inc line_buffer_index
+ jmp return_success
+
+; ----------------------------------------------------------------------------
+; Get a line of input from the user, terminated by the Return key.
+
+get_line:
+ lda #$00
+ sta BUFCNT
+ sta line_buffer_index
+
+show_cursor:
+; .ifdef FUJICHAT
+ lda #$00
+; .else
+; lda #$20
+; .endif
+ sta TMPCHR
+ lda #$FF
+ sta inverse_mask
+ jsr setup_font_ptr
+ jsr setup_screen_ptr
+ jsr write_font_data
+ jsr get_keystroke
+ cpy #$01
+ beq keystroke_ok
+; .ifdef FUJICHAT
+ dey ; yes, we really care about 1-byte optimizations
+; .else
+; ldy #$00
+; .endif
+ sty line_buffer_index
+ sty BUFCNT
+
+keystroke_ok:
+; .ifdef FUJICHAT
+ cmp #$20
+ bcc show_cursor ; ignore low ASCII
+; .endif
+ cmp #$9B
+ bne check_backs_key
+ jmp return_key_hit
+
+check_backs_key:
+ cmp #$7E
+ bne check_clear_key
+ jmp backs_key_hit
+
+check_clear_key:
+ cmp #$7D
+ bne normal_key_hit
+ jmp clear_key_hit
+
+normal_key_hit:
+ ldx BUFCNT
+ bpl buffer_character
+; .ifdef FUJICHAT
+ jmp show_cursor
+; .else
+; jmp beep
+; .endif
+
+buffer_character:
+ sta line_buffer,x
+ jsr col80_putbyte
+ inc BUFCNT
+ jmp show_cursor
+
+return_key_hit:
+ jsr print_space
+ lda #$9B
+ ldx BUFCNT
+ sta line_buffer,x
+ inc BUFCNT
+ jsr col80_putbyte
+ jmp get_next_byte
+
+clear_key_hit:
+; .ifndef FUJICHAT
+; jsr clear_screen
+; .endif
+ lda #$00
+ sta line_buffer_index
+ sta BUFCNT
+ jmp get_line
+
+backs_key_hit:
+ jsr print_space
+ lda BUFCNT
+ beq backs_key_done
+ dec COLCRS
+ lda COLCRS
+ clc
+ adc #$01
+ cmp LMARGN
+ bne backs_same_line
+ lda right_margin
+ sta COLCRS
+ dec ROWCRS
+
+backs_same_line:
+ dec BUFCNT
+
+backs_key_done:
+ jmp show_cursor
+
+; ----------------------------------------------------------------------------
+; Ring the margin bell. COL80 doesn't implement the ctrl-2 bell (character
+; 253), and instead of using the GTIA keyclick speaker, it uses POKEY to
+; make a beep
+
+;;; .ifndef FUJICHAT
+;;;beep: ldy #$00
+;;; ldx #$AF
+;;;
+;;;beep_delay_x:
+;;; stx AUDF1
+;;; stx AUDC1
+;;;
+;;;beep_delay_y:
+;;; dey
+;;; bne beep_delay_y
+;;; dex
+;;; cpx #$9F
+;;; bne beep_delay_x
+;;; jmp show_cursor
+;;; .endif
+
+; ----------------------------------------------------------------------------
+; Print a space character at the current cursor position. Does not
+; update the cursor position.
+print_space:
+ lda #$00
+ sta inverse_mask
+;;; .ifndef FUJICHAT
+;;; lda #$20
+;;; .endif
+ sta TMPCHR
+ jsr setup_font_ptr
+ jsr setup_screen_ptr
+ jsr write_font_data
+ rts
+
+; ----------------------------------------------------------------------------
+; Get a keystroke (blocking). Just calls the OS K: get-one-byte routine
+; (call by pushing address-minus-one then doing an RTS)
+get_keystroke:
+ lda k_dev_get_hi
+ pha
+ lda k_dev_get_lo
+ pha
+ rts
+
+; ----------------------------------------------------------------------------
+; COL80 vector table, in the format required by the OS. Our HATABS entry
+; will point to this table, and the OS will call the routines listed here
+; via the "call by RTS" method (which is why they're address-minus-one).
+
+; See the entry on HATABS in "Mapping the Atari" or the OS manual.
+
+col80_vector_tab:
+ .word col80_open-1
+ .word col80_close-1
+ .word col80_getbyte-1
+ .word col80_putbyte-1
+ .word col80_close-1
+ .word col80_close-1
+ jmp col80_init
+
+END_ADDRESS = *-1
+
+START_ADDRESS_2 = $03FD
+
+; xex segment header #2
+ .word START_ADDRESS_2
+ .word END_ADDRESS_2
+
+ .rorg START_ADDRESS_2
+
+; ----------------------------------------------------------------------------
+; Various bits of runtime state here. It's unclear to me why the standard
+; OS buffer location couldn't have been used instead (normally the top
+; half of page 5), or why the other stuff couldn't have been stored in
+; zero page, in locations used by the ROM E: handler (thus unused when
+; it's replaced with COL80). line_buffer_index needs to be preserved
+; across calls to col80_getbyte, but lo_nybble_flag and inverse_mask are
+; freshly calculated every time they're used, so they could be almost
+; anywhere.
+
+lo_nybble_flag:
+ .byte $00
+
+inverse_mask:
+ .byte $00
+
+line_buffer_index:
+ .byte $12
+
+
+; ----------------------------------------------------------------------------
+; Initialization callback. The OS will call this on coldstart (or would do,
+; if the driver were in ROM), and also on warmstart (because we stole the
+; DOSINI vector).
+; This routine is also the first thing that gets called by the mainline
+; init code. Its job is to install COL80 in the handler table at HATABS.
+; Actually the handler is first installed as X:, then the main init code
+; fixes this up to E: unless the user is holding down SELECT. This allows
+; the user to toggle between the 40-column ROM E: and COL80 without doing
+; a full reboot. No idea if this was a documented feature or something the
+; author used for development/debugging.
+
+; .ifdef FUJICHAT
+;col80_init = return_success
+; .else
+col80_init:
+ ldy #$00
+
+next_hatab_slot:
+ lda HATABS,y
+ beq register_x_handler
+ iny
+ iny
+ iny
+ cpy #$20
+ bcc next_hatab_slot
+ jmp return_success
+
+register_x_handler:
+ lda #$58
+ sta HATABS,y
+ lda #<col80_vector_tab
+ iny
+ sta HATABS,y
+ lda #>col80_vector_tab
+ iny
+ sta HATABS,y
+ jmp return_success
+; .endif
+
+; ----------------------------------------------------------------------------
+; The OS jumps here on warmstart (also, this is the run address in our
+; binary load file)
+
+dosini_entry_point:
+;;; .ifndef FUJICHAT
+;;; nop
+;;; nop
+;;; nop
+;;; .endif
+
+main_entry_point:
+;;; .ifndef FUJICHAT
+ jsr col80_init
+;;; lda CONSOL
+;;; and #$04
+;;; beq no_e_handler
+;;; .endif
+ lda #$0C
+ sta ICCOM
+ ldx #$00
+ jsr CIOV
+; .ifndef FUJICHAT ; note: will not work with BASIC! DOS/etc OK
+ lda #$58
+ sta font_ptr_lo
+ lda #$03
+ sta ICCOM
+ lda #font_ptr_lo
+ sta ICBAL
+ lda #$00
+ sta ICBAH
+ ldx #$00
+ jsr CIOV
+; .endif
+ ldy #$07
+ lda #<col80_vector_tab
+ sta HATABS,y
+ lda #>col80_vector_tab
+ iny
+ sta HATABS,y
+no_e_handler:
+ lda #<START_ADDRESS
+ sta MEMTOP
+ lda #>START_ADDRESS
+ sta MEMTOP+1
+ jmp return_success
+
+END_ADDRESS_2 = *-1
+
+; xex segment header #3
+ ;.word RUNAD
+ ;.word RUNAD+1
+ .word INITAD
+ .word INITAD+1
+ .word main_entry_point
+
+; ----------------------------------------------------------------------------
+; (when does this actually get called? da65 can't find any references
+; to it, and it's not a run or init address in the binary load file)
+;;; .ifndef FUJICHAT
+;;; lda #<dosini_entry_point
+;;; sta DOSINI
+;;; lda #>dosini_entry_point
+;;; sta DOSINI+1
+;;; jmp main_entry_point
+;;; .endif
+
+; ----------------------------------------------------------------------------
+; There's absolutely no reason why this data needs to be included in the
+; binary load file: the line buffer's initial contents are meaningless, they
+; will be blown away the first time anything reads from the E: device.
+
+; Notice the author was running his debugger in COL80 when he built the
+; binary (ASCII "S COL80 7A00 7F80" command still in the buffer).
+
+ ;.ifdef FUJICHAT
+
+line_buffer = $0400 ; cassette buffer
+
+ ;.else
+;line_buffer:
+ ;.byte $53,$20,$43,$4F,$4C,$38,$30,$20
+ ;.byte $37,$41,$30,$30,$20,$37,$46,$38
+ ;.byte $30,$9B,$20,$20,$20,$20,$9B,$27
+ ;.byte $40,$40,$40,$40,$28,$28,$28,$28
+ ;.byte $40,$40,$40,$40,$40,$40,$40,$40
+ ;.byte $40,$40,$40,$40,$40,$40,$40,$40
+ ;.byte $9B,$FD,$FD,$FD,$FD,$9B
+ ;.endif
+
+
+; I've found a variant (modified version?) of this code, that doesn't
+; include the line_buffer in the file (no reason for it to be there),
+; or the $0C segment, and that has another segment, loaded at $6000,
+; with the run address changed to $6000. The code looks like:
+
+; .org $6000
+; jsr dosini_entry_point
+; lda #$50
+; sta RMARGN
+; lda #$00
+; sta COLOR2
+
+; also, the default colors have been changed in init_graphics_8.
+
+; There are at least two binaries floating around that contain
+; extra (garbage) bytes at the end, presumably from being transferred
+; over XMODEM or similar. They are otherwise identical.
+
diff --git a/src/col80_modified/col80_hacked.xex b/src/col80_modified/col80_hacked.xex
new file mode 100644
index 0000000..73ac7e3
--- /dev/null
+++ b/src/col80_modified/col80_hacked.xex
Binary files differ
diff --git a/src/col80_modified/cruft/Makefile b/src/col80_modified/cruft/Makefile
new file mode 100644
index 0000000..2152ced
--- /dev/null
+++ b/src/col80_modified/cruft/Makefile
@@ -0,0 +1,45 @@
+
+SRCFILES=col80_dosini_seg.s col80_header_seg.s col80_main.s \
+ col80_runad_seg.s col80_startaddr.s
+
+all: cc65_hack
+ binload -h col80.xex
+
+cc65_hack: $(SRCFILES) col80.s
+ ca65 -t atari -DFUJICHAT col80.s
+ ld65 -C col80_cc65_hack.cfg -o col80_main.xex col80.o
+ ca65 -t atari -DFUJICHAT col80_startup.s
+ ld65 -o col80_startup.xex col80_startup.o
+ cat col80_main.xex col80_startup.xex > col80.xex
+
+
+col80.xex:
+ $(MAKE) dasm_build || $(MAKE) ca65_build || $(MAKE) atasm_build
+
+dasm_build: $(SRCFILES) col80.dasm
+ dasm col80.dasm -f3 -ocol80.xex
+
+ca65_build: $(SRCFILES) col80.s
+ ca65 -t atari col80.s
+ ld65 -t atari -o col80.xex col80.o
+
+atasm_build: $(SRCFILES) col80.atasm
+ perl dasm2atasm col80_header_seg.s col80_header_seg.atasm
+ perl dasm2atasm col80_main.s col80_main.atasm
+ atasm -r -ocol80.xex col80.atasm
+
+check: col80.xex
+ @if cmp col80.xex col80_orig.xex; then \
+ echo "OK: New binary is identical to original" ;\
+ else \
+ echo "BAD: New binary differs from original" ;\
+ fi
+
+clean:
+ rm -f *.o col80_header_seg.atasm col80_main.atasm col80.xex
+
+test:
+ cp dos_20s.atr test.atr
+ cp col80.xex autorun.sys
+ axe -w autorun.sys test.atr
+ atari800 -nobasic test.atr
diff --git a/src/col80_modified/cruft/README.txt b/src/col80_modified/cruft/README.txt
new file mode 100644
index 0000000..720a1cc
--- /dev/null
+++ b/src/col80_modified/cruft/README.txt
@@ -0,0 +1,89 @@
+
+COL80 is a software 80-column driver for the Atari 8-bit computer. It
+uses GRAPHICS 8 with 4x8 pixel character cells, and replaces the OS
+ROM's E: handler.
+
+The file is found in various Atari archives, under various names such
+as COL80.COM, COL80E.COM, COL80HND.COM. The original author and date of
+publication are unknown.
+
+I've disassembled the binary and labelled/commented the source with
+(hopefully) meaningful names. The resulting sources can be reassembled
+with the DASM, ca65, or Atasm assemblers, which will result in a binary
+that compares as identical to the original.
+
+If you have one of the supported assemblers available on your path,
+plus a "make" utility (GNU, BSD, or probably Microsoft's nmake are OK),
+you can use the provided Makefile to rebuild the binary (including your
+own modified version, if you're into that sort of thing).
+
+File list:
+
+README.txt - you're reading it now
+
+Makefile - the usual
+
+col80_main.s - The actual source code for COL80
+
+col80_dosini_seg.s, col80_header_seg.s, col80_runad_seg.s, and
+col80_startaddr.s - Include files, used to build the multi-segment Atari
+binary load format object file.
+
+col80.s, col80.dasm, col80.atasm - Top-level wrappers for the various
+assemblers, which include the other files in the proper order and using
+the proper syntax for the assembler being used.
+
+Modification Ideas:
+
+Implement the missing control character actions. COL80 only does EOL and
+the clear-screen code (125), and the others (arrows, delete/insert/bell)
+are just printed in their graphical form.
+
+The original COL80 loads the driver code at $7A00, so it'll be compatible
+with BASIC, or other cartridge software. I've built a version org'ed at
+$9A00, which works great with disk-only software and gives an extra 8K
+of available RAM (change START_ADDR in col80_startaddr.s).
+
+It should be possible to use 4x7 or 4x6 character cells instead of
+4x8. The font would of course need to be redesigned, and the characters
+would be even smaller than they are now, but this would give you 27 or
+32 rows of text on screen (or more, if you expand the display by a few
+scanlines). With a good green or amber monitor and luma-only output,
+this could be usable.
+
+Instead of inverse video for characters 128-255, could do an expanded
+international character set (ISO Latin-1). Add a UTF-8 parser and you've
+got Unicode on the Atari!
+
+Add a VT100/ANSI escape-sequence parser. Could render actual underlined
+characters, and bold as inverse video. ANSI color codes we can't easily
+do, but could at least strip them out.
+
+Squeeze the driver down to save RAM. Use the standard E: buffer in page 5,
+move the code up so it ends just before the GR.8 display list, eliminate
+the code that installs the handler as X: and checks for the SELECT key
+being held down... get rid of the margin beep. Use RMARGN in zero page
+instead of right_margin at $7C00, move the other COL80 variables to
+page zero. Eliminate the lookup tables, if they can be replaced with
+code that takes up less space and calculates the values on the fly.
+The current driver code is 3 pages long; it might be possible to squish
+it into 2 pages... like, say, page 6 and the cassette buffer, or make it
+auto-relocate itself to MEMLO like Bob-Verter does. Using a 4x6 or 4x7
+font shrinks the font table, too... another thing to do would be to get
+rid of the clear_screen routine (replace with a call to init_graphics_8)
+
+For XL/XE machines, turn COL80 into an OS patch. For modified 400/800
+machines with RAM at $C000-CFFF, move COL80 there. For 130XEs, use an
+extended RAM bank for the driver, and another bank for the screen RAM
+(separate ANTIC/CPU access mode, won't work on most upgraded 800XLs). Just
+keep a tiny stub driver in main RAM, that switches in the driver's bank
+and jumps to it.
+
+Make a COL64 driver (like the SpartaDOS X CON64.SYS). Use 5x8 characters
+for 64 columns (or 5x6 for 64x32). Probably this would count more as
+a rewrite than a modification. The font would have to be stored one
+character per 8 bytes (take up twice as much space), and lots of shifting
+would have to happen when writing to the screen (slow)... Could also
+do 56 columns (7 pixel wide), and actually use the ROM font (just cut
+off the high bit, and for 56x27 also cut off the bottom scanline).
+
diff --git a/src/col80_modified/cruft/autorun.sys b/src/col80_modified/cruft/autorun.sys
new file mode 100644
index 0000000..e62d76d
--- /dev/null
+++ b/src/col80_modified/cruft/autorun.sys
Binary files differ
diff --git a/src/col80_modified/cruft/col80.atasm b/src/col80_modified/cruft/col80.atasm
new file mode 100644
index 0000000..3fdd27a
--- /dev/null
+++ b/src/col80_modified/cruft/col80.atasm
@@ -0,0 +1,6 @@
+
+ .include "col80_startaddr.s"
+ .include "col80_header_seg.atasm"
+ .include "col80_main.atasm"
+ .include "col80_dosini_seg.s"
+ .include "col80_runad_seg.s"
diff --git a/src/col80_modified/cruft/col80.dasm b/src/col80_modified/cruft/col80.dasm
new file mode 100644
index 0000000..b3a1de2
--- /dev/null
+++ b/src/col80_modified/cruft/col80.dasm
@@ -0,0 +1,10 @@
+
+ processor 6502 ; dasm
+
+ .include col80_startaddr.s
+ .include col80_header_seg.s
+ .include col80_main.s
+ .include col80_dosini_seg.s
+
+ .include col80_runad_seg.s
+
diff --git a/src/col80_modified/cruft/col80.info b/src/col80_modified/cruft/col80.info
new file mode 100644
index 0000000..ad821a4
--- /dev/null
+++ b/src/col80_modified/cruft/col80.info
@@ -0,0 +1,152 @@
+global {
+ comments 4;
+ inputname "col80e.raw";
+ outputname "col80e.dasm";
+ startaddr $7A00;
+};
+
+range {
+ start $7A00;
+ end $7BFF;
+ type bytetable;
+};
+
+range {
+ start $7F48;
+ end $7F80;
+ type bytetable;
+};
+
+range {
+ start $7D52;
+ end $7D81;
+ type bytetable;
+};
+
+range {
+ start $7DEA;
+ end $7DF0;
+ type bytetable;
+};
+
+range {
+ start $7EE5;
+ end $7EF0;
+ type addrtable;
+};
+
+LABEL { NAME "s_dev_open_lo"; ADDR $E410; };
+LABEL { NAME "s_dev_open_hi"; ADDR $E411; };
+
+LABEL { NAME "k_dev_get_lo"; ADDR $E424; };
+LABEL { NAME "k_dev_get_hi"; ADDR $E425; };
+
+LABEL { NAME "DOSINI"; ADDR $0C; };
+LABEL { NAME "DOSINI+1"; ADDR $0D; };
+LABEL { NAME "TMPCHR"; ADDR $50; };
+LABEL { NAME "LMARGN"; ADDR $52; };
+LABEL { NAME "DINDEX"; ADDR $57; };
+LABEL { NAME "SAVMSC"; ADDR $58; };
+LABEL { NAME "SAVMSC+1"; ADDR $59; };
+LABEL { NAME "ICAX1Z"; ADDR $2A; };
+LABEL { NAME "ICAX2Z"; ADDR $2B; };
+LABEL { NAME "ROWCRS"; ADDR $54; };
+LABEL { NAME "COLCRS"; ADDR $55; };
+LABEL { NAME "BUFCNT"; ADDR $6B; };
+LABEL { NAME "SSFLAG"; ADDR $02FF; };
+LABEL { NAME "HATABS"; ADDR $031A; };
+LABEL { NAME "CIOV"; ADDR $E456; };
+LABEL { NAME "CONSOL"; ADDR $D01F; };
+LABEL { NAME "AUDF1"; ADDR $D200; };
+LABEL { NAME "AUDC1"; ADDR $D201; };
+LABEL { NAME "ICCOM"; ADDR $0342; };
+LABEL { NAME "ICBAL"; ADDR $0344; };
+LABEL { NAME "ICBAH"; ADDR $0345; };
+LABEL { NAME "COLOR1"; ADDR $02C5; };
+LABEL { NAME "COLOR2"; ADDR $02C6; };
+LABEL { NAME "MEMTOP"; ADDR $02E5; };
+LABEL { NAME "MEMTOP+1"; ADDR $02E6; };
+
+LABEL { NAME "col80e_vector_tab"; ADDR $7EE5; };
+LABEL { NAME "col80e_open-1"; ADDR $7C00; };
+LABEL { NAME "col80e_open"; ADDR $7C01; };
+LABEL { NAME "col80e_close-1"; ADDR $7C3F; };
+LABEL { NAME "col80e_close"; ADDR $7C40; };
+LABEL { NAME "col80e_getbyte-1"; ADDR $7DF1; };
+LABEL { NAME "col80e_getbyte"; ADDR $7DF2; };
+LABEL { NAME "col80e_putbyte-1"; ADDR $7C42; };
+LABEL { NAME "col80e_putbyte"; ADDR $7C43; };
+LABEL { NAME "col80e_init"; ADDR $7EC0; };
+
+LABEL { NAME "screen_ptr_lo"; ADDR $CB; };
+LABEL { NAME "screen_ptr_hi"; ADDR $CC; };
+LABEL { NAME "font_ptr_lo"; ADDR $CD; };
+LABEL { NAME "font_ptr_hi"; ADDR $CE; };
+
+LABEL { NAME "font_data"; ADDR $7A00; };
+LABEL { NAME "lo_nybble_flag"; ADDR $7F48; };
+
+LABEL { NAME "clear_screen"; ADDR $7D0B; };
+LABEL { NAME "regular_char"; ADDR $7C56; };
+LABEL { NAME "check_ssflag"; ADDR $7C7F; };
+LABEL { NAME "dosini_entry_point"; ADDR $7EF4; };
+LABEL { NAME "main_entry_point"; ADDR $7EF7; };
+LABEL { NAME "get_keystroke"; ADDR $7EB7; };
+LABEL { NAME "return_success"; ADDR $7D31; };
+LABEL { NAME "inverse_mask"; ADDR $7F49; };
+LABEL { NAME "not_inverse"; ADDR $7C60; };
+LABEL { NAME "open_s_dev"; ADDR $7C37; };
+LABEL { NAME "init_graphics_8"; ADDR $7C14; };
+LABEL { NAME "not_eol"; ADDR $7C4F; };
+LABEL { NAME "graphics_ok"; ADDR $7C73; };
+LABEL { NAME "setup_screen_ptr"; ADDR $7D34; };
+LABEL { NAME "setup_font_ptr"; ADDR $7CC9; };
+LABEL { NAME "hi_byte_ok"; ADDR $7D4F; };
+LABEL { NAME "row_low_offset_tab"; ADDR $7D52; };
+LABEL { NAME "row_high_offset_tab"; ADDR $7D6A; };
+LABEL { NAME "cls_loop"; ADDR $7D19; };
+LABEL { NAME "write_font_data_odd"; ADDR $7D82; };
+LABEL { NAME "write_font_data_even"; ADDR $7DB9; };
+LABEL { NAME "scroll_screen"; ADDR $7C87; };
+LABEL { NAME "advance_cursor"; ADDR $7CEE; };
+LABEL { NAME "skip_write"; ADDR $7C7C; };
+LABEL { NAME "skip_ninv"; ADDR $7C65; };
+LABEL { NAME "lo_nybble_odd"; ADDR $7D97; };
+LABEL { NAME "hi_nybble_even"; ADDR $7DC8; };
+LABEL { NAME "write_font_done_odd"; ADDR $7DB8; };
+LABEL { NAME "get_font_nybble_odd"; ADDR $7D8C; };
+LABEL { NAME "get_font_nybble_even"; ADDR $7DBD; };
+LABEL { NAME "screen_ptr_ok_odd"; ADDR $7DB0; };
+LABEL { NAME "screen_ptr_ok_even"; ADDR $7DE1; };
+LABEL { NAME "write_font_done_even"; ADDR $7DE9; };
+LABEL { NAME "scanline_offset_tab"; ADDR $7DEA; };
+LABEL { NAME "get_line"; ADDR $7E04; };
+LABEL { NAME "line_buffer_index"; ADDR $7F4A; };
+LABEL { NAME "line_buffer"; ADDR $7F4B; };
+LABEL { NAME "get_next_byte"; ADDR $7DF6; };
+LABEL { NAME "show_cursor"; ADDR $7E0B; };
+LABEL { NAME "keystroke_ok"; ADDR $7E2B; };
+LABEL { NAME "return_key_hit"; ADDR $7E52; };
+LABEL { NAME "check_backs_key"; ADDR $7E32; };
+LABEL { NAME "backs_key_hit"; ADDR $7E71; };
+LABEL { NAME "check_clear_key"; ADDR $7E39; };
+LABEL { NAME "clear_key_hit"; ADDR $7E64; };
+LABEL { NAME "normal_key_hit"; ADDR $7E40; };
+LABEL { NAME "beep"; ADDR $7E8F; };
+LABEL { NAME "beep_delay_x"; ADDR $7E93; };
+LABEL { NAME "beep_delay_y"; ADDR $7E99; };
+LABEL { NAME "buffer_character"; ADDR $7E47; };
+LABEL { NAME "print_space"; ADDR $7EA4; };
+LABEL { NAME "backs_key_done"; ADDR $7E8C; };
+LABEL { NAME "same_line"; ADDR $7E8A; };
+LABEL { NAME "next_hatab_slot"; ADDR $7EC2; };
+LABEL { NAME "register_x_handler"; ADDR $7ED1; };
+LABEL { NAME "no_e_handler"; ADDR $7F30; };
+LABEL { NAME "no_scroll"; ADDR $7D08; };
+LABEL { NAME "next_line"; ADDR $7D0A; };
+LABEL { NAME "font_hi_nybble"; ADDR $7CDB; };
+LABEL { NAME "scroll_line_loop"; ADDR $7C9C; };
+LABEL { NAME "blank_bottom_row"; ADDR $7CAA; };
+LABEL { NAME "blank_loop"; ADDR $7CBA; };
+LABEL { NAME "blank_tail"; ADDR $7CC3; };
+
diff --git a/src/col80_modified/cruft/col80.s b/src/col80_modified/cruft/col80.s
new file mode 100644
index 0000000..334082a
--- /dev/null
+++ b/src/col80_modified/cruft/col80.s
@@ -0,0 +1,21 @@
+
+; ca65 wrapper for building col80
+
+ .setcpu "6502"
+
+ .segment "EXEHDR"
+ .include "col80_startaddr.s"
+ .include "col80_header_seg.s"
+
+ .segment "CODE"
+ .include "col80_main.s"
+
+ .ifndef FUJICHAT
+ .include "col80_dosini_seg.s"
+
+ .segment "AUTOSTRT"
+ .include "col80_runad_seg.s"
+ .endif
+
+ .segment "ZPSAVE"
+ ; nothing to see here, just shutting up ld65's warning
diff --git a/src/col80_modified/cruft/col80.xex b/src/col80_modified/cruft/col80.xex
new file mode 100644
index 0000000..5872c7f
--- /dev/null
+++ b/src/col80_modified/cruft/col80.xex
Binary files differ
diff --git a/src/col80_modified/cruft/col80_cc65_hack.cfg b/src/col80_modified/cruft/col80_cc65_hack.cfg
new file mode 100644
index 0000000..82b2c25
--- /dev/null
+++ b/src/col80_modified/cruft/col80_cc65_hack.cfg
@@ -0,0 +1,41 @@
+FEATURES {
+ STARTADDRESS: default = $2E00;
+}
+SYMBOLS {
+ __STACKSIZE__ = $800; # 2K stack
+ __RESERVED_MEMORY__: value = $0, weak = yes;
+}
+MEMORY {
+ ZP: start = $0082, size = $007E, type = rw, define = yes;
+ HEADER: start = $0000, size = $0006, file = %O;
+ RAM: start = %S, size = $BC20 - __STACKSIZE__ - %S, file = %O;
+ TRAILER: start = $0000, size = $0006, file = %O;
+}
+SEGMENTS {
+ EXEHDR: load = HEADER, type = ro;
+ LOWCODE: load = RAM, type = ro, define = yes, optional = yes;
+ INIT: load = RAM, type = ro, optional = yes;
+ CODE: load = RAM, type = ro, define = yes;
+ RODATA: load = RAM, type = ro;
+ DATA: load = RAM, type = rw;
+ ZPSAVE: load = RAM, type = bss, define = yes;
+ BSS: load = RAM, type = bss, define = yes;
+ HEAP: load = RAM, type = bss, optional = yes; # must sit just below stack
+ ZEROPAGE: load = ZP, type = zp, optional = yes;
+ EXTZP: load = ZP, type = zp, optional = yes;
+ AUTOSTRT: load = TRAILER, type = ro, optional = yes;
+}
+FEATURES {
+ CONDES: segment = INIT,
+ type = constructor,
+ label = __CONSTRUCTOR_TABLE__,
+ count = __CONSTRUCTOR_COUNT__;
+ CONDES: segment = RODATA,
+ type = destructor,
+ label = __DESTRUCTOR_TABLE__,
+ count = __DESTRUCTOR_COUNT__;
+ CONDES: type = interruptor,
+ segment = RODATA,
+ label = __INTERRUPTOR_TABLE__,
+ count = __INTERRUPTOR_COUNT__;
+}
diff --git a/src/col80_modified/cruft/col80_dosini_seg.s b/src/col80_modified/cruft/col80_dosini_seg.s
new file mode 100644
index 0000000..d92e7ed
--- /dev/null
+++ b/src/col80_modified/cruft/col80_dosini_seg.s
@@ -0,0 +1,12 @@
+
+; Second segment of the file loads at $0C (aka DOSINI), and just contains
+; the address of dosini_entry_point
+
+ .ifndef FUJICHAT
+ .word $FFFF ; unnecessary, though the original file had it
+ .endif
+
+ .word $000C ; DOSINI
+ .word $000D
+ .word dosini_entry_point
+
diff --git a/src/col80_modified/cruft/col80_entry.s b/src/col80_modified/cruft/col80_entry.s
new file mode 100644
index 0000000..edf0d96
--- /dev/null
+++ b/src/col80_modified/cruft/col80_entry.s
@@ -0,0 +1,61 @@
+; ----------------------------------------------------------------------------
+; The OS jumps here on warmstart (also, this is the run address in our
+; binary load file)
+
+dosini_entry_point:
+ .ifndef FUJICHAT
+ nop
+ nop
+ nop
+ .endif
+
+main_entry_point:
+ jsr col80_init
+ .ifndef FUJICHAT
+ lda CONSOL
+ and #$04
+ beq no_e_handler
+ .endif
+ lda #$0C
+ sta ICCOM
+ ldx #$00
+ jsr CIOV
+ lda #$58
+ sta font_ptr_lo
+ lda #$03
+ sta ICCOM
+ lda #font_ptr_lo
+ sta ICBAL
+ lda #$00
+ sta ICBAH
+ ldx #$00
+ jsr CIOV
+ ldy #$07
+ lda #<col80_vector_tab
+ sta HATABS,y
+ lda #>col80_vector_tab
+ iny
+ sta HATABS,y
+no_e_handler:
+ lda #<START_ADDRESS
+ sta MEMTOP
+ lda #>START_ADDRESS
+ sta MEMTOP+1
+ .ifdef FUJICHAT
+ ldy #$01
+ rts
+ .else
+ jmp return_success
+ .endif
+
+; ----------------------------------------------------------------------------
+; (when does this actually get called? da65 can't find any references
+; to it, and it's not a run or init address in the binary load file)
+ .ifndef FUJICHAT
+ lda #<dosini_entry_point
+ sta DOSINI
+ lda #>dosini_entry_point
+ sta DOSINI+1
+ jmp main_entry_point
+ .endif
+
diff --git a/src/col80_modified/cruft/col80_header_seg.s b/src/col80_modified/cruft/col80_header_seg.s
new file mode 100644
index 0000000..2f96ad9
--- /dev/null
+++ b/src/col80_modified/cruft/col80_header_seg.s
@@ -0,0 +1,6 @@
+
+ .org START_ADDRESS-6
+ .word $FFFF
+ .word START_ADDRESS
+ .word END_ADDRESS
+
diff --git a/src/col80_modified/cruft/col80_include.s b/src/col80_modified/cruft/col80_include.s
new file mode 100644
index 0000000..943c579
--- /dev/null
+++ b/src/col80_modified/cruft/col80_include.s
@@ -0,0 +1,50 @@
+; ----------------------------------------------------------------------------
+; Zero page labels (OS equates)
+
+DOSINI = $000C
+ICAX1Z = $002A
+ICAX2Z = $002B
+TMPCHR = $0050
+LMARGN = $0052
+ROWCRS = $0054
+COLCRS = $0055
+DINDEX = $0057
+SAVMSC = $0058
+BUFCNT = $006B
+
+; ----------------------------------------------------------------------------
+; Zero page labels (COL80 equates)
+
+screen_ptr_lo = $00CB
+screen_ptr_hi = $00CC
+font_ptr_lo = $00CD
+font_ptr_hi = $00CE
+
+; ----------------------------------------------------------------------------
+; Non-zeropage RAM labels (OS equates)
+
+COLOR1 = $02C5
+COLOR2 = $02C6
+RUNAD = $02E0
+MEMTOP = $02E5
+SSFLAG = $02FF
+HATABS = $031A
+ICCOM = $0342
+ICBAL = $0344
+ICBAH = $0345
+
+; ----------------------------------------------------------------------------
+; Hardware (memory-mapped I/O, OS equates)
+
+CONSOL = $D01F
+AUDF1 = $D200
+AUDC1 = $D201
+
+; ----------------------------------------------------------------------------
+; OS ROM labels
+
+s_dev_open_lo = $E410 ; (not named in OS sources)
+s_dev_open_hi = $E411 ; ""
+k_dev_get_lo = $E424 ; ""
+k_dev_get_hi = $E425 ; ""
+CIOV = $E456 ; Central Input/Output entry point
diff --git a/src/col80_modified/cruft/col80_init.s b/src/col80_modified/cruft/col80_init.s
new file mode 100644
index 0000000..89ccf75
--- /dev/null
+++ b/src/col80_modified/cruft/col80_init.s
@@ -0,0 +1,35 @@
+; ----------------------------------------------------------------------------
+; Initialization callback. The OS will call this on coldstart (or would do,
+; if the driver were in ROM), and also on warmstart (because we stole the
+; DOSINI vector).
+; This routine is also the first thing that gets called by the mainline
+; init code. Its job is to install COL80 in the handler table at HATABS.
+; Actually the handler is first installed as X:, then the main init code
+; fixes this up to E: unless the user is holding down SELECT. This allows
+; the user to toggle between the 40-column ROM E: and COL80 without doing
+; a full reboot. No idea if this was a documented feature or something the
+; author used for development/debugging.
+
+col80_init:
+ ldy #$00
+
+next_hatab_slot:
+ lda HATABS,y
+ beq register_x_handler
+ iny
+ iny
+ iny
+ cpy #$20
+ bcc next_hatab_slot
+ jmp return_success
+
+register_x_handler:
+ lda #$58
+ sta HATABS,y
+ lda #<col80_vector_tab
+ iny
+ sta HATABS,y
+ lda #>col80_vector_tab
+ iny
+ sta HATABS,y
+ jmp return_success
diff --git a/src/col80_modified/cruft/col80_main.s b/src/col80_modified/cruft/col80_main.s
new file mode 100644
index 0000000..0ced210
--- /dev/null
+++ b/src/col80_modified/cruft/col80_main.s
@@ -0,0 +1,824 @@
+; THIS IS A MODIFIED VERSION, for use with FujiChat
+
+; COL80.COM, aka COL80E.COM, aka COL80HND.COM
+; (and probably several other names)
+
+; Original author unknown
+; License unknown
+; Disassembly and comments by Urchlay
+
+; This is a widely-distributed software 80-column driver for the Atari
+; 8-bit computers. It replaces the OS's E: driver, and uses GRAPHICS 8
+; for display, with 4x8 pixel character cells.
+
+; Disassembly was done with da65, with many iterations of "edit the
+; .info file, disassemble again", and the results were tweaked by hand
+; into something assemblable by dasm (and fairly compatible with other
+; assemblers).
+
+
+ .include "col80_include.s"
+
+; START_ADDRESS is defined in col80_startaddr.s
+ .org START_ADDRESS
+
+; ----------------------------------------------------------------------------
+; Start of COL80. The font is stored in packed form. Each group of 8 bytes
+; defines two glyphs: the upper 4 bits of the 8 bytes, taken together,
+; define the bitmap for the first glyph, and the lower 4 bits are the second.
+; Note that the bits that make up a single character are spread across 8
+; bytes, so it's hard to visualize these even if you're used to reading hex
+; dumps.
+
+; The first 2 characters look like:
+
+; .... .O.. ; $04
+; .... .O.. ; $04
+; O.O. .O.. ; $A4
+; OOO. .O.. ; $E4
+; OOO. .OOO ; $E7
+; .O.. .O.. ; $44
+; .... .O.. ; $04
+; .... .O.. ; $04
+
+; These are the ATASCII heart symbol (character code 0) and the ATASCII
+; control-A line-drawing symbol (code 1).
+
+; Note: unlike the ROM font, this font is stored in ATASCII order instead
+; of the standard Atari character order imposed by the hardware. Like
+; the ROM font, inverse characters are not stored here (the bitmaps get
+; inverted by the driver)
+
+font_data:
+ .ifdef FUJICHAT
+ .include "new_font.s"
+ .else
+ ; Low ATASCII graphics symbols (code 0-31)
+ .byte $04,$04,$A4,$E4,$E7,$44,$04,$04
+ .byte $14,$14,$14,$14,$1C,$10,$10,$10
+ .byte $40,$40,$40,$40,$CC,$44,$44,$44
+ .byte $18,$18,$24,$24,$42,$42,$81,$81
+ .byte $10,$10,$30,$30,$73,$73,$F3,$F3
+ .byte $83,$83,$C3,$C3,$E0,$E0,$F0,$F0
+ .byte $CF,$CF,$C0,$C0,$00,$00,$00,$00
+ .byte $00,$00,$00,$00,$0C,$0C,$FC,$FC
+ .byte $00,$00,$00,$40,$A7,$44,$E4,$04
+ .byte $04,$04,$04,$04,$FF,$04,$04,$04
+ .byte $00,$00,$60,$F0,$FF,$6F,$0F,$0F
+ .byte $80,$80,$80,$80,$8F,$84,$84,$84
+ .byte $4C,$4C,$4C,$4C,$FC,$0C,$0C,$0C
+ .byte $40,$4C,$48,$4C,$78,$0C,$06,$00
+ .byte $00,$44,$E4,$44,$4E,$44,$00,$00
+ .byte $00,$24,$42,$FF,$42,$24,$00,$00
+
+ ; Space ! " # etc (codes 32-63)
+ .byte $00,$04,$04,$04,$04,$00,$04,$00
+ .byte $00,$A0,$AA,$AE,$0A,$0E,$0A,$00
+ .byte $00,$40,$68,$82,$44,$28,$C2,$40
+ .byte $00,$C4,$64,$E4,$60,$C0,$40,$00
+ .byte $00,$44,$82,$82,$82,$82,$82,$44
+ .byte $00,$04,$A4,$4E,$E4,$44,$A0,$00
+ .byte $00,$00,$00,$0E,$00,$40,$40,$80
+ .byte $00,$02,$02,$04,$04,$08,$48,$00
+ .byte $00,$E4,$AC,$A4,$A4,$A4,$EE,$00
+ .byte $00,$EE,$22,$22,$EE,$82,$EE,$00
+ .byte $00,$AE,$A8,$AE,$E2,$22,$2E,$00
+ .byte $00,$EE,$82,$E2,$A4,$A4,$E4,$00
+ .byte $00,$EE,$AA,$EA,$AE,$A2,$EE,$00
+ .byte $00,$00,$00,$44,$00,$44,$04,$08
+ .byte $00,$20,$4E,$80,$4E,$20,$00,$00
+ .byte $00,$8C,$42,$22,$44,$80,$04,$00
+
+ ; @ A B C etc (codes 64-95)
+ .byte $00,$6E,$9A,$BA,$BE,$8A,$6A,$00
+ .byte $00,$C6,$A8,$C8,$A8,$A8,$C6,$00
+ .byte $00,$CE,$A8,$AC,$A8,$A8,$CE,$00
+ .byte $00,$E6,$88,$C8,$8A,$8A,$86,$00
+ .byte $00,$AE,$A4,$E4,$A4,$A4,$AE,$00
+ .byte $00,$2A,$2A,$2C,$2A,$2A,$CA,$00
+ .byte $00,$8A,$8E,$8E,$8A,$8A,$EA,$00
+ .byte $00,$C4,$AA,$AA,$AA,$AA,$A4,$00
+ .byte $00,$EE,$AA,$EA,$8A,$8A,$8E,$03
+ .byte $00,$C6,$A8,$AC,$C2,$A2,$AC,$00
+ .byte $00,$EA,$4A,$4A,$4A,$4A,$4E,$00
+ .byte $00,$AA,$AA,$AA,$AE,$AE,$4A,$00
+ .byte $00,$AA,$4A,$4E,$44,$44,$A4,$00
+ .byte $00,$EE,$28,$48,$88,$88,$E8,$0E
+ .byte $00,$8E,$82,$42,$42,$22,$22,$0E
+ .byte $00,$00,$40,$A0,$00,$00,$00,$0F
+
+ ; diamond, lowercase letters, control codes (codes 96-127)
+ .byte $00,$00,$00,$46,$E2,$4E,$0E,$00
+ .byte $00,$80,$80,$C6,$A8,$A8,$C6,$00
+ .byte $00,$20,$20,$6E,$AE,$A8,$6E,$00
+ .byte $00,$00,$C0,$86,$CA,$8E,$82,$0C
+ .byte $00,$80,$84,$80,$C4,$A4,$A4,$00
+ .byte $00,$08,$28,$0A,$2C,$2A,$2A,$C0
+ .byte $00,$40,$40,$4A,$4E,$4A,$4A,$00
+ .byte $00,$00,$00,$CE,$AA,$AA,$AE,$00
+ .byte $00,$00,$00,$C6,$AA,$C6,$82,$82
+ .byte $00,$00,$00,$6E,$88,$86,$8E,$00
+ .byte $00,$00,$40,$EA,$4A,$4A,$6E,$00
+ .byte $00,$00,$00,$AA,$AA,$AE,$4A,$00
+ .byte $00,$00,$00,$AA,$4A,$A6,$A2,$0C
+ .byte $00,$00,$04,$EE,$4E,$84,$EE,$00
+ .byte $40,$4E,$4C,$4E,$4A,$42,$42,$40
+ .byte $00,$28,$6C,$EE,$6C,$28,$00,$00
+ .endif
+
+right_margin:
+ ; Default value is 79 decimal. Unsure why the author didn't use RMARGN at $53
+ .byte $4F
+
+; ----------------------------------------------------------------------------
+; Start of COL80 code.
+
+; Callback for CIO OPEN command.
+
+col80_open:
+ jsr init_graphics_8
+ lda #$00
+ sta ROWCRS
+ sta COLCRS
+ .ifndef FUJICHAT
+ nop
+ nop
+ .endif
+ sta BUFCNT
+ lda #$4F
+ sta right_margin
+ rts
+
+; ----------------------------------------------------------------------------
+; Assembly version of GRAPHICS 8+16 command.
+
+init_graphics_8:
+ lda #$08
+ sta ICAX2Z
+ lda #$0C
+ sta ICAX1Z
+ jsr open_s_dev
+
+ ; Set COL80's default colors
+ lda #$08
+ sta COLOR2
+ .ifndef FUJICHAT
+ nop
+ nop
+ nop
+ .endif
+ lda #$00
+ sta COLOR1
+
+ ; Protect ourselves from BASIC and the OS
+ lda #<START_ADDRESS
+ sta MEMTOP
+ lda #>START_ADDRESS
+ sta MEMTOP+1
+ rts
+
+; ----------------------------------------------------------------------------
+; Call the OPEN vector for the S: device, using the ROM vector table
+; at $E410. The table stores address-minus-one of each routine, which is
+; meant to actually be called via the RTS instruction (standard 6502
+; technique, but confusing the first time you encounter it)
+
+open_s_dev:
+ lda s_dev_open_hi
+ pha
+ lda s_dev_open_lo
+ pha
+ rts
+
+; ----------------------------------------------------------------------------
+; Callback for CIO CLOSE command. Note that the routine does nothing, really
+; (the OS will mark the E: device as being closed, but COL80 doesn't do any
+; cleanup).
+; The SPECIAL and GET STATUS callbacks in col80_vector_tab also point here.
+
+col80_close:
+ jmp return_success
+
+; ----------------------------------------------------------------------------
+; Callback for the internal put-one-byte, used by the OS to implement the
+; CIO PUT RECORD and PUT BYTES commands. This routine's one argument is
+; the byte in the accumulator (the character to print).
+
+; First, the routine checks for the cursor control characters it supports.
+; COL80 only handles the EOL and clear-screen codes; trying to print
+; backspaces, arrows, deletes, inserts, etc just causes their ATASCII
+; graphics character to print instead.
+
+col80_putbyte:
+ ; EOL (decimal 155)?
+ cmp #$9B
+ bne check_clear
+ lda right_margin
+ sta COLCRS
+ jmp skip_write
+
+check_clear:
+ .ifndef FUJICHAT ; save memory by not including clear_screen
+ ; (also, this lets us print the } character)
+ ; Clear (decimal 125)?
+ cmp #$7D
+ bne regular_char
+ jmp clear_screen
+ .endif
+
+ ; See if this is an inverse video char (code >= 128)
+regular_char:
+ tax
+ bpl not_inverse
+ lda #$FF
+ sta inverse_mask
+ bne skip_ninv
+
+not_inverse:
+ lda #$00
+ sta inverse_mask
+
+skip_ninv:
+ txa
+ and #$7F
+ .ifdef FUJICHAT ; mask out low ASCII
+ sec
+ sbc #$20
+ bcs not_low_ascii
+ jmp return_success
+not_low_ascii:
+ .endif
+ sta TMPCHR
+ lda DINDEX
+ cmp #$08
+ beq graphics_ok
+ ; If we're not in GRAPHICS 8 mode, reinitialize ourselves
+ jsr col80_open
+
+graphics_ok:
+ ; Call the routines that actually print the character
+ jsr setup_font_ptr
+ jsr setup_screen_ptr
+ jsr write_font_data
+
+skip_write:
+ ; Move the cursor 1 space to the right. This will
+ ; advance us to the next line if we're at the margin,
+ ; and scroll the screen if needed
+ jsr advance_cursor
+
+check_ssflag:
+ ; The OS keyboard interrupt handler will toggle SSFLAG (start/stop fla
+ ; any time the user presses ctrl-1
+ lda SSFLAG
+ bne check_ssflag
+ jmp return_success
+
+; ----------------------------------------------------------------------------
+; Scroll the screen up one line (8 scanlines). This has to move almost 8K of
+; data, so it's noticeably slower than scrolling the GR.0 text screen.
+
+scroll_screen:
+ lda SAVMSC
+ sta screen_ptr_lo
+ clc
+ adc #$40
+ ; font_ptr_lo is actually being used here as a second pointer into
+ ; screen RAM, instead of its usual use as a pointer into the
+ ; font_data table
+ sta font_ptr_lo
+ lda SAVMSC+1
+ sta screen_ptr_hi
+ adc #$01
+ sta font_ptr_hi
+ ldx #$1D
+ ldy #$00
+
+scroll_line_loop:
+ lda (font_ptr_lo),y
+ sta (screen_ptr_lo),y
+ dey
+ bne scroll_line_loop
+ inc font_ptr_hi
+ inc screen_ptr_hi
+ dex
+ bne scroll_line_loop
+
+blank_bottom_row:
+ lda SAVMSC
+ clc
+ adc #$C0
+ sta screen_ptr_lo
+ lda SAVMSC+1
+ adc #$1C
+ sta screen_ptr_hi
+ lda #$00
+ tay
+
+blank_loop:
+ sta (screen_ptr_lo),y
+ dey
+ bne blank_loop
+ inc screen_ptr_hi
+ ldy #$40
+
+blank_tail:
+ sta (screen_ptr_lo),y
+ dey
+ bpl blank_tail
+ rts
+
+; ----------------------------------------------------------------------------
+; Set up font_ptr_lo/hi to point to the font_data bitmap for the character in
+; TMPCHR. Also sets lo_nybble_flag to let the caller know whether the
+; bitmap is in the upper or lower 4 bits of the bytes pointed to.
+
+setup_font_ptr:
+ lda #$00
+ sta font_ptr_hi
+ sta lo_nybble_flag
+ lda TMPCHR
+ clc
+ ror
+ bcc font_hi_nybble
+ ldx #$FF
+ stx lo_nybble_flag
+
+font_hi_nybble:
+ clc
+ rol
+ rol
+ rol font_ptr_hi
+ rol
+ rol font_ptr_hi
+ adc #<font_data
+ sta font_ptr_lo
+ lda #>font_data
+ adc font_ptr_hi
+ sta font_ptr_hi
+ rts
+
+; ----------------------------------------------------------------------------
+; Move the cursor one space to the right (to the next line if at the margin,
+; and scroll screen if on the last row)
+
+advance_cursor:
+ inc COLCRS
+ lda right_margin
+ cmp COLCRS
+ bcs same_line
+ lda LMARGN
+ sta COLCRS
+ lda ROWCRS
+ ; $17 is 25 decimal, one row below the lowest on the screen
+ cmp #$17
+ bcc no_scroll
+ jsr scroll_screen
+ ; Move to row 24 after scrolling
+ lda #$16
+ sta ROWCRS
+
+no_scroll:
+ inc ROWCRS
+
+same_line:
+ rts
+
+; ----------------------------------------------------------------------------
+; Clear the screen by setting all screen RAM bytes to zero. Slow, but not
+; as slow as scrolling.
+
+ .ifndef FUJICHAT
+clear_screen:
+ lda SAVMSC
+ sta screen_ptr_lo
+ lda SAVMSC+1
+ sta screen_ptr_hi
+ ldy #$00
+ ldx #$1D
+ lda #$00
+
+cls_loop:
+ sta (screen_ptr_lo),y
+ dey
+ bne cls_loop
+ inc screen_ptr_hi
+ dex
+ bne cls_loop
+ jsr blank_bottom_row
+ lda LMARGN
+ sta COLCRS
+ lda #$00
+ sta ROWCRS
+ ; redundant JMP
+ jmp return_success
+ .endif
+
+; ----------------------------------------------------------------------------
+; CIO expects the Y register to contain a status code.
+; 1 means success (no error). Lots of COL80's routines
+; jump here.
+
+return_success:
+ ldy #$01
+ rts
+
+; ----------------------------------------------------------------------------
+; Set screen_ptr_lo/hi to point to the address of the first byte of graphics
+; data at the current cursor position.
+
+setup_screen_ptr:
+ ldy ROWCRS
+ lda SAVMSC
+ clc
+ adc row_low_offset_tab,y
+ sta screen_ptr_lo
+ lda SAVMSC+1
+ adc row_high_offset_tab,y
+ sta screen_ptr_hi
+ lda COLCRS
+ lsr
+ clc
+ adc screen_ptr_lo
+ bcc hi_byte_ok
+ inc screen_ptr_hi
+
+hi_byte_ok:
+ sta screen_ptr_lo
+ rts
+
+; ----------------------------------------------------------------------------
+; Tables of offsets for setup_screen_ptr, to avoid doing multiplication at
+; runtime (the 6502 lacks a MUL instruction, so it's slow...)
+
+row_low_offset_tab:
+ .byte $00,$40,$80,$C0,$00,$40,$80,$C0
+ .byte $00,$40,$80,$C0,$00,$40,$80,$C0
+ .byte $00,$40,$80,$C0,$00,$40,$80,$C0
+
+row_high_offset_tab:
+ .byte $00,$01,$02,$03,$05,$06,$07,$08
+ .byte $0A,$0B,$0C,$0D,$0F,$10,$11,$12
+ .byte $14,$15,$16,$17,$19,$1A,$1B,$1C
+
+; ----------------------------------------------------------------------------
+; Copy pixel data from the font table to screen RAM.
+; font_ptr_lo/hi must point to the correct character, and screen_ptr_lo/hi
+; must point to the correct screen address for the current cursor position.
+; This routine has separate execution paths for even- and odd-numbered
+; cursor positions, since each byte of screen RAM holds data for two
+; adjacent characters (and when printing to one of them, the other needs
+; to be left undisturbed!)
+
+write_font_data:
+ lda COLCRS
+ clc
+ ror
+ bcc write_font_data_even
+ ldx #$00
+ ldy #$00
+
+get_font_nybble_odd:
+ lda (font_ptr_lo),y
+ bit lo_nybble_flag
+ bne lo_nybble_odd
+ ; glyph we want is stored in top 4 bits of font byte,
+ ; shift it down to the bottom 4 bits
+ lsr
+ lsr
+ lsr
+ lsr
+
+lo_nybble_odd:
+ eor inverse_mask
+ and #$0F
+ sta TMPCHR
+ ldy scanline_offset_tab,x
+ lda (screen_ptr_lo),y
+ and #$F0
+ ora TMPCHR
+ sta (screen_ptr_lo),y
+ inx
+ cpx #$07
+ bne screen_ptr_ok_odd
+ inc screen_ptr_hi
+
+screen_ptr_ok_odd:
+ cpx #$08
+ beq write_font_done_odd
+ txa
+ tay
+ bne get_font_nybble_odd
+
+write_font_done_odd:
+ rts
+
+; ----------------------------------------------------------------------------
+; Write data to even-numbered columns, very similar to the above
+
+write_font_data_even:
+ ldx #$00
+ ldy #$00
+
+get_font_nybble_even:
+ lda (font_ptr_lo),y
+ bit lo_nybble_flag
+ beq hi_nybble_even
+ asl
+ asl
+ asl
+ asl
+
+hi_nybble_even:
+ eor inverse_mask
+ and #$F0
+ sta TMPCHR
+ ldy scanline_offset_tab,x
+ lda (screen_ptr_lo),y
+ and #$0F
+ ora TMPCHR
+ sta (screen_ptr_lo),y
+ inx
+ cpx #$07
+ bne screen_ptr_ok_even
+ inc screen_ptr_hi
+
+screen_ptr_ok_even:
+ cpx #$08
+ beq write_font_done_even
+ txa
+ tay
+ bne get_font_nybble_even
+
+write_font_done_even:
+ rts
+
+; ----------------------------------------------------------------------------
+
+scanline_offset_tab:
+ .byte $00,$28,$50,$78,$A0,$C8,$F0,$18
+
+; ----------------------------------------------------------------------------
+; Callback for the internal get-one-byte, used by the OS to implement the
+; CIO GET RECORD and GET BYTES commands. This routine takes no arguments,
+; and returns the read byte in the accumulator.
+
+; Internally, COL80 maintains a line buffer. Each time col80_getbyte is
+; called, it returns the next character in the buffer. If the buffer's
+; empty (or if the last call returned the last character), a new line
+; of input is read from the user (and the first character is returned).
+; This is exactly how the OS E: device works.
+
+col80_getbyte:
+ lda BUFCNT
+ beq get_line
+
+get_next_byte:
+ ldx line_buffer_index
+ lda line_buffer,x
+ dec BUFCNT
+ inc line_buffer_index
+ jmp return_success
+
+; ----------------------------------------------------------------------------
+; Get a line of input from the user, terminated by the Return key.
+
+get_line:
+ lda #$00
+ sta BUFCNT
+ sta line_buffer_index
+
+show_cursor:
+ .ifdef FUJICHAT
+ lda #$00
+ .else
+ lda #$20
+ .endif
+ sta TMPCHR
+ lda #$FF
+ sta inverse_mask
+ jsr setup_font_ptr
+ jsr setup_screen_ptr
+ jsr write_font_data
+ jsr get_keystroke
+ cpy #$01
+ beq keystroke_ok
+ .ifdef FUJICHAT
+ dey ; yes, we really care about 1-byte optimizations
+ .else
+ ldy #$00
+ .endif
+ sty line_buffer_index
+ sty BUFCNT
+
+keystroke_ok:
+ .ifdef FUJICHAT
+ cmp #$20
+ bcc show_cursor ; ignore low ASCII
+ .endif
+ cmp #$9B
+ bne check_backs_key
+ jmp return_key_hit
+
+check_backs_key:
+ cmp #$7E
+ bne check_clear_key
+ jmp backs_key_hit
+
+check_clear_key:
+ cmp #$7D
+ bne normal_key_hit
+ jmp clear_key_hit
+
+normal_key_hit:
+ ldx BUFCNT
+ bpl buffer_character
+ .ifdef FUJICHAT
+ jmp show_cursor
+ .else
+ jmp beep
+ .endif
+
+buffer_character:
+ sta line_buffer,x
+ jsr col80_putbyte
+ inc BUFCNT
+ jmp show_cursor
+
+return_key_hit:
+ jsr print_space
+ lda #$9B
+ ldx BUFCNT
+ sta line_buffer,x
+ inc BUFCNT
+ jsr col80_putbyte
+ jmp get_next_byte
+
+clear_key_hit:
+ .ifndef FUJICHAT
+ jsr clear_screen
+ .endif
+ lda #$00
+ sta line_buffer_index
+ sta BUFCNT
+ jmp get_line
+
+backs_key_hit:
+ jsr print_space
+ lda BUFCNT
+ beq backs_key_done
+ dec COLCRS
+ lda COLCRS
+ clc
+ adc #$01
+ cmp LMARGN
+ bne backs_same_line
+ lda right_margin
+ sta COLCRS
+ dec ROWCRS
+
+backs_same_line:
+ dec BUFCNT
+
+backs_key_done:
+ jmp show_cursor
+
+; ----------------------------------------------------------------------------
+; Ring the margin bell. COL80 doesn't implement the ctrl-2 bell (character
+; 253), and instead of using the GTIA keyclick speaker, it uses POKEY to
+; make a beep
+
+ .ifndef FUJICHAT
+beep: ldy #$00
+ ldx #$AF
+
+beep_delay_x:
+ stx AUDF1
+ stx AUDC1
+
+beep_delay_y:
+ dey
+ bne beep_delay_y
+ dex
+ cpx #$9F
+ bne beep_delay_x
+ jmp show_cursor
+ .endif
+
+; ----------------------------------------------------------------------------
+; Print a space character at the current cursor position. Does not
+; update the cursor position.
+print_space:
+ lda #$00
+ sta inverse_mask
+ .ifndef FUJICHAT
+ lda #$20
+ .endif
+ sta TMPCHR
+ jsr setup_font_ptr
+ jsr setup_screen_ptr
+ jsr write_font_data
+ rts
+
+; ----------------------------------------------------------------------------
+; Get a keystroke (blocking). Just calls the OS K: get-one-byte routine
+; (call by pushing address-minus-one then doing an RTS)
+get_keystroke:
+ lda k_dev_get_hi
+ pha
+ lda k_dev_get_lo
+ pha
+ rts
+
+ .ifndef FUJICHAT
+ .include "col80_init.s"
+ .endif
+
+; ----------------------------------------------------------------------------
+; COL80 vector table, in the format required by the OS. Our HATABS entry
+; will point to this table, and the OS will call the routines listed here
+; via the "call by RTS" method (which is why they're address-minus-one).
+
+; See the entry on HATABS in "Mapping the Atari" or the OS manual.
+
+col80_vector_tab:
+ .word col80_open-1
+ .word col80_close-1
+ .word col80_getbyte-1
+ .word col80_putbyte-1
+ .word col80_close-1
+ .word col80_close-1
+ .ifdef FUJICHAT
+ .byte 0, 0, 0 ; heh.
+ .else
+ jmp col80_init
+ .endif
+
+ .ifndef FUJICHAT
+ .include "col80_entry.s"
+ .endif
+
+; ----------------------------------------------------------------------------
+; Various bits of runtime state here. It's unclear to me why the standard
+; OS buffer location couldn't have been used instead (normally the top
+; half of page 5), or why the other stuff couldn't have been stored in
+; zero page, in locations used by the ROM E: handler (thus unused when
+; it's replaced with COL80). line_buffer_index needs to be preserved
+; across calls to col80_getbyte, but lo_nybble_flag and inverse_mask are
+; freshly calculated every time they're used, so they could be almost
+; anywhere.
+
+ .ifdef FUJICHAT
+ .segment "CODE"
+ .endif
+
+lo_nybble_flag:
+ .byte $00
+
+inverse_mask:
+ .byte $00
+
+line_buffer_index:
+ .byte $12
+
+; ----------------------------------------------------------------------------
+; There's absolutely no reason why this data needs to be included in the
+; binary load file: the line buffer's initial contents are meaningless, they
+; will be blown away the first time anything reads from the E: device.
+
+; Notice the author was running his debugger in COL80 when he built the
+; binary (ASCII "S COL80 7A00 7F80" command still in the buffer).
+
+ .ifdef FUJICHAT
+line_buffer = $03FD ; cassette buffer
+ .else
+line_buffer:
+ .byte $53,$20,$43,$4F,$4C,$38,$30,$20
+ .byte $37,$41,$30,$30,$20,$37,$46,$38
+ .byte $30,$9B,$20,$20,$20,$20,$9B,$27
+ .byte $40,$40,$40,$40,$28,$28,$28,$28
+ .byte $40,$40,$40,$40,$40,$40,$40,$40
+ .byte $40,$40,$40,$40,$40,$40,$40,$40
+ .byte $9B,$FD,$FD,$FD,$FD,$9B
+ .endif
+
+END_ADDRESS = *-1
+
+; I've found a variant (modified version?) of this code, that doesn't
+; include the line_buffer in the file (no reason for it to be there),
+; or the $0C segment, and that has another segment, loaded at $6000,
+; with the run address changed to $6000. The code looks like:
+
+; .org $6000
+; jsr dosini_entry_point
+; lda #$50
+; sta RMARGN
+; lda #$00
+; sta COLOR2
+
+; also, the default colors have been changed in init_graphics_8.
+
+; There are at least two binaries floating around that contain
+; extra (garbage) bytes at the end, presumably from being transferred
+; over XMODEM or similar. They are otherwise identical.
+
diff --git a/src/col80_modified/cruft/col80_main.s.orig b/src/col80_modified/cruft/col80_main.s.orig
new file mode 100644
index 0000000..0b56ee3
--- /dev/null
+++ b/src/col80_modified/cruft/col80_main.s.orig
@@ -0,0 +1,895 @@
+; COL80.COM, aka COL80E.COM, aka COL80HND.COM
+; (and probably several other names)
+
+; Original author unknown
+; License unknown
+; Disassembly and comments by Urchlay
+
+; This is a widely-distributed software 80-column driver for the Atari
+; 8-bit computers. It replaces the OS's E: driver, and uses GRAPHICS 8
+; for display, with 4x8 pixel character cells.
+
+; Disassembly was done with da65, with many iterations of "edit the
+; .info file, disassemble again", and the results were tweaked by hand
+; into something assemblable by dasm (and fairly compatible with other
+; assemblers).
+
+
+; START_ADDRESS is defined in col80_startaddr.s
+ .org START_ADDRESS
+
+; ----------------------------------------------------------------------------
+; Zero page labels (OS equates)
+
+DOSINI = $000C
+ICAX1Z = $002A
+ICAX2Z = $002B
+TMPCHR = $0050
+LMARGN = $0052
+ROWCRS = $0054
+COLCRS = $0055
+DINDEX = $0057
+SAVMSC = $0058
+BUFCNT = $006B
+
+; ----------------------------------------------------------------------------
+; Zero page labels (COL80 equates)
+
+screen_ptr_lo = $00CB
+screen_ptr_hi = $00CC
+font_ptr_lo = $00CD
+font_ptr_hi = $00CE
+
+; ----------------------------------------------------------------------------
+; Non-zeropage RAM labels (OS equates)
+
+COLOR1 = $02C5
+COLOR2 = $02C6
+RUNAD = $02E0
+MEMTOP = $02E5
+SSFLAG = $02FF
+HATABS = $031A
+ICCOM = $0342
+ICBAL = $0344
+ICBAH = $0345
+
+; ----------------------------------------------------------------------------
+; Hardware (memory-mapped I/O, OS equates)
+
+CONSOL = $D01F
+AUDF1 = $D200
+AUDC1 = $D201
+
+; ----------------------------------------------------------------------------
+; OS ROM labels
+
+s_dev_open_lo = $E410 ; (not named in OS sources)
+s_dev_open_hi = $E411 ; ""
+k_dev_get_lo = $E424 ; ""
+k_dev_get_hi = $E425 ; ""
+CIOV = $E456 ; Central Input/Output entry point
+
+; ----------------------------------------------------------------------------
+; Start of COL80. The font is stored in packed form. Each group of 8 bytes
+; defines two glyphs: the upper 4 bits of the 8 bytes, taken together,
+; define the bitmap for the first glyph, and the lower 4 bits are the second.
+; Note that the bits that make up a single character are spread across 8
+; bytes, so it's hard to visualize these even if you're used to reading hex
+; dumps.
+
+; The first 2 characters look like:
+
+; .... .O.. ; $04
+; .... .O.. ; $04
+; O.O. .O.. ; $A4
+; OOO. .O.. ; $E4
+; OOO. .OOO ; $E7
+; .O.. .O.. ; $44
+; .... .O.. ; $04
+; .... .O.. ; $04
+
+; These are the ATASCII heart symbol (character code 0) and the ATASCII
+; control-A line-drawing symbol (code 1).
+
+; Note: unlike the ROM font, this font is stored in ATASCII order instead
+; of the standard Atari character order imposed by the hardware. Like
+; the ROM font, inverse characters are not stored here (the bitmaps get
+; inverted by the driver)
+
+font_data:
+ ; Low ATASCII graphics symbols (code 0-31)
+ .byte $04,$04,$A4,$E4,$E7,$44,$04,$04 ; 7A00
+ .byte $14,$14,$14,$14,$1C,$10,$10,$10 ; 7A08
+ .byte $40,$40,$40,$40,$CC,$44,$44,$44 ; 7A10
+ .byte $18,$18,$24,$24,$42,$42,$81,$81 ; 7A18
+ .byte $10,$10,$30,$30,$73,$73,$F3,$F3 ; 7A20
+ .byte $83,$83,$C3,$C3,$E0,$E0,$F0,$F0 ; 7A28
+ .byte $CF,$CF,$C0,$C0,$00,$00,$00,$00 ; 7A30
+ .byte $00,$00,$00,$00,$0C,$0C,$FC,$FC ; 7A38
+ .byte $00,$00,$00,$40,$A7,$44,$E4,$04 ; 7A40
+ .byte $04,$04,$04,$04,$FF,$04,$04,$04 ; 7A48
+ .byte $00,$00,$60,$F0,$FF,$6F,$0F,$0F ; 7A50
+ .byte $80,$80,$80,$80,$8F,$84,$84,$84 ; 7A58
+ .byte $4C,$4C,$4C,$4C,$FC,$0C,$0C,$0C ; 7A60
+ .byte $40,$4C,$48,$4C,$78,$0C,$06,$00 ; 7A68
+ .byte $00,$44,$E4,$44,$4E,$44,$00,$00 ; 7A70
+ .byte $00,$24,$42,$FF,$42,$24,$00,$00 ; 7A78
+
+ ; Space ! " # etc (codes 32-63)
+ .byte $00,$04,$04,$04,$04,$00,$04,$00 ; 7A80
+ .byte $00,$A0,$AA,$AE,$0A,$0E,$0A,$00 ; 7A88
+ .byte $00,$40,$68,$82,$44,$28,$C2,$40 ; 7A90
+ .byte $00,$C4,$64,$E4,$60,$C0,$40,$00 ; 7A98
+ .byte $00,$44,$82,$82,$82,$82,$82,$44 ; 7AA0
+ .byte $00,$04,$A4,$4E,$E4,$44,$A0,$00 ; 7AA8
+ .byte $00,$00,$00,$0E,$00,$40,$40,$80 ; 7AB0
+ .byte $00,$02,$02,$04,$04,$08,$48,$00 ; 7AB8
+ .byte $00,$E4,$AC,$A4,$A4,$A4,$EE,$00 ; 7AC0
+ .byte $00,$EE,$22,$22,$EE,$82,$EE,$00 ; 7AC8
+ .byte $00,$AE,$A8,$AE,$E2,$22,$2E,$00 ; 7AD0
+ .byte $00,$EE,$82,$E2,$A4,$A4,$E4,$00 ; 7AD8
+ .byte $00,$EE,$AA,$EA,$AE,$A2,$EE,$00 ; 7AE0
+ .byte $00,$00,$00,$44,$00,$44,$04,$08 ; 7AE8
+ .byte $00,$20,$4E,$80,$4E,$20,$00,$00 ; 7AF0
+ .byte $00,$8C,$42,$22,$44,$80,$04,$00 ; 7AF8
+
+ ; @ A B C etc (codes 64-95)
+ .byte $00,$6E,$9A,$BA,$BE,$8A,$6A,$00 ; 7B00
+ .byte $00,$C6,$A8,$C8,$A8,$A8,$C6,$00 ; 7B08
+ .byte $00,$CE,$A8,$AC,$A8,$A8,$CE,$00 ; 7B10
+ .byte $00,$E6,$88,$C8,$8A,$8A,$86,$00 ; 7B18
+ .byte $00,$AE,$A4,$E4,$A4,$A4,$AE,$00 ; 7B20
+ .byte $00,$2A,$2A,$2C,$2A,$2A,$CA,$00 ; 7B28
+ .byte $00,$8A,$8E,$8E,$8A,$8A,$EA,$00 ; 7B30
+ .byte $00,$C4,$AA,$AA,$AA,$AA,$A4,$00 ; 7B38
+ .byte $00,$EE,$AA,$EA,$8A,$8A,$8E,$03 ; 7B40
+ .byte $00,$C6,$A8,$AC,$C2,$A2,$AC,$00 ; 7B48
+ .byte $00,$EA,$4A,$4A,$4A,$4A,$4E,$00 ; 7B50
+ .byte $00,$AA,$AA,$AA,$AE,$AE,$4A,$00 ; 7B58
+ .byte $00,$AA,$4A,$4E,$44,$44,$A4,$00 ; 7B60
+ .byte $00,$EE,$28,$48,$88,$88,$E8,$0E ; 7B68
+ .byte $00,$8E,$82,$42,$42,$22,$22,$0E ; 7B70
+ .byte $00,$00,$40,$A0,$00,$00,$00,$0F ; 7B78
+
+ ; diamond, lowercase letters, control codes (codes 96-127)
+ .byte $00,$00,$00,$46,$E2,$4E,$0E,$00 ; 7B80
+ .byte $00,$80,$80,$C6,$A8,$A8,$C6,$00 ; 7B88
+ .byte $00,$20,$20,$6E,$AE,$A8,$6E,$00 ; 7B90
+ .byte $00,$00,$C0,$86,$CA,$8E,$82,$0C ; 7B98
+ .byte $00,$80,$84,$80,$C4,$A4,$A4,$00 ; 7BA0
+ .byte $00,$08,$28,$0A,$2C,$2A,$2A,$C0 ; 7BA8
+ .byte $00,$40,$40,$4A,$4E,$4A,$4A,$00 ; 7BB0
+ .byte $00,$00,$00,$CE,$AA,$AA,$AE,$00 ; 7BB8
+ .byte $00,$00,$00,$C6,$AA,$C6,$82,$82 ; 7BC0
+ .byte $00,$00,$00,$6E,$88,$86,$8E,$00 ; 7BC8
+ .byte $00,$00,$40,$EA,$4A,$4A,$6E,$00 ; 7BD0
+ .byte $00,$00,$00,$AA,$AA,$AE,$4A,$00 ; 7BD8
+ .byte $00,$00,$00,$AA,$4A,$A6,$A2,$0C ; 7BE0
+ .byte $00,$00,$04,$EE,$4E,$84,$EE,$00 ; 7BE8
+ .byte $40,$4E,$4C,$4E,$4A,$42,$42,$40 ; 7BF0
+ .byte $00,$28,$6C,$EE,$6C,$28,$00,$00 ; 7BF8
+
+right_margin:
+ ; Default value is 79 decimal. Unsure why the author didn't use RMARGN at $53
+ .byte $4F ; 7C00 4F
+
+; ----------------------------------------------------------------------------
+; Start of COL80 code.
+
+; Callback for CIO OPEN command.
+
+col80_open:
+ jsr init_graphics_8 ; 7C01 20 14 7C
+ lda #$00 ; 7C04 A9 00
+ sta ROWCRS ; 7C06 85 54
+ sta COLCRS ; 7C08 85 55
+ nop ; 7C0A EA
+ nop ; 7C0B EA
+ sta BUFCNT ; 7C0C 85 6B
+ lda #$4F ; 7C0E A9 4F
+ sta right_margin ; 7C10 8D 00 7C
+ rts ; 7C13 60
+
+; ----------------------------------------------------------------------------
+; Assembly version of GRAPHICS 8+16 command.
+
+init_graphics_8:
+ lda #$08 ; 7C14 A9 08
+ sta ICAX2Z ; 7C16 85 2B
+ lda #$0C ; 7C18 A9 0C
+ sta ICAX1Z ; 7C1A 85 2A
+ jsr open_s_dev ; 7C1C 20 37 7C
+
+ ; Set COL80's default colors
+ lda #$08 ; 7C1F A9 08
+ sta COLOR2 ; 7C21 8D C6 02
+ nop ; 7C24 EA
+ nop ; 7C25 EA
+ nop ; 7C26 EA
+ lda #$00 ; 7C27 A9 00
+ sta COLOR1 ; 7C29 8D C5 02
+
+ ; Protect ourselves from BASIC and the OS
+ lda #<START_ADDRESS ; 7C2C A9 00
+ sta MEMTOP ; 7C2E 8D E5 02
+ lda #>START_ADDRESS ; 7C31 A9 7A
+ sta MEMTOP+1 ; 7C33 8D E6 02
+ rts ; 7C36 60
+
+; ----------------------------------------------------------------------------
+; Call the OPEN vector for the S: device, using the ROM vector table
+; at $E410. The table stores address-minus-one of each routine, which is
+; meant to actually be called via the RTS instruction (standard 6502
+; technique, but confusing the first time you encounter it)
+
+open_s_dev:
+ lda s_dev_open_hi ; 7C37 AD 11 E4
+ pha ; 7C3A 48
+ lda s_dev_open_lo ; 7C3B AD 10 E4
+ pha ; 7C3E 48
+ rts ; 7C3F 60
+
+; ----------------------------------------------------------------------------
+; Callback for CIO CLOSE command. Note that the routine does nothing, really
+; (the OS will mark the E: device as being closed, but COL80 doesn't do any
+; cleanup).
+; The SPECIAL and GET STATUS callbacks in col80_vector_tab also point here.
+
+col80_close:
+ jmp return_success
+
+; ----------------------------------------------------------------------------
+; Callback for the internal put-one-byte, used by the OS to implement the
+; CIO PUT RECORD and PUT BYTES commands. This routine's one argument is
+; the byte in the accumulator (the character to print).
+
+; First, the routine checks for the cursor control characters it supports.
+; COL80 only handles the EOL and clear-screen codes; trying to print
+; backspaces, arrows, deletes, inserts, etc just causes their ATASCII
+; graphics character to print instead.
+
+col80_putbyte:
+ ; EOL (decimal 155)?
+ cmp #$9B ; 7C43 C9 9B
+ bne check_clear ; 7C45 D0 08
+ lda right_margin ; 7C47 AD 00 7C
+ sta COLCRS ; 7C4A 85 55
+ jmp skip_write ; 7C4C 4C 7C 7C
+
+check_clear:
+ ; Clear (decimal 125)?
+ cmp #$7D ; 7C4F C9 7D
+ bne regular_char ; 7C51 D0 03
+ jmp clear_screen ; 7C53 4C 0B 7D
+
+ ; See if this is an inverse video char (code >= 128)
+regular_char:
+ tax ; 7C56 AA
+ bpl not_inverse ; 7C57 10 07
+ lda #$FF ; 7C59 A9 FF
+ sta inverse_mask ; 7C5B 8D 49 7F
+ bne skip_ninv ; 7C5E D0 05
+
+not_inverse:
+ lda #$00 ; 7C60 A9 00
+ sta inverse_mask ; 7C62 8D 49 7F
+
+skip_ninv:
+ txa ; 7C65 8A
+ and #$7F ; 7C66 29 7F
+ sta TMPCHR ; 7C68 85 50
+ lda DINDEX ; 7C6A A5 57
+ cmp #$08 ; 7C6C C9 08
+ beq graphics_ok ; 7C6E F0 03
+ ; If we're not in GRAPHICS 8 mode, reinitialize ourselves
+ jsr col80_open ; 7C70 20 01 7C
+
+graphics_ok:
+ ; Call the routines that actually print the character
+ jsr setup_font_ptr ; 7C73 20 C9 7C
+ jsr setup_screen_ptr ; 7C76 20 34 7D
+ jsr write_font_data ; 7C79 20 82 7D
+
+skip_write:
+ ; Move the cursor 1 space to the right. This will
+ ; advance us to the next line if we're at the margin,
+ ; and scroll the screen if needed
+ jsr advance_cursor ; 7C7C 20 EE 7C
+
+check_ssflag:
+ ; The OS keyboard interrupt handler will toggle SSFLAG (start/stop fla
+ ; any time the user presses ctrl-1
+ lda SSFLAG ; 7C7F AD FF 02
+ bne check_ssflag ; 7C82 D0 FB
+ jmp return_success ; 7C84 4C 31 7D
+
+; ----------------------------------------------------------------------------
+; Scroll the screen up one line (8 scanlines). This has to move almost 8K of
+; data, so it's noticeably slower than scrolling the GR.0 text screen.
+
+scroll_screen:
+ lda SAVMSC ; 7C87 A5 58
+ sta screen_ptr_lo ; 7C89 85 CB
+ clc ; 7C8B 18
+ adc #$40 ; 7C8C 69 40
+ ; font_ptr_lo is actually being used here as a second pointer into
+ ; screen RAM, instead of its usual use as a pointer into the
+ ; font_data table
+ sta font_ptr_lo ; 7C8E 85 CD
+ lda SAVMSC+1 ; 7C90 A5 59
+ sta screen_ptr_hi ; 7C92 85 CC
+ adc #$01 ; 7C94 69 01
+ sta font_ptr_hi ; 7C96 85 CE
+ ldx #$1D ; 7C98 A2 1D
+ ldy #$00 ; 7C9A A0 00
+
+scroll_line_loop:
+ lda (font_ptr_lo),y ; 7C9C B1 CD
+ sta (screen_ptr_lo),y ; 7C9E 91 CB
+ dey ; 7CA0 88
+ bne scroll_line_loop ; 7CA1 D0 F9
+ inc font_ptr_hi ; 7CA3 E6 CE
+ inc screen_ptr_hi ; 7CA5 E6 CC
+ dex ; 7CA7 CA
+ bne scroll_line_loop ; 7CA8 D0 F2
+
+blank_bottom_row:
+ lda SAVMSC ; 7CAA A5 58
+ clc ; 7CAC 18
+ adc #$C0 ; 7CAD 69 C0
+ sta screen_ptr_lo ; 7CAF 85 CB
+ lda SAVMSC+1 ; 7CB1 A5 59
+ adc #$1C ; 7CB3 69 1C
+ sta screen_ptr_hi ; 7CB5 85 CC
+ lda #$00 ; 7CB7 A9 00
+ tay ; 7CB9 A8
+
+blank_loop:
+ sta (screen_ptr_lo),y ; 7CBA 91 CB
+ dey ; 7CBC 88
+ bne blank_loop ; 7CBD D0 FB
+ inc screen_ptr_hi ; 7CBF E6 CC
+ ldy #$40 ; 7CC1 A0 40
+
+blank_tail:
+ sta (screen_ptr_lo),y ; 7CC3 91 CB
+ dey ; 7CC5 88
+ bpl blank_tail ; 7CC6 10 FB
+ rts ; 7CC8 60
+
+; ----------------------------------------------------------------------------
+; Set up font_ptr_lo/hi to point to the font_data bitmap for the character in
+; TMPCHR. Also sets lo_nybble_flag to let the caller know whether the
+; bitmap is in the upper or lower 4 bits of the bytes pointed to.
+
+setup_font_ptr:
+ lda #$00 ; 7CC9 A9 00
+ sta font_ptr_hi ; 7CCB 85 CE
+ sta lo_nybble_flag ; 7CCD 8D 48 7F
+ lda TMPCHR ; 7CD0 A5 50
+ clc ; 7CD2 18
+ ror ; 7CD3 6A
+ bcc font_hi_nybble ; 7CD4 90 05
+ ldx #$FF ; 7CD6 A2 FF
+ stx lo_nybble_flag ; 7CD8 8E 48 7F
+
+font_hi_nybble:
+ clc ; 7CDB 18
+ rol ; 7CDC 2A
+ rol ; 7CDD 2A
+ rol font_ptr_hi ; 7CDE 26 CE
+ rol ; 7CE0 2A
+ rol font_ptr_hi ; 7CE1 26 CE
+ adc #<font_data ; 7CE3 69 00
+ sta font_ptr_lo ; 7CE5 85 CD
+ lda #>font_data ; 7CE7 A9 7A
+ adc font_ptr_hi ; 7CE9 65 CE
+ sta font_ptr_hi ; 7CEB 85 CE
+ rts ; 7CED 60
+
+; ----------------------------------------------------------------------------
+; Move the cursor one space to the right (to the next line if at the margin,
+; and scroll screen if on the last row)
+
+advance_cursor:
+ inc COLCRS ; 7CEE E6 55
+ lda right_margin ; 7CF0 AD 00 7C
+ cmp COLCRS ; 7CF3 C5 55
+ bcs same_line ; 7CF5 B0 13
+ lda LMARGN ; 7CF7 A5 52
+ sta COLCRS ; 7CF9 85 55
+ lda ROWCRS ; 7CFB A5 54
+ ; $17 is 25 decimal, one row below the lowest on the screen
+ cmp #$17 ; 7CFD C9 17
+ bcc no_scroll ; 7CFF 90 07
+ jsr scroll_screen ; 7D01 20 87 7C
+ ; Move to row 24 after scrolling
+ lda #$16 ; 7D04 A9 16
+ sta ROWCRS ; 7D06 85 54
+
+no_scroll:
+ inc ROWCRS ; 7D08 E6 54
+
+same_line:
+ rts ; 7D0A 60
+
+; ----------------------------------------------------------------------------
+; Clear the screen by setting all screen RAM bytes to zero. Slow, but not
+; as slow as scrolling.
+
+clear_screen:
+ lda SAVMSC ; 7D0B A5 58
+ sta screen_ptr_lo ; 7D0D 85 CB
+ lda SAVMSC+1 ; 7D0F A5 59
+ sta screen_ptr_hi ; 7D11 85 CC
+ ldy #$00 ; 7D13 A0 00
+ ldx #$1D ; 7D15 A2 1D
+ lda #$00 ; 7D17 A9 00
+
+cls_loop:
+ sta (screen_ptr_lo),y ; 7D19 91 CB
+ dey ; 7D1B 88
+ bne cls_loop ; 7D1C D0 FB
+ inc screen_ptr_hi ; 7D1E E6 CC
+ dex ; 7D20 CA
+ bne cls_loop ; 7D21 D0 F6
+ jsr blank_bottom_row ; 7D23 20 AA 7C
+ lda LMARGN ; 7D26 A5 52
+ sta COLCRS ; 7D28 85 55
+ lda #$00 ; 7D2A A9 00
+ sta ROWCRS ; 7D2C 85 54
+ ; redundant JMP
+ jmp return_success ; 7D2E 4C 31 7D
+
+; ----------------------------------------------------------------------------
+; CIO expects the Y register to contain a status code.
+; 1 means success (no error). Lots of COL80's routines
+; jump here.
+
+return_success:
+ ldy #$01 ; 7D31 A0 01
+ rts ; 7D33 60
+
+; ----------------------------------------------------------------------------
+; Set screen_ptr_lo/hi to point to the address of the first byte of graphics
+; data at the current cursor position.
+
+setup_screen_ptr:
+ ldy ROWCRS ; 7D34 A4 54
+ lda SAVMSC ; 7D36 A5 58
+ clc ; 7D38 18
+ adc row_low_offset_tab,y ; 7D39 79 52 7D
+ sta screen_ptr_lo ; 7D3C 85 CB
+ lda SAVMSC+1 ; 7D3E A5 59
+ adc row_high_offset_tab,y ; 7D40 79 6A 7D
+ sta screen_ptr_hi ; 7D43 85 CC
+ lda COLCRS ; 7D45 A5 55
+ lsr ; 7D47 4A
+ clc ; 7D48 18
+ adc screen_ptr_lo ; 7D49 65 CB
+ bcc hi_byte_ok ; 7D4B 90 02
+ inc screen_ptr_hi ; 7D4D E6 CC
+
+hi_byte_ok:
+ sta screen_ptr_lo ; 7D4F 85 CB
+ rts ; 7D51 60
+
+; ----------------------------------------------------------------------------
+; Tables of offsets for setup_screen_ptr, to avoid doing multiplication at
+; runtime (the 6502 lacks a MUL instruction, so it's slow...)
+
+row_low_offset_tab:
+ .byte $00,$40,$80,$C0,$00,$40,$80,$C0 ; 7D52
+ .byte $00,$40,$80,$C0,$00,$40,$80,$C0 ; 7D5A
+ .byte $00,$40,$80,$C0,$00,$40,$80,$C0 ; 7D62
+
+row_high_offset_tab:
+ .byte $00,$01,$02,$03,$05,$06,$07,$08 ; 7D6A
+ .byte $0A,$0B,$0C,$0D,$0F,$10,$11,$12 ; 7D72
+ .byte $14,$15,$16,$17,$19,$1A,$1B,$1C ; 7D7A
+
+; ----------------------------------------------------------------------------
+; Copy pixel data from the font table to screen RAM.
+; font_ptr_lo/hi must point to the correct character, and screen_ptr_lo/hi
+; must point to the correct screen address for the current cursor position.
+; This routine has separate execution paths for even- and odd-numbered
+; cursor positions, since each byte of screen RAM holds data for two
+; adjacent characters (and when printing to one of them, the other needs
+; to be left undisturbed!)
+
+write_font_data:
+ lda COLCRS ; 7D82 A5 55
+ clc ; 7D84 18
+ ror ; 7D85 6A
+ bcc write_font_data_even ; 7D86 90 31
+ ldx #$00 ; 7D88 A2 00
+ ldy #$00 ; 7D8A A0 00
+
+get_font_nybble_odd:
+ lda (font_ptr_lo),y ; 7D8C B1 CD
+ bit lo_nybble_flag ; 7D8E 2C 48 7F
+ bne lo_nybble_odd ; 7D91 D0 04
+ ; glyph we want is stored in top 4 bits of font byte,
+ ; shift it down to the bottom 4 bits
+ lsr ; 7D93 4A
+ lsr ; 7D94 4A
+ lsr ; 7D95 4A
+ lsr ; 7D96 4A
+
+lo_nybble_odd:
+ eor inverse_mask ; 7D97 4D 49 7F
+ and #$0F ; 7D9A 29 0F
+ sta TMPCHR ; 7D9C 85 50
+ ldy scanline_offset_tab,x ; 7D9E BC EA 7D
+ lda (screen_ptr_lo),y ; 7DA1 B1 CB
+ and #$F0 ; 7DA3 29 F0
+ ora TMPCHR ; 7DA5 05 50
+ sta (screen_ptr_lo),y ; 7DA7 91 CB
+ inx ; 7DA9 E8
+ cpx #$07 ; 7DAA E0 07
+ bne screen_ptr_ok_odd ; 7DAC D0 02
+ inc screen_ptr_hi ; 7DAE E6 CC
+
+screen_ptr_ok_odd:
+ cpx #$08 ; 7DB0 E0 08
+ beq write_font_done_odd ; 7DB2 F0 04
+ txa ; 7DB4 8A
+ tay ; 7DB5 A8
+ bne get_font_nybble_odd ; 7DB6 D0 D4
+
+write_font_done_odd:
+ rts ; 7DB8 60
+
+; ----------------------------------------------------------------------------
+; Write data to even-numbered columns, very similar to the above
+
+write_font_data_even:
+ ldx #$00 ; 7DB9 A2 00
+ ldy #$00 ; 7DBB A0 00
+
+get_font_nybble_even:
+ lda (font_ptr_lo),y ; 7DBD B1 CD
+ bit lo_nybble_flag ; 7DBF 2C 48 7F
+ beq hi_nybble_even ; 7DC2 F0 04
+ asl ; 7DC4 0A
+ asl ; 7DC5 0A
+ asl ; 7DC6 0A
+ asl ; 7DC7 0A
+
+hi_nybble_even:
+ eor inverse_mask ; 7DC8 4D 49 7F
+ and #$F0 ; 7DCB 29 F0
+ sta TMPCHR ; 7DCD 85 50
+ ldy scanline_offset_tab,x ; 7DCF BC EA 7D
+ lda (screen_ptr_lo),y ; 7DD2 B1 CB
+ and #$0F ; 7DD4 29 0F
+ ora TMPCHR ; 7DD6 05 50
+ sta (screen_ptr_lo),y ; 7DD8 91 CB
+ inx ; 7DDA E8
+ cpx #$07 ; 7DDB E0 07
+ bne screen_ptr_ok_even ; 7DDD D0 02
+ inc screen_ptr_hi ; 7DDF E6 CC
+
+screen_ptr_ok_even:
+ cpx #$08 ; 7DE1 E0 08
+ beq write_font_done_even ; 7DE3 F0 04
+ txa ; 7DE5 8A
+ tay ; 7DE6 A8
+ bne get_font_nybble_even ; 7DE7 D0 D4
+
+write_font_done_even:
+ rts ; 7DE9 60
+
+; ----------------------------------------------------------------------------
+
+scanline_offset_tab:
+ .byte $00,$28,$50,$78,$A0,$C8,$F0,$18 ; 7DEA
+
+; ----------------------------------------------------------------------------
+; Callback for the internal get-one-byte, used by the OS to implement the
+; CIO GET RECORD and GET BYTES commands. This routine takes no arguments,
+; and returns the read byte in the accumulator.
+
+; Internally, COL80 maintains a line buffer. Each time col80_getbyte is
+; called, it returns the next character in the buffer. If the buffer's
+; empty (or if the last call returned the last character), a new line
+; of input is read from the user (and the first character is returned).
+; This is exactly how the OS E: device works.
+
+col80_getbyte:
+ lda BUFCNT ; 7DF2 A5 6B
+ beq get_line ; 7DF4 F0 0E
+
+get_next_byte:
+ ldx line_buffer_index ; 7DF6 AE 4A 7F
+ lda line_buffer,x ; 7DF9 BD 4B 7F
+ dec BUFCNT ; 7DFC C6 6B
+ inc line_buffer_index ; 7DFE EE 4A 7F
+ jmp return_success ; 7E01 4C 31 7D
+
+; ----------------------------------------------------------------------------
+; Get a line of input from the user, terminated by the Return key.
+
+get_line:
+ lda #$00 ; 7E04 A9 00
+ sta BUFCNT ; 7E06 85 6B
+ sta line_buffer_index ; 7E08 8D 4A 7F
+
+show_cursor:
+ lda #$20 ; 7E0B A9 20
+ sta TMPCHR ; 7E0D 85 50
+ lda #$FF ; 7E0F A9 FF
+ sta inverse_mask ; 7E11 8D 49 7F
+ jsr setup_font_ptr ; 7E14 20 C9 7C
+ jsr setup_screen_ptr ; 7E17 20 34 7D
+ jsr write_font_data ; 7E1A 20 82 7D
+ jsr get_keystroke ; 7E1D 20 B7 7E
+ cpy #$01 ; 7E20 C0 01
+ beq keystroke_ok ; 7E22 F0 07
+ ldy #$00 ; 7E24 A0 00
+ sty line_buffer_index ; 7E26 8C 4A 7F
+ sty BUFCNT ; 7E29 84 6B
+
+keystroke_ok:
+ cmp #$9B ; 7E2B C9 9B
+ bne check_backs_key ; 7E2D D0 03
+ jmp return_key_hit ; 7E2F 4C 52 7E
+
+check_backs_key:
+ cmp #$7E ; 7E32 C9 7E
+ bne check_clear_key ; 7E34 D0 03
+ jmp backs_key_hit ; 7E36 4C 71 7E
+
+check_clear_key:
+ cmp #$7D ; 7E39 C9 7D
+ bne normal_key_hit ; 7E3B D0 03
+ jmp clear_key_hit ; 7E3D 4C 64 7E
+
+normal_key_hit:
+ ldx BUFCNT ; 7E40 A6 6B
+ bpl buffer_character ; 7E42 10 03
+ jmp beep ; 7E44 4C 8F 7E
+
+buffer_character:
+ sta line_buffer,x ; 7E47 9D 4B 7F
+ jsr col80_putbyte ; 7E4A 20 43 7C
+ inc BUFCNT ; 7E4D E6 6B
+ jmp show_cursor ; 7E4F 4C 0B 7E
+
+return_key_hit:
+ jsr print_space ; 7E52 20 A4 7E
+ lda #$9B ; 7E55 A9 9B
+ ldx BUFCNT ; 7E57 A6 6B
+ sta line_buffer,x ; 7E59 9D 4B 7F
+ inc BUFCNT ; 7E5C E6 6B
+ jsr col80_putbyte ; 7E5E 20 43 7C
+ jmp get_next_byte ; 7E61 4C F6 7D
+
+clear_key_hit:
+ jsr clear_screen ; 7E64 20 0B 7D
+ lda #$00 ; 7E67 A9 00
+ sta line_buffer_index ; 7E69 8D 4A 7F
+ sta BUFCNT ; 7E6C 85 6B
+ jmp get_line ; 7E6E 4C 04 7E
+
+backs_key_hit:
+ jsr print_space ; 7E71 20 A4 7E
+ lda BUFCNT ; 7E74 A5 6B
+ beq backs_key_done ; 7E76 F0 14
+ dec COLCRS ; 7E78 C6 55
+ lda COLCRS ; 7E7A A5 55
+ clc ; 7E7C 18
+ adc #$01 ; 7E7D 69 01
+ cmp LMARGN ; 7E7F C5 52
+ bne backs_same_line ; 7E81 D0 07
+ lda right_margin ; 7E83 AD 00 7C
+ sta COLCRS ; 7E86 85 55
+ dec ROWCRS ; 7E88 C6 54
+
+backs_same_line:
+ dec BUFCNT ; 7E8A C6 6B
+
+backs_key_done:
+ jmp show_cursor ; 7E8C 4C 0B 7E
+
+; ----------------------------------------------------------------------------
+; Ring the margin bell. COL80 doesn't implement the ctrl-2 bell (character
+; 253), and instead of using the GTIA keyclick speaker, it uses POKEY to
+; make a beep
+
+beep: ldy #$00 ; 7E8F A0 00
+ ldx #$AF ; 7E91 A2 AF
+
+beep_delay_x:
+ stx AUDF1 ; 7E93 8E 00 D2
+ stx AUDC1 ; 7E96 8E 01 D2
+
+beep_delay_y:
+ dey ; 7E99 88
+ bne beep_delay_y ; 7E9A D0 FD
+ dex ; 7E9C CA
+ cpx #$9F ; 7E9D E0 9F
+ bne beep_delay_x ; 7E9F D0 F2
+ jmp show_cursor ; 7EA1 4C 0B 7E
+
+; ----------------------------------------------------------------------------
+; Print a space character at the current cursor position. Does not
+; update the cursor position.
+print_space:
+ lda #$00 ; 7EA4 A9 00
+ sta inverse_mask ; 7EA6 8D 49 7F
+ lda #$20 ; 7EA9 A9 20
+ sta TMPCHR ; 7EAB 85 50
+ jsr setup_font_ptr ; 7EAD 20 C9 7C
+ jsr setup_screen_ptr ; 7EB0 20 34 7D
+ jsr write_font_data ; 7EB3 20 82 7D
+ rts ; 7EB6 60
+
+; ----------------------------------------------------------------------------
+; Get a keystroke (blocking). Just calls the OS K: get-one-byte routine
+; (call by pushing address-minus-one then doing an RTS)
+get_keystroke:
+ lda k_dev_get_hi ; 7EB7 AD 25 E4
+ pha ; 7EBA 48
+ lda k_dev_get_lo ; 7EBB AD 24 E4
+ pha ; 7EBE 48
+ rts ; 7EBF 60
+
+; ----------------------------------------------------------------------------
+; Initialization callback. The OS will call this on coldstart (or would do,
+; if the driver were in ROM), and also on warmstart (because we stole the
+; DOSINI vector).
+; This routine is also the first thing that gets called by the mainline
+; init code. Its job is to install COL80 in the handler table at HATABS.
+; Actually the handler is first installed as X:, then the main init code
+; fixes this up to E: unless the user is holding down SELECT. This allows
+; the user to toggle between the 40-column ROM E: and COL80 without doing
+; a full reboot. No idea if this was a documented feature or something the
+; author used for development/debugging.
+
+col80_init:
+ ldy #$00 ; 7EC0 A0 00
+
+next_hatab_slot:
+ lda HATABS,y ; 7EC2 B9 1A 03
+ beq register_x_handler ; 7EC5 F0 0A
+ iny ; 7EC7 C8
+ iny ; 7EC8 C8
+ iny ; 7EC9 C8
+ cpy #$20 ; 7ECA C0 20
+ bcc next_hatab_slot ; 7ECC 90 F4
+ jmp return_success ; 7ECE 4C 31 7D
+
+register_x_handler:
+ lda #$58 ; 7ED1 A9 58
+ sta HATABS,y ; 7ED3 99 1A 03
+ lda #<col80_vector_tab ; 7ED6 A9 E5
+ iny ; 7ED8 C8
+ sta HATABS,y ; 7ED9 99 1A 03
+ lda #>col80_vector_tab ; 7EDC A9 7E
+ iny ; 7EDE C8
+ sta HATABS,y ; 7EDF 99 1A 03
+ jmp return_success ; 7EE2 4C 31 7D
+
+; ----------------------------------------------------------------------------
+; COL80 vector table, in the format required by the OS. Our HATABS entry
+; will point to this table, and the OS will call the routines listed here
+; via the "call by RTS" method (which is why they're address-minus-one).
+
+; See the entry on HATABS in "Mapping the Atari" or the OS manual.
+
+col80_vector_tab:
+ .word col80_open-1 ; 7EE5 00 7C
+ .word col80_close-1 ; 7EE7 3F 7C
+ .word col80_getbyte-1 ; 7EE9 F1 7D
+ .word col80_putbyte-1 ; 7EEB 42 7C
+ .word col80_close-1 ; 7EED 3F 7C
+ .word col80_close-1 ; 7EEF 3F 7C
+ jmp col80_init ; 7EF1 4C C0 7E
+
+; ----------------------------------------------------------------------------
+; The OS jumps here on warmstart (also, this is the run address in our
+; binary load file)
+
+dosini_entry_point:
+ nop ; 7EF4 EA
+ nop ; 7EF5 EA
+ nop ; 7EF6 EA
+
+main_entry_point:
+ jsr col80_init ; 7EF7 20 C0 7E
+ lda CONSOL ; 7EFA AD 1F D0
+ and #$04 ; 7EFD 29 04
+ beq no_e_handler ; 7EFF F0 2F
+ lda #$0C ; 7F01 A9 0C
+ sta ICCOM ; 7F03 8D 42 03
+ ldx #$00 ; 7F06 A2 00
+ jsr CIOV ; 7F08 20 56 E4
+ lda #$58 ; 7F0B A9 58
+ sta font_ptr_lo ; 7F0D 85 CD
+ lda #$03 ; 7F0F A9 03
+ sta ICCOM ; 7F11 8D 42 03
+ lda #$CD ; 7F14 A9 CD
+ sta ICBAL ; 7F16 8D 44 03
+ lda #$00 ; 7F19 A9 00
+ sta ICBAH ; 7F1B 8D 45 03
+ ldx #$00 ; 7F1E A2 00
+ jsr CIOV ; 7F20 20 56 E4
+ ldy #$07 ; 7F23 A0 07
+ lda #<col80_vector_tab ; 7F25 A9 E5
+ sta HATABS,y ; 7F27 99 1A 03
+ lda #>col80_vector_tab ; 7F2A A9 7E
+ iny ; 7F2C C8
+ sta HATABS,y ; 7F2D 99 1A 03
+no_e_handler:
+ lda #<START_ADDRESS ; 7F30 A9 00
+ sta MEMTOP ; 7F32 8D E5 02
+ lda #>START_ADDRESS ; 7F35 A9 7A
+ sta MEMTOP+1 ; 7F37 8D E6 02
+ jmp return_success ; 7F3A 4C 31 7D
+
+; ----------------------------------------------------------------------------
+; (when does this actually get called? da65 can't find any references
+; to it, and it's not a run or init address in the binary load file)
+ lda #<dosini_entry_point ; 7F3D A9 F4
+ sta DOSINI ; 7F3F 85 0C
+ lda #>dosini_entry_point ; 7F41 A9 7E
+ sta DOSINI+1 ; 7F43 85 0D
+ jmp main_entry_point ; 7F45 4C F7 7E
+
+; ----------------------------------------------------------------------------
+; Various bits of runtime state here. It's unclear to me why the standard
+; OS buffer location couldn't have been used instead (normally the top
+; half of page 5), or why the other stuff couldn't have been stored in
+; zero page, in locations used by the ROM E: handler (thus unused when
+; it's replaced with COL80). line_buffer_index needs to be preserved
+; across calls to col80_getbyte, but lo_nybble_flag and inverse_mask are
+; freshly calculated every time they're used, so they could be almost
+; anywhere.
+
+lo_nybble_flag:
+ .byte $00 ; 7F48 00
+
+inverse_mask:
+ .byte $00 ; 7F49 00
+
+line_buffer_index:
+ .byte $12 ; 7F4A 12
+
+; ----------------------------------------------------------------------------
+; There's absolutely no reason why this data needs to be included in the
+; binary load file: the line buffer's initial contents are meaningless, they
+; will be blown away the first time anything reads from the E: device.
+
+; Notice the author was running his debugger in COL80 when he built the
+; binary (ASCII "S COL80 7A00 7F80" command still in the buffer).
+
+line_buffer:
+ .byte $53,$20,$43,$4F,$4C,$38,$30,$20 ; 7F4B
+ .byte $37,$41,$30,$30,$20,$37,$46,$38 ; 7F53
+ .byte $30,$9B,$20,$20,$20,$20,$9B,$27 ; 7F5B
+ .byte $40,$40,$40,$40,$28,$28,$28,$28 ; 7F63
+ .byte $40,$40,$40,$40,$40,$40,$40,$40 ; 7F6B
+ .byte $40,$40,$40,$40,$40,$40,$40,$40 ; 7F73
+ .byte $9B,$FD,$FD,$FD,$FD,$9B ; 7F7B
+
+END_ADDRESS = *-1
+
+; I've found a variant (modified version?) of this code, that doesn't
+; include the line_buffer in the file (no reason for it to be there),
+; or the $0C segment, and that has another segment, loaded at $6000,
+; with the run address changed to $6000. The code looks like:
+
+; .org $6000
+; jsr dosini_entry_point
+; lda #$50
+; sta RMARGN
+; lda #$00
+; sta COLOR2
+
+; also, the default colors have been changed in init_graphics_8.
+
+; There are at least two binaries floating around that contain
+; extra (garbage) bytes at the end, presumably from being transferred
+; over XMODEM or similar. They are otherwise identical.
+
diff --git a/src/col80_modified/cruft/col80_main.xex b/src/col80_modified/cruft/col80_main.xex
new file mode 100644
index 0000000..90208c3
--- /dev/null
+++ b/src/col80_modified/cruft/col80_main.xex
Binary files differ
diff --git a/src/col80_modified/cruft/col80_orig.xex b/src/col80_modified/cruft/col80_orig.xex
new file mode 100644
index 0000000..f5f9548
--- /dev/null
+++ b/src/col80_modified/cruft/col80_orig.xex
Binary files differ
diff --git a/src/col80_modified/cruft/col80_runad_seg.s b/src/col80_modified/cruft/col80_runad_seg.s
new file mode 100644
index 0000000..234d621
--- /dev/null
+++ b/src/col80_modified/cruft/col80_runad_seg.s
@@ -0,0 +1,13 @@
+
+; Third segment is the run address
+
+;.ifdef FUJICHAT
+;INITAD = $02E2
+; .word INITAD
+; .word INITAD+1
+; .word dosini_entry_point
+;.else
+ .word RUNAD
+ .word RUNAD+1
+ .word dosini_entry_point
+;.endif
diff --git a/src/col80_modified/cruft/col80_startaddr.s b/src/col80_modified/cruft/col80_startaddr.s
new file mode 100644
index 0000000..d88203b
--- /dev/null
+++ b/src/col80_modified/cruft/col80_startaddr.s
@@ -0,0 +1,7 @@
+
+ .ifdef FUJICHAT
+START_ADDRESS = $9C01 ; subtract $0800 (2048) if using BASIC or other cart
+;START_ADDRESS = $7A00
+ .else
+START_ADDRESS = $7A00
+ .endif
diff --git a/src/col80_modified/cruft/col80_startup.s b/src/col80_modified/cruft/col80_startup.s
new file mode 100644
index 0000000..b170a3c
--- /dev/null
+++ b/src/col80_modified/cruft/col80_startup.s
@@ -0,0 +1,4 @@
+
+ .include "col80_include.s"
+ .include "col80_init.s"
+ .include "col80_entry.s"
diff --git a/src/col80_modified/cruft/dasm2atasm b/src/col80_modified/cruft/dasm2atasm
new file mode 100755
index 0000000..b7ebe66
--- /dev/null
+++ b/src/col80_modified/cruft/dasm2atasm
@@ -0,0 +1,362 @@
+#!/usr/bin/perl -w
+
+=head1 NAME
+
+dasm2atasm - converts 6502 assembly in DASM syntax to ATASM (or MAC/65) format.
+
+=head1 SYNOPSIS
+
+ dasm2atasm mycode.asm
+
+Writes output to I<mycode.m65>
+
+ dasm2atasm stuff.asm other.m65
+
+Reads from I<stuff.asm>, writes to I<other.m65>
+
+=head1 DESCRIPTION
+
+B<dasm2atasm> tries its best to convert DASM's syntax into something
+that B<ATASM> can use. Since B<ATASM>'s syntax is 99% compatible with
+that of B<MAC/65>, B<dasm2atasm> can be used for that as well.
+
+=head1 CAVEATS
+
+There are a few B<DASM> directives that aren't quite supported by
+B<ATASM>.
+
+=over 4
+
+=item echo
+
+In B<DASM> syntax, I<echo> can interpolate values, like so:
+
+ echo $100-*, " bytes of zero page left"
+
+B<ATASM>'s closest equivalent to I<echo> is I<.warn>, but it doesn't
+allow multiple arguments or interpolation. For now, B<dasm2atasm> just
+comments out the line with the I<echo> directive.
+
+=item seg and seg.u
+
+B<ATASM> just plain doesn't support segments. These directives will
+just be commented out. This I<shouldn't> have any effect on the
+object code.
+
+=item sta.w, sty.w, stx.w
+
+B<ATASM> doesn't provide a way to force word addressing, when the operand
+of a store instruction will allow zero page addressing to be used. You'll
+run into this a lot in Atari 2600 code, or any other 6502 code that has to
+maintain sync with an external piece of hardware (using word addressing
+causes the 6502 to use an extra CPU cycle, which is the only way to cause
+a 1-cycle delay).
+
+For now, we're just converting any I<st?.w> instructions to the appropriate
+I<.byte> directives, like so:
+
+ ;;;;; dasm2atasm: was `sta.w COLUPF', using .byte to generate opcode
+ .byte $8d, COLUPF, $00
+
+This works fine if I<COLUPF> is a zero-page label. It's possible, though
+unlikely, that you'll run across code where the programmer has used I<sta.w>
+with a label that would already cause absolute word addressing to be used,
+in which case the extra I<$00> will break our code (literally: I<$00> is
+the I<BRK> instruction!)
+
+This isn't likely to be fixed by I<dasm2atasm>. The correct fix will be to
+support I<sta.w> and friends in B<ATASM> itself, which may happen in the
+future.
+
+=item . (dot)
+
+B<DASM> allows the use of I<.> or I<*> to represent the current program counter
+in expressions. B<ATASM> only allows I<*>, and unless I want to include a
+full expression-parser in B<dasm2atasm>, I can't reliably translate this.
+
+For now, you'll have to fix this yourself. Future versions will at least
+make an attempt, but this one doesn't.
+
+=back
+
+=head1 AUTHOR
+
+B. Watson I<< <urchlay@urchlay.com> >>. Comments & constructive criticism
+welcome, or just a friendly `hello'. Spam will be redirected to /dev/null
+and so will the spammer's entire domain.
+
+=cut
+
+sub usage {
+ print <<EOF;
+Usage: $0 -[aclmr] infile.asm [outfile.m65]
+
+EOF
+ exit 1;
+}
+
+sub get_mac_sub {
+ my $rex = shift;
+ my $code = "sub { s/($rex)/\\U\$1/gio };";
+ #warn "code is $code";
+ return eval "$code";
+}
+
+sub unhex {
+ # makes a proper $xx, $xx, $xx list of bytes
+ # from a list of hex digits, spaces optional.
+ my $bytes = shift;
+ my $ret = "";
+
+ $bytes =~ s/\s//g;
+
+ #warn "unhex: bytes is $bytes";
+
+ for($bytes =~ /(..)/g) {
+ #warn "unhex: found $_";
+ $ret .= "\$$_, ";
+ }
+
+ chop $ret;
+ chop $ret;
+
+ return $ret;
+}
+
+sub fix_include {
+ my $inc = shift;
+ my $old = $inc;
+ $inc =~ s/\.(\w+)("?)$/.m65$2/;
+
+ if($recursive) {
+ system("$cmd $old $inc");
+ } else {
+ warn "Don't forget to convert included file `$old' to .m65 format!\n";
+ }
+ return $inc;
+}
+
+sub do_subs {
+ # Do the dirty work of the substitutions. Only reason we have this
+ # as a subroutine of its own is for profiling purposes (and we do
+ # spend a *lot* of time here!)
+ my $line = shift;
+
+ for($line) {
+ s/^(\@?\w+):/$1/; # no colons after labels, in atasm
+ s/%/~/g; # binary constant
+ s/!=/<>/g; # inequality
+
+ s/^(\s+)\.?echo(.*)/;;;;;$1.warn$2/i &&
+ do { warn "$in, line $.:\n\t`.warn' not fully compatible with dasm's `echo', commented out\n" }
+ && next;
+
+ # This is supposed to change e.g. `bpl .label' to `bpl @label'
+ s/^(\s+)([a-z]{3})(\s+)\.(\w+)/$1$2$3\@$4/i
+ && next;
+
+
+ s/{(\d)}/%$1/g; # macro arg (gotta do this *after* bin. constants!)
+
+# atasm doesn't support shifts, emulate with multiply/divide
+ s/\s*<<\s*(\d+)/"*" . 2**$1/eg;
+ s/\s*>>\s*(\d+)/"\/" . 2**$1/eg;
+
+# atasm chokes sometimes when there's whitespace around an operator
+# unfortunately, a construct like `bne *-1' can't afford to lose the
+# space before the *... why, oh why, does * have to be both multiply and
+# program counter? *sigh*
+
+# s/\s*([-!|\/+*&])\s*/$1/g;
+
+# ARGH. Why does dasm allow `byte #1, #2, #3'... and why do people *use* it?!
+ s/^(\s+)\.?byte(\s+)/$1.byte$2/i && do { s/#//g } && next;
+ s/^(\s+)\.?word(\s+)/$1.word$2/i && do { s/#//g } && next;
+ s/^(\s+)\.?dc\.w(\s+)/$1.word$2/i && do { s/#//g } && next;
+ s/^(\s+)\.?dc(?:\.b)?(\s+)/$1.byte$2/i && do { s/#//g } && next;
+
+# 20070529 bkw: turn ".DS foo" into ".DC foo 0"
+ s/^(\s+)\.?ds(\s+)(\S+)/$1.dc $3 0 /i && do { s/#//g } && next;
+
+# I really want to add `hex' to atasm. 'til then though, fake with .byte
+ s/^(\s+)\.?hex\s+(.*)/$1 . '.byte ' .
+ unhex($2)/ie && next;
+
+ s/^(\s+)\.?subroutine(.*)/$1.local$2/i && next;
+ s/^(\s+)\.?include(\s+)(.*)/$1 . '.include' . $2 . fix_include($3)/gie
+ && next;
+ s/^(\s+)\.?equ\b/$1=/i && next;
+ s/^(\s+)\.?repeat\b/$1.rept/i && next;
+ s/^(\s+)\.?repend\b/$1.endr/i && next;
+ s/^(\s+)\.?endm\b/$1.endm/i && next;
+ s/^(\s+)\.?org(\s+)([^,]*).*$/$1*=$2$3/i && next;
+ s/^(\s+)\.?incbin\b/$1\.incbin/i && next;
+ s/^(\s+)\.?err(.*)/$1.error$2/i && next; # TODO: see if atasm allows `.error' with no message.
+ s/^(\s+)\.?ifconst\s+(.*)/$1.if .def $2/i
+ && next; # TODO: test this!
+ s/^(\s+)\.?else/$1.else/i && next;
+ s/^(\s+)\.?endif/$1.endif/i && next;
+ s/^(\s+)\.?if\s+(.*)/$1.if $2/i && next;
+
+ # stuff that doesn't work:
+ s/^(\s+)(\.?seg(\..)?\s.*)/;;;;; dasm2atasm: `seg' not supported by atasm\n;;;;;$1$2/i
+ && next;
+ s/^(\s+)(\.?processor\s.*)/;;;;; dasm2atasm: `processor' not supported by atasm\n;;;;;$1$2/i
+ && next;
+
+ s/^(\s+)sta\.w(\s+)(.*)/;;;;; dasm2atasm: was `sta.w $3', using .byte to generate opcode\n$1.byte \$8d, <$3, >$3/i
+ && next;
+
+ s/^(\s+)stx\.w(\s+)(.*)/;;;;; dasm2atasm: was `stx.w $3', using .byte to generate opcode\n$1.byte \$8e, <$3, >$3/i
+ && next;
+
+ s/^(\s+)sta\.w(\s+)(.*)/;;;;; dasm2atasm: was `sty.w $3', using .byte to generate opcode\n$1.byte \$8c, <$3, >$3/i
+ && next;
+
+ # atasm lacks `align', so make up for it with a macro
+ if(s/(\s)\.?align(\s+)(.*)/$1ALIGN$2$3/i) {
+ if(!$align_defined) { # only gotta define it if not already defined.
+ for($align_macro) {
+ $_ =~ s/^/($linenum += 10) . " "/gme if $linenum;
+ $_ =~ s/\n/\x9b/g if $a8eol;
+ }
+
+ print OUT $align_macro; # no, I wouldn't use these globals in a CS class assignment.
+ $align_defined++;
+ }
+ next;
+ }
+
+ # macros. This is by far the biggest pain in the ass yet.
+ s/(\s)\.?mac\b/$1.macro/i;
+ if(/(\s)\.macro(\s+)(\w+)/) {
+ $mac_regex .= "|\\b$3\\b";
+ $mac_sub = get_mac_sub($mac_regex);
+ }
+
+ if(ref $mac_sub) { # if we've found at least one macro so far...
+ &$mac_sub; # CAPITALIZE everything matching a macro name
+ } # note: this code assumes macros are *always* defined before they're
+ # used. atasm requires this, but does dasm?
+
+ }
+ return $line;
+}
+
+## main() ##
+
+$ca65 = 0;
+$a8eol = 0;
+$linenum = 0;
+$recursive = 0;
+
+$cmd = $0;
+
+while($ARGV[0] =~ /^-/i) {
+ my $opt = shift;
+ $cmd .= " $opt";
+
+ if($opt eq "-c") {
+ $ca65++;
+ } elsif($opt eq "-a") {
+ $a8eol++;
+ } elsif($opt eq "-l") {
+ $linenum = 1000;
+ } elsif($opt eq "-m") {
+ $a8eol++;
+ $linenum = 1000;
+ } elsif($opt eq "-r") {
+ $recursive++;
+ } elsif($opt eq "--") {
+ last;
+ } else {
+ warn "Unknown option '$opt'\n";
+ usage;
+ }
+}
+
+if($ca65 && ($linenum || $a8eol)) {
+ die "Can't use line numbers and/or Atari EOLs with ca65 output\n";
+}
+
+$align_macro = <<EOF;
+;;;;;; ALIGN macro defined by dasm2atasm
+ .macro ALIGN
+ *= [[*/%1]+1] * %1
+ .endm
+EOF
+
+$align_defined = 0; # we only need to emit the macro definition once.
+
+$in = shift || usage;
+$out = shift;
+
+($out = $in) =~ s/(\.\w+)?$/.m65/ unless $out;
+
+die "$0: can't use $in for both input and output\n" if $out eq $in;
+
+open IN, "<$in" or die "Can't read $in: $!\n";
+open OUT, ">$out" or die "Can't write to $out: $!\n";
+
+$hdr = <<EOF;
+;;; Converted from DASM syntax with command:
+; $cmd $in $out
+
+EOF
+
+for($hdr) {
+ $_ =~ s/^/($linenum += 10) . " "/gme if $linenum;
+ $_ =~ s/\n/\x9b/g if $a8eol;
+}
+
+print OUT $hdr;
+
+if($ca65) {
+ print OUT <<EOF;
+;;; ca65 features enabled by dasm2atasm
+; To build with ca65:
+; ca65 -o foo.o -t none foo.asm
+; ld65 -o foo.bin -t none foo.o
+.FEATURE pc_assignment
+.FEATURE labels_without_colons
+
+EOF
+}
+
+$mac_regex = "!THIS_ISNT_SUPPOSED_TO_MATCH";
+$mac_sub = ""; # this will be the code ref we call to match $mac_regex
+
+while(<IN>) {
+ chomp;
+ s/\r//; # you might not want this on dos/win, not sure if it matters.
+ $label = "";
+
+ if(/^(\w+)\s*=\s*\1/i) {
+ print OUT ";;;;; dasm2atasm: labels are case-insensitive in atasm\n";
+ $line = ";;;;; $_ ; This assignment is an error in atasm";
+ next;
+ }
+
+# do this before we split out the label:
+ s/^\./\@/; # local label (dot in dasm, @ in atasm)
+
+ if(s/^([^:;\s]*):?(\s+)/$2/) {
+ $label = $1;
+ }
+
+ ($line, $comment) = split /;/, $_, 2;
+ next unless $line;
+
+ $line = do_subs($line);
+
+} continue {
+ if($linenum) {
+ print OUT "$linenum ";
+ $linenum += 10;
+ }
+
+ print OUT $label if $label;
+ print OUT $line if $line;
+ print OUT ";$comment" if $comment;
+ print OUT ($a8eol ? "\x9b" : "\n");
+}
diff --git a/src/col80_modified/cruft/dos_20s.atr b/src/col80_modified/cruft/dos_20s.atr
new file mode 100755
index 0000000..8016b73
--- /dev/null
+++ b/src/col80_modified/cruft/dos_20s.atr
Binary files differ
diff --git a/src/col80_modified/cruft/font.bin b/src/col80_modified/cruft/font.bin
new file mode 100644
index 0000000..d2fd3d4
--- /dev/null
+++ b/src/col80_modified/cruft/font.bin
Binary files differ
diff --git a/src/col80_modified/cruft/font.s b/src/col80_modified/cruft/font.s
new file mode 100644
index 0000000..78266ea
--- /dev/null
+++ b/src/col80_modified/cruft/font.s
@@ -0,0 +1,54 @@
+ .org 1000
+ ; Space ! " # etc (codes 32-63)
+ .byte $00,$04,$04,$04,$04,$00,$04,$00
+ .byte $00,$A0,$AA,$AE,$0A,$0E,$0A,$00
+ .byte $00,$40,$68,$82,$44,$28,$C2,$40
+ .byte $00,$C4,$64,$E4,$60,$C0,$40,$00
+ .byte $00,$44,$82,$82,$82,$82,$82,$44
+ .byte $00,$04,$A4,$4E,$E4,$44,$A0,$00
+ .byte $00,$00,$00,$0E,$00,$40,$40,$80
+ .byte $00,$02,$02,$04,$04,$08,$48,$00
+ .byte $00,$E4,$AC,$A4,$A4,$A4,$EE,$00
+ .byte $00,$EE,$22,$22,$EE,$82,$EE,$00
+ .byte $00,$AE,$A8,$AE,$E2,$22,$2E,$00
+ .byte $00,$EE,$82,$E2,$A4,$A4,$E4,$00
+ .byte $00,$EE,$AA,$EA,$AE,$A2,$EE,$00
+ .byte $00,$00,$00,$44,$00,$44,$04,$08
+ .byte $00,$20,$4E,$80,$4E,$20,$00,$00
+ .byte $00,$8C,$42,$22,$44,$80,$04,$00
+
+ ; @ A B C etc (codes 64-95)
+ .byte $00,$6E,$9A,$BA,$BE,$8A,$6A,$00
+ .byte $00,$C6,$A8,$C8,$A8,$A8,$C6,$00
+ .byte $00,$CE,$A8,$AC,$A8,$A8,$CE,$00
+ .byte $00,$E6,$88,$C8,$8A,$8A,$86,$00
+ .byte $00,$AE,$A4,$E4,$A4,$A4,$AE,$00
+ .byte $00,$2A,$2A,$2C,$2A,$2A,$CA,$00
+ .byte $00,$8A,$8E,$8E,$8A,$8A,$EA,$00
+ .byte $00,$C4,$AA,$AA,$AA,$AA,$A4,$00
+ .byte $00,$EE,$AA,$EA,$8A,$8A,$8E,$03
+ .byte $00,$C6,$A8,$AC,$C2,$A2,$AC,$00
+ .byte $00,$EA,$4A,$4A,$4A,$4A,$4E,$00
+ .byte $00,$AA,$AA,$AA,$AE,$AE,$4A,$00
+ .byte $00,$AA,$4A,$4E,$44,$44,$A4,$00
+ .byte $00,$EE,$28,$48,$88,$88,$E8,$0E
+ .byte $00,$8E,$82,$42,$42,$22,$22,$0E
+ .byte $00,$00,$40,$A0,$00,$00,$00,$0F
+
+ ; diamond, lowercase letters, control codes (codes 96-127)
+ .byte $00,$00,$00,$46,$E2,$4E,$0E,$00
+ .byte $00,$80,$80,$C6,$A8,$A8,$C6,$00
+ .byte $00,$20,$20,$6E,$AE,$A8,$6E,$00
+ .byte $00,$00,$C0,$86,$CA,$8E,$82,$0C
+ .byte $00,$80,$84,$80,$C4,$A4,$A4,$00
+ .byte $00,$08,$28,$0A,$2C,$2A,$2A,$C0
+ .byte $00,$40,$40,$4A,$4E,$4A,$4A,$00
+ .byte $00,$00,$00,$CE,$AA,$AA,$AE,$00
+ .byte $00,$00,$00,$C6,$AA,$C6,$82,$82
+ .byte $00,$00,$00,$6E,$88,$86,$8E,$00
+ .byte $00,$00,$40,$EA,$4A,$4A,$6E,$00
+ .byte $00,$00,$00,$AA,$AA,$AE,$4A,$00
+ .byte $00,$00,$00,$AA,$4A,$A6,$A2,$0C
+ .byte $00,$00,$04,$EE,$4E,$84,$EE,$00
+ .byte $40,$4E,$4C,$4E,$4A,$42,$42,$40
+ .byte $00,$28,$6C,$EE,$6C,$28,$00,$00
diff --git a/src/col80_modified/cruft/font2xbm.pl b/src/col80_modified/cruft/font2xbm.pl
new file mode 100644
index 0000000..3337139
--- /dev/null
+++ b/src/col80_modified/cruft/font2xbm.pl
@@ -0,0 +1,47 @@
+#!/usr/bin/perl -w
+
+use bytes;
+
+$name = "xbm";
+$width = 8;
+$height = 384;
+$cwidth = $width / 8;
+$cheight = $height / 8;
+
+print <<EOF;
+#define ${name}_width ${width}
+#define ${name}_height ${height}
+static unsigned char ${name}_bits[] = {
+EOF
+
+undef $/;
+$_ = <>;
+@inbytes = split "";
+
+# reverse bits, print 12 bytes/line
+
+$c = 0;
+for($i=0; $i<@inbytes; $i++) {
+ $byte = ord $inbytes[$i];
+ if(!$c) {
+ print " ";
+ }
+
+ printf "0x%02x", reverse_bits($byte);
+ if($i != $#inbytes) {
+ if($c == 12) {
+ print ",\n";
+ $c = 0;
+ } else {
+ print ", ";
+ $c++;
+ }
+ }
+}
+
+print " };\n";
+
+sub reverse_bits {
+ my $bitstr = reverse sprintf("%08b", $_[0]);
+ return eval "0b$bitstr";
+}
diff --git a/src/col80_modified/cruft/new_font.s b/src/col80_modified/cruft/new_font.s
new file mode 100644
index 0000000..f70ae8b
--- /dev/null
+++ b/src/col80_modified/cruft/new_font.s
@@ -0,0 +1,48 @@
+ .byte $00,$04,$04,$04,$04,$00,$04,$00
+ .byte $00,$A0,$AA,$AE,$0A,$0E,$0A,$00
+ .byte $00,$40,$68,$82,$44,$28,$C2,$40
+ .byte $00,$44,$E4,$84,$60,$80,$E0,$40
+ .byte $00,$44,$82,$82,$82,$82,$82,$44
+ .byte $00,$00,$A4,$44,$EE,$44,$A4,$00
+ .byte $00,$00,$00,$0E,$00,$40,$40,$80
+ .byte $00,$02,$02,$04,$04,$08,$48,$00
+ .byte $00,$E4,$AC,$A4,$A4,$A4,$EE,$00
+ .byte $00,$EE,$22,$22,$EE,$82,$EE,$00
+ .byte $00,$AE,$A8,$AE,$E2,$22,$2E,$00
+ .byte $00,$EE,$82,$E2,$A4,$A4,$E4,$00
+ .byte $00,$EE,$AA,$EA,$AE,$A2,$EE,$00
+ .byte $00,$00,$00,$44,$00,$44,$04,$08
+ .byte $00,$20,$4E,$80,$4E,$20,$00,$00
+ .byte $00,$8C,$42,$22,$44,$80,$04,$00
+ .byte $00,$6E,$9A,$BA,$BE,$8A,$6A,$00
+ .byte $00,$C6,$A8,$C8,$A8,$A8,$C6,$00
+ .byte $00,$CE,$A8,$AC,$A8,$A8,$CE,$00
+ .byte $00,$E6,$88,$C8,$8A,$8A,$86,$00
+ .byte $00,$AE,$A4,$E4,$A4,$A4,$AE,$00
+ .byte $00,$2A,$2A,$2C,$2A,$2A,$CA,$00
+ .byte $00,$8A,$8E,$8E,$8A,$8A,$EA,$00
+ .byte $00,$C4,$AA,$AA,$AA,$AA,$A4,$00
+ .byte $00,$EE,$AA,$EA,$8A,$8A,$8E,$03
+ .byte $00,$C6,$A8,$AC,$C2,$A2,$AC,$00
+ .byte $00,$EA,$4A,$4A,$4A,$4A,$4E,$00
+ .byte $00,$AA,$AA,$AA,$AE,$AE,$4A,$00
+ .byte $00,$AA,$4A,$4E,$44,$44,$A4,$00
+ .byte $00,$EE,$28,$48,$88,$88,$E8,$0E
+ .byte $00,$8E,$82,$42,$42,$22,$22,$0E
+ .byte $00,$00,$40,$A0,$00,$00,$00,$0F
+ .byte $00,$00,$0C,$42,$E6,$4A,$0E,$00
+ .byte $00,$80,$80,$C6,$A8,$A8,$C6,$00
+ .byte $00,$20,$26,$6A,$AE,$A8,$6E,$00
+ .byte $00,$00,$C0,$86,$CA,$8E,$82,$0C
+ .byte $00,$80,$84,$80,$C4,$A4,$A4,$00
+ .byte $00,$08,$28,$0A,$2C,$2A,$2A,$C0
+ .byte $00,$40,$40,$4A,$4E,$4A,$4A,$00
+ .byte $00,$00,$00,$CE,$AA,$AA,$AE,$00
+ .byte $00,$00,$00,$C6,$AA,$C6,$82,$83
+ .byte $00,$00,$00,$6E,$88,$86,$8E,$00
+ .byte $00,$00,$40,$EA,$4A,$4A,$6E,$00
+ .byte $00,$00,$00,$AA,$AA,$AE,$4A,$00
+ .byte $00,$00,$00,$AA,$4A,$A6,$A2,$0C
+ .byte $00,$06,$04,$E4,$48,$84,$E4,$06
+ .byte $40,$4C,$44,$44,$42,$44,$44,$4C
+ .byte $00,$08,$5C,$AE,$0C,$08,$00,$00
diff --git a/src/col80_modified/cruft/new_font.xbm b/src/col80_modified/cruft/new_font.xbm
new file mode 100644
index 0000000..a7fab38
--- /dev/null
+++ b/src/col80_modified/cruft/new_font.xbm
@@ -0,0 +1,35 @@
+#define font_width 8
+#define font_height 384
+static unsigned char font_bits[] = {
+ 0x00, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00, 0x05, 0x55, 0x75,
+ 0x50, 0x70, 0x50, 0x00, 0x00, 0x02, 0x16, 0x41, 0x22, 0x14, 0x43, 0x02,
+ 0x00, 0x22, 0x27, 0x21, 0x06, 0x01, 0x07, 0x02, 0x00, 0x22, 0x41, 0x41,
+ 0x41, 0x41, 0x41, 0x22, 0x00, 0x00, 0x25, 0x22, 0x77, 0x22, 0x25, 0x00,
+ 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, 0x02, 0x01, 0x00, 0x40, 0x40, 0x20,
+ 0x20, 0x10, 0x12, 0x00, 0x00, 0x27, 0x35, 0x25, 0x25, 0x25, 0x77, 0x00,
+ 0x00, 0x77, 0x44, 0x44, 0x77, 0x41, 0x77, 0x00, 0x00, 0x75, 0x15, 0x75,
+ 0x47, 0x44, 0x74, 0x00, 0x00, 0x77, 0x41, 0x47, 0x25, 0x25, 0x27, 0x00,
+ 0x00, 0x77, 0x55, 0x57, 0x75, 0x45, 0x77, 0x00, 0x00, 0x00, 0x00, 0x22,
+ 0x00, 0x22, 0x20, 0x10, 0x00, 0x04, 0x72, 0x01, 0x72, 0x04, 0x00, 0x00,
+ 0x00, 0x31, 0x42, 0x44, 0x22, 0x01, 0x20, 0x00, 0x00, 0x76, 0x59, 0x5d,
+ 0x7d, 0x51, 0x56, 0x00, 0x00, 0x63, 0x15, 0x13, 0x15, 0x15, 0x63, 0x00,
+ 0x00, 0x73, 0x15, 0x35, 0x15, 0x15, 0x73, 0x00, 0x00, 0x67, 0x11, 0x13,
+ 0x51, 0x51, 0x61, 0x00, 0x00, 0x75, 0x25, 0x27, 0x25, 0x25, 0x75, 0x00,
+ 0x00, 0x54, 0x54, 0x34, 0x54, 0x54, 0x53, 0x00, 0x00, 0x51, 0x71, 0x71,
+ 0x51, 0x51, 0x57, 0x00, 0x00, 0x23, 0x55, 0x55, 0x55, 0x55, 0x25, 0x00,
+ 0x00, 0x77, 0x55, 0x57, 0x51, 0x51, 0x71, 0xc0, 0x00, 0x63, 0x15, 0x35,
+ 0x43, 0x45, 0x35, 0x00, 0x00, 0x57, 0x52, 0x52, 0x52, 0x52, 0x72, 0x00,
+ 0x00, 0x55, 0x55, 0x55, 0x75, 0x75, 0x52, 0x00, 0x00, 0x55, 0x52, 0x72,
+ 0x22, 0x22, 0x25, 0x00, 0x00, 0x77, 0x14, 0x12, 0x11, 0x11, 0x17, 0x70,
+ 0x00, 0x71, 0x41, 0x42, 0x42, 0x44, 0x44, 0x70, 0x00, 0x00, 0x02, 0x05,
+ 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x30, 0x42, 0x67, 0x52, 0x70, 0x00,
+ 0x00, 0x01, 0x01, 0x63, 0x15, 0x15, 0x63, 0x00, 0x00, 0x04, 0x64, 0x56,
+ 0x75, 0x15, 0x76, 0x00, 0x00, 0x00, 0x03, 0x61, 0x53, 0x71, 0x41, 0x30,
+ 0x00, 0x01, 0x21, 0x01, 0x23, 0x25, 0x25, 0x00, 0x00, 0x10, 0x14, 0x50,
+ 0x34, 0x54, 0x54, 0x03, 0x00, 0x02, 0x02, 0x52, 0x72, 0x52, 0x52, 0x00,
+ 0x00, 0x00, 0x00, 0x73, 0x55, 0x55, 0x75, 0x00, 0x00, 0x00, 0x00, 0x63,
+ 0x55, 0x63, 0x41, 0xc1, 0x00, 0x00, 0x00, 0x76, 0x11, 0x61, 0x71, 0x00,
+ 0x00, 0x00, 0x02, 0x57, 0x52, 0x52, 0x76, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x55, 0x75, 0x52, 0x00, 0x00, 0x00, 0x00, 0x55, 0x52, 0x65, 0x45, 0x30,
+ 0x00, 0x60, 0x20, 0x27, 0x12, 0x21, 0x27, 0x60, 0x02, 0x32, 0x22, 0x22,
+ 0x42, 0x22, 0x22, 0x32, 0x00, 0x10, 0x3a, 0x75, 0x30, 0x10, 0x00, 0x00 };
diff --git a/src/col80_modified/cruft/test.atr b/src/col80_modified/cruft/test.atr
new file mode 100755
index 0000000..0127b33
--- /dev/null
+++ b/src/col80_modified/cruft/test.atr
Binary files differ
diff --git a/src/col80_modified/cruft/xbm2font.pl b/src/col80_modified/cruft/xbm2font.pl
new file mode 100644
index 0000000..758d57e
--- /dev/null
+++ b/src/col80_modified/cruft/xbm2font.pl
@@ -0,0 +1,29 @@
+#!/usr/bin/perl -w
+
+use bytes;
+
+$c = 0;
+
+while(<>) {
+ next unless @bytes = (/0x([0-9a-fA-F]{2})/g);
+ for(@bytes) {
+ if(!($c % 8)) {
+ print " .byte ";
+ }
+
+ printf "\$%02X", reverse_bits(hex $_);
+
+ if(($c % 8 == 7) || ($c == $#bytes)) {
+ print "\n";
+ $c = 0;
+ } else {
+ print ",";
+ $c++;
+ }
+ }
+}
+
+sub reverse_bits {
+ my $bitstr = reverse sprintf("%08b", $_[0]);
+ return eval "0b$bitstr";
+}
diff --git a/src/col80_modified/dos_20s.atr b/src/col80_modified/dos_20s.atr
new file mode 100755
index 0000000..8016b73
--- /dev/null
+++ b/src/col80_modified/dos_20s.atr
Binary files differ
diff --git a/src/col80_modified/font2xbm.pl b/src/col80_modified/font2xbm.pl
new file mode 100644
index 0000000..c0ec3be
--- /dev/null
+++ b/src/col80_modified/font2xbm.pl
@@ -0,0 +1,48 @@
+#!/usr/bin/perl -w
+
+use bytes;
+
+$name = "xbm";
+$width = 8;
+$height = 384;
+#$height = 512;
+$cwidth = $width / 8;
+$cheight = $height / 8;
+
+print <<EOF;
+#define ${name}_width ${width}
+#define ${name}_height ${height}
+static unsigned char ${name}_bits[] = {
+EOF
+
+undef $/;
+$_ = <>;
+@inbytes = split "";
+
+# reverse bits, print 12 bytes/line
+
+$c = 0;
+for($i=0; $i<@inbytes; $i++) {
+ $byte = ord $inbytes[$i];
+ if(!$c) {
+ print " ";
+ }
+
+ printf "0x%02x", reverse_bits($byte);
+ if($i != $#inbytes) {
+ if($c == 12) {
+ print ",\n";
+ $c = 0;
+ } else {
+ print ", ";
+ $c++;
+ }
+ }
+}
+
+print " };\n";
+
+sub reverse_bits {
+ my $bitstr = reverse sprintf("%08b", $_[0]);
+ return eval "0b$bitstr";
+}
diff --git a/src/col80_modified/icet.xbm b/src/col80_modified/icet.xbm
new file mode 100644
index 0000000..946753b
--- /dev/null
+++ b/src/col80_modified/icet.xbm
@@ -0,0 +1,43 @@
+#define xbm_width 8
+#define xbm_height 512
+static unsigned char xbm_bits[] = {
+ 0x00, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00, 0x55, 0x75, 0x50, 0x70,
+ 0x50, 0x00, 0x00, 0x02, 0x16, 0x41, 0x22, 0x14, 0x43, 0x02, 0x00, 0x00, 0x42,
+ 0x25, 0x02, 0x05, 0x02, 0x04, 0x00, 0x00, 0x14, 0x22, 0x22, 0x22, 0x22, 0x14,
+ 0x00, 0x00, 0x25, 0x22, 0x77, 0x22, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+ 0x00, 0x02, 0x02, 0x01, 0x00, 0x40, 0x40, 0x20, 0x20, 0x12, 0x12, 0x00, 0x00,
+ 0x22, 0x35, 0x25, 0x25, 0x25, 0x72, 0x00, 0x00, 0x32, 0x45, 0x34, 0x42, 0x41,
+ 0x37, 0x00, 0x00, 0x75, 0x15, 0x35, 0x46, 0x44, 0x34, 0x00, 0x00, 0x72, 0x41,
+ 0x23, 0x25, 0x15, 0x12, 0x00, 0x00, 0x22, 0x55, 0x52, 0x65, 0x45, 0x22, 0x00,
+ 0x00, 0x00, 0x22, 0x00, 0x20, 0x22, 0x10, 0x00, 0x00, 0x04, 0x72, 0x01, 0x72,
+ 0x04, 0x00, 0x00, 0x00, 0x21, 0x52, 0x44, 0x22, 0x01, 0x20, 0x00, 0x00, 0x22,
+ 0x57, 0x57, 0x75, 0x51, 0x56, 0x00, 0x00, 0x63, 0x15, 0x13, 0x15, 0x15, 0x67,
+ 0x00, 0x00, 0x73, 0x15, 0x75, 0x15, 0x15, 0x73, 0x00, 0x00, 0x67, 0x11, 0x17,
+ 0x51, 0x51, 0x61, 0x00, 0x00, 0x75, 0x25, 0x27, 0x25, 0x25, 0x75, 0x00, 0x00,
+ 0x56, 0x54, 0x34, 0x54, 0x55, 0x52, 0x00, 0x00, 0x51, 0x71, 0x51, 0x51, 0x51,
+ 0x57, 0x00, 0x00, 0x74, 0x55, 0x57, 0x57, 0x55, 0x71, 0x00, 0x00, 0x73, 0x55,
+ 0x55, 0x53, 0x71, 0x41, 0x00, 0x00, 0x63, 0x15, 0x23, 0x45, 0x45, 0x35, 0x00,
+ 0x00, 0x57, 0x52, 0x52, 0x52, 0x52, 0x72, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55,
+ 0x72, 0x52, 0x00, 0x00, 0x55, 0x55, 0x52, 0x22, 0x25, 0x25, 0x00, 0x00, 0x67,
+ 0x24, 0x22, 0x21, 0x21, 0x67, 0x00, 0x00, 0x31, 0x21, 0x22, 0x22, 0x24, 0x34,
+ 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x70, 0x00, 0x25, 0x2a, 0x25, 0xea,
+ 0x25, 0x2a, 0x25, 0x2a, 0x28, 0x28, 0x28, 0x38, 0x08, 0x08, 0x08, 0x08, 0x02,
+ 0x02, 0x02, 0x33, 0x22, 0x22, 0x22, 0x22, 0x00, 0x22, 0x52, 0x27, 0x07, 0x02,
+ 0x02, 0x00, 0x00, 0x42, 0x27, 0x12, 0x20, 0x47, 0x70, 0x00, 0x00, 0x01, 0xf2,
+ 0x54, 0x52, 0x51, 0x57, 0x00, 0x00, 0x24, 0x37, 0x22, 0x77, 0x21, 0x70, 0x00,
+ 0xf0, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xe0, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xff, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00,
+ 0x00, 0x0f, 0x00, 0xf0, 0x00, 0x00, 0x01, 0x01, 0x01, 0xf1, 0x21, 0x21, 0x21,
+ 0x21, 0x02, 0x02, 0x02, 0x0f, 0x00, 0x00, 0x00, 0xf0, 0xa2, 0xd2, 0xf2, 0xde,
+ 0x00, 0x10, 0x10, 0x50, 0x00, 0x00, 0x18, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x08, 0x4c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x34, 0x40, 0x70, 0x50,
+ 0x70, 0x00, 0x00, 0x01, 0x61, 0x13, 0x15, 0x15, 0x63, 0x00, 0x00, 0x04, 0x24,
+ 0x56, 0x75, 0x15, 0x66, 0x00, 0x00, 0x06, 0x61, 0x57, 0x51, 0x61, 0x41, 0x30,
+ 0x00, 0x21, 0x01, 0x33, 0x25, 0x25, 0x65, 0x00, 0x00, 0x14, 0x10, 0x54, 0x34,
+ 0x54, 0x54, 0x03, 0x00, 0x03, 0x52, 0x72, 0x52, 0x52, 0x56, 0x00, 0x00, 0x00,
+ 0x23, 0x55, 0x55, 0x55, 0x25, 0x00, 0x00, 0x00, 0x63, 0x55, 0x55, 0x63, 0x41,
+ 0x41, 0x00, 0x00, 0x66, 0x11, 0x21, 0x41, 0x31, 0x00, 0x00, 0x02, 0x57, 0x52,
+ 0x52, 0x52, 0x76, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x72, 0x52, 0x00, 0x00,
+ 0x00, 0x55, 0x55, 0x52, 0x65, 0x45, 0x30, 0x00, 0x60, 0x27, 0x14, 0x22, 0x21,
+ 0x67, 0x00, 0x02, 0x32, 0x22, 0x42, 0x22, 0x22, 0x32, 0x02, 0x0f, 0x2f, 0x2f,
+ 0x2f, 0x2f, 0x2f, 0x2f, 0x0f };
diff --git a/src/col80_modified/icet_packed.fnt b/src/col80_modified/icet_packed.fnt
new file mode 100644
index 0000000..2b599b8
--- /dev/null
+++ b/src/col80_modified/icet_packed.fnt
Binary files differ
diff --git a/src/col80_modified/icet_to_col80 b/src/col80_modified/icet_to_col80
new file mode 100755
index 0000000..9dac02c
--- /dev/null
+++ b/src/col80_modified/icet_to_col80
Binary files differ
diff --git a/src/col80_modified/icet_to_col80.c b/src/col80_modified/icet_to_col80.c
new file mode 100644
index 0000000..aa07223
--- /dev/null
+++ b/src/col80_modified/icet_to_col80.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+
+int main(int argc, char **argv) {
+ int c, d, byte = 0;
+ char out[8];
+
+ do {
+ c = getchar();
+ if(byte == 16) {
+ for(byte = 0; byte < 8; ++byte)
+ putchar(out[byte]);
+
+ byte = 0;
+ }
+
+ if(c != EOF) {
+ if(byte < 8) {
+ out[byte] = (c & 0xf0);
+ ++byte;
+ } else if(byte < 16) {
+ out[byte - 8] |= (c & 0x0f);
+ ++byte;
+ }
+ }
+ } while(c != EOF);
+}
diff --git a/src/col80_modified/icet_vt.fnt b/src/col80_modified/icet_vt.fnt
new file mode 100644
index 0000000..7c29cd1
--- /dev/null
+++ b/src/col80_modified/icet_vt.fnt
Binary files differ
diff --git a/src/col80_modified/icetmod.raw b/src/col80_modified/icetmod.raw
new file mode 100644
index 0000000..59e1331
--- /dev/null
+++ b/src/col80_modified/icetmod.raw
Binary files differ
diff --git a/src/col80_modified/icetmod.s b/src/col80_modified/icetmod.s
new file mode 100644
index 0000000..0c11274
--- /dev/null
+++ b/src/col80_modified/icetmod.s
@@ -0,0 +1,48 @@
+ .byte $00,$02,$02,$02,$02,$00,$02,$00
+ .byte $00,$55,$57,$05,$07,$05,$00,$00
+ .byte $20,$34,$41,$22,$14,$61,$20,$00
+ .byte $20,$31,$42,$30,$40,$30,$20,$00
+ .byte $00,$14,$22,$22,$22,$22,$14,$00
+ .byte $00,$52,$22,$77,$22,$52,$00,$00
+ .byte $00,$00,$00,$07,$00,$20,$20,$40
+ .byte $00,$01,$01,$02,$02,$24,$24,$00
+ .byte $00,$22,$56,$52,$52,$52,$27,$00
+ .byte $00,$26,$51,$16,$21,$41,$76,$00
+ .byte $00,$57,$54,$56,$31,$11,$16,$00
+ .byte $00,$27,$41,$62,$52,$54,$24,$00
+ .byte $00,$22,$55,$25,$53,$51,$22,$00
+ .byte $00,$00,$22,$00,$02,$22,$04,$00
+ .byte $00,$10,$27,$40,$27,$10,$00,$00
+ .byte $00,$42,$25,$11,$22,$40,$02,$00
+ .byte $00,$22,$75,$75,$57,$45,$35,$00
+ .byte $00,$63,$54,$64,$54,$54,$73,$00
+ .byte $00,$67,$54,$57,$54,$54,$67,$00
+ .byte $00,$73,$44,$74,$45,$45,$43,$00
+ .byte $00,$57,$52,$72,$52,$52,$57,$00
+ .byte $00,$35,$15,$16,$15,$55,$25,$00
+ .byte $00,$4A,$4F,$4F,$49,$49,$79,$00
+ .byte $00,$67,$55,$55,$55,$55,$57,$00
+ .byte $00,$67,$55,$55,$65,$47,$41,$00
+ .byte $00,$63,$54,$62,$51,$51,$56,$00
+ .byte $00,$75,$25,$25,$25,$25,$27,$00
+ .byte $00,$59,$59,$59,$5F,$2F,$2A,$00
+ .byte $00,$55,$55,$25,$22,$52,$52,$00
+ .byte $00,$73,$12,$22,$42,$42,$73,$00
+ .byte $00,$46,$42,$22,$22,$12,$16,$00
+ .byte $00,$20,$50,$00,$00,$00,$07,$00
+ .byte $00,$20,$16,$01,$07,$05,$07,$00
+ .byte $00,$40,$43,$64,$54,$54,$63,$00
+ .byte $00,$10,$12,$35,$57,$54,$33,$00
+ .byte $00,$30,$43,$75,$45,$43,$41,$06
+ .byte $00,$42,$40,$66,$52,$52,$53,$00
+ .byte $00,$14,$04,$15,$16,$15,$15,$60
+ .byte $00,$60,$25,$27,$25,$25,$35,$00
+ .byte $00,$00,$62,$55,$55,$55,$52,$00
+ .byte $00,$00,$63,$55,$55,$63,$41,$41
+ .byte $00,$00,$33,$44,$42,$41,$46,$00
+ .byte $00,$20,$75,$25,$25,$25,$37,$00
+ .byte $00,$00,$55,$55,$55,$27,$25,$00
+ .byte $00,$00,$55,$55,$25,$53,$51,$06
+ .byte $00,$03,$72,$14,$22,$42,$73,$00
+ .byte $20,$26,$22,$21,$22,$22,$26,$20
+ .byte $07,$01,$54,$A1,$04,$01,$04,$07
diff --git a/src/col80_modified/icetmod.xbm b/src/col80_modified/icetmod.xbm
new file mode 100644
index 0000000..fb61a13
--- /dev/null
+++ b/src/col80_modified/icetmod.xbm
@@ -0,0 +1,35 @@
+#define icetmod_width 8
+#define icetmod_height 384
+static unsigned char icetmod_bits[] = {
+ 0x00, 0x40, 0x40, 0x40, 0x40, 0x00, 0x40, 0x00, 0x00, 0xaa, 0xea, 0xa0,
+ 0xe0, 0xa0, 0x00, 0x00, 0x04, 0x2c, 0x82, 0x44, 0x28, 0x86, 0x04, 0x00,
+ 0x04, 0x8c, 0x42, 0x0c, 0x02, 0x0c, 0x04, 0x00, 0x00, 0x28, 0x44, 0x44,
+ 0x44, 0x44, 0x28, 0x00, 0x00, 0x4a, 0x44, 0xee, 0x44, 0x4a, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xe0, 0x00, 0x04, 0x04, 0x02, 0x00, 0x80, 0x80, 0x40,
+ 0x40, 0x24, 0x24, 0x00, 0x00, 0x44, 0x6a, 0x4a, 0x4a, 0x4a, 0xe4, 0x00,
+ 0x00, 0x64, 0x8a, 0x68, 0x84, 0x82, 0x6e, 0x00, 0x00, 0xea, 0x2a, 0x6a,
+ 0x8c, 0x88, 0x68, 0x00, 0x00, 0xe4, 0x82, 0x46, 0x4a, 0x2a, 0x24, 0x00,
+ 0x00, 0x44, 0xaa, 0xa4, 0xca, 0x8a, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00,
+ 0x40, 0x44, 0x20, 0x00, 0x00, 0x08, 0xe4, 0x02, 0xe4, 0x08, 0x00, 0x00,
+ 0x00, 0x42, 0xa4, 0x88, 0x44, 0x02, 0x40, 0x00, 0x00, 0x44, 0xae, 0xae,
+ 0xea, 0xa2, 0xac, 0x00, 0x00, 0xc6, 0x2a, 0x26, 0x2a, 0x2a, 0xce, 0x00,
+ 0x00, 0xe6, 0x2a, 0xea, 0x2a, 0x2a, 0xe6, 0x00, 0x00, 0xce, 0x22, 0x2e,
+ 0xa2, 0xa2, 0xc2, 0x00, 0x00, 0xea, 0x4a, 0x4e, 0x4a, 0x4a, 0xea, 0x00,
+ 0x00, 0xac, 0xa8, 0x68, 0xa8, 0xaa, 0xa4, 0x00, 0x00, 0x52, 0xf2, 0xf2,
+ 0x92, 0x92, 0x9e, 0x00, 0x00, 0xe6, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0x00,
+ 0x00, 0xe6, 0xaa, 0xaa, 0xa6, 0xe2, 0x82, 0x00, 0x00, 0xc6, 0x2a, 0x46,
+ 0x8a, 0x8a, 0x6a, 0x00, 0x00, 0xae, 0xa4, 0xa4, 0xa4, 0xa4, 0xe4, 0x00,
+ 0x00, 0x9a, 0x9a, 0x9a, 0xfa, 0xf4, 0x54, 0x00, 0x00, 0xaa, 0xaa, 0xa4,
+ 0x44, 0x4a, 0x4a, 0x00, 0x00, 0xce, 0x48, 0x44, 0x42, 0x42, 0xce, 0x00,
+ 0x00, 0x62, 0x42, 0x44, 0x44, 0x48, 0x68, 0x00, 0x00, 0x04, 0x0a, 0x00,
+ 0x00, 0x00, 0xe0, 0x00, 0x00, 0x04, 0x68, 0x80, 0xe0, 0xa0, 0xe0, 0x00,
+ 0x00, 0x02, 0xc2, 0x26, 0x2a, 0x2a, 0xc6, 0x00, 0x00, 0x08, 0x48, 0xac,
+ 0xea, 0x2a, 0xcc, 0x00, 0x00, 0x0c, 0xc2, 0xae, 0xa2, 0xc2, 0x82, 0x60,
+ 0x00, 0x42, 0x02, 0x66, 0x4a, 0x4a, 0xca, 0x00, 0x00, 0x28, 0x20, 0xa8,
+ 0x68, 0xa8, 0xa8, 0x06, 0x00, 0x06, 0xa4, 0xe4, 0xa4, 0xa4, 0xac, 0x00,
+ 0x00, 0x00, 0x46, 0xaa, 0xaa, 0xaa, 0x4a, 0x00, 0x00, 0x00, 0xc6, 0xaa,
+ 0xaa, 0xc6, 0x82, 0x82, 0x00, 0x00, 0xcc, 0x22, 0x42, 0x82, 0x62, 0x00,
+ 0x00, 0x04, 0xae, 0xa4, 0xa4, 0xa4, 0xec, 0x00, 0x00, 0x00, 0xaa, 0xaa,
+ 0xaa, 0xe4, 0xa4, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xa4, 0xca, 0x8a, 0x60,
+ 0x00, 0xc0, 0x4e, 0x28, 0x44, 0x42, 0xce, 0x00, 0x04, 0x64, 0x44, 0x84,
+ 0x44, 0x44, 0x64, 0x04, 0xe0, 0x80, 0x2a, 0x85, 0x20, 0x80, 0x20, 0xe0 };
diff --git a/src/col80_modified/icetmod_maybe.xbm b/src/col80_modified/icetmod_maybe.xbm
new file mode 100644
index 0000000..60bc84c
--- /dev/null
+++ b/src/col80_modified/icetmod_maybe.xbm
@@ -0,0 +1,35 @@
+#define icetmod_width 8
+#define icetmod_height 384
+static unsigned char icetmod_bits[] = {
+ 0x00, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00, 0x55, 0x75, 0x50,
+ 0x70, 0x50, 0x00, 0x00, 0x02, 0x16, 0x41, 0x22, 0x14, 0x43, 0x02, 0x00,
+ 0x02, 0x46, 0x21, 0x06, 0x01, 0x06, 0x02, 0x00, 0x00, 0x14, 0x22, 0x22,
+ 0x22, 0x22, 0x14, 0x00, 0x00, 0x25, 0x22, 0x77, 0x22, 0x25, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, 0x02, 0x01, 0x00, 0x40, 0x40, 0x20,
+ 0x20, 0x12, 0x12, 0x00, 0x00, 0x22, 0x35, 0x25, 0x25, 0x25, 0x72, 0x00,
+ 0x00, 0x32, 0x45, 0x34, 0x42, 0x41, 0x37, 0x00, 0x00, 0x75, 0x15, 0x35,
+ 0x46, 0x44, 0x34, 0x00, 0x00, 0x72, 0x41, 0x23, 0x25, 0x15, 0x12, 0x00,
+ 0x00, 0x22, 0x55, 0x52, 0x65, 0x45, 0x22, 0x00, 0x00, 0x00, 0x22, 0x00,
+ 0x20, 0x22, 0x10, 0x00, 0x00, 0x04, 0x72, 0x01, 0x72, 0x04, 0x00, 0x00,
+ 0x00, 0x21, 0x52, 0x44, 0x22, 0x01, 0x20, 0x00, 0x00, 0x22, 0x57, 0x57,
+ 0x75, 0x51, 0x56, 0x00, 0x00, 0x63, 0x15, 0x13, 0x15, 0x15, 0x67, 0x00,
+ 0x00, 0x73, 0x15, 0x75, 0x15, 0x15, 0x73, 0x00, 0x00, 0x67, 0x11, 0x17,
+ 0x51, 0x51, 0x61, 0x00, 0x00, 0x75, 0x25, 0x27, 0x25, 0x25, 0x75, 0x00,
+ 0x00, 0x56, 0x54, 0x34, 0x54, 0x55, 0x52, 0x00, 0x00, 0x51, 0x71, 0x51,
+ 0x51, 0x51, 0x57, 0x00, 0x00, 0x73, 0x55, 0x55, 0x55, 0x55, 0x75, 0x00,
+ 0x00, 0x73, 0x55, 0x55, 0x53, 0x71, 0x41, 0x00, 0x00, 0x63, 0x15, 0x23,
+ 0x45, 0x45, 0x35, 0x00, 0x00, 0x57, 0x52, 0x52, 0x52, 0x52, 0x72, 0x00,
+ 0x00, 0x55, 0x55, 0x55, 0x55, 0x72, 0x52, 0x00, 0x00, 0x55, 0x55, 0x52,
+ 0x22, 0x25, 0x25, 0x00, 0x00, 0x67, 0x24, 0x22, 0x21, 0x21, 0x67, 0x00,
+ 0x00, 0x31, 0x21, 0x22, 0x22, 0x24, 0x34, 0x00, 0x00, 0x02, 0x05, 0x00,
+ 0x00, 0x00, 0x70, 0x00, 0x00, 0x02, 0x34, 0x40, 0x70, 0x50, 0x70, 0x00,
+ 0x00, 0x01, 0x61, 0x13, 0x15, 0x15, 0x63, 0x00, 0x00, 0x04, 0x24, 0x56,
+ 0x75, 0x15, 0x66, 0x00, 0x00, 0x06, 0x61, 0x57, 0x51, 0x61, 0x41, 0x30,
+ 0x00, 0x21, 0x01, 0x33, 0x25, 0x25, 0x65, 0x00, 0x00, 0x14, 0x10, 0x54,
+ 0x34, 0x54, 0x54, 0x03, 0x00, 0x03, 0x52, 0x72, 0x52, 0x52, 0x56, 0x00,
+ 0x00, 0x00, 0x23, 0x55, 0x55, 0x55, 0x25, 0x00, 0x00, 0x00, 0x63, 0x55,
+ 0x55, 0x63, 0x41, 0x41, 0x00, 0x00, 0x66, 0x11, 0x21, 0x41, 0x31, 0x00,
+ 0x00, 0x02, 0x57, 0x52, 0x52, 0x52, 0x76, 0x00, 0x00, 0x00, 0x55, 0x55,
+ 0x55, 0x72, 0x52, 0x00, 0x00, 0x00, 0x55, 0x55, 0x52, 0x65, 0x45, 0x30,
+ 0x00, 0x60, 0x27, 0x14, 0x22, 0x21, 0x67, 0x00, 0x02, 0x32, 0x22, 0x42,
+ 0x22, 0x22, 0x32, 0x02, 0x00, 0x20, 0x2a, 0x25, 0x20, 0x20, 0x20, 0x00 };
diff --git a/src/col80_modified/icetmod_old.xbm b/src/col80_modified/icetmod_old.xbm
new file mode 100644
index 0000000..01fa394
--- /dev/null
+++ b/src/col80_modified/icetmod_old.xbm
@@ -0,0 +1,35 @@
+#define icetmod_width 8
+#define icetmod_height 384
+static unsigned char icetmod_bits[] = {
+ 0x00, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00, 0x55, 0x75, 0x50,
+ 0x70, 0x50, 0x00, 0x00, 0x02, 0x16, 0x41, 0x22, 0x14, 0x43, 0x02, 0x00,
+ 0x00, 0x42, 0x25, 0x02, 0x05, 0x02, 0x04, 0x00, 0x00, 0x14, 0x22, 0x22,
+ 0x22, 0x22, 0x14, 0x00, 0x00, 0x25, 0x22, 0x77, 0x22, 0x25, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x70, 0x00, 0x02, 0x02, 0x01, 0x00, 0x40, 0x40, 0x20,
+ 0x20, 0x12, 0x12, 0x00, 0x00, 0x22, 0x35, 0x25, 0x25, 0x25, 0x72, 0x00,
+ 0x00, 0x32, 0x45, 0x34, 0x42, 0x41, 0x37, 0x00, 0x00, 0x75, 0x15, 0x35,
+ 0x46, 0x44, 0x34, 0x00, 0x00, 0x72, 0x41, 0x23, 0x25, 0x15, 0x12, 0x00,
+ 0x00, 0x22, 0x55, 0x52, 0x65, 0x45, 0x22, 0x00, 0x00, 0x00, 0x22, 0x00,
+ 0x20, 0x22, 0x10, 0x00, 0x00, 0x04, 0x72, 0x01, 0x72, 0x04, 0x00, 0x00,
+ 0x00, 0x21, 0x52, 0x44, 0x22, 0x01, 0x20, 0x00, 0x00, 0x22, 0x57, 0x57,
+ 0x75, 0x51, 0x56, 0x00, 0x00, 0x63, 0x15, 0x13, 0x15, 0x15, 0x67, 0x00,
+ 0x00, 0x73, 0x15, 0x75, 0x15, 0x15, 0x73, 0x00, 0x00, 0x67, 0x11, 0x17,
+ 0x51, 0x51, 0x61, 0x00, 0x00, 0x75, 0x25, 0x27, 0x25, 0x25, 0x75, 0x00,
+ 0x00, 0x56, 0x54, 0x34, 0x54, 0x55, 0x52, 0x00, 0x00, 0x51, 0x71, 0x51,
+ 0x51, 0x51, 0x57, 0x00, 0x00, 0x74, 0x55, 0x57, 0x57, 0x55, 0x71, 0x00,
+ 0x00, 0x73, 0x55, 0x55, 0x53, 0x71, 0x41, 0x00, 0x00, 0x63, 0x15, 0x23,
+ 0x45, 0x45, 0x35, 0x00, 0x00, 0x57, 0x52, 0x52, 0x52, 0x52, 0x72, 0x00,
+ 0x00, 0x55, 0x55, 0x55, 0x55, 0x72, 0x52, 0x00, 0x00, 0x55, 0x55, 0x52,
+ 0x22, 0x25, 0x25, 0x00, 0x00, 0x67, 0x24, 0x22, 0x21, 0x21, 0x67, 0x00,
+ 0x00, 0x31, 0x21, 0x22, 0x22, 0x24, 0x34, 0x00, 0x00, 0x02, 0x05, 0x00,
+ 0x00, 0x00, 0x70, 0x00, 0x00, 0x02, 0x34, 0x40, 0x70, 0x50, 0x70, 0x00,
+ 0x00, 0x01, 0x61, 0x13, 0x15, 0x15, 0x63, 0x00, 0x00, 0x04, 0x24, 0x56,
+ 0x75, 0x15, 0x66, 0x00, 0x00, 0x06, 0x61, 0x57, 0x51, 0x61, 0x41, 0x30,
+ 0x00, 0x21, 0x01, 0x33, 0x25, 0x25, 0x65, 0x00, 0x00, 0x14, 0x10, 0x54,
+ 0x34, 0x54, 0x54, 0x03, 0x00, 0x03, 0x52, 0x72, 0x52, 0x52, 0x56, 0x00,
+ 0x00, 0x00, 0x23, 0x55, 0x55, 0x55, 0x25, 0x00, 0x00, 0x00, 0x63, 0x55,
+ 0x55, 0x63, 0x41, 0x41, 0x00, 0x00, 0x66, 0x11, 0x21, 0x41, 0x31, 0x00,
+ 0x00, 0x02, 0x57, 0x52, 0x52, 0x52, 0x76, 0x00, 0x00, 0x00, 0x55, 0x55,
+ 0x55, 0x72, 0x52, 0x00, 0x00, 0x00, 0x55, 0x55, 0x52, 0x65, 0x45, 0x30,
+ 0x00, 0x60, 0x27, 0x14, 0x22, 0x21, 0x67, 0x00, 0x02, 0x32, 0x22, 0x42,
+ 0x22, 0x22, 0x32, 0x02, 0x00, 0x20, 0x2a, 0x25, 0x20, 0x20, 0x20, 0x00 };
diff --git a/src/col80_modified/lsr.pl b/src/col80_modified/lsr.pl
new file mode 100644
index 0000000..915f769
--- /dev/null
+++ b/src/col80_modified/lsr.pl
@@ -0,0 +1,29 @@
+#!/usr/bin/perl -w
+
+use bytes;
+
+$c = 0;
+
+while(<>) {
+ next unless @bytes = (/0x([0-9a-fA-F]{2})/g);
+ for(@bytes) {
+ if(!($c % 8)) {
+ print " .byte ";
+ }
+
+ printf "\$%02X", (reverse_bits(hex $_) >> 1);
+
+ if(($c % 8 == 7) || ($c == $#bytes)) {
+ print "\n";
+ $c = 0;
+ } else {
+ print ",";
+ $c++;
+ }
+ }
+}
+
+sub reverse_bits {
+ my $bitstr = reverse sprintf("%08b", $_[0]);
+ return eval "0b$bitstr";
+}
diff --git a/src/col80_modified/new_font.s b/src/col80_modified/new_font.s
new file mode 100644
index 0000000..f4fcfa4
--- /dev/null
+++ b/src/col80_modified/new_font.s
@@ -0,0 +1,48 @@
+ .byte $00,$04,$04,$04,$04,$00,$04,$00
+ .byte $00,$AA,$AE,$0A,$0E,$0A,$00,$00
+ .byte $40,$68,$82,$44,$28,$C2,$40,$00
+ .byte $40,$62,$84,$60,$80,$60,$40,$00
+ .byte $00,$28,$44,$44,$44,$44,$28,$00
+ .byte $00,$A4,$44,$EE,$44,$A4,$00,$00
+ .byte $00,$00,$00,$0E,$00,$40,$40,$80
+ .byte $00,$02,$02,$04,$04,$48,$48,$00
+ .byte $00,$44,$AC,$A4,$A4,$A4,$4E,$00
+ .byte $00,$4C,$A2,$2C,$42,$82,$EC,$00
+ .byte $00,$AE,$A8,$AC,$62,$22,$2C,$00
+ .byte $00,$4E,$82,$C4,$A4,$A8,$48,$00
+ .byte $00,$44,$AA,$4A,$A6,$A2,$44,$00
+ .byte $00,$00,$44,$00,$04,$44,$08,$00
+ .byte $00,$20,$4E,$80,$4E,$20,$00,$00
+ .byte $00,$84,$4A,$22,$44,$80,$04,$00
+ .byte $00,$44,$EA,$EA,$AE,$8A,$6A,$00
+ .byte $00,$C6,$A8,$C8,$A8,$A8,$E6,$00
+ .byte $00,$CE,$A8,$AE,$A8,$A8,$CE,$00
+ .byte $00,$E6,$88,$E8,$8A,$8A,$86,$00
+ .byte $00,$AE,$A4,$E4,$A4,$A4,$AE,$00
+ .byte $00,$6A,$2A,$2C,$2A,$AA,$4A,$00
+ .byte $00,$8A,$8E,$8A,$8A,$8A,$EA,$00
+ .byte $00,$CE,$AA,$AA,$AA,$AA,$AE,$00
+ .byte $00,$CE,$AA,$AA,$CA,$8E,$82,$00
+ .byte $00,$C6,$A8,$C4,$A2,$A2,$AC,$00
+ .byte $00,$EA,$4A,$4A,$4A,$4A,$4E,$00
+ .byte $00,$AA,$AA,$AA,$AA,$4E,$4A,$00
+ .byte $00,$AA,$AA,$4A,$44,$A4,$A4,$00
+ .byte $00,$E6,$24,$44,$84,$84,$E6,$00
+ .byte $00,$8C,$84,$44,$44,$24,$2C,$00
+ .byte $00,$40,$A0,$00,$00,$00,$0E,$00
+ .byte $00,$40,$2C,$02,$0E,$0A,$0E,$00
+ .byte $00,$80,$86,$C8,$A8,$A8,$C6,$00
+ .byte $00,$20,$24,$6A,$AE,$A8,$66,$00
+ .byte $00,$60,$86,$EA,$8A,$86,$82,$0C
+ .byte $00,$84,$80,$CC,$A4,$A4,$A6,$00
+ .byte $00,$28,$08,$2A,$2C,$2A,$2A,$C0
+ .byte $00,$C0,$4A,$4E,$4A,$4A,$6A,$00
+ .byte $00,$00,$C4,$AA,$AA,$AA,$A4,$00
+ .byte $00,$00,$C6,$AA,$AA,$C6,$82,$82
+ .byte $00,$00,$66,$88,$84,$82,$8C,$00
+ .byte $00,$40,$EA,$4A,$4A,$4A,$6E,$00
+ .byte $00,$00,$AA,$AA,$AA,$4E,$4A,$00
+ .byte $00,$00,$AA,$AA,$4A,$A6,$A2,$0C
+ .byte $00,$06,$E4,$28,$44,$84,$E6,$00
+ .byte $40,$4C,$44,$42,$44,$44,$4C,$40
+ .byte $00,$04,$54,$A4,$04,$04,$04,$00
diff --git a/src/col80_modified/t.dasm b/src/col80_modified/t.dasm
new file mode 100644
index 0000000..e32d950
--- /dev/null
+++ b/src/col80_modified/t.dasm
@@ -0,0 +1,3 @@
+ .processor 6502
+ .org 0
+ .include icetmod.s
diff --git a/src/col80_modified/test.atr b/src/col80_modified/test.atr
new file mode 100755
index 0000000..57b2d13
--- /dev/null
+++ b/src/col80_modified/test.atr
Binary files differ
diff --git a/src/col80_modified/xbm2font.pl b/src/col80_modified/xbm2font.pl
new file mode 100644
index 0000000..758d57e
--- /dev/null
+++ b/src/col80_modified/xbm2font.pl
@@ -0,0 +1,29 @@
+#!/usr/bin/perl -w
+
+use bytes;
+
+$c = 0;
+
+while(<>) {
+ next unless @bytes = (/0x([0-9a-fA-F]{2})/g);
+ for(@bytes) {
+ if(!($c % 8)) {
+ print " .byte ";
+ }
+
+ printf "\$%02X", reverse_bits(hex $_);
+
+ if(($c % 8 == 7) || ($c == $#bytes)) {
+ print "\n";
+ $c = 0;
+ } else {
+ print ",";
+ $c++;
+ }
+ }
+}
+
+sub reverse_bits {
+ my $bitstr = reverse sprintf("%08b", $_[0]);
+ return eval "0b$bitstr";
+}
diff --git a/src/commands.c b/src/commands.c
new file mode 100644
index 0000000..001f384
--- /dev/null
+++ b/src/commands.c
@@ -0,0 +1,206 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <peekpoke.h>
+#include "fujichat.h"
+#include "features.h"
+#include "common.h"
+
+void cmd_join(void);
+void cmd_msg(void);
+void cmd_nick(void);
+void cmd_part(void);
+void cmd_ping(void);
+// void cmd_quit(void);
+void cmd_quote(void);
+void cmd_ver(void);
+void do_me(void);
+#ifdef FEAT_COLOR_COMMAND
+void cmd_fgcolor(void);
+void cmd_bgcolor(void);
+#endif
+
+fuji_cmd_t cmd_list[] = {
+ { "JOIN", ARGTYPE_OPT, cmd_join },
+ { "J", ARGTYPE_OPT, cmd_join },
+ { "MSG", ARGTYPE_REQUIRED, cmd_msg },
+ { "M", ARGTYPE_REQUIRED, cmd_msg },
+ { "NICK", ARGTYPE_REQUIRED, cmd_nick },
+ { "PART", ARGTYPE_NONE, cmd_part },
+ { "PING", ARGTYPE_REQUIRED, cmd_ping },
+ // { "QUIT", ARGTYPE_OPT, cmd_quit },
+ { "QUOTE", ARGTYPE_REQUIRED, cmd_quote },
+ { "VER", ARGTYPE_REQUIRED, cmd_ver },
+ { "VERSION", ARGTYPE_REQUIRED, cmd_ver },
+ { "ME", ARGTYPE_REQUIRED, do_me },
+#ifdef FEAT_COLOR_COMMAND
+ { "FGCOLOR", ARGTYPE_REQUIRED, cmd_fgcolor },
+ { "BGCOLOR", ARGTYPE_REQUIRED, cmd_bgcolor },
+#endif
+};
+
+#define CMD_LIST_SIZE (sizeof(cmd_list) / sizeof(fuji_cmd_t))
+
+char *cmd_arg;
+
+static void errmsg(char *msg) {
+ puts(msg);
+ bell();
+}
+
+static void err_missing_arg(void) {
+ errmsg("Command requires argument");
+}
+
+static void err_arg_not_allowed(void) {
+ errmsg("No argument allowed");
+}
+
+static void err_already_joined(void) {
+ errmsg("You are already in a channel (use /part to leave)");
+}
+
+
+void do_me(void) {
+ serv_msg_buf_len = sprintf(serv_msg_buf, "PRIVMSG %s :%cACTION %s%c%c",
+ channel, 1, cmd_arg, 1, NL);
+ send_serv_msg_buf();
+}
+
+void cmd_ver(void) {
+ serv_msg_buf_len = sprintf(serv_msg_buf, "PRIVMSG %s %cVERSION%c%c",
+ cmd_arg, 1, 1, NL);
+ send_serv_msg_buf();
+}
+
+void cmd_ping(void) {
+ serv_msg_buf_len = sprintf(serv_msg_buf, "PRIVMSG %s %cPING %03d %03d %03d%c%c",
+ cmd_arg, 1, PEEK(20), PEEK(19), PEEK(18), 1, NL);
+ send_serv_msg_buf();
+}
+
+void cmd_join(void) {
+ if(joined_channel) {
+ if(cmd_arg)
+ err_already_joined();
+ else
+ send_server_cmd("JOIN", channel);
+ } else {
+ if(cmd_arg) {
+ joined_channel = 1;
+ strcpy(channel, cmd_arg);
+ send_server_cmd("JOIN", cmd_arg);
+ } else {
+ err_missing_arg();
+ }
+ }
+}
+
+void cmd_part(void) {
+ joined_channel = 0;
+ send_server_cmd("PART", channel);
+}
+
+void cmd_msg(void) {
+ send_server_cmd("PRIVMSG", cmd_arg);
+}
+
+void cmd_quote(void) {
+ send_server_cmd(cmd_arg, NULL);
+}
+
+void cmd_nick(void) {
+ strcpy(config->nick, cmd_arg);
+ send_server_cmd("NICK", cmd_arg);
+ printf("> You are now known as %s\n", config->nick);
+}
+
+#ifdef FEAT_COLOR_COMMAND
+static void do_color(u16_t reg) {
+ u16_t c;
+
+ if(cmd_arg[0] >= '0' && cmd_arg[0] <= '9') {
+ c = atoi(cmd_arg);
+ if(c < 0x100) {
+ POKE(reg, c);
+ return;
+ }
+ }
+
+ puts("Bad color (range 0-255)");
+ bell();
+}
+
+void cmd_fgcolor(void) {
+ do_color(709);
+}
+
+void cmd_bgcolor(void) {
+ do_color(710);
+}
+
+#endif
+
+void handle_command(void) {
+ char i, *cend;
+ char *cmd = input_buf + 1;
+ char *p = cmd;
+
+ cmd_arg = NULL;
+
+ /* convert command word to uppercase */
+ while((*p != NL) && (*p != ' ')) {
+ *p = toupper(*p);
+ ++p;
+ }
+
+ cend = p;
+
+ /* set cmd_arg pointer, nul-terminate cmd_arg, if present */
+ /* (otherwise, cmd_arg remains NULL) */
+ if(*p != NL) {
+ cmd_arg = p;
+ /* skip extra whitespace */
+ while(*cmd_arg == ' ')
+ ++cmd_arg;
+ p = cmd_arg + 1;
+ while(*p && (*p != NL))
+ ++p;
+ *p = '\0';
+ }
+
+ /* nul-terminate cmd */
+ *cend = '\0';
+
+ for(i=0; i<CMD_LIST_SIZE; ++i) {
+ if(strcmp(cmd, cmd_list[i].cmd) != 0)
+ continue;
+
+ switch(cmd_list[i].arg_type) {
+ case ARGTYPE_REQUIRED:
+ if(!cmd_arg) {
+ err_missing_arg();
+ return;
+ }
+ break;
+
+ case ARGTYPE_NONE:
+ if(cmd_arg) {
+ err_arg_not_allowed();
+ return;
+ }
+ return;
+
+ default:
+ break;
+ }
+
+ (cmd_list[i].handler)();
+ return;
+ }
+
+ /* no idea what this is, send it as-is */
+ send_server_cmd(cmd, cmd_arg);
+}
diff --git a/src/common.c b/src/common.c
new file mode 100644
index 0000000..0a28871
--- /dev/null
+++ b/src/common.c
@@ -0,0 +1,255 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <rs232.h>
+#include "uip.h"
+#include "common.h"
+#include "aexec.h"
+#include "fujichat.h"
+
+int __fastcall__ (*atari_exec_p)(char *) = (int __fastcall__ (*)(char *))0x600;
+fuji_conf_t *config = (fuji_conf_t *)CONFIG_ADDRESS;
+
+void disable_break(void) {
+ asm("lda $10"); /* POKMSK */
+ asm("and #$7f");
+ asm("sta $10"); /* POKMSK */
+ asm("sta $D20E"); /* IRQEN */
+}
+
+/* easier to copy/paste this tiny function from uip.c
+ than it would be to rebuild all of uIP for use in
+ this program! Also don't want to bloat fujiconf by
+ linking uip.a, even if it would link without a
+ recompile. */
+/*
+u16_t local_htons(u16_t val) {
+ return HTONS(val);
+}
+*/
+
+/* this version's half the size */
+u16_t local_htons(u16_t val) {
+ __AX__ = val;
+ asm("sta tmp1");
+ asm("txa");
+ asm("ldx tmp1");
+}
+
+/* helper for fuji_cgetc */
+void __fastcall__ call_keybdv(void) {
+ asm("lda $E420+5"); /* KEYBDV */
+ asm("pha");
+ asm("lda $E420+4");
+ asm("pha");
+ asm("lda #12");
+ asm("sta $2A"); /* ICAX1Z */
+}
+
+/* replacement for cgetc() that doesn't include cursor enable/disable
+ stuff (otherwise copied from cc65's cgetc.s) */
+char __fastcall__ fuji_cgetc(void) {
+ asm("jsr _call_keybdv");
+ asm("ldx #0");
+}
+
+
+#if 0
+char get_config(void) {
+ char config_valid = 0;
+ FILE *f = fopen(DEFAULT_CONF_FILE, "rb");
+
+ puts("Loading config from " DEFAULT_CONF_FILE);
+
+ if(f) {
+ config_valid =
+ fread(config, 1, sizeof(fuji_conf_t), f) == sizeof(fuji_conf_t);
+ fclose(f);
+ if(!config_valid)
+ puts("Config file is wrong size");
+ } else {
+ puts("No config file found");
+ }
+
+ if(config_valid) {
+ if(!config_is_valid()) {
+ puts("Invalid or outdated config file");
+ config_valid = 0;
+ } else {
+ puts("Loaded OK");
+ }
+ }
+
+ return config_valid;
+}
+
+#else
+/* using open() read() close() instead of fopen() fread() fclose()
+ is a big win: save us 438 bytes! */
+char get_config(void) {
+ char config_valid = 0;
+ int f = open(DEFAULT_CONF_FILE, O_RDONLY);
+
+ puts("Loading config from " DEFAULT_CONF_FILE);
+
+ if(f >= 0) {
+ config_valid =
+ (read(f, config, sizeof(fuji_conf_t)) == sizeof(fuji_conf_t));
+ close(f);
+ if(!config_valid)
+ puts("Config file is wrong size");
+ } else {
+ puts("No config file found");
+ }
+
+ if(config_valid) {
+ if(!config_is_valid()) {
+ puts("Invalid or outdated config file");
+ config_valid = 0;
+ } else {
+ puts("Loaded OK");
+ }
+ }
+
+ return config_valid;
+}
+#endif
+
+char config_is_valid(void) {
+ // return( (memcmp(config->signature, CONF_SIGNATURE, 2) == 0) && (config->version == CONF_VERSION) );
+ return
+ *((char *)CONFIG_ADDRESS) == CONF_SIGNATURE_LO &&
+ *(char *)(CONFIG_ADDRESS+1) == CONF_SIGNATURE_HI &&
+ *(char *)(CONFIG_ADDRESS+2) == CONF_VERSION;
+}
+
+void set_default_config(void) {
+ puts("Using built-in defaults");
+ /*
+ // FIXME: why does this end up always 0.0.0.0 now?
+ // has something to do with macro expansion. What a mess.
+ uip_ipaddr(&(config->local_ip), 192,168,0,2);
+ uip_ipaddr(&(config->peer_ip), 192,168,0,1);
+ uip_ipaddr(&(config->resolver_ip), 192,168,0,1);
+ */
+
+ config->local_ip[0] = 0xa8c0;
+ config->local_ip[1] = 0x0200;
+
+ config->peer_ip[0] = 0xa8c0;
+ config->peer_ip[1] = 0x0100;
+
+ config->resolver_ip[0] = 0xa8c0;
+ config->resolver_ip[1] = 0x0100;
+
+ strcpy(config->server, "na.newnet.net");
+ strcpy(config->nick, DEFAULT_NICK);
+ strcpy(config->real_name, "FujiChat User");
+ config->server_port = 6667;
+ config->ui_flags = UIFLAG_HIDEMOTD;
+ config->bg_color = 0xc0; /* dark green */
+ config->fg_color = 0x0c;
+ config->baud = RS_BAUD_4800;
+
+ *(char *)(CONFIG_ADDRESS) = CONF_SIGNATURE_LO;
+ *(char *)(CONFIG_ADDRESS+1) = CONF_SIGNATURE_HI;
+ *(char *)(CONFIG_ADDRESS+2) = CONF_VERSION;
+
+ // config_valid = 1;
+}
+
+static char ipbuf[20];
+/*
+static char *fmt = "%d.%d.%d.%d";
+*/
+char * format_ip(uip_ipaddr_t *ip) {
+
+ u16_t *ipaddr = (u16_t *)ip;
+ sprintf(ipbuf, "%d.%d.%d.%d",
+ local_htons(ipaddr[0]) >> 8,
+ local_htons(ipaddr[0]) & 0xff,
+ local_htons(ipaddr[1]) >> 8,
+ local_htons(ipaddr[1]) & 0xff);
+
+ return ipbuf;
+
+ /*
+ asm(" sta ptr1");
+ asm(" stx ptr1+1");
+
+ asm(" lda #<_ipbuf");
+ asm(" ldx #>_ipbuf");
+ asm(" jsr pushax");
+
+ asm(" lda #<_fmt");
+ asm(" ldx #>_fmt");
+ asm(" jsr pushax");
+
+ asm(" ldy #0");
+ asm(" lda (ptr1),y");
+ asm(" jsr pusha0");
+
+ asm(" ldy #1");
+ asm(" lda (ptr1),y");
+ asm(" jsr pusha0");
+
+ asm(" ldy #2");
+ asm(" lda (ptr1),y");
+ asm(" jsr pusha0");
+
+ asm(" ldy #3");
+ asm(" lda (ptr1),y");
+ asm(" jsr pusha0");
+
+ asm(" ldy #$0c");
+ asm(" jsr _sprintf");
+
+ asm(" lda #<_ipbuf");
+ asm(" ldx #>_ipbuf");
+ */
+}
+
+void get_line(char *buf, unsigned char len) {
+ asm("ldy #$00");
+ asm("lda (sp),y");
+ asm("sta $e2");
+
+ asm("ldy #$02");
+ asm("jsr ldaxysp");
+ asm("sta $e0");
+ asm("stx $e0+1");
+
+ asm("@loop: lda _stdin");
+ asm("ldx _stdin+1");
+ asm("jsr _fgetc");
+
+ asm("cmp #$9B");
+ asm("beq @out");
+
+ asm("ldy #$00");
+ asm("sta ($e0),y");
+ asm("inc $e0");
+ asm("bne @noinc");
+ asm("inc $e0+1");
+ asm("@noinc:");
+
+ asm("dec $e2");
+ asm("bne @loop");
+
+ asm("@out:");
+ asm("ldy #$00");
+ asm("tya");
+ asm("sta ($e0),y");
+
+ /*
+ // C implementation is 80 bytes, asm is 50
+ fgets(buf, len, stdin);
+ while(*buf) {
+ if(*buf == '\n')
+ *buf = '\0';
+ ++buf;
+ }
+ */
+}
+
diff --git a/src/common.h b/src/common.h
new file mode 100644
index 0000000..c84b417
--- /dev/null
+++ b/src/common.h
@@ -0,0 +1,27 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+#include "fujichat.h"
+
+/* common functions, shared by fujichat.c and fujiconf.c.
+ Don't put anything here unless it really is shared! */
+
+/* This stays resident */
+extern fuji_conf_t *config;
+
+/* uIP-related */
+char * format_ip(uip_ipaddr_t *ip);
+u16_t local_htons(u16_t val);
+
+/* config-related */
+char get_config(void);
+char config_is_valid(void);
+void set_default_config(void);
+
+/* UI-related */
+char __fastcall__ fuji_cgetc(void);
+void __fastcall__ fuji_putchar(char); /* fujiput.s */
+void get_line(char *buf, unsigned char len);
+void disable_break(void);
+
+#endif
diff --git a/src/dns.c b/src/dns.c
new file mode 100644
index 0000000..f5eef0f
--- /dev/null
+++ b/src/dns.c
@@ -0,0 +1,130 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <atari.h>
+#include "uip.h"
+#include "uiplib.h"
+#include "rs232dev.h"
+#include <conio.h>
+#include <peekpoke.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "telnet.h"
+#include "resolv.h"
+#include "timer.h"
+
+#ifndef NULL
+#define NULL (void *)0
+#endif /* NULL */
+
+char buf[256];
+
+int main(void) {
+ char c;
+ int i;
+ uip_ipaddr_t ipaddr;
+ struct timer periodic_timer;
+
+ timer_set(&periodic_timer, CLOCK_SECOND / 2);
+
+ rs232dev_init();
+ uip_init();
+
+ uip_ipaddr(ipaddr, 192,168,0,2);
+ uip_sethostaddr(ipaddr);
+ uip_ipaddr(ipaddr, 192,168,0,1);
+ uip_setdraddr(ipaddr);
+ uip_ipaddr(ipaddr, 255,255,255,0);
+ uip_setnetmask(ipaddr);
+
+ resolv_init();
+ uip_ipaddr(ipaddr, 192,168,88,1);
+ resolv_conf(ipaddr);
+
+ cursor(1);
+
+ while(1) {
+ puts("DNS test. Hostname:");
+ fgets(buf, 256, stdin);
+ for(i=0; i<strlen(buf); ++i)
+ if(buf[i] == '\n') buf[i] = '\0';
+ printf("Trying to resolve host %s, press any key to stop\n", buf);
+ resolv_query(buf);
+
+ while(1) {
+ /* This part of the while loop is straight from the no-ARP example
+ code, from the uIP docs. */
+ uip_len = rs232dev_poll();
+ if(uip_len > 0) {
+ uip_input();
+ /* If the above function invocation resulted in data that
+ should be sent out on the network, the global variable
+ uip_len is set to a value > 0. */
+ if(uip_len > 0) {
+ rs232dev_send();
+ }
+ } else if(timer_expired(&periodic_timer)) {
+ timer_reset(&periodic_timer);
+ for(i = 0; i < UIP_CONNS; i++) {
+ uip_periodic(i);
+ /* If the above function invocation resulted in data that
+ should be sent out on the network, the global variable
+ uip_len is set to a value > 0. */
+ if(uip_len > 0) {
+ rs232dev_send();
+ }
+ }
+
+#if UIP_UDP
+ for(i = 0; i < UIP_UDP_CONNS; i++) {
+ uip_udp_periodic(i);
+ /* If the above function invocation resulted in data that
+ should be sent out on the network, the global variable
+ uip_len is set to a value > 0. */
+ if(uip_len > 0) {
+ rs232dev_send();
+ }
+ }
+#endif /* UIP_UDP */
+ }
+
+ if(kbhit()) {
+ cgetc();
+ break;
+ }
+ }
+ }
+}
+
+void telnet_connected(struct telnet_state *s) {
+}
+
+void telnet_closed(struct telnet_state *s) {
+}
+
+void telnet_sent(struct telnet_state *s) {
+}
+
+void telnet_aborted(struct telnet_state *s) {
+}
+
+void telnet_timedout(struct telnet_state *s) {
+}
+
+void telnet_newdata(struct telnet_state *s, char *data, u16_t len) {
+}
+
+void resolv_found(char *name, u16_t *ipaddr) {
+ if(ipaddr == NULL) {
+ printf("Host '%s' not found.\n", name);
+ } else {
+ printf("Found name '%s' = %d.%d.%d.%d\n", name,
+ htons(ipaddr[0]) >> 8,
+ htons(ipaddr[0]) & 0xff,
+ htons(ipaddr[1]) >> 8,
+ htons(ipaddr[1]) & 0xff);
+ puts("Press any key...");
+ // webclient_get("www.google.com", 80, "/index.html");
+ // webclient_get(name, 80, "/~adam/uip");
+ }
+}
diff --git a/src/dos25_4drives.atr b/src/dos25_4drives.atr
new file mode 100644
index 0000000..a032ec9
--- /dev/null
+++ b/src/dos25_4drives.atr
Binary files differ
diff --git a/src/dos_20s.atr b/src/dos_20s.atr
new file mode 100644
index 0000000..8016b73
--- /dev/null
+++ b/src/dos_20s.atr
Binary files differ
diff --git a/src/env.sh b/src/env.sh
new file mode 100644
index 0000000..0d1e50e
--- /dev/null
+++ b/src/env.sh
@@ -0,0 +1,10 @@
+# source this file to set up your environment for a snapshot of cc65
+# installed in a nonstandard place.
+
+CC65_PREFIX=/home/urchlay/cc65_snap
+
+PATH=$CC65_PREFIX/bin:$PATH
+CC65_INC=$CC65_PREFIX/lib/cc65/include
+CC65_LIB=$CC65_PREFIX/lib/cc65/lib
+
+export PATH CC65_INC CC65_LIB
diff --git a/src/equates.inc b/src/equates.inc
new file mode 100644
index 0000000..9759a8a
--- /dev/null
+++ b/src/equates.inc
@@ -0,0 +1,1386 @@
+;
+; ATARI 800 EQUATE LISTING
+;
+; (version 20070530_bkw)
+;
+; This is a heavily modified copy of Appendix A of the Atari System
+; Reference Manual (with much info added from Appendix B, and from
+; Mapping the Atari and other sources)
+;
+;
+;This listing is based on the original release of Operating System,
+;version A. The vectors shown here were not changed in version B.
+;New equates for XL and XE models are included and noted. Changes
+;from version B to XL/XE are also noted.
+;
+;Most of the equate names given below are the official Atari
+;names. They are in common use but are not mandatory.
+
+; This file can be included in your assembly source, but it's also
+; got a lot of useful human-readable comments. It's meant to serve as
+; a "quick reference" to Atari programmers, particularly ones who use
+; a cross-assembler on a UNIX-ish platform and a text editor that can
+; use "ctags":
+
+; $ ctags equates.inc
+; $ vim mystuff.dasm
+
+; While in vim, press ^] (control-right-bracket) while sitting on a label,
+; to jump to that label's definition in this file. (Also, you can type
+; :tag labelname). You can also do completion on the labels in vim by
+; typing part of a label and pressing ^N (or Tab, if you use the
+; CleverTab script from vimhelp.org)
+
+; GNU Emacs and XEmacs also support ctags, but I've never used them, so
+; I dunno how to do it. I do know that you need to use "Exuberant" ctags,
+; not the ctags that comes with emacs (which doesn't grok 6502 asm).
+
+; If you're using an Atari assembler instead of a cross-assembler, you
+; don't want to use this as-is: all the extra comments make it huge, and
+; it'll be either too large for the Atari's memory, or at least will take
+; a long time to assemble. You can make a comment-less, Atari-compatible
+; version like so:
+
+; perl -lne 's/;.*//; s/\s*$//; print if $_' < equates.inc > small.inc
+
+; ...then use a8eol to convert it to ATASCII format.
+
+; 20061028 bkw: Originally downloaded from:
+
+; http://atrey.karlin.mff.cuni.cz/~pavel/atari/atrb.html
+
+; ...and converted to DASM/ATASM/CA65 format. dasm, atasm, and ca65 use
+; similar enough syntax that this file can be used as-is with any of
+; them. Unfortunately, this means I can't do conditional assembly in this
+; file, since the two assemblers use different semantics... macros are
+; even less compatible :(
+
+; If you use ca65, you need this line in your source:
+
+;; .FEATURE labels_without_colons
+
+; before including this file, or else run ca65 with
+; "--feature labels_without_colons").
+
+; 20070529 bkw: updated, added missing GTIA/POKEY/ANTIC equates,
+; documented where the shadows are for those GTIA/POKEY/ANTIC/PIA
+; registers that have them. Also added a list of error messages and
+; explanation of the cassette buffer layout, and organized the C_*
+; CIO constants. Made minor modifications to get this file to assemble
+; with ATasm as well as DASM.
+
+; I have added a few missing equates: this file only
+; contained OS ROM locations when I got it.
+; I added a few from FMS/DOS as well (e.g. RUNAD and INITAD).
+
+; XL-specific locations in the original file were duplicate labels
+; (e.g. PTIMOT was defined as both $1C and $314), which keeps DASM
+; from being able to assemble the file. I prefixed the XL/XL versions
+; with "XL_"
+
+; Also, I've prefixed the CIO command and AUX1 constants with C_, since some
+; of them conflicted with other labels in the original version.
+
+; Areas listed as "unmapped" are literally not connected to anything.
+; Trying to read from unmapped address space results in reading whatever
+; garbage was on the data bus when the read happened. On my 1200XL, this
+; generally results in all 1's ($FF or 255).
+; In a 400, 600XL or other Atari with less than 48K of RAM, the missing
+; RAM address space is also unmapped.
+
+; Still TODO:
+; - Rest of the DOS/FMS equates
+; - Mark 800-ony locations with OSB_
+; - ifdef code, so the user can set the machine type (OSB or XL),
+; then refer to e.g. PTIMOT and get either OSB_PTIMOT or XL_PTIMOT
+; - Split into separate files? I'd rather not (it's only about 1000 lines)
+
+; This file's mostly intended for new development. It could also be
+; useful for porting old ASM/ED or Mac65 code to DASM, but such code
+; may need work... you can always assemble it with ATasm, in that case,
+; since it's 99.999% source code compatible with Mac65.
+
+; References to "APPENDIX C" and such are referring to the Atari System
+; Reference Manual, a version of which can be found at:
+
+; http://atrey.karlin.mff.cuni.cz/~pavel/atari/atrtblc.html
+
+; References to "Mapping" refer to "Mapping the Atari, Revised Edition",
+; which can be found at:
+
+; http://www.atariarchives.org/mapping/index.php
+
+; I've pasted a few quotes from Mapping into this file; I consider them
+; small enough to be covered under the "fair use" provisions of copyright law
+; (I am not a lawyer, though).
+
+;
+;
+; DEVICE NAMES
+;
+;
+;SCREDT = "E" SCREEN EDITOR
+;KBD = "K" KEYBOARD
+;DISPLY = "S" DISPLAY
+;PRINTR = "P" PRINTER
+;CASSET = "C" CASSETTE
+;DISK = "D" DISK DRIVE
+;
+;
+;
+; STATUS CODES
+;
+;
+
+; 20070529 bkw: These are returned as error codes, though various DOSes
+; also define their own codes (usually in the range 160-255).
+; Errors 2-21 are defined by BASIC.
+; Errors 150-154 are defined by the R: (850 or compatible, RS-232) handler.
+SUCCES = $01 ; 1
+BRKABT = $80 ; 128 BREAK KEY ABORT
+PRVOPN = $82 ; 130 IOCB ALREADY OPEN
+NONDEV = $82 ; 130 NONEXISTANT DEVICE
+WRONLY = $83 ; 131 OPENED FOR WRITE ONLY
+NVALID = $84 ; 132 INVALID COMMAND
+NOTOPN = $85 ; 133 DEVICE OR FILE NOT OPEN
+BADIOC = $86 ; 134 INVALID IOCB NUMBER
+RDONLY = $87 ; 135 OPENED FOR READ ONLY
+EOFERR = $88 ; 136 END OF FILE
+TRNRCD = $89 ; 137 TRUNCATED RECORD
+TIMOUT = $8A ; 138 PERIPHERAL TIME OUT
+DNACK = $8B ; 139 DEVICE DOES NOT ACKNOWLEDGE
+FRMERR = $8C ; 140 SERIAL BUS FRAMING ERROR
+CRSROR = $8D ; 141 CURSOR OUT OF RANGE
+OVRRUN = $8E ; 142 SERIAL BUS DATA OVERRUN
+CHKERR = $8F ; 143 SERIAL BUS CHECKSUM ERROR
+DERROR = $90 ; 144 PERIPHERAL DEVICE ERROR
+BADMOD = $91 ; 145 NON EXISTANT SCREEN MODE
+FNCNOT = $92 ; 146 FUNCTION NOT IMPLEMENTED
+SCRMEM = $93 ; 147 NOT ENOUGH MEMORY FOR SCREEN MODE
+
+; BASIC error codes (also used by e.g. Basic XL/XE and Turbo BASIC):
+;; 2: Insufficient Memory
+;; 3: Value Error
+;; 4: Too Many Variables
+;; 5: String Length Error
+;; 6: Out of Data Error
+;; 7: Number Greater than 32767
+;; 8: Input Statement Error
+;; 9: Array or String DIM Error
+;; 10: Argument Stack Overflow
+;; 11: Floating Point Overflow or Underflow Error
+;; 12: Line Not Found
+;; 13: No Matching FOR Statement
+;; 14: Line Too Long
+;; 15: GOSUB or FOR Line Deleted
+;; 16: RETURN Error
+;; 17: Garbage Error
+;; 18: Invalid String Character
+;; 19: LOAD Program Too Long
+;; 20: Bad Channel Number
+;; 21: LOAD File Error
+
+; 850/R: error codes:
+;; 150: Serial Port Already Open
+;; 151: Concurrent Mode Not Enabled
+;; 152: Illegal User-Supplied Buffer
+;; 153: Active Concurrent Mode Error
+;; 154: Concurrent Mode Not Active
+
+; DOS error codes (DOS 2.0S only; other DOSes may define other errors)
+;; 160: Device Number Error
+;; 161: Too Many OPEN Files
+;; 162: Disk Full
+;; 163: Fatal System Error
+;; 164: File Number Mismatch
+;; 165: Bad File Name
+;; 166: POINT Data Length Error
+;; 167: File Locked
+;; 168: Invalid XIO Command
+;; 169: Directory Full
+;; 170: File Not Found
+;; 171: POINT Invalid
+;; 172: DOS 1 File
+;; 173: Bad Sector
+;; 255: FORMATTING Error (DOS 2.5)
+
+;
+;
+;
+;
+; COMMAND CODES FOR CIO
+;
+;
+
+; Command byte goes in ICCOM,x
+
+;; General-purpose commands:
+C_OPEN = $03 ; 3 OPEN (BASIC OPEN)
+C_GETREC = $05 ; 5 GET RECORD
+C_GETCHR = $07 ; 7 GET BYTE
+C_PUTREC = $09 ; 9 WRITE RECORD
+C_PUTCHR = $0B ; 11 PUT-BYTE
+C_CLOSE = $0C ; 12
+C_STATUS = $0D ; 13
+C_SPECIL = $0E ; 14 BEGINNING OF SPECIAL COMMANDS (aka XIO)
+;; Commands for S: device:
+C_DRAWLN = $11 ; 17 SCREEN DRAW (BASIC DRAWTO)
+C_FILLIN = $12 ; 18 SCREEN FILL
+;; Commands for D: device (only when DOS is loaded):
+C_RENAME = $20 ; 32
+C_DELETE = $21 ; 33
+C_LOCK = $23 ; 35
+C_UNLOCK = $24 ; 36
+C_POINT = $25 ; 37
+C_NOTE = $26 ; 38
+
+; AUX1 modes (ICAX1,x or 2nd parameter of BASIC OPEN command):
+C_OPREAD = $04 ; 4 OPEN FOR INPUT
+C_OWRITE = $08 ; 8 OPEN FOR OUTPUT
+C_APPEND = $09 ; 9 OPEN TO APPEND TO END OF DISK FILE
+C_OUPDAT = $0C ; 12 OPEN FOR INPUT AND OUTPUT AT THE SAME TIME
+;; D: (DOS) only:
+C_OPDIR = $06 ; 6 OPEN TO DISK DIRECTORY
+;; S: only:
+C_MXDMOD = $10 ; 16 OPEN TO SPLIT SCREEN (MIXED MODE)
+C_INSCLR = $20 ; 32 OPEN TO SCREEN BUT DON'T ERASE
+;; C: only:
+C_NOIRG = $80 ; 128 NO GAP CASSETTE MODE
+
+;; Command bytes (ICCOM) for the RS-232 (R:) device:
+;;
+;; Output partial block 32 $20
+;; Control RTS,XMT,DTR 34 $22
+;; Baud, stop bits, word size 36 $24
+;; Translation mode 38 $26
+;; Concurrent mode 40 $28
+;;
+;; (see the 850 Interface Manual for details)
+
+
+; SIO command bytes (not part of CIO):
+S_DFRMAT = $21 ; 33 FORMAT DISK (RESIDENT DISK HANDLER (RDH))
+S_PTSECT = $50 ; 80 RDH PUT SECTOR
+S_GTSECT = $52 ; 82 RDH GET SECTOR
+S_DSTAT = $53 ; 83 RDH GET STATUS
+S_PSECTV = $57 ; 87 RDH PUT SECTOR AND VERIFY
+; Various other SIO commands are supported by different drives
+
+; 20061028 bkw: CR/EOL not really part of CIO, but useful:
+CR = $9B ; 155 CARRIAGE RETURN (EOL)
+EOL = CR ; defined in SYSEQU.ASM
+
+;
+IOCBSZ = $10 ; 16 IOCB SIZE
+MAXIOC = $80 ; 128 MAX IOCB BLOCK SIZE
+IOCBF = $FF ; 255 IOCB FREE
+;
+LEDGE = $02 ; 2 DEFAULT LEFT MARGIN
+REDGE = $27 ; 39 DEFAULT RIGHT MARGIN
+
+; OS VARIABLES
+;
+; PAGE 0
+;
+LINZBS = $00 ; 0 (800) FOR ORIGINAL DEBUGGER
+; $00 0 (XL) RESERVED
+NGFLAG = $01 ; 1 (XL) FOR POWER-UP SELF TEST
+CASINI = $02 ; 2
+RAMLO = $04 ; 4 POINTER FOR SELF TEST
+TRAMSZ = $06 ; 6 TEMPORARY RAM SIZE
+TSTDAT = $07 ; 7 TEST DATA
+WARMST = $08 ; 8
+BOOTQ = $09 ; 9 SUCCESSFUL BOOT FLAG
+; aka BOOT? in the OS source, but some assemblers don't support ? in labels
+DOSVEC = $0A ; 10 PROGRAM RUN VECTOR
+DOSINI = $0C ; 12 PROGRAM INITIALIZATION
+APPMHI = $0E ; 14 DISPLAY LOW LIMIT
+POKMSK = $10 ; 16 IRQ ENABLE FLAGS (shadow for IRQEN)
+BRKKEY = $11 ; 17 FLAG
+RTCLOK = $12 ; 18 3 BYTES, MSB FIRST
+BUFADR = $15 ; 21 INDIRECT BUFFER ADDRESS
+ICCOMT = $17 ; 23 COMMAND FOR VECTOR
+DSKFMS = $18 ; 24 DISK FILE MANAGER POINTER
+DSKUTL = $1A ; 26 DISK UTILITY POINTER (DUP.SYS)
+PTIMOT = $1C ; 28 (800) PRINTER TIME OUT REGISTER
+ABUFPT = $1C ; 28 (XL) RESERVED
+PBPNT = $1D ; 29 (800) PRINTER BUFFER POINTER
+; $1D ; 29 (XL) RESERVED
+PBUFSZ = $1E ; 30 (800) PRINTER BUFFER SIZE
+; $1E ; 30 (XL) RESERVED
+PTEMP = $1F ; 31 (800) TEMPORARY REGISTER (PTEMP deleted in XL OS)
+; $1F ; 31 (XL) RESERVED
+ZIOCB = $20 ; 32 ZERO PAGE IOCB
+ICHIDZ = $20 ; 32 HANDLER INDEX NUMBER (ID)
+ICDNOZ = $21 ; 33 DEVICE NUMBER
+ICCOMZ = $22 ; 34 COMMAND
+ICSTAZ = $23 ; 35 STATUS
+ICBALZ = $24 ; 36 BUFFER POINTER LOW BYTE
+ICBAHZ = $25 ; 37 BUFFER POINTER HIGH BYTE
+ICPTLZ = $26 ; 38 PUT ROUTINE POINTER LOW
+ICPTHZ = $27 ; 39 PUT ROUTINE POINTER HIGH
+ICBLLZ = $28 ; 40 BUFFER LENGTH LOW
+ICBLHZ = $29 ; 41
+ICAX1Z = $2A ; 42 AUXILIARY INFORMATION BYTE 1
+ICAX2Z = $2B ; 43
+ICSPRZ = $2C ; 44 TWO SPARE BYTES (CIO USE)
+ICIDNO = $2E ; 46 IOCB NUMBER X 16
+CIOCHR = $2F ; 47 CHARACTER BYTE FOR CURRENT OPERATION
+;
+STATUS = $30 ; 48 STATUS STORAGE
+CHKSUM = $31 ; 49 SUM WITH CARRY ADDED BACK
+BUFRLO = $32 ; 50 DATA BUFFER LOW BYTE
+BUFRHI = $33 ; 51
+BFENLO = $34 ; 52 ADDRESS OF LAST BUFFER BYTE +1 (LOW)
+BFENHI = $35 ; 53
+CRETRY = $36 ; 54 (800) NUMBER OF COMMAND FRAME RETRIES
+XL_LTEMP = $36 ; 54 (XL) LOADER TEMPORARY STORAGE, 2 BYTES
+DRETRY = $37 ; 55 (800) DEVICE RETRIES
+BUFRFL = $38 ; 56 BUFFER FULL FLAG
+RECVDN = $39 ; 57 RECEIVE DONE FLAG
+XMTDON = $3A ; 58 TRANSMISSION DONE FLAG
+CHKSNT = $3B ; 59 CHECKSUM-SENT FLAG
+NOCKSM = $3C ; 60 CHECKSUM-DOES-NOT-FOLLOW-DATA FLAG
+BPTR = $3D ; 61
+FTYPE = $3E ; 62
+FEOF = $3F ; 63
+FREQ = $40 ; 64
+;
+SOUNDR = $41 ; 65 0=QUIET I/O
+CRITIC = $42 ; 66 CRITICAL FUNCTION FLAG, NO DEFFERED VBI
+FMSZPG = $43 ; 67 DOS ZERO PAGE, 7 BYTES
+CKEY = $4A ; 74 (800) START KEY FLAG
+XL_ZCHAIN = $4A ; 74 (XL) HANDLER LOADER TEMP, 2 BYTES
+CASSBT = $4B ; 75 (800) CASSETTE BOOT FLAG
+DSTAT = $4C ; 76 DISPLAY STATUS
+;
+ATRACT = $4D ; 77
+DRKMSK = $4E ; 78 ATTRACT MASK
+COLRSH = $4F ; 79 ATTRACT COLOR SHIFTER (EORed WITH GRAPHICS)
+;
+TMPCHR = $50 ; 80
+HOLD1 = $51 ; 81
+LMARGN = $52 ; 82 SCREEN LEFT MARGIN REGISTER
+RMARGN = $53 ; 83 SCREEN RIGHT MARGIN
+ROWCRS = $54 ; 84 CURSOR ROW
+COLCRS = $55 ; 85 CURSOR COLUMN, 2 BYTES
+DINDEX = $57 ; 87 DISPLAY MODE
+SAVMSC = $58 ; 88 SCREEN ADDRESS
+OLDROW = $5A ; 90 CURSOR BEFORE DRAW OR FILL
+OLDCOL = $5B ; 91
+OLDCHR = $5D ; 93 DATA UNDER CURSOR
+OLDADR = $5E ; 94 CURSOR ADDRESS
+XL_FKDEF = $60 ; 96 (XL) FUNCTION KEY DEFINITION POINTER (LSB/MSB)
+NEWROW = $60 ; 96 (800) DRAWTO DESTINATION
+NEWCOL = $61 ; 97 (800) DRAWTO DESTINATION, 2 BYTES
+XL_PALNTS = $62 ; 98 (XL) EUROPE/NORTH AMERICA TV FLAG
+LOGCOL = $63 ; 99 LOGICAL LINE COLUMN POINTER
+MLTTMP = $66 ; 102
+OPNTMP = $66 ; 102 TEMPORARY STORAGE FOR CHANNEL OPEN
+SAVADR = $68 ; 104
+RAMTOP = $6A ; 106 START OF ROM (END OF RAM + 1), HIGH BYTE ONLY
+BUFCNT = $6B ; 107 BUFFER COUNT
+BUFSTR = $6C ; 108 POINTER USED BY EDITOR
+BITMSK = $6E ; 110 POINTER USED BY EDITOR
+SHFAMT = $6F ; 111
+ROWAC = $70 ; 112
+COLAC = $72 ; 114
+ENDPT = $74 ; 116
+DELTAR = $76 ; 118
+DELTAC = $77 ; 119
+ROWINC = $79 ; 121 (800)
+XL_KEYDEF = $79 ; 121 (XL) KEY DEFINITION POINTER, 2 BYTES
+COLINC = $7A ; 122 (800)
+SWPFLG = $7B ; 123 NON 0 IF TEXT AND REGULAR RAM IS SWAPPED
+HOLDCH = $7C ; 124 CH MOVED HERE BEFORE CTRL AND SHIFT
+INSDAT = $7D ; 125 used by S: handler, tmp for char under cursor
+COUNTR = $7E ; 126 used by XIO DRAW command (2 bytes)
+
+; $80 to $FF are free if BASIC and floating point are not used.
+; If BASIC is not used, but FP is, $80 to $D0 are still free.
+; There is no way to use BASIC without constantly using FP, as all BASIC
+; numbers are FP (even "integers" such as line numbers).
+ZROFRE = $80 ; 128 FREE ZERO PAGE, 84 BYTES
+
+; BASIC zero page variables:
+LOMEM = $80 ; 128 LSB, BASIC start-of-memory pointer
+; $81 ; 129 MSB, LOMEM (not to be confused with the OS's MEMLO!)
+VNTP = $82 ; 130 LSB, BASIC start of Variable Name Table pointer
+; $83 ; 131 MSB, VNTP
+VNTD = $84 ; 132 LSB, BASIC end of Variable Name Table pointer (+1 byte)
+; $85 ; 133 MSB, VNTP
+VVTP = $86 ; 134 LSB, BASIC start of Variable Value Table pointer
+; $87 ; 135 MSB, VVTP
+STMTAB = $88 ; 136 LSB, BASIC start of Statement Table pointer
+; $89 ; 137 MSB, STMTAB
+STMCUR = $8A ; 138 LSB, BASIC current statement pointer
+; $8B ; 139 MSB, STMCUR
+STARP = $8C ; 140 LSB, BASIC current string/array table pointer
+; $8D ; 141 MSB, STARP (also points to end of BASIC program)
+RUNSTK = $8E ; 142 LSB, BASIC runtime stack pointer
+; $8F ; 143 MSG, RUNSTK
+; BASIC and the OS both use the name MEMTOP; I've renamed the BASIC one.
+BAS_MEMTOP = $90 ; 144 LSB, pointer to top of BASIC memory
+; $91 ; 145 MSB, BAS_MEMTOP
+MEOLFLG = $92 ; 146 "modified EOL flag register", whatever that is
+; $93 ; 147 listed as "spare" by Mapping's Errata
+;COX = $94 ; 148 current output index (?)
+POKADR = $95 ; 149 LSB, address of last POKE location
+; ; 150 MSB, POKADR
+
+; Locations $96 to $B5 are used for various purposes by BASIC,
+; and most of them are of little or no interest, even for someone
+; writing assembly code meant to run as a USR() routine, so I haven't
+; bothered listing them all here. See Compute! Books' "Atari BASIC Sourcebook"
+; for the gory details. In fact, you can see it here:
+
+; http://users.telenet.be/kim1-6502/6502/absb.html
+
+; It's fascinating (at least it is to me)... includes full source code
+; to Atari BASIC!
+
+; DATAD and DATALN are reset to 0 by BASIC RESTORE command.
+DATAD = $B6 ; 182 the data element being read (e.g. 10 for 10th item
+ ; in a DATA statement)
+DATALN = $B7 ; 183 LSB current DATA statement line number
+; $B8 ; 184 MSB, DATALN
+;ERRNUM = $B9 ; 185 Most recent error number. Gets cleared before you
+ ; can PEEK it; use ERRSAVE instead.
+STOPLN = $BA ; 186 LSB, line where a program stopped by STOP/break/error
+; $BB ; 187 MSB, STOPLN
+; what are $BC and $BD for?
+SAVCUR = $BE ; 190 Saves the current line address (LSB?)
+; $BF ; 191 presumably, the MSB of SAVCUR?
+IOCMD = $C0 ; 192, I/O Command (Mapping Errata)
+IODVC = $C1 ; 193, I/O Device (Mapping Errata)
+PROMPT = $C2 ; 194, Prompt character (Mapping Errata, presumably INPUT?)
+ERRSAVE = $C3 ; 195 Error code that caused a stop or TRAP
+;TEMPA = $C4 ; 196 a 2-byte temp
+;ZTEMP2 = $C6 ; 198 a 2-byte temp
+COLOR = $C8 ; 200 Stores color from COLOR command
+PTABW = $C9 ; 201 Number of columns between tab stops
+ ; (for PRINT with commas, not the TAB key)
+LOADFLG = $CA ; 202 Load in progress flag. I can tell you from bitter
+ ; experience that BASIC clears this often.
+
+; $CB - $CF are unused by BASIC or the ASM/ED cart.
+; $D0 and $D1 are unused by BASIC (does that mean they *are* used by ASM/ED?)
+
+; $D2 and $D3 are used by BASIC. Mapping Errata calls them the "BASIC
+; floating-point work area". They get cleared to 0 by BASIC, probably
+; every time a FP number is used (e.g. "POKE 210,1:? PEEK(210)" prints 0).
+; The BASIC source code labels $D2 as TVTYPE and VTYPE, and $D3 as
+; TVNUM and VNUM.
+
+; Floating point zero page variables:
+FPZRO = $D4 ; 212 FLOATING POINT RAM, 43 BYTES
+ ; (20070530 bkw: pretty sure that comment is wrong, and
+ ; should read 44 bytes; see $FF below)
+FR0 = $D4 ; 212 FP REGISTER 0 (also used by BASIC for USR() return val)
+ ; (FR0/FRE/FR1/FR2 are each 6 bytes long)
+FRE = $DA ; 218
+FR1 = $E0 ; 224 FP REGISTER 1
+FR2 = $E6 ; 230 FP REGISTER 2
+FRX = $EC ; 236 SPARE
+EEXP = $ED ; 237 VALUE OF E
+NSIGN = $ED ; 237 SIGN OF FP NUMBER
+ESIGN = $EF ; 239 SIGN OF FP EXPONENT
+FCHFLG = $F0 ; 240 FIRST CHARACTER FLAG
+DIGRT = $F1 ; 241 NUMBER OF DIGITS RIGHT OF DECIMAL POINT
+CIX = $F2 ; 242 INPUT INDEX
+INBUFF = $F3 ; 243 POINTER TO ASCII FP NUMBER
+ZTEMP1 = $F5 ; 245
+ZTEMP4 = $F7 ; 247
+ZTEMP3 = $F9 ; 249
+DEGFLG = $FB ; 251
+RADFLG = $FB ; 251 0=RADIANS, 6=DEGREES
+FLPTR = $FC ; 252 POINTER TO BCD FP NUMBER (2 bytes)
+FPTR2 = $FE ; 254 maybe a 2nd pointer to an FP number? (2 bytes)
+; $FF ; 255 This *definitely* is used by the FP package
+ ; Try: POKE 255,0:? SIN(1):? PEEK(255)
+
+;
+; PAGE 1
+;
+; 65O2 STACK
+;
+;
+
+;
+;
+; PAGE 2
+;
+;
+; 20070529 bkw: Bytes listed as "spare" should NOT be used for your own
+; purposes. They may not really be unused (just undocumented), and/or they
+; may be unused on the 800 but not the XL (or vice versa).
+INTABS = $0200 ; 512 INTERRUPT RAM
+VDSLST = $0200 ; 512 NMI VECTOR
+VPRCED = $0202 ; 514 PROCEED LINE IRQ VECTOR
+VINTER = $0204 ; 516 INTERRUPT LINE IRQ VECTOR
+VBREAK = $0206 ; 518 break key IRQ vector (not in OS rev. A)
+VKEYBD = $0208 ; 520 keyboard IRQ vector (not break/console keys)
+VSERIN = $020A ; 522 SERIAL INPUT READY IRQ
+VSEROR = $020C ; 524 SERIAL OUTPUT READY IRQ
+VSEROC = $020E ; 526 SERIAL OUTPUT COMPLETE IRQ
+VTIMR1 = $0210 ; 528 TIMER 1 IRQ vector
+VTIMR2 = $0212 ; 530 TIMER 2 IRQ vector
+VTIMR4 = $0214 ; 532 TIMER 4 IRQ vector
+VIMIRQ = $0216 ; 534 IRQ VECTOR
+CDTMV1 = $0218 ; 536 COUNTDOWN TIMER 1 vector
+CDTMV2 = $021A ; 538 COUNTDOWN TIMER 2 vector
+CDTMV3 = $021C ; 540 COUNTDOWN TIMER 3 vector
+CDTMV4 = $021E ; 542 COUNTDOWN TIMER 4 vector
+CDTMV5 = $0220 ; 544 COUNTDOWN TIMER 5 vector
+VVBLKI = $0222 ; 546 immediate VBLANK vector
+VVBLKD = $0224 ; 548 deferred VBLANK vector (ignore if CRITIC != 0)
+CDTMA1 = $0226 ; 550 COUNTDOWN TIMER 1 JSR ADDRESS
+CDTMA2 = $0228 ; 552 COUNTDOWN TIMER 2 JSR ADDRESS
+CDTMF3 = $022A ; 554 COUNTDOWN TIMER 3 FLAG
+SRTIMR = $022B ; 555 REPEAT TIMER
+CDTMF4 = $022C ; 556 COUNTDOWN TIMER 4 FLAG
+INTEMP = $022D ; 557 IAN'S TEMP (used by SETVBL routine)
+CDTMF5 = $022E ; 558 COUNTDOWN TIMER FLAG 5
+SDMCTL = $022F ; 559 DMACTL SHADOW
+SDLSTL = $0230 ; 560 DISPLAY LIST POINTER, LSB (shadow for DLISTL)
+SDLSTH = $0231 ; 561 display list pointer, MSB (shadow for DLISTH)
+SSKCTL = $0232 ; 562 SKCTL SHADOW
+; $0233 ; 563 (800) UNLISTED (Mapping calls this SPARE)
+XL_LCOUNT = $0233 ; 563 (XL) LOADER TEMP
+LPENH = $0234 ; 564 LIGHT PEN HORIZONTAL (shadow for PENH)
+LPENV = $0235 ; 565 LIGHT PEN VERTICAL (shadow for PENV)
+; $0236 ; 566 2 SPARE BYTES on OS rev A
+VBRKKY = $0236 ; 566 Break key interrupt vector (OS rev B and XL)
+BRKKY = VBRKKY ; "OS rev 5" listing calls it this
+; $0238 ; 568 (800) SPARE, 2 BYTES
+;XL_RELADR = $0238 ; 568 (XL) relocatable loader relative addr, 1200XL only!
+XL_VPIRQ = $0238 ; 568 (XL) PBI IRQ vector (not on 1200XL!)
+CDEVIC = $023A ; 570 DEVICE COMMAND FRAME BUFFER
+CAUX1 = $023C ; 572 DEVICE COMMAND AUX 1
+CAUX2 = $023D ; 573 DEVICE COMMAND AUX 2
+TEMP = $023E ; 574 TEMPORARY STORAGE
+ERRFLG = $023F ; 575 DEVICE ERROR FLAG (EXCEPT TIMEOUT)
+DFLAGS = $0240 ; 576 FLAGS FROM DISK SECTOR 1
+DBSECT = $0241 ; 577 NUMBER OF BOOT DISK SECTORS
+BOOTAD = $0242 ; 578 BOOT LOAD ADDRESS POINTER
+COLDST = $0244 ; 580 COLD START FLAG, 1 = COLD START IN PROGRESS
+; $0245 ; 581 (800) SPARE
+XL_RECLEN = $0245 ; 581 (XL) LOADER
+DSKTIM = $0246 ; 582 (800) DISK TIME OUT REGISTER
+; $0246 ; 582 (XL) RESERVED, 39 BYTES
+LINBUF = $0247 ; 583 (800) CHARACTER LINE BUFFER, 40 BYTES
+ ; LINBUF was deleted from the XL OS and replaced with:
+
+; $0247 - $024D are "reserved" on the 1200XL. On other XL's they are:
+XL_PDVMSK = $0247 ; 583 shadow for PBI device selection register @ $D1FF
+XL_SHPDVS = $0248 ; 584 shadow for PBI register (where??)
+XL_PDMSK = $0249 ; 585 PBI interrupt mask
+XL_RELADR = $024A ; 586 (XL) LSB, relocatable loader relative addr (NOT 1200XL)
+; $024B ; 587 MSB, XL_RELADR
+XL_PPTMPA = $024C ; 588 temporaries for relocatable loader
+XL_PPTMPX = $024D ; 589 "
+
+; $024E - $026A are "spare" on all XL/XE's
+
+; More XL stuff:
+XL_CHSALT = $026B ; 619 (XL) CHARACTER SET POINTER (ctrl-F4 on 1200XL)
+XL_VSFLAG = $026C ; 620 (XL) FINE SCROLL TEMPORARY
+XL_KEYDIS = $026D ; 621 (XL) KEYBOARD DISABLE (ctrl-F1 on 1200XL)
+XL_FINE = $026E ; 622 (XL) FINE SCROLL FLAG (POKE 622,255:GR.0)
+
+GPRIOR = $026F ; 623 P/M PRIORITY AND GTIA MODES (shadow for PRIOR)
+;GTIA = $026F ; 623 ; 20070529 bkw: does anyone define this?
+
+; Game controller shadows (joysticks/paddles)
+; Joystick directions and paddle triggers (buttons) are wired to the PIA.
+; Joystick triggers (fire buttons) and the actual paddle potentiometers
+; are wired to the GTIA.
+; If this seems a little odd, that's because it is :)
+
+; Paddles (potentiometers):
+PADDL0 = $0270 ; 624 (XL) 3 MORE PADDLES, (800) 7 MORE PADDLES
+PADDL1 = $0271 ; 625 (these are read in BASIC with PADDLE(x)
+PADDL2 = $0272 ; 626 (PADDL0-7 are shadows for POT0-7)
+PADDL3 = $0273 ; 627
+PADDL4 = $0274 ; 628 (PADDL4-7 are copies of PADDL0-3 on the XL)
+PADDL5 = $0275 ; 629
+PADDL6 = $0276 ; 630
+PADDL7 = $0277 ; 631
+
+; Joysticks (directions only)
+STICK0 = $0278 ; 632 (XL) 1 MORE STICK, (800) 3 MORE STICKS
+STICK1 = $0279 ; 633 (these are read in BASIC with STICK(x)
+STICK2 = $027A ; 634 (STICK0/1 are shadows for PORTA; STICK2/3 shadows PORTB)
+STICK3 = $027B ; 635
+; STICK0 is a shadow for bits 4-7 of PORTA (shifted 4 bits right)
+; STICK1 is a shadow for bits 0-3 of PORTA
+
+; On the 800:
+; STICK2 is a shadow for bits 4-7 of PORTB (shifted 4 bits right)
+; STICK3 is a shadow for bits 0-3 of PORTB
+
+; On the XL/XE series:
+; STICK2 and STICK3 are copies of STICK0 and STICK1, respectively.
+
+; In the XL/XE machines, there are only 2 joystick ports, and PORTB
+; (formerly joystick ports) is now used to control the MMU.
+
+; joystick directions are active low (1=not pressed) and decode as:
+
+; bit direction
+; 0 or 4 up
+; 1 or 5 down
+; 2 or 6 left
+; 3 or 7 right
+
+; A value of $0F in a STICKx register means no direction is being pressed.
+; When a direction is pressed, its bit becomes a logic 0, so e.g. $0E means
+; someone's moving the joystick up.
+
+; (bits 4-7 are only used when reading directly from the HW registers,
+; PORTA and PORTB).
+
+; Paddle triggers (buttons)
+PTRIG0 = $027C ; 636 (XL) 3 MORE PADDLE TRIGGERS, (800) 7 MORE
+PTRIG1 = $027D ; 637 (these are read in BASIC with PTRIG(x))
+PTRIG2 = $027E ; 638 (PTRIG0-3 are shadows for PORTA)
+PTRIG3 = $027F ; 639
+PTRIG4 = $0280 ; 640 (PTRIG4-7 are shadows for PORTB on the 800)
+PTRIG5 = $0281 ; 641 (they are copies of PTRIG0-3 on the XL)
+PTRIG6 = $0282 ; 642
+PTRIG7 = $0283 ; 643
+; In case someone doesn't already know this: The paddle triggers are wired
+; to the same pins on the joystick port as the left/right joystick directions.
+; Each pair of paddles uses left for the first paddle's trigger and right
+; for the second (so PTRIG0/1 are also the left/right bits in STICK0,
+; PTRIG2/3 are STICK1, etc).
+
+; Joystick triggers (buttons)
+STRIG0 = $0284 ; 644 (XL) 1 MORE STICK TRIGGER, (800) 3 MORE
+STRIG1 = $0285 ; 645 (these are read in BASIC with STRIG(x))
+STRIG2 = $0286 ; 646 (STRIG0-3 are shadows for TRIG0-3)
+STRIG3 = $0287 ; 647
+
+; C: handler variables:
+CSTAT = $0288 ; 648 (800) Cassette status register
+; note that CSTAT was deleted from the XL OS, and replaced with:
+XL_HIBYTE = $0288 ; 648 (XL) used by relocatable loader
+WMODE = $0289 ; 649 used by C: handler (0=read, 128-write)
+BLIM = $028A ; 650 cassette buffer data record size
+; $028B ; 651 (800) 5 SPARE BYTES (to $028F)
+XL_IMASK = $028B ; 651 (XL) used by relocatable loader
+XL_JVECK = $028C ; 652 (XL) (Mapping says it's unused)
+ ; 653 (XL) Presumably the MSB of JVECK (unused?)
+XL_NEWADR = $028E ; 654 (XL) LOADER RAM (2 bytes)
+
+; Misc. S: and/or E: handler variables:
+TXTROW = $0290 ; 656
+TXTCOL = $0291 ; 657
+TINDEX = $0293 ; 659 TEXT INDEX
+TXTMSC = $0294 ; 660
+TXTOLD = $0296 ; 662 OLD ROW AND OLD COL FOR TEXT, 2 BYTES
+; $0298 ; 664 4 SPARE BYTES
+TMPX1 = $029C ; 668 (800)
+; note that TMPX1 was deleted from the XL OS, and replaced with:
+XL_CRETRY = $029C ; 668 (XL) NUMBER OF COMMAND FRAME RETRIES
+ ; (moved from CRETRY on 800)
+SUBTMP = $029E ; 670
+HOLD2 = $029F ; 671
+DMASK = $02A0 ; 672
+TMPLBT = $02A1 ; 673
+ESCFLG = $02A2 ; 674
+TABMAP = $02A3 ; 675 15 BYTE BIT MAP FOR TAB SETTINGS
+LOGMAP = $02B2 ; 690 4 BYTE LOGICAL LINE START BIT MAP
+INVFLG = $02B6 ; 694 mask for inverse video ($80=inverse, 0=normal)
+FILFLG = $02B7 ; 695 FILL DURING DRAW FLAG
+TMPROW = $02B8 ; 696
+TMPCOL = $02B9 ; 697
+SCRFLG = $02BB ; 699 SCROLL FLAG
+HOLD4 = $02BC ; 700
+HOLD5 = $02BD ; 701 (800)
+; note that HOLD5 was deleted from the XL OS, and replaced with:
+XL_DRETRY = $02BD ; 701 (XL) NUMBER OF DEVICE RETRIES
+ ; (moved from DRETRY on 800)
+SHFLOC = $02BE ; 702
+BOTSCR = $02BF ; 703 24 NORM, 4 SPLIT
+
+; Color register shadows (HW registers are in GTIA)
+PCOLR0 = $02C0 ; 704 3 MORE PLAYER COLOR REGISTERS (shadows for COLPM0-3)
+PCOLR1 = $02C1 ; 705 (missiles use same color regs as same-numbered players!)
+PCOLR2 = $02C2 ; 706
+PCOLR3 = $02C3 ; 707
+COLOR0 = $02C4 ; 708 4 MORE GRAPHICS COLOR REGISTERS (shadows for COLPF0-3)
+COLOR1 = $02C5 ; 709 (text luminance in GR.0)
+COLOR2 = $02C6 ; 710 (text background and chroma in GR.0)
+COLOR3 = $02C7 ; 711
+COLOR4 = $02C8 ; 712 (background, shadow for COLBK)
+; On boot, system reset, or any time S:/E: devices are opened:
+; PCOLR0-3 are initialzed to 0 ($00, black)
+; COLOR0 is initialized to 40 ($28, orange)
+; COLOR1 is initialized to 202 ($CA, green)
+; COLOR2 is initialized to 148 ($94, blue)
+; COLOR3 is initialized to 70 ($46, red)
+; COLOR4 is initialized to 0 ($00, black)
+
+; $02C9 713 (800) 23 SPARE BYTES
+; XL relocatable handler and other variables:
+XL_RUNADR = $02C9 ; 713 (XL) LOADER VECTOR
+XL_HIUSED = $02CB ; 715 (XL) LOADER VECTOR
+XL_ZHIUSE = $02CD ; 717 (XL) LOADER VECTOR
+XL_GBYTEA = $02CF ; 719 (XL) LOADER VECTOR
+XL_LOADAD = $02D1 ; 721 (XL) LOADER VECTOR
+XL_ZLOADA = $02D3 ; 723 (XL) LOADER VECTOR
+XL_DSCTLN = $02D5 ; 725 (XL) DISK SECTOR SIZ
+XL_ACMISR = $02D7 ; 727 (XL) RESERVED
+XL_KRPDER = $02D9 ; 729 (XL) KEY AUTO REPEAT DELAY
+XL_KEYREP = $02DA ; 730 (XL) KEY AUTO REPEAT RATE
+XL_NOCLIK = $02DB ; 731 (XL) KEY CLICK DISABLE (ctrl-F3 on 1200XL)
+XL_HELPFG = $02DC ; 732 (XL) HELP KEY FLAG
+XL_DMASAV = $02DD ; 733 (XL) SDMCTL (DMA) SAVE (ctrl-F2 on 1200XL)
+XL_PBPNT = $02DE ; 734 (XL) PRINTER BUFFER POINTER (moved from PBPNT on 800)
+XL_PBUFSZ = $02DF ; 735 (XL) PRINTER BUFFER SIZE (moved from PBUFSZ on 800)
+; note that PTEMP was deleted from the XL OS
+
+; DOS/FMS variables:
+GLBABS = $02E0 ; 736 GLOBAL VARIABLES, 4 SPARE BYTES (if DOS not loaded)
+ ; If DOS/FMS is loaded:
+RUNAD = $02E0 ; 736 (DOS) Run address for binary file (LSB/MSB)
+INITAD = $02E2 ; 736 (DOS) Init address for binary file (LSB/MSB)
+
+; SYSEQU.ASM defines these:
+GOADR = RUNAD
+INITADR = INITAD
+
+; OS variables:
+RAMSIZ = $02E4 ; 740 PERMANENT START OF ROM POINTER
+MEMTOP = $02E5 ; 741 END OF FREE RAM
+MEMLO = $02E7 ; 743 LSB, points to bottom of free memory ($0700 if DOS
+ ; not booted). Not to be confused with BASIC's LOMEM!
+; $02E8 ; 744 MSB of MEMLO
+
+; $02E9 ; 745 (800) SPARE
+XL_HNDLOD = $02E9 ; 745 (XL) HANDLER LOADER FLAG
+
+DVSTAT = $02EA ; 746 DEVICE STATUS BUFFER, 4 BYTES
+CBAUDL = $02EE ; 750 CASSETTE BAUD RATE, 2 BYTES
+CRSINH = $02F0 ; 752 1 = INHIBIT CURSOR
+KEYDEL = $02F1 ; 753 KEY DELAY AND RATE (aka debounce counter)
+CH1 = $02F2 ; 754 prior keyboard character code
+CHACT = $02F3 ; 755 (shadow for CHACTL)
+CHBAS = $02F4 ; 756 CHARACTER SET POINTER (shadow for CHBASE)
+
+; These next 4 are located elsewhere on the 800 OS:
+XL_NEWROW = $02F5 ; 757 (XL) DRAW DESTINATION
+XL_NEWCOL = $02F6 ; 758 (XL) DRAW DESTINATION
+XL_ROWINC = $02F8 ; 760 (XL)
+XL_COLINC = $02F9 ; 761 (XL)
+; $02F5 - $02F9 are "spare" on the 800.
+
+CHAR = $02FA ; 762 most recent character read/written (screen code)
+ATACHR = $02FB ; 763 ATASCII CHARACTER FOR CIO
+CH = $02FC ; 764 last key pressed (internal scan code)
+FILDAT = $02FC ; 764 COLOR FOR SCREEN FILL
+DSPFLG = $02FE ; 766 DISPLAY CONTROL CHARACTERS FLAG
+SSFLAG = $02FF ; 767 DISPLAY START/STOP FLAFG
+
+;
+; PAGE 3
+;
+;
+; RESIDENT DISK HANDLER/SIO INTERFACE
+;
+; The DCB is used for SIO (serial I/O).
+DCB = $0300 ; 768 DEVICE CONTROL BLOCK
+DDEVIC = $0300 ; 768 device ID ($31-$38 for D1:-D8:)
+DUNIT = $0301 ; 769 disk/device unit numder
+DCOMND = $0302 ; 770 device command
+DSTATS = $0303 ; 771 status code (set by OS)
+DBUFLO = $0304 ; 772 data buffer LSB (set by user)
+DBUFHI = $0305 ; 773 data buffer MSB (set by user)
+DTIMLO = $0306 ; 774 timeout (set by user, units of 60/64 seconds)
+DUNUSE = $0307 ; 775 unused
+DBYTLO = $0308 ; 776 number of bytes to transfer, LSB
+DBYTHI = $0309 ; 777 number of bytes to transfer, MSB
+DAUX1 = $030A ; 778 LSB of sector number (for disk) (set by user)
+DAUX2 = $030B ; 779 MSB of sector number (for disk)
+TIMER1 = $030C ; 780 INITIAL TIMER VALUE
+ADDCOR = $030E ; 782 (800) ADDITION CORRECTION
+; note that ADDCOR was deleted from the XL OS, and replaced with:
+XL_JMPERS = $030E ; 782 (XL) OPTION JUMPERS
+CASFLG = $030F ; 783 CASSETTE MODE WHEN SET
+TIMER2 = $0310 ; 784 FINAL VALUE, TIMERS 1 & 2 DETERMINE BAUD RATE
+TEMP1 = $0312 ; 786
+XL_TEMP2 = $0313 ; 787 (XL)
+TEMP2 = $0314 ; 788 (800)
+XL_PTIMOT = $0314 ; 788 (XL) PRINTER TIME OUT
+TEMP3 = $0315 ; 789
+SAVIO = $0316 ; 790 SAVE SERIAL IN DATA PORT
+TIMFLG = $0317 ; 791 TIME OUT FLAG FOR BAUD RATE CORRECTION
+STACKP = $0318 ; 792 SIO STACK POINTER SAVE
+TSTAT = $0319 ; 793 TEMPORARY STATUS HOLDER
+HATABS = $031A ; 794 HANDLER ADDRESS TABLE, 38 BYTES
+MAXDEV = $0321 ; 801 MAXIMUM HANDLER ADDRESS INDEX
+XL_PUPBT1 = $033D ; 829 (XL) POWER-UP/RESET
+XL_PUPBT2 = $033E ; 830 (XL) POWER-UP/RESET
+XL_PUPBT3 = $033F ; 831 (XL) POWER-UP/RESET
+
+; IOCB's, 8 of them, 16 bytes each.
+; Set X register to (IOCB number * 16), and use e.g. ICCOM,x
+;
+IOCB = $0340 ; 832 ; IOCB base address
+ICHID = $0340 ; 832 ; Handler ID (set by OS)
+ICDNO = $0341 ; 833 ; Device number (set by OS)
+ICCOM = $0342 ; 834 ; Command byte (see C_* constants) (set by user)
+ICCMD = ICCOM ; ; alternate name for ICCOM, according to Mapping.
+ICSTA = $0343 ; 835 ; Status (set by OS)
+ICBAL = $0344 ; 836 ; Buffer address, LSB (set by user)
+ICBAH = $0345 ; 837 ; Buffer address, MSB (set by user)
+ICPTL = $0346 ; 838 ; Put-one-byte address minus one, LSB (set by OS)
+ICPTH = $0347 ; 839 ; Put-one-byte address minus one, MSB (set by OS)
+ICBLL = $0348 ; 840 ; Buffer length, LSB (set by user)
+ICBLH = $0349 ; 841 ; Buffer length, MSB (set by user)
+ICAX1 = $034A ; 842 ; AUX1 byte (2nd param in BASIC OPEN) (set by user)
+ICAX2 = $034B ; 843 ; AUX2 byte (4rd param in BASIC OPEN) (set by user)
+ICAX3 = $034C ; 844 ; AUX3 byte (used by NOTE/POINT) (set by user)
+ICAX4 = $034D ; 845 ; AUX4 byte (used by NOTE/POINT) (set by user)
+ICAX5 = $034E ; 846 ; AUX5 byte (used by NOTE/POINT) (set by user)
+ICAX6 = $034F ; 847 ; Spare aux byte
+; OTHER IOCB's, 112 BYTES ($300 + $10 * channel)
+
+IOCBLEN = ICAX6-IOCB+1 ; length of one IOCB (from SYSEQU.ASM)
+
+; Alternative names for the above. I found these in SYSEQU.ASM, as
+; distributed with the disk version of Mac65.
+ICBADR = ICBAL
+ICPUT = ICPTL
+ICBLEN = ICBLL
+ICAUX1 = ICAX1
+ICAUX2 = ICAX2
+ICAUX3 = ICAX3
+ICAUX4 = ICAX4
+ICAUX5 = ICAX5
+ICAUX6 = ICAX6
+
+PRNBUF = $03C0 ; 960 PRINTER BUFFER, 40 BYTES
+; $03E8 ; 1000 (800) 21 SPARE BYTES
+XL_SUPERF = $03E8 ; 1000 (XL) SCREEN EDITOR
+XL_CKEY = $03E9 ; 1001 (XL) START KEY FLAG
+XL_CASSBT = $03EA ; 1002 (XL) CASSETTE BOOT FLAG
+XL_CARTCK = $03EB ; 1003 (XL) CARTRIDGE CHECKSUM
+XL_ACMVAR = $03ED ; 1005 (XL) RESERVED, 10 BYTES (to $03F7)
+XL_BASICF = $03F8 ; 1006 (XL) 0 if ROM-BASIC enabled, 1 if not
+XL_MINTLK = $03F9 ; 1017 (XL) RESERVED
+XL_GINTLK = $03FA ; 1018 (XL) CARTRIDGE INTERLOCK
+XL_CHLINK = $03FB ; 1019 (XL) HANDLER CHAIN, 2 BYTES
+CASBUF = $03FD ; 1021 CASSETTE BUFFER, 131 BYTES TO $047F
+
+; Layout of the cassette buffer after a cassette block is read:
+
+; Baud correction ($55 $55) bytes are located at offsets 0 and 1
+; Control byte is at offset 2 ($03FF):
+; Actual data (128 bytes) runs from offset 3 ($0400) to $047F.
+; Each cassette frame has a 1 byte checksum after the 128 data bytes, but
+; the checksum is NOT stored anywhere in the cassette buffer!
+
+; CONTROL BYTE VALUES
+; Value Meaning
+; 250 ($FA) Partial record follows. The actual number of bytes is stored
+; in the last byte of the record (CASBUF+130, or $047F).
+; 252 ($FC) Record full; 128 bytes follow.
+; 254 ($FE) End of File (EOF) record; followed by 128 zero bytes.
+
+; Boot tapes normally don't have partial or EOF records, but BASIC
+; CLOAD/LOAD/LIST and data file tapes do.
+
+; Mapping the Atari says the first disk boot sector is read into CASBUF also.
+
+;
+;
+; PAGE 4
+;
+;
+USAREA = $0480 ; 1152 128 SPARE BYTES (but used by BASIC)
+;
+; SEE APPENDIX C FOR PAGES 4 AND 5 USAGE
+
+;
+;
+;
+;
+; PAGE 5
+;
+PAGE5 = $0500 ; 1280 127 FREE BYTES
+; $057E 1406 129 FREE BYTES IF FLOATING POINT ROUTINES NOT USED
+;
+;FLOATING POINT NON-ZERO PAGE RAM, NEEDED ONLY IF FP IS USED
+; (20070529 bkw: BASIC constantly uses FP! Also, it uses some of these
+; addresses for its own purposes.)
+;
+LBPR1 = $057E ; 1406 LBUFF PREFIX 1
+LBPR2 = $05FE ; 1534 LBUFF PREFIX 2
+LBUFF = $0580 ; 1408 LINE BUFFER
+PLYARG = $05E0 ; 1504 POLYNOMIAL ARGUMENTS
+FPSCR = $05E6 ; 1510 PLYARG+FPREC
+FPSCR1 = $05EC ; 1516 FPSCR+FPREC
+FSCR = $05E6 ; 1510 =FPSCR
+FSCR1 = $05EC ; 1516 =FPSCR1
+LBFEND = $05FF ; 1535 END OF LBUFF
+
+;
+; PAGE 6
+;
+;
+PAGE6 = $0600 ; 1536 256 FREE BYTES
+
+;
+;
+; PAGE 7
+;
+;
+BOOTRG = $0700 ; 1792 PROGRAM AREA
+; Boot disks (including DOS) are generally loaded here. Also, BASIC RAM
+; (variables and program) starts here, if BASIC is booted without DOS.
+
+; Page 80 (XL): Self-test (aka diagnostic) ROM is mapped at $5000,
+; if enabled with bit 7 of PORTB. Normally only happens if you boot without
+; BASIC, cartridge, tape, or disk... or if the OS detects a memory error
+; during boot.
+
+;
+;
+; UPPER ADDRESSES
+;
+;
+RITCAR = $8000 ;32768 RAM IF NO CARTRIDGE (extends to $9FFF)
+LFTCAR = $A000 ;40960 RAM IF NO CARTRIDGE (extends to $BFFF)
+
+; These 2 are from the Atari System Reference Manual, chapter 12:
+CARTA = LFTCAR
+CARTB = RITCAR
+
+CARTLOC = $BFFA ;49146 cartridge run address (from SYSEQU.ASM)
+
+; Carts were originally 8K only when the 400/800 were first released.
+; There were plans to release 16K programs on two cartridges, but this
+; never happened (the price of 16K ROMs came down, I guess). 16K cartridges
+; go in the left slot, but they actually use the address space for both
+; the right and left slots.
+
+; Mapping the Atari has this to say about cartridges:
+;; Byte Purpose
+;; Left (A) Right(B)
+;; 49146 ($BFFA) 40954 ($9FFA) Cartridge start address (low byte)
+;;
+;; 49147 ($BFFB) 40955 ($9FFB) Cartridge start address (high byte)
+;;
+;; 49148 ($BFFC) 40956 ($9FFC) Reads zero if a cartridge is
+;; inserted, non-zero when no cartridge is present. This information
+;; is passed down to the page zero RAM: if the A cartridge is plugged
+;; in, then location 6 will read one; if the B cartridge is plugged in,
+;; then location 7 will read one; otherwise they will read zero.
+;;
+;; 49149 ($BFFD) 40957 ($9FFD) Option byte. If BIT 0 equals one,
+;; then boot the disk (else there is no disk boot). If BIT 2 equals one,
+;; then initialize and start the cartridge (else initialize but do not
+;; start). If BIT 7 equals one, then the cartridge is a diagnostic
+;; cartridge which will take control, but not initialize the OS (else
+;; non-diagnostic cartridge). Diagnostic cartridges were used by
+;; Atari in the development of the system and are not available to the
+;; public.
+;;
+;; 49150 ($BFFE) 40958 ($9FFE) Cartridge initialization address
+;; low byte.
+;;
+;; 49151 ($BFFF) 40959 ($9FFF) Cartridge initialization address
+;; high byte. This is the address to which the OS will jump during all
+;; powerup and RESETs.
+;;
+;; The OS makes temporary use of locations 36876 to 36896 ($900C to
+;; $9020) to set up vectors for the interrupt handler. See the OS
+;; listings pages 31 and 81. This code was only used in the
+;; development system used to design the Atari.
+
+
+; Page 192
+
+C0PAGE = $C000 ;49152 (800) EMPTY, 4K BYTES
+ ; 20070529 bkw: unmapped address space.
+ ; Mapping the Atari erroneously lists this as "unused ROM".
+ ; There are upgrades to the 800 to give 4K of RAM here
+ ; (for a total of 52K of RAM), or ROM (Omnimon?).
+ ; Also, there is RAM here if you boot the Translator
+ ; disk on an XL.
+
+; (XL) $C000 also contains info about the ROM revision. From Mapping:
+
+;Bytes 49152-49163 ($C000-$C00B) are used to identify the computer
+;and the ROM in the $C000-$DFFF block:
+;
+;Byte Use
+;49152-3/C000-1 Checksum (LSB/MSB) of all the bytes
+; in ROM except the checksum bytes
+; themselves.
+;49154/C002 Revision date, stored in the form
+; DDMMYY. This is DD, day, usually $10.
+;49155/C003 Revision date, month; usually $05.
+;49156/C004 Revision date, year; usually $83.
+;49157/C005 Reserved option byte; reads zero for
+; the 1200, 800XL, and 130XE.
+;49158/C006 Part number in the form AANNNNNN;
+; AA is an ASCII character and
+; NNNNNN is a four-bit BCD digit. This is
+; byte A1.
+;49159-62/C007-A Part number, bytes A2, N1-N6 (each
+; byte has two N values of four bits
+; each).
+;49163/C00B Revision number. Mapping author's 800XL and 130XE say 2.
+
+;C0PAGE = $C000 ;49152 (XL) OS ROM, mostly interrupt handlers
+; $C800 51200 (XL) START OF OS ROM
+CHORG2 = $CC00 ;52224 (XL) INTERNATIONAL CHARACTER SET
+
+
+
+;
+;
+; HARDWARE REGISTERS
+;
+;
+; SEE REGISTER LIST FOR MORE INFORMATION
+;
+;
+
+; GTIA
+GTIA = $D000
+HPOSP0 = $D000 ;53248 (W) ; P/M positions (no shadows)
+HPOSP1 = $D001 ;53249 (W)
+HPOSP2 = $D002 ;53250 (W)
+HPOSP3 = $D003 ;53251 (W)
+HPOSM0 = $D004 ;53252 (W)
+HPOSM1 = $D005 ;53253 (W)
+HPOSM2 = $D006 ;53254 (W)
+HPOSM3 = $D007 ;53255 (W)
+SIZEP0 = $D008 ;53256 (W) ; P/M size regs (no shadows)
+SIZEP1 = $D009 ;53257 (W)
+SIZEP2 = $D00A ;53258 (W)
+SIZEP3 = $D00B ;53259 (W)
+SIZEM = $D00C ;53260 (W)
+M0PF = $D000 ;53248 (R) ; collision regs (no shadows)
+M1PF = $D001 ;53249 (R)
+M2PF = $D002 ;53250 (R)
+M3PF = $D003 ;53251 (R)
+P0PF = $D004 ;53252 (R)
+P1PF = $D005 ;53253 (R)
+P2PF = $D006 ;53254 (R)
+P3PF = $D007 ;53255 (R)
+M0PL = $D008 ;53256 (R)
+M1PL = $D009 ;53257 (R)
+M2PL = $D00A ;53258 (R)
+M3PL = $D00B ;53259 (R)
+P0PL = $D00C ;53260 (R)
+P1PL = $D00D ;53261 (R)
+P2PL = $D00E ;53262 (R)
+P3PL = $D00F ;53263 (R)
+GRAFP0 = $D00D ;53261 (W) ; direct (non-DMA) P/M graphics regs (no shadows)
+GRAFP1 = $D00E ;53262 (W)
+GRAFP2 = $D00F ;53263 (W)
+GRAFP3 = $D010 ;53264 (W)
+GRAFM = $D011 ;53265 (W)
+TRIG0 = $D010 ;53264 (R) ; Joystick triggers (shadows @ STRIG0-3)
+TRIG1 = $D011 ;53265 (R)
+TRIG2 = $D012 ;53266 (R)
+TRIG3 = $D013 ;53267 (R)
+PAL = $D014 ;53268 (R) ; PAL/NTSC detect (no shadow)
+ ; PAL supposedly moved to XL_PALNTS on XL; what was it
+ ; replaced with?
+COLPM0 = $D012 ;53266 (W) ; P/M colors (shadows @ PCOLR0-3)
+COLPM1 = $D013 ;53267 (W)
+COLPM2 = $D014 ;53268 (W)
+COLPM3 = $D015 ;53269 (W)
+COLPF0 = $D016 ;53270 (W) ; Playfield colors (shadows @ COLOR0-3)
+COLPF1 = $D017 ;53271 (W)
+COLPF2 = $D018 ;53272 (W)
+COLPF3 = $D019 ;53273 (W)
+COLBK = $D01A ;53274 (W) ; Background color (shadow @ COLOR4)
+PRIOR = $D01B ;53275 (W) ; GTIA priority (shadow @ GPRIOR)
+GTIAR = $D01B ;53275 (R?)
+VDELAY = $D01C ;53276 (W)
+GRACTL = $D01D ;53277 (W)
+HITCLR = $D01E ;53278 (W), latch
+CONSOL = $D01F ;53279 (W=keyclick spkr, R=console keys)
+
+; $D020 - $D0FF are mirrors of GTIA address space
+; $D100 - $D1FF are supposed to be unused (unmapped) on the 800
+; On the XL, $D100 - $D1FF is switched to device memory during PBI I/O
+
+; POKEY
+POKEY = $D200
+; no shadows for AUDC/AUDF
+AUDF1 = $D200 ;53760 (W) ; Audio frequency 1
+AUDC1 = $D201 ;53761 (W) ; Audio control 1 (distortion/volume)
+AUDF2 = $D202 ;53762 (W)
+AUDC2 = $D203 ;53763 (W)
+AUDF3 = $D204 ;53764 (W)
+AUDC3 = $D205 ;53765 (W)
+AUDF4 = $D206 ;53766 (W)
+AUDC4 = $D207 ;53767 (W)
+
+; POT0-7 shadows at PADDL0-7
+POT0 = $D200 ;53760 (R) ; Paddle positions
+POT1 = $D201 ;53761 (R)
+POT2 = $D202 ;53762 (R)
+POT3 = $D203 ;53763 (R)
+POT4 = $D204 ;53764 (R) ; pots 3-7 don't exist on XL/XE
+POT5 = $D205 ;53765 (R)
+POT6 = $D206 ;53766 (R)
+POT7 = $D207 ;53767 (R)
+
+AUDCTL = $D208 ;53768 (W) ; Audio control (no shadow)
+ALLPOT = $D208 ;53768 (R) (no shadow)
+STIMER = $D209 ;53769 (W) (no shadow)
+KBCODE = $D209 ;53769 (R) (shadow @ CH)
+SKREST = $D20A ;53770 (W) (latch)
+RANDOM = $D20A ;53770 (R) (no shadow)
+POTGO = $D20B ;53771 (W) (latch)
+; $D20C (53772) is unused
+SEROUT = $D20D ;53773 (W) (no shadow)
+SERIN = $D20D ;53773 (R) (no shadow)
+IRQEN = $D20E ;53774 (W) (shadow @ POKMSK)
+IRQST = $D20E ;53774 (R)
+SKCTL = $D20F ;53775 (W) (shadow @ SSKCTL)
+SKSTAT = $D20F ;53775 (R)
+
+; $D210 - $D2FF are mirrors of POKEY address space. The "stereo POKEY"
+; modification adds a second POKEY chip, usually addressed at $D210.
+
+; PIA
+; No shadow regs for PIA regs
+PIA = $D300
+PORTA = $D300 ;54016
+PORTB = $D301 ;54017
+PACTL = $D302 ;54018
+PBCTL = $D303 ;54019
+
+; $D304 - $D3FF are mirrors of PIA address space
+
+; ANTIC
+ANTIC = $D400
+DMACTL = $D400 ;54272 (W) (shadow @ SDMCTL)
+CHACTL = $D401 ;54273 (W) (shadow @ CHACT)
+DLISTL = $D402 ;54274 (W) (shadow @ SDLSTL)
+DLISTH = $D403 ;54275 (W) (shadow @ SDLSTH)
+HSCROL = $D404 ;54276 (W) (no shadow)
+VSCROL = $D405 ;54277 (W) (no shadow)
+; $D406 (54278) is unused
+PMBASE = $D407 ;54279 (W) (no shadow)
+; $D408 (54280) is unused
+CHBASE = $D409 ;54281 (W) (shadow @ CHBAS)
+WSYNC = $D40A ;54282 (W), latch (data written doesn't matter)
+VCOUNT = $D40B ;54283 (R) (no shadow)
+PENH = $D40C ;54284 (R) (shadow @ LPENH)
+PENV = $D40D ;54285 (R) (shadow @ LPENV)
+NMIEN = $D40E ;54286 (W) (no shadow)
+NMIRES = $D40F ;54287 (W), latch?
+NMIST = $D40F ;54287 (R) (no shadow)
+
+; $D410 - $D4FF are mirrors of ANTIC address space
+
+CCNTL = $D500 ;54528 Cartridge control (sometimes used for bankswitching)
+; $D500 - $D5FF is supposed to be all be mapped to CCNTL
+
+; $D600 - $D7FF is unmapped? used by PBI on XL? seems to read all $FF
+
+;
+; FLOATING POINT MATH ROUTINES
+;
+; From Mapping:
+; These entry points are the same on 400/800 and XL OS, though the
+; routines themselves are different (bugfixed/optimized for XL)
+; Also, on the XL, the $D800 area is bankswitched to PBI device ROM,
+; during PBI I/O. Not sure if all of $D800 - $DFFF is switched out
+; or just part of it.
+AFP = $D800 ;55296 ASCII to Floating Point (FP) conversion.
+FASC = $D8E6 ;55526 FP value to ASCII conversion.
+IFP = $D9AA ;55722 Integer to FP conversion
+FPI = $D9D2 ;55762 FP to Integer conversion
+ZFR0 = $DA44 ;55876 Clear FR0 (set all bytes to 0)
+ZF1 = $DA46 ;55878 Clear FR1 (set all bytes to 0) (aka AF1 (De Re))
+FSUB = $DA60 ;55904 FP subtract: FR0 = FR0 - FR1
+FADD = $DA66 ;55910 FP add: FR0 = FR0 + FR1
+FMUL = $DADB ;56027 FP multiply: FR0 = FR0 * FR1
+FDIV = $DB28 ;56104 FP divide: FR0 = FR0 / FR1
+PLYEVL = $DD40 ;56640 FP polynomial evaluation
+FLD0R = $DD89 ;56713 Load FP number into FR0 from 6502 X/Y registers
+FLD0P = $DD8D ;56717 Load FP number into FR0 from FLPTR
+FLD1R = $DD98 ;56728 Load FP number into FR1 from 6502 X/Y registers
+FLD1P = $DD9C ;56732 Load FP number into FR1 from FLPTR
+FST0R = $DDA7 ;56743 Store FP number into 6502 X/Y regs from FR0
+FST0P = $DDAB ;56747 Store FP number from FR0, using FLPTR
+FMOVE = $DDB6 ;56758 Move FP number from FR0 into FR1 (FR1 = FR0)
+EXP = $DDC0 ;56768 FP base e exponentiation
+EXP10 = $DDCC ;56780 FP base 10 exponentiation
+LOG = $DECD ;57037 FP natural logarithm
+LOG10 = $DED1 ;57041 FP base 10 logarithm
+
+;
+;
+; OPERATING SYSTEM
+;
+;
+; MODULE ORIGIN TABLE
+;
+CHORG = $E000 ;57344 CHARACTER SET, 1K
+VECTBL = $E400 ;58368 VECTOR TABLE
+VCTABL = $E480 ;58496 RAM VECTOR INITIAL VALUE TABLE
+CIOORG = $E4A6 ;58534 CIO HANDLER
+INTORG = $E6D5 ;59093 INTERRUPT HANDLER
+SIOORG = $E944 ;59716 SIO DRIVER
+DSKORT = $EDEA ;60906 DISK HANDLER
+PRNORG = $EE78 ;61048 PRINTER HANDLER
+CASORG = $EE78 ;61048 CASSETTE HANDLER
+MONORG = $F0E3 ;61667 MONITOR/POWER UP MODULE
+KBDORG = $F3E4 ;62436 KEYBOARD/DISPLAY HANDLER
+;
+;
+; VECTOR TABLE, CONTAINS ADDRESSES OF CIO ROUTINES IN THE
+; FOLLOWING ORDER. THE ADDRESSES IN THE TABLE ARE TRUE ADDRESSES-1
+;
+; ADDRESS + 0 OPEN
+; + 2 CLOSE
+; + 4 GET
+; + 6 PUT
+; + 8 STATUS
+; + A SPECIAL
+; + C JMP TO INITIALIZATION
+; + F NOT USED
+;
+;
+
+; 20070529 bkw: why are they address minus one? because they are called
+; via RTS: a JSR actually pushes the return address minus one, and RTS
+; increments the address on the stack after popping it. The Atari OS
+; "pretends" to have done a JSR by pushing the address-1 on the stack,
+; then executes RTS, which "returns" to the correct address.
+
+EDITRV = $E400 ;58368 EDITOR
+SCRENV = $E410 ;58384 SCREEN
+KEYBDV = $E420 ;58400 KEYBOARD
+PRINTV = $E430 ;58416 PRINTER
+CASETV = $E440 ;58432 CASSETTE
+;
+; ROM VECTORS
+;
+; 20070529 bkw: These consist of a JMP xxxx instruction in the ROM.
+DSKINV = $E453 ;58451
+CIOV = $E456 ;58454 ; Main CIO entry point!
+SIOV = $E459 ;58457 ; Main SIO entry point!
+SETVBV = $E45C ;58460
+SYSVBV = $E45F ;58463
+VBIVAL = $E460 ;58464 ADR AT VVBLKI (operand of JMP @ $E45F)
+XITVBV = $E462 ;58466 EXIT VBI
+VBIXVL = $E463 ;58467 ADR AT VVBLKD (operand of JMP @ $E462)
+SIOINV = $E465 ;58469
+SENDEV = $E468 ;58472
+INTINV = $E46B ;58475
+CIOINV = $E46E ;58478
+BLKBDV = $E471 ;58481 MEMO PAD MODE (self-test in XL)
+WARMSV = $E474 ;58484 ; warmstart (RESET key jumps here)
+COLDSV = $E477 ;58487 ; coldstart (reboot) the Atari
+RBLOKV = $E47A ;58490
+CSOPIV = $E47D ;58493
+
+; SYSEQU.ASM defines this:
+CIO = CIOV
+
+; XL-only entry points:
+XL_SELFSV = BLKBDV ; self-test (same entry point as 800 memo pad)
+XL_SELFTST = BLKBDV ; alt. name (Mapping)
+XL_PUPDIV = $E480 ;58496 (XL) Power-up ATARI logo (1200XL only), or self-test
+XL_SLFTSV = $E483 ;58499 (XL) Self-test vector (points to $5000)
+XL_PENTV = $E486 ;58502 (XL) Entry to the handler uploaded from peripheral
+ ; or disk (is this for the PBI?)
+XL_PHUNLV = $E489 ;58505 (XL) Entry to uploaded handler unlink (PBI?)
+XL_PHINIV = $E48C ;58508 (XL) Entry to uploaded handler init (PBI?)
+XL_GPDVV = $E48F ;58511 (XL) General-purpose parallel device handler
+ ; (copy to HATABS to use)
+
+;;;;; Here endeth the list of official mnemonics
+
+; Mapping has this to say about the XL ROMs:
+;Byte Use
+;65518/FFEE Revision date D1 and D2 (four-bit BCD)
+;65519/FFEF Revision date M1 and M2
+;65520/FFF0 Revision date Y1 and Y2
+;65521/FFF1 Option byte; should read 1 for the
+; 1200XL (Mapping author's 800XL reads 2)
+;65522-26/FFF2-6 Part number in the form AANNNNNN
+;65527/FFF7 Revision number (again, mine reads 2)
+;65528-9/FFF8-9 Checksum, bytes (LSB/MSB)
+; There don't seem to be any known mnemonics for the above...
+
+; 20061120 bkw: display list stuff. These are not official Atari mnemonics,
+; but they *are* somewhat based on the "Checkers Demo" by Carol Shaw,
+; in the Atari Hardware Manual (she didn't define all these, and she didn't
+; use the "DL_" prefix, probably because her assembler was limited to
+; 6-character labels and/or didn't support the underscore).
+
+; blank lines, 1-8 scanlines high
+DL_BLANK1 = $00
+DL_BLANK2 = $10
+DL_BLANK3 = $20
+DL_BLANK4 = $30
+DL_BLANK5 = $40
+DL_BLANK6 = $50
+DL_BLANK7 = $60
+DL_BLANK8 = $70
+
+; modifier bits..
+DL_VSCROLL = $10
+DL_HSCROLL = $20
+DL_LMS = $40
+DL_DLI = $80
+
+; graphics modes (these are the BASIC modes)
+; If you're more familiar with the ANTIC modes, nobody's forcing you
+; to use these :)
+DL_GR0 = $02
+DL_GR1 = $06
+DL_GR2 = $07
+DL_GR3 = $08
+DL_GR4 = $09
+DL_GR5 = $0A
+DL_GR6 = $0B
+DL_GR7 = $0D
+DL_GR8 = $0F
+DL_GR12 = $04 ; GR. 12-15 only supported by GRAPHICS command on XL/XE,
+DL_GR13 = $05 ; but they exist on all ANTIC revisions
+DL_GR14 = $0C
+DL_GR15 = $0E ; AKA "graphics 7.5"
+; No GRAPHICS mode for ANTIC $03 (true descender) mode
+
+; jump instructions
+DL_JMP = $01 ; jump without vertical blank (used to skip over 1K boundary)
+DL_JVB = $41 ; jump & wait for VBLANK (end of display list)
+
+; How to use the above: here's a sample display list for GR.0, with a DLI
+; on screen line 10.
+
+; dlist:
+; ; 4*8 = 32 blank lines at start of display
+; byte DL_BLANK8, DL_BLANK8, DL_BLANK8, DL_BLANK8
+;
+; byte DL_GR0 | DL_LMS ; display GR.0 line, and load screen memory address..
+; word screen_ram ; ...from our screen memory (declared elsewhere)
+;
+; ; 8 more GR.0 lines
+; byte DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0
+;
+; byte DL_GR0 | DL_DLI ; another GR.0 line, with the DLI bit enabled
+;
+; ; lines 11-24 (14 more GR.0 bytes)
+; byte DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0
+; byte DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0, DL_GR0
+;
+; ; that's 24 lines, so finish with a VBLANK
+; byte DL_JVB ; jump (and wait), to...
+; word dlist ; ...the beginning.
diff --git a/src/features.h b/src/features.h
new file mode 100644
index 0000000..ec7d194
--- /dev/null
+++ b/src/features.h
@@ -0,0 +1,102 @@
+#ifndef FEATURES_H
+#define FEATURES_H
+
+
+// #define FEAT_COL64_HACK
+// #define FEAT_COL80_HACK
+
+#ifdef FEAT_COL64_HACK
+#define COLUMNS 64
+#define FEAT_COL80_HACK
+#endif
+
+#if defined(FEAT_TINY) && defined(FEAT_COL80_HACK)
+#error "You may not define both FEAT_TINY and FEAT_COL80_HACK"
+#endif
+
+#ifdef FEAT_TINY
+
+#define FEAT_LOW_RAM_BUFFERS
+#undef FEAT_DYNAMIC_VERSION
+#undef FEAT_VISUAL_BELL
+#undef FEAT_CURSOR_CONTROLS
+#undef FEAT_KEYBOARD_MACROS
+#undef FEAT_TRAFFIC_INDICATOR
+#undef FEAT_ATRACT_AWAY
+#undef FEAT_KEYBOARD_BUFFER
+#undef FEAT_COLOR_COMMAND
+
+#elif defined(FEAT_COL80_HACK)
+
+#define FEAT_LOW_RAM_BUFFERS
+#define FEAT_VISUAL_BELL
+#define FEAT_KEYBOARD_MACROS
+// #define FEAT_TRAFFIC_INDICATOR
+#define FEAT_KEYBOARD_BUFFER
+#define FEAT_COLOR_COMMAND
+
+/* COL80 hack uses 9K of high RAM, so let's disable
+ some bells & whistles. */
+#undef FEAT_DYNAMIC_VERSION
+#undef FEAT_ATRACT_AWAY
+
+/* Do not enable cursor controls with COL80 hack, because they don't work
+ anyway (arrows and deletes not implemented in the driver). Not needed
+ anyway, fujichat.c contains code that does the same thing when COL80
+ is enabled (slower though) */
+#undef FEAT_CURSOR_CONTROLS
+
+#else
+/* Removable features. Compiling with everything turned off
+ (except FEAT_LOW_RAM_BUFFERS!) saves us around 1322 bytes at
+ runtime (including data/bss) */
+
+/* Keep our bigger buffers in low memory, where possible. Saves
+ space in the DATA segment, allowing MEMTOP to be set lower
+ (to make room for more scrollback, or an 80-col driver, etc) */
+#define FEAT_LOW_RAM_BUFFERS
+
+/* Make CTCP version response say "Atari 8-bit" instead of calling
+ get_ostype(). Saves 179 bytes in executable. */
+#define FEAT_DYNAMIC_VERSION
+
+/* Support visual bell. Saves 110 bytes in exe when undef'd. */
+// TODO: make fujiconf not ask about visual bell, too
+#define FEAT_VISUAL_BELL
+
+/* Don't use cursor controls to keep from splitting up the user's
+ edit buffer when packets come in while he's typing. The 80-column
+ version will probably need this disabled.
+ Saves 410 bytes in exe. */
+#define FEAT_CURSOR_CONTROLS
+
+/* Disable the keyboard macros (^W, ^N, Tab at start of line). Saves
+ about 230 bytes in exe. */
+#define FEAT_KEYBOARD_MACROS
+
+/* Have the rs232dev code display up/down arrows in top right of
+ screen. Accesses screen RAM directly, don't use with 80 cols. */
+#define FEAT_TRAFFIC_INDICATOR
+
+/* Set /away on the server when Atari goes into attract mode,
+ clear when user presses a key */
+#define FEAT_ATRACT_AWAY
+
+/* Experimental logging (backlog, scrollback) support. Expect trouble. */
+// TODO: implement!
+// #define FEAT_LOGGING
+
+/* Disable the keyboard prebuffering during serial I/O */
+#define FEAT_KEYBOARD_BUFFER
+
+/* Support /bgcolor and /fgcolor command in FujiChat (instead of having to go
+ back to setup menu to change text colors) */
+#define FEAT_COLOR_COMMAND
+
+/* messing around, not functional yet */
+// #define FEAT_UNICODE_TEST
+
+/* End of features */
+
+#endif
+#endif
diff --git a/src/fuji6432.atr b/src/fuji6432.atr
new file mode 100644
index 0000000..f77c6dd
--- /dev/null
+++ b/src/fuji6432.atr
Binary files differ
diff --git a/src/fuji80.atr b/src/fuji80.atr
new file mode 100644
index 0000000..d8757ba
--- /dev/null
+++ b/src/fuji80.atr
Binary files differ
diff --git a/src/fuji_asm.s b/src/fuji_asm.s
new file mode 100644
index 0000000..2d9f205
--- /dev/null
+++ b/src/fuji_asm.s
@@ -0,0 +1,3016 @@
+;
+; File generated by cc65 v 2.12.9
+;
+ .fopt compiler,"cc65 v 2.12.9"
+ .setcpu "6502"
+ .smart on
+ .autoimport on
+ .case on
+ .debuginfo off
+ .importzp sp, sreg, regsave, regbank, tmp1, ptr1, ptr2
+ .macpack longbranch
+ .import _stdout
+ .import _fflush
+ .import _fputs
+ .import _printf
+ .import _putchar
+ .import _puts
+ .import _sprintf
+ .import _atoi
+ .import _exit
+ .import _strcmp
+ .import _strcpy
+ .import _strlen
+ .import _memcmp
+ .import _memcpy
+ .import _strcasecmp
+ .import _toupper
+ .import _get_ostype
+ .import _kbhit
+ .import _cgetc
+ .import _cursor
+ .import __clocks_per_sec
+ .import _clock
+ .import _timer_set
+ .import _timer_reset
+ .import _timer_expired
+ .export _resolv_found
+ .import _resolv_conf
+ .import _resolv_init
+ .import _resolv_query
+ .import _telnet_send
+ .export _telnet_connected
+ .export _telnet_closed
+ .export _telnet_sent
+ .export _telnet_aborted
+ .export _telnet_timedout
+ .export _telnet_newdata
+ .import _uip_init
+ .import _uip_connect
+ .import _htons
+ .import _uip_len
+ .import _uip_conn
+ .import _uip_conns
+ .import _uip_udp_conn
+ .import _uip_udp_conns
+ .import _uip_flags
+ .import _uip_process
+ .import _uip_hostaddr
+ .import _uip_netmask
+ .import _uip_draddr
+ .import _uiplib_ipaddrconv
+ .import _rs232dev_init
+ .import _rs232dev_send
+ .import _rs232dev_close
+ .import _rs232dev_poll
+ .import _atari_exec_p
+ .import _config
+ .import _format_ip
+ .import _get_config
+ .import _config_is_valid
+ .import _get_line
+ .import _set_default_config
+ .import _disable_break
+ .export _os_version
+ .export _input_buf
+ .export _chan_msg_buf
+ .export _output_buf
+ .export _channel
+ .export _last_msg_nick
+ .export _input_buf_len
+ .export _output_buf_len
+ .export _done
+ .export _connected
+ .export _joined_channel
+ .export _nick_registered
+ .export _vbell_active
+ .export _bell
+ .export _redraw_user_buffer
+ .export _nick_reg_timer
+ .export _tstate
+ .export _vbell_timer
+ .export _main
+ .export _do_pong
+ .export _do_server_msg
+ .export _do_ctcp
+ .export _do_msg
+ .export _del_user_buffer
+
+.segment "DATA"
+
+_os_version:
+ .byte $58,$4C,$5F,$58,$45,$00
+ .res 4,$00
+_input_buf:
+ .word $2900
+_chan_msg_buf:
+ .word $2A00
+_output_buf:
+ .word $2C00
+_last_msg_nick:
+ .byte $00
+ .res 20,$00
+_input_buf_len:
+ .word $0000
+_output_buf_len:
+ .word $0000
+_done:
+ .byte $00
+_connected:
+ .byte $00
+_joined_channel:
+ .byte $00
+_nick_registered:
+ .byte $00
+_vbell_active:
+ .byte $00
+
+.segment "RODATA"
+
+L0001:
+ .byte $38,$30,$30,$00,$31,$32,$30,$30,$58,$4C,$00,$C6,$F5,$EA,$E9,$C3
+ .byte $E8,$E1,$F4,$20,$76,$30,$2E,$35,$00,$53,$65,$72,$76,$65,$72,$20
+ .byte $6E,$61,$6D,$65,$2F,$49,$50,$2C,$20,$5B,$43,$5D,$6F,$6E,$66,$69
+ .byte $67,$2C,$20,$6F,$72,$20,$5B,$44,$5D,$4F,$53,$9B,$00,$5B,$25,$73
+ .byte $5D,$3A,$20,$00,$64,$00,$63,$00,$44,$3A,$46,$55,$4A,$49,$43,$4F
+ .byte $4E,$46,$2E,$43,$4F,$4D,$00,$45,$72,$72,$6F,$72,$20,$25,$64,$21
+ .byte $9B,$00,$2A,$20,$52,$65,$67,$69,$73,$74,$65,$72,$69,$6E,$67,$20
+ .byte $6E,$69,$63,$6B,$00,$4E,$49,$43,$4B,$20,$25,$73,$25,$63,$55,$53
+ .byte $45,$52,$20,$25,$73,$20,$25,$73,$20,$25,$73,$20,$3A,$25,$73,$25
+ .byte $63,$00,$46,$75,$6A,$69,$43,$68,$61,$74,$00,$43,$6F,$6D,$6D,$61
+ .byte $6E,$64,$20,$72,$65,$71,$75,$69,$72,$65,$73,$20,$61,$72,$67,$75
+ .byte $6D,$65,$6E,$74,$00,$59,$6F,$75,$20,$61,$72,$65,$20,$6E,$6F,$74
+ .byte $20,$69,$6E,$20,$61,$20,$63,$68,$61,$6E,$6E,$65,$6C,$20,$28,$75
+ .byte $73,$65,$20,$2F,$6A,$6F,$69,$6E,$20,$23,$63,$68,$61,$6E,$6E,$65
+ .byte $6C,$29,$00,$59,$6F,$75,$20,$61,$72,$65,$20,$61,$6C,$72,$65,$61
+ .byte $64,$79,$20,$69,$6E,$20,$61,$20,$63,$68,$61,$6E,$6E,$65,$6C,$20
+ .byte $28,$75,$73,$65,$20,$2F,$70,$61,$72,$74,$20,$74,$6F,$20,$6C,$65
+ .byte $61,$76,$65,$29,$00,$4E,$41,$4D,$45,$53,$00,$57,$48,$4F,$00,$2F
+ .byte $6D,$73,$67,$20,$25,$73,$20,$00,$50,$52,$49,$56,$4D,$53,$47,$20
+ .byte $25,$73,$20,$3A,$25,$73,$00,$25,$73,$20,$25,$73,$25,$63,$00,$25
+ .byte $73,$25,$63,$00,$50,$52,$49,$56,$4D,$53,$47,$20,$25,$73,$20,$25
+ .byte $63,$56,$45,$52,$53,$49,$4F,$4E,$25,$63,$25,$63,$00,$50,$52,$49
+ .byte $56,$4D,$53,$47,$20,$25,$73,$20,$25,$63,$50,$49,$4E,$47,$20,$25
+ .byte $30,$33,$64,$20,$25,$30,$33,$64,$20,$25,$30,$33,$64,$25,$63,$25
+ .byte $63,$00,$50,$52,$49,$56,$4D,$53,$47,$20,$25,$73,$20,$3A,$25,$63
+ .byte $41,$43,$54,$49,$4F,$4E,$20,$25,$73,$25,$63,$25,$63,$00,$4D,$45
+ .byte $00,$4D,$53,$47,$00,$4D,$00,$50,$52,$49,$56,$4D,$53,$47,$00,$4A
+ .byte $4F,$49,$4E,$00,$4A,$00,$4A,$4F,$49,$4E,$00,$4A,$4F,$49,$4E,$00
+ .byte $50,$41,$52,$54,$00,$50,$41,$52,$54,$00,$56,$45,$52,$53,$49,$4F
+ .byte $4E,$00,$56,$45,$52,$00,$50,$49,$4E,$47,$00,$4E,$49,$43,$4B,$00
+ .byte $2A,$20,$59,$6F,$75,$20,$61,$72,$65,$20,$6E,$6F,$77,$20,$6B,$6E
+ .byte $6F,$77,$6E,$20,$61,$73,$20,$25,$73,$9B,$00,$51,$55,$4F,$54,$45
+ .byte $00,$43,$6F,$6E,$6E,$65,$63,$74,$65,$64,$20,$74,$6F,$20,$73,$65
+ .byte $72,$76,$65,$72,$00,$43,$6F,$6E,$6E,$65,$63,$74,$69,$6F,$6E,$20
+ .byte $63,$6C,$6F,$73,$65,$64,$00,$43,$6F,$6E,$6E,$65,$63,$74,$69,$6F
+ .byte $6E,$20,$61,$62,$6F,$72,$74,$65,$64,$00,$43,$6F,$6E,$6E,$65,$63
+ .byte $74,$69,$6F,$6E,$20,$74,$69,$6D,$65,$64,$20,$6F,$75,$74,$00,$5B
+ .byte $50,$49,$4E,$47,$2C,$50,$4F,$4E,$47,$5D,$00,$2A,$20,$54,$6F,$70
+ .byte $69,$63,$3A,$20,$25,$73,$00,$2A,$20,$54,$6F,$70,$69,$63,$20,$73
+ .byte $65,$74,$20,$62,$79,$20,$25,$73,$00,$2A,$20,$48,$69,$64,$69,$6E
+ .byte $67,$20,$4D,$4F,$54,$44,$20,$28,$62,$65,$20,$70,$61,$74,$69,$65
+ .byte $6E,$74,$29,$00,$25,$64,$20,$25,$73,$00,$25,$73,$20,$25,$73,$00
+ .byte $50,$49,$4E,$47,$20,$00,$2A,$20,$25,$73,$20,$70,$69,$6E,$67,$20
+ .byte $74,$69,$6D,$65,$3A,$20,$25,$64,$2E,$25,$64,$9B,$00,$50,$52,$49
+ .byte $56,$4D,$53,$47,$00,$01,$41,$43,$54,$49,$4F,$4E,$20,$00,$2A,$20
+ .byte $25,$73,$20,$25,$73,$00,$25,$73,$20,$25,$73,$00,$01,$50,$49,$4E
+ .byte $47,$20,$00,$4E,$4F,$54,$49,$43,$45,$20,$25,$73,$20,$3A,$01,$50
+ .byte $49,$4E,$47,$20,$25,$73,$01,$25,$63,$00,$2A,$20,$43,$54,$43,$50
+ .byte $20,$50,$49,$4E,$47,$20,$66,$72,$6F,$6D,$20,$25,$73,$9B,$00,$01
+ .byte $56,$45,$52,$53,$49,$4F,$4E,$01,$00,$4E,$4F,$54,$49,$43,$45,$20
+ .byte $25,$73,$20,$3A,$01,$56,$45,$52,$53,$49,$4F,$4E,$20,$46,$75,$6A
+ .byte $69,$43,$68,$61,$74,$20,$76,$30,$2E,$35,$20,$2D,$20,$72,$75,$6E
+ .byte $6E,$69,$6E,$67,$20,$6F,$6E,$20,$61,$6E,$20,$41,$74,$61,$72,$69
+ .byte $20,$25,$73,$01,$25,$63,$00,$2A,$20,$43,$54,$43,$50,$20,$56,$45
+ .byte $52,$53,$49,$4F,$4E,$20,$66,$72,$6F,$6D,$20,$25,$73,$9B,$00,$4D
+ .byte $53,$47,$3A,$20,$25,$73,$20,$25,$73,$00,$4E,$4F,$54,$49,$43,$45
+ .byte $00,$2A,$20,$43,$54,$43,$50,$20,$72,$65,$70,$6C,$79,$20,$66,$72
+ .byte $6F,$6D,$20,$25,$73,$3A,$20,$25,$73,$00,$25,$73,$20,$25,$73,$20
+ .byte $25,$73,$20,$25,$73,$00,$25,$73,$20,$25,$73,$20,$25,$73,$00,$5B
+ .byte $62,$75,$66,$66,$65,$72,$20,$6F,$76,$65,$72,$66,$6C,$6F,$77,$5D
+ .byte $FD,$00,$50,$49,$4E,$47,$00,$48,$6F,$73,$74,$20,$27,$25,$73,$27
+ .byte $20,$6E,$6F,$74,$20,$66,$6F,$75,$6E,$64,$2E,$9B,$00,$25,$73,$20
+ .byte $69,$73,$20,$25,$73,$9B,$00
+
+.segment "BSS"
+
+_channel:
+ .res 64,$00
+_nick_reg_timer:
+ .res 4,$00
+_tstate:
+ .res 2,$00
+_vbell_timer:
+ .res 4,$00
+
+; ---------------------------------------------------------------
+; void __near__ resolv_found (__near__ unsigned char*, __near__ unsigned int*)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _resolv_found: near
+
+.segment "CODE"
+
+ ldy #$00
+ lda (sp),y
+ iny
+ ora (sp),y
+ bne L0501
+ lda #<(L0001+967)
+ ldx #>(L0001+967)
+ jsr pushax
+ ldy #$07
+ jsr pushwysp
+ ldy #$04
+ jsr _printf
+ lda #$01
+ sta _done
+ jmp incsp4
+L0501: lda #<(L0001+989)
+ ldx #>(L0001+989)
+ jsr pushax
+ ldy #$07
+ jsr pushwysp
+ ldy #$07
+ jsr pushwysp
+ jsr _format_ip
+ jsr pushax
+ ldy #$06
+ jsr _printf
+ lda _connected
+ jne incsp4
+ jsr pushw0sp
+ lda _config
+ ldx _config+1
+ ldy #$53
+ jsr pushwidx
+ jsr _htons
+ jsr pushax
+ jsr _uip_connect
+ jmp incsp4
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ telnet_connected (__near__ struct telnet_state*)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _telnet_connected: near
+
+.segment "CODE"
+
+ lda #<(L0001+513)
+ ldx #>(L0001+513)
+ jsr _puts
+ jsr ldax0sp
+ sta _tstate
+ stx _tstate+1
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$01
+ sta (sreg),y
+ iny
+ sta (sreg),y
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$03
+ sta (sreg),y
+ iny
+ sta (sreg),y
+ lda #<(_nick_reg_timer)
+ ldx #>(_nick_reg_timer)
+ jsr pushax
+ jsr __clocks_per_sec
+ jsr pushax
+ jsr _timer_set
+ lda #$01
+ sta _connected
+ jmp incsp2
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ telnet_closed (__near__ struct telnet_state*)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _telnet_closed: near
+
+.segment "CODE"
+
+ lda #<(L0001+533)
+ ldx #>(L0001+533)
+ jsr _puts
+ lda #$10
+ sta _uip_flags
+ lda #$01
+ sta _done
+ jmp incsp2
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ telnet_sent (__near__ struct telnet_state*)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _telnet_sent: near
+
+.segment "CODE"
+
+ jmp incsp2
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ telnet_aborted (__near__ struct telnet_state*)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _telnet_aborted: near
+
+.segment "CODE"
+
+ lda #<(L0001+551)
+ ldx #>(L0001+551)
+ jsr _puts
+ lda #$20
+ sta _uip_flags
+ lda #$01
+ sta _done
+ jmp incsp2
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ telnet_timedout (__near__ struct telnet_state*)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _telnet_timedout: near
+
+.segment "CODE"
+
+ lda #<(L0001+570)
+ ldx #>(L0001+570)
+ jsr _puts
+ lda #$20
+ sta _uip_flags
+ lda #$01
+ sta _done
+ jmp incsp2
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ telnet_newdata (__near__ struct telnet_state*, __near__ unsigned char*, unsigned int)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _telnet_newdata: near
+
+.segment "CODE"
+
+ jsr pushw0sp
+ jsr decsp1
+ ldy #$08
+ jsr pushwysp
+ jsr pushc0
+L04AF: ldy #$05
+ jsr ldaxysp
+ sta regsave
+ stx regsave+1
+ jsr decax1
+ ldy #$04
+ jsr staxysp
+ lda regsave
+ ora regsave+1
+ jeq L04B0
+ ldy #$02
+ jsr ldaxysp
+ sta regsave
+ stx regsave+1
+ jsr incax1
+ ldy #$01
+ jsr staxysp
+ ldy #$00
+ lda (regsave),y
+ ldy #$03
+ sta (sp),y
+ cmp #$0A
+ beq L04AF
+ lda (sp),y
+ cmp #$0D
+ bne L04B8
+ lda #$9B
+ sta (sp),y
+ lda #$01
+ ldy #$00
+ jmp L0515
+L04B8: lda (sp),y
+ cmp #$09
+ bne L04BF
+ lda #$7F
+ jmp L0515
+L04BF: lda (sp),y
+ cmp #$7B
+ bne L04C4
+ lda #$DB
+ jmp L0515
+L04C4: lda (sp),y
+ cmp #$7D
+ bne L04C9
+ lda #$DD
+ jmp L0515
+L04C9: lda (sp),y
+ cmp #$7E
+ bne L04CE
+ lda #$DE
+ jmp L0515
+L04CE: lda (sp),y
+ cmp #$60
+ bne L04D3
+ lda #$A7
+L0515: sta (sp),y
+L04D3: lda _output_buf
+ ldx _output_buf+1
+ jsr pushax
+ lda _output_buf_len
+ ldx _output_buf_len+1
+ sta regsave
+ stx regsave+1
+ jsr incax1
+ sta _output_buf_len
+ stx _output_buf_len+1
+ lda regsave
+ ldx regsave+1
+ jsr tosaddax
+ sta sreg
+ stx sreg+1
+ ldy #$03
+ lda (sp),y
+ ldy #$00
+ sta (sreg),y
+ lda _output_buf_len
+ ldx _output_buf_len+1
+ jsr pushax
+ ldx #$02
+ lda #$00
+ jsr tosicmp
+ bmi L04DA
+ lda #<(L0001+943)
+ ldx #>(L0001+943)
+ jsr _puts
+ lda #$01
+ ldy #$00
+ sta (sp),y
+ jmp L04B0
+L04DA: ldy #$00
+ lda (sp),y
+ jeq L04AF
+ jsr _del_user_buffer
+ lda _output_buf
+ ldx _output_buf+1
+ clc
+ adc _output_buf_len
+ pha
+ txa
+ adc _output_buf_len+1
+ tax
+ pla
+ sta sreg
+ stx sreg+1
+ lda #$00
+ tay
+ sta (sreg),y
+ lda _output_buf_len
+ ldx _output_buf_len+1
+ jsr pushax
+ lda #$05
+ jsr tosgea0
+ beq L04E6
+ lda _output_buf
+ ldx _output_buf+1
+ jsr pushax
+ lda #<(L0001+962)
+ ldx #>(L0001+962)
+ jsr pushax
+ ldx #$00
+ lda #$04
+ jsr _memcmp
+ cpx #$00
+ bne L04E6
+ cmp #$00
+ bne L04E6
+ jsr _do_pong
+ jmp L04F5
+L04E6: lda _output_buf
+ ldx _output_buf+1
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$3A
+ bne L04F1
+ jsr _do_msg
+ jmp L04F5
+L04F1: lda _output_buf
+ ldx _output_buf+1
+ jsr pushax
+ lda _stdout
+ ldx _stdout+1
+ jsr _fputs
+ lda _stdout
+ ldx _stdout+1
+ jsr _fflush
+L04F5: jsr _redraw_user_buffer
+ lda #$00
+ sta _output_buf_len
+ sta _output_buf_len+1
+ tay
+ sta (sp),y
+ jmp L04AF
+L04B0: ldy #$0C
+ jmp addysp
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ handle_keystroke (void)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _handle_keystroke: near
+
+.segment "CODE"
+
+ jsr decsp2
+ jsr pushc0
+ jsr _cgetc
+ ldy #$01
+ sta (sp),y
+ lda _input_buf_len
+ ora _input_buf_len+1
+ jne L01A9
+ lda (sp),y
+ cmp #$0E
+ beq L01AB
+ cmp #$17
+ beq L01B2
+ cmp #$7F
+ beq L01BB
+ cmp #$9B
+ jeq incsp3
+ jmp L01A9
+L01AB: lda _joined_channel
+ jeq incsp3
+ lda #<(L0001+277)
+ ldx #>(L0001+277)
+ jsr pushax
+ lda #<(_channel)
+ ldx #>(_channel)
+ jsr pushax
+ jsr _send_server_cmd
+ jmp incsp3
+L01B2: lda _joined_channel
+ jeq incsp3
+ lda #<(L0001+283)
+ ldx #>(L0001+283)
+ jsr pushax
+ lda #<(_channel)
+ ldx #>(_channel)
+ jsr pushax
+ jsr _send_server_cmd
+ jmp incsp3
+L01BB: lda _last_msg_nick
+ jeq incsp3
+ lda _input_buf
+ ldx _input_buf+1
+ jsr pushax
+ lda #<(L0001+287)
+ ldx #>(L0001+287)
+ jsr pushax
+ lda #<(_last_msg_nick)
+ ldx #>(_last_msg_nick)
+ jsr pushax
+ ldy #$06
+ jsr _sprintf
+ lda _input_buf
+ ldx _input_buf+1
+ jsr _strlen
+ sta _input_buf_len
+ stx _input_buf_len+1
+ lda #$00
+ ldy #$02
+L0519: sta (sp),y
+ lda (sp),y
+ jsr pusha0
+ lda _input_buf_len
+ ldx _input_buf_len+1
+ jsr tosicmp
+ jcs incsp3
+ lda _input_buf
+ sta sreg
+ lda _input_buf+1
+ sta sreg+1
+ ldy #$02
+ lda (sp),y
+ clc
+ adc sreg
+ ldx sreg+1
+ bcc L0517
+ inx
+L0517: ldy #$00
+ sta ptr1
+ stx ptr1+1
+ ldx #$00
+ lda (ptr1),y
+ ora #$80
+ jsr _putchar
+ ldy #$02
+ lda (sp),y
+ clc
+ adc #$01
+ jmp L0519
+L01A9: lda (sp),y
+ cmp #$7E
+ bne L01D2
+ lda _input_buf_len
+ ldx _input_buf_len+1
+ jsr pushax
+ lda #$01
+ jsr tosgea0
+ beq L01D4
+ lda _input_buf_len
+ ldx _input_buf_len+1
+ jsr decax1
+ sta _input_buf_len
+ stx _input_buf_len+1
+ ldy #$01
+ ldx #$00
+ lda (sp),y
+ jsr _putchar
+ jmp incsp3
+L01D4: jsr _bell
+ jmp incsp3
+L01D2: lda (sp),y
+ cmp #$9C
+ beq L01DD
+ lda (sp),y
+ cmp #$15
+ bne L01DC
+L01DD: ldx #$00
+ txa
+ sta _input_buf_len
+ sta _input_buf_len+1
+ lda #$9C
+ jsr _putchar
+ jmp incsp3
+L01DC: lda (sp),y
+ cmp #$17
+ bne L01E4
+ jsr _del_last_word
+ jmp incsp3
+L01E4: ldx #$00
+ lda (sp),y
+ ora #$80
+ jsr _putchar
+ ldy #$01
+ lda (sp),y
+ cmp #$9B
+ bne L01E9
+ lda #$0A
+ sta (sp),y
+ tya
+ dey
+ jmp L0518
+L01E9: lda (sp),y
+ cmp #$7F
+ bne L01F0
+ lda #$09
+L0518: sta (sp),y
+L01F0: lda _input_buf
+ ldx _input_buf+1
+ jsr pushax
+ lda _input_buf_len
+ ldx _input_buf_len+1
+ sta regsave
+ stx regsave+1
+ jsr incax1
+ sta _input_buf_len
+ stx _input_buf_len+1
+ lda regsave
+ ldx regsave+1
+ jsr tosaddax
+ sta sreg
+ stx sreg+1
+ ldy #$01
+ lda (sp),y
+ dey
+ sta (sreg),y
+ lda _input_buf_len
+ ldx _input_buf_len+1
+ jsr pushax
+ ldx #$01
+ lda #$00
+ jsr tosicmp
+ bmi L01F9
+ ldy #$00
+ lda (sp),y
+ bne L01F9
+ jsr _bell
+ ldx #$00
+ lda #$7E
+ jsr _putchar
+ lda _input_buf_len
+ ldx _input_buf_len+1
+ jsr decax1
+ sta _input_buf_len
+ stx _input_buf_len+1
+L01F9: ldy #$00
+ lda (sp),y
+ jeq incsp3
+ lda _input_buf
+ ldx _input_buf+1
+ clc
+ adc _input_buf_len
+ pha
+ txa
+ adc _input_buf_len+1
+ tax
+ pla
+ sta sreg
+ stx sreg+1
+ tya
+ sta (sreg),y
+ lda _input_buf
+ sta ptr1
+ lda _input_buf+1
+ sta ptr1+1
+ lda (ptr1),y
+ cmp #$2F
+ bne L0204
+ jsr _handle_command
+ jmp L0214
+L0204: lda _joined_channel
+ beq L0208
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda #<(L0001+296)
+ ldx #>(L0001+296)
+ jsr pushax
+ lda #<(_channel)
+ ldx #>(_channel)
+ jsr pushax
+ lda _input_buf
+ ldx _input_buf+1
+ jsr pushax
+ ldy #$08
+ jsr _sprintf
+ lda _tstate
+ ldx _tstate+1
+ jsr pushax
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr _strlen
+ jsr pushax
+ jsr _telnet_send
+ jmp L0214
+L0208: jsr _err_no_channel
+L0214: lda #$00
+ sta _input_buf_len
+ sta _input_buf_len+1
+ jmp incsp3
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ handle_command (void)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _handle_command: near
+
+.segment "CODE"
+
+ lda _input_buf
+ ldx _input_buf+1
+ jsr incax1
+ jsr pushax
+ jsr decsp2
+ jsr push0
+ ldy #$07
+ jsr pushwysp
+L0261: jsr ldax0sp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$0A
+ beq L0262
+ jsr ldax0sp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$20
+ beq L0262
+ jsr pushw0sp
+ ldy #$03
+ jsr ldaxysp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ ldx #$00
+ lda (ptr1),y
+ jsr _toupper
+ ldy #$00
+ jsr staspidx
+ ldx #$00
+ lda #$01
+ jsr addeq0sp
+ jmp L0261
+L0262: jsr ldax0sp
+ ldy #$04
+ jsr staxysp
+ jsr ldax0sp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$0A
+ beq L026E
+ jsr ldax0sp
+ ldy #$02
+ jsr staxysp
+L0272: ldy #$03
+ jsr ldaxysp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$20
+ bne L0273
+ ldy #$02
+ ldx #$00
+ lda #$01
+ jsr addeqysp
+ jmp L0272
+L0273: ldy #$03
+ jsr ldaxysp
+ jsr incax1
+ jsr stax0sp
+L0278: jsr ldax0sp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ beq L0279
+ jsr ldax0sp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$0A
+ beq L0279
+ ldx #$00
+ lda #$01
+ jsr addeq0sp
+ jmp L0278
+L0279: jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ tay
+ sta (sreg),y
+L026E: ldy #$05
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ tay
+ sta (sreg),y
+ ldy #$09
+ jsr pushwysp
+ lda #<(L0001+414)
+ ldx #>(L0001+414)
+ jsr _strcmp
+ cpx #$00
+ bne L0283
+ cmp #$00
+ bne L0283
+ lda _joined_channel
+ bne L0288
+ jsr _err_no_channel
+ jmp incsp8
+L0288: ldy #$03
+ lda (sp),y
+ dey
+ ora (sp),y
+ bne L028C
+ jsr _err_missing_arg
+ jmp incsp8
+L028C: ldy #$05
+ jsr pushwysp
+ jsr _do_me
+ jmp incsp8
+L0283: ldy #$09
+ jsr pushwysp
+ lda #<(L0001+417)
+ ldx #>(L0001+417)
+ jsr _strcmp
+ cpx #$00
+ bne L051B
+ cmp #$00
+ beq L0294
+L051B: ldy #$09
+ jsr pushwysp
+ lda #<(L0001+421)
+ ldx #>(L0001+421)
+ jsr _strcmp
+ cpx #$00
+ bne L0293
+ cmp #$00
+ bne L0293
+L0294: ldy #$03
+ lda (sp),y
+ dey
+ ora (sp),y
+ bne L029C
+ jsr _err_missing_arg
+ jmp incsp8
+L029C: lda #<(L0001+423)
+ ldx #>(L0001+423)
+ jmp L0524
+L0293: ldy #$09
+ jsr pushwysp
+ lda #<(L0001+431)
+ ldx #>(L0001+431)
+ jsr _strcmp
+ cpx #$00
+ bne L051D
+ cmp #$00
+ beq L02A5
+L051D: ldy #$09
+ jsr pushwysp
+ lda #<(L0001+436)
+ ldx #>(L0001+436)
+ jsr _strcmp
+ cpx #$00
+ bne L02A4
+ cmp #$00
+ bne L02A4
+L02A5: lda _joined_channel
+ beq L02AD
+ ldy #$03
+ lda (sp),y
+ dey
+ ora (sp),y
+ beq L02AF
+ jsr _err_already_joined
+ jmp incsp8
+L02AF: lda #<(L0001+438)
+ ldx #>(L0001+438)
+ jsr pushax
+ lda #<(_channel)
+ ldx #>(_channel)
+ jmp L0521
+L02AD: ldy #$03
+ lda (sp),y
+ dey
+ ora (sp),y
+ beq L02B7
+ lda #$01
+ sta _joined_channel
+ lda #<(_channel)
+ ldx #>(_channel)
+ jsr pushax
+ ldy #$05
+ jsr ldaxysp
+ jsr _strcpy
+ lda #<(L0001+443)
+ ldx #>(L0001+443)
+ jmp L0524
+L02B7: jsr _err_missing_arg
+ jmp incsp8
+L02A4: ldy #$09
+ jsr pushwysp
+ lda #<(L0001+448)
+ ldx #>(L0001+448)
+ jsr _strcmp
+ cpx #$00
+ bne L02C4
+ cmp #$00
+ bne L02C4
+ lda _joined_channel
+ bne L02C9
+ jsr _err_no_channel
+ jmp incsp8
+L02C9: txa
+ sta _joined_channel
+ lda #<(L0001+453)
+ ldx #>(L0001+453)
+ jsr pushax
+ lda #<(_channel)
+ ldx #>(_channel)
+ jmp L0521
+L02C4: ldy #$09
+ jsr pushwysp
+ lda #<(L0001+458)
+ ldx #>(L0001+458)
+ jsr _strcmp
+ cpx #$00
+ bne L051F
+ cmp #$00
+ beq L02D4
+L051F: ldy #$09
+ jsr pushwysp
+ lda #<(L0001+466)
+ ldx #>(L0001+466)
+ jsr _strcmp
+ cpx #$00
+ bne L02D3
+ cmp #$00
+ bne L02D3
+L02D4: ldy #$03
+ lda (sp),y
+ dey
+ ora (sp),y
+ bne L02DC
+ jsr _err_missing_arg
+ jmp incsp8
+L02DC: ldy #$05
+ jsr pushwysp
+ jsr _send_ctcp_version
+ jmp incsp8
+L02D3: ldy #$09
+ jsr pushwysp
+ lda #<(L0001+470)
+ ldx #>(L0001+470)
+ jsr _strcmp
+ cpx #$00
+ bne L02E3
+ cmp #$00
+ bne L02E3
+ ldy #$03
+ lda (sp),y
+ dey
+ ora (sp),y
+ bne L02E8
+ jsr _err_missing_arg
+ jmp incsp8
+L02E8: ldy #$05
+ jsr pushwysp
+ jsr _send_ctcp_ping
+ jmp incsp8
+L02E3: ldy #$09
+ jsr pushwysp
+ lda #<(L0001+475)
+ ldx #>(L0001+475)
+ jsr _strcmp
+ cpx #$00
+ bne L02EF
+ cmp #$00
+ bne L02EF
+ ldy #$03
+ lda (sp),y
+ dey
+ ora (sp),y
+ bne L02F4
+ jsr _err_missing_arg
+ jmp incsp8
+L02F4: lda _config
+ ldx _config+1
+ ldy #$54
+ jsr incaxy
+ jsr pushax
+ ldy #$05
+ jsr ldaxysp
+ jsr _strcpy
+ ldy #$09
+ jsr pushwysp
+ ldy #$07
+ jsr pushwysp
+ jsr _send_server_cmd
+ lda #<(L0001+480)
+ ldx #>(L0001+480)
+ jsr pushax
+ lda _config
+ ldx _config+1
+ ldy #$54
+ jsr incaxy
+ jsr pushax
+ ldy #$04
+ jsr _printf
+ jmp incsp8
+L02EF: ldy #$09
+ jsr pushwysp
+ lda #<(L0001+507)
+ ldx #>(L0001+507)
+ jsr _strcmp
+ cpx #$00
+ bne L0302
+ cmp #$00
+ bne L0302
+ ldy #$03
+ lda (sp),y
+ dey
+ ora (sp),y
+ bne L0307
+ jsr _err_missing_arg
+ jmp incsp8
+L0307: ldy #$05
+ jsr pushwysp
+ ldx #$00
+ txa
+ jmp L0521
+L0302: ldy #$07
+ jsr ldaxysp
+L0524: jsr pushax
+ ldy #$05
+ jsr ldaxysp
+L0521: jsr pushax
+ jsr _send_server_cmd
+ jmp incsp8
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ send_server_cmd (__near__ unsigned char*, __near__ unsigned char*)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _send_server_cmd: near
+
+.segment "CODE"
+
+ ldy #$01
+ lda (sp),y
+ dey
+ ora (sp),y
+ beq L0219
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda #<(L0001+311)
+ ldx #>(L0001+311)
+ jsr pushax
+ ldy #$09
+ jsr pushwysp
+ ldy #$09
+ jsr pushwysp
+ lda #$0A
+ jsr pusha0
+ tay
+ jmp L0525
+L0219: lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda #<(L0001+319)
+ ldx #>(L0001+319)
+ jsr pushax
+ ldy #$09
+ jsr pushwysp
+ lda #$0A
+ jsr pusha0
+ ldy #$08
+L0525: jsr _sprintf
+ lda _tstate
+ ldx _tstate+1
+ jsr pushax
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr _strlen
+ jsr pushax
+ jsr _telnet_send
+ jmp incsp4
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ bell (void)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _bell: near
+
+.segment "CODE"
+
+ lda _config
+ ldx _config+1
+ ldy #$96
+ jsr ldaxidx
+ txa
+ and #$08
+ bne L015D
+ lda _config
+ ldx _config+1
+ ldy #$96
+ jsr ldaxidx
+ txa
+ and #$20
+ beq L0160
+ lda #$01
+ sta _vbell_active
+ lda #<(_vbell_timer)
+ ldx #>(_vbell_timer)
+ jsr pushax
+ jsr __clocks_per_sec
+ jsr pushax
+ lda #$0A
+ jsr tosudiva0
+ jsr pushax
+ jsr _timer_set
+ lda _config
+ ldx _config+1
+ ldy #$93
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ clc
+ adc #$08
+ sta $02C6
+ rts
+L0160: ldx #$00
+ lda #$FD
+ jmp _putchar
+L015D: rts
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ redraw_user_buffer (void)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _redraw_user_buffer: near
+
+.segment "CODE"
+
+ jsr decsp2
+ ldx #$28
+ lda #$00
+ jsr pushax
+ lda _input_buf_len
+ ora _input_buf_len+1
+ jeq incsp4
+ lda _input_buf_len
+ ldx _input_buf_len+1
+ jsr decax1
+ ldy #$02
+ jsr staxysp
+L049B: jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ ldy #$03
+ jsr ldaxysp
+ clc
+ adc sreg
+ sta sreg
+ txa
+ adc sreg+1
+ tax
+ lda sreg
+ sta ptr2
+ stx ptr2+1
+ lda _input_buf
+ sta sreg
+ lda _input_buf+1
+ sta sreg+1
+ ldy #$03
+ jsr ldaxysp
+ clc
+ adc sreg
+ sta sreg
+ txa
+ adc sreg+1
+ tax
+ lda sreg
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ ora #$80
+ sta (ptr2),y
+ ldy #$03
+ jsr ldaxysp
+ sta regsave
+ stx regsave+1
+ jsr decax1
+ ldy #$02
+ jsr staxysp
+ lda regsave
+ ora regsave+1
+ bne L049B
+ jsr ldax0sp
+ clc
+ adc _input_buf_len
+ pha
+ txa
+ adc _input_buf_len+1
+ tax
+ pla
+ sta sreg
+ stx sreg+1
+ lda #$00
+ tay
+ sta (sreg),y
+ jsr pushw0sp
+ lda _stdout
+ ldx _stdout+1
+ jsr _fputs
+ lda _stdout
+ ldx _stdout+1
+ jsr _fflush
+ jmp incsp4
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ main (void)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _main: near
+
+.segment "CODE"
+
+ ldy #$4C
+ jsr subysp
+ jsr _disable_break
+ jsr _get_ostype
+ and #$07
+ ldy #$4B
+ sta (sp),y
+ cmp #$01
+ bne L003B
+ ldy #$FF
+L0040: iny
+ lda L0001,y
+ sta _os_version,y
+ bne L0040
+ jmp L0042
+L003B: lda (sp),y
+ cmp #$02
+ bne L0042
+ ldy #$FF
+L0047: iny
+ lda L0001+4,y
+ sta _os_version,y
+ bne L0047
+L0042: lda #$01
+ jsr _cursor
+ lda #$00
+ sta $02C6
+ lda #$0C
+ sta $02C5
+ ldx #$00
+ lda #$7D
+ jsr _putchar
+ lda #<(L0001+11)
+ ldx #>(L0001+11)
+ jsr _puts
+ ldx #$00
+ lda #$9B
+ jsr _putchar
+ jsr _config_is_valid
+ tax
+ bne L005C
+ jsr _get_config
+ tax
+ bne L005C
+ jsr _set_default_config
+L005C: lda _config
+ ldx _config+1
+ sta sreg
+ stx sreg+1
+ ldy #$96
+ jsr ldaxidx
+ pha
+ txa
+ ora #$10
+ tax
+ pla
+ ldy #$95
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+L0061: lda #$00
+ sta _done
+ jsr _rs232dev_close
+ lda _config
+ ldx _config+1
+ ldy #$93
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta $02C6
+ lda _config
+ ldx _config+1
+ iny
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta $02C5
+ lda #<(L0001+25)
+ ldx #>(L0001+25)
+ jsr pushax
+ ldy #$02
+ jsr _printf
+ lda #<(L0001+61)
+ ldx #>(L0001+61)
+ jsr pushax
+ lda _config
+ ldx _config+1
+ ldy #$11
+ jsr incaxy
+ jsr pushax
+ ldy #$04
+ jsr _printf
+ lda _stdout
+ ldx _stdout+1
+ jsr _fflush
+ lda sp
+ ldx sp+1
+ jsr pushax
+ lda #$40
+ jsr pusha
+ jsr _get_line
+ lda sp
+ ldx sp+1
+ jsr pushax
+ lda #<(L0001+68)
+ ldx #>(L0001+68)
+ jsr _strcasecmp
+ cpx #$00
+ bne L007B
+ cmp #$00
+ bne L007B
+ jsr _exit
+ jmp L0092
+L007B: lda sp
+ ldx sp+1
+ jsr pushax
+ lda #<(L0001+70)
+ ldx #>(L0001+70)
+ jsr _strcasecmp
+ cpx #$00
+ bne L0083
+ cmp #$00
+ bne L0083
+ lda _atari_exec_p
+ ldx _atari_exec_p+1
+ jsr pushax
+ lda #<(L0001+72)
+ ldx #>(L0001+72)
+ pha
+ ldy #$00
+ lda (sp),y
+ sta jmpvec+1
+ iny
+ lda (sp),y
+ sta jmpvec+2
+ pla
+ jsr jmpvec
+ jsr incsp2
+ ldy #$49
+ jsr staxysp
+ lda #<(L0001+87)
+ ldx #>(L0001+87)
+ jsr pushax
+ ldy #$4E
+ jsr pushwysp
+ ldy #$04
+ jsr _printf
+ ldy #$00
+ jsr _bell
+ jmp L0061
+L0083: ldy #$00
+ lda (sp),y
+ beq L0092
+ lda _config
+ ldx _config+1
+ ldy #$11
+ jsr incaxy
+ jsr pushax
+ lda #$02
+ jsr leaasp
+ jsr _strcpy
+L0092: lda _config
+ ldx _config+1
+ ldy #$10
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ jsr pusha
+ jsr _rs232dev_init
+ cmp #$00
+ jne L0061
+ lda #$41
+ jsr leaasp
+ jsr pushax
+ jsr __clocks_per_sec
+ jsr shrax1
+ jsr pushax
+ jsr _timer_set
+ jsr _uip_init
+ lda #<(_uip_hostaddr)
+ ldx #>(_uip_hostaddr)
+ jsr pushax
+ lda _config
+ ldx _config+1
+ jsr incax4
+ jsr pushax
+ ldx #$00
+ lda #$04
+ jsr _memcpy
+ lda #<(_uip_draddr)
+ ldx #>(_uip_draddr)
+ jsr pushax
+ lda _config
+ ldx _config+1
+ jsr incax8
+ jsr pushax
+ ldx #$00
+ lda #$04
+ jsr _memcpy
+ lda #$45
+ jsr leaasp
+ sta sreg
+ stx sreg+1
+ lda #$FF
+ ldy #$00
+ sta (sreg),y
+ iny
+ sta (sreg),y
+ lda #$45
+ jsr leaasp
+ sta sreg
+ stx sreg+1
+ lda #$FF
+ iny
+ sta (sreg),y
+ iny
+ lda #$00
+ sta (sreg),y
+ lda #<(_uip_netmask)
+ ldx #>(_uip_netmask)
+ jsr pushax
+ lda #$47
+ jsr leaasp
+ jsr ldaxi
+ ldy #$00
+ jsr staxspidx
+ lda #<(_uip_netmask)
+ ldx #>(_uip_netmask)
+ jsr pushax
+ lda #$47
+ jsr leaasp
+ ldy #$03
+ jsr ldaxidx
+ ldy #$02
+ jsr staxspidx
+ lda _config
+ ldx _config+1
+ ldy #$11
+ jsr incaxy
+ jsr pushax
+ lda #$47
+ jsr leaasp
+ jsr pushax
+ jsr _uiplib_ipaddrconv
+ tax
+ beq L00E3
+ lda #$45
+ jsr leaasp
+ jsr pushax
+ lda _config
+ ldx _config+1
+ ldy #$53
+ jsr pushwidx
+ jsr _htons
+ jsr pushax
+ jsr _uip_connect
+ jmp L00EB
+L00E3: jsr _resolv_init
+ lda _config
+ ldx _config+1
+ ldy #$0C
+ jsr incaxy
+ jsr pushax
+ jsr _resolv_conf
+ lda _config
+ ldx _config+1
+ ldy #$11
+ jsr incaxy
+ jsr pushax
+ jsr _resolv_query
+L00EB: lda _done
+ jne L00F3
+ jsr _rs232dev_poll
+ sta _uip_len
+ stx _uip_len+1
+ cpx #$00
+ bne L0526
+ cmp #$00
+ beq L00F7
+L0526: jsr pushc1
+ jsr _uip_process
+ lda _uip_len
+ ora _uip_len+1
+ jeq L011C
+ jsr _rs232dev_send
+ jmp L011C
+L00F7: lda #$41
+ jsr leaasp
+ jsr pushax
+ jsr _timer_expired
+ stx tmp1
+ ora tmp1
+ jeq L011C
+ lda #$41
+ jsr leaasp
+ jsr pushax
+ jsr _timer_reset
+ ldx #$00
+ txa
+L0529: ldy #$49
+ jsr staxysp
+ jsr pushax
+ lda #$01
+ jsr toslta0
+ beq L0107
+ ldy #$4A
+ jsr ldaxysp
+ jsr pushax
+ lda #$23
+ jsr tosmula0
+ clc
+ adc #<(_uip_conns)
+ tay
+ txa
+ adc #>(_uip_conns)
+ tax
+ tya
+ sta _uip_conn
+ stx _uip_conn+1
+ jsr pushc2
+ jsr _uip_process
+ lda _uip_len
+ ora _uip_len+1
+ beq L0108
+ jsr _rs232dev_send
+L0108: ldy #$4A
+ jsr ldaxysp
+ jsr incax1
+ jmp L0529
+L0107: ldx #$00
+ txa
+L052A: ldy #$49
+ jsr staxysp
+ jsr pushax
+ lda #$01
+ jsr toslta0
+ beq L011C
+ ldy #$4A
+ jsr ldaxysp
+ jsr pushax
+ lda #$0B
+ jsr tosmula0
+ clc
+ adc #<(_uip_udp_conns)
+ tay
+ txa
+ adc #>(_uip_udp_conns)
+ tax
+ tya
+ sta _uip_udp_conn
+ stx _uip_udp_conn+1
+ lda #$05
+ jsr pusha
+ jsr _uip_process
+ lda _uip_len
+ ora _uip_len+1
+ beq L011D
+ jsr _rs232dev_send
+L011D: ldy #$4A
+ jsr ldaxysp
+ jsr incax1
+ jmp L052A
+L011C: lda _vbell_active
+ beq L0130
+ lda #<(_vbell_timer)
+ ldx #>(_vbell_timer)
+ jsr pushax
+ jsr _timer_expired
+ stx tmp1
+ ora tmp1
+ beq L0130
+ lda _config
+ ldx _config+1
+ ldy #$93
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta $02C6
+ lda #$00
+ sta _vbell_active
+L0130: jsr _kbhit
+ tax
+ beq L013C
+ jsr _handle_keystroke
+L013C: lda _connected
+ jeq L00EB
+ lda _nick_registered
+ jne L00EB
+ lda #<(_nick_reg_timer)
+ ldx #>(_nick_reg_timer)
+ jsr pushax
+ jsr _timer_expired
+ stx tmp1
+ ora tmp1
+ jeq L00EB
+ lda #<(L0001+98)
+ ldx #>(L0001+98)
+ jsr _puts
+ lda _input_buf
+ ldx _input_buf+1
+ jsr pushax
+ lda #<(L0001+117)
+ ldx #>(L0001+117)
+ jsr pushax
+ lda _config
+ ldx _config+1
+ ldy #$54
+ jsr incaxy
+ jsr pushax
+ lda #$0A
+ jsr pusha0
+ lda _config
+ ldx _config+1
+ ldy #$54
+ jsr incaxy
+ jsr pushax
+ lda #<(L0001+146)
+ ldx #>(L0001+146)
+ jsr pushax
+ lda _config
+ ldx _config+1
+ ldy #$11
+ jsr incaxy
+ jsr pushax
+ lda _config
+ ldx _config+1
+ ldy #$69
+ jsr incaxy
+ jsr pushax
+ lda #$0A
+ jsr pusha0
+ ldy #$12
+ jsr _sprintf
+ lda _tstate
+ ldx _tstate+1
+ jsr pushax
+ lda _input_buf
+ ldx _input_buf+1
+ jsr pushax
+ lda _input_buf
+ ldx _input_buf+1
+ jsr _strlen
+ jsr pushax
+ jsr _telnet_send
+ lda #$00
+ sta _input_buf_len
+ sta _input_buf_len+1
+ lda #$01
+ sta _nick_registered
+ jmp L00EB
+L00F3: lda #$00
+ sta _joined_channel
+ sta _nick_registered
+ sta _connected
+ jmp L0061
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ err_missing_arg (void)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _err_missing_arg: near
+
+.segment "CODE"
+
+ lda #<(L0001+155)
+ ldx #>(L0001+155)
+ jsr _puts
+ jmp _bell
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ err_no_channel (void)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _err_no_channel: near
+
+.segment "CODE"
+
+ lda #<(L0001+181)
+ ldx #>(L0001+181)
+ jsr _puts
+ jmp _bell
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ err_already_joined (void)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _err_already_joined: near
+
+.segment "CODE"
+
+ lda #<(L0001+227)
+ ldx #>(L0001+227)
+ jsr _puts
+ jmp _bell
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ del_last_word (void)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _del_last_word: near
+
+.segment "CODE"
+
+ lda _input_buf_len
+ ldx _input_buf_len+1
+ jsr pushax
+ jsr push0
+L017E: lda _input_buf_len
+ ora _input_buf_len+1
+ beq L017F
+ lda _input_buf
+ ldx _input_buf+1
+ clc
+ adc _input_buf_len
+ pha
+ txa
+ adc _input_buf_len+1
+ tax
+ pla
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$20
+ bne L017F
+ ldx #$00
+ lda #$01
+ jsr addeq0sp
+ lda _input_buf_len
+ ldx _input_buf_len+1
+ jsr decax1
+ sta _input_buf_len
+ stx _input_buf_len+1
+ jmp L017E
+L017F: lda _input_buf_len
+ ora _input_buf_len+1
+ beq L0187
+ lda _input_buf
+ ldx _input_buf+1
+ clc
+ adc _input_buf_len
+ pha
+ txa
+ adc _input_buf_len+1
+ tax
+ pla
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$20
+ beq L0187
+ ldx #$00
+ lda #$01
+ jsr addeq0sp
+ lda _input_buf_len
+ ldx _input_buf_len+1
+ jsr decax1
+ sta _input_buf_len
+ stx _input_buf_len+1
+ jmp L017F
+L0187: ldy #$05
+ jsr pushwysp
+ lda #$79
+ jsr tosgea0
+ beq L018E
+ lda _input_buf_len
+ ldx _input_buf_len+1
+ jsr pushax
+ lda #$79
+ jsr toslta0
+ beq L018E
+ ldx #$00
+ lda #$1C
+ jsr _putchar
+ ldx #$00
+ lda #$9C
+ jsr _putchar
+ ldx #$00
+ lda #$9C
+ jsr _putchar
+ ldy #$00
+ jsr _redraw_user_buffer
+ jmp incsp4
+L018E: ldx #$00
+ lda #$7E
+ jsr _putchar
+ ldx #$00
+ lda #$01
+ ldy #$00
+ jsr subeqysp
+ stx tmp1
+ ora tmp1
+ bne L018E
+ jmp incsp4
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ send_ctcp_version (__near__ unsigned char*)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _send_ctcp_version: near
+
+.segment "CODE"
+
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda #<(L0001+324)
+ ldx #>(L0001+324)
+ jsr pushax
+ ldy #$07
+ jsr pushwysp
+ jsr push1
+ jsr push1
+ lda #$0A
+ jsr pusha0
+ ldy #$0C
+ jsr _sprintf
+ lda _tstate
+ ldx _tstate+1
+ jsr pushax
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr _strlen
+ jsr pushax
+ jsr _telnet_send
+ jmp incsp2
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ send_ctcp_ping (__near__ unsigned char*)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _send_ctcp_ping: near
+
+.segment "CODE"
+
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda #<(L0001+349)
+ ldx #>(L0001+349)
+ jsr pushax
+ ldy #$07
+ jsr pushwysp
+ jsr push1
+ lda $0014
+ jsr pusha0
+ lda $0013
+ jsr pusha0
+ lda $0012
+ jsr pusha0
+ jsr push1
+ lda #$0A
+ jsr pusha0
+ ldy #$12
+ jsr _sprintf
+ lda _tstate
+ ldx _tstate+1
+ jsr pushax
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr _strlen
+ jsr pushax
+ jsr _telnet_send
+ jmp incsp2
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ do_me (__near__ unsigned char*)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _do_me: near
+
+.segment "CODE"
+
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda #<(L0001+386)
+ ldx #>(L0001+386)
+ jsr pushax
+ lda #<(_channel)
+ ldx #>(_channel)
+ jsr pushax
+ jsr push1
+ ldy #$0B
+ jsr pushwysp
+ jsr push1
+ lda #$0A
+ jsr pusha0
+ ldy #$0E
+ jsr _sprintf
+ lda _tstate
+ ldx _tstate+1
+ jsr pushax
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr _strlen
+ jsr pushax
+ jsr _telnet_send
+ jmp incsp2
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ do_pong (void)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _do_pong: near
+
+.segment "CODE"
+
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda _output_buf
+ ldx _output_buf+1
+ jsr pushax
+ lda _output_buf_len
+ ldx _output_buf_len+1
+ jsr _memcpy
+ lda _chan_msg_buf
+ sta sreg
+ lda _chan_msg_buf+1
+ sta sreg+1
+ lda #$4F
+ ldy #$01
+ sta (sreg),y
+L0343: jsr ldax0sp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ beq L0344
+ jsr ldax0sp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$9B
+ bne L0346
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$0A
+ ldy #$00
+ sta (sreg),y
+L0346: jsr ldax0sp
+ jsr incax1
+ jsr stax0sp
+ jmp L0343
+L0344: lda _tstate
+ ldx _tstate+1
+ jsr pushax
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda _output_buf_len
+ ldx _output_buf_len+1
+ jsr pushax
+ jsr _telnet_send
+ lda _config
+ ldx _config+1
+ ldy #$96
+ jsr ldaxidx
+ txa
+ and #$40
+ jeq incsp2
+ lda #<(L0001+591)
+ ldx #>(L0001+591)
+ jsr _puts
+ jmp incsp2
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ do_server_msg (void)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _do_server_msg: near
+
+.segment "CODE"
+
+ lda _output_buf
+ ldx _output_buf+1
+ jsr pushax
+ jsr decsp6
+ jsr push0
+ jsr decsp2
+L0356: ldy #$0B
+ jsr ldaxysp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$20
+ beq L0357
+ ldy #$0A
+ ldx #$00
+ lda #$01
+ jsr addeqysp
+ jmp L0356
+L0357: ldy #$0A
+ ldx #$00
+ lda #$01
+ jsr addeqysp
+ ldy #$0B
+ jsr ldaxysp
+ ldy #$08
+ jsr staxysp
+L035D: ldy #$09
+ jsr ldaxysp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$20
+ beq L035E
+ ldy #$08
+ ldx #$00
+ lda #$01
+ jsr addeqysp
+ jmp L035D
+L035E: ldy #$09
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ tay
+ sta (sreg),y
+ ldy #$08
+ tax
+ lda #$01
+ jsr addeqysp
+ lda _config
+ ldx _config+1
+ ldy #$54
+ jsr incaxy
+ jsr _strlen
+ jsr stax0sp
+ ldy #$0B
+ jsr pushwysp
+ lda _config
+ ldx _config+1
+ ldy #$54
+ jsr incaxy
+ jsr pushax
+ ldy #$05
+ jsr ldaxysp
+ jsr _memcmp
+ cpx #$00
+ bne L0367
+ cmp #$00
+ bne L0367
+ jsr ldax0sp
+ jsr incax1
+ ldy #$08
+ jsr addeqysp
+L0367: ldy #$0B
+ jsr ldaxysp
+ jsr _atoi
+ ldy #$02
+ jsr staxysp
+ stx tmp1
+ ora tmp1
+ jeq L0370
+ ldy #$03
+ jsr ldaxysp
+ cpx #$01
+ jne L039D
+ cmp #$3B
+ jeq L038C
+ cmp #$4C
+ beq L0379
+ cmp #$4D
+ beq L037E
+ cmp #$60
+ beq L038C
+ cmp #$61
+ beq L038C
+ cmp #$6E
+ beq L038C
+ cmp #$74
+ beq L0383
+ cmp #$76
+ beq L038C
+ cmp #$77
+ beq L038B
+ jmp L039D
+L0379: lda #<(L0001+603)
+ ldx #>(L0001+603)
+ jsr pushax
+ ldy #$0D
+ jsr pushwysp
+ ldy #$04
+ jmp L052B
+L037E: lda #<(L0001+615)
+ ldx #>(L0001+615)
+ jsr pushax
+ ldy #$0D
+ jsr pushwysp
+ ldy #$04
+ jmp L052B
+L0383: lda _config
+ ldx _config+1
+ ldy #$96
+ jsr ldaxidx
+ txa
+ and #$10
+ tax
+ lda #$00
+ jsr bnegax
+ beq L03A2
+ ldy #$0B
+ jsr pushwysp
+ lda _stdout
+ ldx _stdout+1
+ jsr _fputs
+ jmp L03A2
+L038B: lda _config
+ ldx _config+1
+ ldy #$96
+ jsr ldaxidx
+ txa
+ and #$10
+ beq L038C
+ lda #<(L0001+633)
+ ldx #>(L0001+633)
+ jsr _puts
+ jmp L03A2
+L038C: ldy #$0B
+ jsr pushwysp
+ lda _stdout
+ ldx _stdout+1
+ jsr _fputs
+ jmp L03A2
+L039D: lda #<(L0001+660)
+ ldx #>(L0001+660)
+ jsr pushax
+ ldy #$05
+ jmp L0531
+L0370: lda #<(L0001+666)
+ ldx #>(L0001+666)
+ jsr pushax
+ ldy #$0D
+L0531: jsr ldaxysp
+ jsr pushax
+ ldy #$0F
+ jsr pushwysp
+ ldy #$06
+L052B: jsr _printf
+L03A2: ldy #$0C
+ jmp addysp
+
+.endproc
+
+; ---------------------------------------------------------------
+; unsigned char __near__ do_ctcp (__near__ unsigned char*, __near__ unsigned char*)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _do_ctcp: near
+
+.segment "CODE"
+
+ ldy #$0C
+ jsr subysp
+ ldy #$0F
+ jsr pushwysp
+ lda #<(L0001+672)
+ ldx #>(L0001+672)
+ jsr pushax
+ ldx #$00
+ lda #$05
+ jsr _memcmp
+ cpx #$00
+ jne L03A8
+ cmp #$00
+ jne L03A8
+ jsr _clock
+ jsr pusheax
+ ldx #$00
+ stx sreg
+ stx sreg+1
+ lda #$0A
+ jsr tosumuleax
+ ldy #$08
+ jsr steaxysp
+ ldy #$0D
+ jsr ldaxysp
+ jsr incax5
+ jsr _atoi
+ jsr axlong
+ jsr pusheax
+ ldy #$11
+ jsr ldaxysp
+ ldy #$09
+ jsr incaxy
+ jsr _atoi
+ jsr axlong
+ ldy sreg
+ sty sreg+1
+ stx sreg
+ tax
+ lda #$00
+ jsr tosaddeax
+ jsr pusheax
+ ldy #$11
+ jsr ldaxysp
+ ldy #$0D
+ jsr incaxy
+ jsr _atoi
+ jsr axlong
+ stx sreg+1
+ sta sreg
+ lda #$00
+ tax
+ jsr tosaddeax
+ jsr pusheax
+ ldx #$00
+ stx sreg
+ stx sreg+1
+ lda #$0A
+ jsr tosmuleax
+ ldy #$04
+ jsr steaxysp
+ ldy #$07
+ jsr ldeaxysp
+ ldy #$08
+ jsr lsubeqysp
+ ldy #$0B
+ jsr ldeaxysp
+ jsr pusheax
+ jsr __clocks_per_sec
+ jsr axulong
+ jsr tosudiveax
+ ldy #$08
+ jsr steaxysp
+ ldy #$0B
+ jsr ldeaxysp
+ jsr pusheax
+ ldx #$00
+ stx sreg
+ stx sreg+1
+ lda #$0A
+ jsr tosdiveax
+ ldy #$02
+ jsr staxysp
+ ldy #$0B
+ jsr ldeaxysp
+ jsr pusheax
+ ldx #$00
+ stx sreg
+ stx sreg+1
+ lda #$0A
+ jsr tosmodeax
+ jsr stax0sp
+ lda #<(L0001+678)
+ ldx #>(L0001+678)
+ jsr pushax
+ ldy #$13
+ jsr pushwysp
+ ldy #$09
+ jsr pushwysp
+ ldy #$09
+ jsr pushwysp
+ ldy #$08
+ jsr _printf
+ ldx #$00
+ lda #$01
+ jmp L03A7
+L03A8: ldx #$00
+ txa
+L03A7: ldy #$10
+ jmp addysp
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ do_msg (void)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _do_msg: near
+
+.segment "CODE"
+
+ lda _output_buf
+ ldx _output_buf+1
+ jsr pushax
+ lda _output_buf
+ ldx _output_buf+1
+ jsr pushax
+ jsr push0
+ jsr push0
+ jsr push0
+L03D0: ldy #$07
+ jsr ldaxysp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$20
+ beq L03D1
+ ldy #$07
+ jsr ldaxysp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$21
+ bne L03D3
+ ldy #$07
+ jsr ldaxysp
+ jsr stax0sp
+L03D3: ldy #$06
+ ldx #$00
+ lda #$01
+ jsr addeqysp
+ jmp L03D0
+L03D1: iny
+ lda (sp),y
+ dey
+ ora (sp),y
+ bne L03D8
+ jsr _do_server_msg
+ jmp L03CA
+L03D8: ldy #$07
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ tay
+ sta (sreg),y
+ ldy #$06
+ tax
+ lda #$01
+ jsr addeqysp
+ ldy #$07
+ jsr ldaxysp
+ ldy #$04
+ jsr staxysp
+L03E0: ldy #$05
+ jsr ldaxysp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$20
+ beq L03E1
+ ldy #$04
+ ldx #$00
+ lda #$01
+ jsr addeqysp
+ jmp L03E0
+L03E1: ldy #$05
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ tay
+ sta (sreg),y
+ ldy #$04
+ tax
+ lda #$01
+ jsr addeqysp
+ ldy #$05
+ jsr ldaxysp
+ ldy #$02
+ jsr staxysp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$9B
+ beq L03F6
+L03EB: ldy #$03
+ jsr ldaxysp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ beq L03EC
+ ldy #$03
+ jsr ldaxysp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$20
+ beq L03EC
+ ldy #$02
+ ldx #$00
+ lda #$01
+ jsr addeqysp
+ jmp L03EB
+L03EC: ldy #$03
+ jsr ldaxysp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ beq L03F6
+ ldy #$03
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ tay
+ sta (sreg),y
+ ldy #$02
+ tax
+ lda #$01
+ jsr addeqysp
+ ldy #$03
+ jsr ldaxysp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$3A
+ bne L03F6
+ ldy #$02
+ ldx #$00
+ lda #$01
+ jsr addeqysp
+L03F6: ldy #$09
+ jsr pushwysp
+ lda #<(L0001+701)
+ ldx #>(L0001+701)
+ jsr _strcmp
+ cpx #$00
+ jne L03F9
+ cmp #$00
+ jne L03F9
+ ldy #$09
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ lda #$3C
+ ldy #$00
+ sta (sreg),y
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$3E
+ ldy #$00
+ sta (sreg),y
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$01
+ sta (sreg),y
+ ldy #$07
+ jsr pushwysp
+ lda _config
+ ldx _config+1
+ ldy #$54
+ jsr incaxy
+ jsr _strcasecmp
+ cpx #$00
+ bne L0533
+ cmp #$00
+ jeq L0407
+L0533: ldy #$05
+ jsr pushwysp
+ lda #<(L0001+709)
+ ldx #>(L0001+709)
+ jsr pushax
+ ldx #$00
+ lda #$08
+ jsr _memcmp
+ cpx #$00
+ bne L040C
+ cmp #$00
+ bne L040C
+ ldy #$09
+ jsr ldaxysp
+ jsr incax1
+ ldy #$08
+ jsr staxysp
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ tay
+ sta (sreg),y
+ lda _output_buf
+ ldx _output_buf+1
+ jsr pushax
+ lda _output_buf_len
+ ldx _output_buf_len+1
+ jsr decax2
+ jsr tosaddax
+ sta sreg
+ stx sreg+1
+ lda #$9B
+ ldy #$00
+ sta (sreg),y
+ lda _output_buf
+ ldx _output_buf+1
+ jsr pushax
+ lda _output_buf_len
+ ldx _output_buf_len+1
+ jsr decax1
+ jsr tosaddax
+ sta sreg
+ stx sreg+1
+ lda #$00
+ tay
+ sta (sreg),y
+ lda #<(L0001+718)
+ ldx #>(L0001+718)
+ jsr pushax
+ ldy #$0D
+ jsr pushwysp
+ ldy #$07
+ jsr ldaxysp
+ jsr incax8
+ jsr pushax
+ ldy #$06
+ jmp L0532
+L040C: lda #<(L0001+726)
+ ldx #>(L0001+726)
+ jsr pushax
+ ldy #$0D
+ jsr pushwysp
+ ldy #$09
+ jsr pushwysp
+ ldy #$06
+ jmp L0532
+L0407: ldy #$05
+ jsr pushwysp
+ lda #<(L0001+732)
+ ldx #>(L0001+732)
+ jsr pushax
+ ldx #$00
+ lda #$06
+ jsr _memcmp
+ cpx #$00
+ jne L0425
+ cmp #$00
+ jne L0425
+ ldy #$09
+ jsr ldaxysp
+ jsr incax1
+ ldy #$08
+ jsr staxysp
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ tay
+ sta (sreg),y
+ lda _output_buf
+ ldx _output_buf+1
+ jsr pushax
+ lda _output_buf_len
+ ldx _output_buf_len+1
+ jsr decax2
+ jsr tosaddax
+ sta sreg
+ stx sreg+1
+ lda #$00
+ tay
+ sta (sreg),y
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda #<(L0001+739)
+ ldx #>(L0001+739)
+ jsr pushax
+ ldy #$0F
+ jsr pushwysp
+ ldy #$09
+ jsr ldaxysp
+ jsr incax6
+ jsr pushax
+ lda #$0A
+ jsr pusha0
+ tay
+ jsr _sprintf
+ lda _tstate
+ ldx _tstate+1
+ jsr pushax
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr _strlen
+ jsr pushax
+ jsr _telnet_send
+ lda #<(L0001+762)
+ ldx #>(L0001+762)
+ jsr pushax
+ ldy #$0D
+ jsr pushwysp
+ ldy #$04
+ jmp L0532
+L0425: ldy #$05
+ jsr pushwysp
+ lda #<(L0001+783)
+ ldx #>(L0001+783)
+ jsr pushax
+ ldx #$00
+ lda #$09
+ jsr _memcmp
+ cpx #$00
+ bne L0440
+ cmp #$00
+ bne L0440
+ ldy #$09
+ jsr ldaxysp
+ jsr incax1
+ ldy #$08
+ jsr staxysp
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ tay
+ sta (sreg),y
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda #<(L0001+793)
+ ldx #>(L0001+793)
+ jsr pushax
+ ldy #$0F
+ jsr pushwysp
+ lda #<(_os_version)
+ ldx #>(_os_version)
+ jsr pushax
+ lda #$0A
+ jsr pusha0
+ tay
+ jsr _sprintf
+ lda _tstate
+ ldx _tstate+1
+ jsr pushax
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr pushax
+ lda _chan_msg_buf
+ ldx _chan_msg_buf+1
+ jsr _strlen
+ jsr pushax
+ jsr _telnet_send
+ lda #<(L0001+855)
+ ldx #>(L0001+855)
+ jsr pushax
+ ldy #$0D
+ jsr pushwysp
+ ldy #$04
+ jmp L0532
+L0440: lda #<(L0001+879)
+ ldx #>(L0001+879)
+ jsr pushax
+ ldy #$0D
+ jsr pushwysp
+ ldy #$09
+ jsr pushwysp
+ ldy #$06
+ jsr _printf
+ lda _config
+ ldx _config+1
+ ldy #$96
+ jsr ldaxidx
+ txa
+ and #$80
+ beq L045C
+ jsr _bell
+L045C: jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ tay
+ sta (sreg),y
+ lda #<(_last_msg_nick)
+ ldx #>(_last_msg_nick)
+ jsr pushax
+ ldy #$0B
+ jsr ldaxysp
+ jsr incax1
+ jsr _strcpy
+ jmp L0482
+L03F9: ldy #$09
+ jsr pushwysp
+ lda #<(L0001+890)
+ ldx #>(L0001+890)
+ jsr _strcmp
+ cpx #$00
+ bne L0465
+ cmp #$00
+ bne L0465
+ ldy #$03
+ jsr ldaxysp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$01
+ bne L0465
+ ldy #$09
+ jsr ldaxysp
+ jsr incax1
+ ldy #$08
+ jsr staxysp
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ tay
+ sta (sreg),y
+ ldy #$0B
+ jsr pushwysp
+ ldy #$05
+ jsr ldaxysp
+ jsr incax1
+ jsr pushax
+ jsr _do_ctcp
+ tax
+ bne L0482
+ lda #<(L0001+897)
+ ldx #>(L0001+897)
+ jsr pushax
+ ldy #$0D
+ jsr pushwysp
+ ldy #$07
+ jsr ldaxysp
+ jsr incax1
+ jsr pushax
+ ldy #$06
+ jmp L0532
+L0465: ldy #$03
+ jsr ldaxysp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ beq L047A
+ lda #<(L0001+922)
+ ldx #>(L0001+922)
+ jsr pushax
+ ldy #$0D
+ jsr pushwysp
+ ldy #$0D
+ jsr pushwysp
+ ldy #$0D
+ jsr pushwysp
+ ldy #$0D
+ jsr pushwysp
+ ldy #$0A
+ jmp L0532
+L047A: lda #<(L0001+934)
+ ldx #>(L0001+934)
+ jsr pushax
+ ldy #$0D
+ jsr pushwysp
+ ldy #$0D
+ jsr pushwysp
+ ldy #$0D
+ jsr pushwysp
+ ldy #$08
+L0532: jsr _printf
+L0482: lda _stdout
+ ldx _stdout+1
+ jsr _fflush
+L03CA: ldy #$0A
+ jmp addysp
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ del_user_buffer (void)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _del_user_buffer: near
+
+.segment "CODE"
+
+ lda _input_buf_len
+ ora _input_buf_len+1
+ beq L048F
+ ldx #$00
+ lda #$9C
+ jsr _putchar
+ lda _input_buf_len
+ ldx _input_buf_len+1
+ jsr pushax
+ lda #$78
+ jsr tosgea0
+ beq L048F
+ ldx #$00
+ lda #$1C
+ jsr _putchar
+ ldx #$00
+ lda #$9C
+ jmp _putchar
+L048F: rts
+
+.endproc
+
diff --git a/src/fujichat-0.1.atr b/src/fujichat-0.1.atr
new file mode 100644
index 0000000..47f16d0
--- /dev/null
+++ b/src/fujichat-0.1.atr
Binary files differ
diff --git a/src/fujichat-0.3.atr b/src/fujichat-0.3.atr
new file mode 100644
index 0000000..95c2f70
--- /dev/null
+++ b/src/fujichat-0.3.atr
Binary files differ
diff --git a/src/fujichat.atr b/src/fujichat.atr
new file mode 100644
index 0000000..613a085
--- /dev/null
+++ b/src/fujichat.atr
Binary files differ
diff --git a/src/fujichat.atr.ok b/src/fujichat.atr.ok
new file mode 100644
index 0000000..b1f8912
--- /dev/null
+++ b/src/fujichat.atr.ok
Binary files differ
diff --git a/src/fujichat.c b/src/fujichat.c
new file mode 100644
index 0000000..c6412c6
--- /dev/null
+++ b/src/fujichat.c
@@ -0,0 +1,1054 @@
+/*
+ * Copyright (c) 2008, Brian Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgements:
+ * This product includes software developed by Adam Dunkels.
+ * This product includes software developed by Brian Watson.
+ * 4. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the FujiChat IRC client.
+ *
+ */
+
+
+/* standard C includes */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+/* cc65 includes */
+#include <rs232.h>
+#include <peekpoke.h>
+#include <atari.h>
+
+/* uIP includes */
+#include "timer.h"
+#include "uip.h"
+#include "uiplib.h"
+#include "rs232dev.h"
+
+/* FujiChat includes */
+#include "fujichat.h"
+#include "common.h"
+#include "features.h"
+
+#ifdef FEAT_KEYBOARD_MACROS
+#include "keybuf.h"
+#endif
+
+#ifdef FEAT_COL80_HACK
+/* $54 and $55 are ROWCRS and COLCRS.
+ COL80 uses them the same way the OS does. */
+# define fuji_gotox(x) POKE(0x55, x)
+# define fuji_gotoy(y) POKE(0x54, y)
+# define fuji_getxpos() PEEK(0x55)
+# define fuji_getypos() PEEK(0x54)
+
+/* TODO: calculate from RMARGN-LMARGN. Currently COL80 doesn't set RMARGN */
+# ifndef COLUMNS
+# define COLUMNS 80
+# endif
+#endif
+
+
+#ifdef FEAT_DYNAMIC_VERSION
+char os_version[10] = "XL_XE";
+#else
+#define os_version "8-bit"
+#endif
+
+#ifdef FEAT_LOW_RAM_BUFFERS
+#define LOW_RAM_BASE 0x2900
+char *input_buf = (char *)LOW_RAM_BASE; // $2900 - $21FF
+char *serv_msg_buf = (char *)(LOW_RAM_BASE + BUF_SIZE); // $2A00 - $2BFF
+char *output_buf = (char *)(LOW_RAM_BASE + BUF_SIZE + BUF_SIZE * 2); // $2C00 - $2DFF
+#else
+char input_buf[BUF_SIZE];
+char serv_msg_buf[BUF_SIZE * 2];
+char output_buf[OUTBUF_SIZE];
+#endif
+
+char channel[HOSTLEN];
+
+#ifdef FEAT_KEYBOARD_MACROS
+char last_msg_nick[NICKLEN+1] = "";
+#endif
+
+int serv_msg_buf_len = 0;
+int input_buf_len = 0;
+int output_buf_len = 0;
+
+char done = 0;
+char connected = 0;
+char joined_channel = 0; /* true if we're in a channel */
+char nick_registered = 0;
+
+#ifdef FEAT_VISUAL_BELL
+char vbell_active = 0;
+#endif
+
+#ifdef FEAT_ATRACT_AWAY
+char away = 0;
+#endif
+
+static void handle_keystroke(void);
+
+#ifdef FEAT_LOGGING
+static void alloc_log_buffer();
+#endif
+
+#if defined(FEAT_CURSOR_CONTROLS) || defined(FEAT_COL80_HACK)
+void redraw_user_buffer();
+void del_user_buffer();
+#endif
+
+/* uIP API stuff */
+struct timer nick_reg_timer; /* ../uip/timer.h */
+struct telnet_state *tstate; /* ../apps/telnet.h */
+
+#ifdef FEAT_VISUAL_BELL
+struct timer vbell_timer;
+#endif
+
+/*---------------------------------------------------------------------------*/
+void main(void) {
+#ifdef FEAT_DYNAMIC_VERSION
+ char c;
+#endif
+ int i;
+ uip_ipaddr_t ipaddr;
+ struct timer periodic_timer;
+ char cmdbuf[HOSTLEN+1];
+
+ disable_break();
+
+#ifdef FEAT_DYNAMIC_VERSION
+ c = get_ostype() & AT_OS_TYPE_MAIN;
+ if(c == AT_OS_400800) {
+ strcpy(os_version, "800");
+ } else if(c == AT_OS_1200XL) {
+ strcpy(os_version, "1200XL");
+ }
+#endif
+
+ /* set screen colors to white-on-black initially. They may be
+ reset by the user's config file, once it's loaded */
+ POKE(710, 0);
+ POKE(709, 12);
+
+#ifndef FEAT_COL80_HACK
+ fuji_putchar(A_CLR);
+#endif
+
+ puts(BANNER);
+ fuji_putchar('\n');
+
+ if(!config_is_valid()) {
+ if(!get_config())
+ set_default_config();
+ }
+
+#ifdef FEAT_LOGGING
+ alloc_log_buffer();
+#endif
+
+ // config->ui_flags |= UIFLAG_HIDEMOTD; // TODO: make it a preference!
+
+ while(1) {
+ done = 0;
+ rs232dev_close();
+
+ POKE(710, config->bg_color);
+ POKE(709, config->fg_color);
+
+ printf("Server name/IP, [C]onfig, or [D]OS\n");
+ printf("[%s]: ", config->server);
+ fflush(stdout);
+ get_line(cmdbuf, HOSTLEN);
+
+ if(strcasecmp(cmdbuf, "d") == 0) {
+ exit(0);
+ } else if(strcasecmp(cmdbuf, "c") == 0) {
+ i = atari_exec(SETUP_FILENAME);
+ printf("Error %d!\n", i);
+ bell();
+ continue;
+ } else if(*cmdbuf) {
+ strcpy(config->server, cmdbuf);
+ }
+ /* else, use the existing config->server */
+
+ if(rs232dev_init(config->baud) != RS_ERR_OK)
+ continue;
+
+ timer_set(&periodic_timer, CLOCK_SECOND / 2);
+
+ uip_init();
+
+ memcpy(uip_hostaddr, &(config->local_ip), 4);
+ memcpy(uip_draddr, &(config->peer_ip), 4);
+
+ /* can I use 255.255.255.252 here? Does it matter? */
+ uip_ipaddr(ipaddr, 255,255,255,0);
+ uip_setnetmask(ipaddr);
+
+ if(uiplib_ipaddrconv(config->server, (unsigned char*)&ipaddr)) {
+ (void)uip_connect(&ipaddr, htons(config->server_port));
+ } else {
+ resolv_init();
+ resolv_conf((u16_t *)&(config->resolver_ip)); // TODO: fix so I don't need extra ()
+ resolv_query(config->server);
+ }
+
+ while(!done) {
+ /* This part of the while loop is straight from the no-ARP example
+ code, from the uIP docs. */
+ uip_len = rs232dev_poll();
+ if(uip_len > 0) {
+ uip_input();
+ /* If the above function invocation resulted in data that
+ should be sent out on the network, the global variable
+ uip_len is set to a value > 0. */
+ if(uip_len > 0) {
+ rs232dev_send();
+ }
+ } else if(timer_expired(&periodic_timer)) {
+ timer_reset(&periodic_timer);
+ for(i = 0; i < UIP_CONNS; i++) {
+ uip_periodic(i);
+ /* If the above function invocation resulted in data that
+ should be sent out on the network, the global variable
+ uip_len is set to a value > 0. */
+ if(uip_len > 0) {
+ rs232dev_send();
+ }
+ }
+
+#if UIP_UDP
+ for(i = 0; i < UIP_UDP_CONNS; i++) {
+ uip_udp_periodic(i);
+ /* If the above function invocation resulted in data that
+ should be sent out on the network, the global variable
+ uip_len is set to a value > 0. */
+ if(uip_len > 0) {
+ rs232dev_send();
+ }
+ }
+#endif /* UIP_UDP */
+ }
+
+#ifdef FEAT_VISUAL_BELL
+ if(vbell_active && timer_expired(&vbell_timer)) {
+ POKE(710, config->bg_color);
+ vbell_active = 0;
+ }
+#endif
+
+ /* Call the keyboard handler if the user pressed a key. Note that
+ we're using stdio for printing, but conio for reading, which
+ works on the Atari but may not work on all other cc65 platforms */
+#ifdef FEAT_KEYBOARD_BUFFER
+ /* always call; will return if nothing to do */
+ handle_keystroke();
+#else
+ if(PEEK(764) != 0xff) { /* check CH (replaces kbhit()) */
+ handle_keystroke();
+ }
+#endif
+
+#ifdef FEAT_ATRACT_AWAY
+ if(away && input_buf_len && !(PEEK(77) & 0x80)) {
+ away = 0;
+ send_server_cmd("AWAY", NULL);
+ } else if(!away && (PEEK(77) & 0x80)) {
+ away = 1;
+ send_server_cmd("AWAY", "ATRACT Mode");
+ }
+#endif
+
+ /* Automatically register the nick and userhost after being
+ connected for a couple seconds. The parameters for the USER
+ command are ignored by the server (at least the NewNet servers) */
+ if(connected && !nick_registered && timer_expired(&nick_reg_timer)) {
+ puts("> Registering nick");
+
+ serv_msg_buf_len = sprintf(
+ serv_msg_buf, "NICK %s%cUSER %s %s %s :%s%c",
+ config->nick, NL, config->nick, SELF,
+ config->server, config->real_name, NL);
+ send_serv_msg_buf();
+
+ /*
+ sprintf(input_buf, "NICK %s%cUSER %s %s %s :%s%c",
+ config->nick, NL, config->nick, SELF,
+ config->server, config->real_name, NL);
+ telnet_send(tstate, input_buf, strlen(input_buf));
+ */
+
+ input_buf_len = 0;
+ nick_registered = 1;
+ /* TODO: check for failure registering the nick */
+ }
+
+ /*
+ if(PEEK(53279) == 6) { // START pressed
+ puts("Disconnecting");
+ uip_close();
+ // done = 1;
+ }
+ */
+ }
+
+ connected = nick_registered = joined_channel = 0;
+ }
+ // return 0;
+}
+
+void bell() {
+ if(config->ui_flags & UIFLAG_NOBELL)
+ return;
+
+#ifdef FEAT_VISUAL_BELL
+ if(config->ui_flags & UIFLAG_VBELL) {
+ vbell_active = 1;
+ timer_set(&vbell_timer, CLOCK_SECOND / 10);
+ POKE(710, config->bg_color + 8);
+ return;
+ }
+#endif
+
+#ifndef FEAT_COL80_HACK /* COL80 E: doesn't do the bell character */
+ fuji_putchar(A_BEL);
+#endif
+}
+
+static void err_no_channel(void) {
+ puts("You are not in a channel (use /join #channel)");
+ bell();
+}
+
+#ifdef FEAT_CURSOR_CONTROLS
+static void del_last_word(void) {
+ int old = input_buf_len, bs = 0;
+
+ while(input_buf_len && input_buf[input_buf_len] == ' ') {
+ ++bs;
+ input_buf_len--;
+ }
+
+ while(input_buf_len && input_buf[input_buf_len] != ' ') {
+ ++bs;
+ input_buf_len--;
+ }
+
+ if(old > 120 && input_buf_len <= 120) {
+ fuji_putchar(0x1c);
+ fuji_putchar(A_DEL);
+ fuji_putchar(A_DEL);
+ redraw_user_buffer();
+ } else do {
+ fuji_putchar(A_BS);
+ } while(--bs);
+}
+#endif
+
+#ifdef FEAT_COL80_HACK
+void col80_backspace(char destructive) {
+ char x = fuji_getxpos();
+ char y = fuji_getypos();
+
+ if(x) {
+ --x;
+ } else {
+ x = COLUMNS - 1;
+ --y;
+ }
+
+ fuji_gotox(x);
+ fuji_gotoy(y);
+ if(destructive) {
+ fuji_putchar(' ');
+ fuji_gotox(x);
+ fuji_gotoy(y);
+ }
+}
+
+//void col80_cursor(void) {
+// fuji_putchar(0xa0); /* inverse space */
+// col80_backspace(0);
+//}
+
+# define backspace() col80_backspace(1)
+
+#else
+# define backspace() fuji_putchar(A_BS)
+#endif
+
+/* Keyboard handler. For now, the keyboard macros are hard-coded. */
+static void handle_keystroke(void) {
+ char i, c, send_buf = 0;
+
+ /* TODO:
+ ctrl-7 = ` (warning: cgetc() can't read this)
+ ctrl-, = {
+ ctrl-. = }
+ ctrl-; = ~ (don't do ctrl-^, that's left-arrow!)
+
+ Ignore inverse-video key, ATASCII graphics, unwanted
+ cursor actions, make caps-lock stop freezing the program.
+ To do this right, we have to examine location 764 for some
+ of these, and don't call cgetc() at all... or actually,
+ stuff a valid keycode there, then call cgetc() to make a
+ keyclick noise (but ignore its return value).
+ Addendum - this should be handled in keybuf.s?
+
+ Stock col80 key mappings are warped:
+ ctrl-clear = }
+ ctrl-; = {
+ ctrl-. = `
+ No way to type a tilde because that's the A8 backspace char :(
+
+ */
+#ifdef FEAT_KEYBOARD_BUFFER
+ c = keybuf_cgetc();
+ if(!c) return;
+#else
+ c = fuji_cgetc();
+#endif
+
+#ifdef FEAT_KEYBOARD_MACROS
+ /* Keyboard macros, only allowed at the start of a new line */
+ if(input_buf_len == 0) {
+ switch(c) {
+ case 0x0e: /* ctrl-N */
+ if(joined_channel) send_server_cmd("NAMES", channel);
+ return;
+
+ case 0x17: /* ctrl-W */
+ if(joined_channel) send_server_cmd("WHO", channel);
+ return;
+
+ case A_EOL:
+ return; /* ignore Return on a line by itself */
+
+ case A_TAB:
+ if(last_msg_nick[0]) {
+ sprintf(input_buf, "/msg %s ", last_msg_nick);
+ input_buf_len = strlen(input_buf);
+ for(i=0; i<input_buf_len; i++)
+ fuji_putchar(input_buf[i] | 0x80);
+ }
+ return;
+
+ default:
+ break;
+ }
+ }
+#else
+ if(!input_buf_len && c == A_EOL)
+ return;
+#endif
+
+ /* Editing keys */
+ /* TODO: more editing keys. At minimum:
+ left/right arrows
+ ^W = delete last word
+ ^U = kill to start of line
+ ^K = kill to end of line
+ ^A = goto start of line
+ ^E = goto end of line
+ ^L = redraw input buffer
+ */
+ if(c == A_BS) { /* backspace */
+ if(input_buf_len > 0) {
+ input_buf_len--;
+#ifdef FEAT_COL80_HACK
+ col80_backspace(1);
+ // fuji_putchar(' ');
+ // col80_backspace(0);
+ // col80_cursor();
+#else
+ fuji_putchar(c);
+#endif
+ } else {
+ bell();
+ }
+
+ return;
+ } else if(c == A_DEL || c == 0x15) {
+ /* shift-backspace or ^U (delete line) */
+#ifdef FEAT_COL80_HACK
+ del_user_buffer();
+ // col80_cursor();
+#else
+ fuji_putchar(A_DEL);
+#endif
+ input_buf_len = 0;
+ return;
+#ifdef FEAT_CURSOR_CONTROLS
+ } else if(c == 0x17) {
+ /* ^W (delete word) */
+ del_last_word();
+ return;
+#endif
+ }
+
+ /* Echo keystroke */
+ fuji_putchar(c | 0x80); /* inverse video for now */
+
+ if(c == A_EOL) {
+ c = NL;
+ send_buf = 1;
+ } else if(c == A_TAB) {
+ c = TAB;
+ }
+// #ifdef FEAT_COL80_HACK
+ // else { col80_cursor(); }
+// #endif
+
+
+#ifdef FEAT_UNICODE_TEST
+ if(c == 0x10) { /* ATASCII clubs symbol */
+ input_buf[input_buf_len++] = 0xe2; /* UTF-8 marker */
+ input_buf[input_buf_len++] = 0x99;
+ input_buf[input_buf_len++] = 0xa3;
+ fuji_putchar(c);
+ return;
+ }
+#endif
+
+ /* Store keystroke in input buffer */
+ input_buf[input_buf_len++] = c;
+
+ /* If line too long, ring the "margin" bell */
+ if(input_buf_len > BUF_SIZE - 1)
+ if(!send_buf) {
+ bell();
+ // fuji_putchar(A_BS);
+ backspace();
+ input_buf_len--;
+ }
+
+ /* If we've got a complete line of input and user has pressed Return,
+ send it to the server */
+ if(send_buf) {
+ input_buf[input_buf_len] = '\0';
+
+ if(*input_buf == '/') {
+ handle_command();
+ } else if(joined_channel) {
+ sprintf(serv_msg_buf, "PRIVMSG %s :%s", channel, input_buf);
+ telnet_send(tstate, serv_msg_buf, strlen(serv_msg_buf));
+ } else {
+ err_no_channel();
+ }
+
+ input_buf_len = 0;
+ }
+}
+
+void send_serv_msg_buf(void) {
+ telnet_send(tstate, serv_msg_buf, serv_msg_buf_len);
+}
+
+void send_server_cmd(char *cmd, char *arg) {
+ if(arg) {
+ serv_msg_buf_len = sprintf(serv_msg_buf, "%s %s%c", cmd, arg, NL);
+ } else {
+ serv_msg_buf_len = sprintf(serv_msg_buf, "%s%c", cmd, NL);
+ }
+
+ send_serv_msg_buf();
+}
+
+/* The telnet_* functions are uIP application callbacks. */
+void telnet_connected(struct telnet_state *s) {
+ /* puts("Connected to host, press START to disconnect"); */
+ puts("> Connected to server");
+ tstate = s;
+ s->text = NULL;
+ s->textlen = 0;
+ timer_set(&nick_reg_timer, CLOCK_SECOND);
+ connected = 1;
+}
+
+/* 20081125 bkw: why don't these pragmas do anything? */
+#pragma warn (off)
+void telnet_closed(struct telnet_state *s) {
+ puts("> Connection closed");
+ uip_close();
+ done = 1;
+}
+
+void telnet_sent(struct telnet_state *s) {
+}
+
+void telnet_aborted(struct telnet_state *s) {
+ puts("> Connection aborted");
+ uip_abort();
+ done = 1;
+}
+
+void telnet_timedout(struct telnet_state *s) {
+ puts("> Connection timed out");
+ uip_abort();
+ done = 1;
+}
+#pragma warn (on)
+
+void do_pong() {
+ char *p = serv_msg_buf;
+
+ memcpy(serv_msg_buf, output_buf, output_buf_len);
+ serv_msg_buf[1] = 'O';
+ while(*p) {
+ if(*p == A_EOL) *p = NL;
+ p++;
+ }
+
+ telnet_send(tstate, serv_msg_buf, output_buf_len);
+ if(config->ui_flags & UIFLAG_SHOWPING)
+ puts("[PING,PONG]");
+}
+
+void do_server_msg() {
+ char *cmd = output_buf, *arg;
+ int numeric = 0, len;
+
+ while(*cmd != ' ')
+ ++cmd;
+
+ ++cmd;
+
+ arg = cmd;
+ while(*arg != ' ')
+ ++arg;
+
+ *arg = '\0';
+ ++arg;
+
+ len = strlen(config->nick);
+ if(memcmp(arg, config->nick, len) == 0)
+ arg += (len + 1); // skip nick if present
+
+ if(arg[0] == ':')
+ ++arg;
+
+ /* now cmd points to the command (numeric or whatever),
+ arg points to the rest of the string.
+ Numeric commands we handle now I guess. I think they
+ all have the nick as the 1st argument...
+ */
+ if( (numeric = atoi(cmd)) ) {
+ switch(numeric) {
+ case 332: // topic
+ printf("> Topic: %s", arg);
+ return;
+ break;
+
+ case 333: // topic nick
+ printf("> Topic set by %s", arg);
+ return;
+ break;
+
+ case 375: // start of MOTD
+ case 372: // MOTD text
+ if(config->ui_flags & UIFLAG_HIDEMOTD) {
+ if(numeric == 375)
+ puts("> Hiding MOTD (be patient)");
+ }
+ return;
+ break;
+
+ case 376: // end of MOTD
+ case 422: // or MOTD missing
+ if(*(config->channel)) {
+ strcpy(channel, config->channel);
+ printf("> Joining %s\n", channel);
+ send_server_cmd("JOIN", channel);
+ joined_channel = 1;
+ }
+ break;
+
+ /*
+ case 352: // /who list
+ case 353: // /names list
+ case 366: // end of /names
+ case 315: // end of /who
+ break;
+ */
+
+ default:
+ break;
+ }
+ }
+
+ printf("%s %s", cmd, arg);
+}
+
+char incoming_ctcp(char *nick, char *msg) {
+ long now, then;
+ int sec, dec;
+
+ if(memcmp(msg, "PING ", 5) == 0) {
+ now = clock() * 10L;
+ then = ((long)(atoi(msg + 5)) +
+ ((long)(atoi(msg + 9)) << 8) +
+ ((long)(atoi(msg + 13)) << 16)) * 10L;
+
+ now -= then;
+ now /= CLOCKS_PER_SEC;
+ sec = now / 10;
+ dec = now % 10;
+
+ /* silently ignore timestamp wraparound */
+ /*
+ if(then >= now)
+ return 1;
+ */
+
+ printf("> %s ping time: %d.%d\n", nick, sec, dec);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Handler for text received from the server, responsible for
+ formatting. TODO: part/join/quit aren't handled correctly. */
+void do_msg() {
+ char *nick = output_buf, *cmd = output_buf, *chan = NULL, *msg = NULL;
+ char *bang = NULL;
+
+ while(*cmd != ' ') {
+ if(*cmd == '!') {
+ bang = cmd;
+ }
+ ++cmd;
+ }
+
+ /* no ! in nick means a server message */
+ if(!bang) {
+ do_server_msg();
+ return;
+ }
+
+ *cmd = '\0';
+ ++cmd;
+ chan = cmd;
+
+ while(*chan != ' ')
+ ++chan;
+ *chan = '\0';
+ ++chan;
+ msg = chan;
+
+ if(*msg != A_EOL) {
+ while(*msg && *msg != ' ')
+ ++msg;
+ if(*msg) {
+ *msg = '\0';
+ ++msg;
+ if(*msg == ':') ++msg;
+ }
+ }
+
+ /* FIXME: This stuff is hairy, unmaintainable, and probably just wrong
+ (works OK with the 2 or 3 NewNet servers I test with, not tried
+ others). It's the result of too much coffee, and needs to be
+ redesigned. Heck, it needs to be designed in the first place! */
+ if(strcmp(cmd, "PRIVMSG") == 0) {
+ nick[0] = '<';
+ bang[0] = '>';
+ bang[1] = '\0';
+ if(strcasecmp(chan, config->nick) != 0) {
+ // privmsg, not to our nick, must be channel text
+ if(memcmp(msg, "\x01" "ACTION ", 8) == 0) {
+ nick++;
+ *bang = '\0';
+ output_buf[output_buf_len - 2] = A_EOL;
+ output_buf[output_buf_len - 1] = '\0';
+ printf("* %s %s", nick, msg + 8);
+ } else {
+ printf("%s %s", nick, msg);
+ }
+ } else {
+ // privmsg, is to our nick
+ if(memcmp(msg, "\x01" "PING ", 6) == 0) {
+ nick++;
+ bang[0] = '\0';
+ output_buf[output_buf_len - 2] = '\0';
+ serv_msg_buf_len = sprintf(serv_msg_buf, "NOTICE %s :\x01PING %s\x01%c",
+ nick, msg + 6, 0x0a);
+ send_serv_msg_buf();
+ printf("* CTCP PING from %s\n", nick);
+ } else if(memcmp(msg, "\x01" "VERSION\x01", 9) == 0) {
+ nick++;
+ *bang = '\0';
+ serv_msg_buf_len = sprintf(serv_msg_buf, "NOTICE %s :\x01VERSION "
+ VERSION_REPLY " - running on "
+ "an Atari %s\x01%c",
+ nick, os_version, 0x0a);
+ send_serv_msg_buf();
+ printf("* CTCP VERSION from %s\n", nick);
+ } else {
+ printf("-> %s %s", nick, msg);
+ if(config->ui_flags & UIFLAG_MSGBELL)
+ bell();
+ bang[0] = '\0';
+#ifdef FEAT_KEYBOARD_MACROS
+ strcpy(last_msg_nick, nick + 1);
+#endif
+ }
+ }
+ } else if((strcmp(cmd, "NOTICE") == 0) && msg[0] == '\x01') {
+ nick++;
+ *bang = '\0';
+ if(!incoming_ctcp(nick, msg+1))
+ printf("* CTCP reply from %s: %s", nick, msg+1); // still has A_EOL
+ } else {
+ if(*msg) {
+ printf("%s %s %s %s", nick, cmd, chan, msg);
+ } else {
+ printf("%s %s %s", nick, cmd, chan);
+ }
+ }
+
+ fflush(stdout);
+}
+
+#ifdef FEAT_CURSOR_CONTROLS
+void del_user_buffer() {
+ /* delete user edit buffer */
+ if(input_buf_len) {
+ fuji_putchar(A_DEL);
+ if(input_buf_len > 119) {
+ fuji_putchar(0x1c); /* up arrow */
+ fuji_putchar(A_DEL);
+ }
+ }
+}
+
+#elif defined(FEAT_COL80_HACK)
+
+/* COL80 doesn't support the delete-line or arrow key
+ control codes.
+
+ Deleting and redrawing the user buffer is done by:
+
+ 1. Move the cursor to the start of the buffer on screen
+ 2. Print input_buf_len spaces
+ 3. Move cursor to the same spot as (1)
+ 4. Print the incoming text including EOL as usual
+ 5. redraw_user_buffer() as usual
+*/
+
+void del_user_buffer() {
+ int tlen;
+ char oldy;
+
+ if(!input_buf_len)
+ return;
+
+ tlen = input_buf_len;
+ oldy = fuji_getypos() - (input_buf_len / COLUMNS);
+
+ fuji_gotox(0);
+ fuji_gotoy(oldy);
+
+ do {
+ fuji_putchar(' ');
+ } while(--tlen);
+
+ fuji_gotox(0);
+ fuji_gotoy(oldy);
+}
+
+#endif
+
+#if defined(FEAT_CURSOR_CONTROLS) || defined(FEAT_COL80_HACK)
+//void redraw_user_buffer() {
+// int tlen;
+//# ifdef FEAT_LOW_RAM_BUFFERS
+//# define redraw_buf ((char *) 0x2800)
+//# else
+// static char redraw_buf[BUF_SIZE];
+//# endif
+// /* reprint user edit buffer */
+// if(input_buf_len) {
+// tlen = input_buf_len - 1;
+// do {
+// redraw_buf[tlen] = input_buf[tlen] | 0x80;
+// } while(tlen--);
+// redraw_buf[input_buf_len] = '\0';
+// fputs(redraw_buf, stdout);
+// fflush(stdout);
+// }
+//}
+
+void redraw_user_buffer() {
+ int i;
+ if(input_buf_len) {
+ for(i=0; i<input_buf_len; ++i)
+ fuji_putchar(input_buf[i] | 0x80);
+ }
+}
+
+#endif
+
+/* Another uIP app callback. This decides whether or not we've received
+ a complete message from the server (which may be split into multiple
+ packets, and may end in the middle of a packet) */
+void telnet_newdata(struct telnet_state *s, char *data, u16_t len) {
+ u16_t tlen = len;
+ char c, *t = data, buf_done = 0;
+
+ while(tlen-- != 0) {
+ c = *t++;
+ if(c == NL) { // swallow NL
+ continue;
+ } else if(c == CR) { // CR => EOL
+ c = A_EOL;
+ buf_done = 1;
+ } else if(c == TAB) { // tab
+ c = A_TAB;
+#ifndef FEAT_COL80_HACK
+ /* COL80 can actually print these OK */
+ } else if(c == '{') {
+ c = '[' | 0x80;
+ } else if(c == '}') {
+ c = ']' | 0x80;
+ } else if(c == '~') {
+ c = '^' | 0x80;
+ } else if(c == 0x60) { // backtick
+ c = 0xa7; // inverse quote
+#endif
+ }
+
+ output_buf[output_buf_len++] = c;
+ if(output_buf_len >= OUTBUF_SIZE) {
+ puts("[buffer overflow]\xfd");
+ buf_done = 1;
+ break;
+ }
+
+ if(buf_done) {
+#if defined(FEAT_CURSOR_CONTROLS) || defined(FEAT_COL80_HACK)
+ del_user_buffer();
+#endif
+ output_buf[output_buf_len] = '\0';
+
+ if(output_buf_len > 4 && (memcmp(output_buf, "PING", 4) == 0)) {
+ do_pong();
+ } else if(output_buf[0] == ':') {
+ do_msg();
+ } else {
+ fputs(output_buf, stdout);
+ fflush(stdout);
+ }
+
+#if defined(FEAT_CURSOR_CONTROLS) || defined(FEAT_COL80_HACK)
+ redraw_user_buffer();
+#endif
+
+#ifdef FEAT_COL80_HACK
+ // col80_cursor();
+#endif
+ output_buf_len = 0;
+ buf_done = 0;
+ }
+ }
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+/* uIP app callback for the resolver */
+void resolv_found(char *name, u16_t *ipaddr) {
+ if(ipaddr == NULL) {
+ printf("Host '%s' not found.\n", name);
+ done = 1;
+ } else {
+ printf("%s is %s\n", name, format_ip((uip_ipaddr_t *)ipaddr));
+ /*
+ printf("Found name '%s' = %d.%d.%d.%d\n", name,
+ htons(ipaddr[0]) >> 8,
+ htons(ipaddr[0]) & 0xff,
+ htons(ipaddr[1]) >> 8,
+ htons(ipaddr[1]) & 0xff);
+ */
+ if(!connected)
+ (void)uip_connect((uip_ipaddr_t *)ipaddr, htons(config->server_port));
+ }
+}
+
+#ifdef FEAT_LOGGING
+
+/* 0x100 * 32 = 8K (but we likely won't get that much) */
+#define LOG_PAGE_SIZE 0x200
+#define LOG_MAX_PAGES 16
+#define LOG_SCROLL_PAGES 2
+
+static char *log_buffer = NULL;
+static char *log_buf_end = NULL;
+static char *log_buf_current = NULL;
+static int log_pages = LOG_MAX_PAGES;
+
+static char last_log_nick[NICKLEN + 1];
+
+static void alloc_log_buffer() {
+ do {
+ printf("Trying to malloc(%x)...", LOG_PAGE_SIZE * log_pages);
+
+ log_buffer = malloc(LOG_PAGE_SIZE * log_pages);
+
+ if(log_buffer) {
+ puts("OK");
+ } else {
+ puts("Failed");
+ }
+ } while(!log_buffer && (--log_pages > LOG_SCROLL_PAGES * 2));
+
+ if(!log_buffer) return;
+
+ log_buf_end = (char *)(log_pages * LOG_PAGE_SIZE - 1);
+ log_buf_current = log_buffer;
+
+ printf("log_buffer == %x (%x)", log_buffer, log_pages * LOG_PAGE_SIZE);
+ fuji_cgetc();
+}
+
+static void log_msg(char *msg) {
+ int len = strlen(msg);
+ if( (log_buf_current + len + 1) > log_buf_end ) {
+ memmove(log_buffer, log_buffer + (LOG_SCROLL_PAGES * LOG_PAGE_SIZE), (log_pages - LOG_SCROLL_PAGES) * LOG_PAGE_SIZE);
+ log_buf_current -= (LOG_SCROLL_PAGES * LOG_PAGE_SIZE);
+ }
+}
+
+#endif
diff --git a/src/fujichat.cfg b/src/fujichat.cfg
new file mode 100644
index 0000000..974f49e
--- /dev/null
+++ b/src/fujichat.cfg
Binary files differ
diff --git a/src/fujichat.h b/src/fujichat.h
new file mode 100644
index 0000000..6b899ea
--- /dev/null
+++ b/src/fujichat.h
@@ -0,0 +1,136 @@
+#ifndef FUJICHAT_H
+#define FUJICHAT_H
+
+#include "uip.h"
+#include "aexec.h"
+
+/* Program name (plain ASCII for network use) */
+#define SELF "FujiChat"
+/* inverse video version, used for local prompts: */
+#define SELF_INV "\xc6\xf5\xea\xe9\xc3\xe8\xe1\xf4"
+
+#define VERSION "0.5_pre4"
+#define BANNER SELF_INV " v" VERSION
+#define VERSION_REPLY SELF " v" VERSION
+
+#define DEFAULT_NICK SELF
+
+// #define CONF_SIGNATURE "\x03\x0e"
+#define CONF_SIGNATURE_LO 0x03
+#define CONF_SIGNATURE_HI 0x0e
+#define CONF_VERSION 5
+
+#define BUF_SIZE 256
+#define OUTBUF_SIZE 512
+#define NICKLEN 20
+#define HOSTLEN 64
+
+/* fuji_conf_t is stored in the config file verbatim.
+ Don't forget to update CONF_VERSION when changing this struct!
+ Also, the first member should never, ever change, and the 2nd
+ (version) should only ever be set to CONF_VERSION (which can be
+ changed)
+
+ */
+typedef struct {
+ char signature[2];
+ u16_t version;
+
+ /* uIP settings: */
+ uip_ipaddr_t local_ip;
+ uip_ipaddr_t peer_ip;
+ uip_ipaddr_t resolver_ip;
+ char baud;
+
+ /* IRC settings: */
+ char server[HOSTLEN+1];
+ u16_t server_port;
+ char nick[NICKLEN+1];
+ char alt_nick[NICKLEN+1];
+ char real_name[NICKLEN+1];
+ char channel[NICKLEN+1];
+
+ /* UI settings: */
+ char bg_color;
+ char fg_color;
+ u16_t ui_flags; /* bitwise OR of UIFLAG_* constants */
+
+ /* Other stuff: */
+ char timezone; /* for later, when we use /TIME to set the clock */
+} fuji_conf_t;
+
+/* Chunk of RAM that holds our config data. Setup leaves the config
+ here for FujiChat to find. */
+#define CONFIG_ADDRESS 0x500
+
+#define ARGTYPE_NONE 0
+#define ARGTYPE_REQUIRED 1
+#define ARGTYPE_OPT 2
+
+typedef struct {
+ char *cmd; /* e.g. "ME" or "PING" */
+ char arg_type; /* one of ARGTYPE_* constants */
+ void (*handler)(void);
+} fuji_cmd_t;
+
+extern fuji_cmd_t cmd_list[];
+extern char *serv_msg_buf;
+extern int serv_msg_buf_len;
+extern char *cmd_arg;
+extern char channel[];
+extern struct telnet_state *tstate;
+extern char joined_channel;
+extern char *input_buf;
+
+void send_serv_msg_buf(void);
+void send_server_cmd(char *cmd, char *arg);
+void handle_command(void);
+void bell();
+
+/* Filenames */
+#define DEFAULT_CONF_FILE "D:FUJICHAT.CFG"
+#define MENU_FILENAME "D:FUJIMENU.COM"
+#define SETUP_FILENAME "D:FUJICONF.COM"
+#define IRC_FILENAME "D:FUJICHAT.COM"
+// #define IRC_LOADER_FILENAME "D:LOADCHAT.COM"
+#define SERIAL_DRIVER_FILENAME "D:DEFAULT.SER"
+#define DEFAULT_SERIAL_DRIVER "D:BOBVERT.SER"
+
+/* Whether or not to ring the bell on receiving private message */
+#define UIFLAG_MSGBELL 0x8000
+
+/* Whether or not to show [PING,PONG] */
+#define UIFLAG_SHOWPING 0x4000
+
+/* Visual bell (screen flash) instead of audible */
+#define UIFLAG_VBELL 0x2000
+
+/* Hide (don't display) the server MOTD */
+#define UIFLAG_HIDEMOTD 0x1000
+
+/* Disable bells entirely */
+#define UIFLAG_NOBELL 0x0800
+
+/* Auto-away when ATRACT mode kicks in */
+#define UIFLAG_ATRACT_AWAY 0x400
+
+
+/* ATASCII characters */
+#define A_EOL 0x9b
+#define A_TAB 0x7f
+#define A_BS 0x7e
+#define A_CLR 0x7d
+#define A_BEL 0xfd
+#define A_DEL 0x9c
+
+/* plain ASCII characters */
+#define NL 0x0a
+#define CR 0x0d
+#define TAB 0x09
+
+/* cc65's rs232.h doesn't define this for Atari: */
+#ifndef RS_BAUD_19200
+#define RS_BAUD_19200 0x0f
+#endif
+
+#endif
diff --git a/src/fujiconf.c b/src/fujiconf.c
new file mode 100644
index 0000000..f77f2a9
--- /dev/null
+++ b/src/fujiconf.c
@@ -0,0 +1,359 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <rs232.h>
+#include <errno.h>
+#include <peekpoke.h>
+#include "uip.h"
+#include "uiplib.h"
+#include "fujichat.h"
+#include "common.h"
+
+/* TODO: move these to an external file or otherwise come up with a way
+ to reuse the memory */
+#define SERVER_LIST_LEN (sizeof(servers) / sizeof(servers[0]))
+static char *servers[][2] = {
+ /*
+ { "82.165.139.95", "irc.tobug.net (US)" },
+ { "63.243.153.235", "irc.carterroadband.com (US)" },
+ { "209.133.9.109", "ircd.eyearesee.org (US)" },
+ { "89.238.135.210", "london.eyearesee.org (EU)" },
+ { "193.23.141.104", "hungary.eyearesee.org (EU)" },
+ */
+ { "na.newnet.net", "NewNet (North America)" },
+ { "eu.newnet.net", "NewNet (Europe)" },
+ { "us.undernet.org", "Undernet (US)" },
+ { "eu.undernet.org", "Undernet (Europe)" },
+ { "irc.freenode.org", "FreeNode" },
+ { "kubrick.freenode.net", "FreeNode (US)" },
+ { "irc.efnet.org", "Eris Free Net" },
+ { "82.165.139.95", "irc.tobug.net (NewNet, US)" },
+};
+
+// char rs232_already_loaded = 0;
+
+int baud_values[] = { 1200, 2400, 4800, 9600, 19200 };
+char baud_bytes[] = { RS_BAUD_1200, RS_BAUD_2400, RS_BAUD_4800, RS_BAUD_9600, RS_BAUD_19200 };
+char max_baud = sizeof(baud_bytes);
+
+static void get_conf_color(char *name, char *color, char dflt);
+static char get_yesno(char *prompt, char dflt);
+void save_config(void);
+
+static void bell() {
+ putchar(A_BEL);
+}
+
+static void get_baudrate(void) {
+ char i, buf[5];
+
+ putchar('\n');
+ for(i=0; i<max_baud; ++i)
+ if(config->baud == baud_bytes[i])
+ printf("[%d] %d\n", i+1, baud_values[i]);
+ else
+ printf(" %d. %d\n", i+1, baud_values[i]);
+
+ fputs("\nBaud rate: ", stdout);
+ fflush(stdout);
+
+ do {
+ get_line(buf, 4);
+ if(!*buf)
+ return;
+
+ i = atoi(buf);
+ } while (i < 1 || i > max_baud);
+ config->baud = baud_bytes[--i];
+}
+
+static void get_ip_addr(char *prompt, char *dflt, uip_ipaddr_t *addr) {
+ char ok;
+ char buf[HOSTLEN+1];
+
+ do {
+ printf("%s IP address [%s]: ", prompt, dflt);
+ fflush(stdout);
+ get_line(buf, HOSTLEN);
+ if(!*buf) strcpy(buf, dflt);
+ ok = uiplib_ipaddrconv(buf, (unsigned char*)addr);
+ if(!ok) bell();
+ } while(!ok);
+}
+
+#if 0
+char scan_hatabs(char dev) {
+ int entry;
+
+ /* 0x031A is HATABS from OS equates */
+ for(entry = 0x031A; entry < 0x033F; entry += 3)
+ if(PEEK(entry) == dev) return 1;
+
+ return 0;
+}
+
+int copy_file(char *dst, char *src) {
+ // THIS FUNCTION IS BROKEN!
+ static char buf[256];
+ int i;
+ FILE *from, *to;
+
+ if( !(from = fopen(src, "rb")) ) {
+ perror(src);
+ i = errno;
+ goto done;
+ }
+
+ if( !(to = fopen(dst, "wb")) ) {
+ perror(dst);
+ i = errno;
+ goto done;
+ }
+
+ while( (i = fread(buf, 1, 256, from)) )
+ fwrite(buf, 1, i, to);
+
+ if(feof(from))
+ i = 0;
+ else
+ i = errno;
+
+done:
+ if(from) fclose(from);
+ if(to) fclose(to);
+ return i;
+}
+#endif
+
+static void config_menu(void) {
+ char i, buf[HOSTLEN+1], ok = 0;
+ unsigned int new_value;
+
+ // strcpy(config->signature, CONF_SIGNATURE);
+ ((char *)config->signature)[0] = CONF_SIGNATURE_LO;
+ ((char *)config->signature)[1] = CONF_SIGNATURE_HI;
+ config->version = CONF_VERSION;
+
+ if(!config_is_valid())
+ set_default_config();
+
+ do {
+ puts("\n==> Serial Port Settings\n");
+
+ if(get_yesno("Change RS232 driver", 0)) {
+ atari_exec("D:MAKEAUTO.COM");
+ }
+
+ get_baudrate();
+
+ /* TODO: choose which Rn: device to use (e.g. on the 850),
+ turn HW flow control on/off (buried in cc65 rs232 lib code) */
+
+ puts("\n==> Network Settings\n");
+ get_ip_addr("Local", format_ip(&(config->local_ip)), &(config->local_ip));
+ get_ip_addr("Peer", format_ip(&(config->peer_ip)), &(config->peer_ip));
+ get_ip_addr("DNS Server", format_ip(&(config->resolver_ip)), &(config->resolver_ip));
+
+ puts("\n==> IRC Settings\n");
+ puts("Server list:");
+ for(i=0; i<SERVER_LIST_LEN; ++i) {
+ printf("%d: %s\n %s\n",
+ i + 1,
+ servers[i][0],
+ servers[i][1]);
+ }
+
+ printf("\nEnter # or any server host/IP [%s]: ", config->server);
+ fflush(stdout);
+ fgets(buf, HOSTLEN, stdin);
+
+ if(*buf != '\n') {
+ if(buf[0] >= '1' && buf[0] <= (SERVER_LIST_LEN + '0') && buf[1] == '\n') {
+ strcpy(buf, servers[buf[0] - '1'][0]);
+ }
+
+ for(i=0; buf[i] && (buf[i] != '\n'); ++i)
+ ;
+
+ buf[i] = '\0';
+ strcpy(config->server, buf);
+ }
+
+ printf("Server port [%d]: ", config->server_port);
+ get_line(buf, 10);
+ new_value = atoi(buf);
+ if(new_value) config->server_port = new_value;
+
+ printf("Your nickname [%s]: ", config->nick);
+ get_line(buf, NICKLEN);
+ if(*buf) strcpy(config->nick, buf);
+
+ printf("Your 'real' name [%s]: ", config->real_name);
+ get_line(buf, NICKLEN);
+ if(*buf) strcpy(config->real_name, buf);
+
+ do {
+ printf("Autojoin channel (or 0 for none)\n[%s]: ", config->channel);
+ get_line(buf, NICKLEN);
+
+ switch(*buf) {
+ case '\0':
+ ok = 1;
+ break;
+
+ case '#':
+ case '&':
+ strcpy(config->channel, buf);
+ ok = 1;
+ break;
+
+ case '0':
+ *(config->channel) = '\0';
+ ok = 1;
+ break;
+
+ default:
+ // user-friendly:
+ *(config->channel) = '#';
+ strcpy((config->channel) + 1, buf);
+ ok = 1;
+ break;
+
+ // user-hostile:
+ /*
+ puts("IRC channel names must begin with # or &");
+ bell();
+ ok = 0;
+ */
+ }
+
+ /* TODO: scan for illegal chars, set ok=0 */
+ } while(!ok);
+
+
+ puts("\n==> User Interface Settings\n");
+ do {
+ get_conf_color("Background", &(config->bg_color), config->bg_color);
+ get_conf_color("Foreground", &(config->fg_color), config->fg_color);
+ ok = ((config->bg_color & 0x0e) != (config->fg_color & 0x0e));
+ if(!ok)
+ puts("These colors would make your text\n"
+ "impossible to see. Try again.\n");
+ } while(!ok);
+
+ new_value =
+ (get_yesno("Disable bell", config->ui_flags & UIFLAG_NOBELL) ? UIFLAG_NOBELL : 0);
+
+ if(!(new_value & UIFLAG_NOBELL)) {
+ new_value |=
+ (get_yesno("Visual bell", config->ui_flags & UIFLAG_VBELL) ? UIFLAG_VBELL : 0);
+
+ new_value |=
+ (get_yesno("Bell on msg", config->ui_flags & UIFLAG_MSGBELL) ? UIFLAG_MSGBELL : 0);
+ };
+
+ new_value |=
+ (get_yesno("Show ping/pong", config->ui_flags & UIFLAG_SHOWPING) ? UIFLAG_SHOWPING : 0);
+
+ new_value |=
+ (get_yesno("Hide MOTD", config->ui_flags & UIFLAG_HIDEMOTD) ? UIFLAG_HIDEMOTD : 0);
+
+ config->ui_flags = new_value;
+
+ puts("\n==> Config complete\n");
+ ok = get_yesno("Is this correct", 1);
+ } while(!ok);
+
+ if(get_yesno("Save this config", 1))
+ save_config();
+
+ putchar('\n');
+}
+
+void save_config(void) {
+ FILE *f = fopen(DEFAULT_CONF_FILE, "wb");
+ if(f) {
+ fwrite(config, sizeof(fuji_conf_t), 1, f);
+ fclose(f);
+ puts("Config saved to " DEFAULT_CONF_FILE);
+ }
+}
+
+static void get_conf_color(char *name, char *color, char dflt) {
+ char buf[5];
+
+ printf("%s color [%d]: ", name, dflt);
+ fgets(buf, 5, stdin);
+
+ if(!(*buf >= '0' && *buf <= '9'))
+ *color = dflt;
+ else
+ *color = atoi(buf);
+}
+
+static char get_yesno(char *prompt, char dflt) {
+ char buf[5];
+
+ printf("%s [%c/%c]: ",
+ prompt,
+ (dflt ? 'Y' : 'y'),
+ (dflt ? 'n' : 'N'));
+
+ fflush(stdout);
+ get_line(buf, 4);
+ switch(*buf) {
+ case 'y':
+ case 'Y':
+ return 1;
+
+ case 'n':
+ case 'N':
+ return 0;
+
+ default:
+ return dflt;
+ }
+}
+
+void reboot(void) {
+ asm("jmp $e477");
+}
+
+void main(void) {
+ char *next_file, buf[2];
+ int ret;
+
+ disable_break();
+
+ putchar(125);
+ puts(BANNER " Setup\n");
+ get_config();
+
+ if(!config_is_valid())
+ set_default_config();
+
+ config_menu();
+
+ /*
+ if(rs232_already_loaded) {
+ puts("\nAn RS232 driver is already resident.\n"
+ "You must reboot to use the new driver.\n");
+ if(get_yesno("Reboot now", 1))
+ reboot();
+ }
+ */
+
+ if(get_yesno("Start FujiChat now", 1)) {
+ // next_file = IRC_LOADER_FILENAME;
+ next_file = IRC_FILENAME;
+ } else {
+ next_file = MENU_FILENAME;
+ }
+
+ printf("\nLoading %s...\n", next_file);
+ ret = atari_exec(next_file);
+
+ printf("Error %d!\n\xfd", ret);
+ puts("Press Enter to exit to DOS");
+ get_line(buf, 2);
+}
diff --git a/src/fujimenu.c b/src/fujimenu.c
new file mode 100644
index 0000000..29c9d7d
--- /dev/null
+++ b/src/fujimenu.c
@@ -0,0 +1,90 @@
+#include <stdio.h>
+#include <conio.h>
+#include <string.h>
+#include "fujichat.h"
+#include "common.h"
+
+/* TODO:
+ - rewrite in asm
+*/
+
+void run_prog(char *file) {
+ int c;
+ printf("\nLoading %s...\n", file);
+ c = atari_exec(file);
+ printf("Error %d!\n\xfd", c);
+}
+
+void main(void) {
+ int c, have_conf;
+
+ disable_break();
+
+ puts("\x7d" BANNER " Main Menu\n");
+
+ have_conf = get_config();
+ if(!have_conf)
+ set_default_config();
+
+ while(1) {
+ printf("\n %cbout\n", 'A' | 0x80);
+
+ printf("%s%cetup\n",
+ (have_conf ? " " : "* "),
+ 'S' | 0x80);
+
+ printf("%s%chat\n",
+ (have_conf ? "* " : " "),
+ 'C' | 0x80);
+
+ printf(" %cOS\n", 'D' | 0x80);
+
+ putchar('\n');
+ putchar('>');
+
+ cursor(1);
+ c = cgetc();
+ if(c == A_EOL || c == ' ')
+ c = (have_conf ? 'C' : 'S');
+
+ putchar(c | 0x80);
+
+ switch(c) {
+ case 'A':
+ case 'a':
+ run_prog("D:ABOUT.COM");
+ break;
+
+ case 'S':
+ case 's':
+ run_prog(SETUP_FILENAME);
+ break;
+
+ case 'C':
+ case 'c':
+ run_prog(IRC_FILENAME);
+ // run_prog(IRC_LOADER_FILENAME);
+ break;
+
+ /*
+ if(config_is_valid()) {
+ // atari_exec(IRC_LOADER_FILENAME);
+ atari_exec(IRC_FILENAME);
+ return 0;
+ } else {
+ putchar(A_BS);
+ puts("\nYou must run Setup first");
+ break;
+ }
+ */
+
+ case 'D':
+ case 'd':
+ return;
+
+ default:
+ putchar(A_BS);
+ break;
+ }
+ }
+}
diff --git a/src/fujiput.s b/src/fujiput.s
new file mode 100644
index 0000000..21a4969
--- /dev/null
+++ b/src/fujiput.s
@@ -0,0 +1,21 @@
+ .fopt compiler,"cc65 v 2.12.9"
+ .setcpu "6502"
+ .smart on
+ .autoimport on
+ .case on
+ .debuginfo off
+ .importzp sp, sreg, regsave, regbank, tmp1, ptr1, ptr2
+ .macpack longbranch
+ .export _fuji_putchar
+
+.segment "CODE"
+_fuji_putchar:
+ tax
+ ;lda $E407 ; don't use ROM, might be running COL80
+ lda $0347 ; grab from IOCB 0 instead
+ pha
+ ;lda $E406
+ lda $0346
+ pha
+ txa
+ rts
diff --git a/src/fujitest.atr b/src/fujitest.atr
new file mode 100644
index 0000000..7157856
--- /dev/null
+++ b/src/fujitest.atr
Binary files differ
diff --git a/src/getsmess.c b/src/getsmess.c
new file mode 100644
index 0000000..1a8494b
--- /dev/null
+++ b/src/getsmess.c
@@ -0,0 +1,66 @@
+#include <stdio.h>
+#include <peekpoke.h>
+
+
+void getlnasm(char *buf, char len) {
+ asm("ldy #$00");
+ asm("lda (sp),y");
+ asm("sta $e2");
+
+ asm("ldy #$02");
+ asm("jsr ldaxysp");
+ asm("sta $e0");
+ asm("stx $e0+1");
+
+ asm("@loop: lda _stdin");
+ asm("ldx _stdin+1");
+ asm("jsr _fgetc");
+
+ asm("cmp #$9B");
+ asm("beq @out");
+
+ asm("ldy #$00");
+ asm("sta ($e0),y");
+ asm("inc $e0");
+ asm("bne @noinc");
+ asm("inc $e0+1");
+ asm("@noinc:");
+
+ asm("dec $e2");
+ asm("bne @loop");
+
+ asm("@out:");
+ asm("ldy #$00");
+ asm("tya");
+ asm("sta ($e0),y");
+}
+
+void getln(char *buf, char len) {
+ char *p = buf;
+
+ do {
+ *p = fgetc(stdin);
+ if(*p == '\n') break;
+ } while(++p, --len);
+ *p = '\0';
+}
+
+void main(void) {
+ char buf[100] = "HELLO";
+ while(1) {
+ /*
+ puts("gets");
+ gets(buf);
+ puts(buf);
+ puts("fgets");
+ fgets(buf, 99, stdin);
+ puts(buf);
+ puts("getln");
+ getln(buf, 99);
+ puts(buf);
+ */
+ puts("getlnasm");
+ getlnasm(buf, 99);
+ puts(buf);
+ }
+}
diff --git a/src/hex2inc.pl b/src/hex2inc.pl
new file mode 100644
index 0000000..047438d
--- /dev/null
+++ b/src/hex2inc.pl
@@ -0,0 +1,31 @@
+#!/usr/bin/perl -w
+
+$|++;
+
+while(<>) {
+ chomp;
+ my ($c, $data) = split /:/;
+ $c = hex($c);
+ next unless $c >= 32 && $c <= 127;
+
+ my @data = ($data =~ /(..)/g);
+ die "invalid data" unless @data == 6;
+ my $last = pop @data;
+ die "bottom row not blank: $last" if $last ne "00";
+
+ $glyphs[$c] = \@data;
+}
+
+$idx = 0;
+for(my $c = 32; $c < 128; $c += 2) {
+ print " byte ";
+ $bits = "";
+ for(my $byte = 0; $byte < 5; ++$byte) {
+ printf '$%02X', hex($glyphs[$c][$byte]) | (hex($glyphs[$c+1][$byte]) >> 4);
+ print ", " unless $byte == 4;
+ $bits .= sprintf "%08b\n", hex($glyphs[$c][$byte]) | (hex($glyphs[$c+1][$byte]) >> 4);
+ }
+ print " ; [$idx] $c," . ($c+1) . " " . chr($c) . "," . chr($c+1) . "\n";
+# print STDERR $bits;
+ $idx += 5;
+}
diff --git a/src/irc_notes b/src/irc_notes
new file mode 100644
index 0000000..11006f0
--- /dev/null
+++ b/src/irc_notes
@@ -0,0 +1,95 @@
+connect to server, wait a second... NICK $nick
+USER dammit dammit irc.newnet.net :dammit
+JOIN #channel
+PRIVMSG #channel Hello world!
+
+At any time, if you get a PING $whatever, respond with PONG $whatever
+
+For now just dump everything to stdout, raw. Later we can be nice and format
+stuff like a real IRC client would...
+
+Need a custom DL, 24 lines of GR.0, set up correctly for the OS to print
+and scroll, etc, then one blank scanline and one more line of GR.0. Whatever
+the user types on the bottom line there gets displayed but not sent to
+the server until the user presses Return. If joined to a channel, there
+should be a prompt with the channel name, and any text typed should get
+sent as PRIVMSG #$channel $text. If no channel, don't send to server.
+Whether on a channel or not, user can use /commands. Minimal set we
+want to support:
+
+/nick $newnick
+/join #$channel
+/part
+/quit <$quitmsg>
+/msg $user $text
+/whois
+
+For now, only one channel can be joined. PRIVMSG's from other users, and
+server messages, etc, will be displayed mixed with channel text.
+
+Actually, the DL should maybe have an additional GR.0 status line at
+the top. This will be 26 lines... or we can have the 2nd line have a LMS
+pointing 40 bytes past the "real" location of the OS's screen RAM, meaning
+the OS will print & scroll the top line, but it won't actually be displayed.
+Eventually the whole thing has to be done with a custom screen handler,
+for performance reasons.
+
+/nick $nick
+
+Send "NICK $nick" to server
+
+If you send NICK $nick and get back a 433, that's "nick already in use",
+pick a different nick & try again. The USER command won't succeed until
+the initial NICK is established (nor will any JOINs, etc)
+
+/join $channel
+
+Send "JOIN $channel" to server. The user has to type the # (which might
+be some other character for some kinds of channels). Only one channel is
+supported for now.
+
+/part - send "PART $channel" to server ($channel is from the previous
+/join command)
+
+/quit <$quitmsg>
+
+With a message, send "QUIT :$quitmsg", otherwise just send "QUIT"
+
+/msg $user $test - send "PRIVMSG $user :$text" (should also allow /m)
+
+/whois $nick - send "WHOIS $nick"
+
+For normal channel text, send "PRIVMSG $channel :$text"
+
+Incoming text, need to translate EOLs and tabs... and strip color codes,
+handle ^AACTION, translate or ignore other unprintables in ATASCII,
+particularly { } ~ chars. Nicks need everything after the ! removed.
+A PRIVMSG to the current channel also needs everything up to and
+including "PRIVMSG $channel :" removed.
+
+The biggest problem right now: the code assumes each line of text from
+the IRC server (terminated with \n) will arrive in its own packet. This
+is often the case, but not always. What needs to happen is that there
+should be an output line buffer. The buffer starts empty, and as packets
+come in, they should be scanned for \n's and put into the buffer... when
+we hit a \n char, print (or format/parse) the output buffer, clear it,
+and start scanning again. If we hit end-of-packet, don't do anything with
+the buffer. Next packet, we'll start appending to the old buffer until we
+hit \n again. This will allow us to respond to PING requests even when
+they get split across packets. The buffer will probably be 1K in size,
+we need to handle overflow conditions in a sane way (maybe just pretend
+we got a \n and print/clear the buffer).
+
+actions:
+
+Send:
+PRIVMSG #chan :^AACTION does an action^A
+
+Receive:
+:nick PRIVMSG #chan ^AACTION does an action^A
+
+pings:
+
+Receive:
+
+:nick PRIVMSG nick ^APING <stuff>^A
diff --git a/src/keybuf.h b/src/keybuf.h
new file mode 100644
index 0000000..1430ef4
--- /dev/null
+++ b/src/keybuf.h
@@ -0,0 +1,26 @@
+
+/* Dead simple keyboard buffer mechanism
+
+ Call keybuf_init() at startup
+
+ During busy loops, periodically call keybuf_poll_kbd(),
+ which will buffer keystrokes as they're pressed.
+
+ When ready to read the keyboard, call keybuf_cgetc()
+ Return value is 0 for no key pressed and no keys in buffer,
+ or else the ASCII code of the next key.
+
+ Also, can call keybuf_is_empty() to find out whether the
+ buffer's got anything in it.
+
+ It would be possible to have the OS periodically call
+ keybuf_poll_kbd() for us, using one of the countdown timers.
+ For now, not going to do this, as it adds complexity and
+ fujichat only has 2 or 3 places that count as busy
+ loops.
+ */
+
+void __fastcall__ keybuf_init(void);
+void __fastcall__ keybuf_poll_kbd(void);
+char __fastcall__ keybuf_is_empty(void);
+char __fastcall__ keybuf_cgetc(void);
diff --git a/src/keybuf.s b/src/keybuf.s
new file mode 100644
index 0000000..cf24e77
--- /dev/null
+++ b/src/keybuf.s
@@ -0,0 +1,94 @@
+ .fopt compiler,"cc65 v 2.12.9"
+ .setcpu "6502"
+ .smart on
+ .autoimport on
+ .case on
+ .debuginfo off
+ .importzp sp, sreg, regsave, regbank, tmp1, ptr1, ptr2
+ .export _keybuf_init, _keybuf_poll_kbd, _keybuf_cgetc
+
+NO_KEY = $FF
+max_buf_len = 12 ; aka buffer size
+
+BUFFER_BASE = $F0
+
+keybuf_head = BUFFER_BASE
+keybuf_tail = BUFFER_BASE+1
+keybuf = BUFFER_BASE+2
+keybuf_end = keybuf + max_buf_len
+
+CH = $02FC
+
+ .segment "CODE"
+
+; void __fastcall__ keybuf_init(void)
+_keybuf_init:
+ lda #keybuf
+ sta keybuf_head
+ sta keybuf_tail
+ rts
+
+; void __fastcall__ keybuf_poll_kbd(void)
+_keybuf_poll_kbd:
+ lda CH
+ cmp #NO_KEY
+ beq kbpoll_done
+
+ ; got a key, see if room in buffer
+ ldx keybuf_tail
+ cpx #keybuf_end+1
+ bcs kbpoll_done
+
+ ; buffer not full, so store key in buffer
+ sta 0,x
+ inc keybuf_tail
+
+ ; clear keyboard register
+ lda #NO_KEY
+ sta CH
+
+kbpoll_done:
+ rts
+
+
+; char __fastcall__ keybuf_is_empty(void)
+_keybuf_is_empty:
+ ldx #0
+ sec
+ lda keybuf_tail
+ sbc keybuf_head
+ rts
+
+
+; char __fastcall__ keybuf_cgetc(void)
+
+; Note: 0 means "no key pressed", which means we
+; can't return character code 0 (not a big deal).
+; If this is a problem, we could change the return
+; type to int, and return -1 instead.
+
+_keybuf_cgetc:
+ ldx keybuf_head
+ cpx keybuf_tail
+ beq check_ch
+
+ ; got a key, stuff it in CH
+ lda 0,x
+ sta CH
+ inc keybuf_head
+
+call_cgetc:
+ ; ...and return the ASCII code
+ jmp _fuji_cgetc
+
+check_ch:
+ jsr _keybuf_init
+
+ ldx CH
+ cpx #NO_KEY
+ bne call_cgetc
+
+ inx ; was $FF, now 0
+ txa ; aka return(0)
+ rts
+
diff --git a/src/keybuftest.c b/src/keybuftest.c
new file mode 100644
index 0000000..4ea7f12
--- /dev/null
+++ b/src/keybuftest.c
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <peekpoke.h>
+#include <conio.h>
+
+#include "keybuf.h"
+
+#define RTCLOK 0x14
+
+void read_input(void) {
+ char got[20];
+ char c, *p = got;
+
+ while( (c = keybuf_cgetc()) )
+ putchar(c);
+
+ // *p++ = c;
+
+ /*
+ *p = '\0';
+
+ if(p != got)
+ fputs(got, stdout);
+ */
+}
+
+void process(void) {
+ POKE(RTCLOK, 0);
+ while(PEEK(RTCLOK) < 30) {
+ keybuf_poll_kbd();
+ }
+}
+
+void idle(void) {
+ char c;
+ POKE(RTCLOK, 0);
+ while(PEEK(RTCLOK) < 30) {
+ if( (c = keybuf_cgetc()) )
+ putchar(c);
+ }
+}
+
+void main(void) {
+ cursor(1);
+ keybuf_init();
+
+ while(1) {
+ process();
+ read_input();
+ idle();
+ }
+}
diff --git a/src/loadchat.dasm b/src/loadchat.dasm
new file mode 100644
index 0000000..c63ed41
--- /dev/null
+++ b/src/loadchat.dasm
@@ -0,0 +1,54 @@
+
+; If no R: driver is loaded, load DEFAULT.SER
+; Then, load FujiChat
+
+; This is needed because e.g. Bob-verter loads at $5000, smack in the
+; middle of FujiChat's code. This tiny little loader program should be
+; small enough and out-of-the-way enough that nothing will stomp on it.
+
+ processor 6502
+ include "equates.inc"
+
+atari_exec = $0600
+main = $2E00 ; same place as cc65
+
+; segment header
+ org main-6
+ word $FFFF
+ word main
+ word endmain-1
+
+ org main
+
+; search handler table for R entry
+ ldx #0
+tabloop:
+ lda HATABS,x
+ cmp #'R
+ beq load_chat
+ inx
+ inx
+ inx
+ cpx #$24 ; 12 entries * 3 bytes = 36
+ bne tabloop
+
+; no R: driver found, load one
+ lda #<driver_filename
+ ldx #>driver_filename
+ jsr atari_exec
+
+; load main fujichat program (does not return)
+; (in fact it better not return, it overwrites this program!)
+load_chat:
+ lda #<chat_filename
+ ldx #>chat_filename
+ jmp atari_exec
+
+driver_filename .byte "D:DEFAULT.SER", 0
+chat_filename .byte "D:FUJICHAT.COM", 0
+endmain
+
+; segment header
+ word RUNAD
+ word RUNAD+1
+ word main
diff --git a/src/loadmenu.dasm b/src/loadmenu.dasm
new file mode 100644
index 0000000..71cbdfc
--- /dev/null
+++ b/src/loadmenu.dasm
@@ -0,0 +1,69 @@
+
+; Load MENU.COM
+
+; This will be part of AUTORUN.SYS on the disk. Without it,
+; I'd have to make AUTORUN.SYS a copy of MENU.COM :(
+
+ processor 6502
+ include "equates.inc"
+
+atari_exec = $0600
+main = $2E00 ; same place as cc65
+
+; segment header
+ org main-6
+ word $FFFF
+ word main
+ word endmain-1
+
+ org main
+
+; do this so pressing Reset give us DOS
+; ldx #1
+; stx BOOTQ
+; dex
+; stx COLDST
+
+; remove later: see if FujiChat can work with only 44K
+;; lda #$B0
+;; sta RAMTOP
+;; lda #12 ; CIO CLOSE
+;; sta ICCOM
+;; ldx #0
+;; jsr CIOV
+;;
+;;
+;; lda #3 ; Command 3=OPEN
+;; sta ICCOM
+;; lda #12 ; 12=R/W access
+;; sta ICAX1
+;; lda #0
+;; sta ICAX2
+;; lda #<e_dev ; E: device
+;; sta ICBAL
+;; lda #>e_dev
+;; sta ICBAH
+;; lda #e_dev_len
+;; sta ICBLL
+;; lda #0
+;; tax
+;; sta ICBLH
+;; jsr CIOV ; call CIO
+
+
+; our raison d'etre...
+ lda #<menu_filename
+ ldx #>menu_filename
+ jmp atari_exec
+
+menu_filename .byte "D:FUJIMENU.COM", 0
+
+e_dev byte "E:",0
+e_dev_len equ *-e_dev+1
+
+endmain
+
+; segment header
+ word RUNAD
+ word RUNAD+1
+ word main
diff --git a/src/loadmkau.dasm b/src/loadmkau.dasm
new file mode 100644
index 0000000..613be44
--- /dev/null
+++ b/src/loadmkau.dasm
@@ -0,0 +1,69 @@
+
+; Load MENU.COM
+
+; This will be part of AUTORUN.SYS on the disk. Without it,
+; I'd have to make AUTORUN.SYS a copy of MENU.COM :(
+
+ processor 6502
+ include "equates.inc"
+
+atari_exec = $0600
+main = $2E00 ; same place as cc65
+
+; segment header
+ org main-6
+ word $FFFF
+ word main
+ word endmain-1
+
+ org main
+
+; do this so pressing Reset give us DOS
+; ldx #1
+; stx BOOTQ
+; dex
+; stx COLDST
+
+; remove later: see if FujiChat can work with only 44K
+;; lda #$B0
+;; sta RAMTOP
+;; lda #12 ; CIO CLOSE
+;; sta ICCOM
+;; ldx #0
+;; jsr CIOV
+;;
+;;
+;; lda #3 ; Command 3=OPEN
+;; sta ICCOM
+;; lda #12 ; 12=R/W access
+;; sta ICAX1
+;; lda #0
+;; sta ICAX2
+;; lda #<e_dev ; E: device
+;; sta ICBAL
+;; lda #>e_dev
+;; sta ICBAH
+;; lda #e_dev_len
+;; sta ICBLL
+;; lda #0
+;; tax
+;; sta ICBLH
+;; jsr CIOV ; call CIO
+
+
+; our raison d'etre...
+ lda #<menu_filename
+ ldx #>menu_filename
+ jmp atari_exec
+
+menu_filename .byte "D:MAKEAUTO.COM", 0
+
+e_dev byte "E:",0
+e_dev_len equ *-e_dev+1
+
+endmain
+
+; segment header
+ word RUNAD
+ word RUNAD+1
+ word main
diff --git a/src/loadtest.c b/src/loadtest.c
new file mode 100644
index 0000000..cf56627
--- /dev/null
+++ b/src/loadtest.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+void __fastcall__ (*atari_exec_p)(char *) = (void __fastcall__ (*)(char *))0x600;
+#define atari_exec(x) ((*atari_exec_p)(x))
+
+int main(int, char **) {
+ puts("Loading D:RVERT.COM");
+ atari_exec("D:RVERT.COM");
+ puts("Loading D:FUJICHAT.RAW");
+ atari_exec("D:FUJICHAT.RAW");
+ puts("Should never get here!");
+}
diff --git a/src/logcomptest.pl b/src/logcomptest.pl
new file mode 100644
index 0000000..6285f93
--- /dev/null
+++ b/src/logcomptest.pl
@@ -0,0 +1,229 @@
+#!/usr/bin/perl -w
+
+# sample session for IRC log compression scheme
+
+$lastnick = "";
+$textlen = 0;
+while(<DATA>) {
+ $lines++;
+ $bigtot += length($_);
+ chomp;
+
+ my ($nick, $text) = split " ", $_, 2;
+ for($nick, $text) {
+ s/(.)$/chr(ord($1)|0x80)/e;
+ }
+
+ if(($nick ne $lastnick) || ($textlen + length($text) > 256)) {
+ $output .= $nick;
+ $output .= $text;
+ $lastnick = $nick;
+ $textlen = length($text);
+ } else {
+ $output .= chr(1) . $text;
+ $textlen += length($text);
+ }
+}
+
+print "lines: $lines\n";
+print "old: $bigtot\n";
+print "new: " . length($output) . "\n";
+print "saved: " . ($bigtot - length($output)) . "\n";
+print "compression: " . (1.0 - (length($output) / $bigtot)) . "\n";
+
+print STDERR $output;
+
+__DATA__
+Slor WIDE?
+Slor dunno
+Redbeard I've seen a 29w7 though.
+SteveS who you calling WIDE?
+DogWombl i'm not wide, i'm just badly out of proportion
+Redbeard Was labeled "video" on the back of a Intergraph machine, back when they had their own unix running on a custom cpu.
+Slor where'd urch go, anyway?
+Slor ask a question and disappear
+SteveS he said he had real work
+SteveS be back late, late
+BeetlePC hey SteveSI have two 10base2 NICs but I don't need transceivers and I definitely don't want any of those fat ass transceiver cables.
+SteveS beetle, how is the 1080 coming?
+SteveS bah. I'm going through BSG withdrawal!
+Redbeard Transcievers would allow you to put a 10base5 nic onto the same coax network. Or sometimes rackmount switches have a (is it db15?) connector on them.
+Slor someone tell me this too - what is a "Modem Eliminator"? Is that just fancy for null modem?
+SteveS group shrug
+BeetlePC i didn't work on it lately
+SteveS grrr. I still can't figure why my MyIDE movie audio player is not playing nice.
+SteveS I will order parts for SDrive this week. I will. I will. I will.
+Redbeard q
+SteveS been saying that for a while now
+BeetlePC good, good, good
+BeetlePC :)
+Slor doesn't buy it
+SteveS $7 seems too much for a SD connector though. I might try the floppy cable connector hack on the first try.
+BeetlePC you can also cannibalize a dead/cheap SD card reader
+SteveS don't have one
+ChrisTOS nn
+BeetlePC night
+SteveS nite
+SteveS christos
+ChrisTOS q
+Slor didn't even see him talk today
+SteveS I need to get a working one though
+atarixle q
+SteveS I didn't know atarixle was here
+SteveS Would ask him if there is an English version of the new Boss X.
+BeetlePC he told you
+SteveS people need better names, btw. XL Boss, Boss XL, and Boss X.
+BeetlePC 10.4 will be available in german and english
+SteveS oh!
+SteveS I missed the answer.
+SteveS I thought he ignored me
+BeetlePC i remembered it :)
+SteveS my mistake. sorry.
+BeetlePC np
+BeetlePC gets himself a beer
+BeetlePC cheers
+SteveS has no beer in the house and is not going out in 19 degree weather to get some.
+SteveS cheers
+SteveS holds up his empty tea mug
+BeetlePC :)
+BeetlePC *pling*
+BeetlePC i scored an IBM thinkpad T42 on ebay today
+BeetlePC its for my dad
+SteveS Zum Wohl to dad
+BeetlePC 1.6 GHz Pentium M, 1 Gig of RAM and a new 160GB HD, plus a new IBM battery (used laptop batterys are most often dead)
+BeetlePC should do for his mobile computing needs
+SteveS :)
+BeetlePC He is some 'car accident expert' i don't know how that job is called in english. He views damaged cars and estimates the cost of repairs. He also reconstructs what happend during the crash.
+BeetlePC How the crash happend
+BeetlePC happened
+SteveS Adjuster?
+SteveS Insurance Adjuster, is what we call them.
+BeetlePC hmm
+BeetlePC he does not work for an insurance
+SteveS oh
+BeetlePC one-man-company
+BeetlePC he is the boss of himself :)
+BeetlePC and also the best boy
+SteveS I don't think we have a single equivalent for that job.
+BeetlePC Kfz-Sachverständiger
+BeetlePC lets see what google says
+BeetlePC car expert :-/
+SteveS oops when I cut and pasted into babel fish I got my Atari font
+SteveS Kfz-Sachverständiger
+SteveS looks Ok here
+SteveS Atari Extrasmooth
+BeetlePC well, he looks at the damaged car, writes down every harmed component and calculates the time to repair it.
+SteveS in babel fish
+BeetlePC and for this job, a laptop would be nice
+SteveS estimates are performed by a representative of your insurance company here.
+BeetlePC thats common here, too
+SteveS also called Claims Adjuster
+BeetlePC but the job has not to be done by someone from the insurance
+BeetlePC you are allowed to choose here
+SteveS some insurance companines allow you to call to a service shop or even several service shops.
+BeetlePC and a 'independend claims adjuster' might get a larger payment form the insurance of your opponent than his insurances representant
+BeetlePC from -from
+BeetlePC because he doesn't get payed for keeping costs small for the insurance
+SteveS Some insurance companies won't even pay for original parts
+BeetlePC because of that, if your car gets damaged by someone, you are allowed to choose who will examine you car
+rrCurtisP j
+SteveS My friend bought a Mini Cooper
+SteveS a new one
+BeetlePC wow, nice
+SteveS I think he is a having a mid-life crisis. Normally a very conservative person.
+SteveS I always wanted a Porshe 356
+BeetlePC well, if a car he likes helps - better than leaviing wife and kids as a neighour here does
+SteveS ouch
+BeetlePC fuse blown - i have no other explanation
+SteveS 20 yr-old GF maybe
+BeetlePC no - or he does hide it well
+BeetlePC :)
+charliec j
+charliec good evening all
+BeetlePC hey charliec
+charliec Hiya Beetle
+Harlock q
+SteveS hey charliec
+charliec Hi Steve
+SteveS charliie, did I remember to send you MyDOS 3.19?
+charliec Nope
+SteveS It has the RS232 driver for ATR8000
+charliec didnt know if you caught that..
+SteveS sorry
+charliec dont be
+SteveS dcc in just a second
+charliec hold.. im on fuji
+SteveS oh
+SteveS that won't work
+SteveS not yet
+charliec not yet huh
+cc_PC j
+cc_PC okee
+cc_PC ready when you are
+Harlock j
+cc_PC Thanks!
+SteveS welcome
+SteveS you will be asked to build a version of DOS. It does it in memory the you must select 'H', Save DOS files.
+cc_PC Ok
+charliec ever run CP/M on the ATR Steve?
+Moloch j
+charliec well heading to a surprise b-day party, cant be late for those!
+charliec nute
+charliec heh.. nite
+charliec q
+cc_PC q
+BeetlePC good night
+BeetlePC q
+fres j
+fres hey, all.
+fres and by all I mean, uh... who?
+Slor yo
+SteveS oops. I fell asleep
+Slor heh
+SteveS hi fres
+SteveS Hot cocoa! BRB...
+fres fellas...
+Harlock q
+Harlock j
+SteveS _FujIRC time to backup MyIDE
+SteveS _FujIRC q
+SteveS damn, it's quiet in here
+DogWombl it seems to be quiet in irc channels everywhere
+Harlock everyone but us out on friday night
+Moloch q
+SteveS _FujIRC j
+SteveS _FujIRC back
+SteveS wb
+rrCurtisP q
+Woodzy q
+DocRotCod j
+SteveS _FujIRC q
+Velcro_MM q
+Velcro_MM j
+fres nope
+SteveS yup yup yup
+SteveS nothing to see here
+SteveS Anyone have to travel for Thanksgiving?
+SteveS Not me.
+DocRotCod q
+Urchlay Redb3ard and JellE are driving to Indiana
+SteveS oh, is Red from there?
+Urchlay think he's from Virginia, but got family there
+Redb3ard Grew up in Indiana, only place I'd ever been until I was 18.
+Urchlay my grandma (like 88 this year) was going to come up this year
+Redb3ard I just happened to be in Virginia, when we started talking.
+Urchlay ah
+Urchlay grandma can't drive for 4 hours straight (er, way she drives it'd take 8 anyway)
+Urchlay the other day my aunt who was gonna do the driving, fell & broke her hip
+Urchlay so no aunt, no grandma, no cool cousin
+Urchlay (well, maybe cool cousin, she lives in Riverdale IIRC)
+SteveS ouch. well, I wish your aunt a fast recovery.
+Urchlay the doc says she's doing great
+Urchlay I really don't think of her as *old* but she's in her 60s now I guess
+Urchlay (if I ask, she'll say she's still 59 I'm sure)
+Urchlay wish I had the car, I'd drive down there
+Urchlay go see her in the hospital, bring a fake can of peanuts with a snake in it
+Urchlay (a fake one!)
+Urchlay eh, sorry, the snake thing is like a 20-year running gag I guess
+SteveS um
+SteveS ok
diff --git a/src/logtest.c b/src/logtest.c
new file mode 100644
index 0000000..4a22cb4
--- /dev/null
+++ b/src/logtest.c
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* 0x100 * 32 = 8K (but we likely won't get that much) */
+#define LOG_PAGE_SIZE 0x20
+#define LOG_MAX_PAGES 16
+#define LOG_SCROLL_PAGES 2
+
+static char *log_buffer = NULL;
+static char *log_buf_end = NULL;
+static char *log_buf_current = NULL;
+static int log_pages = LOG_MAX_PAGES;
+
+// static char last_log_nick[NICKLEN + 1];
+
+static void alloc_log_buffer() {
+ log_buffer = malloc(LOG_PAGE_SIZE * log_pages);
+ log_buf_end = (char *)(log_buffer + log_pages * LOG_PAGE_SIZE - 1);
+ log_buf_end[1] = 0xaa;
+ log_buf_current = log_buffer;
+}
+
+static void log_msg(char *msg) {
+ int len = strlen(msg);
+ if( (log_buf_current + len + 1) > log_buf_end ) {
+ memmove(log_buffer, log_buffer + (LOG_SCROLL_PAGES * LOG_PAGE_SIZE), (log_pages - LOG_SCROLL_PAGES) * LOG_PAGE_SIZE);
+ log_buf_current -= (LOG_SCROLL_PAGES * LOG_PAGE_SIZE);
+ }
+
+ memcpy(log_buf_current, msg, len);
+ log_buf_current += (len + 1);
+ *log_buf_current = '\0';
+}
+
+static void dump_log_stats(void) {
+ printf("start: %x, end: %x, cur: %x\n", log_buffer, log_buf_end, log_buf_current);
+}
+
+void main(void) {
+ char buf[100];
+ int i;
+
+ alloc_log_buffer();
+ dump_log_stats();
+
+ for(i=0; i<24; i++) {
+ sprintf(buf, ":--------------------Iteration #%d\n", i);
+ log_msg(buf);
+ dump_log_stats();
+ }
+HANG: goto HANG;
+}
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..2e5ee17
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,1184 @@
+/*
+ * Copyright (c) 2008, Brian Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgements:
+ * This product includes software developed by Adam Dunkels.
+ * This product includes software developed by Brian Watson.
+ * 4. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the FujiChat IRC client.
+ *
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <atari.h>
+#include "uip.h"
+#include "uiplib.h"
+#include "rs232dev.h"
+#include <conio.h>
+#include <peekpoke.h>
+#include <string.h>
+#include <ctype.h>
+#include <rs232.h>
+
+#include "timer.h"
+
+#ifndef NULL
+#define NULL (void *)0
+#endif /* NULL */
+
+/* Program name (plain ASCII for network use) */
+#define SELF "FujiChat"
+/* inverse video version, used for local prompts: */
+#define SELF_INV "\xc6\xf5\xea\xe9\xc3\xe8\xe1\xf4"
+
+#define VERSION "0.3.1"
+#define BANNER SELF_INV " v" VERSION
+#define VERSION_REPLY SELF " v" VERSION
+
+
+#define DEFAULT_NICK SELF
+
+#define CONF_SIGNATURE "\x03\x0e"
+#define CONF_VERSION 4
+#define DEFAULT_CONF_FILE "FUJICHAT.CFG"
+
+/* TODO: move the non-IRC-related config to a separate SETUP program,
+ and a separate UIP.CFG file. This will be shared by all apps that
+ use uIP, such as the planned telnet and FTP clients. Also it means
+ we don't have to bloat each program with a complete config UI
+ for things like the local/peer/DNS IP addresses.
+
+ In fact the SETUP utility might resolve IP addresses for us, so
+ each app might not need its own copy of the resolver... though
+ that's maybe a bit clumsy to use for FTP, since you generally want
+ to easily be able to connect to arbitrary servers (unlike, say, IRC
+ where you usually use the same server all the time). Perhaps SETUP
+ could resolve arbitrary hostnames, then write them to a /etc/hosts
+ type of file. Parsing /etc/hosts entries is fairly lightweight,
+ could be done in all the client programs...
+
+ ...or maybe what should happen is that there should be a RESOLV
+ program that can resolve hostnames, and read/write them in text
+ form to a HOSTS.TXT file... and also parses the HOSTS file and
+ stores the hostname strings and 4-byte IP addresses in a fixed
+ area of memory. The app programs could just look up hostnames in
+ this memory area, without having to open & parse HOSTS themselves.
+ cc65 programs by default start at $2E00. The Bob-verter driver ends
+ around $2200 (other R: drivers should be comparable), which gives
+ us around 3K of unallocated memory. Assuming the average hostname/IP
+ pair is 50 bytes, that'd give us about 60 of them. The RESOLV program
+ would stop the user from adding more hostnames when there's no space
+ for them (and let them delete some to make room, maybe commenting them
+ out so they remain in the HOSTS file for future uncommenting).
+
+ Ultimately there should be a master AUTORUN.SYS file with a menu
+ that runs the other sub-apps (or lets you exit to DUP). Menu would
+ have options like "DNS", "IRC", "FTP", "Telnet", and "Network
+ Setup". Of course I need to write a program loader, there's no
+ exec* functions in cc65! The Network Setup option would let you
+ specify the R: driver you want to load, so it wouldn't have to
+ be prepended to any of the executables, and would be auto-loaded
+ the first time you try to run any of the apps that need it. It'd
+ be nice if the main menu program had at least a few DOS functions
+ as well (delete/copy/rename/lock/unlock, format too?)
+
+ Probably, FujiChat's 1.0 release will be as a standalone IRC client,
+ with the current config UI stuff as-is. The other stuff would be
+ released months from now, under the label "FujiNet" or something, and
+ include a new version of FujiChat as one of several apps.
+
+ The final distibution disk will need at least some documentation in
+ Atari-readable text format, plus a doc-reader program.
+
+ All the subprograms need to end with RTS to the menu program, which
+ shold be small and stay resident in addresses not touched by cc65
+ (I've got 128 bytes each in the cassette buffer and page 5, also
+ 256 more in page 6. Should be easy to squeeze into 512 bytes, no?)
+
+ So a disk directory would contain:
+
+ DOS.SYS, DUP.SYS
+ AUTORUN.SYS - the main menu and subprogram loader
+ BOBVERT.XEX - the Bob-verter R: driver
+ A850.XEX - the 850 R: driver (from DOS 2.0S I guess)
+ MIO.XEX, BLACKBOX.XEX, etc, drivers for other serial ports
+ HOSTS.TXT - the /etc/hosts file, human-readable and -editable
+ README.TXT - docs
+ MORE.XEX - doc reader (should handle ASCII or ATASCII EOLs)
+ SETUP.XEX - set up global network settings (local/remote/dns IPs, also
+ things like screen colors, key-repeat rate, etc).
+ DNS.XEX - lookup hostnames, maintain and parse HOSTS.TXT
+ FTP.XEX, TELNET.XEX, IRC.XEX, PING.XEX - the apps
+ FTP.CFG, TELNET.CFG, IRC.CFG, etc - app-specific settings
+ FUJINET.CFG - global settings
+ ...if there's room on the disk, a small text editor might be nice
+ to include.
+
+ The whole thing should be distributed as a bootable, single-density
+ DOS disk (undecided which DOS, either 2.0S or MyDOS 4.5).
+
+ Alternatively, all the XEX files might be named COM, and the whole
+ thing could run under a CLI DOS like Sparta (if it'll actually
+ run). The apps could take optional CLI arguments, also... and the
+ AUTORUN.SYS would actually be unnecessary!
+
+ */
+
+#define BUF_SIZE 256
+#define OUTBUF_SIZE 768
+#define NICKLEN 20
+#define HOSTLEN 64
+
+/* fuji_conf_t is stored in the config file verbatim.
+ Don't forget to update CONF_VERSION when changing this struct!
+ Also, the first member should never, ever change, and the 2nd
+ (version) should only ever be set to CONF_VERSION (which can be
+ changed)
+
+ TODO:
+ char alt_nick[NICKLEN+1];
+ */
+typedef struct {
+ char signature[2];
+ u16_t version;
+
+ /* uIP settings: */
+ uip_ipaddr_t local_ip;
+ uip_ipaddr_t peer_ip;
+ uip_ipaddr_t resolver_ip;
+ char baud;
+
+ /* IRC settings: */
+ char server[HOSTLEN+1];
+ u16_t server_port;
+ char nick[NICKLEN+1];
+ char real_name[NICKLEN+1];
+ char channel[NICKLEN+1];
+
+ /* UI settings: */
+ char bg_color;
+ char fg_color;
+ u16_t ui_flags; /* bitwise OR of UIFLAG_* constants */
+} fuji_conf_t;
+
+fuji_conf_t config;
+
+/* Whether or not to ring the bell on receiving private message */
+#define UIFLAG_MSGBELL 0x8000
+
+/* Whether or not to show [PING,PONG] */
+#define UIFLAG_SHOWPING 0x4000
+
+/* Visual bell (screen flash) instead of audible */
+#define UIFLAG_VBELL 0x2000
+
+/* Hide (don't display) the server MOTD */
+/* TODO: implement */
+#define UIFLAG_HIDEMOTD 0x1000
+
+/* Disable bells entirely */
+#define UIFLAG_NOBELL 0x0800
+
+char os_version[10] = "XL_XE";
+char channel[BUF_SIZE];
+char input_buf[BUF_SIZE];
+char chan_msg_buf[BUF_SIZE * 2];
+char output_buf[OUTBUF_SIZE + 1];
+char last_msg_nick[NICKLEN+1] = "";
+
+int input_buf_len = 0;
+int output_buf_len = 0;
+
+char config_valid = 0;
+char done = 0;
+char connected = 0;
+char joined_channel = 0; /* true if we're in a channel */
+char nick_registered = 0;
+char vbell_active = 0;
+
+static void get_line(char *buf, unsigned char len);
+static void handle_keystroke(void);
+static void handle_command(void);
+static void get_config(void);
+static void config_menu(void);
+static void send_server_cmd(char *cmd, char *arg);
+static void bell();
+void redraw_user_buffer();
+
+/* ATASCII characters */
+#define A_EOL 0x9b
+#define A_TAB 0x7f
+#define A_BS 0x7e
+#define A_CLR 0x7d
+#define A_BEL 0xfd
+#define A_DEL 0x9c
+
+/* plain ASCII characters */
+#define NL 0x0a
+#define CR 0x0d
+#define TAB 0x09
+
+/* TODO: move these to an external file or otherwise come up with a way
+ to reuse the memory */
+#define SERVER_LIST_LEN 8
+static char *servers[][2] = {
+ /*
+ { "82.165.139.95", "irc.tobug.net (US)" },
+ { "63.243.153.235", "irc.carterroadband.com (US)" },
+ { "209.133.9.109", "ircd.eyearesee.org (US)" },
+ { "89.238.135.210", "london.eyearesee.org (EU)" },
+ { "193.23.141.104", "hungary.eyearesee.org (EU)" },
+ */
+ { "na.newnet.net", "NewNet (North America)" },
+ { "eu.newnet.net", "NewNet (Europe)" },
+ { "us.undernet.org", "Undernet (US)" },
+ { "eu.undernet.org", "Undernet (Europe)" },
+ { "irc.freenode.org", "FreeNode" },
+ { "kubrick.freenode.net", "FreeNode (US)" },
+ { "irc.efnet.org", "Eris Free Net" },
+ { "82.165.139.95", "irc.tobug.net (NewNet, US)" },
+};
+
+/* uIP API stuff */
+struct timer nick_reg_timer; /* ../uip/timer.h */
+struct timer vbell_timer;
+struct telnet_state *tstate; /* ../apps/telnet.h */
+
+/*---------------------------------------------------------------------------*/
+int main(void) {
+ char c;
+ int i;
+ uip_ipaddr_t ipaddr;
+ struct timer periodic_timer;
+ char cmdbuf[HOSTLEN+1];
+
+ c = get_ostype() & AT_OS_TYPE_MAIN;
+ if(c == AT_OS_400800) {
+ strcpy(os_version, "800");
+ } else if(c == AT_OS_1200XL) {
+ strcpy(os_version, "1200XL");
+ }
+
+ cursor(1); /* don't let conio hide the cursor */
+
+ /* set screen colors to white-on-black initially. They may be
+ reset by the user's config file, once it's loaded */
+ POKE(710, 0);
+ POKE(709, 12);
+
+ putchar(A_CLR);
+ puts(BANNER);
+ putchar('\n');
+
+ get_config();
+
+ while(1) {
+ done = 0;
+ rs232dev_close();
+
+ POKE(710, config.bg_color);
+ POKE(709, config.fg_color);
+
+ printf("Server name/IP, [C]onfig, or e[X]it\n");
+ printf("[%s]: ", config.server);
+ fflush(stdout);
+ get_line(cmdbuf, HOSTLEN);
+
+ if(strcasecmp(cmdbuf, "x") == 0) {
+ exit(0);
+ } else if(strcasecmp(cmdbuf, "c") == 0) {
+ config_menu();
+ continue;
+ } else if(*cmdbuf) {
+ strcpy(config.server, cmdbuf);
+ }
+ /* else, use the existing config.server */
+
+ timer_set(&periodic_timer, CLOCK_SECOND / 2);
+
+ rs232dev_init(config.baud);
+ uip_init();
+
+ uip_sethostaddr(config.local_ip);
+ uip_setdraddr(config.peer_ip);
+
+ /* can I use 255.255.255.252 here? Does it matter? */
+ uip_ipaddr(ipaddr, 255,255,255,0);
+ uip_setnetmask(ipaddr);
+
+ if(uiplib_ipaddrconv(config.server, (unsigned char*)&ipaddr)) {
+ (void)uip_connect(&ipaddr, htons(config.server_port));
+ } else {
+ resolv_init();
+ resolv_conf(config.resolver_ip);
+ resolv_query(config.server);
+ }
+
+ while(!done) {
+ /* This part of the while loop is straight from the no-ARP example
+ code, from the uIP docs. */
+ uip_len = rs232dev_poll();
+ if(uip_len > 0) {
+ uip_input();
+ /* If the above function invocation resulted in data that
+ should be sent out on the network, the global variable
+ uip_len is set to a value > 0. */
+ if(uip_len > 0) {
+ rs232dev_send();
+ }
+ } else if(timer_expired(&periodic_timer)) {
+ timer_reset(&periodic_timer);
+ for(i = 0; i < UIP_CONNS; i++) {
+ uip_periodic(i);
+ /* If the above function invocation resulted in data that
+ should be sent out on the network, the global variable
+ uip_len is set to a value > 0. */
+ if(uip_len > 0) {
+ rs232dev_send();
+ }
+ }
+
+#if UIP_UDP
+ for(i = 0; i < UIP_UDP_CONNS; i++) {
+ uip_udp_periodic(i);
+ /* If the above function invocation resulted in data that
+ should be sent out on the network, the global variable
+ uip_len is set to a value > 0. */
+ if(uip_len > 0) {
+ rs232dev_send();
+ }
+ }
+#endif /* UIP_UDP */
+ }
+
+ if(vbell_active && timer_expired(&vbell_timer)) {
+ POKE(710, config.bg_color);
+ vbell_active = 0;
+ }
+
+ /* Call the keyboard handler if the user pressed a key. Note that
+ we're using stdio for printing, but conio for reading, which
+ works on the Atari but may not work on all other cc65 platforms */
+ if(kbhit()) {
+ handle_keystroke();
+ }
+
+ /* Automatically register the nick and userhost after being
+ connected for a couple seconds. The parameters for the USER
+ command are ignored by the server (at least the NewNet servers) */
+ if(connected && !nick_registered && timer_expired(&nick_reg_timer)) {
+ puts("Registering nick");
+ sprintf(input_buf, "NICK %s%cUSER %s %s %s :%s%c",
+ config.nick, NL, config.nick, SELF,
+ config.server, config.real_name, NL);
+ telnet_send(tstate, input_buf, strlen(input_buf));
+ input_buf_len = 0;
+ nick_registered = 1;
+ /* TODO: check for failure registering the nick */
+ }
+
+ /*
+ if(PEEK(53279) == 6) { // START pressed
+ puts("Disconnecting");
+ uip_close();
+ // done = 1;
+ }
+ */
+ }
+
+ connected = nick_registered = joined_channel = 0;
+ }
+ return 0;
+}
+
+static void bell() {
+ if(config.ui_flags & UIFLAG_NOBELL)
+ return;
+
+ if(config.ui_flags & UIFLAG_VBELL) {
+ vbell_active = 1;
+ timer_set(&vbell_timer, CLOCK_SECOND / 10);
+ POKE(710, config.bg_color + 8);
+ } else {
+ putchar(A_BEL);
+ }
+}
+
+/* The err_* functions will probably support "visual bell" (screen flashing)
+ as an option one day. */
+static void err_missing_arg(void) {
+ puts("Command requires argument");
+ bell();
+}
+
+static void err_no_channel(void) {
+ puts("You are not in a channel (use /join #channel)");
+ bell();
+}
+
+static void err_already_joined(void) {
+ puts("You are already in a channel (use /part to leave)");
+ bell();
+}
+
+static void del_last_word(void) {
+ int old = input_buf_len, bs = 0;
+
+ while(input_buf_len && input_buf[input_buf_len] == ' ') {
+ ++bs;
+ input_buf_len--;
+ }
+
+ while(input_buf_len && input_buf[input_buf_len] != ' ') {
+ ++bs;
+ input_buf_len--;
+ }
+
+ if(old > 120 && input_buf_len <= 120) {
+ putchar(0x1c);
+ putchar(A_DEL);
+ putchar(A_DEL);
+ redraw_user_buffer();
+ } else do {
+ putchar(A_BS);
+ } while(--bs);
+}
+
+/* Keyboard handler. For now, the keyboard macros are hard-coded. */
+static void handle_keystroke(void) {
+ char i, c, send_buf = 0;
+
+ /* TODO:
+ ctrl-7 = ` (warning: cgetc() can't read this)
+ ctrl-, = {
+ ctrl-. = }
+ ctrl-; = ~ (don't do ctrl-^, that's left-arrow!)
+
+ Ignore inverse-video key, ATASCII graphics, unwanted
+ cursor actions, make caps-lock stop freezing the program.
+ To do this right, we have to examine location 764 for some
+ of these, and don't call cgetc() at all... or actually,
+ stuff a valid keycode there, then call cgetc() to make a
+ keyclick noise (but ignore its return value)
+
+ Make Break act like delete-line
+
+ */
+ c = cgetc();
+
+ /* Keyboard macros, only allowed at the start of a new line */
+ if(input_buf_len == 0) {
+ switch(c) {
+ case 0x0e: /* ctrl-N */
+ if(joined_channel) send_server_cmd("NAMES", channel);
+ return;
+
+ case 0x17: /* ctrl-W */
+ if(joined_channel) send_server_cmd("WHO", channel);
+ return;
+
+ case A_EOL:
+ return; /* ignore Return on a line by itself */
+
+ case A_TAB:
+ if(last_msg_nick[0]) {
+ sprintf(input_buf, "/msg %s ", last_msg_nick);
+ input_buf_len = strlen(input_buf);
+ for(i=0; i<input_buf_len; i++)
+ putchar(input_buf[i] | 0x80);
+ }
+ return;
+
+ default:
+ break;
+ }
+ }
+
+ /* Editing keys */
+ /* TODO: more editing keys. At minimum:
+ left/right arrows
+ ^W = delete last word
+ ^U = kill to start of line
+ ^K = kill to end of line
+ ^A = goto start of line
+ ^E = goto end of line
+ ^L = redraw input buffer
+ */
+ if(c == A_BS) { /* backspace */
+ if(input_buf_len > 0) {
+ input_buf_len--;
+ putchar(c);
+ } else {
+ bell();
+ }
+
+ return;
+ } else if(c == A_DEL || c == 0x15) {
+ /* shift-backspace or ^U (delete line) */
+ input_buf_len = 0;
+ putchar(A_DEL);
+ return;
+ } else if(c == 0x17) {
+ /* ^W (delete word) */
+ del_last_word();
+ return;
+ }
+
+ /* Echo keystroke */
+ putchar(c | 0x80); /* inverse video for now */
+
+ if(c == A_EOL) {
+ c = NL;
+ send_buf = 1;
+ } else if(c == A_TAB) {
+ c = TAB;
+ }
+
+ /* Store keystroke in input buffer */
+ input_buf[input_buf_len++] = c;
+
+ /* If line too long, ring the "margin" bell */
+ if(input_buf_len > BUF_SIZE - 1)
+ if(!send_buf) {
+ bell();
+ putchar(A_BS);
+ input_buf_len--;
+ }
+
+ /* If we've got a complete line of input and user has pressed Return,
+ send it to the server */
+ if(send_buf) {
+ input_buf[input_buf_len] = '\0';
+
+ if(*input_buf == '/') {
+ handle_command();
+ } else if(joined_channel) {
+ sprintf(chan_msg_buf, "PRIVMSG %s :%s", channel, input_buf);
+ telnet_send(tstate, chan_msg_buf, strlen(chan_msg_buf));
+ } else {
+ err_no_channel();
+ }
+
+ input_buf_len = 0;
+ }
+}
+
+static void send_server_cmd(char *cmd, char *arg) {
+ if(arg) {
+ sprintf(chan_msg_buf, "%s %s%c", cmd, arg, NL);
+ } else {
+ sprintf(chan_msg_buf, "%s%c", cmd, NL);
+ }
+
+ telnet_send(tstate, chan_msg_buf, strlen(chan_msg_buf));
+}
+
+static void send_ctcp_version(char *arg) {
+ sprintf(chan_msg_buf, "PRIVMSG %s %cVERSION%c%c",
+ arg, 1, 1, NL);
+ telnet_send(tstate, chan_msg_buf, strlen(chan_msg_buf));
+}
+
+static void send_ctcp_ping(char *arg) {
+ sprintf(chan_msg_buf, "PRIVMSG %s %cPING %c%c",
+ arg, 1, 1, NL);
+ telnet_send(tstate, chan_msg_buf, strlen(chan_msg_buf));
+}
+
+static void do_me(char *arg) { /* Do me, baby! */
+ sprintf(chan_msg_buf, "PRIVMSG %s :%cACTION %s%c%c",
+ channel, 1, arg, 1, NL);
+ telnet_send(tstate, chan_msg_buf, strlen(chan_msg_buf));
+}
+
+static void handle_command(void) {
+ char *cmd = input_buf + 1, *cend;
+ char *arg = NULL, *p = cmd;
+
+ /* convert command word to uppercase */
+ while((*p != NL) && (*p != ' ')) {
+ *p = toupper(*p);
+ ++p;
+ }
+
+ cend = p;
+
+ /* set arg pointer, nul-terminate arg, if present */
+ /* (otherwise, arg remains NULL) */
+ if(*p != NL) {
+ arg = p;
+ /* skip extra whitespace */
+ while(*arg == ' ')
+ ++arg;
+ p = arg + 1;
+ while(*p && (*p != NL))
+ ++p;
+ *p = '\0';
+ }
+
+ /* nul-terminate cmd */
+ *cend = '\0';
+
+ /* See if it's a command that needs client-side help */
+ if(strcmp(cmd, "ME") == 0) {
+ if(!joined_channel)
+ err_no_channel();
+ else if(!arg)
+ err_missing_arg();
+ else
+ do_me(arg);
+ } else if(strcmp(cmd, "MSG") == 0 || strcmp(cmd, "M") == 0) {
+ if(!arg)
+ err_missing_arg();
+ else
+ send_server_cmd("PRIVMSG", arg);
+ } else if(strcmp(cmd, "JOIN") == 0 || strcmp(cmd, "J") == 0) {
+ if(joined_channel) {
+ err_already_joined();
+ } else {
+ joined_channel = 1;
+ strcpy(channel, arg);
+ send_server_cmd("JOIN", arg);
+ }
+ } else if(strcmp(cmd, "PART") == 0) {
+ if(!joined_channel) {
+ err_no_channel();
+ } else {
+ joined_channel = 0;
+ send_server_cmd("PART", channel);
+ }
+ } else if(strcmp(cmd, "VERSION") == 0 || strcmp(cmd, "VER") == 0) {
+ if(!arg)
+ err_missing_arg();
+ else
+ send_ctcp_version(arg);
+ } else if(strcmp(cmd, "PING") == 0) {
+ if(!arg)
+ err_missing_arg();
+ else
+ send_ctcp_ping(arg);
+ } else if(strcmp(cmd, "QUOTE") == 0) {
+ if(!arg)
+ err_missing_arg();
+ else
+ send_server_cmd(arg, NULL);
+ } else {
+ /* Anything we don't recognize as a client command, we pass
+ directly to the server. */
+ send_server_cmd(cmd, arg);
+ }
+}
+
+/* The telnet_* functions are uIP application callbacks. */
+void telnet_connected(struct telnet_state *s) {
+ /* puts("Connected to host, press START to disconnect"); */
+ puts("Connected to server");
+ tstate = s;
+ s->text = NULL;
+ s->textlen = 0;
+ timer_set(&nick_reg_timer, CLOCK_SECOND);
+ connected = 1;
+}
+
+void telnet_closed(struct telnet_state *s) {
+ puts("Connection closed");
+ uip_close();
+ done = 1;
+}
+
+void telnet_sent(struct telnet_state *s) {
+}
+
+void telnet_aborted(struct telnet_state *s) {
+ puts("Connection aborted");
+ uip_abort();
+ done = 1;
+}
+
+void telnet_timedout(struct telnet_state *s) {
+ puts("Connection timed out");
+ uip_abort();
+ done = 1;
+}
+
+void do_pong() {
+ char *p = chan_msg_buf;
+
+ memcpy(chan_msg_buf, output_buf, output_buf_len);
+ chan_msg_buf[1] = 'O';
+ while(*p) {
+ if(*p == A_EOL) *p = NL;
+ p++;
+ }
+
+ telnet_send(tstate, chan_msg_buf, output_buf_len);
+ if(config.ui_flags & UIFLAG_SHOWPING)
+ puts("[PING,PONG]");
+}
+
+/* Handler for text received from the server, responsible for
+ formatting. TODO: part/join/quit aren't handled correctly. */
+void do_msg() {
+ char *nick = output_buf, *cmd = output_buf, *chan = NULL, *msg = NULL;
+ char *bang = NULL;
+
+ while(*cmd != ' ') {
+ if(*cmd == '!') {
+ bang = cmd;
+ }
+ ++cmd;
+ }
+
+ /* no ! in nick means a server message or something, just print as-is */
+ if(!bang) {
+ fputs(output_buf, stdout);
+ fflush(stdout);
+ return;
+ }
+
+ *cmd = '\0';
+ ++cmd;
+ chan = cmd;
+
+ while(*chan != ' ')
+ ++chan;
+ *chan = '\0';
+ ++chan;
+ msg = chan;
+
+ if(*msg != A_EOL) {
+ while(*msg && *msg != ' ')
+ ++msg;
+ if(*msg) {
+ *msg = '\0';
+ ++msg;
+ if(*msg == ':') ++msg;
+ }
+ }
+
+ /* FIXME: This stuff is hairy, unmaintainable, and probably just wrong
+ (works OK with the 2 or 3 NewNet servers I test with, not tried
+ others). It's the result of too much coffee, and needs to be
+ redesigned. Heck, it needs to be designed in the first place! */
+ if(strcmp(cmd, "PRIVMSG") == 0) {
+ nick[0] = '<';
+ bang[0] = '>';
+ bang[1] = '\0';
+ if(strcasecmp(chan, config.nick) != 0) {
+ // privmsg, not to our nick, must be channel text
+ if(memcmp(msg, "\x01" "ACTION ", 8) == 0) {
+ nick++;
+ *bang = '\0';
+ output_buf[output_buf_len - 2] = A_EOL;
+ output_buf[output_buf_len - 1] = '\0';
+ printf("* %s %s", nick, msg + 8);
+ } else {
+ printf("%s %s", nick, msg);
+ }
+ } else {
+ // privmsg, is to our nick
+ if(memcmp(msg, "\x01" "PING ", 6) == 0) {
+ nick++;
+ *bang = '\0';
+ output_buf[output_buf_len - 2] = '\0';
+ sprintf(chan_msg_buf, "NOTICE %s :\x01PING %s\x01%c",
+ nick, msg + 6, 0x0a);
+ telnet_send(tstate, chan_msg_buf, strlen(chan_msg_buf));
+ printf("* CTCP PING from %s\n", nick);
+ } else if(memcmp(msg, "\x01" "VERSION\x01", 9) == 0) {
+ nick++;
+ *bang = '\0';
+ sprintf(chan_msg_buf, "NOTICE %s :\x01VERSION "
+ VERSION_REPLY " - running on "
+ "an Atari %s\x01%c",
+ nick, os_version, 0x0a);
+ telnet_send(tstate, chan_msg_buf, strlen(chan_msg_buf));
+ printf("* CTCP VERSION from %s\n", nick);
+ } else {
+ printf("MSG: %s %s", nick, msg);
+ if(config.ui_flags & UIFLAG_MSGBELL)
+ bell();
+ *bang = '\0';
+ strcpy(last_msg_nick, nick + 1);
+ }
+ }
+ } else {
+ if(*msg) {
+ printf("%s %s %s %s", nick, cmd, chan, msg);
+ } else {
+ printf("%s %s %s", nick, cmd, chan);
+ }
+ }
+
+ fflush(stdout);
+}
+
+void del_user_buffer() {
+ /* delete user edit buffer */
+ if(input_buf_len) {
+ putchar(A_DEL);
+ if(input_buf_len > 119) {
+ putchar(0x1c); /* up arrow */
+ putchar(A_DEL);
+ }
+ }
+}
+
+void redraw_user_buffer() {
+ int tlen;
+ static char redraw_buf[BUF_SIZE];
+ /* reprint user edit buffer */
+ if(input_buf_len) {
+ tlen = input_buf_len - 1;
+ do {
+ redraw_buf[tlen] = input_buf[tlen] | 0x80;
+ } while(tlen--);
+ redraw_buf[input_buf_len] = '\0';
+ fputs(redraw_buf, stdout);
+ fflush(stdout);
+ }
+}
+
+/* Another uIP app callback. This decides whether or not we've received
+ a complete message from the server (which may be split into multiple
+ packets, and may end in the middle of a packet) */
+void telnet_newdata(struct telnet_state *s, char *data, u16_t len) {
+ u16_t tlen = len;
+ char c, *t = data, buf_done = 0;
+
+ while(tlen-- != 0) {
+ c = *t++;
+ if(c == NL) { // swallow NL
+ continue;
+ } else if(c == CR) { // CR => EOL
+ c = A_EOL;
+ buf_done = 1;
+ } else if(c == TAB) { // tab
+ c = A_TAB;
+ } else if(c == '{') {
+ c = '[' | 0x80;
+ } else if(c == '}') {
+ c = ']' | 0x80;
+ } else if(c == '~') {
+ c = '^' | 0x80;
+ } else if(c == 0x60) { // backtick
+ c = 0xa7; // inverse quote
+ }
+
+ output_buf[output_buf_len++] = c;
+ if(output_buf_len >= OUTBUF_SIZE - 1) {
+ puts("[buffer overflow]\xfd");
+ buf_done = 1;
+ break;
+ }
+
+ if(buf_done) {
+ del_user_buffer();
+ output_buf[output_buf_len] = '\0';
+
+ if(output_buf_len > 4 && (memcmp(output_buf, "PING", 4) == 0)) {
+ do_pong();
+ } else if(output_buf[0] == ':') {
+ do_msg();
+ } else {
+ fputs(output_buf, stdout);
+ fflush(stdout);
+ }
+
+ redraw_user_buffer();
+ output_buf_len = 0;
+ buf_done = 0;
+ }
+ }
+}
+
+/* Load config file, offer the user a chance to change the config */
+static void get_config(void) {
+ // char filename[20];
+ FILE *f = fopen(DEFAULT_CONF_FILE, "rb");
+
+ puts("Loading config from " DEFAULT_CONF_FILE);
+
+ if(f) {
+ config_valid =
+ fread(&config, 1, sizeof(fuji_conf_t), f) == sizeof(fuji_conf_t);
+ fclose(f);
+ if(!config_valid)
+ puts("Config file is wrong size");
+ } else {
+ puts("No config file found");
+ }
+
+ if(config_valid) {
+ if(memcmp(config.signature, CONF_SIGNATURE, 2) != 0) {
+ puts("Not a valid config file");
+ config_valid = 0;
+ } else if(config.version != CONF_VERSION) {
+ puts("Config is for the wrong version of FujiChat, ignoring");
+ config_valid = 0;
+ } else {
+ puts("Loaded OK");
+ /*
+ printf("Loaded OK. Use defaults [Y/n]? ");
+ fflush(stdout);
+ fgets(input_buf, 10, stdin);
+ if(*input_buf == 'N' || *input_buf == 'n')
+ config_menu();
+ */
+ }
+ }
+
+ if(!config_valid)
+ config_menu();
+}
+
+static void save_config(void) {
+ FILE *f = fopen(DEFAULT_CONF_FILE, "wb");
+ if(f) {
+ fwrite(&config, sizeof(fuji_conf_t), 1, f);
+ fclose(f);
+ puts("Config saved to " DEFAULT_CONF_FILE);
+ }
+}
+
+static void get_conf_color(char *name, char *color, char dflt) {
+ char buf[5];
+
+ printf("%s color [%d]: ", name, dflt);
+ fgets(buf, 5, stdin);
+
+ if(!(*buf >= '0' && *buf <= '9'))
+ *color = dflt;
+ else
+ *color = atoi(buf);
+}
+
+static void get_line(char *buf, unsigned char len) {
+ fgets(buf, len, stdin);
+ while(*buf) {
+ if(*buf == '\n')
+ *buf = '\0';
+ ++buf;
+ }
+}
+
+static char get_yesno(char *prompt, char dflt) {
+ char buf[5];
+
+ printf("%s [%c/%c]: ",
+ prompt,
+ (dflt ? 'Y' : 'y'),
+ (dflt ? 'n' : 'N'));
+
+ fflush(stdout);
+ get_line(buf, 4);
+ switch(*buf) {
+ case 'y':
+ case 'Y':
+ return 1;
+
+ case 'n':
+ case 'N':
+ return 0;
+
+ default:
+ return dflt;
+ }
+}
+
+static void get_ip_addr(char *prompt, char *dflt, uip_ipaddr_t *addr) {
+ char ok;
+ char buf[HOSTLEN+1];
+
+ do {
+ printf("%s IP address [%s]: ", prompt, dflt);
+ fflush(stdout);
+ get_line(buf, HOSTLEN);
+ if(!*buf) strcpy(buf, dflt);
+ ok = uiplib_ipaddrconv(buf, (unsigned char*)addr);
+ if(!ok) bell();
+ } while(!ok);
+}
+
+static char *format_ip(uip_ipaddr_t *ip) {
+ static char buf[20];
+ u16_t *ipaddr = (u16_t *)ip;
+ sprintf(buf, "%d.%d.%d.%d",
+ htons(ipaddr[0]) >> 8,
+ htons(ipaddr[0]) & 0xff,
+ htons(ipaddr[1]) >> 8,
+ htons(ipaddr[1]) & 0xff);
+ return buf;
+}
+
+void set_default_config(void) {
+ uip_ipaddr(&(config.local_ip), 192,168,0,2);
+ uip_ipaddr(&(config.peer_ip), 192,168,0,1);
+ uip_ipaddr(&(config.resolver_ip), 192,168,0,1);
+ strcpy(config.server, servers[0][0]);
+ strcpy(config.nick, DEFAULT_NICK);
+ strcpy(config.real_name, "FujiChat User");
+ config.server_port = 6667;
+ config.ui_flags = 0;
+ config.bg_color = 0xc0; /* dark green */
+ config.fg_color = 0x0c;
+ config.baud = RS_BAUD_4800;
+
+ config_valid = 1;
+}
+
+int baud_values[] = { 1200, 2400, 4800, 9600 };
+char baud_bytes[] = { RS_BAUD_1200, RS_BAUD_2400, RS_BAUD_4800, RS_BAUD_9600 };
+char max_baud = sizeof(baud_bytes);
+
+static void get_baudrate(void) {
+ char i, buf[5];
+
+ for(i=0; i<max_baud; ++i)
+ if(config.baud == baud_bytes[i])
+ printf("[%d]=%d ", i+1, baud_values[i]);
+ else
+ printf("%d=%d ", i+1, baud_values[i]);
+
+ fputs("Baud rate: ", stdout);
+ fflush(stdout);
+
+ do {
+ get_line(buf, 4);
+ if(!*buf)
+ return;
+
+ i = atoi(buf);
+ } while (i < 1 || i > max_baud);
+ config.baud = baud_bytes[--i];
+}
+
+static void config_menu(void) {
+ char i, buf[HOSTLEN+1], ok = 0;
+ unsigned int new_value;
+
+ strcpy(config.signature, CONF_SIGNATURE);
+ config.version = CONF_VERSION;
+
+ if(!config_valid)
+ set_default_config();
+
+ do {
+ get_baudrate();
+ get_ip_addr("Local", format_ip(&(config.local_ip)), &(config.local_ip));
+ get_ip_addr("Peer", format_ip(&(config.peer_ip)), &(config.peer_ip));
+ get_ip_addr("DNS Server", format_ip(&(config.resolver_ip)), &(config.resolver_ip));
+
+ puts("Server list:");
+ for(i=0; i<SERVER_LIST_LEN; ++i) {
+ printf("%d: %s\n %s\n",
+ i + 1,
+ servers[i][0],
+ servers[i][1]);
+ }
+
+ printf("\nEnter # or any server host/IP [%s]: ", config.server);
+ fflush(stdout);
+ fgets(buf, HOSTLEN, stdin);
+
+ if(buf[0] == '\n') {
+ buf[0] = '1';
+ buf[1] = '\n';
+ }
+
+ if(buf[0] >= '1' && buf[0] <= (SERVER_LIST_LEN + '0') && buf[1] == '\n') {
+ strcpy(buf, servers[buf[0] - '1'][0]);
+ }
+
+ for(i=0; buf[i] && (buf[i] != '\n'); ++i)
+ ;
+
+ buf[i] = '\0';
+ strcpy(config.server, buf);
+
+ printf("Server port [%d]: ", config.server_port);
+ get_line(buf, 10);
+ new_value = atoi(buf);
+ if(new_value) config.server_port = new_value;
+
+ printf("Your nickname [%s]: ", config.nick);
+ get_line(buf, NICKLEN);
+ if(*buf) strcpy(config.nick, buf);
+
+ printf("Your 'real' name [%s]: ", config.real_name);
+ get_line(buf, NICKLEN);
+ if(*buf) strcpy(config.real_name, buf);
+
+ // if(!*(config.nick)) strcpy(config.nick, DEFAULT_NICK);
+ /* TODO: scan for invalid chars */
+
+ get_conf_color("Background", &(config.bg_color), config.bg_color);
+ get_conf_color("Foreground", &(config.fg_color), config.fg_color);
+
+ new_value =
+ (get_yesno("Disable bell", config.ui_flags & UIFLAG_NOBELL) ? UIFLAG_NOBELL : 0);
+
+ if(!(config.ui_flags & UIFLAG_NOBELL)) {
+ new_value |=
+ (get_yesno("Visual bell", config.ui_flags & UIFLAG_VBELL) ? UIFLAG_VBELL : 0);
+
+ new_value |=
+ (get_yesno("Bell on msg", config.ui_flags & UIFLAG_MSGBELL) ? UIFLAG_MSGBELL : 0);
+ };
+
+ new_value |=
+ (get_yesno("Show ping/pong", config.ui_flags & UIFLAG_SHOWPING) ? UIFLAG_SHOWPING : 0);
+
+ config.ui_flags = new_value;
+
+ ok = get_yesno("Is this correct", 1);
+ } while(!ok);
+
+ if(get_yesno("Save this config", 1))
+ save_config();
+}
+
+/*---------------------------------------------------------------------------*/
+
+/* uIP app callback for the resolver */
+void resolv_found(char *name, u16_t *ipaddr) {
+ if(ipaddr == NULL) {
+ printf("Host '%s' not found.\n", name);
+ done = 1;
+ } else {
+ printf("Found name '%s' = %d.%d.%d.%d\n", name,
+ htons(ipaddr[0]) >> 8,
+ htons(ipaddr[0]) & 0xff,
+ htons(ipaddr[1]) >> 8,
+ htons(ipaddr[1]) & 0xff);
+ if(!connected)
+ (void)uip_connect((uip_ipaddr_t *)ipaddr, htons(config.server_port));
+ }
+}
diff --git a/src/makeauto.c b/src/makeauto.c
new file mode 100644
index 0000000..6e8ff71
--- /dev/null
+++ b/src/makeauto.c
@@ -0,0 +1,177 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "fujichat.h"
+#include "common.h"
+#include "features.h"
+
+#define DRIVER_LIST_LEN (sizeof(rs232_drivers) / sizeof(rs232_drivers[0]))
+static char *rs232_drivers[][2] = {
+ { NULL, "(No driver; manual setup)" },
+ { "D:BOBVERT.SER", "SIO2PC or R:Verter" },
+ { "D:ATARI850.SER", "Atari 850" },
+ { "D:PRCONN.SER", "P:R: Connection" },
+};
+
+/* APPEND_BUF_SIZE should be >= the size of the largest .SER file */
+#define APPEND_BUF_SIZE 2048
+
+void reboot(void) {
+ asm("jmp $e477");
+}
+
+static char get_yesno(char *prompt, char dflt) {
+ char buf[5];
+
+ printf("%s [%c/%c]: ",
+ prompt,
+ (dflt ? 'Y' : 'y'),
+ (dflt ? 'n' : 'N'));
+
+ fflush(stdout);
+ get_line(buf, 4);
+ switch(*buf) {
+ case 'y':
+ case 'Y':
+ return 1;
+
+ case 'n':
+ case 'N':
+ return 0;
+
+ default:
+ return dflt;
+ }
+}
+
+//char append_to(FILE *to, char *src) {
+// int bytes;
+// char ret;
+// static char buf[APPEND_BUF_SIZE];
+// FILE *from = fopen(src, "rb");
+//
+// printf("append_to: %s\n", src);
+//
+// if(!from) {
+// perror(src);
+// return 0;
+// }
+//
+// while( (bytes = fread(buf, 1, APPEND_BUF_SIZE, from)) ) {
+// printf("%d bytes in, eof? %d\n", bytes, feof(from));
+// bytes = fwrite(buf, 1, bytes, to);
+// printf("%d bytes out\n", bytes);
+// }
+//
+// ret = feof(from); /* 1 = no error */
+// fclose(from);
+//
+// return ret;
+//}
+
+char append_to(FILE *to, char *src) {
+ int bytes = 0, c;
+ char ret;
+ // static char buf[APPEND_BUF_SIZE];
+ FILE *from = fopen(src, "rb");
+
+ printf("append_to: %s\n", src);
+
+ if(!from) {
+ perror(src);
+ return 0;
+ }
+
+ /* painfully slow, sorry! TODO: figure out why fread() returns
+ extra bytes after EOF (probably because the file doesn't
+ end on a sector boundary, or something equally lame) */
+ while( (c = fgetc(from)) != EOF ) {
+ fputc(c, to);
+ ++bytes;
+ }
+
+ ret = feof(from); /* 1 = no error */
+ fclose(from);
+
+ printf("bytes=%d, ret=%d\n", bytes, ret);
+ return ret;
+}
+
+char append_files(char *dst, char *src1, char *src2) {
+ char ret;
+ FILE *dfile = fopen(dst, "wb");
+
+ if(dfile) {
+ ret = (append_to(dfile, src1) && append_to(dfile, src2));
+ fclose(dfile);
+ return ret;
+ } else {
+ perror(dst);
+ return 0;
+ }
+}
+
+static void rs232_driver_menu() {
+ static char buf[256];
+ int i;
+
+ puts("Select your serial port type\n");
+ for(i=0; i<DRIVER_LIST_LEN; ++i) {
+ printf("%d: %s\n",
+ i + 1,
+ rs232_drivers[i][1]);
+ }
+
+ puts("\nEnter number from list, or the\ndriver filename if not listed.");
+ fputs("[2]: ", stdout);
+ fflush(stdout);
+
+ do {
+ i = 0;
+ get_line(buf, 255);
+
+ if(!*buf) *buf = '2';
+
+ if(*buf == '1') {
+ return;
+ } else if(*buf >= '2' && *buf <= '9') {
+ i = *buf - '1';
+ if(i < DRIVER_LIST_LEN) {
+ strcpy(buf, rs232_drivers[i][0]);
+ i = 0;
+ } else {
+ putchar(A_BEL);
+ i = 1;
+ }
+ } /* else use whatever they entered as a filename */
+ } while(i);
+
+ // if(!rename("D:AUTORUN.SYS", "D:AUTORUN.BAK")) {
+ // puts("Renamed AUTORUN.SYS to AUTORUN.BAK");
+ // }
+
+ do {
+ printf("\nCreating AUTORUN.SYS from\n%s and LOADMENU.COM\n", buf);
+ i = !append_files("D:AUTORUN.SYS", buf, "D:LOADMENU.COM");
+ if(i) {
+ i = get_yesno("\xfdRetry", 1);
+ if(!i) {
+ puts("Failed to change driver");
+ return;
+ }
+ }
+ } while(i);
+
+ puts("You must reboot to use the new driver.");
+ if(get_yesno("Reboot now", 1))
+ reboot();
+
+ // rs232_already_loaded = scan_hatabs('R');
+}
+
+void main(int, char **) {
+ rs232_driver_menu();
+ exit(0);
+}
+
diff --git a/src/mkdisk.sh b/src/mkdisk.sh
new file mode 100644
index 0000000..5da6985
--- /dev/null
+++ b/src/mkdisk.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+set -e
+
+rm -rf disk
+mkdir disk
+cp dos_20s.atr disk/fujichat.atr
+cp uip fujichat.xex
+cp atari850.ser disk/atari850.ser
+cp bobvert.com disk/bobvert.ser
+cp prconn.ser disk/prconn.ser
+
+if [ -f about.txt ]; then
+ perl -pe 's/\n/\x9b/' < about.txt > disk/about.txt
+fi
+
+cd disk
+for i in about loadmenu fujimenu makeauto fujiconf fujichat; do
+ cat ../aexec.xex ../$i.xex > $i.com
+ axe -w $i.com fujichat.atr
+done
+
+#cat ../bobvert.com fujimenu.com > autorun.sys
+#cat fujimenu.com > autorun.sys
+
+cat ../aexec.xex ../loadmkau.xex > autorun.sys
+axe -w autorun.sys fujichat.atr
+
+axe -w atari850.ser fujichat.atr
+axe -w bobvert.ser fujichat.atr
+axe -w prconn.ser fujichat.atr
+
+if [ -f about.txt ]; then
+ axe -w about.txt fujichat.atr
+fi
+
+cp fujichat.atr ..
+
+# build my own test disk so I don't have to keep going thru the
+# serial port and config every time
+if [ "`whoami`" = "urchlay" ]; then
+ cat bobvert.ser loadmenu.com > autorun.sys
+ cp ../fujichat.cfg .
+ cp fujichat.atr fujitest.atr
+ axe -w autorun.sys fujitest.atr
+ axe -w fujichat.cfg fujitest.atr
+ mv fujitest.atr ..
+fi
diff --git a/src/mkfuji64.sh b/src/mkfuji64.sh
new file mode 100644
index 0000000..88ff391
--- /dev/null
+++ b/src/mkfuji64.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+cat bobvert.com col64.xex disk/fujichat.com > autorun.sys
+axe -w autorun.sys fuji80.atr
diff --git a/src/mkfuji80.sh b/src/mkfuji80.sh
new file mode 100644
index 0000000..c4b7e75
--- /dev/null
+++ b/src/mkfuji80.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+cat bobvert.com col80_modified/col80_hacked.xex disk/fujichat.com > autorun.sys
+axe -w autorun.sys fuji80.atr
diff --git a/src/new_format_ip.s b/src/new_format_ip.s
new file mode 100644
index 0000000..5fab2ba
--- /dev/null
+++ b/src/new_format_ip.s
@@ -0,0 +1,54 @@
+ .fopt compiler,"cc65 v 2.12.9"
+ .setcpu "6502"
+ .smart on
+ .autoimport on
+ .case on
+ .debuginfo off
+ .importzp sp, sreg, regsave, regbank, tmp1, ptr1, ptr2
+ .macpack longbranch
+ .export _new_format_ip
+
+ .segment "BSS"
+buf:
+ .res 20,$0
+
+ .segment "RODATA"
+fmt: .byte "%d.%d.%d.%d", 0
+
+; unsigned char* __fastcall__ format_ip (__near__ unsigned int[2]*)
+ .segment "CODE"
+_new_format_ip:
+ sta ptr1
+ stx ptr1+1
+
+ lda #<buf
+ ldx #>buf
+ jsr pushax
+
+ lda #<fmt
+ ldx #>fmt
+ jsr pushax
+
+ ldy #0
+ lda (ptr1),y
+ jsr pusha0
+
+ ldy #1
+ lda (ptr1),y
+ jsr pusha0
+
+ ldy #2
+ lda (ptr1),y
+ jsr pusha0
+
+ ldy #3
+ lda (ptr1),y
+ jsr pusha0
+
+ ldy #$0c
+ jsr _sprintf
+
+ lda #<buf
+ ldx #>buf
+
+ rts
diff --git a/src/notes.64x34 b/src/notes.64x34
new file mode 100644
index 0000000..e886760
--- /dev/null
+++ b/src/notes.64x34
@@ -0,0 +1,176 @@
+
+64x34 software text mode needs GR.8 style screen, at 320x204. This
+requires 8160 bytes for screen memory, plus (I think) 214 bytes
+for display list. The initial version will probably use the plain
+GR.8+16 display, and only support 32 rows.
+
+Character cells are 5x6, with glyphs being mostly 4x5 with a blank row
+at the bottom and blank column on the left. Probably for lowercase and
+capital M/m/W/w, I'll hard-code a bit of logic to copy the right-most
+bit into the normally-blank left-most column, so these characters will
+be fully-formed, though they'll touch the char to the left. Doing it
+this way allows packing one row of pixels from 2 different glyphs into
+each byte of glyph-definition table, like COL80 does.
+
+Depending on the design of the final font, it might also be that I can
+avoid storing the bottom row (a few characters might need it to be a
+copy of the top row, or I might get away with hard-coding zero). If
+I'm not storing the bottom row, each 2 glyphs will take up 5 bytes
+of table space (for a 128-character font, that's 320 bytes; for an
+ASCII-only 96-char font, only 240 bytes! That fits in one page, so
+I can simplify the routine that reads it). If I do store the bottom
+row, those numbers become 384 and 288 bytes, respectively. Later on
+if there's support for UTF-8 or whatever, it still might be better
+to use the 240-byte 96-char fonts, but allow for more than one of
+them.
+
+The renderer needs to be able to handle inverse video. It would also be
+nice to support underlining (just force the bottom row of each glyph to
+all 1's), but then there needs to be a way for the calling application
+to set underline mode. Also it might be hard to read... Theoretically
+it'd be possible to do italics too (shift the bottom few rows of pixels
+left), but I think it would come out too ugly to want to use.
+
+Writing a glyph to screen RAM involves a 2-byte buffer for each row of
+pixels. Extract 4-bit glyph data from glyph table, synthesize the 5th
+bit for MmWw, store in the 2-byte buffer (in top 5 bits), then calculate
+how many pixels to shift it, based on the cursor position. When actually
+writing to RAM, have to load the old data from each of the 2 bytes, mask
+off the appropriate bits, OR in the new bits, store back to RAM. This is
+kind of an expensive operation, but we're only doing it for 6 scanlines
+instead of 8 like COL80 uses, so maybe it'll be fast enough.
+
+If the right mask is $00, we don't have to touch the 2nd byte at all. The
+left mask will never be $00. (algorithm below does touch the 2nd byte though)
+
+leftbyte = int(COLCRS*5/8), easy enough to calculate, but table lookup
+will be faster. If we get tight on space, try it without the table.
+
+shift amounts will be stored in a table. Only 8 entries needed, lookup
+on COLCRS%8.
+
+; first, calculate or lookup the start address of the current
+; screen line, *SAVMSC + (*ROWCRS * 5), and store in rowptr
+; next, calculate or lookup the start address of the corrent
+; glyph, extract the relevant 4 bits (top or bottom nybble) and
+; store in glyphdata bits 2-6 (all other bits 0). Store 0 in glyphdata+1.
+; This is the body of the inner loop... rowptr needs to get 40 added to
+; it every time through the loop.
+ lda COLCRS
+ tax
+ lda left_byte_table,x
+ clc
+ adc rowptr
+ sta zptr
+ adc rowptr+1
+ sta zptr+1
+ ; (zptr) now points to left byte
+ ldy #0
+ lda (zptr),y
+ sta olddata
+ iny
+ lda (zptr),y
+ sta olddata+1
+ ; olddata holds the old screen RAM contents
+
+ lda #$07
+ sta mask
+ lda #$FF
+ sta mask+1
+
+ txa
+ and #$07 ; a%=8
+ tay
+ lda shift_amt_table,y
+ tay ; Y now holds the shift amount
+ beq no_shift
+
+shift_loop:
+ lsr glyphdata
+ ror glyphdata+1
+ sec
+ ror mask
+ ror mask+1
+ dey
+ bpl shift_loop
+
+ iny ; Y = 0
+no_shift:
+ lda olddata
+ and mask
+ ora glyphdata
+ sta (zptr),y
+ iny
+ lda olddata+1
+ and mask+1
+ ora glyphdata+1
+ sta (zptr),y
+
+To calculate screen bytes to alter... COLCRS ranges 0 to 63:
+
+COLCRS - leftbyte - shift amount - leftmask - rightmask
+0 0 0 $F8 $00
+1 0 5 $07 $C0
+2 1 2 $3E $00
+3 1 7 $01 $F0
+4 2 4 $0F $80
+5 3 1 $7C $00
+6 3 6 $03 $E0
+7 4 3 $1F $00
+8 5
+9 5
+10 6
+11 6
+12 7
+13 8
+14 8
+15 9
+16 10
+17 10
+18 11
+19 11
+20 12
+21 13
+22 13
+23 14
+24 15
+25 15
+26 16
+27 16
+28 17
+29 18
+30 18
+31 19
+32 20
+33 20
+34 21
+35 21
+36 22
+37 23
+38 23
+39 24
+40 25
+41 25
+42 26
+43 26
+44 27
+45 28
+46 28
+47 29
+48 30
+49 30
+50 31
+51 31
+52 32
+53 33
+54 33
+55 34
+56 35
+57 35
+58 36
+59 36
+60 37
+61 38
+62 38
+63 39
+
diff --git a/src/prconn.ser b/src/prconn.ser
new file mode 100644
index 0000000..8332d4e
--- /dev/null
+++ b/src/prconn.ser
Binary files differ
diff --git a/src/put.c b/src/put.c
new file mode 100644
index 0000000..7425fb3
--- /dev/null
+++ b/src/put.c
@@ -0,0 +1,12 @@
+
+void __fastcall__ fuji_putchar(char);
+
+void main(void) {
+ char msg[] = "Test\n";
+ char i;
+
+ for(i=0; i<5; ++i)
+ fuji_putchar(msg[i]);
+
+HANG: goto HANG;
+}
diff --git a/src/rs232dev.c b/src/rs232dev.c
new file mode 100644
index 0000000..9738fce
--- /dev/null
+++ b/src/rs232dev.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2001, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Adam Dunkels.
+ * 4. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: rs232dev.c,v 1.1 2001/11/20 20:49:45 adam Exp $
+ *
+ */
+
+/*
+ * This is a generic implementation of the SLIP protocol over an RS232
+ * (serial) device. While initially intented for the C64, the code can
+ * easily be ported to other platforms as well.
+ *
+ * Huge thanks to Ullrich von Bassewitz <uz@cc65.org> of cc65 fame for
+ * and endless supply of bugfixes, insightsful comments and
+ * suggestions, and improvements to this code!
+ */
+
+#include <rs232.h>
+#include <time.h>
+#include <string.h>
+
+ /* This will include the system specific header files as well */
+#if defined(__CBM__)
+# include <cbm.h>
+#elif defined(__ATARI__)
+# include <atari.h>
+#endif
+
+#include "uip.h"
+
+#include "features.h"
+
+#ifdef FEAT_KEYBOARD_BUFFER
+#include "keybuf.h"
+#endif
+
+#define SLIP_END 0300
+#define SLIP_ESC 0333
+#define SLIP_ESC_END 0334
+#define SLIP_ESC_ESC 0335
+
+
+#define SIO_RECV(c) while(rs232_get(&c) == RS_ERR_NO_DATA)
+#define SIO_POLL(c) (rs232_get(&c) != RS_ERR_NO_DATA)
+#define SIO_SEND(c) rs232_put(c)
+
+#define MAX_SIZE UIP_BUFSIZE
+
+static u8_t slip_buf[MAX_SIZE];
+
+#if MAX_SIZE > 255
+static u16_t len, tmplen;
+#else
+static u8_t len, tmplen;
+#endif /* MAX_SIZE > 255 */
+
+#if 0
+#define printf(x)
+#else
+#include <stdio.h>
+#endif
+
+#ifdef FEAT_TRAFFIC_INDICATOR
+#include <peekpoke.h>
+/* FujiChat screen stuff */
+static u16_t traffic_indicator;
+static char old_char;
+
+#define DOWN_ARROW 0xdd
+#define UP_ARROW 0xdc
+
+#endif
+
+/*-----------------------------------------------------------------------------------*/
+static void rs232_err(char err) {
+ switch(err) {
+ case RS_ERR_OK:
+ // printf("RS232 OK\n");
+ break;
+ case RS_ERR_NOT_INITIALIZED:
+ printf("RS232 not initialized\n");
+ break;
+ case RS_ERR_BAUD_TOO_FAST:
+ printf("RS232 baud too fast\n");
+ break;
+ case RS_ERR_BAUD_NOT_AVAIL:
+ printf("RS232 baud rate not available\n");
+ break;
+ case RS_ERR_NO_DATA:
+ printf("RS232 nothing to read\n");
+ break;
+ case RS_ERR_OVERFLOW:
+ printf("RS232 overflow\n");
+ break;
+ }
+}
+
+/*-----------------------------------------------------------------------------------*/
+/*
+ * rs232dev_send():
+ *
+ * Sends the packet in the uip_buf and uip_appdata buffers. The first
+ * 40 bytes of the packet (the IP and TCP headers) are read from the
+ * uip_buf buffer, and the following bytes (the application data) are
+ * read from the uip_appdata buffer.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+
+void rs232dev_send(void) {
+#if MAX_SIZE > 255
+ u16_t i;
+#else
+ u8_t i;
+#endif /* MAX_SIZE > 255 */
+ volatile u8_t *ptr;
+ u8_t c;
+
+#ifdef FEAT_TRAFFIC_INDICATOR
+ old_char = PEEK(traffic_indicator);
+ POKE(traffic_indicator, UP_ARROW);
+#endif
+
+ SIO_SEND(SLIP_END);
+
+ ptr = uip_buf;
+ for(i = 0; i < uip_len; ++i) {
+ if(i == 40) {
+ ptr = uip_appdata;
+ }
+ c = *ptr++;
+ switch(c) {
+ case SLIP_END:
+ SIO_SEND(SLIP_ESC);
+ SIO_SEND(SLIP_ESC_END);
+ break;
+ case SLIP_ESC:
+ SIO_SEND(SLIP_ESC);
+ SIO_SEND(SLIP_ESC_ESC);
+ break;
+ default:
+ SIO_SEND(c);
+ break;
+ }
+#ifdef FEAT_KEYBOARD_BUFFER
+ keybuf_poll_kbd();
+#endif
+ }
+ SIO_SEND(SLIP_END);
+
+#ifdef FEAT_TRAFFIC_INDICATOR
+ POKE(traffic_indicator, old_char);
+#endif
+}
+
+/*-----------------------------------------------------------------------------------*/
+/*
+ * rs232dev_poll():
+ *
+ * Read all avaliable bytes from the RS232 interface into the slip_buf
+ * buffer. If no more bytes are avaliable, it returns with 0 to
+ * indicate that no packet was immediately ready. When a full packet
+ * has been read into the buffer, the packet is copied into the
+ * uip_buf buffer and the length of the packet is returned.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+
+#if MAX_SIZE > 255
+u16_t
+#else
+u8_t
+#endif /* MAX_SIZE > 255 */
+rs232dev_poll(void) {
+ u8_t c;
+ static u8_t lastc;
+
+#ifdef FEAT_TRAFFIC_INDICATOR
+ old_char = PEEK(traffic_indicator);
+#endif
+
+ while(SIO_POLL(c)) {
+#ifdef FEAT_TRAFFIC_INDICATOR
+ POKE(traffic_indicator, DOWN_ARROW);
+#endif
+#ifdef FEAT_KEYBOARD_BUFFER
+ keybuf_poll_kbd();
+#endif
+ switch(c) {
+ case SLIP_ESC:
+ lastc = c;
+ break;
+
+ case SLIP_END:
+ lastc = c;
+ /* End marker found, we copy our input buffer to the uip_buf
+ buffer and return the size of the packet we copied. */
+ memcpy(uip_buf, slip_buf, len);
+ tmplen = len;
+ len = 0;
+#ifdef FEAT_TRAFFIC_INDICATOR
+ POKE(traffic_indicator, old_char);
+#endif
+ return tmplen;
+
+ default:
+ if(lastc == SLIP_ESC) {
+ lastc = c;
+ /* Previous read byte was an escape byte, so this byte will be
+ interpreted differently from others. */
+ switch(c) {
+ case SLIP_ESC_END:
+ c = SLIP_END;
+ break;
+ case SLIP_ESC_ESC:
+ c = SLIP_ESC;
+ break;
+ }
+ } else {
+ lastc = c;
+ }
+
+ slip_buf[len] = c;
+ ++len;
+
+ if(len > MAX_SIZE) {
+ len = 0;
+ }
+
+ break;
+ }
+ }
+
+#ifdef FEAT_TRAFFIC_INDICATOR
+ POKE(traffic_indicator, old_char);
+#endif
+ return 0;
+}
+
+/*-----------------------------------------------------------------------------------*/
+/*
+ * rs232dev_init():
+ *
+ * Initializes the RS232 device and sets the parameters of the device.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+
+char rs232dev_init(unsigned char baud) {
+ char err;
+
+#ifdef FEAT_TRAFFIC_INDICATOR
+ traffic_indicator = PEEKW(0x58) + 39; /* upper-right corner */
+#endif
+
+ err = rs232_init(0);
+ rs232_err(err);
+ err = rs232_params(baud, RS_PAR_NONE);
+ rs232_err(err);
+
+ len = 0;
+
+ return err;
+}
+/*-----------------------------------------------------------------------------------*/
+
+void rs232dev_close(void) {
+ rs232_done();
+}
diff --git a/src/rs232dev.h b/src/rs232dev.h
new file mode 100644
index 0000000..543ab99
--- /dev/null
+++ b/src/rs232dev.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2001, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Adam Dunkels.
+ * 4. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: rs232dev.h,v 1.1 2001/11/20 20:49:45 adam Exp $
+ *
+ */
+
+#ifndef __RS232DEV_H__
+#define __RS232DEV_H__
+
+#include "uip.h"
+
+char rs232dev_init(unsigned char baud);
+u8_t rs232dev_read(void);
+void rs232dev_send(void);
+void rs232dev_close(void);
+
+#if UIP_BUFSIZE > 255
+u16_t rs232dev_poll(void);
+#else
+u8_t rs232dev_poll(void);
+#endif /* UIP_BUFSIZE > 255 */
+
+#endif /* __RS232DEV_H__ */
diff --git a/src/rvert.com b/src/rvert.com
new file mode 100644
index 0000000..b5aeccc
--- /dev/null
+++ b/src/rvert.com
Binary files differ
diff --git a/src/slattach_rts.diff b/src/slattach_rts.diff
new file mode 100644
index 0000000..d14afe1
--- /dev/null
+++ b/src/slattach_rts.diff
@@ -0,0 +1,26 @@
+--- net-tools-1.60/slattach.c 2008-11-01 12:29:56.000000000 -0400
++++ net-tools-1.60.patched/slattach.c 2008-10-31 21:41:43.000000000 -0400
+@@ -347,6 +347,7 @@
+ tty->c_cflag |= CLOCAL;
+ else
+ tty->c_cflag |= CRTSCTS;
++ tty->c_cflag &= ~CRTSCTS; /* 20081031 bkw: need or not? */
+ tty->c_cflag |= speed; /* restore speed */
+ return(0);
+ }
+@@ -723,6 +724,15 @@
+ (void) signal(SIGQUIT, sig_catch);
+ (void) signal(SIGTERM, sig_catch);
+
++ /* 20081031 bkw: force RTS off (Tucker sio2pc) */
++ {
++ int tstatus;
++ fprintf(stderr, "slattach: RTS forced off (Tucker SIO2PC)\n");
++ ioctl(tty_fd, TIOCMGET, &tstatus);
++ tstatus &= ~TIOCM_RTS;
++ ioctl(tty_fd, TIOCMSET, &tstatus);
++ }
++
+ /* Wait until we get killed if hanging on a terminal. */
+ if (opt_e == 0) {
+ while(1) {
diff --git a/src/slirp_debug b/src/slirp_debug
new file mode 100644
index 0000000..7a2f1b5
--- /dev/null
+++ b/src/slirp_debug
@@ -0,0 +1,2 @@
+Slirp 1.0.16 - Debugging Started.
+Debugging Started level 10.
diff --git a/src/start_getty.sh b/src/start_getty.sh
new file mode 100644
index 0000000..7195d5e
--- /dev/null
+++ b/src/start_getty.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+ATR_IMAGE=${1-dumb.atr}
+TTY=/dev/ttyS0
+
+fuser -k $TTY 2&>/dev/null # make sure nobody's using the port...
+$DELAY
+fuser -k -9 $TTY 2&>/dev/null # Just in case...
+$DELAY
+modprobe atarisio port=$TTY
+$DELAY
+atariserver $ATR_IMAGE
+#atariserver autorun.sys # fails when run from MyPicoDOS, why?
+$DELAY
+rmmod atarisio
+$DELAY
+strace -o/dev/null agetty -L $TTY 4800 vt100 &
+$DELAY
+./clear_rts
diff --git a/src/start_slip.sh b/src/start_slip.sh
new file mode 100755
index 0000000..8a9320a
--- /dev/null
+++ b/src/start_slip.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+# Configurable stuff:
+
+TTY=/dev/ttyUSB0 # serial port to use
+BAUD=9600 # must match compiled-in value in rs232dev.c
+SLATTACH=a8_slattach # slattach binary (possibly patched)
+SLIP_IFACE=sl0 # probably no need to change this
+LOCAL_IP=192.168.0.1 # SLIP IP address for Linux host
+REMOTE_IP=192.168.0.2 # SLIP IP address for Atari host
+IP_FORWARD=yes # Route packets for the Atari?
+IP_MASQUERADE=yes # NAT for the Atari?
+MASQ_IFACE=eth1 # if NATing, our main (LAM or internet) interface
+DUMP_PACKETS=yes # Run tcpdump on sl0 interface?
+
+# DELAY may not be needed on all systems...
+
+# No delay:
+#DELAY="true"
+
+# 1 second:
+#DELAY="sleep 1"
+
+# 1/4 second (may not work on old Linux installs):
+DELAY="usleep 250000"
+
+# End of config section, start of code:
+
+ifconfig $SLIP_IFACE down 2&>/dev/null
+killall $SLATTACH 2&>/dev/null
+fuser -k $TTY 2&>/dev/null # make sure nobody's using the port...
+$DELAY
+fuser -k -9 $TTY 2&>/dev/null # Just in case...
+$DELAY
+
+echo "Starting SLIP on $SLIP_IFACE, local $LOCAL_IP, remote $REMOTE_IP"
+$SLATTACH -L -p slip -s $BAUD $TTY &
+$DELAY
+ifconfig $SLIP_IFACE $LOCAL_IP mtu 576
+ifconfig $SLIP_IFACE $LOCAL_IP pointopoint $REMOTE_IP
+
+if [ "$IP_MASQUERADE" = "yes" ]; then
+ echo "IP Masquerading enabled"
+ iptables -F
+ iptables -t nat -F
+ iptables -t nat -A POSTROUTING -o $MASQ_IFACE -j MASQUERADE
+fi
+
+if [ "$IP_FORWARD" = "yes" ]; then
+ echo "IP Forwarding enabled"
+ echo "1" > /proc/sys/net/ipv4/ip_forward
+fi
+
+if [ "$DUMP_PACKETS" = "yes" ]; then
+ tcpdump -i $SLIP_IFACE -X -n -vvv -s 0
+fi
diff --git a/src/start_slirp.sh b/src/start_slirp.sh
new file mode 100644
index 0000000..4f3ad40
--- /dev/null
+++ b/src/start_slirp.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+# Configurable stuff:
+
+TTY=/dev/ttyS0 # serial port to use
+BAUD=4800 # must match FujiChat conf
+
+# This setting is only needed if you're using an AtariMax (Steve Tucker)
+# auto-sensing SIO2PC as your serial device.
+TUCKER_SIO2PC_HACK="yes"
+
+# DELAY is needed on some (most?) systems because e.g. atariserver tries
+# to run before the atarisio module is fully initialized. Choose one:
+
+# No delay:
+#DELAY="true"
+
+# 1 second:
+#DELAY="sleep 1"
+
+# 1/4 second (may not work on old Linux installs):
+DELAY="usleep 250000"
+
+slirp "tty $TTY" "mru 576" "mtu 576" "baudrate $BAUD" &
+
+if [ "$TUCKER_SIO2PC_HACK" = "yes" ]; then
+ sleep 1
+ ./clear_rts
+fi
diff --git a/src/test.atr b/src/test.atr
new file mode 100644
index 0000000..67e0b78
--- /dev/null
+++ b/src/test.atr
Binary files differ
diff --git a/src/testip.c b/src/testip.c
new file mode 100644
index 0000000..44f1086
--- /dev/null
+++ b/src/testip.c
@@ -0,0 +1,10 @@
+
+#include <stdio.h>
+
+extern unsigned char * __fastcall__ new_format_ip (void *);
+
+void main(void) {
+ char ip[4] = { 0xc0, 0xa8, 0x00, 0x01 };
+ puts(new_format_ip(ip));
+HANG: goto HANG;
+}
diff --git a/src/uip-conf.h b/src/uip-conf.h
new file mode 100644
index 0000000..1a9e745
--- /dev/null
+++ b/src/uip-conf.h
@@ -0,0 +1,180 @@
+
+/**
+ * \addtogroup uipopt
+ * @{
+ */
+
+/**
+ * \name Project-specific configuration options
+ * @{
+ *
+ * uIP has a number of configuration options that can be overridden
+ * for each project. These are kept in a project-specific uip-conf.h
+ * file and all configuration names have the prefix UIP_CONF.
+ */
+
+/*
+ * Copyright (c) 2006, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: uip-conf.h,v 1.6 2006/06/12 08:00:31 adam Exp $
+ */
+
+/**
+ * \file
+ * An example uIP configuration file
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ */
+
+#ifndef __UIP_CONF_H__
+#define __UIP_CONF_H__
+
+/**
+ * 8 bit datatype
+ *
+ * This typedef defines the 8-bit type used throughout uIP.
+ *
+ * \hideinitializer
+ */
+typedef unsigned char u8_t;
+
+/**
+ * 16 bit datatype
+ *
+ * This typedef defines the 16-bit type used throughout uIP.
+ *
+ * \hideinitializer
+ */
+typedef unsigned int u16_t;
+
+/**
+ * Statistics datatype
+ *
+ * This typedef defines the dataype used for keeping statistics in
+ * uIP.
+ *
+ * \hideinitializer
+ */
+typedef unsigned short uip_stats_t;
+
+/**
+ * Maximum number of TCP connections.
+ *
+ * \hideinitializer
+ */
+// #define UIP_CONF_MAX_CONNECTIONS 5
+#define UIP_CONF_MAX_CONNECTIONS 1
+#define UIP_CONF_UDP_CONNS 1
+
+/* disable TCP listen support entirely, saves approx. 1K
+ in the binary
+ */
+// #define UIP_CONF_TCP_LISTEN
+#undef UIP_CONF_TCP_LISTEN
+
+/**
+ * Maximum number of listening TCP ports.
+ * (not used if UIP_CONF_TCP_LISTEN is 0)
+ *
+ * \hideinitializer
+ */
+// #define UIP_CONF_MAX_LISTENPORTS 5
+#define UIP_CONF_MAX_LISTENPORTS 1
+
+/**
+ * uIP buffer size.
+ *
+ * \hideinitializer
+ */
+// #define UIP_CONF_BUFFER_SIZE 160
+#define UIP_CONF_BUFFER_SIZE 576
+
+/**
+ * CPU byte order.
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_BYTE_ORDER LITTLE_ENDIAN
+
+/**
+ * Logging on or off
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_LOGGING 0
+
+/**
+ * UDP support on or off
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_UDP 1
+
+/**
+ * UDP checksums on or off
+ *
+ * \hideinitializer
+ */
+// #define UIP_CONF_UDP_CHECKSUMS 1
+#define UIP_CONF_UDP_CHECKSUMS 0
+
+/**
+ * uIP statistics on or off
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_STATISTICS 0
+
+/* 0 for SLIP, 14 for Ethernet */
+#define UIP_CONF_LLH_LEN 0
+
+/* Here we include the header file for the application(s) we use in
+ our project. */
+/*#include "smtp.h"*/
+/*#include "hello-world.h"*/
+/*#include "telnetd.h"*/
+// #include "webclient.h"
+/*#include "dhcpc.h"*/
+/*#include "webclient.h"*/
+
+/*
+#ifdef LIB_ONLY
+#define uip_tcp_appstate_t int
+#undef UIP_CONF_UDP
+#else
+*/
+#include "resolv.h"
+#include "telnet.h"
+// #endif
+
+#endif /* __UIP_CONF_H__ */
+
+/** @} */
+/** @} */
diff --git a/src/uip_arch.h b/src/uip_arch.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/uip_arch.h
diff --git a/src/uip_asm_output.s b/src/uip_asm_output.s
new file mode 100644
index 0000000..7f8c38c
--- /dev/null
+++ b/src/uip_asm_output.s
@@ -0,0 +1,5253 @@
+;
+; File generated by cc65 v 2.12.9
+;
+ .fopt compiler,"cc65 v 2.12.9"
+ .setcpu "6502"
+ .smart on
+ .autoimport on
+ .case on
+ .debuginfo off
+ .importzp sp, sreg, regsave, regbank, tmp1, ptr1, ptr2
+ .macpack longbranch
+ .import _resolv_appcall
+ .import _telnet_app
+ .export _uip_init
+ .export _uip_setipid
+ .export _uip_buf
+ .export _uip_listen
+ .export _uip_unlisten
+ .export _uip_connect
+ .export _uip_send
+ .export _uip_udp_new
+ .export _htons
+ .export _uip_appdata
+ .export _uip_len
+ .export _uip_conn
+ .export _uip_conns
+ .export _uip_acc32
+ .export _uip_udp_conn
+ .export _uip_udp_conns
+ .export _uip_flags
+ .export _uip_process
+ .export _uip_hostaddr
+ .export _uip_netmask
+ .export _uip_draddr
+ .export _uip_chksum
+ .export _uip_ipchksum
+ .export _uip_tcpchksum
+ .import _memcpy
+ .import _memset
+ .export _uip_ethaddr
+ .export _uip_sappdata
+ .export _uip_slen
+ .export _uip_listenports
+ .export _uip_add32
+
+.segment "DATA"
+
+_all_ones_addr:
+ .word $FFFF
+ .word $FFFF
+_all_zeroes_addr:
+ .word $0000
+ .word $0000
+_uip_ethaddr:
+ .byte $00
+ .byte $00
+ .byte $00
+ .byte $00
+ .byte $00
+ .byte $00
+
+.segment "BSS"
+
+_uip_hostaddr:
+ .res 4,$00
+_uip_draddr:
+ .res 4,$00
+_uip_netmask:
+ .res 4,$00
+_uip_buf:
+ .res 578,$00
+_uip_appdata:
+ .res 2,$00
+_uip_sappdata:
+ .res 2,$00
+_uip_len:
+ .res 2,$00
+_uip_slen:
+ .res 2,$00
+_uip_flags:
+ .res 1,$00
+_uip_conn:
+ .res 2,$00
+_uip_conns:
+ .res 35,$00
+_uip_listenports:
+ .res 2,$00
+_uip_udp_conn:
+ .res 2,$00
+_uip_udp_conns:
+ .res 11,$00
+_ipid:
+ .res 2,$00
+_iss:
+ .res 4,$00
+_lastport:
+ .res 2,$00
+_uip_acc32:
+ .res 4,$00
+_c:
+ .res 1,$00
+_opt:
+ .res 1,$00
+_tmp16:
+ .res 2,$00
+
+; ---------------------------------------------------------------
+; void __near__ uip_init (void)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _uip_init: near
+
+.segment "CODE"
+
+;
+; for(c = 0; c < UIP_LISTENPORTS; ++c) {
+;
+ lda #$00
+ sta _c
+L00BF: lda _c
+ cmp #$01
+ bcs L00C0
+;
+; uip_listenports[c] = 0;
+;
+ ldx #$00
+ lda _c
+ jsr aslax1
+ clc
+ adc #<(_uip_listenports)
+ tay
+ txa
+ adc #>(_uip_listenports)
+ tax
+ tya
+ sta sreg
+ stx sreg+1
+ lda #$00
+ tay
+ sta (sreg),y
+ iny
+ sta (sreg),y
+;
+; for(c = 0; c < UIP_LISTENPORTS; ++c) {
+;
+ inc _c
+ jmp L00BF
+;
+; for(c = 0; c < UIP_CONNS; ++c) {
+;
+L00C0: lda #$00
+ sta _c
+L00CA: lda _c
+ cmp #$01
+ bcs L00CB
+;
+; uip_conns[c].tcpstateflags = UIP_CLOSED;
+;
+ lda _c
+ jsr pusha0
+ lda #$23
+ jsr tosmula0
+ clc
+ adc #<(_uip_conns)
+ tay
+ txa
+ adc #>(_uip_conns)
+ tax
+ tya
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$19
+ sta (sreg),y
+;
+; for(c = 0; c < UIP_CONNS; ++c) {
+;
+ inc _c
+ jmp L00CA
+;
+; lastport = 1024;
+;
+L00CB: ldx #$04
+ lda #$00
+ sta _lastport
+ stx _lastport+1
+;
+; for(c = 0; c < UIP_UDP_CONNS; ++c) {
+;
+ sta _c
+L00D7: lda _c
+ cmp #$01
+ bcs L00D8
+;
+; uip_udp_conns[c].lport = 0;
+;
+ lda _c
+ jsr pusha0
+ lda #$0B
+ jsr tosmula0
+ clc
+ adc #<(_uip_udp_conns)
+ tay
+ txa
+ adc #>(_uip_udp_conns)
+ tax
+ tya
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$04
+ sta (sreg),y
+ iny
+ sta (sreg),y
+;
+; for(c = 0; c < UIP_UDP_CONNS; ++c) {
+;
+ inc _c
+ jmp L00D7
+;
+; }
+;
+L00D8: rts
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ uip_setipid (unsigned int)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _uip_setipid: near
+
+.segment "CODE"
+
+;
+; void uip_setipid(u16_t id) { ipid = id; }
+;
+ jsr ldax0sp
+ sta _ipid
+ stx _ipid+1
+ jmp incsp2
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ uip_listen (unsigned int)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _uip_listen: near
+
+.segment "CODE"
+
+;
+; for(c = 0; c < UIP_LISTENPORTS; ++c) {
+;
+ lda #$00
+ sta _c
+L01AF: lda _c
+ cmp #$01
+ jcs incsp2
+;
+; if(uip_listenports[c] == 0) {
+;
+ ldx #$00
+ lda _c
+ jsr aslax1
+ clc
+ adc #<(_uip_listenports)
+ tay
+ txa
+ adc #>(_uip_listenports)
+ tax
+ tya
+ jsr ldaxi
+ cpx #$00
+ bne L01B1
+ cmp #$00
+ bne L01B1
+;
+; uip_listenports[c] = port;
+;
+ lda _c
+ jsr aslax1
+ clc
+ adc #<(_uip_listenports)
+ tay
+ txa
+ adc #>(_uip_listenports)
+ tax
+ tya
+ sta sreg
+ stx sreg+1
+ jsr ldax0sp
+ ldy #$00
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; return;
+;
+ jmp incsp2
+;
+; for(c = 0; c < UIP_LISTENPORTS; ++c) {
+;
+L01B1: inc _c
+ jmp L01AF
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ uip_unlisten (unsigned int)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _uip_unlisten: near
+
+.segment "CODE"
+
+;
+; for(c = 0; c < UIP_LISTENPORTS; ++c) {
+;
+ lda #$00
+ sta _c
+L01A0: lda _c
+ cmp #$01
+ jcs incsp2
+;
+; if(uip_listenports[c] == port) {
+;
+ ldx #$00
+ lda _c
+ jsr aslax1
+ clc
+ adc #<(_uip_listenports)
+ tay
+ txa
+ adc #>(_uip_listenports)
+ tax
+ tya
+ jsr pushw
+ ldy #$03
+ jsr ldaxysp
+ jsr tosicmp
+ bne L01A2
+;
+; uip_listenports[c] = 0;
+;
+ ldx #$00
+ lda _c
+ jsr aslax1
+ clc
+ adc #<(_uip_listenports)
+ tay
+ txa
+ adc #>(_uip_listenports)
+ tax
+ tya
+ sta sreg
+ stx sreg+1
+ lda #$00
+ tay
+ sta (sreg),y
+ iny
+ sta (sreg),y
+;
+; return;
+;
+ jmp incsp2
+;
+; for(c = 0; c < UIP_LISTENPORTS; ++c) {
+;
+L01A2: inc _c
+ jmp L01A0
+
+.endproc
+
+; ---------------------------------------------------------------
+; __near__ struct uip_conn* __near__ uip_connect (__near__ unsigned int[2]*, unsigned int)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _uip_connect: near
+
+.segment "CODE"
+
+;
+; again:
+;
+ jsr decsp4
+;
+; ++lastport;
+;
+L00E3: inc _lastport
+ bne L00E5
+ inc _lastport+1
+;
+; if(lastport >= 32000) {
+;
+L00E5: ldx _lastport+1
+ cpx #$7D
+ bcc L00E6
+;
+; lastport = 4096;
+;
+ ldx #$10
+ lda #$00
+ sta _lastport
+ stx _lastport+1
+;
+; for(c = 0; c < UIP_CONNS; ++c) {
+;
+L00E6: lda #$00
+ sta _c
+L00EA: lda _c
+ cmp #$01
+ bcs L00EB
+;
+; conn = &uip_conns[c];
+;
+ lda _c
+ jsr pusha0
+ lda #$23
+ jsr tosmula0
+ clc
+ adc #<(_uip_conns)
+ tay
+ txa
+ adc #>(_uip_conns)
+ tax
+ tya
+ ldy #$02
+ jsr staxysp
+;
+; if(conn->tcpstateflags != UIP_CLOSED &&
+;
+ ldy #$19
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ beq L00EC
+;
+; conn->lport == htons(lastport)) {
+;
+ ldy #$03
+ jsr ldaxysp
+ ldy #$05
+ jsr pushwidx
+ lda _lastport
+ ldx _lastport+1
+ jsr pushax
+ jsr _htons
+ jsr tosicmp
+ beq L00E3
+;
+; for(c = 0; c < UIP_CONNS; ++c) {
+;
+L00EC: inc _c
+ jmp L00EA
+;
+; conn = 0;
+;
+L00EB: ldx #$00
+ txa
+ ldy #$02
+ jsr staxysp
+;
+; for(c = 0; c < UIP_CONNS; ++c) {
+;
+ sta _c
+L00FC: lda _c
+ cmp #$01
+ bcs L00FD
+;
+; cconn = &uip_conns[c];
+;
+ lda _c
+ jsr pusha0
+ lda #$23
+ jsr tosmula0
+ clc
+ adc #<(_uip_conns)
+ tay
+ txa
+ adc #>(_uip_conns)
+ tax
+ tya
+ jsr stax0sp
+;
+; if(cconn->tcpstateflags == UIP_CLOSED) {
+;
+ ldy #$19
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ bne L0107
+;
+; conn = cconn;
+;
+ jsr ldax0sp
+ ldy #$02
+ jsr staxysp
+;
+; break;
+;
+ jmp L00FD
+;
+; if(cconn->tcpstateflags == UIP_TIME_WAIT) {
+;
+L0107: jsr ldax0sp
+ ldy #$19
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$07
+ bne L00FE
+;
+; if(conn == 0 ||
+;
+ ldy #$02
+ lda (sp),y
+ iny
+ ora (sp),y
+ beq L010E
+;
+; cconn->timer > conn->timer) {
+;
+ jsr ldax0sp
+ ldy #$1A
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ jsr pusha0
+ ldy #$05
+ jsr ldaxysp
+ ldy #$1A
+ sta ptr1
+ stx ptr1+1
+ ldx #$00
+ lda (ptr1),y
+ jsr tosicmp
+ beq L00FE
+ bcc L00FE
+;
+; conn = cconn;
+;
+L010E: jsr ldax0sp
+ ldy #$02
+ jsr staxysp
+;
+; for(c = 0; c < UIP_CONNS; ++c) {
+;
+L00FE: inc _c
+ jmp L00FC
+;
+; if(conn == 0) {
+;
+L00FD: ldy #$02
+ lda (sp),y
+ iny
+ ora (sp),y
+ bne L0113
+;
+; return 0;
+;
+ tax
+ jmp incsp8
+;
+; conn->tcpstateflags = UIP_SYN_SENT;
+;
+L0113: jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ lda #$02
+ ldy #$19
+ sta (sreg),y
+;
+; conn->snd_nxt[0] = iss[0];
+;
+ ldy #$03
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ lda _iss
+ ldy #$0C
+ sta (sreg),y
+;
+; conn->snd_nxt[1] = iss[1];
+;
+ ldy #$03
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ lda _iss+1
+ ldy #$0D
+ sta (sreg),y
+;
+; conn->snd_nxt[2] = iss[2];
+;
+ ldy #$03
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ lda _iss+2
+ ldy #$0E
+ sta (sreg),y
+;
+; conn->snd_nxt[3] = iss[3];
+;
+ ldy #$03
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ lda _iss+3
+ ldy #$0F
+ sta (sreg),y
+;
+; conn->initialmss = conn->mss = UIP_TCP_MSS;
+;
+ ldy #$05
+ jsr pushwysp
+ ldy #$07
+ jsr pushwysp
+ ldx #$00
+ lda #$78
+ ldy #$12
+ jsr staxspidx
+ ldy #$14
+ jsr staxspidx
+;
+; conn->len = 1; /* TCP length of the SYN is one. */
+;
+ ldy #$03
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ lda #$01
+ ldy #$10
+ sta (sreg),y
+ iny
+ lda #$00
+ sta (sreg),y
+;
+; conn->nrtx = 0;
+;
+ ldy #$03
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$1B
+ sta (sreg),y
+;
+; conn->timer = 1; /* Send the SYN next time around. */
+;
+ ldy #$03
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ lda #$01
+ ldy #$1A
+ sta (sreg),y
+;
+; conn->rto = UIP_RTO;
+;
+ ldy #$03
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ lda #$03
+ ldy #$18
+ sta (sreg),y
+;
+; conn->sa = 0;
+;
+ tay
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$16
+ sta (sreg),y
+;
+; conn->sv = 16; /* Initial value of the RTT variance. */
+;
+ ldy #$03
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ lda #$10
+ ldy #$17
+ sta (sreg),y
+;
+; conn->lport = htons(lastport);
+;
+ ldy #$05
+ jsr pushwysp
+ lda _lastport
+ ldx _lastport+1
+ jsr pushax
+ jsr _htons
+ ldy #$04
+ jsr staxspidx
+;
+; conn->rport = rport;
+;
+ dey
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ ldy #$05
+ jsr ldaxysp
+ ldy #$06
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; uip_ipaddr_copy(&conn->ripaddr, ripaddr);
+;
+ ldy #$03
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ ldy #$07
+ jsr ldaxysp
+ jsr ldaxi
+ ldy #$00
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+ ldy #$03
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ ldy #$07
+ jsr ldaxysp
+ ldy #$03
+ jsr ldaxidx
+ ldy #$02
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; return conn;
+;
+ jsr ldaxysp
+;
+; }
+;
+ jmp incsp8
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ uip_send (__near__ const void*, int)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _uip_send: near
+
+.segment "CODE"
+
+;
+; if(len > 0) {
+;
+ jsr pushw0sp
+ lda #$01
+ jsr tosgea0
+ jeq incsp4
+;
+; uip_slen = len;
+;
+ jsr ldax0sp
+ sta _uip_slen
+ stx _uip_slen+1
+;
+; if(data != uip_sappdata) {
+;
+ ldy #$05
+ jsr pushwysp
+ lda _uip_sappdata
+ ldx _uip_sappdata+1
+ jsr tosicmp
+ jeq incsp4
+;
+; memcpy(uip_sappdata, (data), uip_slen);
+;
+ lda _uip_sappdata
+ ldx _uip_sappdata+1
+ jsr pushax
+ ldy #$07
+ jsr pushwysp
+ lda _uip_slen
+ ldx _uip_slen+1
+ jsr _memcpy
+;
+; }
+;
+ jmp incsp4
+
+.endproc
+
+; ---------------------------------------------------------------
+; __near__ struct uip_udp_conn* __near__ uip_udp_new (__near__ unsigned int[2]*, unsigned int)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _uip_udp_new: near
+
+.segment "CODE"
+
+;
+; again:
+;
+ jsr decsp2
+;
+; ++lastport;
+;
+L0151: inc _lastport
+ bne L0153
+ inc _lastport+1
+;
+; if(lastport >= 32000) {
+;
+L0153: ldx _lastport+1
+ cpx #$7D
+ bcc L0154
+;
+; lastport = 4096;
+;
+ ldx #$10
+ lda #$00
+ sta _lastport
+ stx _lastport+1
+;
+; for(c = 0; c < UIP_UDP_CONNS; ++c) {
+;
+L0154: lda #$00
+ sta _c
+L0158: lda _c
+ cmp #$01
+ bcs L0159
+;
+; if(uip_udp_conns[c].lport == htons(lastport)) {
+;
+ lda _c
+ jsr pusha0
+ lda #$0B
+ jsr tosmula0
+ clc
+ adc #<(_uip_udp_conns)
+ tay
+ txa
+ adc #>(_uip_udp_conns)
+ tax
+ tya
+ ldy #$05
+ jsr pushwidx
+ lda _lastport
+ ldx _lastport+1
+ jsr pushax
+ jsr _htons
+ jsr tosicmp
+;
+; goto again;
+;
+ beq L0151
+;
+; for(c = 0; c < UIP_UDP_CONNS; ++c) {
+;
+ inc _c
+ jmp L0158
+;
+; conn = 0;
+;
+L0159: ldx #$00
+ txa
+ jsr stax0sp
+;
+; for(c = 0; c < UIP_UDP_CONNS; ++c) {
+;
+ sta _c
+L0166: lda _c
+ cmp #$01
+ bcs L0167
+;
+; if(uip_udp_conns[c].lport == 0) {
+;
+ lda _c
+ jsr pusha0
+ lda #$0B
+ jsr tosmula0
+ clc
+ adc #<(_uip_udp_conns)
+ tay
+ txa
+ adc #>(_uip_udp_conns)
+ tax
+ tya
+ ldy #$05
+ jsr ldaxidx
+ cpx #$00
+ bne L0168
+ cmp #$00
+ bne L0168
+;
+; conn = &uip_udp_conns[c];
+;
+ lda _c
+ jsr pusha0
+ lda #$0B
+ jsr tosmula0
+ clc
+ adc #<(_uip_udp_conns)
+ tay
+ txa
+ adc #>(_uip_udp_conns)
+ tax
+ tya
+ jsr stax0sp
+;
+; break;
+;
+ jmp L0167
+;
+; for(c = 0; c < UIP_UDP_CONNS; ++c) {
+;
+L0168: inc _c
+ jmp L0166
+;
+; if(conn == 0) {
+;
+L0167: ldy #$00
+ lda (sp),y
+ iny
+ ora (sp),y
+ bne L0175
+;
+; return 0;
+;
+ tax
+ jmp incsp6
+;
+; conn->lport = HTONS(lastport);
+;
+L0175: jsr ldax0sp
+ sta ptr1
+ stx ptr1+1
+ ldx _lastport
+ stx sreg+1
+ ldx #$00
+ lda _lastport+1
+ sta sreg
+ txa
+ ora sreg+1
+ tax
+ lda sreg
+ ldy #$04
+ sta (ptr1),y
+ iny
+ txa
+ sta (ptr1),y
+;
+; conn->rport = rport;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ ldy #$03
+ jsr ldaxysp
+ ldy #$06
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; if(ripaddr == NULL) {
+;
+ ldy #$04
+ lda (sp),y
+ iny
+ ora (sp),y
+ bne L0184
+;
+; memset(conn->ripaddr, 0, sizeof(uip_ipaddr_t));
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$03
+L087D: sta (sreg),y
+ dey
+ bpl L087D
+;
+; } else {
+;
+ jmp L018E
+;
+; uip_ipaddr_copy(&conn->ripaddr, ripaddr);
+;
+L0184: jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ ldy #$05
+ jsr ldaxysp
+ jsr ldaxi
+ ldy #$00
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ ldy #$05
+ jsr ldaxysp
+ ldy #$03
+ jsr ldaxidx
+ ldy #$02
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; conn->ttl = UIP_TTL;
+;
+L018E: jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$40
+ ldy #$08
+ sta (sreg),y
+;
+; return conn;
+;
+ jsr ldax0sp
+;
+; }
+;
+ jmp incsp6
+
+.endproc
+
+; ---------------------------------------------------------------
+; unsigned int __near__ htons (unsigned int)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _htons: near
+
+.segment "CODE"
+
+;
+; return HTONS(val);
+;
+ ldy #$00
+ lda (sp),y
+ tax
+ stx sreg+1
+ ldx #$00
+ iny
+ lda (sp),y
+ sta sreg
+ txa
+ ora sreg+1
+ tax
+ lda sreg
+;
+; }
+;
+ jmp incsp2
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ uip_process (unsigned char)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _uip_process: near
+
+.segment "CODE"
+
+;
+; register struct uip_conn *uip_connr = uip_conn;
+;
+ lda _uip_conn
+ ldx _uip_conn+1
+ jsr pushax
+;
+; if(flag == UIP_UDP_SEND_CONN) {
+;
+ ldy #$02
+ lda (sp),y
+ cmp #$04
+;
+; goto udp_send;
+;
+ jeq L01D6
+;
+; uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
+;
+ lda #<(_uip_buf+40)
+ ldx #>(_uip_buf+40)
+ sta _uip_appdata
+ stx _uip_appdata+1
+ sta _uip_sappdata
+ stx _uip_sappdata+1
+;
+; if(flag == UIP_POLL_REQUEST) {
+;
+ lda (sp),y
+ cmp #$03
+ bne L01DC
+;
+; if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED &&
+;
+ jsr ldax0sp
+ ldy #$19
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ and #$0F
+ cmp #$03
+ jne L01EA
+;
+; !uip_outstanding(uip_connr)) {
+;
+ jsr ldax0sp
+ ldy #$11
+ jsr ldaxidx
+ stx tmp1
+ ora tmp1
+ jne L01EA
+;
+; uip_flags = UIP_POLL;
+;
+ lda #$08
+ sta _uip_flags
+;
+; goto appsend;
+;
+ jmp L0888
+;
+; } else if(flag == UIP_TIMER) {
+;
+L01DC: lda (sp),y
+ cmp #$02
+ jne L01EC
+;
+; if(++iss[3] == 0) {
+;
+ inc _iss+3
+ lda _iss+3
+ bne L01F4
+;
+; if(++iss[2] == 0) {
+;
+ inc _iss+2
+ lda _iss+2
+ bne L01F4
+;
+; if(++iss[1] == 0) {
+;
+ inc _iss+1
+ lda _iss+1
+ bne L01F4
+;
+; ++iss[0];
+;
+ inc _iss
+;
+; uip_len = 0;
+;
+L01F4: lda #$00
+ sta _uip_len
+ sta _uip_len+1
+;
+; uip_slen = 0;
+;
+ sta _uip_slen
+ sta _uip_slen+1
+;
+; if(uip_connr->tcpstateflags == UIP_TIME_WAIT ||
+;
+ jsr ldax0sp
+ ldy #$19
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$07
+ beq L01FE
+;
+; uip_connr->tcpstateflags == UIP_FIN_WAIT_2) {
+;
+ jsr ldax0sp
+ ldy #$19
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$05
+ bne L01FD
+;
+; ++(uip_connr->timer);
+;
+L01FE: jsr ldax0sp
+ sta ptr1
+ stx ptr1+1
+ ldy #$1A
+ lda #$01
+ clc
+ adc (ptr1),y
+ sta (ptr1),y
+;
+; if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) {
+;
+ jsr ldax0sp
+ ldy #$1A
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$78
+ jne L01EA
+;
+; uip_connr->tcpstateflags = UIP_CLOSED;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$19
+ sta (sreg),y
+;
+; } else if(uip_connr->tcpstateflags != UIP_CLOSED) {
+;
+ jmp L01EA
+L01FD: jsr ldax0sp
+ ldy #$19
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ jeq L01EA
+;
+; if(uip_outstanding(uip_connr)) {
+;
+ jsr ldax0sp
+ ldy #$10
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ iny
+ ora (ptr1),y
+ jeq L0209
+;
+; if(uip_connr->timer-- == 0) {
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ ldy #$1A
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ pha
+ sec
+ sbc #$01
+ sta (sreg),y
+ pla
+ jne L01EA
+;
+; if(uip_connr->nrtx == UIP_MAXRTX ||
+;
+ jsr ldax0sp
+ ldy #$1B
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$08
+ beq L0210
+;
+; ((uip_connr->tcpstateflags == UIP_SYN_SENT ||
+;
+ jsr ldax0sp
+ ldy #$19
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$02
+ beq L0212
+;
+; uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
+;
+ jsr ldax0sp
+ ldy #$19
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$01
+ bne L020F
+;
+; uip_connr->nrtx == UIP_MAXSYNRTX)) {
+;
+L0212: jsr ldax0sp
+ ldy #$1B
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$05
+ bne L020F
+;
+; uip_connr->tcpstateflags = UIP_CLOSED;
+;
+L0210: jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$19
+ sta (sreg),y
+;
+; uip_flags = UIP_TIMEDOUT;
+;
+ lda #$80
+ sta _uip_flags
+;
+; UIP_APPCALL();
+;
+ jsr _telnet_app
+;
+; BUF->flags = TCP_RST | TCP_ACK;
+;
+ lda #$14
+;
+; goto tcp_send_nodata;
+;
+ jmp L0889
+;
+; uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
+;
+L020F: jsr pushw0sp
+ jsr push3
+ ldy #$05
+ jsr ldaxysp
+ ldy #$1B
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ cmp #$05
+;
+; 4:
+;
+ bcc L0224
+ lda #$04
+;
+; uip_connr->nrtx);
+;
+ jmp L0226
+L0224: ldy #$05
+ jsr ldaxysp
+ ldy #$1B
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+L0226: jsr tosaslax
+ ldy #$1A
+ jsr staspidx
+;
+; ++(uip_connr->nrtx);
+;
+ jsr ldax0sp
+ sta ptr1
+ stx ptr1+1
+ ldy #$1B
+ lda #$01
+ clc
+ adc (ptr1),y
+ sta (ptr1),y
+;
+; switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
+;
+ jsr ldax0sp
+ ldy #$19
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ and #$0F
+;
+; }
+;
+ cmp #$01
+ jeq L0230
+ cmp #$02
+ beq L0232
+ cmp #$03
+ beq L0239
+ cmp #$04
+ jeq L0244
+ cmp #$06
+ jeq L0244
+ cmp #$08
+ jeq L0244
+ jmp L01EA
+;
+; BUF->flags = 0;
+;
+L0232: lda #$00
+;
+; goto tcp_send_syn;
+;
+ jmp L088A
+;
+; uip_flags = UIP_REXMIT;
+;
+L0239: lda #$04
+ sta _uip_flags
+;
+; UIP_APPCALL();
+;
+ jsr _telnet_app
+;
+; goto apprexmit;
+;
+ jmp L023D
+;
+; } else if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) {
+;
+L0209: jsr ldax0sp
+ ldy #$19
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ and #$0F
+ cmp #$03
+ jne L01EA
+;
+; uip_flags = UIP_POLL;
+;
+ lda #$08
+ sta _uip_flags
+;
+; goto appsend;
+;
+ jmp L0888
+;
+; if(flag == UIP_UDP_TIMER) {
+;
+L01EC: lda (sp),y
+ cmp #$05
+ bne L024D
+;
+; if(uip_udp_conn->lport != 0) {
+;
+ lda _uip_udp_conn
+ ldx _uip_udp_conn+1
+ ldy #$05
+ jsr ldaxidx
+ cpx #$00
+ bne L0895
+ cmp #$00
+ jeq L01EA
+;
+; uip_conn = NULL;
+;
+L0895: lda #$00
+ sta _uip_conn
+ sta _uip_conn+1
+;
+; uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
+;
+ lda #<(_uip_buf+28)
+ ldx #>(_uip_buf+28)
+ sta _uip_appdata
+ stx _uip_appdata+1
+ sta _uip_sappdata
+ stx _uip_sappdata+1
+;
+; uip_len = uip_slen = 0;
+;
+ lda #$00
+ sta _uip_slen
+ sta _uip_slen+1
+ sta _uip_len
+ sta _uip_len+1
+;
+; uip_flags = UIP_POLL;
+;
+ lda #$08
+ sta _uip_flags
+;
+; goto udp_send;
+;
+ jmp L088B
+;
+; if(BUF->vhl != 0x45) { /* IP version and header length. */
+;
+L024D: lda _uip_buf
+ cmp #$45
+;
+; goto drop;
+;
+ jne L01EA
+;
+; if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) {
+;
+ ldx _uip_buf+2
+ lda #$00
+ clc
+ adc _uip_buf+3
+ bcc L087E
+ inx
+L087E: jsr pushax
+ lda _uip_len
+ ldx _uip_len+1
+ jsr tosicmp
+ beq L0891
+ jcs L01EA
+;
+; uip_len = (BUF->len[0] << 8) + BUF->len[1];
+;
+L0891: ldx _uip_buf+2
+ lda #$00
+ clc
+ adc _uip_buf+3
+ bcc L087F
+ inx
+L087F: sta _uip_len
+ stx _uip_len+1
+;
+; if((BUF->ipoffset[0] & 0x3f) != 0 ||
+;
+ lda _uip_buf+6
+ and #$3F
+ jne L01EA
+;
+; BUF->ipoffset[1] != 0) {
+;
+ lda _uip_buf+7
+ jne L01EA
+;
+; if(uip_ipaddr_cmp(uip_hostaddr, all_zeroes_addr)) {
+;
+ lda #<(_uip_hostaddr)
+ ldx #>(_uip_hostaddr)
+ jsr pushw
+ lda #<(_all_zeroes_addr)
+ ldx #>(_all_zeroes_addr)
+ jsr ldaxi
+ jsr tosicmp
+ bne L0282
+ lda #<(_uip_hostaddr)
+ ldx #>(_uip_hostaddr)
+ ldy #$03
+ jsr pushwidx
+ lda #<(_all_zeroes_addr)
+ ldx #>(_all_zeroes_addr)
+ ldy #$03
+ jsr ldaxidx
+ jsr tosicmp
+ beq L0290
+;
+; if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr)) {
+;
+L0282: lda #<(_uip_buf+16)
+ ldx #>(_uip_buf+16)
+ jsr pushw
+ lda #<(_uip_hostaddr)
+ ldx #>(_uip_hostaddr)
+ jsr ldaxi
+ jsr tosicmp
+ bne L0299
+ lda #<(_uip_buf+16)
+ ldx #>(_uip_buf+16)
+ ldy #$03
+ jsr pushwidx
+ lda #<(_uip_hostaddr)
+ ldx #>(_uip_hostaddr)
+ ldy #$03
+ jsr ldaxidx
+ jsr tosicmp
+ beq L0292
+L0299: lda #$00
+ jmp L02A0
+L0292: lda #$01
+L02A0: jsr bnega
+;
+; goto drop;
+;
+ jne L01EA
+;
+; checksum. */
+;
+L0290: jsr _uip_ipchksum
+ cpx #$FF
+ jne L01EA
+ cmp #$FF
+;
+; goto drop;
+;
+ jne L01EA
+;
+; processing. */
+;
+ lda _uip_buf+9
+ cmp #$06
+;
+; goto tcp_input;
+;
+ jeq L02A8
+;
+; if(BUF->proto == UIP_PROTO_UDP) {
+;
+ lda _uip_buf+9
+ cmp #$11
+;
+; goto udp_input;
+;
+ jeq L02AD
+;
+; here. */
+;
+ lda _uip_buf+9
+ cmp #$01
+;
+; goto drop;
+;
+ jne L01EA
+;
+; if(ICMPBUF->type != ICMP_ECHO) {
+;
+ lda _uip_buf+20
+ cmp #$08
+;
+; goto drop;
+;
+ jne L01EA
+;
+; ICMPBUF->type = ICMP_ECHO_REPLY;
+;
+ lda #$00
+ sta _uip_buf+20
+;
+; if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) {
+;
+ lda _uip_buf+22+1
+ cmp #$FF
+ bne L02C7
+ lda _uip_buf+22
+ cmp #$F7
+L02C7: bcc L02BA
+;
+; ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;
+;
+ lda #$09
+;
+; } else {
+;
+ jmp L089F
+;
+; ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);
+;
+L02BA: lda #$08
+L089F: clc
+ adc _uip_buf+22
+ sta _uip_buf+22
+ bcc L02E0
+ inc _uip_buf+22+1
+;
+; uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
+;
+L02E0: lda #<(_uip_buf+16)
+ sta sreg
+ lda #>(_uip_buf+16)
+ sta sreg+1
+ lda #<(_uip_buf+12)
+ ldx #>(_uip_buf+12)
+ jsr ldaxi
+ ldy #$00
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+ lda #<(_uip_buf+16)
+ sta sreg
+ lda #>(_uip_buf+16)
+ sta sreg+1
+ lda #<(_uip_buf+12)
+ ldx #>(_uip_buf+12)
+ ldy #$03
+ jsr ldaxidx
+ ldy #$02
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+;
+ lda #<(_uip_buf+12)
+ sta sreg
+ lda #>(_uip_buf+12)
+ sta sreg+1
+ lda #<(_uip_hostaddr)
+ ldx #>(_uip_hostaddr)
+ jsr ldaxi
+ ldy #$00
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+ lda #<(_uip_buf+12)
+ sta sreg
+ lda #>(_uip_buf+12)
+ sta sreg+1
+ lda #<(_uip_hostaddr)
+ ldx #>(_uip_hostaddr)
+ ldy #$03
+ jsr ldaxidx
+ ldy #$02
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; goto send;
+;
+ jmp L030D
+;
+; uip_len = uip_len - UIP_IPUDPH_LEN;
+;
+L02AD: lda _uip_len
+ ldx _uip_len+1
+ ldy #$1C
+ jsr decaxy
+ sta _uip_len
+ stx _uip_len+1
+;
+; for(uip_udp_conn = &uip_udp_conns[0];
+;
+ lda #<(_uip_udp_conns)
+ sta _uip_udp_conn
+ lda #>(_uip_udp_conns)
+ sta _uip_udp_conn+1
+;
+; uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];
+;
+L0311: lda _uip_udp_conn
+ ldx _uip_udp_conn+1
+ jsr pushax
+ lda #<(_uip_udp_conns+11)
+ ldx #>(_uip_udp_conns+11)
+ jsr tosicmp
+ jcs L01EA
+;
+; if(uip_udp_conn->lport != 0 &&
+;
+ lda _uip_udp_conn
+ ldx _uip_udp_conn+1
+ ldy #$05
+ jsr ldaxidx
+ cpx #$00
+ bne L0896
+ cmp #$00
+ jeq L0313
+;
+; UDPBUF->destport == uip_udp_conn->lport &&
+;
+L0896: lda _uip_buf+22
+ ldx _uip_buf+22+1
+ jsr pushax
+ lda _uip_udp_conn
+ ldx _uip_udp_conn+1
+ ldy #$05
+ jsr ldaxidx
+ jsr tosicmp
+ jne L0313
+;
+; (uip_udp_conn->rport == 0 ||
+;
+ lda _uip_udp_conn
+ ldx _uip_udp_conn+1
+ ldy #$07
+ jsr ldaxidx
+ cpx #$00
+ bne L0897
+ cmp #$00
+ beq L0322
+;
+; UDPBUF->srcport == uip_udp_conn->rport) &&
+;
+L0897: lda _uip_buf+20
+ ldx _uip_buf+20+1
+ jsr pushax
+ lda _uip_udp_conn
+ ldx _uip_udp_conn+1
+ ldy #$07
+ jsr ldaxidx
+ jsr tosicmp
+ jne L0313
+;
+; (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||
+;
+L0322: lda _uip_udp_conn
+ ldx _uip_udp_conn+1
+ jsr pushw
+ lda #<(_all_zeroes_addr)
+ ldx #>(_all_zeroes_addr)
+ jsr ldaxi
+ jsr tosicmp
+ bne L0885
+ lda _uip_udp_conn
+ ldx _uip_udp_conn+1
+ ldy #$03
+ jsr pushwidx
+ lda #<(_all_zeroes_addr)
+ ldx #>(_all_zeroes_addr)
+ ldy #$03
+ jsr ldaxidx
+ jsr tosicmp
+ beq L034F
+;
+; uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||
+;
+L0885: lda _uip_udp_conn
+ ldx _uip_udp_conn+1
+ jsr pushw
+ lda #<(_all_ones_addr)
+ ldx #>(_all_ones_addr)
+ jsr ldaxi
+ jsr tosicmp
+ bne L0886
+ lda _uip_udp_conn
+ ldx _uip_udp_conn+1
+ ldy #$03
+ jsr pushwidx
+ lda #<(_all_ones_addr)
+ ldx #>(_all_ones_addr)
+ ldy #$03
+ jsr ldaxidx
+ jsr tosicmp
+ beq L034F
+;
+; uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) {
+;
+L0886: lda #<(_uip_buf+12)
+ ldx #>(_uip_buf+12)
+ jsr pushw
+ lda _uip_udp_conn
+ ldx _uip_udp_conn+1
+ jsr ldaxi
+ jsr tosicmp
+ bne L0313
+ lda #<(_uip_buf+12)
+ ldx #>(_uip_buf+12)
+ ldy #$03
+ jsr pushwidx
+ lda _uip_udp_conn
+ ldx _uip_udp_conn+1
+ ldy #$03
+ jsr ldaxidx
+ jsr tosicmp
+ beq L034F
+;
+; ++uip_udp_conn) {
+;
+L0313: lda #$0B
+ clc
+ adc _uip_udp_conn
+ sta _uip_udp_conn
+ jcc L0311
+ inc _uip_udp_conn+1
+ jmp L0311
+;
+; uip_conn = NULL;
+;
+L034F: lda #$00
+ sta _uip_conn
+ sta _uip_conn+1
+;
+; uip_flags = UIP_NEWDATA;
+;
+ lda #$02
+ sta _uip_flags
+;
+; uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
+;
+ lda #<(_uip_buf+28)
+ ldx #>(_uip_buf+28)
+ sta _uip_appdata
+ stx _uip_appdata+1
+ sta _uip_sappdata
+ stx _uip_sappdata+1
+;
+; uip_slen = 0;
+;
+ lda #$00
+ sta _uip_slen
+ sta _uip_slen+1
+;
+; UIP_UDP_APPCALL();
+;
+L088B: jsr _resolv_appcall
+;
+; if(uip_slen == 0) {
+;
+L01D6: lda _uip_slen
+ ora _uip_slen+1
+;
+; goto drop;
+;
+ jeq L01EA
+;
+; uip_len = uip_slen + UIP_IPUDPH_LEN;
+;
+ lda _uip_slen
+ ldx _uip_slen+1
+ ldy #$1C
+ jsr incaxy
+ sta _uip_len
+ stx _uip_len+1
+;
+; BUF->len[0] = (uip_len >> 8);
+;
+ lda _uip_len+1
+ sta _uip_buf+2
+;
+; BUF->len[1] = (uip_len & 0xff);
+;
+ lda _uip_len
+ sta _uip_buf+3
+;
+; BUF->ttl = uip_udp_conn->ttl;
+;
+ lda _uip_udp_conn
+ ldx _uip_udp_conn+1
+ ldy #$08
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta _uip_buf+8
+;
+; BUF->proto = UIP_PROTO_UDP;
+;
+ lda #$11
+ sta _uip_buf+9
+;
+; UDPBUF->udplen = HTONS(uip_slen + UIP_UDPH_LEN);
+;
+ lda _uip_slen
+ clc
+ adc #$08
+ tax
+ lda #$00
+ jsr pushax
+ lda _uip_slen
+ ldx _uip_slen+1
+ jsr incax8
+ txa
+ ldx #$00
+ jsr tosorax
+ sta _uip_buf+24
+ stx _uip_buf+24+1
+;
+; UDPBUF->udpchksum = 0;
+;
+ lda #$00
+ sta _uip_buf+26
+ sta _uip_buf+26+1
+;
+; BUF->srcport = uip_udp_conn->lport;
+;
+ lda _uip_udp_conn
+ ldx _uip_udp_conn+1
+ ldy #$05
+ jsr ldaxidx
+ sta _uip_buf+20
+ stx _uip_buf+20+1
+;
+; BUF->destport = uip_udp_conn->rport;
+;
+ lda _uip_udp_conn
+ ldx _uip_udp_conn+1
+ ldy #$07
+ jsr ldaxidx
+ sta _uip_buf+22
+ stx _uip_buf+22+1
+;
+; uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+;
+ lda #<(_uip_buf+12)
+ sta sreg
+ lda #>(_uip_buf+12)
+ sta sreg+1
+ lda #<(_uip_hostaddr)
+ ldx #>(_uip_hostaddr)
+ jsr ldaxi
+ ldy #$00
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+ lda #<(_uip_buf+12)
+ sta sreg
+ lda #>(_uip_buf+12)
+ sta sreg+1
+ lda #<(_uip_hostaddr)
+ ldx #>(_uip_hostaddr)
+ ldy #$03
+ jsr ldaxidx
+ ldy #$02
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr);
+;
+ lda #<(_uip_buf+16)
+ sta sreg
+ lda #>(_uip_buf+16)
+ sta sreg+1
+ lda _uip_udp_conn
+ ldx _uip_udp_conn+1
+ jsr ldaxi
+ ldy #$00
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+ lda #<(_uip_buf+16)
+ sta sreg
+ lda #>(_uip_buf+16)
+ sta sreg+1
+ lda _uip_udp_conn
+ ldx _uip_udp_conn+1
+ ldy #$03
+ jsr ldaxidx
+ ldy #$02
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
+;
+ lda #<(_uip_buf+40)
+ sta _uip_appdata
+ lda #>(_uip_buf+40)
+ sta _uip_appdata+1
+;
+; goto ip_send_nolen;
+;
+ jmp L03B9
+;
+; checksum. */
+;
+L02A8: jsr _uip_tcpchksum
+ cpx #$FF
+ jne L01EA
+ cmp #$FF
+;
+; goto drop;
+;
+ jne L01EA
+;
+; for(uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1];
+;
+ lda #<(_uip_conns)
+ ldx #>(_uip_conns)
+ jsr stax0sp
+L03BD: jsr pushw0sp
+ lda #<(_uip_conns)
+ ldx #>(_uip_conns)
+ jsr tosicmp
+ beq L0892
+ bcs L03BE
+;
+; if(uip_connr->tcpstateflags != UIP_CLOSED &&
+;
+L0892: jsr ldax0sp
+ ldy #$19
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ beq L03BF
+;
+; BUF->destport == uip_connr->lport &&
+;
+ lda _uip_buf+22
+ ldx _uip_buf+22+1
+ jsr pushax
+ ldy #$03
+ jsr ldaxysp
+ ldy #$05
+ jsr ldaxidx
+ jsr tosicmp
+ bne L03BF
+;
+; BUF->srcport == uip_connr->rport &&
+;
+ lda _uip_buf+20
+ ldx _uip_buf+20+1
+ jsr pushax
+ ldy #$03
+ jsr ldaxysp
+ ldy #$07
+ jsr ldaxidx
+ jsr tosicmp
+ bne L03BF
+;
+; uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) {
+;
+ lda #<(_uip_buf+12)
+ ldx #>(_uip_buf+12)
+ jsr pushw
+ ldy #$03
+ jsr ldaxysp
+ jsr ldaxi
+ jsr tosicmp
+ bne L03BF
+ lda #<(_uip_buf+12)
+ ldx #>(_uip_buf+12)
+ ldy #$03
+ jsr pushwidx
+ ldy #$03
+ jsr ldaxysp
+ ldy #$03
+ jsr ldaxidx
+ jsr tosicmp
+ jeq L03DE
+;
+; ++uip_connr) {
+;
+L03BF: ldx #$00
+ lda #$23
+ jsr addeq0sp
+ jmp L03BD
+;
+; if((BUF->flags & TCP_CTL) != TCP_SYN) {
+;
+L03BE: lda _uip_buf+33
+ and #$3F
+ cmp #$02
+;
+; goto reset;
+;
+ bne L03E5
+;
+; tmp16 = BUF->destport;
+;
+ lda _uip_buf+22
+ sta _tmp16
+ lda _uip_buf+22+1
+ sta _tmp16+1
+;
+; for(c = 0; c < UIP_LISTENPORTS; ++c) {
+;
+ lda #$00
+ sta _c
+L03EA: lda _c
+ cmp #$01
+ bcs L03E5
+;
+; if(tmp16 == uip_listenports[c])
+;
+ lda _tmp16
+ ldx _tmp16+1
+ jsr pushax
+ ldx #$00
+ lda _c
+ jsr aslax1
+ clc
+ adc #<(_uip_listenports)
+ tay
+ txa
+ adc #>(_uip_listenports)
+ tax
+ tya
+ jsr ldaxi
+ jsr tosicmp
+;
+; goto found_listen;
+;
+ jeq L03F5
+;
+; for(c = 0; c < UIP_LISTENPORTS; ++c) {
+;
+ inc _c
+ jmp L03EA
+;
+; if(BUF->flags & TCP_RST) {
+;
+L03E5: lda _uip_buf+33
+ and #$04
+;
+; goto drop;
+;
+ jne L01EA
+;
+; BUF->flags = TCP_RST | TCP_ACK;
+;
+ lda #$14
+ sta _uip_buf+33
+;
+; uip_len = UIP_IPTCPH_LEN;
+;
+ ldx #$00
+ lda #$28
+ sta _uip_len
+ stx _uip_len+1
+;
+; BUF->tcpoffset = 5 << 4;
+;
+ lda #$50
+ sta _uip_buf+32
+;
+; c = BUF->seqno[3];
+;
+ lda _uip_buf+27
+ sta _c
+;
+; BUF->seqno[3] = BUF->ackno[3];
+;
+ lda _uip_buf+31
+ sta _uip_buf+27
+;
+; BUF->ackno[3] = c;
+;
+ lda _c
+ sta _uip_buf+31
+;
+; c = BUF->seqno[2];
+;
+ lda _uip_buf+26
+ sta _c
+;
+; BUF->seqno[2] = BUF->ackno[2];
+;
+ lda _uip_buf+30
+ sta _uip_buf+26
+;
+; BUF->ackno[2] = c;
+;
+ lda _c
+ sta _uip_buf+30
+;
+; c = BUF->seqno[1];
+;
+ lda _uip_buf+25
+ sta _c
+;
+; BUF->seqno[1] = BUF->ackno[1];
+;
+ lda _uip_buf+29
+ sta _uip_buf+25
+;
+; BUF->ackno[1] = c;
+;
+ lda _c
+ sta _uip_buf+29
+;
+; c = BUF->seqno[0];
+;
+ lda _uip_buf+24
+ sta _c
+;
+; BUF->seqno[0] = BUF->ackno[0];
+;
+ lda _uip_buf+28
+ sta _uip_buf+24
+;
+; BUF->ackno[0] = c;
+;
+ lda _c
+ sta _uip_buf+28
+;
+; if(++BUF->ackno[3] == 0) {
+;
+ inc _uip_buf+31
+ lda _uip_buf+31
+ bne L044D
+;
+; if(++BUF->ackno[2] == 0) {
+;
+ inc _uip_buf+30
+ lda _uip_buf+30
+ bne L044D
+;
+; if(++BUF->ackno[1] == 0) {
+;
+ inc _uip_buf+29
+ lda _uip_buf+29
+ bne L044D
+;
+; ++BUF->ackno[0];
+;
+ inc _uip_buf+28
+;
+; tmp16 = BUF->srcport;
+;
+L044D: lda _uip_buf+20
+ sta _tmp16
+ lda _uip_buf+20+1
+ sta _tmp16+1
+;
+; BUF->srcport = BUF->destport;
+;
+ lda _uip_buf+22
+ sta _uip_buf+20
+ lda _uip_buf+22+1
+ sta _uip_buf+20+1
+;
+; BUF->destport = tmp16;
+;
+ lda _tmp16
+ sta _uip_buf+22
+ lda _tmp16+1
+ sta _uip_buf+22+1
+;
+; uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
+;
+ lda #<(_uip_buf+16)
+ sta sreg
+ lda #>(_uip_buf+16)
+ sta sreg+1
+ lda #<(_uip_buf+12)
+ ldx #>(_uip_buf+12)
+ jsr ldaxi
+ ldy #$00
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+ lda #<(_uip_buf+16)
+ sta sreg
+ lda #>(_uip_buf+16)
+ sta sreg+1
+ lda #<(_uip_buf+12)
+ ldx #>(_uip_buf+12)
+ ldy #$03
+ jsr ldaxidx
+ ldy #$02
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+;
+ lda #<(_uip_buf+12)
+ sta sreg
+ lda #>(_uip_buf+12)
+ sta sreg+1
+ lda #<(_uip_hostaddr)
+ ldx #>(_uip_hostaddr)
+ jsr ldaxi
+ ldy #$00
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+ lda #<(_uip_buf+12)
+ sta sreg
+ lda #>(_uip_buf+12)
+ sta sreg+1
+ lda #<(_uip_hostaddr)
+ ldx #>(_uip_hostaddr)
+ ldy #$03
+ jsr ldaxidx
+ ldy #$02
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; goto tcp_send_noconn;
+;
+ jmp L049A
+;
+; uip_connr = 0;
+;
+L03F5: ldx #$00
+ txa
+ jsr stax0sp
+;
+; for(c = 0; c < UIP_CONNS; ++c) {
+;
+ sta _c
+L049D: lda _c
+ cmp #$01
+ jcs L049E
+;
+; if(uip_conns[c].tcpstateflags == UIP_CLOSED) {
+;
+ lda _c
+ jsr pusha0
+ lda #$23
+ jsr tosmula0
+ clc
+ adc #<(_uip_conns)
+ sta ptr1
+ txa
+ adc #>(_uip_conns)
+ sta ptr1+1
+ ldy #$19
+ lda (ptr1),y
+ bne L04A5
+;
+; uip_connr = &uip_conns[c];
+;
+ lda _c
+ jsr pusha0
+ lda #$23
+ jsr tosmula0
+ clc
+ adc #<(_uip_conns)
+ tay
+ txa
+ adc #>(_uip_conns)
+ tax
+ tya
+ jsr stax0sp
+;
+; break;
+;
+ jmp L049E
+;
+; if(uip_conns[c].tcpstateflags == UIP_TIME_WAIT) {
+;
+L04A5: lda _c
+ jsr pusha0
+ lda #$23
+ jsr tosmula0
+ clc
+ adc #<(_uip_conns)
+ sta ptr1
+ txa
+ adc #>(_uip_conns)
+ sta ptr1+1
+ ldy #$19
+ lda (ptr1),y
+ cmp #$07
+ bne L049F
+;
+; if(uip_connr == 0 ||
+;
+ ldy #$00
+ lda (sp),y
+ iny
+ ora (sp),y
+ beq L04AF
+;
+; uip_conns[c].timer > uip_connr->timer) {
+;
+ lda _c
+ jsr pusha0
+ lda #$23
+ jsr tosmula0
+ clc
+ adc #<(_uip_conns)
+ sta ptr1
+ txa
+ adc #>(_uip_conns)
+ sta ptr1+1
+ ldy #$1A
+ lda (ptr1),y
+ jsr pusha0
+ ldy #$03
+ jsr ldaxysp
+ ldy #$1A
+ sta ptr1
+ stx ptr1+1
+ ldx #$00
+ lda (ptr1),y
+ jsr tosicmp
+ beq L049F
+ bcc L049F
+;
+; uip_connr = &uip_conns[c];
+;
+L04AF: lda _c
+ jsr pusha0
+ lda #$23
+ jsr tosmula0
+ clc
+ adc #<(_uip_conns)
+ tay
+ txa
+ adc #>(_uip_conns)
+ tax
+ tya
+ jsr stax0sp
+;
+; for(c = 0; c < UIP_CONNS; ++c) {
+;
+L049F: inc _c
+ jmp L049D
+;
+; if(uip_connr == 0) {
+;
+L049E: ldy #$00
+ lda (sp),y
+ iny
+ ora (sp),y
+;
+; goto drop;
+;
+ jeq L01EA
+;
+; uip_conn = uip_connr;
+;
+ jsr ldax0sp
+ sta _uip_conn
+ stx _uip_conn+1
+;
+; uip_connr->rto = uip_connr->timer = UIP_RTO;
+;
+ jsr ldax0sp
+ sta ptr1
+ stx ptr1+1
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$03
+ ldy #$1A
+ sta (sreg),y
+ ldy #$18
+ sta (ptr1),y
+;
+; uip_connr->sa = 0;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$16
+ sta (sreg),y
+;
+; uip_connr->sv = 4;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$04
+ ldy #$17
+ sta (sreg),y
+;
+; uip_connr->nrtx = 0;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$1B
+ sta (sreg),y
+;
+; uip_connr->lport = BUF->destport;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _uip_buf+22
+ ldx _uip_buf+22+1
+ ldy #$04
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; uip_connr->rport = BUF->srcport;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _uip_buf+20
+ ldx _uip_buf+20+1
+ ldy #$06
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; uip_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr);
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #<(_uip_buf+12)
+ ldx #>(_uip_buf+12)
+ jsr ldaxi
+ ldy #$00
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #<(_uip_buf+12)
+ ldx #>(_uip_buf+12)
+ ldy #$03
+ jsr ldaxidx
+ ldy #$02
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; uip_connr->tcpstateflags = UIP_SYN_RCVD;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$01
+ ldy #$19
+ sta (sreg),y
+;
+; uip_connr->snd_nxt[0] = iss[0];
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _iss
+ ldy #$0C
+ sta (sreg),y
+;
+; uip_connr->snd_nxt[1] = iss[1];
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _iss+1
+ ldy #$0D
+ sta (sreg),y
+;
+; uip_connr->snd_nxt[2] = iss[2];
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _iss+2
+ ldy #$0E
+ sta (sreg),y
+;
+; uip_connr->snd_nxt[3] = iss[3];
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _iss+3
+ ldy #$0F
+ sta (sreg),y
+;
+; uip_connr->len = 1;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$01
+ ldy #$10
+ sta (sreg),y
+ iny
+ lda #$00
+ sta (sreg),y
+;
+; uip_connr->rcv_nxt[3] = BUF->seqno[3];
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _uip_buf+27
+ ldy #$0B
+ sta (sreg),y
+;
+; uip_connr->rcv_nxt[2] = BUF->seqno[2];
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _uip_buf+26
+ ldy #$0A
+ sta (sreg),y
+;
+; uip_connr->rcv_nxt[1] = BUF->seqno[1];
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _uip_buf+25
+ ldy #$09
+ sta (sreg),y
+;
+; uip_connr->rcv_nxt[0] = BUF->seqno[0];
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _uip_buf+24
+ ldy #$08
+ sta (sreg),y
+;
+; uip_add_rcv_nxt(1);
+;
+ jsr push1
+ jsr _uip_add_rcv_nxt
+;
+; if((BUF->tcpoffset & 0xf0) > 0x50) {
+;
+ lda _uip_buf+32
+ and #$F0
+ cmp #$51
+ jcc L0230
+;
+; for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
+;
+ lda #$00
+L088C: sta _c
+L0514: lda _c
+ jsr pusha0
+ lda _uip_buf+32
+ jsr asrax4
+ jsr decax5
+ jsr aslax2
+ jsr tosicmp
+ jcs L0230
+;
+; opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
+;
+ ldx #$00
+ lda _c
+ ldy #$28
+ jsr incaxy
+ clc
+ adc #<(_uip_buf)
+ sta ptr1
+ txa
+ adc #>(_uip_buf)
+ sta ptr1+1
+ ldy #$00
+ lda (ptr1),y
+ sta _opt
+;
+; if(opt == TCP_OPT_END) {
+;
+ lda _opt
+;
+; break;
+;
+ jeq L0230
+;
+; } else if(opt == TCP_OPT_NOOP) {
+;
+ lda _opt
+ cmp #$01
+ bne L0526
+;
+; ++c;
+;
+ inc _c
+;
+; } else if(opt == TCP_OPT_MSS &&
+;
+ jmp L0514
+L0526: lda _opt
+ cmp #$02
+ jne L052A
+;
+; uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
+;
+ ldx #$00
+ lda _c
+ ldy #$29
+ jsr incaxy
+ clc
+ adc #<(_uip_buf)
+ sta ptr1
+ txa
+ adc #>(_uip_buf)
+ sta ptr1+1
+ ldy #$00
+ lda (ptr1),y
+ cmp #$04
+ bne L052A
+;
+; tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
+;
+ ldx #$00
+ lda _c
+ ldy #$2A
+ jsr incaxy
+ clc
+ adc #<(_uip_buf)
+ sta ptr1
+ txa
+ adc #>(_uip_buf)
+ sta ptr1+1
+ ldy #$00
+ lda (ptr1),y
+ tax
+ tya
+;
+; (u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];
+;
+ jsr pushax
+ tax
+ lda _c
+ ldy #$2B
+ jsr incaxy
+ clc
+ adc #<(_uip_buf)
+ sta ptr1
+ txa
+ adc #>(_uip_buf)
+ sta ptr1+1
+ ldy #$00
+ ldx #$00
+ lda (ptr1),y
+ jsr tosorax
+ sta _tmp16
+ stx _tmp16+1
+;
+; uip_connr->initialmss = uip_connr->mss =
+;
+ jsr pushw0sp
+ ldy #$05
+;
+; tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
+;
+ jsr pushwysp
+ lda _tmp16+1
+ cmp #$00
+ bne L053C
+ lda _tmp16
+ cmp #$79
+L053C: bcc L053D
+ ldx #$00
+ lda #$78
+ jmp L0541
+L053D: lda _tmp16
+ ldx _tmp16+1
+L0541: ldy #$12
+ jsr staxspidx
+ ldy #$14
+ jsr staxspidx
+;
+; break;
+;
+ jmp L0230
+;
+; if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
+;
+L052A: ldx #$00
+ lda _c
+ ldy #$29
+ jsr incaxy
+ clc
+ adc #<(_uip_buf)
+ sta ptr1
+ txa
+ adc #>(_uip_buf)
+ sta ptr1+1
+ ldy #$00
+ lda (ptr1),y
+;
+; break;
+;
+ beq L0230
+;
+; c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
+;
+ ldx #$00
+ lda _c
+ ldy #$29
+ jsr incaxy
+ clc
+ adc #<(_uip_buf)
+ sta ptr1
+ txa
+ adc #>(_uip_buf)
+ sta ptr1+1
+ ldy #$00
+ lda (ptr1),y
+ clc
+ adc _c
+;
+; }
+;
+ jmp L088C
+;
+; BUF->flags = TCP_ACK;
+;
+L0230: lda #$10
+L088A: sta _uip_buf+33
+;
+; BUF->flags |= TCP_SYN;
+;
+ ora #$02
+ sta _uip_buf+33
+;
+; BUF->optdata[0] = TCP_OPT_MSS;
+;
+ lda #$02
+ sta _uip_buf+40
+;
+; BUF->optdata[1] = TCP_OPT_MSS_LEN;
+;
+ lda #$04
+ sta _uip_buf+41
+;
+; BUF->optdata[2] = (UIP_TCP_MSS) / 256;
+;
+ lda #$00
+ sta _uip_buf+42
+;
+; BUF->optdata[3] = (UIP_TCP_MSS) & 255;
+;
+ lda #$78
+ sta _uip_buf+43
+;
+; uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN;
+;
+ ldx #$00
+ lda #$2C
+ sta _uip_len
+ stx _uip_len+1
+;
+; BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4;
+;
+ lda #$60
+;
+; goto tcp_send;
+;
+ jmp L088D
+;
+; uip_conn = uip_connr;
+;
+L03DE: jsr ldax0sp
+ sta _uip_conn
+ stx _uip_conn+1
+;
+; uip_flags = 0;
+;
+ lda #$00
+ sta _uip_flags
+;
+; if(BUF->flags & TCP_RST) {
+;
+ lda _uip_buf+33
+ and #$04
+ beq L057D
+;
+; uip_connr->tcpstateflags = UIP_CLOSED;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$19
+ sta (sreg),y
+;
+; uip_flags = UIP_ABORT;
+;
+ lda #$20
+ sta _uip_flags
+;
+; UIP_APPCALL();
+;
+ jsr _telnet_app
+;
+; goto drop;
+;
+ jmp L01EA
+;
+; c = (BUF->tcpoffset >> 4) << 2;
+;
+L057D: tax
+ lda _uip_buf+32
+ jsr asrax4
+ asl a
+ asl a
+ sta _c
+;
+; uip_len = uip_len - c - UIP_IPH_LEN;
+;
+ lda _uip_len
+ ldx _uip_len+1
+ jsr pushax
+ lda _c
+ jsr tossuba0
+ ldy #$14
+ jsr decaxy
+ sta _uip_len
+ stx _uip_len+1
+;
+; if(!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) &&
+;
+ jsr ldax0sp
+ ldy #$19
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ and #$0F
+ cmp #$02
+ bne L0593
+;
+; ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) {
+;
+ lda _uip_buf+33
+ and #$3F
+ cmp #$12
+ beq L058F
+L0593: lda #$00
+ jmp L059A
+L058F: lda #$01
+L059A: jsr bnega
+ jeq L058D
+;
+; if((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
+;
+ lda _uip_len
+ ora _uip_len+1
+ bne L059D
+ lda _uip_buf+33
+ and #$03
+ beq L058D
+;
+; (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
+;
+L059D: lda _uip_buf+24
+ jsr pusha0
+ ldy #$03
+ jsr ldaxysp
+ ldy #$08
+ sta ptr1
+ stx ptr1+1
+ ldx #$00
+ lda (ptr1),y
+ jsr tosicmp
+ jne L05BA
+;
+; BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
+;
+ lda _uip_buf+25
+ jsr pusha0
+ ldy #$03
+ jsr ldaxysp
+ ldy #$09
+ sta ptr1
+ stx ptr1+1
+ ldx #$00
+ lda (ptr1),y
+ jsr tosicmp
+ jne L05BA
+;
+; BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
+;
+ lda _uip_buf+26
+ jsr pusha0
+ ldy #$03
+ jsr ldaxysp
+ ldy #$0A
+ sta ptr1
+ stx ptr1+1
+ ldx #$00
+ lda (ptr1),y
+ jsr tosicmp
+ jne L05BA
+;
+; BUF->seqno[3] != uip_connr->rcv_nxt[3])) {
+;
+ lda _uip_buf+27
+ jsr pusha0
+ ldy #$03
+ jsr ldaxysp
+ ldy #$0B
+ sta ptr1
+ stx ptr1+1
+ ldx #$00
+ lda (ptr1),y
+ jsr tosicmp
+ jne L05BA
+;
+; if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) {
+;
+L058D: lda _uip_buf+33
+ and #$10
+ jeq L05C7
+ jsr ldax0sp
+ ldy #$10
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ iny
+ ora (ptr1),y
+ jeq L05C7
+;
+; uip_add32(uip_connr->snd_nxt, uip_connr->len);
+;
+ jsr ldax0sp
+ ldy #$0C
+ jsr incaxy
+ jsr pushax
+ ldy #$03
+ jsr ldaxysp
+ ldy #$11
+ jsr pushwidx
+ jsr _uip_add32
+;
+; if(BUF->ackno[0] == uip_acc32[0] &&
+;
+ lda _uip_buf+28
+ jsr pusha0
+ lda _uip_acc32
+ jsr tosicmp
+ jne L05C7
+;
+; BUF->ackno[1] == uip_acc32[1] &&
+;
+ lda _uip_buf+29
+ jsr pusha0
+ lda _uip_acc32+1
+ jsr tosicmp
+ jne L05C7
+;
+; BUF->ackno[2] == uip_acc32[2] &&
+;
+ lda _uip_buf+30
+ jsr pusha0
+ lda _uip_acc32+2
+ jsr tosicmp
+ jne L05C7
+;
+; BUF->ackno[3] == uip_acc32[3]) {
+;
+ lda _uip_buf+31
+ jsr pusha0
+ lda _uip_acc32+3
+ jsr tosicmp
+ jne L05C7
+;
+; uip_connr->snd_nxt[0] = uip_acc32[0];
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _uip_acc32
+ ldy #$0C
+ sta (sreg),y
+;
+; uip_connr->snd_nxt[1] = uip_acc32[1];
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _uip_acc32+1
+ ldy #$0D
+ sta (sreg),y
+;
+; uip_connr->snd_nxt[2] = uip_acc32[2];
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _uip_acc32+2
+ ldy #$0E
+ sta (sreg),y
+;
+; uip_connr->snd_nxt[3] = uip_acc32[3];
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _uip_acc32+3
+ ldy #$0F
+ sta (sreg),y
+;
+; if(uip_connr->nrtx == 0) {
+;
+ jsr ldax0sp
+ ldy #$1B
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ jne L05EB
+;
+; m = uip_connr->rto - uip_connr->timer;
+;
+ jsr decsp1
+ ldy #$02
+ jsr ldaxysp
+ ldy #$18
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ jsr pusha0
+ ldy #$04
+ jsr ldaxysp
+ ldy #$1A
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ jsr tossuba0
+ ldy #$00
+ sta (sp),y
+;
+; m = m - (uip_connr->sa >> 3);
+;
+ ldx #$00
+ lda (sp),y
+ bpl L05F1
+ dex
+L05F1: jsr pushax
+ ldy #$04
+ jsr ldaxysp
+ ldy #$16
+ sta ptr1
+ stx ptr1+1
+ ldx #$00
+ lda (ptr1),y
+ jsr asrax3
+ jsr tossubax
+ ldy #$00
+ sta (sp),y
+;
+; uip_connr->sa += m;
+;
+ ldy #$02
+ jsr ldaxysp
+ sta ptr2
+ stx ptr2+1
+ ldy #$16
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta sreg
+ ldy #$00
+ lda (sp),y
+ clc
+ adc sreg
+ ldy #$16
+ sta (ptr2),y
+;
+; if(m < 0) {
+;
+ ldy #$00
+ lda (sp),y
+ tax
+ bpl L05F6
+;
+; m = -m;
+;
+ ldx #$00
+ lda (sp),y
+ bpl L05FB
+ dex
+L05FB: jsr negax
+ sta (sp),y
+;
+; m = m - (uip_connr->sv >> 2);
+;
+L05F6: ldx #$00
+ lda (sp),y
+ bpl L05FE
+ dex
+L05FE: jsr pushax
+ ldy #$04
+ jsr ldaxysp
+ ldy #$17
+ sta ptr1
+ stx ptr1+1
+ ldx #$00
+ lda (ptr1),y
+ jsr asrax2
+ jsr tossubax
+ ldy #$00
+ sta (sp),y
+;
+; uip_connr->sv += m;
+;
+ ldy #$02
+ jsr ldaxysp
+ sta ptr2
+ stx ptr2+1
+ ldy #$17
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta sreg
+ ldy #$00
+ lda (sp),y
+ clc
+ adc sreg
+ ldy #$17
+ sta (ptr2),y
+;
+; uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;
+;
+ ldy #$04
+ jsr pushwysp
+ ldy #$04
+ jsr ldaxysp
+ ldy #$16
+ sta ptr1
+ stx ptr1+1
+ ldx #$00
+ lda (ptr1),y
+ jsr asrax3
+ sta sreg
+ ldy #$04
+ jsr ldaxysp
+ ldy #$17
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ clc
+ adc sreg
+ iny
+ jsr staspidx
+;
+; }
+;
+ jsr incsp1
+;
+; uip_flags = UIP_ACKDATA;
+;
+L05EB: lda #$01
+ sta _uip_flags
+;
+; uip_connr->timer = uip_connr->rto;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ jsr ldax0sp
+ ldy #$18
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ ldy #$1A
+ sta (sreg),y
+;
+; uip_connr->len = 0;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$10
+ sta (sreg),y
+ iny
+ sta (sreg),y
+;
+; switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
+;
+L05C7: jsr ldax0sp
+ ldy #$19
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ and #$0F
+;
+; goto drop;
+;
+ cmp #$01
+ beq L0610
+ cmp #$02
+ beq L0624
+ cmp #$03
+ jeq L0699
+ cmp #$04
+ jeq L0746
+ cmp #$05
+ jeq L076B
+ cmp #$06
+ jeq L0784
+ cmp #$07
+ jeq L05BA
+ cmp #$08
+ jeq L073D
+ jmp L01EA
+;
+; if(uip_flags & UIP_ACKDATA) {
+;
+L0610: lda _uip_flags
+ and #$01
+ jeq L01EA
+;
+; uip_connr->tcpstateflags = UIP_ESTABLISHED;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$03
+ ldy #$19
+ sta (sreg),y
+;
+; uip_flags = UIP_CONNECTED;
+;
+ lda #$40
+ sta _uip_flags
+;
+; uip_connr->len = 0;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$10
+ sta (sreg),y
+ iny
+ sta (sreg),y
+;
+; if(uip_len > 0) {
+;
+ lda _uip_len
+ ora _uip_len+1
+ jeq L089D
+;
+; uip_flags |= UIP_NEWDATA;
+;
+ lda _uip_flags
+ ora #$02
+ sta _uip_flags
+;
+; uip_add_rcv_nxt(uip_len);
+;
+ lda _uip_len
+ ldx _uip_len+1
+ jsr pushax
+ jsr _uip_add_rcv_nxt
+;
+; goto appsend;
+;
+ jmp L089D
+;
+; if((uip_flags & UIP_ACKDATA) &&
+;
+L0624: lda _uip_flags
+ and #$01
+ jeq L0625
+;
+; (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) {
+;
+ lda _uip_buf+33
+ and #$3F
+ cmp #$12
+ jne L0625
+;
+; if((BUF->tcpoffset & 0xf0) > 0x50) {
+;
+ lda _uip_buf+32
+ and #$F0
+ cmp #$51
+ jcc L0636
+;
+; for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
+;
+ lda #$00
+L088E: sta _c
+L0635: lda _c
+ jsr pusha0
+ lda _uip_buf+32
+ jsr asrax4
+ jsr decax5
+ jsr aslax2
+ jsr tosicmp
+ jcs L0636
+;
+; opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c];
+;
+ ldx #$00
+ lda _c
+ ldy #$28
+ jsr incaxy
+ clc
+ adc #<(_uip_buf)
+ sta ptr1
+ txa
+ adc #>(_uip_buf)
+ sta ptr1+1
+ ldy #$00
+ lda (ptr1),y
+ sta _opt
+;
+; if(opt == TCP_OPT_END) {
+;
+ lda _opt
+;
+; break;
+;
+ jeq L0636
+;
+; } else if(opt == TCP_OPT_NOOP) {
+;
+ lda _opt
+ cmp #$01
+ bne L0647
+;
+; ++c;
+;
+ inc _c
+;
+; } else if(opt == TCP_OPT_MSS &&
+;
+ jmp L0635
+L0647: lda _opt
+ cmp #$02
+ jne L064B
+;
+; uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
+;
+ ldx #$00
+ lda _c
+ ldy #$29
+ jsr incaxy
+ clc
+ adc #<(_uip_buf)
+ sta ptr1
+ txa
+ adc #>(_uip_buf)
+ sta ptr1+1
+ ldy #$00
+ lda (ptr1),y
+ cmp #$04
+ bne L064B
+;
+; tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
+;
+ ldx #$00
+ lda _c
+ ldy #$2A
+ jsr incaxy
+ clc
+ adc #<(_uip_buf)
+ sta ptr1
+ txa
+ adc #>(_uip_buf)
+ sta ptr1+1
+ ldy #$00
+ lda (ptr1),y
+ tax
+ tya
+;
+; uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
+;
+ jsr pushax
+ tax
+ lda _c
+ ldy #$2B
+ jsr incaxy
+ clc
+ adc #<(_uip_buf)
+ sta ptr1
+ txa
+ adc #>(_uip_buf)
+ sta ptr1+1
+ ldy #$00
+ ldx #$00
+ lda (ptr1),y
+ jsr tosorax
+ sta _tmp16
+ stx _tmp16+1
+;
+; uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
+;
+ jsr pushw0sp
+ ldy #$05
+ jsr pushwysp
+ lda _tmp16+1
+ cmp #$00
+ bne L065D
+ lda _tmp16
+ cmp #$79
+L065D: bcc L065E
+ ldx #$00
+ lda #$78
+ jmp L0662
+L065E: lda _tmp16
+ ldx _tmp16+1
+L0662: ldy #$12
+ jsr staxspidx
+ ldy #$14
+ jsr staxspidx
+;
+; break;
+;
+ jmp L0636
+;
+; if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
+;
+L064B: ldx #$00
+ lda _c
+ ldy #$29
+ jsr incaxy
+ clc
+ adc #<(_uip_buf)
+ sta ptr1
+ txa
+ adc #>(_uip_buf)
+ sta ptr1+1
+ ldy #$00
+ lda (ptr1),y
+;
+; break;
+;
+ beq L0636
+;
+; c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
+;
+ ldx #$00
+ lda _c
+ ldy #$29
+ jsr incaxy
+ clc
+ adc #<(_uip_buf)
+ sta ptr1
+ txa
+ adc #>(_uip_buf)
+ sta ptr1+1
+ ldy #$00
+ lda (ptr1),y
+ clc
+ adc _c
+;
+; }
+;
+ jmp L088E
+;
+; uip_connr->tcpstateflags = UIP_ESTABLISHED;
+;
+L0636: jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$03
+ ldy #$19
+ sta (sreg),y
+;
+; uip_connr->rcv_nxt[0] = BUF->seqno[0];
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _uip_buf+24
+ ldy #$08
+ sta (sreg),y
+;
+; uip_connr->rcv_nxt[1] = BUF->seqno[1];
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _uip_buf+25
+ ldy #$09
+ sta (sreg),y
+;
+; uip_connr->rcv_nxt[2] = BUF->seqno[2];
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _uip_buf+26
+ ldy #$0A
+ sta (sreg),y
+;
+; uip_connr->rcv_nxt[3] = BUF->seqno[3];
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _uip_buf+27
+ ldy #$0B
+ sta (sreg),y
+;
+; uip_add_rcv_nxt(1);
+;
+ jsr push1
+ jsr _uip_add_rcv_nxt
+;
+; uip_flags = UIP_CONNECTED | UIP_NEWDATA;
+;
+ lda #$42
+ sta _uip_flags
+;
+; uip_connr->len = 0;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$10
+ sta (sreg),y
+ iny
+ sta (sreg),y
+;
+; uip_len = 0;
+;
+ sta _uip_len
+ sta _uip_len+1
+;
+; goto appsend;
+;
+ jmp L089B
+;
+; uip_flags = UIP_ABORT;
+;
+L0625: lda #$20
+ sta _uip_flags
+;
+; UIP_APPCALL();
+;
+ jsr _telnet_app
+;
+; uip_conn->tcpstateflags = UIP_CLOSED;
+;
+ lda _uip_conn
+ sta sreg
+ lda _uip_conn+1
+ sta sreg+1
+ lda #$00
+ ldy #$19
+ sta (sreg),y
+;
+; goto reset;
+;
+ jmp L03E5
+;
+; if(BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
+;
+L0699: lda _uip_buf+33
+ and #$01
+ beq L069A
+ jsr ldax0sp
+ ldy #$19
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ and #$10
+ bne L069A
+;
+; if(uip_outstanding(uip_connr)) {
+;
+ jsr ldax0sp
+ ldy #$10
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ iny
+ ora (ptr1),y
+;
+; goto drop;
+;
+ jne L01EA
+;
+; uip_add_rcv_nxt(1 + uip_len);
+;
+ lda _uip_len
+ ldx _uip_len+1
+ jsr incax1
+ jsr pushax
+ jsr _uip_add_rcv_nxt
+;
+; uip_flags |= UIP_CLOSE;
+;
+ lda _uip_flags
+ ora #$10
+ sta _uip_flags
+;
+; if(uip_len > 0) {
+;
+ lda _uip_len
+ ora _uip_len+1
+ beq L06A9
+;
+; uip_flags |= UIP_NEWDATA;
+;
+ lda _uip_flags
+ ora #$02
+ sta _uip_flags
+;
+; UIP_APPCALL();
+;
+L06A9: jsr _telnet_app
+;
+; uip_connr->len = 1;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$01
+ ldy #$10
+ sta (sreg),y
+ iny
+ lda #$00
+ sta (sreg),y
+;
+; uip_connr->tcpstateflags = UIP_LAST_ACK;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$08
+ ldy #$19
+ sta (sreg),y
+;
+; uip_connr->nrtx = 0;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$1B
+ sta (sreg),y
+;
+; BUF->flags = TCP_FIN | TCP_ACK;
+;
+L0244: lda #$11
+;
+; goto tcp_send_nodata;
+;
+ jmp L0889
+;
+; if((BUF->flags & TCP_URG) != 0) {
+;
+L069A: lda _uip_buf+33
+ and #$20
+ beq L06B9
+;
+; uip_appdata = ((char *)uip_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]);
+;
+ lda _uip_appdata
+ sta ptr1
+ lda _uip_appdata+1
+ sta ptr1+1
+ ldx _uip_buf+38
+ stx sreg+1
+ ldx #$00
+ lda _uip_buf+39
+ sta sreg
+ txa
+ ora sreg+1
+ tax
+ lda sreg
+ clc
+ adc ptr1
+ sta ptr1
+ txa
+ adc ptr1+1
+ tax
+ lda ptr1
+ sta _uip_appdata
+ stx _uip_appdata+1
+;
+; uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1];
+;
+ ldx _uip_buf+38
+ stx sreg+1
+ ldx #$00
+ lda _uip_buf+39
+ sta sreg
+ txa
+ ora sreg+1
+ tax
+ lda sreg
+ sec
+ eor #$FF
+ adc _uip_len
+ sta _uip_len
+ txa
+ eor #$FF
+ adc _uip_len+1
+ sta _uip_len+1
+;
+; if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
+;
+L06B9: lda _uip_len
+ ora _uip_len+1
+ beq L06D3
+ jsr ldax0sp
+ ldy #$19
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ and #$10
+ bne L06D3
+;
+; uip_flags |= UIP_NEWDATA;
+;
+ lda _uip_flags
+ ora #$02
+ sta _uip_flags
+;
+; uip_add_rcv_nxt(uip_len);
+;
+ lda _uip_len
+ ldx _uip_len+1
+ jsr pushax
+ jsr _uip_add_rcv_nxt
+;
+; tmp16 = ((u16_t)BUF->wnd[0] << 8) + (u16_t)BUF->wnd[1];
+;
+L06D3: ldx _uip_buf+34
+ lda #$00
+ clc
+ adc _uip_buf+35
+ bcc L0880
+ inx
+L0880: sta _tmp16
+ stx _tmp16+1
+;
+; if(tmp16 > uip_connr->initialmss ||
+;
+ jsr pushax
+ ldy #$03
+ jsr ldaxysp
+ ldy #$15
+ jsr ldaxidx
+ jsr tosicmp
+ beq L0894
+ bcs L06E7
+;
+; tmp16 == 0) {
+;
+L0894: lda _tmp16
+ ora _tmp16+1
+ bne L06E6
+;
+; tmp16 = uip_connr->initialmss;
+;
+L06E7: jsr ldax0sp
+ ldy #$15
+ jsr ldaxidx
+ sta _tmp16
+ stx _tmp16+1
+;
+; uip_connr->mss = tmp16;
+;
+L06E6: jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _tmp16
+ ldx _tmp16+1
+ ldy #$12
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) {
+;
+ lda _uip_flags
+ and #$03
+ jeq L01EA
+;
+; uip_slen = 0;
+;
+L089D: lda #$00
+L089B: sta _uip_slen
+ sta _uip_slen+1
+;
+; UIP_APPCALL();
+;
+L0888: jsr _telnet_app
+;
+; if(uip_flags & UIP_ABORT) {
+;
+ lda _uip_flags
+ and #$20
+ beq L06F4
+;
+; uip_slen = 0;
+;
+ lda #$00
+ sta _uip_slen
+ sta _uip_slen+1
+;
+; uip_connr->tcpstateflags = UIP_CLOSED;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$19
+ sta (sreg),y
+;
+; BUF->flags = TCP_RST | TCP_ACK;
+;
+ lda #$14
+;
+; goto tcp_send_nodata;
+;
+ jmp L0889
+;
+; if(uip_flags & UIP_CLOSE) {
+;
+L06F4: lda _uip_flags
+ and #$10
+ beq L06FE
+;
+; uip_slen = 0;
+;
+ lda #$00
+ sta _uip_slen
+ sta _uip_slen+1
+;
+; uip_connr->len = 1;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$01
+ ldy #$10
+ sta (sreg),y
+ iny
+ lda #$00
+ sta (sreg),y
+;
+; uip_connr->tcpstateflags = UIP_FIN_WAIT_1;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$04
+ ldy #$19
+ sta (sreg),y
+;
+; uip_connr->nrtx = 0;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$1B
+ sta (sreg),y
+;
+; BUF->flags = TCP_FIN | TCP_ACK;
+;
+ lda #$11
+;
+; goto tcp_send_nodata;
+;
+ jmp L0889
+;
+; if(uip_slen > 0) {
+;
+L06FE: lda _uip_slen
+ ora _uip_slen+1
+ beq L071E
+;
+; if((uip_flags & UIP_ACKDATA) != 0) {
+;
+ lda _uip_flags
+ and #$01
+ beq L070F
+;
+; uip_connr->len = 0;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$10
+ sta (sreg),y
+ iny
+ sta (sreg),y
+;
+; if(uip_connr->len == 0) {
+;
+L070F: jsr ldax0sp
+ ldy #$11
+ jsr ldaxidx
+ cpx #$00
+ bne L0715
+ cmp #$00
+ bne L0715
+;
+; if(uip_slen > uip_connr->mss) {
+;
+ lda _uip_slen
+ ldx _uip_slen+1
+ jsr pushax
+ ldy #$03
+ jsr ldaxysp
+ ldy #$13
+ jsr ldaxidx
+ jsr tosicmp
+ bcc L0718
+ beq L0718
+;
+; uip_slen = uip_connr->mss;
+;
+ jsr ldax0sp
+ ldy #$13
+ jsr ldaxidx
+ sta _uip_slen
+ stx _uip_slen+1
+;
+; uip_connr->len = uip_slen;
+;
+L0718: jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda _uip_slen
+ ldx _uip_slen+1
+ ldy #$10
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; } else {
+;
+ jmp L071E
+;
+; uip_slen = uip_connr->len;
+;
+L0715: jsr ldax0sp
+ ldy #$11
+ jsr ldaxidx
+ sta _uip_slen
+ stx _uip_slen+1
+;
+; uip_connr->nrtx = 0;
+;
+L071E: jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$1B
+ sta (sreg),y
+;
+; uip_appdata = uip_sappdata;
+;
+L023D: lda _uip_sappdata
+ sta _uip_appdata
+ lda _uip_sappdata+1
+ sta _uip_appdata+1
+;
+; if(uip_slen > 0 && uip_connr->len > 0) {
+;
+ lda _uip_slen
+ ora _uip_slen+1
+ beq L0725
+ jsr ldax0sp
+ ldy #$11
+ jsr ldaxidx
+ cpx #$00
+ bne L0726
+ cmp #$00
+ beq L0725
+;
+; uip_len = uip_connr->len + UIP_TCPIP_HLEN;
+;
+L0726: jsr ldax0sp
+ ldy #$11
+ jsr ldaxidx
+ ldy #$28
+ jsr incaxy
+ sta _uip_len
+ stx _uip_len+1
+;
+; BUF->flags = TCP_ACK | TCP_PSH;
+;
+ lda #$18
+ sta _uip_buf+33
+;
+; goto tcp_send_noopts;
+;
+ jmp L0732
+;
+; if(uip_flags & UIP_NEWDATA) {
+;
+L0725: lda _uip_flags
+ and #$02
+ jeq L01EA
+;
+; uip_len = UIP_TCPIP_HLEN;
+;
+ ldx #$00
+ lda #$28
+ sta _uip_len
+ stx _uip_len+1
+;
+; BUF->flags = TCP_ACK;
+;
+ lda #$10
+ sta _uip_buf+33
+;
+; goto tcp_send_noopts;
+;
+ jmp L0732
+;
+; if(uip_flags & UIP_ACKDATA) {
+;
+L073D: lda _uip_flags
+ and #$01
+ jeq L01EA
+;
+; uip_connr->tcpstateflags = UIP_CLOSED;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$19
+ sta (sreg),y
+;
+; uip_flags = UIP_CLOSE;
+;
+ lda #$10
+ sta _uip_flags
+;
+; UIP_APPCALL();
+;
+ jsr _telnet_app
+;
+; break;
+;
+ jmp L01EA
+;
+; if(uip_len > 0) {
+;
+L0746: lda _uip_len
+ ora _uip_len+1
+ beq L0747
+;
+; uip_add_rcv_nxt(uip_len);
+;
+ lda _uip_len
+ ldx _uip_len+1
+ jsr pushax
+ jsr _uip_add_rcv_nxt
+;
+; if(BUF->flags & TCP_FIN) {
+;
+L0747: lda _uip_buf+33
+ and #$01
+ beq L074C
+;
+; if(uip_flags & UIP_ACKDATA) {
+;
+ lda _uip_flags
+ and #$01
+ beq L0750
+;
+; uip_connr->tcpstateflags = UIP_TIME_WAIT;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$07
+ ldy #$19
+ sta (sreg),y
+;
+; uip_connr->timer = 0;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$1A
+ sta (sreg),y
+;
+; uip_connr->len = 0;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$10
+ sta (sreg),y
+ iny
+;
+; } else {
+;
+ jmp L088F
+;
+; uip_connr->tcpstateflags = UIP_CLOSING;
+;
+L0750: jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$06
+ ldy #$19
+L088F: sta (sreg),y
+;
+; uip_add_rcv_nxt(1);
+;
+ jsr push1
+ jsr _uip_add_rcv_nxt
+;
+; uip_flags = UIP_CLOSE;
+;
+ lda #$10
+ sta _uip_flags
+;
+; UIP_APPCALL();
+;
+ jsr _telnet_app
+;
+; goto tcp_send_ack;
+;
+ jmp L05BA
+;
+; } else if(uip_flags & UIP_ACKDATA) {
+;
+L074C: lda _uip_flags
+ and #$01
+ beq L0761
+;
+; uip_connr->tcpstateflags = UIP_FIN_WAIT_2;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$05
+ ldy #$19
+ sta (sreg),y
+;
+; uip_connr->len = 0;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$10
+ sta (sreg),y
+ iny
+ sta (sreg),y
+;
+; goto drop;
+;
+ jmp L01EA
+;
+; if(uip_len > 0) {
+;
+L0761: lda _uip_len
+ ora _uip_len+1
+ jeq L01EA
+;
+; goto tcp_send_ack;
+;
+ jmp L05BA
+;
+; if(uip_len > 0) {
+;
+L076B: lda _uip_len
+ ora _uip_len+1
+ beq L076C
+;
+; uip_add_rcv_nxt(uip_len);
+;
+ lda _uip_len
+ ldx _uip_len+1
+ jsr pushax
+ jsr _uip_add_rcv_nxt
+;
+; if(BUF->flags & TCP_FIN) {
+;
+L076C: lda _uip_buf+33
+ and #$01
+ beq L0771
+;
+; uip_connr->tcpstateflags = UIP_TIME_WAIT;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$07
+ ldy #$19
+ sta (sreg),y
+;
+; uip_connr->timer = 0;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$1A
+ sta (sreg),y
+;
+; uip_add_rcv_nxt(1);
+;
+ jsr push1
+ jsr _uip_add_rcv_nxt
+;
+; uip_flags = UIP_CLOSE;
+;
+ lda #$10
+ sta _uip_flags
+;
+; UIP_APPCALL();
+;
+ jsr _telnet_app
+;
+; goto tcp_send_ack;
+;
+ jmp L05BA
+;
+; if(uip_len > 0) {
+;
+L0771: lda _uip_len
+ ora _uip_len+1
+ jeq L01EA
+;
+; goto tcp_send_ack;
+;
+ jmp L05BA
+;
+; if(uip_flags & UIP_ACKDATA) {
+;
+L0784: lda _uip_flags
+ and #$01
+ jeq L01EA
+;
+; uip_connr->tcpstateflags = UIP_TIME_WAIT;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$07
+ ldy #$19
+ sta (sreg),y
+;
+; uip_connr->timer = 0;
+;
+ jsr ldax0sp
+ sta sreg
+ stx sreg+1
+ lda #$00
+ ldy #$1A
+ sta (sreg),y
+;
+; goto drop;
+;
+ jmp L01EA
+;
+; BUF->flags = TCP_ACK;
+;
+L05BA: lda #$10
+L0889: sta _uip_buf+33
+;
+; uip_len = UIP_IPTCPH_LEN;
+;
+ ldx #$00
+ lda #$28
+ sta _uip_len
+ stx _uip_len+1
+;
+; BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4;
+;
+L0732: lda #$50
+L088D: sta _uip_buf+32
+;
+; BUF->ackno[0] = uip_connr->rcv_nxt[0];
+;
+ jsr ldax0sp
+ ldy #$08
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta _uip_buf+28
+;
+; BUF->ackno[1] = uip_connr->rcv_nxt[1];
+;
+ jsr ldax0sp
+ ldy #$09
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta _uip_buf+29
+;
+; BUF->ackno[2] = uip_connr->rcv_nxt[2];
+;
+ jsr ldax0sp
+ ldy #$0A
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta _uip_buf+30
+;
+; BUF->ackno[3] = uip_connr->rcv_nxt[3];
+;
+ jsr ldax0sp
+ ldy #$0B
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta _uip_buf+31
+;
+; BUF->seqno[0] = uip_connr->snd_nxt[0];
+;
+ jsr ldax0sp
+ ldy #$0C
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta _uip_buf+24
+;
+; BUF->seqno[1] = uip_connr->snd_nxt[1];
+;
+ jsr ldax0sp
+ ldy #$0D
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta _uip_buf+25
+;
+; BUF->seqno[2] = uip_connr->snd_nxt[2];
+;
+ jsr ldax0sp
+ ldy #$0E
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta _uip_buf+26
+;
+; BUF->seqno[3] = uip_connr->snd_nxt[3];
+;
+ jsr ldax0sp
+ ldy #$0F
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta _uip_buf+27
+;
+; BUF->proto = UIP_PROTO_TCP;
+;
+ lda #$06
+ sta _uip_buf+9
+;
+; BUF->srcport = uip_connr->lport;
+;
+ jsr ldax0sp
+ ldy #$05
+ jsr ldaxidx
+ sta _uip_buf+20
+ stx _uip_buf+20+1
+;
+; BUF->destport = uip_connr->rport;
+;
+ jsr ldax0sp
+ ldy #$07
+ jsr ldaxidx
+ sta _uip_buf+22
+ stx _uip_buf+22+1
+;
+; uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+;
+ lda #<(_uip_buf+12)
+ sta sreg
+ lda #>(_uip_buf+12)
+ sta sreg+1
+ lda #<(_uip_hostaddr)
+ ldx #>(_uip_hostaddr)
+ jsr ldaxi
+ ldy #$00
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+ lda #<(_uip_buf+12)
+ sta sreg
+ lda #>(_uip_buf+12)
+ sta sreg+1
+ lda #<(_uip_hostaddr)
+ ldx #>(_uip_hostaddr)
+ ldy #$03
+ jsr ldaxidx
+ ldy #$02
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; uip_ipaddr_copy(BUF->destipaddr, uip_connr->ripaddr);
+;
+ lda #<(_uip_buf+16)
+ sta sreg
+ lda #>(_uip_buf+16)
+ sta sreg+1
+ jsr ldax0sp
+ jsr ldaxi
+ ldy #$00
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+ lda #<(_uip_buf+16)
+ sta sreg
+ lda #>(_uip_buf+16)
+ sta sreg+1
+ jsr ldax0sp
+ ldy #$03
+ jsr ldaxidx
+ ldy #$02
+ sta (sreg),y
+ iny
+ txa
+ sta (sreg),y
+;
+; if(uip_connr->tcpstateflags & UIP_STOPPED) {
+;
+ jsr ldax0sp
+ ldy #$19
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ and #$10
+ beq L07FB
+;
+; BUF->wnd[0] = BUF->wnd[1] = 0;
+;
+ lda #$00
+ sta _uip_buf+35
+ sta _uip_buf+34
+;
+; } else {
+;
+ jmp L049A
+;
+; BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);
+;
+L07FB: sta _uip_buf+34
+;
+; BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);
+;
+ lda #$78
+ sta _uip_buf+35
+;
+; BUF->ttl = UIP_TTL;
+;
+L049A: lda #$40
+ sta _uip_buf+8
+;
+; BUF->len[0] = (uip_len >> 8);
+;
+ lda _uip_len+1
+ sta _uip_buf+2
+;
+; BUF->len[1] = (uip_len & 0xff);
+;
+ lda _uip_len
+ sta _uip_buf+3
+;
+; BUF->urgp[0] = BUF->urgp[1] = 0;
+;
+ lda #$00
+ sta _uip_buf+39
+ sta _uip_buf+38
+;
+; BUF->tcpchksum = 0;
+;
+ sta _uip_buf+36
+ sta _uip_buf+36+1
+;
+; BUF->tcpchksum = ~(uip_tcpchksum());
+;
+ jsr _uip_tcpchksum
+ jsr complax
+ sta _uip_buf+36
+ stx _uip_buf+36+1
+;
+; BUF->vhl = 0x45;
+;
+L03B9: lda #$45
+ sta _uip_buf
+;
+; BUF->tos = 0;
+;
+ lda #$00
+ sta _uip_buf+1
+;
+; BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
+;
+ sta _uip_buf+7
+ sta _uip_buf+6
+;
+; ++ipid;
+;
+ inc _ipid
+ bne L084D
+ inc _ipid+1
+;
+; BUF->ipid[0] = ipid >> 8;
+;
+L084D: lda _ipid+1
+ sta _uip_buf+4
+;
+; BUF->ipid[1] = ipid & 0xff;
+;
+ lda _ipid
+ sta _uip_buf+5
+;
+; BUF->ipchksum = 0;
+;
+ lda #$00
+ sta _uip_buf+10
+ sta _uip_buf+10+1
+;
+; BUF->ipchksum = ~(uip_ipchksum());
+;
+ jsr _uip_ipchksum
+ jsr complax
+ sta _uip_buf+10
+ stx _uip_buf+10+1
+;
+; uip_flags = 0;
+;
+L030D: lda #$00
+;
+; return;
+;
+ jmp L0890
+;
+; uip_len = 0;
+;
+L01EA: lda #$00
+ sta _uip_len
+ sta _uip_len+1
+;
+; uip_flags = 0;
+;
+L0890: sta _uip_flags
+;
+; }
+;
+ jmp incsp3
+
+.endproc
+
+; ---------------------------------------------------------------
+; unsigned int __near__ uip_chksum (__near__ unsigned int*, unsigned int)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _uip_chksum: near
+
+.segment "CODE"
+
+;
+; return htons(chksum(0, (u8_t *)data, len));
+;
+ jsr push0
+ ldy #$07
+ jsr pushwysp
+ ldy #$07
+ jsr pushwysp
+ jsr _chksum
+ jsr pushax
+ jsr _htons
+;
+; }
+;
+ jmp incsp4
+
+.endproc
+
+; ---------------------------------------------------------------
+; unsigned int __near__ uip_ipchksum (void)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _uip_ipchksum: near
+
+.segment "CODE"
+
+;
+; sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN);
+;
+ jsr decsp2
+ jsr push0
+ lda #<(_uip_buf)
+ ldx #>(_uip_buf)
+ jsr pushax
+ lda #$14
+ jsr pusha0
+ jsr _chksum
+ jsr stax0sp
+;
+; return (sum == 0) ? 0xffff : htons(sum);
+;
+ cpx #$00
+ bne L0090
+ cmp #$00
+ bne L0090
+ dex
+ txa
+ jmp incsp2
+L0090: jsr pushw0sp
+ jsr _htons
+ jmp incsp2
+
+.endproc
+
+; ---------------------------------------------------------------
+; unsigned int __near__ uip_tcpchksum (void)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _uip_tcpchksum: near
+
+.segment "CODE"
+
+;
+; return upper_layer_chksum(UIP_PROTO_TCP);
+;
+ lda #$06
+ jsr pusha
+ jmp _upper_layer_chksum
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ uip_add32 (__near__ unsigned char*, unsigned int)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _uip_add32: near
+
+.segment "CODE"
+
+;
+; uip_acc32[3] = op32[3] + (op16 & 0xff);
+;
+ ldy #$03
+ jsr ldaxysp
+ ldy #$03
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta sreg
+ ldy #$00
+ lda (sp),y
+ clc
+ adc sreg
+ sta _uip_acc32+3
+;
+; uip_acc32[2] = op32[2] + (op16 >> 8);
+;
+ ldy #$03
+ jsr ldaxysp
+ ldy #$02
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta sreg
+ dey
+ lda (sp),y
+ clc
+ adc sreg
+ sta _uip_acc32+2
+;
+; uip_acc32[1] = op32[1];
+;
+ ldy #$03
+ jsr ldaxysp
+ ldy #$01
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta _uip_acc32+1
+;
+; uip_acc32[0] = op32[0];
+;
+ ldy #$03
+ jsr ldaxysp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ sta _uip_acc32
+;
+; if(uip_acc32[2] < (op16 >> 8)) {
+;
+ lda _uip_acc32+2
+ jsr pusha0
+ ldy #$03
+ lda (sp),y
+ jsr tosicmp
+ bcs L0045
+;
+; ++uip_acc32[1];
+;
+ inc _uip_acc32+1
+;
+; if(uip_acc32[1] == 0) {
+;
+ lda _uip_acc32+1
+ bne L0045
+;
+; ++uip_acc32[0];
+;
+ inc _uip_acc32
+;
+; if(uip_acc32[3] < (op16 & 0xff)) {
+;
+L0045: lda _uip_acc32+3
+ jsr pusha0
+ ldy #$02
+ lda (sp),y
+ jsr tosicmp
+ jcs incsp4
+;
+; ++uip_acc32[2];
+;
+ inc _uip_acc32+2
+;
+; if(uip_acc32[2] == 0) {
+;
+ lda _uip_acc32+2
+ jne incsp4
+;
+; ++uip_acc32[1];
+;
+ inc _uip_acc32+1
+;
+; if(uip_acc32[1] == 0) {
+;
+ lda _uip_acc32+1
+ jne incsp4
+;
+; ++uip_acc32[0];
+;
+ inc _uip_acc32
+;
+; }
+;
+ jmp incsp4
+
+.endproc
+
+; ---------------------------------------------------------------
+; unsigned int __near__ chksum (unsigned int, __near__ const unsigned char*, unsigned int)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _chksum: near
+
+.segment "CODE"
+
+;
+; dataptr = data;
+;
+ jsr decsp6
+ ldy #$09
+ jsr ldaxysp
+ ldy #$02
+ jsr staxysp
+;
+; last_byte = data + len - 1;
+;
+ ldy #$09
+ jsr ldaxysp
+ sta sreg
+ stx sreg+1
+ ldy #$07
+ jsr ldaxysp
+ clc
+ adc sreg
+ sta sreg
+ txa
+ adc sreg+1
+ tax
+ lda sreg
+ jsr decax1
+ jsr stax0sp
+;
+; while(dataptr < last_byte) { /* At least two more bytes */
+;
+L0065: ldy #$05
+ jsr pushwysp
+ ldy #$03
+ jsr ldaxysp
+ jsr tosicmp
+ bcs L0066
+;
+; t = (dataptr[0] << 8) + dataptr[1];
+;
+ ldy #$03
+ jsr ldaxysp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ tax
+ stx sreg+1
+ ldy #$03
+ jsr ldaxysp
+ ldy #$01
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ clc
+ adc #$00
+ ldx sreg+1
+ bcc L08A2
+ inx
+L08A2: ldy #$04
+ jsr staxysp
+;
+; sum += t;
+;
+ ldy #$0A
+ jsr addeqysp
+;
+; if(sum < t) {
+;
+ ldy #$0D
+ jsr pushwysp
+ ldy #$07
+ jsr ldaxysp
+ jsr tosicmp
+ bcs L006F
+;
+; sum++; /* carry */
+;
+ ldy #$0B
+ jsr ldaxysp
+ jsr incax1
+ ldy #$0A
+ jsr staxysp
+;
+; dataptr += 2;
+;
+L006F: ldy #$02
+ ldx #$00
+ tya
+ jsr addeqysp
+;
+; }
+;
+ jmp L0065
+;
+; if(dataptr == last_byte) {
+;
+L0066: ldy #$05
+ jsr pushwysp
+ ldy #$03
+ jsr ldaxysp
+ jsr tosicmp
+ bne L007C
+;
+; t = (dataptr[0] << 8) + 0;
+;
+ ldy #$03
+ jsr ldaxysp
+ ldy #$00
+ sta ptr1
+ stx ptr1+1
+ lda (ptr1),y
+ tax
+ tya
+ ldy #$04
+ jsr staxysp
+;
+; sum += t;
+;
+ ldy #$0A
+ jsr addeqysp
+;
+; if(sum < t) {
+;
+ ldy #$0D
+ jsr pushwysp
+ ldy #$07
+ jsr ldaxysp
+ jsr tosicmp
+ bcs L007C
+;
+; sum++; /* carry */
+;
+ ldy #$0B
+ jsr ldaxysp
+ jsr incax1
+ ldy #$0A
+ jsr staxysp
+;
+; return sum;
+;
+L007C: ldy #$0B
+ jsr ldaxysp
+;
+; }
+;
+ ldy #$0C
+ jmp addysp
+
+.endproc
+
+; ---------------------------------------------------------------
+; unsigned int __near__ upper_layer_chksum (unsigned char)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _upper_layer_chksum: near
+
+.segment "CODE"
+
+;
+; upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN;
+;
+ jsr decsp4
+ ldx _uip_buf+2
+ lda #$00
+ clc
+ adc _uip_buf+3
+ bcc L08A3
+ inx
+L08A3: ldy #$14
+ jsr decaxy
+ ldy #$02
+ jsr staxysp
+;
+; sum = upper_layer_len + proto;
+;
+ sta sreg
+ stx sreg+1
+ ldy #$04
+ lda (sp),y
+ clc
+ adc sreg
+ ldx sreg+1
+ bcc L08A4
+ inx
+L08A4: jsr stax0sp
+;
+; sum = chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t));
+;
+ jsr pushax
+ lda #<(_uip_buf+12)
+ ldx #>(_uip_buf+12)
+ jsr pushax
+ lda #$08
+ jsr pusha0
+ jsr _chksum
+ jsr stax0sp
+;
+; sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN],
+;
+ jsr pushax
+ lda #<(_uip_buf+20)
+ ldx #>(_uip_buf+20)
+ jsr pushax
+;
+; upper_layer_len);
+;
+ ldy #$09
+ jsr pushwysp
+ jsr _chksum
+ jsr stax0sp
+;
+; return (sum == 0) ? 0xffff : htons(sum);
+;
+ cpx #$00
+ bne L00B5
+ cmp #$00
+ bne L00B5
+ dex
+ txa
+ jmp incsp5
+L00B5: jsr pushw0sp
+ jsr _htons
+ jmp incsp5
+
+.endproc
+
+; ---------------------------------------------------------------
+; void __near__ uip_add_rcv_nxt (unsigned int)
+; ---------------------------------------------------------------
+
+.segment "CODE"
+
+.proc _uip_add_rcv_nxt: near
+
+.segment "CODE"
+
+;
+; uip_add32(uip_conn->rcv_nxt, n);
+;
+ lda _uip_conn
+ ldx _uip_conn+1
+ jsr incax8
+ jsr pushax
+ ldy #$05
+ jsr pushwysp
+ jsr _uip_add32
+;
+; uip_conn->rcv_nxt[0] = uip_acc32[0];
+;
+ lda _uip_conn
+ sta sreg
+ lda _uip_conn+1
+ sta sreg+1
+ lda _uip_acc32
+ ldy #$08
+ sta (sreg),y
+;
+; uip_conn->rcv_nxt[1] = uip_acc32[1];
+;
+ lda _uip_conn
+ sta sreg
+ lda _uip_conn+1
+ sta sreg+1
+ lda _uip_acc32+1
+ iny
+ sta (sreg),y
+;
+; uip_conn->rcv_nxt[2] = uip_acc32[2];
+;
+ lda _uip_conn
+ sta sreg
+ lda _uip_conn+1
+ sta sreg+1
+ lda _uip_acc32+2
+ iny
+ sta (sreg),y
+;
+; uip_conn->rcv_nxt[3] = uip_acc32[3];
+;
+ lda _uip_conn
+ sta sreg
+ lda _uip_conn+1
+ sta sreg+1
+ lda _uip_acc32+3
+ iny
+ sta (sreg),y
+;
+; }
+;
+ jmp incsp2
+
+.endproc
+
diff --git a/uip/README.uIP b/uip/README.uIP
new file mode 100644
index 0000000..b501538
--- /dev/null
+++ b/uip/README.uIP
@@ -0,0 +1,13 @@
+uIP is a very small implementation of the TCP/IP stack that is written
+by Adam Dunkels <adam@sics.se>. More information can be obtained
+at the uIP homepage at http://www.sics.se/~adam/uip/.
+
+This is version $Name: uip-1-0 $.
+
+The directory structure look as follows:
+
+apps/ - Example applications
+doc/ - Documentation
+lib/ - Library code used by some applications
+uip/ - uIP TCP/IP stack code
+unix/ - uIP as a user space process under FreeBSD or Linux
diff --git a/uip/apps/README b/uip/apps/README
new file mode 100644
index 0000000..0096c4e
--- /dev/null
+++ b/uip/apps/README
@@ -0,0 +1,2 @@
+This directory contains a few example applications. They are not all
+heavily tested, however.
diff --git a/uip/apps/dhcpc/Makefile.dhcpc b/uip/apps/dhcpc/Makefile.dhcpc
new file mode 100644
index 0000000..f84c84f
--- /dev/null
+++ b/uip/apps/dhcpc/Makefile.dhcpc
@@ -0,0 +1 @@
+APP_SOURCES += dhcpc.c timer.c
diff --git a/uip/apps/dhcpc/dhcpc.c b/uip/apps/dhcpc/dhcpc.c
new file mode 100644
index 0000000..ac738e7
--- /dev/null
+++ b/uip/apps/dhcpc/dhcpc.c
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2005, Swedish Institute of Computer Science
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * @(#)$Id: dhcpc.c,v 1.2 2006/06/11 21:46:37 adam Exp $
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "uip.h"
+#include "dhcpc.h"
+#include "timer.h"
+#include "pt.h"
+
+#define STATE_INITIAL 0
+#define STATE_SENDING 1
+#define STATE_OFFER_RECEIVED 2
+#define STATE_CONFIG_RECEIVED 3
+
+static struct dhcpc_state s;
+
+struct dhcp_msg {
+ u8_t op, htype, hlen, hops;
+ u8_t xid[4];
+ u16_t secs, flags;
+ u8_t ciaddr[4];
+ u8_t yiaddr[4];
+ u8_t siaddr[4];
+ u8_t giaddr[4];
+ u8_t chaddr[16];
+#ifndef UIP_CONF_DHCP_LIGHT
+ u8_t sname[64];
+ u8_t file[128];
+#endif
+ u8_t options[312];
+};
+
+#define BOOTP_BROADCAST 0x8000
+
+#define DHCP_REQUEST 1
+#define DHCP_REPLY 2
+#define DHCP_HTYPE_ETHERNET 1
+#define DHCP_HLEN_ETHERNET 6
+#define DHCP_MSG_LEN 236
+
+#define DHCPC_SERVER_PORT 67
+#define DHCPC_CLIENT_PORT 68
+
+#define DHCPDISCOVER 1
+#define DHCPOFFER 2
+#define DHCPREQUEST 3
+#define DHCPDECLINE 4
+#define DHCPACK 5
+#define DHCPNAK 6
+#define DHCPRELEASE 7
+
+#define DHCP_OPTION_SUBNET_MASK 1
+#define DHCP_OPTION_ROUTER 3
+#define DHCP_OPTION_DNS_SERVER 6
+#define DHCP_OPTION_REQ_IPADDR 50
+#define DHCP_OPTION_LEASE_TIME 51
+#define DHCP_OPTION_MSG_TYPE 53
+#define DHCP_OPTION_SERVER_ID 54
+#define DHCP_OPTION_REQ_LIST 55
+#define DHCP_OPTION_END 255
+
+static const u8_t xid[4] = {0xad, 0xde, 0x12, 0x23};
+static const u8_t magic_cookie[4] = {99, 130, 83, 99};
+/*---------------------------------------------------------------------------*/
+static u8_t *
+add_msg_type(u8_t *optptr, u8_t type)
+{
+ *optptr++ = DHCP_OPTION_MSG_TYPE;
+ *optptr++ = 1;
+ *optptr++ = type;
+ return optptr;
+}
+/*---------------------------------------------------------------------------*/
+static u8_t *
+add_server_id(u8_t *optptr)
+{
+ *optptr++ = DHCP_OPTION_SERVER_ID;
+ *optptr++ = 4;
+ memcpy(optptr, s.serverid, 4);
+ return optptr + 4;
+}
+/*---------------------------------------------------------------------------*/
+static u8_t *
+add_req_ipaddr(u8_t *optptr)
+{
+ *optptr++ = DHCP_OPTION_REQ_IPADDR;
+ *optptr++ = 4;
+ memcpy(optptr, s.ipaddr, 4);
+ return optptr + 4;
+}
+/*---------------------------------------------------------------------------*/
+static u8_t *
+add_req_options(u8_t *optptr)
+{
+ *optptr++ = DHCP_OPTION_REQ_LIST;
+ *optptr++ = 3;
+ *optptr++ = DHCP_OPTION_SUBNET_MASK;
+ *optptr++ = DHCP_OPTION_ROUTER;
+ *optptr++ = DHCP_OPTION_DNS_SERVER;
+ return optptr;
+}
+/*---------------------------------------------------------------------------*/
+static u8_t *
+add_end(u8_t *optptr)
+{
+ *optptr++ = DHCP_OPTION_END;
+ return optptr;
+}
+/*---------------------------------------------------------------------------*/
+static void
+create_msg(register struct dhcp_msg *m)
+{
+ m->op = DHCP_REQUEST;
+ m->htype = DHCP_HTYPE_ETHERNET;
+ m->hlen = s.mac_len;
+ m->hops = 0;
+ memcpy(m->xid, xid, sizeof(m->xid));
+ m->secs = 0;
+ m->flags = HTONS(BOOTP_BROADCAST); /* Broadcast bit. */
+ /* uip_ipaddr_copy(m->ciaddr, uip_hostaddr);*/
+ memcpy(m->ciaddr, uip_hostaddr, sizeof(m->ciaddr));
+ memset(m->yiaddr, 0, sizeof(m->yiaddr));
+ memset(m->siaddr, 0, sizeof(m->siaddr));
+ memset(m->giaddr, 0, sizeof(m->giaddr));
+ memcpy(m->chaddr, s.mac_addr, s.mac_len);
+ memset(&m->chaddr[s.mac_len], 0, sizeof(m->chaddr) - s.mac_len);
+#ifndef UIP_CONF_DHCP_LIGHT
+ memset(m->sname, 0, sizeof(m->sname));
+ memset(m->file, 0, sizeof(m->file));
+#endif
+
+ memcpy(m->options, magic_cookie, sizeof(magic_cookie));
+}
+/*---------------------------------------------------------------------------*/
+static void
+send_discover(void)
+{
+ u8_t *end;
+ struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
+
+ create_msg(m);
+
+ end = add_msg_type(&m->options[4], DHCPDISCOVER);
+ end = add_req_options(end);
+ end = add_end(end);
+
+ uip_send(uip_appdata, end - (u8_t *)uip_appdata);
+}
+/*---------------------------------------------------------------------------*/
+static void
+send_request(void)
+{
+ u8_t *end;
+ struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
+
+ create_msg(m);
+
+ end = add_msg_type(&m->options[4], DHCPREQUEST);
+ end = add_server_id(end);
+ end = add_req_ipaddr(end);
+ end = add_end(end);
+
+ uip_send(uip_appdata, end - (u8_t *)uip_appdata);
+}
+/*---------------------------------------------------------------------------*/
+static u8_t
+parse_options(u8_t *optptr, int len)
+{
+ u8_t *end = optptr + len;
+ u8_t type = 0;
+
+ while(optptr < end) {
+ switch(*optptr) {
+ case DHCP_OPTION_SUBNET_MASK:
+ memcpy(s.netmask, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_ROUTER:
+ memcpy(s.default_router, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_DNS_SERVER:
+ memcpy(s.dnsaddr, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_MSG_TYPE:
+ type = *(optptr + 2);
+ break;
+ case DHCP_OPTION_SERVER_ID:
+ memcpy(s.serverid, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_LEASE_TIME:
+ memcpy(s.lease_time, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_END:
+ return type;
+ }
+
+ optptr += optptr[1] + 2;
+ }
+ return type;
+}
+/*---------------------------------------------------------------------------*/
+static u8_t
+parse_msg(void)
+{
+ struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
+
+ if(m->op == DHCP_REPLY &&
+ memcmp(m->xid, xid, sizeof(xid)) == 0 &&
+ memcmp(m->chaddr, s.mac_addr, s.mac_len) == 0) {
+ memcpy(s.ipaddr, m->yiaddr, 4);
+ return parse_options(&m->options[4], uip_datalen());
+ }
+ return 0;
+}
+/*---------------------------------------------------------------------------*/
+static
+PT_THREAD(handle_dhcp(void))
+{
+ PT_BEGIN(&s.pt);
+
+ /* try_again:*/
+ s.state = STATE_SENDING;
+ s.ticks = CLOCK_SECOND;
+
+ do {
+ send_discover();
+ timer_set(&s.timer, s.ticks);
+ PT_WAIT_UNTIL(&s.pt, uip_newdata() || timer_expired(&s.timer));
+
+ if(uip_newdata() && parse_msg() == DHCPOFFER) {
+ s.state = STATE_OFFER_RECEIVED;
+ break;
+ }
+
+ if(s.ticks < CLOCK_SECOND * 60) {
+ s.ticks *= 2;
+ }
+ } while(s.state != STATE_OFFER_RECEIVED);
+
+ s.ticks = CLOCK_SECOND;
+
+ do {
+ send_request();
+ timer_set(&s.timer, s.ticks);
+ PT_WAIT_UNTIL(&s.pt, uip_newdata() || timer_expired(&s.timer));
+
+ if(uip_newdata() && parse_msg() == DHCPACK) {
+ s.state = STATE_CONFIG_RECEIVED;
+ break;
+ }
+
+ if(s.ticks <= CLOCK_SECOND * 10) {
+ s.ticks += CLOCK_SECOND;
+ } else {
+ PT_RESTART(&s.pt);
+ }
+ } while(s.state != STATE_CONFIG_RECEIVED);
+
+#if 0
+ printf("Got IP address %d.%d.%d.%d\n",
+ uip_ipaddr1(s.ipaddr), uip_ipaddr2(s.ipaddr),
+ uip_ipaddr3(s.ipaddr), uip_ipaddr4(s.ipaddr));
+ printf("Got netmask %d.%d.%d.%d\n",
+ uip_ipaddr1(s.netmask), uip_ipaddr2(s.netmask),
+ uip_ipaddr3(s.netmask), uip_ipaddr4(s.netmask));
+ printf("Got DNS server %d.%d.%d.%d\n",
+ uip_ipaddr1(s.dnsaddr), uip_ipaddr2(s.dnsaddr),
+ uip_ipaddr3(s.dnsaddr), uip_ipaddr4(s.dnsaddr));
+ printf("Got default router %d.%d.%d.%d\n",
+ uip_ipaddr1(s.default_router), uip_ipaddr2(s.default_router),
+ uip_ipaddr3(s.default_router), uip_ipaddr4(s.default_router));
+ printf("Lease expires in %ld seconds\n",
+ ntohs(s.lease_time[0])*65536ul + ntohs(s.lease_time[1]));
+#endif
+
+ dhcpc_configured(&s);
+
+ /* timer_stop(&s.timer);*/
+
+ /*
+ * PT_END restarts the thread so we do this instead. Eventually we
+ * should reacquire expired leases here.
+ */
+ while(1) {
+ PT_YIELD(&s.pt);
+ }
+
+ PT_END(&s.pt);
+}
+/*---------------------------------------------------------------------------*/
+void
+dhcpc_init(const void *mac_addr, int mac_len)
+{
+ uip_ipaddr_t addr;
+
+ s.mac_addr = mac_addr;
+ s.mac_len = mac_len;
+
+ s.state = STATE_INITIAL;
+ uip_ipaddr(addr, 255,255,255,255);
+ s.conn = uip_udp_new(&addr, HTONS(DHCPC_SERVER_PORT));
+ if(s.conn != NULL) {
+ uip_udp_bind(s.conn, HTONS(DHCPC_CLIENT_PORT));
+ }
+ PT_INIT(&s.pt);
+}
+/*---------------------------------------------------------------------------*/
+void
+dhcpc_appcall(void)
+{
+ handle_dhcp();
+}
+/*---------------------------------------------------------------------------*/
+void
+dhcpc_request(void)
+{
+ u16_t ipaddr[2];
+
+ if(s.state == STATE_INITIAL) {
+ uip_ipaddr(ipaddr, 0,0,0,0);
+ uip_sethostaddr(ipaddr);
+ /* handle_dhcp(PROCESS_EVENT_NONE, NULL);*/
+ }
+}
+/*---------------------------------------------------------------------------*/
diff --git a/uip/apps/dhcpc/dhcpc.h b/uip/apps/dhcpc/dhcpc.h
new file mode 100644
index 0000000..c6550ec
--- /dev/null
+++ b/uip/apps/dhcpc/dhcpc.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2005, Swedish Institute of Computer Science
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * @(#)$Id: dhcpc.h,v 1.3 2006/06/11 21:46:37 adam Exp $
+ */
+#ifndef __DHCPC_H__
+#define __DHCPC_H__
+
+#include "timer.h"
+#include "pt.h"
+
+struct dhcpc_state {
+ struct pt pt;
+ char state;
+ struct uip_udp_conn *conn;
+ struct timer timer;
+ u16_t ticks;
+ const void *mac_addr;
+ int mac_len;
+
+ u8_t serverid[4];
+
+ u16_t lease_time[2];
+ u16_t ipaddr[2];
+ u16_t netmask[2];
+ u16_t dnsaddr[2];
+ u16_t default_router[2];
+};
+
+void dhcpc_init(const void *mac_addr, int mac_len);
+void dhcpc_request(void);
+
+void dhcpc_appcall(void);
+
+void dhcpc_configured(const struct dhcpc_state *s);
+
+typedef struct dhcpc_state uip_udp_appstate_t;
+#define UIP_UDP_APPCALL dhcpc_appcall
+
+
+#endif /* __DHCPC_H__ */
diff --git a/uip/apps/hello-world/Makefile.hello-world b/uip/apps/hello-world/Makefile.hello-world
new file mode 100644
index 0000000..e34aaf5
--- /dev/null
+++ b/uip/apps/hello-world/Makefile.hello-world
@@ -0,0 +1 @@
+APP_SOURCES += hello-world.c
diff --git a/uip/apps/hello-world/hello-world.c b/uip/apps/hello-world/hello-world.c
new file mode 100644
index 0000000..7d0697c
--- /dev/null
+++ b/uip/apps/hello-world/hello-world.c
@@ -0,0 +1,100 @@
+/**
+ * \addtogroup helloworld
+ * @{
+ */
+
+/**
+ * \file
+ * An example of how to write uIP applications
+ * with protosockets.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ */
+
+/*
+ * This is a short example of how to write uIP applications using
+ * protosockets.
+ */
+
+/*
+ * We define the application state (struct hello_world_state) in the
+ * hello-world.h file, so we need to include it here. We also include
+ * uip.h (since this cannot be included in hello-world.h) and
+ * <string.h>, since we use the memcpy() function in the code.
+ */
+#include "hello-world.h"
+#include "uip.h"
+#include <string.h>
+
+/*
+ * Declaration of the protosocket function that handles the connection
+ * (defined at the end of the code).
+ */
+static int handle_connection(struct hello_world_state *s);
+/*---------------------------------------------------------------------------*/
+/*
+ * The initialization function. We must explicitly call this function
+ * from the system initialization code, some time after uip_init() is
+ * called.
+ */
+void
+hello_world_init(void)
+{
+ /* We start to listen for connections on TCP port 1000. */
+ uip_listen(HTONS(1000));
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * In hello-world.h we have defined the UIP_APPCALL macro to
+ * hello_world_appcall so that this funcion is uIP's application
+ * function. This function is called whenever an uIP event occurs
+ * (e.g. when a new connection is established, new data arrives, sent
+ * data is acknowledged, data needs to be retransmitted, etc.).
+ */
+void
+hello_world_appcall(void)
+{
+ /*
+ * The uip_conn structure has a field called "appstate" that holds
+ * the application state of the connection. We make a pointer to
+ * this to access it easier.
+ */
+ struct hello_world_state *s = &(uip_conn->appstate);
+
+ /*
+ * If a new connection was just established, we should initialize
+ * the protosocket in our applications' state structure.
+ */
+ if(uip_connected()) {
+ PSOCK_INIT(&s->p, s->inputbuffer, sizeof(s->inputbuffer));
+ }
+
+ /*
+ * Finally, we run the protosocket function that actually handles
+ * the communication. We pass it a pointer to the application state
+ * of the current connection.
+ */
+ handle_connection(s);
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * This is the protosocket function that handles the communication. A
+ * protosocket function must always return an int, but must never
+ * explicitly return - all return statements are hidden in the PSOCK
+ * macros.
+ */
+static int
+handle_connection(struct hello_world_state *s)
+{
+ PSOCK_BEGIN(&s->p);
+
+ PSOCK_SEND_STR(&s->p, "Hello. What is your name?\n");
+ PSOCK_READTO(&s->p, '\n');
+ strncpy(s->name, s->inputbuffer, sizeof(s->name));
+ PSOCK_SEND_STR(&s->p, "Hello ");
+ PSOCK_SEND_STR(&s->p, s->name);
+ PSOCK_CLOSE(&s->p);
+
+ PSOCK_END(&s->p);
+}
+/*---------------------------------------------------------------------------*/
diff --git a/uip/apps/hello-world/hello-world.h b/uip/apps/hello-world/hello-world.h
new file mode 100644
index 0000000..5ef333b
--- /dev/null
+++ b/uip/apps/hello-world/hello-world.h
@@ -0,0 +1,52 @@
+/**
+ * \addtogroup apps
+ * @{
+ */
+
+/**
+ * \defgroup helloworld Hello, world
+ * @{
+ *
+ * A small example showing how to write applications with
+ * \ref psock "protosockets".
+ */
+
+/**
+ * \file
+ * Header file for an example of how to write uIP applications
+ * with protosockets.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ */
+
+#ifndef __HELLO_WORLD_H__
+#define __HELLO_WORLD_H__
+
+/* Since this file will be included by uip.h, we cannot include uip.h
+ here. But we might need to include uipopt.h if we need the u8_t and
+ u16_t datatypes. */
+#include "uipopt.h"
+
+#include "psock.h"
+
+/* Next, we define the uip_tcp_appstate_t datatype. This is the state
+ of our application, and the memory required for this state is
+ allocated together with each TCP connection. One application state
+ for each TCP connection. */
+typedef struct hello_world_state {
+ struct psock p;
+ char inputbuffer[10];
+ char name[40];
+} uip_tcp_appstate_t;
+
+/* Finally we define the application function to be called by uIP. */
+void hello_world_appcall(void);
+#ifndef UIP_APPCALL
+#define UIP_APPCALL hello_world_appcall
+#endif /* UIP_APPCALL */
+
+void hello_world_init(void);
+
+#endif /* __HELLO_WORLD_H__ */
+/** @} */
+/** @} */
diff --git a/uip/apps/resolv/Makefile.resolv b/uip/apps/resolv/Makefile.resolv
new file mode 100644
index 0000000..94c37d8
--- /dev/null
+++ b/uip/apps/resolv/Makefile.resolv
@@ -0,0 +1 @@
+APP_SOURCES += resolv.c
diff --git a/uip/apps/resolv/resolv.c b/uip/apps/resolv/resolv.c
new file mode 100644
index 0000000..30c8fb2
--- /dev/null
+++ b/uip/apps/resolv/resolv.c
@@ -0,0 +1,464 @@
+/**
+ * \addtogroup apps
+ * @{
+ */
+
+/**
+ * \defgroup resolv DNS resolver
+ * @{
+ *
+ * The uIP DNS resolver functions are used to lookup a hostname and
+ * map it to a numerical IP address. It maintains a list of resolved
+ * hostnames that can be queried with the resolv_lookup()
+ * function. New hostnames can be resolved using the resolv_query()
+ * function.
+ *
+ * When a hostname has been resolved (or found to be non-existant),
+ * the resolver code calls a callback function called resolv_found()
+ * that must be implemented by the module that uses the resolver.
+ */
+
+/**
+ * \file
+ * DNS host name to IP address resolver.
+ * \author Adam Dunkels <adam@dunkels.com>
+ *
+ * This file implements a DNS host name to IP address resolver.
+ */
+
+/*
+ * Copyright (c) 2002-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: resolv.c,v 1.5 2006/06/11 21:46:37 adam Exp $
+ *
+ */
+
+#include "resolv.h"
+#include "uip.h"
+
+#include <string.h>
+
+#ifndef NULL
+#define NULL (void *)0
+#endif /* NULL */
+
+/** \internal The maximum number of retries when asking for a name. */
+#define MAX_RETRIES 8
+
+/** \internal The DNS message header. */
+struct dns_hdr {
+ u16_t id;
+ u8_t flags1, flags2;
+#define DNS_FLAG1_RESPONSE 0x80
+#define DNS_FLAG1_OPCODE_STATUS 0x10
+#define DNS_FLAG1_OPCODE_INVERSE 0x08
+#define DNS_FLAG1_OPCODE_STANDARD 0x00
+#define DNS_FLAG1_AUTHORATIVE 0x04
+#define DNS_FLAG1_TRUNC 0x02
+#define DNS_FLAG1_RD 0x01
+#define DNS_FLAG2_RA 0x80
+#define DNS_FLAG2_ERR_MASK 0x0f
+#define DNS_FLAG2_ERR_NONE 0x00
+#define DNS_FLAG2_ERR_NAME 0x03
+ u16_t numquestions;
+ u16_t numanswers;
+ u16_t numauthrr;
+ u16_t numextrarr;
+};
+
+/** \internal The DNS answer message structure. */
+struct dns_answer {
+ /* DNS answer record starts with either a domain name or a pointer
+ to a name already present somewhere in the packet. */
+ u16_t type;
+ u16_t class;
+ u16_t ttl[2];
+ u16_t len;
+ uip_ipaddr_t ipaddr;
+};
+
+struct namemap {
+#define STATE_UNUSED 0
+#define STATE_NEW 1
+#define STATE_ASKING 2
+#define STATE_DONE 3
+#define STATE_ERROR 4
+ u8_t state;
+ u8_t tmr;
+ u8_t retries;
+ u8_t seqno;
+ u8_t err;
+ char name[32];
+ uip_ipaddr_t ipaddr;
+};
+
+#ifndef UIP_CONF_RESOLV_ENTRIES
+#define RESOLV_ENTRIES 4
+#else /* UIP_CONF_RESOLV_ENTRIES */
+#define RESOLV_ENTRIES UIP_CONF_RESOLV_ENTRIES
+#endif /* UIP_CONF_RESOLV_ENTRIES */
+
+
+static struct namemap names[RESOLV_ENTRIES];
+
+static u8_t seqno;
+
+static struct uip_udp_conn *resolv_conn = NULL;
+
+
+/*---------------------------------------------------------------------------*/
+/** \internal
+ * Walk through a compact encoded DNS name and return the end of it.
+ *
+ * \return The end of the name.
+ */
+/*---------------------------------------------------------------------------*/
+static unsigned char *
+parse_name(unsigned char *query)
+{
+ unsigned char n;
+
+ do {
+ n = *query++;
+
+ while(n > 0) {
+ /* printf("%c", *query);*/
+ ++query;
+ --n;
+ };
+ /* printf(".");*/
+ } while(*query != 0);
+ /* printf("\n");*/
+ return query + 1;
+}
+/*---------------------------------------------------------------------------*/
+/** \internal
+ * Runs through the list of names to see if there are any that have
+ * not yet been queried and, if so, sends out a query.
+ */
+/*---------------------------------------------------------------------------*/
+static void
+check_entries(void)
+{
+ register struct dns_hdr *hdr;
+ char *query, *nptr, *nameptr;
+ static u8_t i;
+ static u8_t n;
+ register struct namemap *namemapptr;
+
+ for(i = 0; i < RESOLV_ENTRIES; ++i) {
+ namemapptr = &names[i];
+ if(namemapptr->state == STATE_NEW ||
+ namemapptr->state == STATE_ASKING) {
+ if(namemapptr->state == STATE_ASKING) {
+ if(--namemapptr->tmr == 0) {
+ if(++namemapptr->retries == MAX_RETRIES) {
+ namemapptr->state = STATE_ERROR;
+ resolv_found(namemapptr->name, NULL);
+ continue;
+ }
+ namemapptr->tmr = namemapptr->retries;
+ } else {
+ /* printf("Timer %d\n", namemapptr->tmr);*/
+ /* Its timer has not run out, so we move on to next
+ entry. */
+ continue;
+ }
+ } else {
+ namemapptr->state = STATE_ASKING;
+ namemapptr->tmr = 1;
+ namemapptr->retries = 0;
+ }
+ hdr = (struct dns_hdr *)uip_appdata;
+ memset(hdr, 0, sizeof(struct dns_hdr));
+ hdr->id = htons(i);
+ hdr->flags1 = DNS_FLAG1_RD;
+ hdr->numquestions = HTONS(1);
+ query = (char *)uip_appdata + 12;
+ nameptr = namemapptr->name;
+ --nameptr;
+ /* Convert hostname into suitable query format. */
+ do {
+ ++nameptr;
+ nptr = query;
+ ++query;
+ for(n = 0; *nameptr != '.' && *nameptr != 0; ++nameptr) {
+ *query = *nameptr;
+ ++query;
+ ++n;
+ }
+ *nptr = n;
+ } while(*nameptr != 0);
+ {
+ static unsigned char endquery[] =
+ {0,0,1,0,1};
+ memcpy(query, endquery, 5);
+ }
+ uip_udp_send((unsigned char)(query + 5 - (char *)uip_appdata));
+ break;
+ }
+ }
+}
+/*---------------------------------------------------------------------------*/
+/** \internal
+ * Called when new UDP data arrives.
+ */
+/*---------------------------------------------------------------------------*/
+static void
+newdata(void)
+{
+ char *nameptr;
+ struct dns_answer *ans;
+ struct dns_hdr *hdr;
+ static u8_t nquestions, nanswers;
+ static u8_t i;
+ register struct namemap *namemapptr;
+
+ hdr = (struct dns_hdr *)uip_appdata;
+ /* printf("ID %d\n", htons(hdr->id));
+ printf("Query %d\n", hdr->flags1 & DNS_FLAG1_RESPONSE);
+ printf("Error %d\n", hdr->flags2 & DNS_FLAG2_ERR_MASK);
+ printf("Num questions %d, answers %d, authrr %d, extrarr %d\n",
+ htons(hdr->numquestions),
+ htons(hdr->numanswers),
+ htons(hdr->numauthrr),
+ htons(hdr->numextrarr));
+ */
+
+ /* The ID in the DNS header should be our entry into the name
+ table. */
+ i = htons(hdr->id);
+ namemapptr = &names[i];
+ if(i < RESOLV_ENTRIES &&
+ namemapptr->state == STATE_ASKING) {
+
+ /* This entry is now finished. */
+ namemapptr->state = STATE_DONE;
+ namemapptr->err = hdr->flags2 & DNS_FLAG2_ERR_MASK;
+
+ /* Check for error. If so, call callback to inform. */
+ if(namemapptr->err != 0) {
+ namemapptr->state = STATE_ERROR;
+ resolv_found(namemapptr->name, NULL);
+ return;
+ }
+
+ /* We only care about the question(s) and the answers. The authrr
+ and the extrarr are simply discarded. */
+ nquestions = htons(hdr->numquestions);
+ nanswers = htons(hdr->numanswers);
+
+ /* Skip the name in the question. XXX: This should really be
+ checked agains the name in the question, to be sure that they
+ match. */
+ nameptr = parse_name((char *)uip_appdata + 12) + 4;
+
+ while(nanswers > 0) {
+ /* The first byte in the answer resource record determines if it
+ is a compressed record or a normal one. */
+ if(*nameptr & 0xc0) {
+ /* Compressed name. */
+ nameptr +=2;
+ /* printf("Compressed anwser\n");*/
+ } else {
+ /* Not compressed name. */
+ nameptr = parse_name((char *)nameptr);
+ }
+
+ ans = (struct dns_answer *)nameptr;
+ /* printf("Answer: type %x, class %x, ttl %x, length %x\n",
+ htons(ans->type), htons(ans->class), (htons(ans->ttl[0])
+ << 16) | htons(ans->ttl[1]), htons(ans->len));*/
+
+ /* Check for IP address type and Internet class. Others are
+ discarded. */
+ if(ans->type == HTONS(1) &&
+ ans->class == HTONS(1) &&
+ ans->len == HTONS(4)) {
+ /* printf("IP address %d.%d.%d.%d\n",
+ htons(ans->ipaddr[0]) >> 8,
+ htons(ans->ipaddr[0]) & 0xff,
+ htons(ans->ipaddr[1]) >> 8,
+ htons(ans->ipaddr[1]) & 0xff);*/
+ /* XXX: we should really check that this IP address is the one
+ we want. */
+ namemapptr->ipaddr[0] = ans->ipaddr[0];
+ namemapptr->ipaddr[1] = ans->ipaddr[1];
+
+ resolv_found(namemapptr->name, namemapptr->ipaddr);
+ return;
+ } else {
+ nameptr = nameptr + 10 + htons(ans->len);
+ }
+ --nanswers;
+ }
+ }
+
+}
+/*---------------------------------------------------------------------------*/
+/** \internal
+ * The main UDP function.
+ */
+/*---------------------------------------------------------------------------*/
+void
+resolv_appcall(void)
+{
+ if(uip_udp_conn->rport == HTONS(53)) {
+ if(uip_poll()) {
+ check_entries();
+ }
+ if(uip_newdata()) {
+ newdata();
+ }
+ }
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Queues a name so that a question for the name will be sent out.
+ *
+ * \param name The hostname that is to be queried.
+ */
+/*---------------------------------------------------------------------------*/
+void
+resolv_query(char *name)
+{
+ static u8_t i;
+ static u8_t lseq, lseqi;
+ register struct namemap *nameptr;
+
+ lseq = lseqi = 0;
+
+ for(i = 0; i < RESOLV_ENTRIES; ++i) {
+ nameptr = &names[i];
+ if(nameptr->state == STATE_UNUSED) {
+ break;
+ }
+ if(seqno - nameptr->seqno > lseq) {
+ lseq = seqno - nameptr->seqno;
+ lseqi = i;
+ }
+ }
+
+ if(i == RESOLV_ENTRIES) {
+ i = lseqi;
+ nameptr = &names[i];
+ }
+
+ /* printf("Using entry %d\n", i);*/
+
+ strcpy(nameptr->name, name);
+ nameptr->state = STATE_NEW;
+ nameptr->seqno = seqno;
+ ++seqno;
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Look up a hostname in the array of known hostnames.
+ *
+ * \note This function only looks in the internal array of known
+ * hostnames, it does not send out a query for the hostname if none
+ * was found. The function resolv_query() can be used to send a query
+ * for a hostname.
+ *
+ * \return A pointer to a 4-byte representation of the hostname's IP
+ * address, or NULL if the hostname was not found in the array of
+ * hostnames.
+ */
+/*---------------------------------------------------------------------------*/
+u16_t *
+resolv_lookup(char *name)
+{
+ static u8_t i;
+ struct namemap *nameptr;
+
+ /* Walk through the list to see if the name is in there. If it is
+ not, we return NULL. */
+ for(i = 0; i < RESOLV_ENTRIES; ++i) {
+ nameptr = &names[i];
+ if(nameptr->state == STATE_DONE &&
+ strcmp(name, nameptr->name) == 0) {
+ return nameptr->ipaddr;
+ }
+ }
+ return NULL;
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Obtain the currently configured DNS server.
+ *
+ * \return A pointer to a 4-byte representation of the IP address of
+ * the currently configured DNS server or NULL if no DNS server has
+ * been configured.
+ */
+/*---------------------------------------------------------------------------*/
+u16_t *
+resolv_getserver(void)
+{
+ if(resolv_conn == NULL) {
+ return NULL;
+ }
+ return resolv_conn->ripaddr;
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Configure which DNS server to use for queries.
+ *
+ * \param dnsserver A pointer to a 4-byte representation of the IP
+ * address of the DNS server to be configured.
+ */
+/*---------------------------------------------------------------------------*/
+void
+resolv_conf(u16_t *dnsserver)
+{
+ if(resolv_conn != NULL) {
+ uip_udp_remove(resolv_conn);
+ }
+
+ resolv_conn = uip_udp_new((uip_ipaddr_t *)dnsserver, HTONS(53));
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Initalize the resolver.
+ */
+/*---------------------------------------------------------------------------*/
+void
+resolv_init(void)
+{
+ static u8_t i;
+
+ for(i = 0; i < RESOLV_ENTRIES; ++i) {
+ names[i].state = STATE_DONE;
+ }
+
+}
+/*---------------------------------------------------------------------------*/
+
+/** @} */
+/** @} */
diff --git a/uip/apps/resolv/resolv.h b/uip/apps/resolv/resolv.h
new file mode 100644
index 0000000..abab34e
--- /dev/null
+++ b/uip/apps/resolv/resolv.h
@@ -0,0 +1,75 @@
+/**
+ * \addtogroup resolv
+ * @{
+ */
+/**
+ * \file
+ * DNS resolver code header file.
+ * \author Adam Dunkels <adam@dunkels.com>
+ */
+
+/*
+ * Copyright (c) 2002-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: resolv.h,v 1.4 2006/06/11 21:46:37 adam Exp $
+ *
+ */
+#ifndef __RESOLV_H__
+#define __RESOLV_H__
+
+typedef int uip_udp_appstate_t;
+void resolv_appcall(void);
+#define UIP_UDP_APPCALL resolv_appcall
+
+#include "uipopt.h"
+
+/**
+ * Callback function which is called when a hostname is found.
+ *
+ * This function must be implemented by the module that uses the DNS
+ * resolver. It is called when a hostname is found, or when a hostname
+ * was not found.
+ *
+ * \param name A pointer to the name that was looked up. \param
+ * ipaddr A pointer to a 4-byte array containing the IP address of the
+ * hostname, or NULL if the hostname could not be found.
+ */
+void resolv_found(char *name, u16_t *ipaddr);
+
+/* Functions. */
+void resolv_conf(u16_t *dnsserver);
+u16_t *resolv_getserver(void);
+void resolv_init(void);
+u16_t *resolv_lookup(char *name);
+void resolv_query(char *name);
+
+#endif /* __RESOLV_H__ */
+
+/** @} */
diff --git a/uip/apps/smtp/Makefile.smtp b/uip/apps/smtp/Makefile.smtp
new file mode 100644
index 0000000..8b3a5aa
--- /dev/null
+++ b/uip/apps/smtp/Makefile.smtp
@@ -0,0 +1 @@
+APP_SOURCES += smtp.c smtp-strings.c memb.c
diff --git a/uip/apps/smtp/makestrings b/uip/apps/smtp/makestrings
new file mode 100755
index 0000000..bea18a6
--- /dev/null
+++ b/uip/apps/smtp/makestrings
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+
+
+sub stringify {
+ my $name = shift(@_);
+ open(OUTPUTC, "> $name.c");
+ open(OUTPUTH, "> $name.h");
+
+ open(FILE, "$name");
+
+ while(<FILE>) {
+ if(/(.+) "(.+)"/) {
+ $var = $1;
+ $data = $2;
+
+ $datan = $data;
+ $datan =~ s/\\r/\r/g;
+ $datan =~ s/\\n/\n/g;
+ $datan =~ s/\\01/\01/g;
+ $datan =~ s/\\0/\0/g;
+
+ printf(OUTPUTC "const char $var\[%d] = \n", length($datan) + 1);
+ printf(OUTPUTC "/* \"$data\" */\n");
+ printf(OUTPUTC "{");
+ for($j = 0; $j < length($datan); $j++) {
+ printf(OUTPUTC "%#02x, ", unpack("C", substr($datan, $j, 1)));
+ }
+ printf(OUTPUTC "};\n");
+
+ printf(OUTPUTH "extern const char $var\[%d];\n", length($datan) + 1);
+
+ }
+ }
+ close(OUTPUTC);
+ close(OUTPUTH);
+}
+stringify("smtp-strings");
+
+exit 0;
+
diff --git a/uip/apps/smtp/smtp-strings b/uip/apps/smtp/smtp-strings
new file mode 100644
index 0000000..27f639c
--- /dev/null
+++ b/uip/apps/smtp/smtp-strings
@@ -0,0 +1,11 @@
+smtp_220 "220"
+smtp_helo "HELO "
+smtp_mail_from "MAIL FROM: "
+smtp_rcpt_to "RCPT TO: "
+smtp_data "DATA\r\n"
+smtp_to "To: "
+smtp_from "From: "
+smtp_subject "Subject: "
+smtp_quit "QUIT\r\n"
+smtp_crnl "\r\n"
+smtp_crnlperiodcrnl "\r\n.\r\n" \ No newline at end of file
diff --git a/uip/apps/smtp/smtp-strings.c b/uip/apps/smtp/smtp-strings.c
new file mode 100644
index 0000000..f3981a1
--- /dev/null
+++ b/uip/apps/smtp/smtp-strings.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2004, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: smtp-strings.c,v 1.3 2006/06/11 21:46:37 adam Exp $
+ */
+const char smtp_220[4] =
+/* "220" */
+{0x32, 0x32, 0x30, };
+const char smtp_helo[6] =
+/* "HELO " */
+{0x48, 0x45, 0x4c, 0x4f, 0x20, };
+const char smtp_mail_from[12] =
+/* "MAIL FROM: " */
+{0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f, 0x4d, 0x3a, 0x20, };
+const char smtp_rcpt_to[10] =
+/* "RCPT TO: " */
+{0x52, 0x43, 0x50, 0x54, 0x20, 0x54, 0x4f, 0x3a, 0x20, };
+const char smtp_data[7] =
+/* "DATA\r\n" */
+{0x44, 0x41, 0x54, 0x41, 0xd, 0xa, };
+const char smtp_to[5] =
+/* "To: " */
+{0x54, 0x6f, 0x3a, 0x20, };
+const char smtp_cc[5] =
+/* "Cc: " */
+{0x43, 0x63, 0x3a, 0x20, };
+const char smtp_from[7] =
+/* "From: " */
+{0x46, 0x72, 0x6f, 0x6d, 0x3a, 0x20, };
+const char smtp_subject[10] =
+/* "Subject: " */
+{0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3a, 0x20, };
+const char smtp_quit[7] =
+/* "QUIT\r\n" */
+{0x51, 0x55, 0x49, 0x54, 0xd, 0xa, };
+const char smtp_crnl[3] =
+/* "\r\n" */
+{0xd, 0xa, };
+const char smtp_crnlperiodcrnl[6] =
+/* "\r\n.\r\n" */
+{0xd, 0xa, 0x2e, 0xd, 0xa, };
diff --git a/uip/apps/smtp/smtp-strings.h b/uip/apps/smtp/smtp-strings.h
new file mode 100644
index 0000000..f5ae68c
--- /dev/null
+++ b/uip/apps/smtp/smtp-strings.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2004, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: smtp-strings.h,v 1.3 2006/06/11 21:46:37 adam Exp $
+ */
+extern const char smtp_220[4];
+extern const char smtp_helo[6];
+extern const char smtp_mail_from[12];
+extern const char smtp_rcpt_to[10];
+extern const char smtp_data[7];
+extern const char smtp_to[5];
+extern const char smtp_cc[5];
+extern const char smtp_from[7];
+extern const char smtp_subject[10];
+extern const char smtp_quit[7];
+extern const char smtp_crnl[3];
+extern const char smtp_crnlperiodcrnl[6];
diff --git a/uip/apps/smtp/smtp.c b/uip/apps/smtp/smtp.c
new file mode 100644
index 0000000..a860006
--- /dev/null
+++ b/uip/apps/smtp/smtp.c
@@ -0,0 +1,262 @@
+/**
+ * \addtogroup apps
+ * @{
+ */
+
+/**
+ * \defgroup smtp SMTP E-mail sender
+ * @{
+ *
+ * The Simple Mail Transfer Protocol (SMTP) as defined by RFC821 is
+ * the standard way of sending and transfering e-mail on the
+ * Internet. This simple example implementation is intended as an
+ * example of how to implement protocols in uIP, and is able to send
+ * out e-mail but has not been extensively tested.
+ */
+
+/**
+ * \file
+ * SMTP example implementation
+ * \author Adam Dunkels <adam@dunkels.com>
+ */
+
+/*
+ * Copyright (c) 2004, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: smtp.c,v 1.4 2006/06/11 21:46:37 adam Exp $
+ */
+#include "smtp.h"
+
+#include "smtp-strings.h"
+#include "psock.h"
+#include "uip.h"
+
+#include <string.h>
+
+static struct smtp_state s;
+
+static char *localhostname;
+static uip_ipaddr_t smtpserver;
+
+#define ISO_nl 0x0a
+#define ISO_cr 0x0d
+
+#define ISO_period 0x2e
+
+#define ISO_2 0x32
+#define ISO_3 0x33
+#define ISO_4 0x34
+#define ISO_5 0x35
+
+
+/*---------------------------------------------------------------------------*/
+static
+PT_THREAD(smtp_thread(void))
+{
+ PSOCK_BEGIN(&s.psock);
+
+ PSOCK_READTO(&s.psock, ISO_nl);
+
+ if(strncmp(s.inputbuffer, smtp_220, 3) != 0) {
+ PSOCK_CLOSE(&s.psock);
+ smtp_done(2);
+ PSOCK_EXIT(&s.psock);
+ }
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_helo);
+ PSOCK_SEND_STR(&s.psock, localhostname);
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
+
+ PSOCK_READTO(&s.psock, ISO_nl);
+
+ if(s.inputbuffer[0] != ISO_2) {
+ PSOCK_CLOSE(&s.psock);
+ smtp_done(3);
+ PSOCK_EXIT(&s.psock);
+ }
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_mail_from);
+ PSOCK_SEND_STR(&s.psock, s.from);
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
+
+ PSOCK_READTO(&s.psock, ISO_nl);
+
+ if(s.inputbuffer[0] != ISO_2) {
+ PSOCK_CLOSE(&s.psock);
+ smtp_done(4);
+ PSOCK_EXIT(&s.psock);
+ }
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_rcpt_to);
+ PSOCK_SEND_STR(&s.psock, s.to);
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
+
+ PSOCK_READTO(&s.psock, ISO_nl);
+
+ if(s.inputbuffer[0] != ISO_2) {
+ PSOCK_CLOSE(&s.psock);
+ smtp_done(5);
+ PSOCK_EXIT(&s.psock);
+ }
+
+ if(s.cc != 0) {
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_rcpt_to);
+ PSOCK_SEND_STR(&s.psock, s.cc);
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
+
+ PSOCK_READTO(&s.psock, ISO_nl);
+
+ if(s.inputbuffer[0] != ISO_2) {
+ PSOCK_CLOSE(&s.psock);
+ smtp_done(6);
+ PSOCK_EXIT(&s.psock);
+ }
+ }
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_data);
+
+ PSOCK_READTO(&s.psock, ISO_nl);
+
+ if(s.inputbuffer[0] != ISO_3) {
+ PSOCK_CLOSE(&s.psock);
+ smtp_done(7);
+ PSOCK_EXIT(&s.psock);
+ }
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_to);
+ PSOCK_SEND_STR(&s.psock, s.to);
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
+
+ if(s.cc != 0) {
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_cc);
+ PSOCK_SEND_STR(&s.psock, s.cc);
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
+ }
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_from);
+ PSOCK_SEND_STR(&s.psock, s.from);
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_subject);
+ PSOCK_SEND_STR(&s.psock, s.subject);
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl);
+
+ PSOCK_SEND(&s.psock, s.msg, s.msglen);
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_crnlperiodcrnl);
+
+ PSOCK_READTO(&s.psock, ISO_nl);
+ if(s.inputbuffer[0] != ISO_2) {
+ PSOCK_CLOSE(&s.psock);
+ smtp_done(8);
+ PSOCK_EXIT(&s.psock);
+ }
+
+ PSOCK_SEND_STR(&s.psock, (char *)smtp_quit);
+ smtp_done(SMTP_ERR_OK);
+ PSOCK_END(&s.psock);
+}
+/*---------------------------------------------------------------------------*/
+void
+smtp_appcall(void)
+{
+ if(uip_closed()) {
+ s.connected = 0;
+ return;
+ }
+ if(uip_aborted() || uip_timedout()) {
+ s.connected = 0;
+ smtp_done(1);
+ return;
+ }
+ smtp_thread();
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Specificy an SMTP server and hostname.
+ *
+ * This function is used to configure the SMTP module with an SMTP
+ * server and the hostname of the host.
+ *
+ * \param lhostname The hostname of the uIP host.
+ *
+ * \param server A pointer to a 4-byte array representing the IP
+ * address of the SMTP server to be configured.
+ */
+void
+smtp_configure(char *lhostname, void *server)
+{
+ localhostname = lhostname;
+ uip_ipaddr_copy(smtpserver, server);
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Send an e-mail.
+ *
+ * \param to The e-mail address of the receiver of the e-mail.
+ * \param cc The e-mail address of the CC: receivers of the e-mail.
+ * \param from The e-mail address of the sender of the e-mail.
+ * \param subject The subject of the e-mail.
+ * \param msg The actual e-mail message.
+ * \param msglen The length of the e-mail message.
+ */
+unsigned char
+smtp_send(char *to, char *cc, char *from,
+ char *subject, char *msg, u16_t msglen)
+{
+ struct uip_conn *conn;
+
+ conn = uip_connect(smtpserver, HTONS(25));
+ if(conn == NULL) {
+ return 0;
+ }
+ s.connected = 1;
+ s.to = to;
+ s.cc = cc;
+ s.from = from;
+ s.subject = subject;
+ s.msg = msg;
+ s.msglen = msglen;
+
+ PSOCK_INIT(&s.psock, s.inputbuffer, sizeof(s.inputbuffer));
+
+ return 1;
+}
+/*---------------------------------------------------------------------------*/
+void
+smtp_init(void)
+{
+ s.connected = 0;
+}
+/*---------------------------------------------------------------------------*/
+/** @} */
+/** @} */
diff --git a/uip/apps/smtp/smtp.h b/uip/apps/smtp/smtp.h
new file mode 100644
index 0000000..44d0766
--- /dev/null
+++ b/uip/apps/smtp/smtp.h
@@ -0,0 +1,103 @@
+
+/**
+ * \addtogroup smtp
+ * @{
+ */
+
+
+/**
+ * \file
+ * SMTP header file
+ * \author Adam Dunkels <adam@dunkels.com>
+ */
+
+/*
+ * Copyright (c) 2002, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: smtp.h,v 1.4 2006/06/11 21:46:37 adam Exp $
+ *
+ */
+#ifndef __SMTP_H__
+#define __SMTP_H__
+
+#include "uipopt.h"
+
+/**
+ * Error number that signifies a non-error condition.
+ */
+#define SMTP_ERR_OK 0
+
+/**
+ * Callback function that is called when an e-mail transmission is
+ * done.
+ *
+ * This function must be implemented by the module that uses the SMTP
+ * module.
+ *
+ * \param error The number of the error if an error occured, or
+ * SMTP_ERR_OK.
+ */
+void smtp_done(unsigned char error);
+
+void smtp_init(void);
+
+/* Functions. */
+void smtp_configure(char *localhostname, u16_t *smtpserver);
+unsigned char smtp_send(char *to, char *from,
+ char *subject, char *msg,
+ u16_t msglen);
+#define SMTP_SEND(to, cc, from, subject, msg) \
+ smtp_send(to, cc, from, subject, msg, strlen(msg))
+
+void smtp_appcall(void);
+
+struct smtp_state {
+ u8_t state;
+ char *to;
+ char *from;
+ char *subject;
+ char *msg;
+ u16_t msglen;
+
+ u16_t sentlen, textlen;
+ u16_t sendptr;
+
+};
+
+
+#ifndef UIP_APPCALL
+#define UIP_APPCALL smtp_appcall
+#endif
+typedef struct smtp_state uip_tcp_appstate_t;
+
+
+#endif /* __SMTP_H__ */
+
+/** @} */
diff --git a/uip/apps/telnet/Makefile.telnet b/uip/apps/telnet/Makefile.telnet
new file mode 100644
index 0000000..8b94786
--- /dev/null
+++ b/uip/apps/telnet/Makefile.telnet
@@ -0,0 +1 @@
+APP_SOURCES += telnet.c
diff --git a/uip/apps/telnet/telnet.c b/uip/apps/telnet/telnet.c
new file mode 100644
index 0000000..f72b6fc
--- /dev/null
+++ b/uip/apps/telnet/telnet.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2002, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: telnet.c,v 1.1.2.3 2003/10/06 11:20:45 adam Exp $
+ *
+ */
+
+#include "uip.h"
+
+#include "telnet.h"
+
+#ifndef NULL
+#define NULL (void *)0
+#endif /* NULL */
+
+#define FLAG_CLOSE 1
+#define FLAG_ABORT 2
+/*-----------------------------------------------------------------------------------*/
+unsigned char
+telnet_send(struct telnet_state *s, char *text, u16_t len)
+{
+ if(s->text != NULL) {
+ return 1;
+ }
+ s->text = text;
+ s->textlen = len;
+ s->sentlen = 0;
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+unsigned char
+telnet_close(struct telnet_state *s)
+{
+ s->flags = FLAG_CLOSE;
+ if(s->text != NULL) {
+ return 1;
+ }
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+unsigned char
+telnet_abort(struct telnet_state *s)
+{
+ s->flags = FLAG_ABORT;
+ if(s->text != NULL) {
+ return 1;
+ }
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+acked(struct telnet_state *s)
+{
+ s->textlen -= s->sentlen;
+ if(s->textlen == 0) {
+ s->text = NULL;
+ telnet_sent(s);
+ } else {
+ s->text += s->sentlen;
+ }
+ s->sentlen = 0;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+senddata(struct telnet_state *s)
+{
+ if(s->text == NULL) {
+ uip_send(s->text, 0);
+ return;
+ }
+ if(s->textlen > uip_mss()) {
+ s->sentlen = uip_mss();
+ } else {
+ s->sentlen = s->textlen;
+ }
+ uip_send(s->text, s->sentlen);
+}
+/*-----------------------------------------------------------------------------------*/
+void telnet_app(void)
+{
+ struct telnet_state *s = (struct telnet_state *)uip_conn->appstate;
+
+ if(uip_connected()) {
+ s->flags = 0;
+ telnet_connected(s);
+ senddata(s);
+ return;
+ }
+
+ if(uip_closed()) {
+ telnet_closed(s);
+ }
+
+ if(uip_aborted()) {
+ telnet_aborted(s);
+ }
+ if(uip_timedout()) {
+ telnet_timedout(s);
+ }
+
+
+ if(s->flags & FLAG_CLOSE) {
+ uip_close();
+ return;
+ }
+ if(s->flags & FLAG_ABORT) {
+ uip_abort();
+ return;
+ }
+ if(uip_acked()) {
+ acked(s);
+ }
+ if(uip_newdata()) {
+ telnet_newdata(s, (char *)uip_appdata, uip_datalen());
+ }
+ if(uip_rexmit() ||
+ uip_newdata() ||
+ uip_acked()) {
+ senddata(s);
+ } else if(uip_poll()) {
+ senddata(s);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
diff --git a/uip/apps/telnet/telnet.h b/uip/apps/telnet/telnet.h
new file mode 100644
index 0000000..a48c8ee
--- /dev/null
+++ b/uip/apps/telnet/telnet.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2002, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: telnet.h,v 1.1.2.4 2003/10/06 22:56:45 adam Exp $
+ *
+ */
+#ifndef __TELNET_H__
+#define __TELNET_H__
+
+struct telnet_state {
+ unsigned char flags;
+ char *text;
+ u16_t textlen;
+ u16_t sentlen;
+};
+
+typedef struct telnet_state uip_tcp_appstate_t;
+void telnet_app(void);
+
+#ifndef UIP_APPCALL
+#define UIP_APPCALL telnet_app
+#endif
+
+#ifndef UIP_APPSTATE_SIZE
+#define UIP_APPSTATE_SIZE (sizeof(struct telnet_state))
+#endif
+
+
+unsigned char telnet_send(struct telnet_state *s, char *text, u16_t len);
+unsigned char telnet_close(struct telnet_state *s);
+unsigned char telnet_abort(struct telnet_state *s);
+
+/* Callbacks, must be implemented by the caller. */
+void telnet_connected(struct telnet_state *s);
+void telnet_closed(struct telnet_state *s);
+void telnet_sent(struct telnet_state *s);
+void telnet_aborted(struct telnet_state *s);
+void telnet_timedout(struct telnet_state *s);
+void telnet_newdata(struct telnet_state *s, char *data, u16_t len);
+#endif /* __TELNET_H__ */
diff --git a/uip/apps/telnetd/Makefile.telnetd b/uip/apps/telnetd/Makefile.telnetd
new file mode 100644
index 0000000..afb1b59
--- /dev/null
+++ b/uip/apps/telnetd/Makefile.telnetd
@@ -0,0 +1 @@
+APP_SOURCES += telnetd.c shell.c memb.c
diff --git a/uip/apps/telnetd/shell.c b/uip/apps/telnetd/shell.c
new file mode 100644
index 0000000..9345cae
--- /dev/null
+++ b/uip/apps/telnetd/shell.c
@@ -0,0 +1,123 @@
+ /*
+ * Copyright (c) 2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: shell.c,v 1.1 2006/06/07 09:43:54 adam Exp $
+ *
+ */
+
+#include "shell.h"
+
+#include <string.h>
+
+struct ptentry {
+ char *commandstr;
+ void (* pfunc)(char *str);
+};
+
+#define SHELL_PROMPT "uIP 1.0> "
+
+/*---------------------------------------------------------------------------*/
+static void
+parse(register char *str, struct ptentry *t)
+{
+ struct ptentry *p;
+ for(p = t; p->commandstr != NULL; ++p) {
+ if(strncmp(p->commandstr, str, strlen(p->commandstr)) == 0) {
+ break;
+ }
+ }
+
+ p->pfunc(str);
+}
+/*---------------------------------------------------------------------------*/
+static void
+inttostr(register char *str, unsigned int i)
+{
+ str[0] = '0' + i / 100;
+ if(str[0] == '0') {
+ str[0] = ' ';
+ }
+ str[1] = '0' + (i / 10) % 10;
+ if(str[0] == ' ' && str[1] == '0') {
+ str[1] = ' ';
+ }
+ str[2] = '0' + i % 10;
+ str[3] = ' ';
+ str[4] = 0;
+}
+/*---------------------------------------------------------------------------*/
+static void
+help(char *str)
+{
+ shell_output("Available commands:", "");
+ shell_output("stats - show network statistics", "");
+ shell_output("conn - show TCP connections", "");
+ shell_output("help, ? - show help", "");
+ shell_output("exit - exit shell", "");
+}
+/*---------------------------------------------------------------------------*/
+static void
+unknown(char *str)
+{
+ if(strlen(str) > 0) {
+ shell_output("Unknown command: ", str);
+ }
+}
+/*---------------------------------------------------------------------------*/
+static struct ptentry parsetab[] =
+ {{"stats", help},
+ {"conn", help},
+ {"help", help},
+ {"exit", shell_quit},
+ {"?", help},
+
+ /* Default action */
+ {NULL, unknown}};
+/*---------------------------------------------------------------------------*/
+void
+shell_init(void)
+{
+}
+/*---------------------------------------------------------------------------*/
+void
+shell_start(void)
+{
+ shell_output("uIP command shell", "");
+ shell_output("Type '?' and return for help", "");
+ shell_prompt(SHELL_PROMPT);
+}
+/*---------------------------------------------------------------------------*/
+void
+shell_input(char *cmd)
+{
+ parse(cmd, parsetab);
+ shell_prompt(SHELL_PROMPT);
+}
+/*---------------------------------------------------------------------------*/
diff --git a/uip/apps/telnetd/shell.h b/uip/apps/telnetd/shell.h
new file mode 100644
index 0000000..b57d7be
--- /dev/null
+++ b/uip/apps/telnetd/shell.h
@@ -0,0 +1,104 @@
+/**
+ * \file
+ * Interface for the Contiki shell.
+ * \author Adam Dunkels <adam@dunkels.com>
+ *
+ * Some of the functions declared in this file must be implemented as
+ * a shell back-end in the architecture specific files of a Contiki
+ * port.
+ */
+
+
+/*
+ * Copyright (c) 2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the Contiki desktop OS.
+ *
+ * $Id: shell.h,v 1.1 2006/06/07 09:43:54 adam Exp $
+ *
+ */
+#ifndef __SHELL_H__
+#define __SHELL_H__
+
+/**
+ * Initialize the shell.
+ *
+ * Called when the shell front-end process starts. This function may
+ * be used to start listening for signals.
+ */
+void shell_init(void);
+
+/**
+ * Start the shell back-end.
+ *
+ * Called by the front-end when a new shell is started.
+ */
+void shell_start(void);
+
+/**
+ * Process a shell command.
+ *
+ * This function will be called by the shell GUI / telnet server whan
+ * a command has been entered that should be processed by the shell
+ * back-end.
+ *
+ * \param command The command to be processed.
+ */
+void shell_input(char *command);
+
+/**
+ * Quit the shell.
+ *
+ */
+void shell_quit(char *);
+
+
+/**
+ * Print a string to the shell window.
+ *
+ * This function is implemented by the shell GUI / telnet server and
+ * can be called by the shell back-end to output a string in the
+ * shell window. The string is automatically appended with a linebreak.
+ *
+ * \param str1 The first half of the string to be output.
+ * \param str2 The second half of the string to be output.
+ */
+void shell_output(char *str1, char *str2);
+
+/**
+ * Print a prompt to the shell window.
+ *
+ * This function can be used by the shell back-end to print out a
+ * prompt to the shell window.
+ *
+ * \param prompt The prompt to be printed.
+ *
+ */
+void shell_prompt(char *prompt);
+
+#endif /* __SHELL_H__ */
diff --git a/uip/apps/telnetd/telnetd.c b/uip/apps/telnetd/telnetd.c
new file mode 100644
index 0000000..7a5ae85
--- /dev/null
+++ b/uip/apps/telnetd/telnetd.c
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: telnetd.c,v 1.2 2006/06/07 09:43:54 adam Exp $
+ *
+ */
+
+#include "uip.h"
+#include "telnetd.h"
+#include "memb.h"
+#include "shell.h"
+
+#include <string.h>
+
+#define ISO_nl 0x0a
+#define ISO_cr 0x0d
+
+struct telnetd_line {
+ char line[TELNETD_CONF_LINELEN];
+};
+MEMB(linemem, struct telnetd_line, TELNETD_CONF_NUMLINES);
+
+#define STATE_NORMAL 0
+#define STATE_IAC 1
+#define STATE_WILL 2
+#define STATE_WONT 3
+#define STATE_DO 4
+#define STATE_DONT 5
+#define STATE_CLOSE 6
+
+static struct telnetd_state s;
+
+#define TELNET_IAC 255
+#define TELNET_WILL 251
+#define TELNET_WONT 252
+#define TELNET_DO 253
+#define TELNET_DONT 254
+/*---------------------------------------------------------------------------*/
+static char *
+alloc_line(void)
+{
+ return memb_alloc(&linemem);
+}
+/*---------------------------------------------------------------------------*/
+static void
+dealloc_line(char *line)
+{
+ memb_free(&linemem, line);
+}
+/*---------------------------------------------------------------------------*/
+void
+shell_quit(char *str)
+{
+ s.state = STATE_CLOSE;
+}
+/*---------------------------------------------------------------------------*/
+static void
+sendline(char *line)
+{
+ static unsigned int i;
+
+ for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
+ if(s.lines[i] == NULL) {
+ s.lines[i] = line;
+ break;
+ }
+ }
+ if(i == TELNETD_CONF_NUMLINES) {
+ dealloc_line(line);
+ }
+}
+/*---------------------------------------------------------------------------*/
+void
+shell_prompt(char *str)
+{
+ char *line;
+ line = alloc_line();
+ if(line != NULL) {
+ strncpy(line, str, TELNETD_CONF_LINELEN);
+ /* petsciiconv_toascii(line, TELNETD_CONF_LINELEN);*/
+ sendline(line);
+ }
+}
+/*---------------------------------------------------------------------------*/
+void
+shell_output(char *str1, char *str2)
+{
+ static unsigned len;
+ char *line;
+
+ line = alloc_line();
+ if(line != NULL) {
+ len = strlen(str1);
+ strncpy(line, str1, TELNETD_CONF_LINELEN);
+ if(len < TELNETD_CONF_LINELEN) {
+ strncpy(line + len, str2, TELNETD_CONF_LINELEN - len);
+ }
+ len = strlen(line);
+ if(len < TELNETD_CONF_LINELEN - 2) {
+ line[len] = ISO_cr;
+ line[len+1] = ISO_nl;
+ line[len+2] = 0;
+ }
+ /* petsciiconv_toascii(line, TELNETD_CONF_LINELEN);*/
+ sendline(line);
+ }
+}
+/*---------------------------------------------------------------------------*/
+void
+telnetd_init(void)
+{
+ uip_listen(HTONS(23));
+ memb_init(&linemem);
+ shell_init();
+}
+/*---------------------------------------------------------------------------*/
+static void
+acked(void)
+{
+ static unsigned int i;
+
+ while(s.numsent > 0) {
+ dealloc_line(s.lines[0]);
+ for(i = 1; i < TELNETD_CONF_NUMLINES; ++i) {
+ s.lines[i - 1] = s.lines[i];
+ }
+ s.lines[TELNETD_CONF_NUMLINES - 1] = NULL;
+ --s.numsent;
+ }
+}
+/*---------------------------------------------------------------------------*/
+static void
+senddata(void)
+{
+ static char *bufptr, *lineptr;
+ static int buflen, linelen;
+
+ bufptr = uip_appdata;
+ buflen = 0;
+ for(s.numsent = 0; s.numsent < TELNETD_CONF_NUMLINES &&
+ s.lines[s.numsent] != NULL ; ++s.numsent) {
+ lineptr = s.lines[s.numsent];
+ linelen = strlen(lineptr);
+ if(linelen > TELNETD_CONF_LINELEN) {
+ linelen = TELNETD_CONF_LINELEN;
+ }
+ if(buflen + linelen < uip_mss()) {
+ memcpy(bufptr, lineptr, linelen);
+ bufptr += linelen;
+ buflen += linelen;
+ } else {
+ break;
+ }
+ }
+ uip_send(uip_appdata, buflen);
+}
+/*---------------------------------------------------------------------------*/
+static void
+closed(void)
+{
+ static unsigned int i;
+
+ for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
+ if(s.lines[i] != NULL) {
+ dealloc_line(s.lines[i]);
+ }
+ }
+}
+/*---------------------------------------------------------------------------*/
+static void
+get_char(u8_t c)
+{
+ if(c == ISO_cr) {
+ return;
+ }
+
+ s.buf[(int)s.bufptr] = c;
+ if(s.buf[(int)s.bufptr] == ISO_nl ||
+ s.bufptr == sizeof(s.buf) - 1) {
+ if(s.bufptr > 0) {
+ s.buf[(int)s.bufptr] = 0;
+ /* petsciiconv_topetscii(s.buf, TELNETD_CONF_LINELEN);*/
+ }
+ shell_input(s.buf);
+ s.bufptr = 0;
+ } else {
+ ++s.bufptr;
+ }
+}
+/*---------------------------------------------------------------------------*/
+static void
+sendopt(u8_t option, u8_t value)
+{
+ char *line;
+ line = alloc_line();
+ if(line != NULL) {
+ line[0] = TELNET_IAC;
+ line[1] = option;
+ line[2] = value;
+ line[3] = 0;
+ sendline(line);
+ }
+}
+/*---------------------------------------------------------------------------*/
+static void
+newdata(void)
+{
+ u16_t len;
+ u8_t c;
+ char *dataptr;
+
+
+ len = uip_datalen();
+ dataptr = (char *)uip_appdata;
+
+ while(len > 0 && s.bufptr < sizeof(s.buf)) {
+ c = *dataptr;
+ ++dataptr;
+ --len;
+ switch(s.state) {
+ case STATE_IAC:
+ if(c == TELNET_IAC) {
+ get_char(c);
+ s.state = STATE_NORMAL;
+ } else {
+ switch(c) {
+ case TELNET_WILL:
+ s.state = STATE_WILL;
+ break;
+ case TELNET_WONT:
+ s.state = STATE_WONT;
+ break;
+ case TELNET_DO:
+ s.state = STATE_DO;
+ break;
+ case TELNET_DONT:
+ s.state = STATE_DONT;
+ break;
+ default:
+ s.state = STATE_NORMAL;
+ break;
+ }
+ }
+ break;
+ case STATE_WILL:
+ /* Reply with a DONT */
+ sendopt(TELNET_DONT, c);
+ s.state = STATE_NORMAL;
+ break;
+
+ case STATE_WONT:
+ /* Reply with a DONT */
+ sendopt(TELNET_DONT, c);
+ s.state = STATE_NORMAL;
+ break;
+ case STATE_DO:
+ /* Reply with a WONT */
+ sendopt(TELNET_WONT, c);
+ s.state = STATE_NORMAL;
+ break;
+ case STATE_DONT:
+ /* Reply with a WONT */
+ sendopt(TELNET_WONT, c);
+ s.state = STATE_NORMAL;
+ break;
+ case STATE_NORMAL:
+ if(c == TELNET_IAC) {
+ s.state = STATE_IAC;
+ } else {
+ get_char(c);
+ }
+ break;
+ }
+
+
+ }
+
+}
+/*---------------------------------------------------------------------------*/
+void
+telnetd_appcall(void)
+{
+ static unsigned int i;
+ if(uip_connected()) {
+ /* tcp_markconn(uip_conn, &s);*/
+ for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) {
+ s.lines[i] = NULL;
+ }
+ s.bufptr = 0;
+ s.state = STATE_NORMAL;
+
+ shell_start();
+ }
+
+ if(s.state == STATE_CLOSE) {
+ s.state = STATE_NORMAL;
+ uip_close();
+ return;
+ }
+
+ if(uip_closed() ||
+ uip_aborted() ||
+ uip_timedout()) {
+ closed();
+ }
+
+ if(uip_acked()) {
+ acked();
+ }
+
+ if(uip_newdata()) {
+ newdata();
+ }
+
+ if(uip_rexmit() ||
+ uip_newdata() ||
+ uip_acked() ||
+ uip_connected() ||
+ uip_poll()) {
+ senddata();
+ }
+}
+/*---------------------------------------------------------------------------*/
diff --git a/uip/apps/telnetd/telnetd.h b/uip/apps/telnetd/telnetd.h
new file mode 100644
index 0000000..2ee8acd
--- /dev/null
+++ b/uip/apps/telnetd/telnetd.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: telnetd.h,v 1.2 2006/06/07 09:43:54 adam Exp $
+ *
+ */
+#ifndef __TELNETD_H__
+#define __TELNETD_H__
+
+#include "uipopt.h"
+
+void telnetd_appcall(void);
+
+#ifndef TELNETD_CONF_LINELEN
+#define TELNETD_CONF_LINELEN 40
+#endif
+#ifndef TELNETD_CONF_NUMLINES
+#define TELNETD_CONF_NUMLINES 16
+#endif
+
+struct telnetd_state {
+ char *lines[TELNETD_CONF_NUMLINES];
+ char buf[TELNETD_CONF_LINELEN];
+ char bufptr;
+ u8_t numsent;
+ u8_t state;
+};
+
+typedef struct telnetd_state uip_tcp_appstate_t;
+
+#ifndef UIP_APPCALL
+#define UIP_APPCALL telnetd_appcall
+#endif
+
+#endif /* __TELNETD_H__ */
diff --git a/uip/apps/webclient/Makefile.webclient b/uip/apps/webclient/Makefile.webclient
new file mode 100644
index 0000000..e6e7f08
--- /dev/null
+++ b/uip/apps/webclient/Makefile.webclient
@@ -0,0 +1 @@
+APP_SOURCES += webclient-strings.c webclient.c
diff --git a/uip/apps/webclient/makestrings b/uip/apps/webclient/makestrings
new file mode 100755
index 0000000..6dec075
--- /dev/null
+++ b/uip/apps/webclient/makestrings
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+
+
+sub stringify {
+ my $name = shift(@_);
+ open(OUTPUTC, "> $name.c");
+ open(OUTPUTH, "> $name.h");
+
+ open(FILE, "$name");
+
+ while(<FILE>) {
+ if(/(.+) "(.+)"/) {
+ $var = $1;
+ $data = $2;
+
+ $datan = $data;
+ $datan =~ s/\\r/\r/g;
+ $datan =~ s/\\n/\n/g;
+ $datan =~ s/\\01/\01/g;
+ $datan =~ s/\\0/\0/g;
+
+ printf(OUTPUTC "const char $var\[%d] = \n", length($datan) + 1);
+ printf(OUTPUTC "/* \"$data\" */\n");
+ printf(OUTPUTC "{");
+ for($j = 0; $j < length($datan); $j++) {
+ printf(OUTPUTC "%#02x, ", unpack("C", substr($datan, $j, 1)));
+ }
+ printf(OUTPUTC "0 };\n");
+
+ printf(OUTPUTH "extern const char $var\[%d];\n", length($datan) + 1);
+
+ }
+ }
+ close(OUTPUTC);
+ close(OUTPUTH);
+}
+stringify("webclient-strings");
+
+exit 0;
+
diff --git a/uip/apps/webclient/webclient-strings b/uip/apps/webclient/webclient-strings
new file mode 100644
index 0000000..a331397
--- /dev/null
+++ b/uip/apps/webclient/webclient-strings
@@ -0,0 +1,31 @@
+http_http "http://"
+http_200 "200 "
+http_301 "301 "
+http_302 "302 "
+http_get "GET "
+http_10 "HTTP/1.0"
+http_11 "HTTP/1.1"
+http_content_type "content-type: "
+http_texthtml "text/html"
+http_location "location: "
+http_host "host: "
+http_crnl "\r\n"
+http_index_html "/index.html"
+http_404_html "/404.html"
+http_content_type_html "Content-type: text/html\r\n\r\n"
+http_content_type_css "Content-type: text/css\r\n\r\n"
+http_content_type_text "Content-type: text/text\r\n\r\n"
+http_content_type_png "Content-type: image/png\r\n\r\n"
+http_content_type_gif "Content-type: image/gif\r\n\r\n"
+http_content_type_jpg "Content-type: image/jpeg\r\n\r\n"
+http_content_type_binary "Content-type: application/octet-stream\r\n\r\n"
+http_html ".html"
+http_shtml ".shtml"
+http_htm ".htm"
+http_css ".css"
+http_png ".png"
+http_gif ".gif"
+http_jpg ".jpg"
+http_text ".text"
+http_txt ".txt"
+http_user_agent_fields "Connection: close\r\nUser-Agent: uIP/1.0 (; http://www.sics.se/~adam/uip/)\r\n\r\n"
diff --git a/uip/apps/webclient/webclient-strings.c b/uip/apps/webclient/webclient-strings.c
new file mode 100644
index 0000000..9472330
--- /dev/null
+++ b/uip/apps/webclient/webclient-strings.c
@@ -0,0 +1,93 @@
+const char http_http[8] =
+/* "http://" */
+{0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0 };
+const char http_200[5] =
+/* "200 " */
+{0x32, 0x30, 0x30, 0x20, 0 };
+const char http_301[5] =
+/* "301 " */
+{0x33, 0x30, 0x31, 0x20, 0 };
+const char http_302[5] =
+/* "302 " */
+{0x33, 0x30, 0x32, 0x20, 0 };
+const char http_get[5] =
+/* "GET " */
+{0x47, 0x45, 0x54, 0x20, 0 };
+const char http_10[9] =
+/* "HTTP/1.0" */
+{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0 };
+const char http_11[9] =
+/* "HTTP/1.1" */
+{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0 };
+const char http_content_type[15] =
+/* "content-type: " */
+{0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0 };
+const char http_texthtml[10] =
+/* "text/html" */
+{0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0 };
+const char http_location[11] =
+/* "location: " */
+{0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0 };
+const char http_host[7] =
+/* "host: " */
+{0x68, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0 };
+const char http_crnl[3] =
+/* "\r\n" */
+{0xd, 0xa, 0 };
+const char http_index_html[12] =
+/* "/index.html" */
+{0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0 };
+const char http_404_html[10] =
+/* "/404.html" */
+{0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0 };
+const char http_content_type_html[28] =
+/* "Content-type: text/html\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, 0 };
+const char http_content_type_css [27] =
+/* "Content-type: text/css\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, 0xd, 0xa, 0xd, 0xa, 0 };
+const char http_content_type_text[28] =
+/* "Content-type: text/text\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x74, 0x65, 0x78, 0x74, 0xd, 0xa, 0xd, 0xa, 0 };
+const char http_content_type_png [28] =
+/* "Content-type: image/png\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0xd, 0xa, 0xd, 0xa, 0 };
+const char http_content_type_gif [28] =
+/* "Content-type: image/gif\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, 0x69, 0x66, 0xd, 0xa, 0xd, 0xa, 0 };
+const char http_content_type_jpg [29] =
+/* "Content-type: image/jpeg\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x65, 0x67, 0xd, 0xa, 0xd, 0xa, 0 };
+const char http_content_type_binary[43] =
+/* "Content-type: application/octet-stream\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0xd, 0xa, 0xd, 0xa, 0 };
+const char http_html[6] =
+/* ".html" */
+{0x2e, 0x68, 0x74, 0x6d, 0x6c, 0 };
+const char http_shtml[7] =
+/* ".shtml" */
+{0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0 };
+const char http_htm[5] =
+/* ".htm" */
+{0x2e, 0x68, 0x74, 0x6d, 0 };
+const char http_css[5] =
+/* ".css" */
+{0x2e, 0x63, 0x73, 0x73, 0 };
+const char http_png[5] =
+/* ".png" */
+{0x2e, 0x70, 0x6e, 0x67, 0 };
+const char http_gif[5] =
+/* ".gif" */
+{0x2e, 0x67, 0x69, 0x66, 0 };
+const char http_jpg[5] =
+/* ".jpg" */
+{0x2e, 0x6a, 0x70, 0x67, 0 };
+const char http_text[6] =
+/* ".text" */
+{0x2e, 0x74, 0x65, 0x78, 0x74, 0 };
+const char http_txt[5] =
+/* ".txt" */
+{0x2e, 0x74, 0x78, 0x74, 0 };
+const char http_user_agent_fields[77] =
+/* "Connection: close\r\nUser-Agent: uIP/1.0 (; http://www.sics.se/~adam/uip/)\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0xd, 0xa, 0x55, 0x73, 0x65, 0x72, 0x2d, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x28, 0x3b, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x2f, 0x7e, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0xd, 0xa, 0 };
diff --git a/uip/apps/webclient/webclient-strings.h b/uip/apps/webclient/webclient-strings.h
new file mode 100644
index 0000000..9e3ec93
--- /dev/null
+++ b/uip/apps/webclient/webclient-strings.h
@@ -0,0 +1,31 @@
+extern const char http_http[8];
+extern const char http_200[5];
+extern const char http_301[5];
+extern const char http_302[5];
+extern const char http_get[5];
+extern const char http_10[9];
+extern const char http_11[9];
+extern const char http_content_type[15];
+extern const char http_texthtml[10];
+extern const char http_location[11];
+extern const char http_host[7];
+extern const char http_crnl[3];
+extern const char http_index_html[12];
+extern const char http_404_html[10];
+extern const char http_content_type_html[28];
+extern const char http_content_type_css [27];
+extern const char http_content_type_text[28];
+extern const char http_content_type_png [28];
+extern const char http_content_type_gif [28];
+extern const char http_content_type_jpg [29];
+extern const char http_content_type_binary[43];
+extern const char http_html[6];
+extern const char http_shtml[7];
+extern const char http_htm[5];
+extern const char http_css[5];
+extern const char http_png[5];
+extern const char http_gif[5];
+extern const char http_jpg[5];
+extern const char http_text[6];
+extern const char http_txt[5];
+extern const char http_user_agent_fields[77];
diff --git a/uip/apps/webclient/webclient.c b/uip/apps/webclient/webclient.c
new file mode 100644
index 0000000..746c008
--- /dev/null
+++ b/uip/apps/webclient/webclient.c
@@ -0,0 +1,439 @@
+/**
+ * \addtogroup apps
+ * @{
+ */
+
+/**
+ * \defgroup webclient Web client
+ * @{
+ *
+ * This example shows a HTTP client that is able to download web pages
+ * and files from web servers. It requires a number of callback
+ * functions to be implemented by the module that utilizes the code:
+ * webclient_datahandler(), webclient_connected(),
+ * webclient_timedout(), webclient_aborted(), webclient_closed().
+ */
+
+/**
+ * \file
+ * Implementation of the HTTP client.
+ * \author Adam Dunkels <adam@dunkels.com>
+ */
+
+/*
+ * Copyright (c) 2002, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: webclient.c,v 1.2 2006/06/11 21:46:37 adam Exp $
+ *
+ */
+
+#include "uip.h"
+#include "uiplib.h"
+#include "webclient.h"
+#include "resolv.h"
+
+#include <string.h>
+
+#define WEBCLIENT_TIMEOUT 100
+
+#define WEBCLIENT_STATE_STATUSLINE 0
+#define WEBCLIENT_STATE_HEADERS 1
+#define WEBCLIENT_STATE_DATA 2
+#define WEBCLIENT_STATE_CLOSE 3
+
+#define HTTPFLAG_NONE 0
+#define HTTPFLAG_OK 1
+#define HTTPFLAG_MOVED 2
+#define HTTPFLAG_ERROR 3
+
+
+#define ISO_nl 0x0a
+#define ISO_cr 0x0d
+#define ISO_space 0x20
+
+
+static struct webclient_state s;
+
+/*-----------------------------------------------------------------------------------*/
+char *
+webclient_mimetype(void)
+{
+ return s.mimetype;
+}
+/*-----------------------------------------------------------------------------------*/
+char *
+webclient_filename(void)
+{
+ return s.file;
+}
+/*-----------------------------------------------------------------------------------*/
+char *
+webclient_hostname(void)
+{
+ return s.host;
+}
+/*-----------------------------------------------------------------------------------*/
+unsigned short
+webclient_port(void)
+{
+ return s.port;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+webclient_init(void)
+{
+
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+init_connection(void)
+{
+ s.state = WEBCLIENT_STATE_STATUSLINE;
+
+ s.getrequestleft = sizeof(http_get) - 1 + 1 +
+ sizeof(http_10) - 1 +
+ sizeof(http_crnl) - 1 +
+ sizeof(http_host) - 1 +
+ sizeof(http_crnl) - 1 +
+ strlen(http_user_agent_fields) +
+ strlen(s.file) + strlen(s.host);
+ s.getrequestptr = 0;
+
+ s.httpheaderlineptr = 0;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+webclient_close(void)
+{
+ s.state = WEBCLIENT_STATE_CLOSE;
+}
+/*-----------------------------------------------------------------------------------*/
+unsigned char
+webclient_get(char *host, u16_t port, char *file)
+{
+ struct uip_conn *conn;
+ uip_ipaddr_t *ipaddr;
+ static uip_ipaddr_t addr;
+
+ /* First check if the host is an IP address. */
+ ipaddr = &addr;
+ if(uiplib_ipaddrconv(host, (unsigned char *)addr) == 0) {
+ ipaddr = (uip_ipaddr_t *)resolv_lookup(host);
+
+ if(ipaddr == NULL) {
+ return 0;
+ }
+ }
+
+ conn = uip_connect(ipaddr, htons(port));
+
+ if(conn == NULL) {
+ return 0;
+ }
+
+ s.port = port;
+ strncpy(s.file, file, sizeof(s.file));
+ strncpy(s.host, host, sizeof(s.host));
+
+ init_connection();
+ return 1;
+}
+/*-----------------------------------------------------------------------------------*/
+static unsigned char *
+copy_string(unsigned char *dest,
+ const unsigned char *src, unsigned char len)
+{
+ strncpy(dest, src, len);
+ return dest + len;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+senddata(void)
+{
+ u16_t len;
+ char *getrequest;
+ char *cptr;
+
+ if(s.getrequestleft > 0) {
+ cptr = getrequest = (char *)uip_appdata;
+
+ cptr = copy_string(cptr, http_get, sizeof(http_get) - 1);
+ cptr = copy_string(cptr, s.file, strlen(s.file));
+ *cptr++ = ISO_space;
+ cptr = copy_string(cptr, http_10, sizeof(http_10) - 1);
+
+ cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1);
+
+ cptr = copy_string(cptr, http_host, sizeof(http_host) - 1);
+ cptr = copy_string(cptr, s.host, strlen(s.host));
+ cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1);
+
+ cptr = copy_string(cptr, http_user_agent_fields,
+ strlen(http_user_agent_fields));
+
+ len = s.getrequestleft > uip_mss()?
+ uip_mss():
+ s.getrequestleft;
+ uip_send(&(getrequest[s.getrequestptr]), len);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+acked(void)
+{
+ u16_t len;
+
+ if(s.getrequestleft > 0) {
+ len = s.getrequestleft > uip_mss()?
+ uip_mss():
+ s.getrequestleft;
+ s.getrequestleft -= len;
+ s.getrequestptr += len;
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+static u16_t
+parse_statusline(u16_t len)
+{
+ char *cptr;
+
+ while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline)) {
+ s.httpheaderline[s.httpheaderlineptr] = *(char *)uip_appdata;
+ ++((char *)uip_appdata);
+ --len;
+ if(s.httpheaderline[s.httpheaderlineptr] == ISO_nl) {
+
+ if((strncmp(s.httpheaderline, http_10,
+ sizeof(http_10) - 1) == 0) ||
+ (strncmp(s.httpheaderline, http_11,
+ sizeof(http_11) - 1) == 0)) {
+ cptr = &(s.httpheaderline[9]);
+ s.httpflag = HTTPFLAG_NONE;
+ if(strncmp(cptr, http_200, sizeof(http_200) - 1) == 0) {
+ /* 200 OK */
+ s.httpflag = HTTPFLAG_OK;
+ } else if(strncmp(cptr, http_301, sizeof(http_301) - 1) == 0 ||
+ strncmp(cptr, http_302, sizeof(http_302) - 1) == 0) {
+ /* 301 Moved permanently or 302 Found. Location: header line
+ will contain thw new location. */
+ s.httpflag = HTTPFLAG_MOVED;
+ } else {
+ s.httpheaderline[s.httpheaderlineptr - 1] = 0;
+ }
+ } else {
+ uip_abort();
+ webclient_aborted();
+ return 0;
+ }
+
+ /* We're done parsing the status line, so we reset the pointer
+ and start parsing the HTTP headers.*/
+ s.httpheaderlineptr = 0;
+ s.state = WEBCLIENT_STATE_HEADERS;
+ break;
+ } else {
+ ++s.httpheaderlineptr;
+ }
+ }
+ return len;
+}
+/*-----------------------------------------------------------------------------------*/
+static char
+casecmp(char *str1, const char *str2, char len)
+{
+ static char c;
+
+ while(len > 0) {
+ c = *str1;
+ /* Force lower-case characters. */
+ if(c & 0x40) {
+ c |= 0x20;
+ }
+ if(*str2 != c) {
+ return 1;
+ }
+ ++str1;
+ ++str2;
+ --len;
+ }
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+static u16_t
+parse_headers(u16_t len)
+{
+ char *cptr;
+ static unsigned char i;
+
+ while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline)) {
+ s.httpheaderline[s.httpheaderlineptr] = *(char *)uip_appdata;
+ ++((char *)uip_appdata);
+ --len;
+ if(s.httpheaderline[s.httpheaderlineptr] == ISO_nl) {
+ /* We have an entire HTTP header line in s.httpheaderline, so
+ we parse it. */
+ if(s.httpheaderline[0] == ISO_cr) {
+ /* This was the last header line (i.e., and empty "\r\n"), so
+ we are done with the headers and proceed with the actual
+ data. */
+ s.state = WEBCLIENT_STATE_DATA;
+ return len;
+ }
+
+ s.httpheaderline[s.httpheaderlineptr - 1] = 0;
+ /* Check for specific HTTP header fields. */
+ if(casecmp(s.httpheaderline, http_content_type,
+ sizeof(http_content_type) - 1) == 0) {
+ /* Found Content-type field. */
+ cptr = strchr(s.httpheaderline, ';');
+ if(cptr != NULL) {
+ *cptr = 0;
+ }
+ strncpy(s.mimetype, s.httpheaderline +
+ sizeof(http_content_type) - 1, sizeof(s.mimetype));
+ } else if(casecmp(s.httpheaderline, http_location,
+ sizeof(http_location) - 1) == 0) {
+ cptr = s.httpheaderline +
+ sizeof(http_location) - 1;
+
+ if(strncmp(cptr, http_http, 7) == 0) {
+ cptr += 7;
+ for(i = 0; i < s.httpheaderlineptr - 7; ++i) {
+ if(*cptr == 0 ||
+ *cptr == '/' ||
+ *cptr == ' ' ||
+ *cptr == ':') {
+ s.host[i] = 0;
+ break;
+ }
+ s.host[i] = *cptr;
+ ++cptr;
+ }
+ }
+ strncpy(s.file, cptr, sizeof(s.file));
+ /* s.file[s.httpheaderlineptr - i] = 0;*/
+ }
+
+
+ /* We're done parsing, so we reset the pointer and start the
+ next line. */
+ s.httpheaderlineptr = 0;
+ } else {
+ ++s.httpheaderlineptr;
+ }
+ }
+ return len;
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+newdata(void)
+{
+ u16_t len;
+
+ len = uip_datalen();
+
+ if(s.state == WEBCLIENT_STATE_STATUSLINE) {
+ len = parse_statusline(len);
+ }
+
+ if(s.state == WEBCLIENT_STATE_HEADERS && len > 0) {
+ len = parse_headers(len);
+ }
+
+ if(len > 0 && s.state == WEBCLIENT_STATE_DATA &&
+ s.httpflag != HTTPFLAG_MOVED) {
+ webclient_datahandler((char *)uip_appdata, len);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void
+webclient_appcall(void)
+{
+ if(uip_connected()) {
+ s.timer = 0;
+ s.state = WEBCLIENT_STATE_STATUSLINE;
+ senddata();
+ webclient_connected();
+ return;
+ }
+
+ if(s.state == WEBCLIENT_STATE_CLOSE) {
+ webclient_closed();
+ uip_abort();
+ return;
+ }
+
+ if(uip_aborted()) {
+ webclient_aborted();
+ }
+ if(uip_timedout()) {
+ webclient_timedout();
+ }
+
+
+ if(uip_acked()) {
+ s.timer = 0;
+ acked();
+ }
+ if(uip_newdata()) {
+ s.timer = 0;
+ newdata();
+ }
+ if(uip_rexmit() ||
+ uip_newdata() ||
+ uip_acked()) {
+ senddata();
+ } else if(uip_poll()) {
+ ++s.timer;
+ if(s.timer == WEBCLIENT_TIMEOUT) {
+ webclient_timedout();
+ uip_abort();
+ return;
+ }
+ /* senddata();*/
+ }
+
+ if(uip_closed()) {
+ if(s.httpflag != HTTPFLAG_MOVED) {
+ /* Send NULL data to signal EOF. */
+ webclient_datahandler(NULL, 0);
+ } else {
+ if(resolv_lookup(s.host) == NULL) {
+ resolv_query(s.host);
+ }
+ webclient_get(s.host, s.port, s.file);
+ }
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+
+/** @} */
+/** @} */
diff --git a/uip/apps/webclient/webclient.h b/uip/apps/webclient/webclient.h
new file mode 100644
index 0000000..44cb95c
--- /dev/null
+++ b/uip/apps/webclient/webclient.h
@@ -0,0 +1,228 @@
+/**
+ * \addtogroup webclient
+ * @{
+ */
+
+/**
+ * \file
+ * Header file for the HTTP client.
+ * \author Adam Dunkels <adam@dunkels.com>
+ */
+
+/*
+ * Copyright (c) 2002, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: webclient.h,v 1.2 2006/06/11 21:46:37 adam Exp $
+ *
+ */
+#ifndef __WEBCLIENT_H__
+#define __WEBCLIENT_H__
+
+
+#include "webclient-strings.h"
+#include "uipopt.h"
+
+#define WEBCLIENT_CONF_MAX_URLLEN 100
+
+struct webclient_state {
+ u8_t timer;
+ u8_t state;
+ u8_t httpflag;
+
+ u16_t port;
+ char host[40];
+ char file[WEBCLIENT_CONF_MAX_URLLEN];
+ u16_t getrequestptr;
+ u16_t getrequestleft;
+
+ char httpheaderline[200];
+ u16_t httpheaderlineptr;
+
+ char mimetype[32];
+};
+
+typedef struct webclient_state uip_tcp_appstate_t;
+#define UIP_APPCALL webclient_appcall
+
+/**
+ * Callback function that is called from the webclient code when HTTP
+ * data has been received.
+ *
+ * This function must be implemented by the module that uses the
+ * webclient code. The function is called from the webclient module
+ * when HTTP data has been received. The function is not called when
+ * HTTP headers are received, only for the actual data.
+ *
+ * \note This function is called many times, repetedly, when data is
+ * being received, and not once when all data has been received.
+ *
+ * \param data A pointer to the data that has been received.
+ * \param len The length of the data that has been received.
+ */
+void webclient_datahandler(char *data, u16_t len);
+
+/**
+ * Callback function that is called from the webclient code when the
+ * HTTP connection has been connected to the web server.
+ *
+ * This function must be implemented by the module that uses the
+ * webclient code.
+ */
+void webclient_connected(void);
+
+/**
+ * Callback function that is called from the webclient code if the
+ * HTTP connection to the web server has timed out.
+ *
+ * This function must be implemented by the module that uses the
+ * webclient code.
+ */
+void webclient_timedout(void);
+
+/**
+ * Callback function that is called from the webclient code if the
+ * HTTP connection to the web server has been aborted by the web
+ * server.
+ *
+ * This function must be implemented by the module that uses the
+ * webclient code.
+ */
+void webclient_aborted(void);
+
+/**
+ * Callback function that is called from the webclient code when the
+ * HTTP connection to the web server has been closed.
+ *
+ * This function must be implemented by the module that uses the
+ * webclient code.
+ */
+void webclient_closed(void);
+
+
+
+/**
+ * Initialize the webclient module.
+ */
+void webclient_init(void);
+
+/**
+ * Open an HTTP connection to a web server and ask for a file using
+ * the GET method.
+ *
+ * This function opens an HTTP connection to the specified web server
+ * and requests the specified file using the GET method. When the HTTP
+ * connection has been connected, the webclient_connected() callback
+ * function is called and when the HTTP data arrives the
+ * webclient_datahandler() callback function is called.
+ *
+ * The callback function webclient_timedout() is called if the web
+ * server could not be contacted, and the webclient_aborted() callback
+ * function is called if the HTTP connection is aborted by the web
+ * server.
+ *
+ * When the HTTP request has been completed and the HTTP connection is
+ * closed, the webclient_closed() callback function will be called.
+ *
+ * \note If the function is passed a host name, it must already be in
+ * the resolver cache in order for the function to connect to the web
+ * server. It is therefore up to the calling module to implement the
+ * resolver calls and the signal handler used for reporting a resolv
+ * query answer.
+ *
+ * \param host A pointer to a string containing either a host name or
+ * a numerical IP address in dotted decimal notation (e.g., 192.168.23.1).
+ *
+ * \param port The port number to which to connect, in host byte order.
+ *
+ * \param file A pointer to the name of the file to get.
+ *
+ * \retval 0 if the host name could not be found in the cache, or
+ * if a TCP connection could not be created.
+ *
+ * \retval 1 if the connection was initiated.
+ */
+unsigned char webclient_get(char *host, u16_t port, char *file);
+
+/**
+ * Close the currently open HTTP connection.
+ */
+void webclient_close(void);
+void webclient_appcall(void);
+
+/**
+ * Obtain the MIME type of the current HTTP data stream.
+ *
+ * \return A pointer to a string contaning the MIME type. The string
+ * may be empty if no MIME type was reported by the web server.
+ */
+char *webclient_mimetype(void);
+
+/**
+ * Obtain the filename of the current HTTP data stream.
+ *
+ * The filename of an HTTP request may be changed by the web server,
+ * and may therefore not be the same as when the original GET request
+ * was made with webclient_get(). This function is used for obtaining
+ * the current filename.
+ *
+ * \return A pointer to the current filename.
+ */
+char *webclient_filename(void);
+
+/**
+ * Obtain the hostname of the current HTTP data stream.
+ *
+ * The hostname of the web server of an HTTP request may be changed
+ * by the web server, and may therefore not be the same as when the
+ * original GET request was made with webclient_get(). This function
+ * is used for obtaining the current hostname.
+ *
+ * \return A pointer to the current hostname.
+ */
+char *webclient_hostname(void);
+
+/**
+ * Obtain the port number of the current HTTP data stream.
+ *
+ * The port number of an HTTP request may be changed by the web
+ * server, and may therefore not be the same as when the original GET
+ * request was made with webclient_get(). This function is used for
+ * obtaining the current port number.
+ *
+ * \return The port number of the current HTTP data stream, in host byte order.
+ */
+unsigned short webclient_port(void);
+
+
+
+#endif /* __WEBCLIENT_H__ */
+
+/** @} */
diff --git a/uip/apps/webserver/Makefile.webserver b/uip/apps/webserver/Makefile.webserver
new file mode 100644
index 0000000..7d3e086
--- /dev/null
+++ b/uip/apps/webserver/Makefile.webserver
@@ -0,0 +1 @@
+APP_SOURCES += httpd.c http-strings.c httpd-fs.c httpd-cgi.c
diff --git a/uip/apps/webserver/http-strings b/uip/apps/webserver/http-strings
new file mode 100644
index 0000000..d0b9121
--- /dev/null
+++ b/uip/apps/webserver/http-strings
@@ -0,0 +1,35 @@
+http_http "http://"
+http_200 "200 "
+http_301 "301 "
+http_302 "302 "
+http_get "GET "
+http_10 "HTTP/1.0"
+http_11 "HTTP/1.1"
+http_content_type "content-type: "
+http_texthtml "text/html"
+http_location "location: "
+http_host "host: "
+http_crnl "\r\n"
+http_index_html "/index.html"
+http_404_html "/404.html"
+http_referer "Referer:"
+http_header_200 "HTTP/1.0 200 OK\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n"
+http_header_404 "HTTP/1.0 404 Not found\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n"
+http_content_type_plain "Content-type: text/plain\r\n\r\n"
+http_content_type_html "Content-type: text/html\r\n\r\n"
+http_content_type_css "Content-type: text/css\r\n\r\n"
+http_content_type_text "Content-type: text/text\r\n\r\n"
+http_content_type_png "Content-type: image/png\r\n\r\n"
+http_content_type_gif "Content-type: image/gif\r\n\r\n"
+http_content_type_jpg "Content-type: image/jpeg\r\n\r\n"
+http_content_type_binary "Content-type: application/octet-stream\r\n\r\n"
+http_html ".html"
+http_shtml ".shtml"
+http_htm ".htm"
+http_css ".css"
+http_png ".png"
+http_gif ".gif"
+http_jpg ".jpg"
+http_text ".txt"
+http_txt ".txt"
+
diff --git a/uip/apps/webserver/http-strings.c b/uip/apps/webserver/http-strings.c
new file mode 100644
index 0000000..0d822ba
--- /dev/null
+++ b/uip/apps/webserver/http-strings.c
@@ -0,0 +1,102 @@
+const char http_http[8] =
+/* "http://" */
+{0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, };
+const char http_200[5] =
+/* "200 " */
+{0x32, 0x30, 0x30, 0x20, };
+const char http_301[5] =
+/* "301 " */
+{0x33, 0x30, 0x31, 0x20, };
+const char http_302[5] =
+/* "302 " */
+{0x33, 0x30, 0x32, 0x20, };
+const char http_get[5] =
+/* "GET " */
+{0x47, 0x45, 0x54, 0x20, };
+const char http_10[9] =
+/* "HTTP/1.0" */
+{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, };
+const char http_11[9] =
+/* "HTTP/1.1" */
+{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, };
+const char http_content_type[15] =
+/* "content-type: " */
+{0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, };
+const char http_texthtml[10] =
+/* "text/html" */
+{0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, };
+const char http_location[11] =
+/* "location: " */
+{0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, };
+const char http_host[7] =
+/* "host: " */
+{0x68, 0x6f, 0x73, 0x74, 0x3a, 0x20, };
+const char http_crnl[3] =
+/* "\r\n" */
+{0xd, 0xa, };
+const char http_index_html[12] =
+/* "/index.html" */
+{0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, };
+const char http_404_html[10] =
+/* "/404.html" */
+{0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, };
+const char http_referer[9] =
+/* "Referer:" */
+{0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, 0x3a, };
+const char http_header_200[84] =
+/* "HTTP/1.0 200 OK\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n" */
+{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x2f, 0x7e, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, 0x70, 0x2f, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0xd, 0xa, };
+const char http_header_404[91] =
+/* "HTTP/1.0 404 Not found\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n" */
+{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x34, 0x30, 0x34, 0x20, 0x4e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0xd, 0xa, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x2f, 0x7e, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, 0x70, 0x2f, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0xd, 0xa, };
+const char http_content_type_plain[29] =
+/* "Content-type: text/plain\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0xd, 0xa, 0xd, 0xa, };
+const char http_content_type_html[28] =
+/* "Content-type: text/html\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, };
+const char http_content_type_css [27] =
+/* "Content-type: text/css\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, 0xd, 0xa, 0xd, 0xa, };
+const char http_content_type_text[28] =
+/* "Content-type: text/text\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x74, 0x65, 0x78, 0x74, 0xd, 0xa, 0xd, 0xa, };
+const char http_content_type_png [28] =
+/* "Content-type: image/png\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0xd, 0xa, 0xd, 0xa, };
+const char http_content_type_gif [28] =
+/* "Content-type: image/gif\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, 0x69, 0x66, 0xd, 0xa, 0xd, 0xa, };
+const char http_content_type_jpg [29] =
+/* "Content-type: image/jpeg\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x65, 0x67, 0xd, 0xa, 0xd, 0xa, };
+const char http_content_type_binary[43] =
+/* "Content-type: application/octet-stream\r\n\r\n" */
+{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0xd, 0xa, 0xd, 0xa, };
+const char http_html[6] =
+/* ".html" */
+{0x2e, 0x68, 0x74, 0x6d, 0x6c, };
+const char http_shtml[7] =
+/* ".shtml" */
+{0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, };
+const char http_htm[5] =
+/* ".htm" */
+{0x2e, 0x68, 0x74, 0x6d, };
+const char http_css[5] =
+/* ".css" */
+{0x2e, 0x63, 0x73, 0x73, };
+const char http_png[5] =
+/* ".png" */
+{0x2e, 0x70, 0x6e, 0x67, };
+const char http_gif[5] =
+/* ".gif" */
+{0x2e, 0x67, 0x69, 0x66, };
+const char http_jpg[5] =
+/* ".jpg" */
+{0x2e, 0x6a, 0x70, 0x67, };
+const char http_text[5] =
+/* ".txt" */
+{0x2e, 0x74, 0x78, 0x74, };
+const char http_txt[5] =
+/* ".txt" */
+{0x2e, 0x74, 0x78, 0x74, };
diff --git a/uip/apps/webserver/http-strings.h b/uip/apps/webserver/http-strings.h
new file mode 100644
index 0000000..f121dd7
--- /dev/null
+++ b/uip/apps/webserver/http-strings.h
@@ -0,0 +1,34 @@
+extern const char http_http[8];
+extern const char http_200[5];
+extern const char http_301[5];
+extern const char http_302[5];
+extern const char http_get[5];
+extern const char http_10[9];
+extern const char http_11[9];
+extern const char http_content_type[15];
+extern const char http_texthtml[10];
+extern const char http_location[11];
+extern const char http_host[7];
+extern const char http_crnl[3];
+extern const char http_index_html[12];
+extern const char http_404_html[10];
+extern const char http_referer[9];
+extern const char http_header_200[84];
+extern const char http_header_404[91];
+extern const char http_content_type_plain[29];
+extern const char http_content_type_html[28];
+extern const char http_content_type_css [27];
+extern const char http_content_type_text[28];
+extern const char http_content_type_png [28];
+extern const char http_content_type_gif [28];
+extern const char http_content_type_jpg [29];
+extern const char http_content_type_binary[43];
+extern const char http_html[6];
+extern const char http_shtml[7];
+extern const char http_htm[5];
+extern const char http_css[5];
+extern const char http_png[5];
+extern const char http_gif[5];
+extern const char http_jpg[5];
+extern const char http_text[5];
+extern const char http_txt[5];
diff --git a/uip/apps/webserver/httpd-cgi.c b/uip/apps/webserver/httpd-cgi.c
new file mode 100644
index 0000000..6257035
--- /dev/null
+++ b/uip/apps/webserver/httpd-cgi.c
@@ -0,0 +1,203 @@
+/**
+ * \addtogroup httpd
+ * @{
+ */
+
+/**
+ * \file
+ * Web server script interface
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+/*
+ * Copyright (c) 2001-2006, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: httpd-cgi.c,v 1.2 2006/06/11 21:46:37 adam Exp $
+ *
+ */
+
+#include "uip.h"
+#include "psock.h"
+#include "httpd.h"
+#include "httpd-cgi.h"
+#include "httpd-fs.h"
+
+#include <stdio.h>
+#include <string.h>
+
+HTTPD_CGI_CALL(file, "file-stats", file_stats);
+HTTPD_CGI_CALL(tcp, "tcp-connections", tcp_stats);
+HTTPD_CGI_CALL(net, "net-stats", net_stats);
+
+static const struct httpd_cgi_call *calls[] = { &file, &tcp, &net, NULL };
+
+/*---------------------------------------------------------------------------*/
+static
+PT_THREAD(nullfunction(struct httpd_state *s, char *ptr))
+{
+ PSOCK_BEGIN(&s->sout);
+ PSOCK_END(&s->sout);
+}
+/*---------------------------------------------------------------------------*/
+httpd_cgifunction
+httpd_cgi(char *name)
+{
+ const struct httpd_cgi_call **f;
+
+ /* Find the matching name in the table, return the function. */
+ for(f = calls; *f != NULL; ++f) {
+ if(strncmp((*f)->name, name, strlen((*f)->name)) == 0) {
+ return (*f)->function;
+ }
+ }
+ return nullfunction;
+}
+/*---------------------------------------------------------------------------*/
+static unsigned short
+generate_file_stats(void *arg)
+{
+ char *f = (char *)arg;
+ return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE, "%5u", httpd_fs_count(f));
+}
+/*---------------------------------------------------------------------------*/
+static
+PT_THREAD(file_stats(struct httpd_state *s, char *ptr))
+{
+ PSOCK_BEGIN(&s->sout);
+
+ PSOCK_GENERATOR_SEND(&s->sout, generate_file_stats, strchr(ptr, ' ') + 1);
+
+ PSOCK_END(&s->sout);
+}
+/*---------------------------------------------------------------------------*/
+static const char closed[] = /* "CLOSED",*/
+{0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0};
+static const char syn_rcvd[] = /* "SYN-RCVD",*/
+{0x53, 0x59, 0x4e, 0x2d, 0x52, 0x43, 0x56,
+ 0x44, 0};
+static const char syn_sent[] = /* "SYN-SENT",*/
+{0x53, 0x59, 0x4e, 0x2d, 0x53, 0x45, 0x4e,
+ 0x54, 0};
+static const char established[] = /* "ESTABLISHED",*/
+{0x45, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x49, 0x53, 0x48,
+ 0x45, 0x44, 0};
+static const char fin_wait_1[] = /* "FIN-WAIT-1",*/
+{0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49,
+ 0x54, 0x2d, 0x31, 0};
+static const char fin_wait_2[] = /* "FIN-WAIT-2",*/
+{0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49,
+ 0x54, 0x2d, 0x32, 0};
+static const char closing[] = /* "CLOSING",*/
+{0x43, 0x4c, 0x4f, 0x53, 0x49,
+ 0x4e, 0x47, 0};
+static const char time_wait[] = /* "TIME-WAIT,"*/
+{0x54, 0x49, 0x4d, 0x45, 0x2d, 0x57, 0x41,
+ 0x49, 0x54, 0};
+static const char last_ack[] = /* "LAST-ACK"*/
+{0x4c, 0x41, 0x53, 0x54, 0x2d, 0x41, 0x43,
+ 0x4b, 0};
+
+static const char *states[] = {
+ closed,
+ syn_rcvd,
+ syn_sent,
+ established,
+ fin_wait_1,
+ fin_wait_2,
+ closing,
+ time_wait,
+ last_ack};
+
+
+static unsigned short
+generate_tcp_stats(void *arg)
+{
+ struct uip_conn *conn;
+ struct httpd_state *s = (struct httpd_state *)arg;
+
+ conn = &uip_conns[s->count];
+ return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE,
+ "<tr><td>%d</td><td>%u.%u.%u.%u:%u</td><td>%s</td><td>%u</td><td>%u</td><td>%c %c</td></tr>\r\n",
+ htons(conn->lport),
+ htons(conn->ripaddr[0]) >> 8,
+ htons(conn->ripaddr[0]) & 0xff,
+ htons(conn->ripaddr[1]) >> 8,
+ htons(conn->ripaddr[1]) & 0xff,
+ htons(conn->rport),
+ states[conn->tcpstateflags & UIP_TS_MASK],
+ conn->nrtx,
+ conn->timer,
+ (uip_outstanding(conn))? '*':' ',
+ (uip_stopped(conn))? '!':' ');
+}
+/*---------------------------------------------------------------------------*/
+static
+PT_THREAD(tcp_stats(struct httpd_state *s, char *ptr))
+{
+
+ PSOCK_BEGIN(&s->sout);
+
+ for(s->count = 0; s->count < UIP_CONNS; ++s->count) {
+ if((uip_conns[s->count].tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) {
+ PSOCK_GENERATOR_SEND(&s->sout, generate_tcp_stats, s);
+ }
+ }
+
+ PSOCK_END(&s->sout);
+}
+/*---------------------------------------------------------------------------*/
+static unsigned short
+generate_net_stats(void *arg)
+{
+ struct httpd_state *s = (struct httpd_state *)arg;
+ return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE,
+ "%5u\n", ((uip_stats_t *)&uip_stat)[s->count]);
+}
+
+static
+PT_THREAD(net_stats(struct httpd_state *s, char *ptr))
+{
+ PSOCK_BEGIN(&s->sout);
+
+#if UIP_STATISTICS
+
+ for(s->count = 0; s->count < sizeof(uip_stat) / sizeof(uip_stats_t);
+ ++s->count) {
+ PSOCK_GENERATOR_SEND(&s->sout, generate_net_stats, s);
+ }
+
+#endif /* UIP_STATISTICS */
+
+ PSOCK_END(&s->sout);
+}
+/*---------------------------------------------------------------------------*/
+/** @} */
diff --git a/uip/apps/webserver/httpd-cgi.h b/uip/apps/webserver/httpd-cgi.h
new file mode 100644
index 0000000..e6ba51e
--- /dev/null
+++ b/uip/apps/webserver/httpd-cgi.h
@@ -0,0 +1,84 @@
+/**
+ * \addtogroup httpd
+ * @{
+ */
+
+/**
+ * \file
+ * Web server script interface header file
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+
+
+/*
+ * Copyright (c) 2001, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: httpd-cgi.h,v 1.2 2006/06/11 21:46:38 adam Exp $
+ *
+ */
+
+#ifndef __HTTPD_CGI_H__
+#define __HTTPD_CGI_H__
+
+#include "psock.h"
+#include "httpd.h"
+
+typedef PT_THREAD((* httpd_cgifunction)(struct httpd_state *, char *));
+
+httpd_cgifunction httpd_cgi(char *name);
+
+struct httpd_cgi_call {
+ const char *name;
+ const httpd_cgifunction function;
+};
+
+/**
+ * \brief HTTPD CGI function declaration
+ * \param name The C variable name of the function
+ * \param str The string name of the function, used in the script file
+ * \param function A pointer to the function that implements it
+ *
+ * This macro is used for declaring a HTTPD CGI
+ * function. This function is then added to the list of
+ * HTTPD CGI functions with the httpd_cgi_add() function.
+ *
+ * \hideinitializer
+ */
+#define HTTPD_CGI_CALL(name, str, function) \
+static PT_THREAD(function(struct httpd_state *, char *)); \
+static const struct httpd_cgi_call name = {str, function}
+
+void httpd_cgi_init(void);
+#endif /* __HTTPD_CGI_H__ */
+
+/** @} */
diff --git a/uip/apps/webserver/httpd-fs.c b/uip/apps/webserver/httpd-fs.c
new file mode 100644
index 0000000..21185e8
--- /dev/null
+++ b/uip/apps/webserver/httpd-fs.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2001, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: httpd-fs.c,v 1.1 2006/06/07 09:13:08 adam Exp $
+ */
+
+#include "httpd.h"
+#include "httpd-fs.h"
+#include "httpd-fsdata.h"
+
+#ifndef NULL
+#define NULL 0
+#endif /* NULL */
+
+#include "httpd-fsdata.c"
+
+#if HTTPD_FS_STATISTICS
+static u16_t count[HTTPD_FS_NUMFILES];
+#endif /* HTTPD_FS_STATISTICS */
+
+/*-----------------------------------------------------------------------------------*/
+static u8_t
+httpd_fs_strcmp(const char *str1, const char *str2)
+{
+ u8_t i;
+ i = 0;
+ loop:
+
+ if(str2[i] == 0 ||
+ str1[i] == '\r' ||
+ str1[i] == '\n') {
+ return 0;
+ }
+
+ if(str1[i] != str2[i]) {
+ return 1;
+ }
+
+
+ ++i;
+ goto loop;
+}
+/*-----------------------------------------------------------------------------------*/
+int
+httpd_fs_open(const char *name, struct httpd_fs_file *file)
+{
+#if HTTPD_FS_STATISTICS
+ u16_t i = 0;
+#endif /* HTTPD_FS_STATISTICS */
+ struct httpd_fsdata_file_noconst *f;
+
+ for(f = (struct httpd_fsdata_file_noconst *)HTTPD_FS_ROOT;
+ f != NULL;
+ f = (struct httpd_fsdata_file_noconst *)f->next) {
+
+ if(httpd_fs_strcmp(name, f->name) == 0) {
+ file->data = f->data;
+ file->len = f->len;
+#if HTTPD_FS_STATISTICS
+ ++count[i];
+#endif /* HTTPD_FS_STATISTICS */
+ return 1;
+ }
+#if HTTPD_FS_STATISTICS
+ ++i;
+#endif /* HTTPD_FS_STATISTICS */
+
+ }
+ return 0;
+}
+/*-----------------------------------------------------------------------------------*/
+void
+httpd_fs_init(void)
+{
+#if HTTPD_FS_STATISTICS
+ u16_t i;
+ for(i = 0; i < HTTPD_FS_NUMFILES; i++) {
+ count[i] = 0;
+ }
+#endif /* HTTPD_FS_STATISTICS */
+}
+/*-----------------------------------------------------------------------------------*/
+#if HTTPD_FS_STATISTICS
+u16_t httpd_fs_count
+(char *name)
+{
+ struct httpd_fsdata_file_noconst *f;
+ u16_t i;
+
+ i = 0;
+ for(f = (struct httpd_fsdata_file_noconst *)HTTPD_FS_ROOT;
+ f != NULL;
+ f = (struct httpd_fsdata_file_noconst *)f->next) {
+
+ if(httpd_fs_strcmp(name, f->name) == 0) {
+ return count[i];
+ }
+ ++i;
+ }
+ return 0;
+}
+#endif /* HTTPD_FS_STATISTICS */
+/*-----------------------------------------------------------------------------------*/
diff --git a/uip/apps/webserver/httpd-fs.h b/uip/apps/webserver/httpd-fs.h
new file mode 100644
index 0000000..d80ed3d
--- /dev/null
+++ b/uip/apps/webserver/httpd-fs.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2001, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: httpd-fs.h,v 1.1 2006/06/07 09:13:08 adam Exp $
+ */
+#ifndef __HTTPD_FS_H__
+#define __HTTPD_FS_H__
+
+#define HTTPD_FS_STATISTICS 1
+
+struct httpd_fs_file {
+ char *data;
+ int len;
+};
+
+/* file must be allocated by caller and will be filled in
+ by the function. */
+int httpd_fs_open(const char *name, struct httpd_fs_file *file);
+
+#ifdef HTTPD_FS_STATISTICS
+#if HTTPD_FS_STATISTICS == 1
+u16_t httpd_fs_count(char *name);
+#endif /* HTTPD_FS_STATISTICS */
+#endif /* HTTPD_FS_STATISTICS */
+
+void httpd_fs_init(void);
+
+#endif /* __HTTPD_FS_H__ */
diff --git a/uip/apps/webserver/httpd-fs/404.html b/uip/apps/webserver/httpd-fs/404.html
new file mode 100644
index 0000000..a17711d
--- /dev/null
+++ b/uip/apps/webserver/httpd-fs/404.html
@@ -0,0 +1,8 @@
+<html>
+ <body bgcolor="white">
+ <center>
+ <h1>404 - file not found</h1>
+ <h3>Go <a href="/">here</a> instead.</h3>
+ </center>
+ </body>
+</html> \ No newline at end of file
diff --git a/uip/apps/webserver/httpd-fs/fade.png b/uip/apps/webserver/httpd-fs/fade.png
new file mode 100644
index 0000000..a9e69f7
--- /dev/null
+++ b/uip/apps/webserver/httpd-fs/fade.png
Binary files differ
diff --git a/uip/apps/webserver/httpd-fs/files.shtml b/uip/apps/webserver/httpd-fs/files.shtml
new file mode 100644
index 0000000..811e230
--- /dev/null
+++ b/uip/apps/webserver/httpd-fs/files.shtml
@@ -0,0 +1,35 @@
+%!: /header.html
+<h1>File statistics</h1>
+<center>
+<table width="300">
+<tr><td><a href="/index.html">/index.html</a></td>
+<td>%! file-stats /index.html
+</td><td><img src="/fade.png" height=10 width=%! file-stats /index.html
+> </td></tr>
+<tr><td><a href="/files.shtml">/files.shtml</a></td>
+<td>%! file-stats /files.shtml
+</td><td><img src="/fade.png" height=10 width=%! file-stats /files.shtml
+> </td></tr>
+<tr><td><a href="/tcp.shtml">/tcp.shtml</a></td>
+<td>%! file-stats /tcp.shtml
+</td><td><img src="/fade.png" height=10 width=%! file-stats /tcp.shtml
+> </td></tr>
+<tr><td><a href="/stats.shtml">/stats.shtml</a></td>
+<td>%! file-stats /stats.shtml
+</td><td><img src="/fade.png" height=10 width=%! file-stats /stats.shtml
+> </td></tr>
+<tr><td><a href="/style.css">/style.css</a></td>
+<td>%! file-stats /style.css
+</td><td><img src="/fade.png" height=10 width=%! file-stats /style.css
+> </td></tr>
+<tr><td><a href="/404.html">/404.html</a></td>
+<td>%! file-stats /404.html
+</td><td><img src="/fade.png" height=10 width=%! file-stats /404.html
+> </td></tr>
+<tr><td><a href="/fade.png">/fade.png</a></td>
+<td>%! file-stats /fade.png
+</td><td><img src="/fade.png" height=10 width=%! file-stats /fade.png
+> </td></tr>
+</table>
+</center>
+%!: /footer.html
diff --git a/uip/apps/webserver/httpd-fs/footer.html b/uip/apps/webserver/httpd-fs/footer.html
new file mode 100644
index 0000000..1fd5f4f
--- /dev/null
+++ b/uip/apps/webserver/httpd-fs/footer.html
@@ -0,0 +1,2 @@
+ </body>
+</html> \ No newline at end of file
diff --git a/uip/apps/webserver/httpd-fs/header.html b/uip/apps/webserver/httpd-fs/header.html
new file mode 100644
index 0000000..7b1a1fe
--- /dev/null
+++ b/uip/apps/webserver/httpd-fs/header.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+ <head>
+ <title>Welcome to the uIP web server!</title>
+ <link rel="stylesheet" type="text/css" href="style.css">
+ </head>
+ <body bgcolor="#fffeec" text="black">
+
+ <div class="menu">
+ <div class="menubox"><a href="/">Front page</a></div>
+ <div class="menubox"><a href="files.shtml">File statistics</a></div>
+ <div class="menubox"><a href="stats.shtml">Network statistics</a></div>
+ <div class="menubox"><a href="tcp.shtml">Network
+ connections</a></div>
+ <br>
+ </div>
+
+ <div class="contentblock">
diff --git a/uip/apps/webserver/httpd-fs/index.html b/uip/apps/webserver/httpd-fs/index.html
new file mode 100644
index 0000000..27cbc93
--- /dev/null
+++ b/uip/apps/webserver/httpd-fs/index.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+ <head>
+ <title>Welcome to the uIP web server!</title>
+ <link rel="stylesheet" type="text/css" href="style.css">
+ </head>
+ <body bgcolor="#fffeec" text="black">
+
+ <div class="menu">
+ <div class="menubox"><a href="/">Front page</a></div>
+ <div class="menubox"><a href="files.shtml">File statistics</a></div>
+ <div class="menubox"><a href="stats.shtml">Network statistics</a></div>
+ <div class="menubox"><a href="tcp.shtml">Network
+ connections</a></div>
+ <br>
+ </div>
+
+ <div class="contentblock">
+ <p>
+ These web pages are served by a small web server running on top of
+ the <a href="http://www.sics.se/~adam/uip/">uIP embedded TCP/IP
+ stack</a>.
+ </p>
+ <p>
+ Click on the links above for web server statistics.
+ </p>
+
+ </body>
+</html>
diff --git a/uip/apps/webserver/httpd-fs/processes.shtml b/uip/apps/webserver/httpd-fs/processes.shtml
new file mode 100644
index 0000000..2f93e35
--- /dev/null
+++ b/uip/apps/webserver/httpd-fs/processes.shtml
@@ -0,0 +1,5 @@
+%!: /header.html
+<h1>System processes</h1><br><table width="100%">
+<tr><th>ID</th><th>Name</th><th>Priority</th><th>Poll handler</th><th>Event handler</th><th>Procstate</th></tr>
+%! processes
+%!: /footer.html \ No newline at end of file
diff --git a/uip/apps/webserver/httpd-fs/stats.shtml b/uip/apps/webserver/httpd-fs/stats.shtml
new file mode 100644
index 0000000..c63ed4a
--- /dev/null
+++ b/uip/apps/webserver/httpd-fs/stats.shtml
@@ -0,0 +1,31 @@
+%!: /header.html
+<h1>Network statistics</h1>
+<center>
+<table width="300" border="0">
+<tr><td><pre>
+IP Packets received
+ Packets sent
+ Packets dropped
+IP errors IP version/header length
+ IP length, high byte
+ IP length, low byte
+ IP fragments
+ Header checksum
+ Wrong protocol
+ICMP Packets received
+ Packets sent
+ Packets dropped
+ Type errors
+TCP Packets received
+ Packets sent
+ Packets dropped
+ Checksum errors
+ Data packets without ACKs
+ Resets
+ Retransmissions
+ No connection avaliable
+ Connection attempts to closed ports
+</pre></td><td><pre>%! net-stats
+</pre></table>
+</center>
+%!: /footer.html
diff --git a/uip/apps/webserver/httpd-fs/style.css b/uip/apps/webserver/httpd-fs/style.css
new file mode 100644
index 0000000..ba6df7f
--- /dev/null
+++ b/uip/apps/webserver/httpd-fs/style.css
@@ -0,0 +1,92 @@
+h1
+{
+ text-align: center;
+ font-size:14pt;
+ font-family:arial,helvetica;
+ font-weight:bold;
+ padding:10px;
+}
+
+body
+{
+
+ background-color: #fffeec;
+ color:black;
+
+ font-size:8pt;
+ font-family:arial,helvetica;
+}
+
+.menu
+{
+ margin: 4px;
+ width:60%;
+
+ padding:2px;
+
+ border: solid 1px;
+ background-color: #fffcd2;
+ text-align:left;
+
+ font-size:9pt;
+ font-family:arial,helvetica;
+}
+
+div.menubox
+{
+ width: 25%;
+ border: 0;
+ float: left;
+text-align: center;
+}
+
+.contentblock
+{
+ margin: 4px;
+ width:60%;
+
+ padding:2px;
+
+ border: 1px dotted;
+ background-color: white;
+
+ font-size:8pt;
+ font-family:arial,helvetica;
+
+}
+
+p.intro
+{
+ margin-left:20px;
+ margin-right:20px;
+
+ font-size:10pt;
+/* font-weight:bold; */
+ font-family:arial,helvetica;
+}
+
+p.clink
+{
+ font-size:12pt;
+ font-family:courier,monospace;
+ text-align:center;
+}
+
+p.clink9
+{
+ font-size:9pt;
+ font-family:courier,monospace;
+ text-align:center;
+}
+
+
+p
+{
+ padding-left:10px;
+}
+
+p.right
+{
+ text-align:right;
+}
+
diff --git a/uip/apps/webserver/httpd-fs/tcp.shtml b/uip/apps/webserver/httpd-fs/tcp.shtml
new file mode 100644
index 0000000..4c4bffe
--- /dev/null
+++ b/uip/apps/webserver/httpd-fs/tcp.shtml
@@ -0,0 +1,5 @@
+%!: /header.html
+<h1>Current connections</h1><br><table width="100%">
+<tr><th>Local</th><th>Remote</th><th>State</th><th>Retransmissions</th><th>Timer</th><th>Flags</th></tr>
+%! tcp-connections
+%!: /footer.html \ No newline at end of file
diff --git a/uip/apps/webserver/httpd-fsdata.c b/uip/apps/webserver/httpd-fsdata.c
new file mode 100644
index 0000000..491095e
--- /dev/null
+++ b/uip/apps/webserver/httpd-fsdata.c
@@ -0,0 +1,607 @@
+static const unsigned char data_processes_shtml[] = {
+ /* /processes.shtml */
+ 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65,
+ 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x68, 0x31,
+ 0x3e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x70, 0x72,
+ 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x3c, 0x2f, 0x68,
+ 0x31, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0x3c, 0x74, 0x61, 0x62,
+ 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22,
+ 0x31, 0x30, 0x30, 0x25, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72,
+ 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x49, 0x44, 0x3c, 0x2f, 0x74,
+ 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x4e, 0x61, 0x6d, 0x65,
+ 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x50,
+ 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x3c, 0x2f, 0x74,
+ 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x50, 0x6f, 0x6c, 0x6c,
+ 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3c, 0x2f,
+ 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x45, 0x76, 0x65,
+ 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72,
+ 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x50,
+ 0x72, 0x6f, 0x63, 0x73, 0x74, 0x61, 0x74, 0x65, 0x3c, 0x2f,
+ 0x74, 0x68, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x25,
+ 0x21, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65,
+ 0x73, 0xa, 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x66, 0x6f, 0x6f,
+ 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0};
+
+static const unsigned char data_404_html[] = {
+ /* /404.html */
+ 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x20, 0x20, 0x3c,
+ 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22,
+ 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x63, 0x65, 0x6e,
+ 0x74, 0x65, 0x72, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d,
+ 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e,
+ 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x68, 0x33,
+ 0x3e, 0x47, 0x6f, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x2f, 0x22, 0x3e, 0x68, 0x65, 0x72, 0x65,
+ 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65,
+ 0x61, 0x64, 0x2e, 0x3c, 0x2f, 0x68, 0x33, 0x3e, 0xa, 0x20,
+ 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65,
+ 0x72, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x62, 0x6f, 0x64,
+ 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e,
+0};
+
+static const unsigned char data_files_shtml[] = {
+ /* /files.shtml */
+ 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65,
+ 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x68, 0x31,
+ 0x3e, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x73, 0x74, 0x61, 0x74,
+ 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x3c, 0x2f, 0x68, 0x31,
+ 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e,
+ 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x3d, 0x22, 0x33, 0x30, 0x30, 0x22, 0x3e,
+ 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x69,
+ 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22,
+ 0x3e, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74,
+ 0x6d, 0x6c, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66,
+ 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x20,
+ 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d,
+ 0x6c, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64,
+ 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, 0x72, 0x63, 0x3d,
+ 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, 0x6e, 0x67,
+ 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x31,
+ 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x25, 0x21,
+ 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74,
+ 0x73, 0x20, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68,
+ 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x72,
+ 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73,
+ 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x2f, 0x66,
+ 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c,
+ 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa,
+ 0x3c, 0x74, 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c,
+ 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x66,
+ 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c,
+ 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e,
+ 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, 0x72, 0x63, 0x3d, 0x22,
+ 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, 0x6e, 0x67, 0x22,
+ 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x31, 0x30,
+ 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x25, 0x21, 0x20,
+ 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73,
+ 0x20, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68,
+ 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x72,
+ 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x74, 0x63, 0x70, 0x2e, 0x73,
+ 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x2f, 0x74, 0x63, 0x70,
+ 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x3c, 0x2f, 0x61, 0x3e,
+ 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e,
+ 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74,
+ 0x61, 0x74, 0x73, 0x20, 0x2f, 0x74, 0x63, 0x70, 0x2e, 0x73,
+ 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e,
+ 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73,
+ 0x72, 0x63, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e,
+ 0x70, 0x6e, 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x3d, 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68,
+ 0x3d, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73,
+ 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x74, 0x63, 0x70, 0x2e,
+ 0x73, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f,
+ 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c,
+ 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x73, 0x74, 0x61,
+ 0x74, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e,
+ 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, 0x68, 0x74,
+ 0x6d, 0x6c, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66,
+ 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x20,
+ 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, 0x68, 0x74,
+ 0x6d, 0x6c, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74,
+ 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, 0x72, 0x63,
+ 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, 0x6e,
+ 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d,
+ 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x25,
+ 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61,
+ 0x74, 0x73, 0x20, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e,
+ 0x73, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f,
+ 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c,
+ 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x73, 0x74, 0x79,
+ 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0x22, 0x3e, 0x2f, 0x73,
+ 0x74, 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0x3c, 0x2f,
+ 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74,
+ 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d,
+ 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x73, 0x74, 0x79,
+ 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0xa, 0x3c, 0x2f, 0x74,
+ 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67,
+ 0x20, 0x73, 0x72, 0x63, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64,
+ 0x65, 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x20, 0x68, 0x65, 0x69,
+ 0x67, 0x68, 0x74, 0x3d, 0x31, 0x30, 0x20, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x3d, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65,
+ 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x73, 0x74,
+ 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0xa, 0x3e, 0x20,
+ 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e,
+ 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c,
+ 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x34,
+ 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x2f,
+ 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3c, 0x2f,
+ 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74,
+ 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d,
+ 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x34, 0x30, 0x34,
+ 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20,
+ 0x73, 0x72, 0x63, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65,
+ 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67,
+ 0x68, 0x74, 0x3d, 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3d, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d,
+ 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x34, 0x30, 0x34,
+ 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f,
+ 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c,
+ 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64,
+ 0x65, 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x3e, 0x2f, 0x66, 0x61,
+ 0x64, 0x65, 0x2e, 0x70, 0x6e, 0x67, 0x3c, 0x2f, 0x61, 0x3e,
+ 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e,
+ 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74,
+ 0x61, 0x74, 0x73, 0x20, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e,
+ 0x70, 0x6e, 0x67, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c,
+ 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, 0x72,
+ 0x63, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70,
+ 0x6e, 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x3d, 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d,
+ 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74,
+ 0x61, 0x74, 0x73, 0x20, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e,
+ 0x70, 0x6e, 0x67, 0xa, 0x3e, 0x20, 0x3c, 0x2f, 0x74, 0x64,
+ 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74,
+ 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x3c, 0x2f, 0x63, 0x65,
+ 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, 0x25, 0x21, 0x3a, 0x20,
+ 0x2f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74,
+ 0x6d, 0x6c, 0xa, 0};
+
+static const unsigned char data_footer_html[] = {
+ /* /footer.html */
+ 0x2f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x20, 0x20, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa,
+ 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0};
+
+static const unsigned char data_header_html[] = {
+ /* /header.html */
+ 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20,
+ 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49,
+ 0x43, 0x20, 0x22, 0x2d, 0x2f, 0x2f, 0x57, 0x33, 0x43, 0x2f,
+ 0x2f, 0x44, 0x54, 0x44, 0x20, 0x48, 0x54, 0x4d, 0x4c, 0x20,
+ 0x34, 0x2e, 0x30, 0x31, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x2f, 0x45,
+ 0x4e, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72,
+ 0x67, 0x2f, 0x54, 0x52, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x34,
+ 0x2f, 0x6c, 0x6f, 0x6f, 0x73, 0x65, 0x2e, 0x64, 0x74, 0x64,
+ 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa,
+ 0x20, 0x20, 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x20,
+ 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e,
+ 0x57, 0x65, 0x6c, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x49, 0x50, 0x20, 0x77,
+ 0x65, 0x62, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x21,
+ 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x20,
+ 0x20, 0x20, 0x20, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x72,
+ 0x65, 0x6c, 0x3d, 0x22, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73,
+ 0x68, 0x65, 0x65, 0x74, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73,
+ 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x73, 0x74,
+ 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0x22, 0x3e, 0x20,
+ 0x20, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64,
+ 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20,
+ 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23,
+ 0x66, 0x66, 0x66, 0x65, 0x65, 0x63, 0x22, 0x20, 0x74, 0x65,
+ 0x78, 0x74, 0x3d, 0x22, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x22,
+ 0x3e, 0xa, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20,
+ 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e,
+ 0x75, 0x22, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76,
+ 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65,
+ 0x6e, 0x75, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x22, 0x3e, 0x46,
+ 0x72, 0x6f, 0x6e, 0x74, 0x20, 0x70, 0x61, 0x67, 0x65, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa,
+ 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61,
+ 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, 0x75, 0x62, 0x6f,
+ 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68,
+ 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x46, 0x69, 0x6c, 0x65, 0x20,
+ 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73,
+ 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e,
+ 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c,
+ 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, 0x75, 0x62,
+ 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73,
+ 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65, 0x74, 0x77,
+ 0x6f, 0x72, 0x6b, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73,
+ 0x74, 0x69, 0x63, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f,
+ 0x64, 0x69, 0x76, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69,
+ 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d,
+ 0x65, 0x6e, 0x75, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x74, 0x63, 0x70,
+ 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65,
+ 0x74, 0x77, 0x6f, 0x72, 0x6b, 0xa, 0x20, 0x20, 0x63, 0x6f,
+ 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa,
+ 0x20, 0x20, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x20, 0x20, 0x3c,
+ 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x20, 0x20, 0xa, 0x20,
+ 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73,
+ 0x73, 0x3d, 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
+ 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x3e, 0xa, 0};
+
+static const unsigned char data_index_html[] = {
+ /* /index.html */
+ 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20,
+ 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49,
+ 0x43, 0x20, 0x22, 0x2d, 0x2f, 0x2f, 0x57, 0x33, 0x43, 0x2f,
+ 0x2f, 0x44, 0x54, 0x44, 0x20, 0x48, 0x54, 0x4d, 0x4c, 0x20,
+ 0x34, 0x2e, 0x30, 0x31, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x2f, 0x45,
+ 0x4e, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72,
+ 0x67, 0x2f, 0x54, 0x52, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x34,
+ 0x2f, 0x6c, 0x6f, 0x6f, 0x73, 0x65, 0x2e, 0x64, 0x74, 0x64,
+ 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa,
+ 0x20, 0x20, 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x20,
+ 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e,
+ 0x57, 0x65, 0x6c, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x49, 0x50, 0x20, 0x77,
+ 0x65, 0x62, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x21,
+ 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x20,
+ 0x20, 0x20, 0x20, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x72,
+ 0x65, 0x6c, 0x3d, 0x22, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73,
+ 0x68, 0x65, 0x65, 0x74, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73,
+ 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x73, 0x74,
+ 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0x22, 0x3e, 0x20,
+ 0x20, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64,
+ 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20,
+ 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23,
+ 0x66, 0x66, 0x66, 0x65, 0x65, 0x63, 0x22, 0x20, 0x74, 0x65,
+ 0x78, 0x74, 0x3d, 0x22, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x22,
+ 0x3e, 0xa, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20,
+ 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e,
+ 0x75, 0x22, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76,
+ 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65,
+ 0x6e, 0x75, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x22, 0x3e, 0x46,
+ 0x72, 0x6f, 0x6e, 0x74, 0x20, 0x70, 0x61, 0x67, 0x65, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa,
+ 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61,
+ 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, 0x75, 0x62, 0x6f,
+ 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x22, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68,
+ 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x46, 0x69, 0x6c, 0x65, 0x20,
+ 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73,
+ 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e,
+ 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c,
+ 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, 0x75, 0x62,
+ 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65,
+ 0x66, 0x3d, 0x22, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73,
+ 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65, 0x74, 0x77,
+ 0x6f, 0x72, 0x6b, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73,
+ 0x74, 0x69, 0x63, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f,
+ 0x64, 0x69, 0x76, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69,
+ 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d,
+ 0x65, 0x6e, 0x75, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x74, 0x63, 0x70,
+ 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65,
+ 0x74, 0x77, 0x6f, 0x72, 0x6b, 0xa, 0x20, 0x20, 0x63, 0x6f,
+ 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa,
+ 0x20, 0x20, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x20, 0x20, 0x3c,
+ 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0xa, 0x20, 0x20, 0x3c,
+ 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d,
+ 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x22, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x70,
+ 0x3e, 0xa, 0x20, 0x20, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20,
+ 0x77, 0x65, 0x62, 0x20, 0x70, 0x61, 0x67, 0x65, 0x73, 0x20,
+ 0x61, 0x72, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64,
+ 0x20, 0x62, 0x79, 0x20, 0x61, 0x20, 0x73, 0x6d, 0x61, 0x6c,
+ 0x6c, 0x20, 0x77, 0x65, 0x62, 0x20, 0x73, 0x65, 0x72, 0x76,
+ 0x65, 0x72, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67,
+ 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x70, 0x20, 0x6f, 0x66,
+ 0xa, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x3c, 0x61, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x69, 0x63,
+ 0x73, 0x2e, 0x73, 0x65, 0x2f, 0x7e, 0x61, 0x64, 0x61, 0x6d,
+ 0x2f, 0x75, 0x69, 0x70, 0x2f, 0x22, 0x3e, 0x75, 0x49, 0x50,
+ 0x20, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x20,
+ 0x54, 0x43, 0x50, 0x2f, 0x49, 0x50, 0xa, 0x20, 0x20, 0x73,
+ 0x74, 0x61, 0x63, 0x6b, 0x3c, 0x2f, 0x61, 0x3e, 0x2e, 0xa,
+ 0x20, 0x20, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0x20, 0x20, 0x3c,
+ 0x70, 0x3e, 0xa, 0x20, 0x20, 0x43, 0x6c, 0x69, 0x63, 0x6b,
+ 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69,
+ 0x6e, 0x6b, 0x73, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x77, 0x65, 0x62, 0x20, 0x73, 0x65,
+ 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69,
+ 0x73, 0x74, 0x69, 0x63, 0x73, 0x2e, 0xa, 0x20, 0x20, 0x3c,
+ 0x2f, 0x70, 0x3e, 0xa, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x62,
+ 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d,
+ 0x6c, 0x3e, 0xa, 0};
+
+static const unsigned char data_style_css[] = {
+ /* /style.css */
+ 0x2f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0,
+ 0x68, 0x31, 0x20, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x74, 0x65,
+ 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20,
+ 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0xa, 0x20, 0x20,
+ 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a,
+ 0x31, 0x34, 0x70, 0x74, 0x3b, 0xa, 0x20, 0x20, 0x66, 0x6f,
+ 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a,
+ 0x61, 0x72, 0x69, 0x61, 0x6c, 0x2c, 0x68, 0x65, 0x6c, 0x76,
+ 0x65, 0x74, 0x69, 0x63, 0x61, 0x3b, 0xa, 0x20, 0x20, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x3a, 0x62, 0x6f, 0x6c, 0x64, 0x3b, 0xa, 0x20, 0x20, 0x70,
+ 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x31, 0x30, 0x70,
+ 0x78, 0x3b, 0x20, 0xa, 0x7d, 0xa, 0xa, 0x62, 0x6f, 0x64,
+ 0x79, 0xa, 0x7b, 0xa, 0xa, 0x20, 0x20, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x65,
+ 0x65, 0x63, 0x3b, 0xa, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x3b, 0xa, 0xa,
+ 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a,
+ 0x65, 0x3a, 0x38, 0x70, 0x74, 0x3b, 0xa, 0x20, 0x20, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79,
+ 0x3a, 0x61, 0x72, 0x69, 0x61, 0x6c, 0x2c, 0x68, 0x65, 0x6c,
+ 0x76, 0x65, 0x74, 0x69, 0x63, 0x61, 0x3b, 0xa, 0x7d, 0xa,
+ 0xa, 0x2e, 0x6d, 0x65, 0x6e, 0x75, 0xa, 0x7b, 0xa, 0x20,
+ 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x34,
+ 0x70, 0x78, 0x3b, 0xa, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3a, 0x36, 0x30, 0x25, 0x3b, 0xa, 0xa, 0x20, 0x20,
+ 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x32, 0x70,
+ 0x78, 0x3b, 0xa, 0x9, 0xa, 0x20, 0x20, 0x62, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x3a, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64,
+ 0x20, 0x31, 0x70, 0x78, 0x3b, 0xa, 0x20, 0x20, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66,
+ 0x63, 0x64, 0x32, 0x3b, 0xa, 0x20, 0x20, 0x74, 0x65, 0x78,
+ 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x6c, 0x65,
+ 0x66, 0x74, 0x3b, 0xa, 0x20, 0x20, 0xa, 0x20, 0x20, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x39,
+ 0x70, 0x74, 0x3b, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74,
+ 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x61, 0x72,
+ 0x69, 0x61, 0x6c, 0x2c, 0x68, 0x65, 0x6c, 0x76, 0x65, 0x74,
+ 0x69, 0x63, 0x61, 0x3b, 0x20, 0x20, 0xa, 0x7d, 0xa, 0xa,
+ 0x64, 0x69, 0x76, 0x2e, 0x6d, 0x65, 0x6e, 0x75, 0x62, 0x6f,
+ 0x78, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3a, 0x20, 0x32, 0x35, 0x25, 0x3b, 0xa, 0x20, 0x20,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x30, 0x3b,
+ 0xa, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3a, 0x20,
+ 0x6c, 0x65, 0x66, 0x74, 0x3b, 0xa, 0x74, 0x65, 0x78, 0x74,
+ 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x63, 0x65,
+ 0x6e, 0x74, 0x65, 0x72, 0x3b, 0xa, 0x7d, 0xa, 0xa, 0x2e,
+ 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x62, 0x6c, 0x6f,
+ 0x63, 0x6b, 0xa, 0x7b, 0x20, 0x20, 0xa, 0x20, 0x20, 0x6d,
+ 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x34, 0x70, 0x78,
+ 0x3b, 0xa, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a,
+ 0x36, 0x30, 0x25, 0x3b, 0xa, 0xa, 0x20, 0x20, 0x70, 0x61,
+ 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x32, 0x70, 0x78, 0x3b,
+ 0xa, 0xa, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x3a, 0x20, 0x31, 0x70, 0x78, 0x20, 0x64, 0x6f, 0x74, 0x74,
+ 0x65, 0x64, 0x3b, 0xa, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x3b,
+ 0xa, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73,
+ 0x69, 0x7a, 0x65, 0x3a, 0x38, 0x70, 0x74, 0x3b, 0xa, 0x20,
+ 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69,
+ 0x6c, 0x79, 0x3a, 0x61, 0x72, 0x69, 0x61, 0x6c, 0x2c, 0x68,
+ 0x65, 0x6c, 0x76, 0x65, 0x74, 0x69, 0x63, 0x61, 0x3b, 0x20,
+ 0x20, 0xa, 0xa, 0x7d, 0xa, 0xa, 0x70, 0x2e, 0x69, 0x6e,
+ 0x74, 0x72, 0x6f, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x6d, 0x61,
+ 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a,
+ 0x32, 0x30, 0x70, 0x78, 0x3b, 0xa, 0x20, 0x20, 0x6d, 0x61,
+ 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74,
+ 0x3a, 0x32, 0x30, 0x70, 0x78, 0x3b, 0xa, 0xa, 0x20, 0x20,
+ 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a,
+ 0x31, 0x30, 0x70, 0x74, 0x3b, 0xa, 0x2f, 0x2a, 0x20, 0x20,
+ 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x3a, 0x62, 0x6f, 0x6c, 0x64, 0x3b, 0x20, 0x2a, 0x2f,
+ 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61,
+ 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x61, 0x72, 0x69, 0x61, 0x6c,
+ 0x2c, 0x68, 0x65, 0x6c, 0x76, 0x65, 0x74, 0x69, 0x63, 0x61,
+ 0x3b, 0x20, 0x20, 0xa, 0x7d, 0xa, 0xa, 0x70, 0x2e, 0x63,
+ 0x6c, 0x69, 0x6e, 0x6b, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x31,
+ 0x32, 0x70, 0x74, 0x3b, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e,
+ 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x63,
+ 0x6f, 0x75, 0x72, 0x69, 0x65, 0x72, 0x2c, 0x6d, 0x6f, 0x6e,
+ 0x6f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x3b, 0x20, 0x20, 0xa,
+ 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69,
+ 0x67, 0x6e, 0x3a, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b,
+ 0xa, 0x7d, 0xa, 0xa, 0x70, 0x2e, 0x63, 0x6c, 0x69, 0x6e,
+ 0x6b, 0x39, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e,
+ 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x39, 0x70, 0x74,
+ 0x3b, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66,
+ 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x63, 0x6f, 0x75, 0x72,
+ 0x69, 0x65, 0x72, 0x2c, 0x6d, 0x6f, 0x6e, 0x6f, 0x73, 0x70,
+ 0x61, 0x63, 0x65, 0x3b, 0x20, 0x20, 0xa, 0x20, 0x20, 0x74,
+ 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a,
+ 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0xa, 0x7d, 0xa,
+ 0xa, 0xa, 0x70, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x70, 0x61,
+ 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x6c, 0x65, 0x66, 0x74,
+ 0x3a, 0x31, 0x30, 0x70, 0x78, 0x3b, 0xa, 0x7d, 0xa, 0xa,
+ 0x70, 0x2e, 0x72, 0x69, 0x67, 0x68, 0x74, 0xa, 0x7b, 0xa,
+ 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69,
+ 0x67, 0x6e, 0x3a, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x20,
+ 0xa, 0x7d, 0xa, 0xa, 0};
+
+static const unsigned char data_tcp_shtml[] = {
+ /* /tcp.shtml */
+ 0x2f, 0x74, 0x63, 0x70, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65,
+ 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x68, 0x31,
+ 0x3e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x63,
+ 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0x3c,
+ 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3d, 0x22, 0x31, 0x30, 0x30, 0x25, 0x22, 0x3e, 0xa,
+ 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x4c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74,
+ 0x68, 0x3e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x3c, 0x2f,
+ 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68,
+ 0x3e, 0x52, 0x65, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69,
+ 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x3c, 0x2f, 0x74, 0x68,
+ 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x54, 0x69, 0x6d, 0x65, 0x72,
+ 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x46,
+ 0x6c, 0x61, 0x67, 0x73, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c,
+ 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x25, 0x21, 0x20, 0x74, 0x63,
+ 0x70, 0x2d, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0xa, 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x66,
+ 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c,
+0};
+
+static const unsigned char data_fade_png[] = {
+ /* /fade.png */
+ 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, 0x6e, 0x67, 0,
+ 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 00, 00,
+ 00, 0xd, 0x49, 0x48, 0x44, 0x52, 00, 00, 00, 0x4,
+ 00, 00, 00, 0xa, 0x8, 0x2, 00, 00, 00, 0x1c,
+ 0x99, 0x68, 0x59, 00, 00, 00, 0x9, 0x70, 0x48, 0x59,
+ 0x73, 00, 00, 0xb, 0x13, 00, 00, 0xb, 0x13, 0x1,
+ 00, 0x9a, 0x9c, 0x18, 00, 00, 00, 0x7, 0x74, 0x49,
+ 0x4d, 0x45, 0x7, 0xd6, 0x6, 0x8, 0x14, 0x1b, 0x39, 0xaf,
+ 0x5b, 0xc0, 0xe3, 00, 00, 00, 0x1d, 0x74, 0x45, 0x58,
+ 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 00, 0x43,
+ 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50,
+ 0xef, 0x64, 0x25, 0x6e, 00, 00, 00, 0x3a, 0x49, 0x44,
+ 0x41, 0x54, 0x8, 0xd7, 0x75, 0x8c, 0x31, 0x12, 00, 0x10,
+ 0x10, 0xc4, 0x2e, 0x37, 0x9e, 0x40, 0x65, 0xfd, 0xff, 0x83,
+ 0xf4, 0xa, 0x1c, 0x8d, 0x54, 0x9b, 0xc9, 0xcc, 0x9a, 0x3d,
+ 0x90, 0x73, 0x71, 0x67, 0x91, 0xd4, 0x74, 0x36, 0xa9, 0x55,
+ 0x1, 0xf8, 0x29, 0x58, 0xc8, 0xbf, 0x48, 0xc4, 0x81, 0x74,
+ 0xb, 0xa3, 0xf, 0x7c, 0xdb, 0x4, 0xe8, 0x40, 0x5, 0xdf,
+ 0xa1, 0xf3, 0xfc, 0x73, 00, 00, 00, 00, 0x49, 0x45,
+ 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0};
+
+static const unsigned char data_stats_shtml[] = {
+ /* /stats.shtml */
+ 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0,
+ 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65,
+ 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x68, 0x31,
+ 0x3e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x73,
+ 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x3c,
+ 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74,
+ 0x65, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65,
+ 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x33, 0x30,
+ 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d,
+ 0x22, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c,
+ 0x74, 0x64, 0x3e, 0x3c, 0x70, 0x72, 0x65, 0x3e, 0xa, 0x49,
+ 0x50, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20,
+ 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0xa, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20,
+ 0x73, 0x65, 0x6e, 0x74, 0xa, 0x9, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64,
+ 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x49, 0x50, 0x20,
+ 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x20, 0x20, 0x20, 0x20,
+ 0x49, 0x50, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+ 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x6c, 0x65,
+ 0x6e, 0x67, 0x74, 0x68, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x50,
+ 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x2c, 0x20, 0x68,
+ 0x69, 0x67, 0x68, 0x20, 0x62, 0x79, 0x74, 0x65, 0xa, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x49, 0x50, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74,
+ 0x68, 0x2c, 0x20, 0x6c, 0x6f, 0x77, 0x20, 0x62, 0x79, 0x74,
+ 0x65, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x50, 0x20, 0x66, 0x72,
+ 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0xa, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 0x68,
+ 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0xa, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x57, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x63, 0x6f, 0x6c, 0xa, 0x49, 0x43, 0x4d, 0x50, 0x9,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65,
+ 0x74, 0x73, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
+ 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65,
+ 0x74, 0x73, 0x20, 0x73, 0x65, 0x6e, 0x74, 0xa, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64,
+ 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x54, 0x79, 0x70, 0x65, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72,
+ 0x73, 0xa, 0x54, 0x43, 0x50, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65,
+ 0x74, 0x73, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
+ 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65,
+ 0x74, 0x73, 0x20, 0x73, 0x65, 0x6e, 0x74, 0xa, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64,
+ 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x20, 0x65,
+ 0x72, 0x72, 0x6f, 0x72, 0x73, 0xa, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x44,
+ 0x61, 0x74, 0x61, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74,
+ 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20,
+ 0x41, 0x43, 0x4b, 0x73, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65,
+ 0x73, 0x65, 0x74, 0x73, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65,
+ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69,
+ 0x6f, 0x6e, 0x73, 0xa, 0x9, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x4e, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x76, 0x61, 0x6c, 0x69, 0x61,
+ 0x62, 0x6c, 0x65, 0xa, 0x9, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
+ 0x20, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x20,
+ 0x74, 0x6f, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x20,
+ 0x70, 0x6f, 0x72, 0x74, 0x73, 0xa, 0x3c, 0x2f, 0x70, 0x72,
+ 0x65, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64,
+ 0x3e, 0x3c, 0x70, 0x72, 0x65, 0x3e, 0x25, 0x21, 0x20, 0x6e,
+ 0x65, 0x74, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0xa, 0x3c,
+ 0x2f, 0x70, 0x72, 0x65, 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62,
+ 0x6c, 0x65, 0x3e, 0xa, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74,
+ 0x65, 0x72, 0x3e, 0xa, 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x66,
+ 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c,
+ 0xa, 0};
+
+const struct httpd_fsdata_file file_processes_shtml[] = {{NULL, data_processes_shtml, data_processes_shtml + 17, sizeof(data_processes_shtml) - 17}};
+
+const struct httpd_fsdata_file file_404_html[] = {{file_processes_shtml, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}};
+
+const struct httpd_fsdata_file file_files_shtml[] = {{file_404_html, data_files_shtml, data_files_shtml + 13, sizeof(data_files_shtml) - 13}};
+
+const struct httpd_fsdata_file file_footer_html[] = {{file_files_shtml, data_footer_html, data_footer_html + 13, sizeof(data_footer_html) - 13}};
+
+const struct httpd_fsdata_file file_header_html[] = {{file_footer_html, data_header_html, data_header_html + 13, sizeof(data_header_html) - 13}};
+
+const struct httpd_fsdata_file file_index_html[] = {{file_header_html, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}};
+
+const struct httpd_fsdata_file file_style_css[] = {{file_index_html, data_style_css, data_style_css + 11, sizeof(data_style_css) - 11}};
+
+const struct httpd_fsdata_file file_tcp_shtml[] = {{file_style_css, data_tcp_shtml, data_tcp_shtml + 11, sizeof(data_tcp_shtml) - 11}};
+
+const struct httpd_fsdata_file file_fade_png[] = {{file_tcp_shtml, data_fade_png, data_fade_png + 10, sizeof(data_fade_png) - 10}};
+
+const struct httpd_fsdata_file file_stats_shtml[] = {{file_fade_png, data_stats_shtml, data_stats_shtml + 13, sizeof(data_stats_shtml) - 13}};
+
+#define HTTPD_FS_ROOT file_stats_shtml
+
+#define HTTPD_FS_NUMFILES 10
diff --git a/uip/apps/webserver/httpd-fsdata.h b/uip/apps/webserver/httpd-fsdata.h
new file mode 100644
index 0000000..0ad2d6e
--- /dev/null
+++ b/uip/apps/webserver/httpd-fsdata.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2001, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: httpd-fsdata.h,v 1.1 2006/06/07 09:13:08 adam Exp $
+ */
+#ifndef __HTTPD_FSDATA_H__
+#define __HTTPD_FSDATA_H__
+
+#include "uip.h"
+
+struct httpd_fsdata_file {
+ const struct httpd_fsdata_file *next;
+ const char *name;
+ const char *data;
+ const int len;
+#ifdef HTTPD_FS_STATISTICS
+#if HTTPD_FS_STATISTICS == 1
+ u16_t count;
+#endif /* HTTPD_FS_STATISTICS */
+#endif /* HTTPD_FS_STATISTICS */
+};
+
+struct httpd_fsdata_file_noconst {
+ struct httpd_fsdata_file *next;
+ char *name;
+ char *data;
+ int len;
+#ifdef HTTPD_FS_STATISTICS
+#if HTTPD_FS_STATISTICS == 1
+ u16_t count;
+#endif /* HTTPD_FS_STATISTICS */
+#endif /* HTTPD_FS_STATISTICS */
+};
+
+#endif /* __HTTPD_FSDATA_H__ */
diff --git a/uip/apps/webserver/httpd.c b/uip/apps/webserver/httpd.c
new file mode 100644
index 0000000..937e138
--- /dev/null
+++ b/uip/apps/webserver/httpd.c
@@ -0,0 +1,338 @@
+/**
+ * \addtogroup apps
+ * @{
+ */
+
+/**
+ * \defgroup httpd Web server
+ * @{
+ * The uIP web server is a very simplistic implementation of an HTTP
+ * server. It can serve web pages and files from a read-only ROM
+ * filesystem, and provides a very small scripting language.
+
+ */
+
+/**
+ * \file
+ * Web server
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ */
+
+
+/*
+ * Copyright (c) 2004, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: httpd.c,v 1.2 2006/06/11 21:46:38 adam Exp $
+ */
+
+#include "uip.h"
+#include "httpd.h"
+#include "httpd-fs.h"
+#include "httpd-cgi.h"
+#include "http-strings.h"
+
+#include <string.h>
+
+#define STATE_WAITING 0
+#define STATE_OUTPUT 1
+
+#define ISO_nl 0x0a
+#define ISO_space 0x20
+#define ISO_bang 0x21
+#define ISO_percent 0x25
+#define ISO_period 0x2e
+#define ISO_slash 0x2f
+#define ISO_colon 0x3a
+
+
+/*---------------------------------------------------------------------------*/
+static unsigned short
+generate_part_of_file(void *state)
+{
+ struct httpd_state *s = (struct httpd_state *)state;
+
+ if(s->file.len > uip_mss()) {
+ s->len = uip_mss();
+ } else {
+ s->len = s->file.len;
+ }
+ memcpy(uip_appdata, s->file.data, s->len);
+
+ return s->len;
+}
+/*---------------------------------------------------------------------------*/
+static
+PT_THREAD(send_file(struct httpd_state *s))
+{
+ PSOCK_BEGIN(&s->sout);
+
+ do {
+ PSOCK_GENERATOR_SEND(&s->sout, generate_part_of_file, s);
+ s->file.len -= s->len;
+ s->file.data += s->len;
+ } while(s->file.len > 0);
+
+ PSOCK_END(&s->sout);
+}
+/*---------------------------------------------------------------------------*/
+static
+PT_THREAD(send_part_of_file(struct httpd_state *s))
+{
+ PSOCK_BEGIN(&s->sout);
+
+ PSOCK_SEND(&s->sout, s->file.data, s->len);
+
+ PSOCK_END(&s->sout);
+}
+/*---------------------------------------------------------------------------*/
+static void
+next_scriptstate(struct httpd_state *s)
+{
+ char *p;
+ p = strchr(s->scriptptr, ISO_nl) + 1;
+ s->scriptlen -= (unsigned short)(p - s->scriptptr);
+ s->scriptptr = p;
+}
+/*---------------------------------------------------------------------------*/
+static
+PT_THREAD(handle_script(struct httpd_state *s))
+{
+ char *ptr;
+
+ PT_BEGIN(&s->scriptpt);
+
+
+ while(s->file.len > 0) {
+
+ /* Check if we should start executing a script. */
+ if(*s->file.data == ISO_percent &&
+ *(s->file.data + 1) == ISO_bang) {
+ s->scriptptr = s->file.data + 3;
+ s->scriptlen = s->file.len - 3;
+ if(*(s->scriptptr - 1) == ISO_colon) {
+ httpd_fs_open(s->scriptptr + 1, &s->file);
+ PT_WAIT_THREAD(&s->scriptpt, send_file(s));
+ } else {
+ PT_WAIT_THREAD(&s->scriptpt,
+ httpd_cgi(s->scriptptr)(s, s->scriptptr));
+ }
+ next_scriptstate(s);
+
+ /* The script is over, so we reset the pointers and continue
+ sending the rest of the file. */
+ s->file.data = s->scriptptr;
+ s->file.len = s->scriptlen;
+ } else {
+ /* See if we find the start of script marker in the block of HTML
+ to be sent. */
+
+ if(s->file.len > uip_mss()) {
+ s->len = uip_mss();
+ } else {
+ s->len = s->file.len;
+ }
+
+ if(*s->file.data == ISO_percent) {
+ ptr = strchr(s->file.data + 1, ISO_percent);
+ } else {
+ ptr = strchr(s->file.data, ISO_percent);
+ }
+ if(ptr != NULL &&
+ ptr != s->file.data) {
+ s->len = (int)(ptr - s->file.data);
+ if(s->len >= uip_mss()) {
+ s->len = uip_mss();
+ }
+ }
+ PT_WAIT_THREAD(&s->scriptpt, send_part_of_file(s));
+ s->file.data += s->len;
+ s->file.len -= s->len;
+
+ }
+ }
+
+ PT_END(&s->scriptpt);
+}
+/*---------------------------------------------------------------------------*/
+static
+PT_THREAD(send_headers(struct httpd_state *s, const char *statushdr))
+{
+ char *ptr;
+
+ PSOCK_BEGIN(&s->sout);
+
+ PSOCK_SEND_STR(&s->sout, statushdr);
+
+ ptr = strrchr(s->filename, ISO_period);
+ if(ptr == NULL) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_binary);
+ } else if(strncmp(http_html, ptr, 5) == 0 ||
+ strncmp(http_shtml, ptr, 6) == 0) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_html);
+ } else if(strncmp(http_css, ptr, 4) == 0) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_css);
+ } else if(strncmp(http_png, ptr, 4) == 0) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_png);
+ } else if(strncmp(http_gif, ptr, 4) == 0) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_gif);
+ } else if(strncmp(http_jpg, ptr, 4) == 0) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_jpg);
+ } else {
+ PSOCK_SEND_STR(&s->sout, http_content_type_plain);
+ }
+ PSOCK_END(&s->sout);
+}
+/*---------------------------------------------------------------------------*/
+static
+PT_THREAD(handle_output(struct httpd_state *s))
+{
+ char *ptr;
+
+ PT_BEGIN(&s->outputpt);
+
+ if(!httpd_fs_open(s->filename, &s->file)) {
+ httpd_fs_open(http_404_html, &s->file);
+ strcpy(s->filename, http_404_html);
+ PT_WAIT_THREAD(&s->outputpt,
+ send_headers(s,
+ http_header_404));
+ PT_WAIT_THREAD(&s->outputpt,
+ send_file(s));
+ } else {
+ PT_WAIT_THREAD(&s->outputpt,
+ send_headers(s,
+ http_header_200));
+ ptr = strchr(s->filename, ISO_period);
+ if(ptr != NULL && strncmp(ptr, http_shtml, 6) == 0) {
+ PT_INIT(&s->scriptpt);
+ PT_WAIT_THREAD(&s->outputpt, handle_script(s));
+ } else {
+ PT_WAIT_THREAD(&s->outputpt,
+ send_file(s));
+ }
+ }
+ PSOCK_CLOSE(&s->sout);
+ PT_END(&s->outputpt);
+}
+/*---------------------------------------------------------------------------*/
+static
+PT_THREAD(handle_input(struct httpd_state *s))
+{
+ PSOCK_BEGIN(&s->sin);
+
+ PSOCK_READTO(&s->sin, ISO_space);
+
+
+ if(strncmp(s->inputbuf, http_get, 4) != 0) {
+ PSOCK_CLOSE_EXIT(&s->sin);
+ }
+ PSOCK_READTO(&s->sin, ISO_space);
+
+ if(s->inputbuf[0] != ISO_slash) {
+ PSOCK_CLOSE_EXIT(&s->sin);
+ }
+
+ if(s->inputbuf[1] == ISO_space) {
+ strncpy(s->filename, http_index_html, sizeof(s->filename));
+ } else {
+ s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0;
+ strncpy(s->filename, &s->inputbuf[0], sizeof(s->filename));
+ }
+
+ /* httpd_log_file(uip_conn->ripaddr, s->filename);*/
+
+ s->state = STATE_OUTPUT;
+
+ while(1) {
+ PSOCK_READTO(&s->sin, ISO_nl);
+
+ if(strncmp(s->inputbuf, http_referer, 8) == 0) {
+ s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0;
+ /* httpd_log(&s->inputbuf[9]);*/
+ }
+ }
+
+ PSOCK_END(&s->sin);
+}
+/*---------------------------------------------------------------------------*/
+static void
+handle_connection(struct httpd_state *s)
+{
+ handle_input(s);
+ if(s->state == STATE_OUTPUT) {
+ handle_output(s);
+ }
+}
+/*---------------------------------------------------------------------------*/
+void
+httpd_appcall(void)
+{
+ struct httpd_state *s = (struct httpd_state *)&(uip_conn->appstate);
+
+ if(uip_closed() || uip_aborted() || uip_timedout()) {
+ } else if(uip_connected()) {
+ PSOCK_INIT(&s->sin, s->inputbuf, sizeof(s->inputbuf) - 1);
+ PSOCK_INIT(&s->sout, s->inputbuf, sizeof(s->inputbuf) - 1);
+ PT_INIT(&s->outputpt);
+ s->state = STATE_WAITING;
+ /* timer_set(&s->timer, CLOCK_SECOND * 100);*/
+ s->timer = 0;
+ handle_connection(s);
+ } else if(s != NULL) {
+ if(uip_poll()) {
+ ++s->timer;
+ if(s->timer >= 20) {
+ uip_abort();
+ }
+ } else {
+ s->timer = 0;
+ }
+ handle_connection(s);
+ } else {
+ uip_abort();
+ }
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * \brief Initialize the web server
+ *
+ * This function initializes the web server and should be
+ * called at system boot-up.
+ */
+void
+httpd_init(void)
+{
+ uip_listen(HTONS(80));
+}
+/*---------------------------------------------------------------------------*/
+/** @} */
diff --git a/uip/apps/webserver/httpd.h b/uip/apps/webserver/httpd.h
new file mode 100644
index 0000000..270d49d
--- /dev/null
+++ b/uip/apps/webserver/httpd.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2001-2005, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: httpd.h,v 1.2 2006/06/11 21:46:38 adam Exp $
+ *
+ */
+
+#ifndef __HTTPD_H__
+#define __HTTPD_H__
+
+#include "psock.h"
+#include "httpd-fs.h"
+
+struct httpd_state {
+ unsigned char timer;
+ struct psock sin, sout;
+ struct pt outputpt, scriptpt;
+ char inputbuf[50];
+ char filename[20];
+ char state;
+ struct httpd_fs_file file;
+ int len;
+ char *scriptptr;
+ int scriptlen;
+
+ unsigned short count;
+};
+
+void httpd_init(void);
+void httpd_appcall(void);
+
+void httpd_log(char *msg);
+void httpd_log_file(u16_t *requester, char *file);
+
+#endif /* __HTTPD_H__ */
diff --git a/uip/apps/webserver/makefsdata b/uip/apps/webserver/makefsdata
new file mode 100755
index 0000000..b2109ab
--- /dev/null
+++ b/uip/apps/webserver/makefsdata
@@ -0,0 +1,78 @@
+#!/usr/bin/perl
+
+open(OUTPUT, "> httpd-fsdata.c");
+
+chdir("httpd-fs");
+
+opendir(DIR, ".");
+@files = grep { !/^\./ && !/(CVS|~)/ } readdir(DIR);
+closedir(DIR);
+
+foreach $file (@files) {
+
+ if(-d $file && $file !~ /^\./) {
+ print "Processing directory $file\n";
+ opendir(DIR, $file);
+ @newfiles = grep { !/^\./ && !/(CVS|~)/ } readdir(DIR);
+ closedir(DIR);
+ printf "Adding files @newfiles\n";
+ @files = (@files, map { $_ = "$file/$_" } @newfiles);
+ next;
+ }
+}
+
+foreach $file (@files) {
+ if(-f $file) {
+
+ print "Adding file $file\n";
+
+ open(FILE, $file) || die "Could not open file $file\n";
+
+ $file =~ s-^-/-;
+ $fvar = $file;
+ $fvar =~ s-/-_-g;
+ $fvar =~ s-\.-_-g;
+ # for AVR, add PROGMEM here
+ print(OUTPUT "static const unsigned char data".$fvar."[] = {\n");
+ print(OUTPUT "\t/* $file */\n\t");
+ for($j = 0; $j < length($file); $j++) {
+ printf(OUTPUT "%#02x, ", unpack("C", substr($file, $j, 1)));
+ }
+ printf(OUTPUT "0,\n");
+
+
+ $i = 0;
+ while(read(FILE, $data, 1)) {
+ if($i == 0) {
+ print(OUTPUT "\t");
+ }
+ printf(OUTPUT "%#02x, ", unpack("C", $data));
+ $i++;
+ if($i == 10) {
+ print(OUTPUT "\n");
+ $i = 0;
+ }
+ }
+ print(OUTPUT "0};\n\n");
+ close(FILE);
+ push(@fvars, $fvar);
+ push(@pfiles, $file);
+ }
+}
+
+for($i = 0; $i < @fvars; $i++) {
+ $file = $pfiles[$i];
+ $fvar = $fvars[$i];
+
+ if($i == 0) {
+ $prevfile = "NULL";
+ } else {
+ $prevfile = "file" . $fvars[$i - 1];
+ }
+ print(OUTPUT "const struct httpd_fsdata_file file".$fvar."[] = {{$prevfile, data$fvar, ");
+ print(OUTPUT "data$fvar + ". (length($file) + 1) .", ");
+ print(OUTPUT "sizeof(data$fvar) - ". (length($file) + 1) ."}};\n\n");
+}
+
+print(OUTPUT "#define HTTPD_FS_ROOT file$fvars[$i - 1]\n\n");
+print(OUTPUT "#define HTTPD_FS_NUMFILES $i\n");
diff --git a/uip/apps/webserver/makestrings b/uip/apps/webserver/makestrings
new file mode 100755
index 0000000..20f0e24
--- /dev/null
+++ b/uip/apps/webserver/makestrings
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+
+
+sub stringify {
+ my $name = shift(@_);
+ open(OUTPUTC, "> $name.c");
+ open(OUTPUTH, "> $name.h");
+
+ open(FILE, "$name");
+
+ while(<FILE>) {
+ if(/(.+) "(.+)"/) {
+ $var = $1;
+ $data = $2;
+
+ $datan = $data;
+ $datan =~ s/\\r/\r/g;
+ $datan =~ s/\\n/\n/g;
+ $datan =~ s/\\01/\01/g;
+ $datan =~ s/\\0/\0/g;
+
+ printf(OUTPUTC "const char $var\[%d] = \n", length($datan) + 1);
+ printf(OUTPUTC "/* \"$data\" */\n");
+ printf(OUTPUTC "{");
+ for($j = 0; $j < length($datan); $j++) {
+ printf(OUTPUTC "%#02x, ", unpack("C", substr($datan, $j, 1)));
+ }
+ printf(OUTPUTC "};\n");
+
+ printf(OUTPUTH "extern const char $var\[%d];\n", length($datan) + 1);
+
+ }
+ }
+ close(OUTPUTC);
+ close(OUTPUTH);
+}
+stringify("http-strings");
+
+exit 0;
+
diff --git a/uip/apps/webserver/webserver.h b/uip/apps/webserver/webserver.h
new file mode 100644
index 0000000..48753e6
--- /dev/null
+++ b/uip/apps/webserver/webserver.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2002, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: webserver.h,v 1.2 2006/06/11 21:46:38 adam Exp $
+ *
+ */
+#ifndef __WEBSERVER_H__
+#define __WEBSERVER_H__
+
+#include "httpd.h"
+
+typedef struct httpd_state uip_tcp_appstate_t;
+/* UIP_APPCALL: the name of the application function. This function
+ must return void and take no arguments (i.e., C type "void
+ appfunc(void)"). */
+#ifndef UIP_APPCALL
+#define UIP_APPCALL httpd_appcall
+#endif
+
+
+#endif /* __WEBSERVER_H__ */
diff --git a/uip/lib/memb.c b/uip/lib/memb.c
new file mode 100644
index 0000000..777b52f
--- /dev/null
+++ b/uip/lib/memb.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: memb.c,v 1.1 2006/06/12 08:21:43 adam Exp $
+ */
+
+/**
+ * \addtogroup memb
+ * @{
+ */
+
+ /**
+ * \file
+ * Memory block allocation routines.
+ * \author Adam Dunkels <adam@sics.se>
+ */
+#include <string.h>
+
+#include "memb.h"
+
+/*---------------------------------------------------------------------------*/
+void
+memb_init(struct memb_blocks *m)
+{
+ memset(m->count, 0, m->num);
+ memset(m->mem, 0, m->size * m->num);
+}
+/*---------------------------------------------------------------------------*/
+void *
+memb_alloc(struct memb_blocks *m)
+{
+ int i;
+
+ for(i = 0; i < m->num; ++i) {
+ if(m->count[i] == 0) {
+ /* If this block was unused, we increase the reference count to
+ indicate that it now is used and return a pointer to the
+ memory block. */
+ ++(m->count[i]);
+ return (void *)((char *)m->mem + (i * m->size));
+ }
+ }
+
+ /* No free block was found, so we return NULL to indicate failure to
+ allocate block. */
+ return NULL;
+}
+/*---------------------------------------------------------------------------*/
+char
+memb_free(struct memb_blocks *m, void *ptr)
+{
+ int i;
+ char *ptr2;
+
+ /* Walk through the list of blocks and try to find the block to
+ which the pointer "ptr" points to. */
+ ptr2 = (char *)m->mem;
+ for(i = 0; i < m->num; ++i) {
+
+ if(ptr2 == (char *)ptr) {
+ /* We've found to block to which "ptr" points so we decrease the
+ reference count and return the new value of it. */
+ if(m->count[i] > 0) {
+ /* Make sure that we don't deallocate free memory. */
+ --(m->count[i]);
+ }
+ return m->count[i];
+ }
+ ptr2 += m->size;
+ }
+ return -1;
+}
+/*---------------------------------------------------------------------------*/
+
+/** @} */
diff --git a/uip/lib/memb.h b/uip/lib/memb.h
new file mode 100644
index 0000000..b725ebe
--- /dev/null
+++ b/uip/lib/memb.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: memb.h,v 1.1 2006/06/12 08:21:43 adam Exp $
+ */
+
+/**
+ * \defgroup memb Memory block management functions
+ *
+ * The memory block allocation routines provide a simple yet powerful
+ * set of functions for managing a set of memory blocks of fixed
+ * size. A set of memory blocks is statically declared with the
+ * MEMB() macro. Memory blocks are allocated from the declared
+ * memory by the memb_alloc() function, and are deallocated with the
+ * memb_free() function.
+ *
+ * \note Because of namespace clashes only one MEMB() can be
+ * declared per C module, and the name scope of a MEMB() memory
+ * block is local to each C module.
+ *
+ * The following example shows how to declare and use a memory block
+ * called "cmem" which has 8 chunks of memory with each memory chunk
+ * being 20 bytes large.
+ *
+ * @{
+ */
+
+
+/**
+ * \file
+ * Memory block allocation routines.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef __MEMB_H__
+#define __MEMB_H__
+
+/*
+ * Here we define a C preprocessing macro for concatenating to
+ * strings. We need use two macros in order to allow concatenation of
+ * two #defined macros.
+ */
+#define MEMB_CONCAT2(s1, s2) s1##s2
+#define MEMB_CONCAT(s1, s2) MEMB_CONCAT2(s1, s2)
+
+/**
+ * Declare a memory block.
+ *
+ * This macro is used to staticall declare a block of memory that can
+ * be used by the block allocation functions. The macro statically
+ * declares a C array with a size that matches the specified number of
+ * blocks and their individual sizes.
+ *
+ * Example:
+ \code
+MEMB(connections, sizeof(struct connection), 16);
+ \endcode
+ *
+ * \param name The name of the memory block (later used with
+ * memb_init(), memb_alloc() and memb_free()).
+ *
+ * \param size The size of each memory chunk, in bytes.
+ *
+ * \param num The total number of memory chunks in the block.
+ *
+ */
+#define MEMB(name, structure, num) \
+ static char MEMB_CONCAT(name,_memb_count)[num]; \
+ static structure MEMB_CONCAT(name,_memb_mem)[num]; \
+ static struct memb_blocks name = {sizeof(structure), num, \
+ MEMB_CONCAT(name,_memb_count), \
+ (void *)MEMB_CONCAT(name,_memb_mem)}
+
+struct memb_blocks {
+ unsigned short size;
+ unsigned short num;
+ char *count;
+ void *mem;
+};
+
+/**
+ * Initialize a memory block that was declared with MEMB().
+ *
+ * \param m A memory block previosly declared with MEMB().
+ */
+void memb_init(struct memb_blocks *m);
+
+/**
+ * Allocate a memory block from a block of memory declared with MEMB().
+ *
+ * \param m A memory block previosly declared with MEMB().
+ */
+void *memb_alloc(struct memb_blocks *m);
+
+/**
+ * Deallocate a memory block from a memory block previously declared
+ * with MEMB().
+ *
+ * \param m m A memory block previosly declared with MEMB().
+ *
+ * \param ptr A pointer to the memory block that is to be deallocated.
+ *
+ * \return The new reference count for the memory block (should be 0
+ * if successfully deallocated) or -1 if the pointer "ptr" did not
+ * point to a legal memory block.
+ */
+char memb_free(struct memb_blocks *m, void *ptr);
+
+/** @} */
+
+#endif /* __MEMB_H__ */
diff --git a/uip/uip-1.0-changelog.txt b/uip/uip-1.0-changelog.txt
new file mode 100644
index 0000000..1e6c61c
--- /dev/null
+++ b/uip/uip-1.0-changelog.txt
@@ -0,0 +1,98 @@
+* A new API: protosockets that are similar to BSD sockets but does not
+ require any underlying multithreading system.
+
+* Very rudimentary IPv6 support
+
+* New application: DHCP client. Web server rewritten with protosockets.
+
+* Removed uIP zero-copy functionality in order to simplify uIP device
+ driver coding: outbound packets are now *always* stored in full in
+ the uip_buf buffer.
+
+* Checksum computation is now part of uip.c, but it still is possible
+ to implement them in assembly code by specifying a configuration
+ option. Checksum code now runs on architectures with 2-byte alignment.
+
+* Added TCP persistent timer.
+
+* Made all IP address representations use the new uip_ipaddr_ip
+ datatype for clarity.
+
+* Updated window behavior so that sending to a host with a small open
+ window works better now.
+
+* UDP API change: uip_udp_new() now takes port numbers in network byte
+ order like TCP functions.
+
+* Allow reception of packets when no IP address is configured to make
+ DHCP work.
+
+* Moved Ethernet address into main uIP module from ARP module.
+
+* Made constants explicit #defines and moved them out of the code
+ (header sizes, TCP options, TCP header length field).
+
+* If uip_len is less than that reported by the IP header, the packet
+ is discarded. If uip_len is greater than the length reported by the
+ IP header, uip_len is adjusted.
+
+* Moved header size definitions into header file.
+
+* Added uIP call for polling an application without triggering any
+ timer events. Removed redundant assignments of uip_len and uip_slen.
+
+* Removed compiler warning about icmp_input label being defined when
+ UIP_PINGADDRCONF was not used.
+
+* Added UIP_APPDATA_SIZE macro that holds the available buffer size
+ for user data.
+
+* Added uip_udp_bind() call.
+
+* Moved checksum code into main uIP module.
+
+* Switched the TCP, UDP and IP header structures to be structs rather
+ than typedefs.
+
+* Prefixed TCP state names with UIP_ to avoid name space
+ contamination.
+
+* Changed declarations of uip_appdatap and friends to void * to avoid
+ explicit typecasts.
+
+* Bugfixes
+
+ o TCP: Fixed bug with high byte of peer window size.
+
+ o TCP: Fixed bug that in some cases prevented concurrent reception and
+ transmission of TCP data.
+
+ o TCP: uip_connect() didn't correctly calculate age of TIME_WAIT
+ connections.
+
+ o TCP: Array index for uip_conns[] array was out of bounds in
+ comparison. Comparison changed to make index within bounds.
+
+ o TCP: if the remote host crashes and tries to reestablish an old
+ connection, uIP should respond with an ACK with the correct
+ sequence and acknowledgment numbers, to which the remote host
+ should respond with an ACK. uIP did not respond with the correct
+ ACK.
+
+ o TCP: Fixed check for SYNACK segment: now checks only relevant TCP
+ control flags and discards flags reserved for future expansion.
+
+ o TCP: Fixed bug where uIP did not inform application that a connection
+ had been aborted during an active open.
+
+ o TCP: FIN segment was accepted even though application had stopped
+ incoming data with uip_stop().
+
+ o TCP: A FINACK segment would not always correctly acknowledge data.
+
+ o UDP: checksums are now calculated after all fields have been
+ filled in.
+
+ o UDP: network byte order on lastport in uip_udp_new().
+
+ o IP: memset() bugs in IP fragment reassembly code fixed.
diff --git a/uip/uip/Makefile.include b/uip/uip/Makefile.include
new file mode 100644
index 0000000..3426dd1
--- /dev/null
+++ b/uip/uip/Makefile.include
@@ -0,0 +1,47 @@
+
+
+ifdef APPS
+ APPDIRS = $(foreach APP, $(APPS), ../apps/$(APP))
+ -include $(foreach APP, $(APPS), ../apps/$(APP)/Makefile.$(APP))
+ CFLAGS += $(addprefix -I../apps/,$(APPS))
+endif
+
+ifndef CCDEP
+ CCDEP = $(CC)
+endif
+ifndef CCDEPCFLAGS
+ CCDEPCFLAGS = $(CFLAGS)
+endif
+ifndef OBJECTDIR
+ OBJECTDIR = obj
+endif
+
+ifeq (${wildcard $(OBJECTDIR)},)
+ DUMMY := ${shell mkdir $(OBJECTDIR)}
+endif
+
+
+vpath %.c . ../uip ../lib $(APPDIRS)
+
+$(OBJECTDIR)/%.o: %.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+$(OBJECTDIR)/%.d: %.c
+ @set -e; rm -f $@; \
+ $(CCDEP) -MM $(CCDEPCFLAGS) $< > $@.$$$$; \
+ sed 's,\($*\)\.o[ :]*,$(OBJECTDIR)/\1.o $@ : ,g' < $@.$$$$ > $@; \
+ rm -f $@.$$$$
+
+UIP_SOURCES=uip.c uip_arp.c uiplib.c psock.c timer.c uip-neighbor.c
+
+
+ifneq ($(MAKECMDGOALS),clean)
+-include $(addprefix $(OBJECTDIR)/,$(UIP_SOURCES:.c=.d) \
+ $(APP_SOURCES:.c=.d))
+endif
+
+uip.a: ${addprefix $(OBJECTDIR)/, $(UIP_SOURCES:.c=.o)}
+ $(AR) a $@ $^
+
+apps.a: ${addprefix $(OBJECTDIR)/, $(APP_SOURCES:.c=.o)}
+ $(AR) a $@ $^
diff --git a/uip/uip/clock.h b/uip/uip/clock.h
new file mode 100644
index 0000000..f34d78f
--- /dev/null
+++ b/uip/uip/clock.h
@@ -0,0 +1,88 @@
+/**
+ * \defgroup clock Clock interface
+ *
+ * The clock interface is the interface between the \ref timer "timer library"
+ * and the platform specific clock functionality. The clock
+ * interface must be implemented for each platform that uses the \ref
+ * timer "timer library".
+ *
+ * The clock interface does only one this: it measures time. The clock
+ * interface provides a macro, CLOCK_SECOND, which corresponds to one
+ * second of system time.
+ *
+ * \sa \ref timer "Timer library"
+ *
+ * @{
+ */
+
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: clock.h,v 1.3 2006/06/11 21:46:39 adam Exp $
+ */
+#ifndef __CLOCK_H__
+#define __CLOCK_H__
+
+#include "clock-arch.h"
+
+/**
+ * Initialize the clock library.
+ *
+ * This function initializes the clock library and should be called
+ * from the main() function of the system.
+ *
+ */
+void clock_init(void);
+
+/**
+ * Get the current clock time.
+ *
+ * This function returns the current system clock time.
+ *
+ * \return The current clock time, measured in system ticks.
+ */
+clock_time_t clock_time(void);
+
+/**
+ * A second, measured in system clock time.
+ *
+ * \hideinitializer
+ */
+#ifdef CLOCK_CONF_SECOND
+#define CLOCK_SECOND CLOCK_CONF_SECOND
+#else
+#define CLOCK_SECOND (clock_time_t)32
+#endif
+
+#endif /* __CLOCK_H__ */
+
+/** @} */
diff --git a/uip/uip/lc-addrlabels.h b/uip/uip/lc-addrlabels.h
new file mode 100644
index 0000000..fe1387e
--- /dev/null
+++ b/uip/uip/lc-addrlabels.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: lc-addrlabels.h,v 1.3 2006/06/12 08:00:30 adam Exp $
+ */
+
+/**
+ * \addtogroup lc
+ * @{
+ */
+
+/**
+ * \file
+ * Implementation of local continuations based on the "Labels as
+ * values" feature of gcc
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ * This implementation of local continuations is based on a special
+ * feature of the GCC C compiler called "labels as values". This
+ * feature allows assigning pointers with the address of the code
+ * corresponding to a particular C label.
+ *
+ * For more information, see the GCC documentation:
+ * http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
+ *
+ * Thanks to dividuum for finding the nice local scope label
+ * implementation.
+ */
+
+#ifndef __LC_ADDRLABELS_H__
+#define __LC_ADDRLABELS_H__
+
+/** \hideinitializer */
+typedef void * lc_t;
+
+#define LC_INIT(s) s = NULL
+
+
+#define LC_RESUME(s) \
+ do { \
+ if(s != NULL) { \
+ goto *s; \
+ } \
+ } while(0)
+
+#define LC_SET(s) \
+ do { ({ __label__ resume; resume: (s) = &&resume; }); }while(0)
+
+#define LC_END(s)
+
+#endif /* __LC_ADDRLABELS_H__ */
+
+/** @} */
diff --git a/uip/uip/lc-switch.h b/uip/uip/lc-switch.h
new file mode 100644
index 0000000..f32885f
--- /dev/null
+++ b/uip/uip/lc-switch.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: lc-switch.h,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+
+/**
+ * \addtogroup lc
+ * @{
+ */
+
+/**
+ * \file
+ * Implementation of local continuations based on switch() statment
+ * \author Adam Dunkels <adam@sics.se>
+ *
+ * This implementation of local continuations uses the C switch()
+ * statement to resume execution of a function somewhere inside the
+ * function's body. The implementation is based on the fact that
+ * switch() statements are able to jump directly into the bodies of
+ * control structures such as if() or while() statmenets.
+ *
+ * This implementation borrows heavily from Simon Tatham's coroutines
+ * implementation in C:
+ * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
+ */
+
+#ifndef __LC_SWITCH_H__
+#define __LC_SWTICH_H__
+
+/* WARNING! lc implementation using switch() does not work if an
+ LC_SET() is done within another switch() statement! */
+
+/** \hideinitializer */
+typedef unsigned short lc_t;
+
+#define LC_INIT(s) s = 0;
+
+#define LC_RESUME(s) switch(s) { case 0:
+
+#define LC_SET(s) s = __LINE__; case __LINE__:
+
+#define LC_END(s) }
+
+#endif /* __LC_SWITCH_H__ */
+
+/** @} */
diff --git a/uip/uip/lc.h b/uip/uip/lc.h
new file mode 100644
index 0000000..a9e9d46
--- /dev/null
+++ b/uip/uip/lc.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: lc.h,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+
+/**
+ * \addtogroup pt
+ * @{
+ */
+
+/**
+ * \defgroup lc Local continuations
+ * @{
+ *
+ * Local continuations form the basis for implementing protothreads. A
+ * local continuation can be <i>set</i> in a specific function to
+ * capture the state of the function. After a local continuation has
+ * been set can be <i>resumed</i> in order to restore the state of the
+ * function at the point where the local continuation was set.
+ *
+ *
+ */
+
+/**
+ * \file lc.h
+ * Local continuations
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifdef DOXYGEN
+/**
+ * Initialize a local continuation.
+ *
+ * This operation initializes the local continuation, thereby
+ * unsetting any previously set continuation state.
+ *
+ * \hideinitializer
+ */
+#define LC_INIT(lc)
+
+/**
+ * Set a local continuation.
+ *
+ * The set operation saves the state of the function at the point
+ * where the operation is executed. As far as the set operation is
+ * concerned, the state of the function does <b>not</b> include the
+ * call-stack or local (automatic) variables, but only the program
+ * counter and such CPU registers that needs to be saved.
+ *
+ * \hideinitializer
+ */
+#define LC_SET(lc)
+
+/**
+ * Resume a local continuation.
+ *
+ * The resume operation resumes a previously set local continuation, thus
+ * restoring the state in which the function was when the local
+ * continuation was set. If the local continuation has not been
+ * previously set, the resume operation does nothing.
+ *
+ * \hideinitializer
+ */
+#define LC_RESUME(lc)
+
+/**
+ * Mark the end of local continuation usage.
+ *
+ * The end operation signifies that local continuations should not be
+ * used any more in the function. This operation is not needed for
+ * most implementations of local continuation, but is required by a
+ * few implementations.
+ *
+ * \hideinitializer
+ */
+#define LC_END(lc)
+
+/**
+ * \var typedef lc_t;
+ *
+ * The local continuation type.
+ *
+ * \hideinitializer
+ */
+#endif /* DOXYGEN */
+
+#ifndef __LC_H__
+#define __LC_H__
+
+#ifdef LC_CONF_INCLUDE
+#include LC_CONF_INCLUDE
+#else
+#include "lc-switch.h"
+#endif /* LC_CONF_INCLUDE */
+
+#endif /* __LC_H__ */
+
+/** @} */
+/** @} */
diff --git a/uip/uip/psock.c b/uip/uip/psock.c
new file mode 100644
index 0000000..f284cb9
--- /dev/null
+++ b/uip/uip/psock.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: psock.c,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "uipopt.h"
+#include "psock.h"
+#include "uip.h"
+
+#define STATE_NONE 0
+#define STATE_ACKED 1
+#define STATE_READ 2
+#define STATE_BLOCKED_NEWDATA 3
+#define STATE_BLOCKED_CLOSE 4
+#define STATE_BLOCKED_SEND 5
+#define STATE_DATA_SENT 6
+
+/*
+ * Return value of the buffering functions that indicates that a
+ * buffer was not filled by incoming data.
+ *
+ */
+#define BUF_NOT_FULL 0
+#define BUF_NOT_FOUND 0
+
+/*
+ * Return value of the buffering functions that indicates that a
+ * buffer was completely filled by incoming data.
+ *
+ */
+#define BUF_FULL 1
+
+/*
+ * Return value of the buffering functions that indicates that an
+ * end-marker byte was found.
+ *
+ */
+#define BUF_FOUND 2
+
+/*---------------------------------------------------------------------------*/
+static void
+buf_setup(struct psock_buf *buf,
+ u8_t *bufptr, u16_t bufsize)
+{
+ buf->ptr = bufptr;
+ buf->left = bufsize;
+}
+/*---------------------------------------------------------------------------*/
+static u8_t
+buf_bufdata(struct psock_buf *buf, u16_t len,
+ u8_t **dataptr, u16_t *datalen)
+{
+ if(*datalen < buf->left) {
+ memcpy(buf->ptr, *dataptr, *datalen);
+ buf->ptr += *datalen;
+ buf->left -= *datalen;
+ *dataptr += *datalen;
+ *datalen = 0;
+ return BUF_NOT_FULL;
+ } else if(*datalen == buf->left) {
+ memcpy(buf->ptr, *dataptr, *datalen);
+ buf->ptr += *datalen;
+ buf->left = 0;
+ *dataptr += *datalen;
+ *datalen = 0;
+ return BUF_FULL;
+ } else {
+ memcpy(buf->ptr, *dataptr, buf->left);
+ buf->ptr += buf->left;
+ *datalen -= buf->left;
+ *dataptr += buf->left;
+ buf->left = 0;
+ return BUF_FULL;
+ }
+}
+/*---------------------------------------------------------------------------*/
+static u8_t
+buf_bufto(register struct psock_buf *buf, u8_t endmarker,
+ register u8_t **dataptr, register u16_t *datalen)
+{
+ u8_t c;
+ while(buf->left > 0 && *datalen > 0) {
+ c = *buf->ptr = **dataptr;
+ ++*dataptr;
+ ++buf->ptr;
+ --*datalen;
+ --buf->left;
+
+ if(c == endmarker) {
+ return BUF_FOUND;
+ }
+ }
+
+ if(*datalen == 0) {
+ return BUF_NOT_FOUND;
+ }
+
+ while(*datalen > 0) {
+ c = **dataptr;
+ --*datalen;
+ ++*dataptr;
+
+ if(c == endmarker) {
+ return BUF_FOUND | BUF_FULL;
+ }
+ }
+
+ return BUF_FULL;
+}
+/*---------------------------------------------------------------------------*/
+static char
+send_data(register struct psock *s)
+{
+ if(s->state != STATE_DATA_SENT || uip_rexmit()) {
+ if(s->sendlen > uip_mss()) {
+ uip_send(s->sendptr, uip_mss());
+ } else {
+ uip_send(s->sendptr, s->sendlen);
+ }
+ s->state = STATE_DATA_SENT;
+ return 1;
+ }
+ return 0;
+}
+/*---------------------------------------------------------------------------*/
+static char
+data_acked(register struct psock *s)
+{
+ if(s->state == STATE_DATA_SENT && uip_acked()) {
+ if(s->sendlen > uip_mss()) {
+ s->sendlen -= uip_mss();
+ s->sendptr += uip_mss();
+ } else {
+ s->sendptr += s->sendlen;
+ s->sendlen = 0;
+ }
+ s->state = STATE_ACKED;
+ return 1;
+ }
+ return 0;
+}
+/*---------------------------------------------------------------------------*/
+PT_THREAD(psock_send(register struct psock *s, const char *buf,
+ unsigned int len))
+{
+ PT_BEGIN(&s->psockpt);
+
+ /* If there is no data to send, we exit immediately. */
+ if(len == 0) {
+ PT_EXIT(&s->psockpt);
+ }
+
+ /* Save the length of and a pointer to the data that is to be
+ sent. */
+ s->sendptr = buf;
+ s->sendlen = len;
+
+ s->state = STATE_NONE;
+
+ /* We loop here until all data is sent. The s->sendlen variable is
+ updated by the data_sent() function. */
+ while(s->sendlen > 0) {
+
+ /*
+ * The condition for this PT_WAIT_UNTIL is a little tricky: the
+ * protothread will wait here until all data has been acknowledged
+ * (data_acked() returns true) and until all data has been sent
+ * (send_data() returns true). The two functions data_acked() and
+ * send_data() must be called in succession to ensure that all
+ * data is sent. Therefore the & operator is used instead of the
+ * && operator, which would cause only the data_acked() function
+ * to be called when it returns false.
+ */
+ PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s));
+ }
+
+ s->state = STATE_NONE;
+
+ PT_END(&s->psockpt);
+}
+/*---------------------------------------------------------------------------*/
+PT_THREAD(psock_generator_send(register struct psock *s,
+ unsigned short (*generate)(void *), void *arg))
+{
+ PT_BEGIN(&s->psockpt);
+
+ /* Ensure that there is a generator function to call. */
+ if(generate == NULL) {
+ PT_EXIT(&s->psockpt);
+ }
+
+ /* Call the generator function to generate the data in the
+ uip_appdata buffer. */
+ s->sendlen = generate(arg);
+ s->sendptr = uip_appdata;
+
+ s->state = STATE_NONE;
+ do {
+ /* Call the generator function again if we are called to perform a
+ retransmission. */
+ if(uip_rexmit()) {
+ generate(arg);
+ }
+ /* Wait until all data is sent and acknowledged. */
+ PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s));
+ } while(s->sendlen > 0);
+
+ s->state = STATE_NONE;
+
+ PT_END(&s->psockpt);
+}
+/*---------------------------------------------------------------------------*/
+u16_t
+psock_datalen(struct psock *psock)
+{
+ return psock->bufsize - psock->buf.left;
+}
+/*---------------------------------------------------------------------------*/
+char
+psock_newdata(struct psock *s)
+{
+ if(s->readlen > 0) {
+ /* There is data in the uip_appdata buffer that has not yet been
+ read with the PSOCK_READ functions. */
+ return 1;
+ } else if(s->state == STATE_READ) {
+ /* All data in uip_appdata buffer already consumed. */
+ s->state = STATE_BLOCKED_NEWDATA;
+ return 0;
+ } else if(uip_newdata()) {
+ /* There is new data that has not been consumed. */
+ return 1;
+ } else {
+ /* There is no new data. */
+ return 0;
+ }
+}
+/*---------------------------------------------------------------------------*/
+PT_THREAD(psock_readto(register struct psock *psock, unsigned char c))
+{
+ PT_BEGIN(&psock->psockpt);
+
+ buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
+
+ /* XXX: Should add buf_checkmarker() before do{} loop, if
+ incoming data has been handled while waiting for a write. */
+
+ do {
+ if(psock->readlen == 0) {
+ PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock));
+ psock->state = STATE_READ;
+ psock->readptr = (u8_t *)uip_appdata;
+ psock->readlen = uip_datalen();
+ }
+ } while((buf_bufto(&psock->buf, c,
+ &psock->readptr,
+ &psock->readlen) & BUF_FOUND) == 0);
+
+ if(psock_datalen(psock) == 0) {
+ psock->state = STATE_NONE;
+ PT_RESTART(&psock->psockpt);
+ }
+ PT_END(&psock->psockpt);
+}
+/*---------------------------------------------------------------------------*/
+PT_THREAD(psock_readbuf(register struct psock *psock))
+{
+ PT_BEGIN(&psock->psockpt);
+
+ buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
+
+ /* XXX: Should add buf_checkmarker() before do{} loop, if
+ incoming data has been handled while waiting for a write. */
+
+ do {
+ if(psock->readlen == 0) {
+ PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock));
+ printf("Waited for newdata\n");
+ psock->state = STATE_READ;
+ psock->readptr = (u8_t *)uip_appdata;
+ psock->readlen = uip_datalen();
+ }
+ } while(buf_bufdata(&psock->buf, psock->bufsize,
+ &psock->readptr,
+ &psock->readlen) != BUF_FULL);
+
+ if(psock_datalen(psock) == 0) {
+ psock->state = STATE_NONE;
+ PT_RESTART(&psock->psockpt);
+ }
+ PT_END(&psock->psockpt);
+}
+/*---------------------------------------------------------------------------*/
+void
+psock_init(register struct psock *psock, char *buffer, unsigned int buffersize)
+{
+ psock->state = STATE_NONE;
+ psock->readlen = 0;
+ psock->bufptr = buffer;
+ psock->bufsize = buffersize;
+ buf_setup(&psock->buf, buffer, buffersize);
+ PT_INIT(&psock->pt);
+ PT_INIT(&psock->psockpt);
+}
+/*---------------------------------------------------------------------------*/
diff --git a/uip/uip/psock.h b/uip/uip/psock.h
new file mode 100644
index 0000000..3dffa73
--- /dev/null
+++ b/uip/uip/psock.h
@@ -0,0 +1,380 @@
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: psock.h,v 1.3 2006/06/12 08:00:30 adam Exp $
+ */
+
+/**
+ * \defgroup psock Protosockets library
+ * @{
+ *
+ * The protosocket library provides an interface to the uIP stack that is
+ * similar to the traditional BSD socket interface. Unlike programs
+ * written for the ordinary uIP event-driven interface, programs
+ * written with the protosocket library are executed in a sequential
+ * fashion and does not have to be implemented as explicit state
+ * machines.
+ *
+ * Protosockets only work with TCP connections.
+ *
+ * The protosocket library uses \ref pt protothreads to provide
+ * sequential control flow. This makes the protosockets lightweight in
+ * terms of memory, but also means that protosockets inherits the
+ * functional limitations of protothreads. Each protosocket lives only
+ * within a single function. Automatic variables (stack variables) are
+ * not retained across a protosocket library function call.
+ *
+ * \note Because the protosocket library uses protothreads, local
+ * variables will not always be saved across a call to a protosocket
+ * library function. It is therefore advised that local variables are
+ * used with extreme care.
+ *
+ * The protosocket library provides functions for sending data without
+ * having to deal with retransmissions and acknowledgements, as well
+ * as functions for reading data without having to deal with data
+ * being split across more than one TCP segment.
+ *
+ * Because each protosocket runs as a protothread, the protosocket has to be
+ * started with a call to PSOCK_BEGIN() at the start of the function
+ * in which the protosocket is used. Similarly, the protosocket protothread can
+ * be terminated by a call to PSOCK_EXIT().
+ *
+ */
+
+/**
+ * \file
+ * Protosocket library header file
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef __PSOCK_H__
+#define __PSOCK_H__
+
+#include "uipopt.h"
+#include "pt.h"
+
+ /*
+ * The structure that holds the state of a buffer.
+ *
+ * This structure holds the state of a uIP buffer. The structure has
+ * no user-visible elements, but is used through the functions
+ * provided by the library.
+ *
+ */
+struct psock_buf {
+ u8_t *ptr;
+ unsigned short left;
+};
+
+/**
+ * The representation of a protosocket.
+ *
+ * The protosocket structrure is an opaque structure with no user-visible
+ * elements.
+ */
+struct psock {
+ struct pt pt, psockpt; /* Protothreads - one that's using the psock
+ functions, and one that runs inside the
+ psock functions. */
+ const u8_t *sendptr; /* Pointer to the next data to be sent. */
+ u8_t *readptr; /* Pointer to the next data to be read. */
+
+ char *bufptr; /* Pointer to the buffer used for buffering
+ incoming data. */
+
+ u16_t sendlen; /* The number of bytes left to be sent. */
+ u16_t readlen; /* The number of bytes left to be read. */
+
+ struct psock_buf buf; /* The structure holding the state of the
+ input buffer. */
+ unsigned int bufsize; /* The size of the input buffer. */
+
+ unsigned char state; /* The state of the protosocket. */
+};
+
+void psock_init(struct psock *psock, char *buffer, unsigned int buffersize);
+/**
+ * Initialize a protosocket.
+ *
+ * This macro initializes a protosocket and must be called before the
+ * protosocket is used. The initialization also specifies the input buffer
+ * for the protosocket.
+ *
+ * \param psock (struct psock *) A pointer to the protosocket to be
+ * initialized
+ *
+ * \param buffer (char *) A pointer to the input buffer for the
+ * protosocket.
+ *
+ * \param buffersize (unsigned int) The size of the input buffer.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_INIT(psock, buffer, buffersize) \
+ psock_init(psock, buffer, buffersize)
+
+/**
+ * Start the protosocket protothread in a function.
+ *
+ * This macro starts the protothread associated with the protosocket and
+ * must come before other protosocket calls in the function it is used.
+ *
+ * \param psock (struct psock *) A pointer to the protosocket to be
+ * started.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_BEGIN(psock) PT_BEGIN(&((psock)->pt))
+
+PT_THREAD(psock_send(struct psock *psock, const char *buf, unsigned int len));
+/**
+ * Send data.
+ *
+ * This macro sends data over a protosocket. The protosocket protothread blocks
+ * until all data has been sent and is known to have been received by
+ * the remote end of the TCP connection.
+ *
+ * \param psock (struct psock *) A pointer to the protosocket over which
+ * data is to be sent.
+ *
+ * \param data (char *) A pointer to the data that is to be sent.
+ *
+ * \param datalen (unsigned int) The length of the data that is to be
+ * sent.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_SEND(psock, data, datalen) \
+ PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, data, datalen))
+
+/**
+ * \brief Send a null-terminated string.
+ * \param psock Pointer to the protosocket.
+ * \param str The string to be sent.
+ *
+ * This function sends a null-terminated string over the
+ * protosocket.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_SEND_STR(psock, str) \
+ PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, str, strlen(str)))
+
+PT_THREAD(psock_generator_send(struct psock *psock,
+ unsigned short (*f)(void *), void *arg));
+
+/**
+ * \brief Generate data with a function and send it
+ * \param psock Pointer to the protosocket.
+ * \param generator Pointer to the generator function
+ * \param arg Argument to the generator function
+ *
+ * This function generates data and sends it over the
+ * protosocket. This can be used to dynamically generate
+ * data for a transmission, instead of generating the data
+ * in a buffer beforehand. This function reduces the need for
+ * buffer memory. The generator function is implemented by
+ * the application, and a pointer to the function is given
+ * as an argument with the call to PSOCK_GENERATOR_SEND().
+ *
+ * The generator function should place the generated data
+ * directly in the uip_appdata buffer, and return the
+ * length of the generated data. The generator function is
+ * called by the protosocket layer when the data first is
+ * sent, and once for every retransmission that is needed.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_GENERATOR_SEND(psock, generator, arg) \
+ PT_WAIT_THREAD(&((psock)->pt), \
+ psock_generator_send(psock, generator, arg))
+
+
+/**
+ * Close a protosocket.
+ *
+ * This macro closes a protosocket and can only be called from within the
+ * protothread in which the protosocket lives.
+ *
+ * \param psock (struct psock *) A pointer to the protosocket that is to
+ * be closed.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_CLOSE(psock) uip_close()
+
+PT_THREAD(psock_readbuf(struct psock *psock));
+/**
+ * Read data until the buffer is full.
+ *
+ * This macro will block waiting for data and read the data into the
+ * input buffer specified with the call to PSOCK_INIT(). Data is read
+ * until the buffer is full..
+ *
+ * \param psock (struct psock *) A pointer to the protosocket from which
+ * data should be read.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_READBUF(psock) \
+ PT_WAIT_THREAD(&((psock)->pt), psock_readbuf(psock))
+
+PT_THREAD(psock_readto(struct psock *psock, unsigned char c));
+/**
+ * Read data up to a specified character.
+ *
+ * This macro will block waiting for data and read the data into the
+ * input buffer specified with the call to PSOCK_INIT(). Data is only
+ * read until the specifieed character appears in the data stream.
+ *
+ * \param psock (struct psock *) A pointer to the protosocket from which
+ * data should be read.
+ *
+ * \param c (char) The character at which to stop reading.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_READTO(psock, c) \
+ PT_WAIT_THREAD(&((psock)->pt), psock_readto(psock, c))
+
+/**
+ * The length of the data that was previously read.
+ *
+ * This macro returns the length of the data that was previously read
+ * using PSOCK_READTO() or PSOCK_READ().
+ *
+ * \param psock (struct psock *) A pointer to the protosocket holding the data.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_DATALEN(psock) psock_datalen(psock)
+
+u16_t psock_datalen(struct psock *psock);
+
+/**
+ * Exit the protosocket's protothread.
+ *
+ * This macro terminates the protothread of the protosocket and should
+ * almost always be used in conjunction with PSOCK_CLOSE().
+ *
+ * \sa PSOCK_CLOSE_EXIT()
+ *
+ * \param psock (struct psock *) A pointer to the protosocket.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_EXIT(psock) PT_EXIT(&((psock)->pt))
+
+/**
+ * Close a protosocket and exit the protosocket's protothread.
+ *
+ * This macro closes a protosocket and exits the protosocket's protothread.
+ *
+ * \param psock (struct psock *) A pointer to the protosocket.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_CLOSE_EXIT(psock) \
+ do { \
+ PSOCK_CLOSE(psock); \
+ PSOCK_EXIT(psock); \
+ } while(0)
+
+/**
+ * Declare the end of a protosocket's protothread.
+ *
+ * This macro is used for declaring that the protosocket's protothread
+ * ends. It must always be used together with a matching PSOCK_BEGIN()
+ * macro.
+ *
+ * \param psock (struct psock *) A pointer to the protosocket.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_END(psock) PT_END(&((psock)->pt))
+
+char psock_newdata(struct psock *s);
+
+/**
+ * Check if new data has arrived on a protosocket.
+ *
+ * This macro is used in conjunction with the PSOCK_WAIT_UNTIL()
+ * macro to check if data has arrived on a protosocket.
+ *
+ * \param psock (struct psock *) A pointer to the protosocket.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_NEWDATA(psock) psock_newdata(psock)
+
+/**
+ * Wait until a condition is true.
+ *
+ * This macro blocks the protothread until the specified condition is
+ * true. The macro PSOCK_NEWDATA() can be used to check if new data
+ * arrives when the protosocket is waiting.
+ *
+ * Typically, this macro is used as follows:
+ *
+ \code
+ PT_THREAD(thread(struct psock *s, struct timer *t))
+ {
+ PSOCK_BEGIN(s);
+
+ PSOCK_WAIT_UNTIL(s, PSOCK_NEWADATA(s) || timer_expired(t));
+
+ if(PSOCK_NEWDATA(s)) {
+ PSOCK_READTO(s, '\n');
+ } else {
+ handle_timed_out(s);
+ }
+
+ PSOCK_END(s);
+ }
+ \endcode
+ *
+ * \param psock (struct psock *) A pointer to the protosocket.
+ * \param condition The condition to wait for.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_WAIT_UNTIL(psock, condition) \
+ PT_WAIT_UNTIL(&((psock)->pt), (condition));
+
+#define PSOCK_WAIT_THREAD(psock, condition) \
+ PT_WAIT_THREAD(&((psock)->pt), (condition))
+
+#endif /* __PSOCK_H__ */
+
+/** @} */
diff --git a/uip/uip/pt.h b/uip/uip/pt.h
new file mode 100644
index 0000000..9f1f64d
--- /dev/null
+++ b/uip/uip/pt.h
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: pt.h,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+
+/**
+ * \addtogroup pt
+ * @{
+ */
+
+/**
+ * \file
+ * Protothreads implementation.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef __PT_H__
+#define __PT_H__
+
+#include "lc.h"
+
+struct pt {
+ lc_t lc;
+};
+
+#define PT_WAITING 0
+#define PT_EXITED 1
+#define PT_ENDED 2
+#define PT_YIELDED 3
+
+/**
+ * \name Initialization
+ * @{
+ */
+
+/**
+ * Initialize a protothread.
+ *
+ * Initializes a protothread. Initialization must be done prior to
+ * starting to execute the protothread.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \sa PT_SPAWN()
+ *
+ * \hideinitializer
+ */
+#define PT_INIT(pt) LC_INIT((pt)->lc)
+
+/** @} */
+
+/**
+ * \name Declaration and definition
+ * @{
+ */
+
+/**
+ * Declaration of a protothread.
+ *
+ * This macro is used to declare a protothread. All protothreads must
+ * be declared with this macro.
+ *
+ * \param name_args The name and arguments of the C function
+ * implementing the protothread.
+ *
+ * \hideinitializer
+ */
+#define PT_THREAD(name_args) char name_args
+
+/**
+ * Declare the start of a protothread inside the C function
+ * implementing the protothread.
+ *
+ * This macro is used to declare the starting point of a
+ * protothread. It should be placed at the start of the function in
+ * which the protothread runs. All C statements above the PT_BEGIN()
+ * invokation will be executed each time the protothread is scheduled.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)
+
+/**
+ * Declare the end of a protothread.
+ *
+ * This macro is used for declaring that a protothread ends. It must
+ * always be used together with a matching PT_BEGIN() macro.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
+ PT_INIT(pt); return PT_ENDED; }
+
+/** @} */
+
+/**
+ * \name Blocked wait
+ * @{
+ */
+
+/**
+ * Block and wait until condition is true.
+ *
+ * This macro blocks the protothread until the specified condition is
+ * true.
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param condition The condition.
+ *
+ * \hideinitializer
+ */
+#define PT_WAIT_UNTIL(pt, condition) \
+ do { \
+ LC_SET((pt)->lc); \
+ if(!(condition)) { \
+ return PT_WAITING; \
+ } \
+ } while(0)
+
+/**
+ * Block and wait while condition is true.
+ *
+ * This function blocks and waits while condition is true. See
+ * PT_WAIT_UNTIL().
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param cond The condition.
+ *
+ * \hideinitializer
+ */
+#define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond))
+
+/** @} */
+
+/**
+ * \name Hierarchical protothreads
+ * @{
+ */
+
+/**
+ * Block and wait until a child protothread completes.
+ *
+ * This macro schedules a child protothread. The current protothread
+ * will block until the child protothread completes.
+ *
+ * \note The child protothread must be manually initialized with the
+ * PT_INIT() function before this function is used.
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param thread The child protothread with arguments
+ *
+ * \sa PT_SPAWN()
+ *
+ * \hideinitializer
+ */
+#define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))
+
+/**
+ * Spawn a child protothread and wait until it exits.
+ *
+ * This macro spawns a child protothread and waits until it exits. The
+ * macro can only be used within a protothread.
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param child A pointer to the child protothread's control structure.
+ * \param thread The child protothread with arguments
+ *
+ * \hideinitializer
+ */
+#define PT_SPAWN(pt, child, thread) \
+ do { \
+ PT_INIT((child)); \
+ PT_WAIT_THREAD((pt), (thread)); \
+ } while(0)
+
+/** @} */
+
+/**
+ * \name Exiting and restarting
+ * @{
+ */
+
+/**
+ * Restart the protothread.
+ *
+ * This macro will block and cause the running protothread to restart
+ * its execution at the place of the PT_BEGIN() call.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_RESTART(pt) \
+ do { \
+ PT_INIT(pt); \
+ return PT_WAITING; \
+ } while(0)
+
+/**
+ * Exit the protothread.
+ *
+ * This macro causes the protothread to exit. If the protothread was
+ * spawned by another protothread, the parent protothread will become
+ * unblocked and can continue to run.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_EXIT(pt) \
+ do { \
+ PT_INIT(pt); \
+ return PT_EXITED; \
+ } while(0)
+
+/** @} */
+
+/**
+ * \name Calling a protothread
+ * @{
+ */
+
+/**
+ * Schedule a protothread.
+ *
+ * This function shedules a protothread. The return value of the
+ * function is non-zero if the protothread is running or zero if the
+ * protothread has exited.
+ *
+ * \param f The call to the C function implementing the protothread to
+ * be scheduled
+ *
+ * \hideinitializer
+ */
+#define PT_SCHEDULE(f) ((f) == PT_WAITING)
+
+/** @} */
+
+/**
+ * \name Yielding from a protothread
+ * @{
+ */
+
+/**
+ * Yield from the current protothread.
+ *
+ * This function will yield the protothread, thereby allowing other
+ * processing to take place in the system.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_YIELD(pt) \
+ do { \
+ PT_YIELD_FLAG = 0; \
+ LC_SET((pt)->lc); \
+ if(PT_YIELD_FLAG == 0) { \
+ return PT_YIELDED; \
+ } \
+ } while(0)
+
+/**
+ * \brief Yield from the protothread until a condition occurs.
+ * \param pt A pointer to the protothread control structure.
+ * \param cond The condition.
+ *
+ * This function will yield the protothread, until the
+ * specified condition evaluates to true.
+ *
+ *
+ * \hideinitializer
+ */
+#define PT_YIELD_UNTIL(pt, cond) \
+ do { \
+ PT_YIELD_FLAG = 0; \
+ LC_SET((pt)->lc); \
+ if((PT_YIELD_FLAG == 0) || !(cond)) { \
+ return PT_YIELDED; \
+ } \
+ } while(0)
+
+/** @} */
+
+#endif /* __PT_H__ */
+
+/** @} */
diff --git a/uip/uip/timer.c b/uip/uip/timer.c
new file mode 100644
index 0000000..74eedf6
--- /dev/null
+++ b/uip/uip/timer.c
@@ -0,0 +1,127 @@
+/**
+ * \addtogroup timer
+ * @{
+ */
+
+/**
+ * \file
+ * Timer library implementation.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ */
+
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: timer.c,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+
+#include "clock.h"
+#include "timer.h"
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Set a timer.
+ *
+ * This function is used to set a timer for a time sometime in the
+ * future. The function timer_expired() will evaluate to true after
+ * the timer has expired.
+ *
+ * \param t A pointer to the timer
+ * \param interval The interval before the timer expires.
+ *
+ */
+void
+timer_set(struct timer *t, clock_time_t interval)
+{
+ t->interval = interval;
+ t->start = clock_time();
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Reset the timer with the same interval.
+ *
+ * This function resets the timer with the same interval that was
+ * given to the timer_set() function. The start point of the interval
+ * is the exact time that the timer last expired. Therefore, this
+ * function will cause the timer to be stable over time, unlike the
+ * timer_rester() function.
+ *
+ * \param t A pointer to the timer.
+ *
+ * \sa timer_restart()
+ */
+void
+timer_reset(struct timer *t)
+{
+ t->start += t->interval;
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Restart the timer from the current point in time
+ *
+ * This function restarts a timer with the same interval that was
+ * given to the timer_set() function. The timer will start at the
+ * current time.
+ *
+ * \note A periodic timer will drift if this function is used to reset
+ * it. For preioric timers, use the timer_reset() function instead.
+ *
+ * \param t A pointer to the timer.
+ *
+ * \sa timer_reset()
+ */
+void
+timer_restart(struct timer *t)
+{
+ t->start = clock_time();
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Check if a timer has expired.
+ *
+ * This function tests if a timer has expired and returns true or
+ * false depending on its status.
+ *
+ * \param t A pointer to the timer
+ *
+ * \return Non-zero if the timer has expired, zero otherwise.
+ *
+ */
+int
+timer_expired(struct timer *t)
+{
+ return (clock_time_t)(clock_time() - t->start) >= (clock_time_t)t->interval;
+}
+/*---------------------------------------------------------------------------*/
+
+/** @} */
diff --git a/uip/uip/timer.h b/uip/uip/timer.h
new file mode 100644
index 0000000..057bea4
--- /dev/null
+++ b/uip/uip/timer.h
@@ -0,0 +1,86 @@
+/**
+ * \defgroup timer Timer library
+ *
+ * The timer library provides functions for setting, resetting and
+ * restarting timers, and for checking if a timer has expired. An
+ * application must "manually" check if its timers have expired; this
+ * is not done automatically.
+ *
+ * A timer is declared as a \c struct \c timer and all access to the
+ * timer is made by a pointer to the declared timer.
+ *
+ * \note The timer library uses the \ref clock "Clock library" to
+ * measure time. Intervals should be specified in the format used by
+ * the clock library.
+ *
+ * @{
+ */
+
+
+/**
+ * \file
+ * Timer library header file.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ */
+
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: timer.h,v 1.3 2006/06/11 21:46:39 adam Exp $
+ */
+#ifndef __TIMER_H__
+#define __TIMER_H__
+
+#include "clock.h"
+
+/**
+ * A timer.
+ *
+ * This structure is used for declaring a timer. The timer must be set
+ * with timer_set() before it can be used.
+ *
+ * \hideinitializer
+ */
+struct timer {
+ clock_time_t start;
+ clock_time_t interval;
+};
+
+void timer_set(struct timer *t, clock_time_t interval);
+void timer_reset(struct timer *t);
+void timer_restart(struct timer *t);
+int timer_expired(struct timer *t);
+
+#endif /* __TIMER_H__ */
+
+/** @} */
diff --git a/uip/uip/uip-fw.c b/uip/uip/uip-fw.c
new file mode 100644
index 0000000..01858ea
--- /dev/null
+++ b/uip/uip/uip-fw.c
@@ -0,0 +1,532 @@
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: uip-fw.c,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+/**
+ * \addtogroup uip
+ * @{
+ */
+
+/**
+ * \defgroup uipfw uIP packet forwarding
+ * @{
+ *
+ */
+
+/**
+ * \file
+ * uIP packet forwarding.
+ * \author Adam Dunkels <adam@sics.se>
+ *
+ * This file implements a number of simple functions which do packet
+ * forwarding over multiple network interfaces with uIP.
+ *
+ */
+
+#include "uip.h"
+#include "uip_arch.h"
+#include "uip-fw.h"
+
+#include <string.h> /* for memcpy() */
+
+/*
+ * The list of registered network interfaces.
+ */
+static struct uip_fw_netif *netifs = NULL;
+
+/*
+ * A pointer to the default network interface.
+ */
+static struct uip_fw_netif *defaultnetif = NULL;
+
+struct tcpip_hdr {
+ /* IP header. */
+ u8_t vhl,
+ tos;
+ u16_t len,
+ ipid,
+ ipoffset;
+ u8_t ttl,
+ proto;
+ u16_t ipchksum;
+ u16_t srcipaddr[2],
+ destipaddr[2];
+
+ /* TCP header. */
+ u16_t srcport,
+ destport;
+ u8_t seqno[4],
+ ackno[4],
+ tcpoffset,
+ flags,
+ wnd[2];
+ u16_t tcpchksum;
+ u8_t urgp[2];
+ u8_t optdata[4];
+};
+
+struct icmpip_hdr {
+ /* IP header. */
+ u8_t vhl,
+ tos,
+ len[2],
+ ipid[2],
+ ipoffset[2],
+ ttl,
+ proto;
+ u16_t ipchksum;
+ u16_t srcipaddr[2],
+ destipaddr[2];
+ /* ICMP (echo) header. */
+ u8_t type, icode;
+ u16_t icmpchksum;
+ u16_t id, seqno;
+ u8_t payload[1];
+};
+
+/* ICMP ECHO. */
+#define ICMP_ECHO 8
+
+/* ICMP TIME-EXCEEDED. */
+#define ICMP_TE 11
+
+/*
+ * Pointer to the TCP/IP headers of the packet in the uip_buf buffer.
+ */
+#define BUF ((struct tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
+
+/*
+ * Pointer to the ICMP/IP headers of the packet in the uip_buf buffer.
+ */
+#define ICMPBUF ((struct icmpip_hdr *)&uip_buf[UIP_LLH_LEN])
+
+/*
+ * Certain fields of an IP packet that are used for identifying
+ * duplicate packets.
+ */
+struct fwcache_entry {
+ u16_t timer;
+
+ u16_t srcipaddr[2];
+ u16_t destipaddr[2];
+ u16_t ipid;
+ u8_t proto;
+ u8_t unused;
+
+#if notdef
+ u16_t payload[2];
+#endif
+
+#if UIP_REASSEMBLY > 0
+ u16_t len, offset;
+#endif
+};
+
+/*
+ * The number of packets to remember when looking for duplicates.
+ */
+#ifdef UIP_CONF_FWCACHE_SIZE
+#define FWCACHE_SIZE UIP_CONF_FWCACHE_SIZE
+#else
+#define FWCACHE_SIZE 2
+#endif
+
+
+/*
+ * A cache of packet header fields which are used for
+ * identifying duplicate packets.
+ */
+static struct fwcache_entry fwcache[FWCACHE_SIZE];
+
+/**
+ * \internal
+ * The time that a packet cache is active.
+ */
+#define FW_TIME 20
+
+/*------------------------------------------------------------------------------*/
+/**
+ * Initialize the uIP packet forwarding module.
+ */
+/*------------------------------------------------------------------------------*/
+void
+uip_fw_init(void)
+{
+ struct uip_fw_netif *t;
+ defaultnetif = NULL;
+ while(netifs != NULL) {
+ t = netifs;
+ netifs = netifs->next;
+ t->next = NULL;
+ }
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * \internal
+ * Check if an IP address is within the network defined by an IP
+ * address and a netmask.
+ *
+ * \param ipaddr The IP address to be checked.
+ * \param netipaddr The IP address of the network.
+ * \param netmask The netmask of the network.
+ *
+ * \return Non-zero if IP address is in network, zero otherwise.
+ */
+/*------------------------------------------------------------------------------*/
+static unsigned char
+ipaddr_maskcmp(u16_t *ipaddr, u16_t *netipaddr, u16_t *netmask)
+{
+ return (ipaddr[0] & netmask [0]) == (netipaddr[0] & netmask[0]) &&
+ (ipaddr[1] & netmask[1]) == (netipaddr[1] & netmask[1]);
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * \internal
+ * Send out an ICMP TIME-EXCEEDED message.
+ *
+ * This function replaces the packet in the uip_buf buffer with the
+ * ICMP packet.
+ */
+/*------------------------------------------------------------------------------*/
+static void
+time_exceeded(void)
+{
+ u16_t tmp16;
+
+ /* We don't send out ICMP errors for ICMP messages. */
+ if(ICMPBUF->proto == UIP_PROTO_ICMP) {
+ uip_len = 0;
+ return;
+ }
+ /* Copy fields from packet header into payload of this ICMP packet. */
+ memcpy(&(ICMPBUF->payload[0]), ICMPBUF, 28);
+
+ /* Set the ICMP type and code. */
+ ICMPBUF->type = ICMP_TE;
+ ICMPBUF->icode = 0;
+
+ /* Calculate the ICMP checksum. */
+ ICMPBUF->icmpchksum = 0;
+ ICMPBUF->icmpchksum = ~uip_chksum((u16_t *)&(ICMPBUF->type), 36);
+
+ /* Set the IP destination address to be the source address of the
+ original packet. */
+ tmp16= BUF->destipaddr[0];
+ BUF->destipaddr[0] = BUF->srcipaddr[0];
+ BUF->srcipaddr[0] = tmp16;
+ tmp16 = BUF->destipaddr[1];
+ BUF->destipaddr[1] = BUF->srcipaddr[1];
+ BUF->srcipaddr[1] = tmp16;
+
+ /* Set our IP address as the source address. */
+ BUF->srcipaddr[0] = uip_hostaddr[0];
+ BUF->srcipaddr[1] = uip_hostaddr[1];
+
+ /* The size of the ICMP time exceeded packet is 36 + the size of the
+ IP header (20) = 56. */
+ uip_len = 56;
+ ICMPBUF->len[0] = 0;
+ ICMPBUF->len[1] = uip_len;
+
+ /* Fill in the other fields in the IP header. */
+ ICMPBUF->vhl = 0x45;
+ ICMPBUF->tos = 0;
+ ICMPBUF->ipoffset[0] = ICMPBUF->ipoffset[1] = 0;
+ ICMPBUF->ttl = UIP_TTL;
+ ICMPBUF->proto = UIP_PROTO_ICMP;
+
+ /* Calculate IP checksum. */
+ ICMPBUF->ipchksum = 0;
+ ICMPBUF->ipchksum = ~(uip_ipchksum());
+
+
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * \internal
+ * Register a packet in the forwarding cache so that it won't be
+ * forwarded again.
+ */
+/*------------------------------------------------------------------------------*/
+static void
+fwcache_register(void)
+{
+ struct fwcache_entry *fw;
+ int i, oldest;
+
+ oldest = FW_TIME;
+ fw = NULL;
+
+ /* Find the oldest entry in the cache. */
+ for(i = 0; i < FWCACHE_SIZE; ++i) {
+ if(fwcache[i].timer == 0) {
+ fw = &fwcache[i];
+ break;
+ } else if(fwcache[i].timer <= oldest) {
+ fw = &fwcache[i];
+ oldest = fwcache[i].timer;
+ }
+ }
+
+ fw->timer = FW_TIME;
+ fw->ipid = BUF->ipid;
+ fw->srcipaddr[0] = BUF->srcipaddr[0];
+ fw->srcipaddr[1] = BUF->srcipaddr[1];
+ fw->destipaddr[0] = BUF->destipaddr[0];
+ fw->destipaddr[1] = BUF->destipaddr[1];
+ fw->proto = BUF->proto;
+#if notdef
+ fw->payload[0] = BUF->srcport;
+ fw->payload[1] = BUF->destport;
+#endif
+#if UIP_REASSEMBLY > 0
+ fw->len = BUF->len;
+ fw->offset = BUF->ipoffset;
+#endif
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * \internal
+ * Find a network interface for the IP packet in uip_buf.
+ */
+/*------------------------------------------------------------------------------*/
+static struct uip_fw_netif *
+find_netif(void)
+{
+ struct uip_fw_netif *netif;
+
+ /* Walk through every network interface to check for a match. */
+ for(netif = netifs; netif != NULL; netif = netif->next) {
+ if(ipaddr_maskcmp(BUF->destipaddr, netif->ipaddr,
+ netif->netmask)) {
+ /* If there was a match, we break the loop. */
+ return netif;
+ }
+ }
+
+ /* If no matching netif was found, we use default netif. */
+ return defaultnetif;
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * Output an IP packet on the correct network interface.
+ *
+ * The IP packet should be present in the uip_buf buffer and its
+ * length in the global uip_len variable.
+ *
+ * \retval UIP_FW_ZEROLEN Indicates that a zero-length packet
+ * transmission was attempted and that no packet was sent.
+ *
+ * \retval UIP_FW_NOROUTE No suitable network interface could be found
+ * for the outbound packet, and the packet was not sent.
+ *
+ * \return The return value from the actual network interface output
+ * function is passed unmodified as a return value.
+ */
+/*------------------------------------------------------------------------------*/
+u8_t
+uip_fw_output(void)
+{
+ struct uip_fw_netif *netif;
+
+ if(uip_len == 0) {
+ return UIP_FW_ZEROLEN;
+ }
+
+ fwcache_register();
+
+#if UIP_BROADCAST
+ /* Link local broadcasts go out on all interfaces. */
+ if(/*BUF->proto == UIP_PROTO_UDP &&*/
+ BUF->destipaddr[0] == 0xffff &&
+ BUF->destipaddr[1] == 0xffff) {
+ if(defaultnetif != NULL) {
+ defaultnetif->output();
+ }
+ for(netif = netifs; netif != NULL; netif = netif->next) {
+ netif->output();
+ }
+ return UIP_FW_OK;
+ }
+#endif /* UIP_BROADCAST */
+
+ netif = find_netif();
+ /* printf("uip_fw_output: netif %p ->output %p len %d\n", netif,
+ netif->output,
+ uip_len);*/
+
+ if(netif == NULL) {
+ return UIP_FW_NOROUTE;
+ }
+ /* If we now have found a suitable network interface, we call its
+ output function to send out the packet. */
+ return netif->output();
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * Forward an IP packet in the uip_buf buffer.
+ *
+ *
+ *
+ * \return UIP_FW_FORWARDED if the packet was forwarded, UIP_FW_LOCAL if
+ * the packet should be processed locally.
+ */
+/*------------------------------------------------------------------------------*/
+u8_t
+uip_fw_forward(void)
+{
+ struct fwcache_entry *fw;
+
+ /* First check if the packet is destined for ourselves and return 0
+ to indicate that the packet should be processed locally. */
+ if(BUF->destipaddr[0] == uip_hostaddr[0] &&
+ BUF->destipaddr[1] == uip_hostaddr[1]) {
+ return UIP_FW_LOCAL;
+ }
+
+ /* If we use ping IP address configuration, and our IP address is
+ not yet configured, we should intercept all ICMP echo packets. */
+#if UIP_PINGADDRCONF
+ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0 &&
+ BUF->proto == UIP_PROTO_ICMP &&
+ ICMPBUF->type == ICMP_ECHO) {
+ return UIP_FW_LOCAL;
+ }
+#endif /* UIP_PINGADDRCONF */
+
+ /* Check if the packet is in the forwarding cache already, and if so
+ we drop it. */
+
+ for(fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) {
+ if(fw->timer != 0 &&
+#if UIP_REASSEMBLY > 0
+ fw->len == BUF->len &&
+ fw->offset == BUF->ipoffset &&
+#endif
+ fw->ipid == BUF->ipid &&
+ fw->srcipaddr[0] == BUF->srcipaddr[0] &&
+ fw->srcipaddr[1] == BUF->srcipaddr[1] &&
+ fw->destipaddr[0] == BUF->destipaddr[0] &&
+ fw->destipaddr[1] == BUF->destipaddr[1] &&
+#if notdef
+ fw->payload[0] == BUF->srcport &&
+ fw->payload[1] == BUF->destport &&
+#endif
+ fw->proto == BUF->proto) {
+ /* Drop packet. */
+ return UIP_FW_FORWARDED;
+ }
+ }
+
+ /* If the TTL reaches zero we produce an ICMP time exceeded message
+ in the uip_buf buffer and forward that packet back to the sender
+ of the packet. */
+ if(BUF->ttl <= 1) {
+ /* No time exceeded for broadcasts and multicasts! */
+ if(BUF->destipaddr[0] == 0xffff && BUF->destipaddr[1] == 0xffff) {
+ return UIP_FW_LOCAL;
+ }
+ time_exceeded();
+ }
+
+ /* Decrement the TTL (time-to-live) value in the IP header */
+ BUF->ttl = BUF->ttl - 1;
+
+ /* Update the IP checksum. */
+ if(BUF->ipchksum >= HTONS(0xffff - 0x0100)) {
+ BUF->ipchksum = BUF->ipchksum + HTONS(0x0100) + 1;
+ } else {
+ BUF->ipchksum = BUF->ipchksum + HTONS(0x0100);
+ }
+
+ if(uip_len > 0) {
+ uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN];
+ uip_fw_output();
+ }
+
+#if UIP_BROADCAST
+ if(BUF->destipaddr[0] == 0xffff && BUF->destipaddr[1] == 0xffff) {
+ return UIP_FW_LOCAL;
+ }
+#endif /* UIP_BROADCAST */
+
+ /* Return non-zero to indicate that the packet was forwarded and that no
+ other processing should be made. */
+ return UIP_FW_FORWARDED;
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * Register a network interface with the forwarding module.
+ *
+ * \param netif A pointer to the network interface that is to be
+ * registered.
+ */
+/*------------------------------------------------------------------------------*/
+void
+uip_fw_register(struct uip_fw_netif *netif)
+{
+ netif->next = netifs;
+ netifs = netif;
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * Register a default network interface.
+ *
+ * All packets that don't go out on any of the other interfaces will
+ * be routed to the default interface.
+ *
+ * \param netif A pointer to the network interface that is to be
+ * registered.
+ */
+/*------------------------------------------------------------------------------*/
+void
+uip_fw_default(struct uip_fw_netif *netif)
+{
+ defaultnetif = netif;
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * Perform periodic processing.
+ */
+/*------------------------------------------------------------------------------*/
+void
+uip_fw_periodic(void)
+{
+ struct fwcache_entry *fw;
+ for(fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) {
+ if(fw->timer > 0) {
+ --fw->timer;
+ }
+ }
+}
+/*------------------------------------------------------------------------------*/
diff --git a/uip/uip/uip-fw.h b/uip/uip/uip-fw.h
new file mode 100644
index 0000000..9033850
--- /dev/null
+++ b/uip/uip/uip-fw.h
@@ -0,0 +1,176 @@
+/**
+ * \addtogroup uipfw
+ * @{
+ */
+
+/**
+ * \file
+ * uIP packet forwarding header file.
+ * \author Adam Dunkels <adam@sics.se>
+ */
+
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: uip-fw.h,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+#ifndef __UIP_FW_H__
+#define __UIP_FW_H__
+
+#include "uip.h"
+
+/**
+ * Representation of a uIP network interface.
+ */
+struct uip_fw_netif {
+ struct uip_fw_netif *next; /**< Pointer to the next interface when
+ linked in a list. */
+ u16_t ipaddr[2]; /**< The IP address of this interface. */
+ u16_t netmask[2]; /**< The netmask of the interface. */
+ u8_t (* output)(void);
+ /**< A pointer to the function that
+ sends a packet. */
+};
+
+/**
+ * Intantiating macro for a uIP network interface.
+ *
+ * Example:
+ \code
+ struct uip_fw_netif slipnetif =
+ {UIP_FW_NETIF(192,168,76,1, 255,255,255,0, slip_output)};
+ \endcode
+ * \param ip1,ip2,ip3,ip4 The IP address of the network interface.
+ *
+ * \param nm1,nm2,nm3,nm4 The netmask of the network interface.
+ *
+ * \param outputfunc A pointer to the output function of the network interface.
+ *
+ * \hideinitializer
+ */
+#define UIP_FW_NETIF(ip1,ip2,ip3,ip4, nm1,nm2,nm3,nm4, outputfunc) \
+ NULL, \
+ {HTONS((ip1 << 8) | ip2), HTONS((ip3 << 8) | ip4)}, \
+ {HTONS((nm1 << 8) | nm2), HTONS((nm3 << 8) | nm4)}, \
+ outputfunc
+
+/**
+ * Set the IP address of a network interface.
+ *
+ * \param netif A pointer to the uip_fw_netif structure for the network interface.
+ *
+ * \param addr A pointer to an IP address.
+ *
+ * \hideinitializer
+ */
+#define uip_fw_setipaddr(netif, addr) \
+ do { (netif)->ipaddr[0] = ((u16_t *)(addr))[0]; \
+ (netif)->ipaddr[1] = ((u16_t *)(addr))[1]; } while(0)
+/**
+ * Set the netmask of a network interface.
+ *
+ * \param netif A pointer to the uip_fw_netif structure for the network interface.
+ *
+ * \param addr A pointer to an IP address representing the netmask.
+ *
+ * \hideinitializer
+ */
+#define uip_fw_setnetmask(netif, addr) \
+ do { (netif)->netmask[0] = ((u16_t *)(addr))[0]; \
+ (netif)->netmask[1] = ((u16_t *)(addr))[1]; } while(0)
+
+void uip_fw_init(void);
+u8_t uip_fw_forward(void);
+u8_t uip_fw_output(void);
+void uip_fw_register(struct uip_fw_netif *netif);
+void uip_fw_default(struct uip_fw_netif *netif);
+void uip_fw_periodic(void);
+
+
+/**
+ * A non-error message that indicates that a packet should be
+ * processed locally.
+ *
+ * \hideinitializer
+ */
+#define UIP_FW_LOCAL 0
+
+/**
+ * A non-error message that indicates that something went OK.
+ *
+ * \hideinitializer
+ */
+#define UIP_FW_OK 0
+
+/**
+ * A non-error message that indicates that a packet was forwarded.
+ *
+ * \hideinitializer
+ */
+#define UIP_FW_FORWARDED 1
+
+/**
+ * A non-error message that indicates that a zero-length packet
+ * transmission was attempted, and that no packet was sent.
+ *
+ * \hideinitializer
+ */
+#define UIP_FW_ZEROLEN 2
+
+/**
+ * An error message that indicates that a packet that was too large
+ * for the outbound network interface was detected.
+ *
+ * \hideinitializer
+ */
+#define UIP_FW_TOOLARGE 3
+
+/**
+ * An error message that indicates that no suitable interface could be
+ * found for an outbound packet.
+ *
+ * \hideinitializer
+ */
+#define UIP_FW_NOROUTE 4
+
+/**
+ * An error message that indicates that a packet that should be
+ * forwarded or output was dropped.
+ *
+ * \hideinitializer
+ */
+#define UIP_FW_DROPPED 5
+
+
+#endif /* __UIP_FW_H__ */
+
+/** @} */
diff --git a/uip/uip/uip-neighbor.c b/uip/uip/uip-neighbor.c
new file mode 100644
index 0000000..18a2502
--- /dev/null
+++ b/uip/uip/uip-neighbor.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2006, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: uip-neighbor.c,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+
+/**
+ * \file
+ * Database of link-local neighbors, used by IPv6 code and
+ * to be used by a future ARP code rewrite.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ */
+
+#include "uip-neighbor.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#define MAX_TIME 128
+
+#ifdef UIP_NEIGHBOR_CONF_ENTRIES
+#define ENTRIES UIP_NEIGHBOR_CONF_ENTRIES
+#else /* UIP_NEIGHBOR_CONF_ENTRIES */
+#define ENTRIES 8
+#endif /* UIP_NEIGHBOR_CONF_ENTRIES */
+
+struct neighbor_entry {
+ uip_ipaddr_t ipaddr;
+ struct uip_neighbor_addr addr;
+ u8_t time;
+};
+static struct neighbor_entry entries[ENTRIES];
+
+/*---------------------------------------------------------------------------*/
+void
+uip_neighbor_init(void)
+{
+ int i;
+
+ for(i = 0; i < ENTRIES; ++i) {
+ entries[i].time = MAX_TIME;
+ }
+}
+/*---------------------------------------------------------------------------*/
+void
+uip_neighbor_periodic(void)
+{
+ int i;
+
+ for(i = 0; i < ENTRIES; ++i) {
+ if(entries[i].time < MAX_TIME) {
+ entries[i].time++;
+ }
+ }
+}
+/*---------------------------------------------------------------------------*/
+void
+uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr)
+{
+ int i, oldest;
+ u8_t oldest_time;
+
+ printf("Adding neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n",
+ addr->addr.addr[0], addr->addr.addr[1], addr->addr.addr[2], addr->addr.addr[3],
+ addr->addr.addr[4], addr->addr.addr[5]);
+
+ /* Find the first unused entry or the oldest used entry. */
+ oldest_time = 0;
+ oldest = 0;
+ for(i = 0; i < ENTRIES; ++i) {
+ if(entries[i].time == MAX_TIME) {
+ oldest = i;
+ break;
+ }
+ if(uip_ipaddr_cmp(entries[i].ipaddr, addr)) {
+ oldest = i;
+ break;
+ }
+ if(entries[i].time > oldest_time) {
+ oldest = i;
+ oldest_time = entries[i].time;
+ }
+ }
+
+ /* Use the oldest or first free entry (either pointed to by the
+ "oldest" variable). */
+ entries[oldest].time = 0;
+ uip_ipaddr_copy(entries[oldest].ipaddr, ipaddr);
+ memcpy(&entries[oldest].addr, addr, sizeof(struct uip_neighbor_addr));
+}
+/*---------------------------------------------------------------------------*/
+static struct neighbor_entry *
+find_entry(uip_ipaddr_t ipaddr)
+{
+ int i;
+
+ for(i = 0; i < ENTRIES; ++i) {
+ if(uip_ipaddr_cmp(entries[i].ipaddr, ipaddr)) {
+ return &entries[i];
+ }
+ }
+ return NULL;
+}
+/*---------------------------------------------------------------------------*/
+void
+uip_neighbor_update(uip_ipaddr_t ipaddr)
+{
+ struct neighbor_entry *e;
+
+ e = find_entry(ipaddr);
+ if(e != NULL) {
+ e->time = 0;
+ }
+}
+/*---------------------------------------------------------------------------*/
+struct uip_neighbor_addr *
+uip_neighbor_lookup(uip_ipaddr_t ipaddr)
+{
+ struct neighbor_entry *e;
+
+ e = find_entry(ipaddr);
+ if(e != NULL) {
+ /* printf("Lookup neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n",
+ e->addr.addr.addr[0], e->addr.addr.addr[1], e->addr.addr.addr[2], e->addr.addr.addr[3],
+ e->addr.addr.addr[4], e->addr.addr.addr[5]);*/
+
+ return &e->addr;
+ }
+ return NULL;
+}
+/*---------------------------------------------------------------------------*/
diff --git a/uip/uip/uip-neighbor.h b/uip/uip/uip-neighbor.h
new file mode 100644
index 0000000..d3b351c
--- /dev/null
+++ b/uip/uip/uip-neighbor.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2006, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: uip-neighbor.h,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+
+/**
+ * \file
+ * Header file for database of link-local neighbors, used by
+ * IPv6 code and to be used by future ARP code.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ */
+
+#ifndef __UIP_NEIGHBOR_H__
+#define __UIP_NEIGHBOR_H__
+
+#include "uip.h"
+
+struct uip_neighbor_addr {
+#if UIP_NEIGHBOR_CONF_ADDRTYPE
+ UIP_NEIGHBOR_CONF_ADDRTYPE addr;
+#else
+ struct uip_eth_addr addr;
+#endif
+};
+
+void uip_neighbor_init(void);
+void uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr);
+void uip_neighbor_update(uip_ipaddr_t ipaddr);
+struct uip_neighbor_addr *uip_neighbor_lookup(uip_ipaddr_t ipaddr);
+void uip_neighbor_periodic(void);
+
+#endif /* __UIP-NEIGHBOR_H__ */
diff --git a/uip/uip/uip-split.c b/uip/uip/uip-split.c
new file mode 100644
index 0000000..a910ee6
--- /dev/null
+++ b/uip/uip/uip-split.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: uip-split.c,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+
+#include <string.h>
+
+#include "uip-split.h"
+#include "uip.h"
+#include "uip-fw.h"
+#include "uip_arch.h"
+
+
+
+#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
+
+/*-----------------------------------------------------------------------------*/
+void
+uip_split_output(void)
+{
+ u16_t tcplen, len1, len2;
+
+ /* We only try to split maximum sized TCP segments. */
+ if(BUF->proto == UIP_PROTO_TCP &&
+ uip_len == UIP_BUFSIZE - UIP_LLH_LEN) {
+
+ tcplen = uip_len - UIP_TCPIP_HLEN;
+ /* Split the segment in two. If the original packet length was
+ odd, we make the second packet one byte larger. */
+ len1 = len2 = tcplen / 2;
+ if(len1 + len2 < tcplen) {
+ ++len2;
+ }
+
+ /* Create the first packet. This is done by altering the length
+ field of the IP header and updating the checksums. */
+ uip_len = len1 + UIP_TCPIP_HLEN;
+#if UIP_CONF_IPV6
+ /* For IPv6, the IP length field does not include the IPv6 IP header
+ length. */
+ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
+ BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
+#else /* UIP_CONF_IPV6 */
+ BUF->len[0] = uip_len >> 8;
+ BUF->len[1] = uip_len & 0xff;
+#endif /* UIP_CONF_IPV6 */
+
+ /* Recalculate the TCP checksum. */
+ BUF->tcpchksum = 0;
+ BUF->tcpchksum = ~(uip_tcpchksum());
+
+#if !UIP_CONF_IPV6
+ /* Recalculate the IP checksum. */
+ BUF->ipchksum = 0;
+ BUF->ipchksum = ~(uip_ipchksum());
+#endif /* UIP_CONF_IPV6 */
+
+ /* Transmit the first packet. */
+ /* uip_fw_output();*/
+ tcpip_output();
+
+ /* Now, create the second packet. To do this, it is not enough to
+ just alter the length field, but we must also update the TCP
+ sequence number and point the uip_appdata to a new place in
+ memory. This place is detemined by the length of the first
+ packet (len1). */
+ uip_len = len2 + UIP_TCPIP_HLEN;
+#if UIP_CONF_IPV6
+ /* For IPv6, the IP length field does not include the IPv6 IP header
+ length. */
+ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
+ BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
+#else /* UIP_CONF_IPV6 */
+ BUF->len[0] = uip_len >> 8;
+ BUF->len[1] = uip_len & 0xff;
+#endif /* UIP_CONF_IPV6 */
+
+ /* uip_appdata += len1;*/
+ memcpy(uip_appdata, (u8_t *)uip_appdata + len1, len2);
+
+ uip_add32(BUF->seqno, len1);
+ BUF->seqno[0] = uip_acc32[0];
+ BUF->seqno[1] = uip_acc32[1];
+ BUF->seqno[2] = uip_acc32[2];
+ BUF->seqno[3] = uip_acc32[3];
+
+ /* Recalculate the TCP checksum. */
+ BUF->tcpchksum = 0;
+ BUF->tcpchksum = ~(uip_tcpchksum());
+
+#if !UIP_CONF_IPV6
+ /* Recalculate the IP checksum. */
+ BUF->ipchksum = 0;
+ BUF->ipchksum = ~(uip_ipchksum());
+#endif /* UIP_CONF_IPV6 */
+
+ /* Transmit the second packet. */
+ /* uip_fw_output();*/
+ tcpip_output();
+ } else {
+ /* uip_fw_output();*/
+ tcpip_output();
+ }
+
+}
+/*-----------------------------------------------------------------------------*/
diff --git a/uip/uip/uip-split.h b/uip/uip/uip-split.h
new file mode 100644
index 0000000..c2c1789
--- /dev/null
+++ b/uip/uip/uip-split.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: uip-split.h,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+/**
+ * \addtogroup uip
+ * @{
+ */
+
+/**
+ * \defgroup uipsplit uIP TCP throughput booster hack
+ * @{
+ *
+ * The basic uIP TCP implementation only allows each TCP connection to
+ * have a single TCP segment in flight at any given time. Because of
+ * the delayed ACK algorithm employed by most TCP receivers, uIP's
+ * limit on the amount of in-flight TCP segments seriously reduces the
+ * maximum achievable throughput for sending data from uIP.
+ *
+ * The uip-split module is a hack which tries to remedy this
+ * situation. By splitting maximum sized outgoing TCP segments into
+ * two, the delayed ACK algorithm is not invoked at TCP
+ * receivers. This improves the throughput when sending data from uIP
+ * by orders of magnitude.
+ *
+ * The uip-split module uses the uip-fw module (uIP IP packet
+ * forwarding) for sending packets. Therefore, the uip-fw module must
+ * be set up with the appropriate network interfaces for this module
+ * to work.
+ */
+
+
+/**
+ * \file
+ * Module for splitting outbound TCP segments in two to avoid the
+ * delayed ACK throughput degradation.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef __UIP_SPLIT_H__
+#define __UIP_SPLIT_H__
+
+/**
+ * Handle outgoing packets.
+ *
+ * This function inspects an outgoing packet in the uip_buf buffer and
+ * sends it out using the uip_fw_output() function. If the packet is a
+ * full-sized TCP segment it will be split into two segments and
+ * transmitted separately. This function should be called instead of
+ * the actual device driver output function, or the uip_fw_output()
+ * function.
+ *
+ * The headers of the outgoing packet is assumed to be in the uip_buf
+ * buffer and the payload is assumed to be wherever uip_appdata
+ * points. The length of the outgoing packet is assumed to be in the
+ * uip_len variable.
+ *
+ */
+void uip_split_output(void);
+
+#endif /* __UIP_SPLIT_H__ */
+
+/** @} */
+/** @} */
diff --git a/uip/uip/uip.c b/uip/uip/uip.c
new file mode 100644
index 0000000..c5f7b93
--- /dev/null
+++ b/uip/uip/uip.c
@@ -0,0 +1,1912 @@
+#define DEBUG_PRINTF(...) /*printf(__VA_ARGS__)*/
+
+/**
+ * \defgroup uip The uIP TCP/IP stack
+ * @{
+ *
+ * uIP is an implementation of the TCP/IP protocol stack intended for
+ * small 8-bit and 16-bit microcontrollers.
+ *
+ * uIP provides the necessary protocols for Internet communication,
+ * with a very small code footprint and RAM requirements - the uIP
+ * code size is on the order of a few kilobytes and RAM usage is on
+ * the order of a few hundred bytes.
+ */
+
+/**
+ * \file
+ * The uIP TCP/IP stack code.
+ * \author Adam Dunkels <adam@dunkels.com>
+ */
+
+/*
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: uip.c,v 1.65 2006/06/11 21:46:39 adam Exp $
+ *
+ */
+
+/*
+ * uIP is a small implementation of the IP, UDP and TCP protocols (as
+ * well as some basic ICMP stuff). The implementation couples the IP,
+ * UDP, TCP and the application layers very tightly. To keep the size
+ * of the compiled code down, this code frequently uses the goto
+ * statement. While it would be possible to break the uip_process()
+ * function into many smaller functions, this would increase the code
+ * size because of the overhead of parameter passing and the fact that
+ * the optimier would not be as efficient.
+ *
+ * The principle is that we have a small buffer, called the uip_buf,
+ * in which the device driver puts an incoming packet. The TCP/IP
+ * stack parses the headers in the packet, and calls the
+ * application. If the remote host has sent data to the application,
+ * this data is present in the uip_buf and the application read the
+ * data from there. It is up to the application to put this data into
+ * a byte stream if needed. The application will not be fed with data
+ * that is out of sequence.
+ *
+ * If the application whishes to send data to the peer, it should put
+ * its data into the uip_buf. The uip_appdata pointer points to the
+ * first available byte. The TCP/IP stack will calculate the
+ * checksums, and fill in the necessary header fields and finally send
+ * the packet back to the peer.
+*/
+
+#include "uip.h"
+#include "uipopt.h"
+#include "uip_arch.h"
+
+#if UIP_CONF_IPV6
+#include "uip-neighbor.h"
+#endif /* UIP_CONF_IPV6 */
+
+#include <string.h>
+
+/*---------------------------------------------------------------------------*/
+/* Variable definitions. */
+
+
+/* The IP address of this host. If it is defined to be fixed (by
+ setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set
+ here. Otherwise, the address */
+#if UIP_FIXEDADDR > 0
+const uip_ipaddr_t uip_hostaddr =
+ {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1),
+ HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};
+const uip_ipaddr_t uip_draddr =
+ {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1),
+ HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};
+const uip_ipaddr_t uip_netmask =
+ {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),
+ HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};
+#else
+uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;
+#endif /* UIP_FIXEDADDR */
+
+static const uip_ipaddr_t all_ones_addr =
+#if UIP_CONF_IPV6
+ {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff};
+#else /* UIP_CONF_IPV6 */
+ {0xffff,0xffff};
+#endif /* UIP_CONF_IPV6 */
+static const uip_ipaddr_t all_zeroes_addr =
+#if UIP_CONF_IPV6
+ {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};
+#else /* UIP_CONF_IPV6 */
+ {0x0000,0x0000};
+#endif /* UIP_CONF_IPV6 */
+
+
+#if UIP_CONF_IPV6
+#if UIP_FIXEDETHADDR
+const struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0,
+ UIP_ETHADDR1,
+ UIP_ETHADDR2,
+ UIP_ETHADDR3,
+ UIP_ETHADDR4,
+ UIP_ETHADDR5}};
+#else
+struct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}};
+#endif
+#endif /* UIP_CONF_IPV6 */
+
+#ifndef UIP_CONF_EXTERNAL_BUFFER
+u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains
+ incoming packets. */
+#endif /* UIP_CONF_EXTERNAL_BUFFER */
+
+void *uip_appdata; /* The uip_appdata pointer points to
+ application data. */
+void *uip_sappdata; /* The uip_appdata pointer points to
+ the application data which is to
+ be sent. */
+#if UIP_URGDATA > 0
+void *uip_urgdata; /* The uip_urgdata pointer points to
+ urgent data (out-of-band data), if
+ present. */
+u16_t uip_urglen, uip_surglen;
+#endif /* UIP_URGDATA > 0 */
+
+u16_t uip_len, uip_slen;
+ /* The uip_len is either 8 or 16 bits,
+ depending on the maximum packet
+ size. */
+
+u8_t uip_flags; /* The uip_flags variable is used for
+ communication between the TCP/IP stack
+ and the application program. */
+struct uip_conn *uip_conn; /* uip_conn always points to the current
+ connection. */
+
+struct uip_conn uip_conns[UIP_CONNS];
+ /* The uip_conns array holds all TCP
+ connections. */
+
+#ifdef UIP_TCP_LISTEN
+u16_t uip_listenports[UIP_LISTENPORTS];
+ /* The uip_listenports list all currently
+ listning ports. */
+#endif
+
+#if UIP_UDP
+struct uip_udp_conn *uip_udp_conn;
+struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
+#endif /* UIP_UDP */
+
+static u16_t ipid; /* Ths ipid variable is an increasing
+ number that is used for the IP ID
+ field. */
+
+void uip_setipid(u16_t id) { ipid = id; }
+
+static u8_t iss[4]; /* The iss variable is used for the TCP
+ initial sequence number. */
+
+#if UIP_ACTIVE_OPEN
+static u16_t lastport; /* Keeps track of the last port used for
+ a new connection. */
+#endif /* UIP_ACTIVE_OPEN */
+
+/* Temporary variables. */
+u8_t uip_acc32[4];
+static u8_t c, opt;
+static u16_t tmp16;
+
+/* Structures and definitions. */
+#define TCP_FIN 0x01
+#define TCP_SYN 0x02
+#define TCP_RST 0x04
+#define TCP_PSH 0x08
+#define TCP_ACK 0x10
+#define TCP_URG 0x20
+#define TCP_CTL 0x3f
+
+#define TCP_OPT_END 0 /* End of TCP options list */
+#define TCP_OPT_NOOP 1 /* "No-operation" TCP option */
+#define TCP_OPT_MSS 2 /* Maximum segment size TCP option */
+
+#define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */
+
+#define ICMP_ECHO_REPLY 0
+#define ICMP_ECHO 8
+
+#define ICMP6_ECHO_REPLY 129
+#define ICMP6_ECHO 128
+#define ICMP6_NEIGHBOR_SOLICITATION 135
+#define ICMP6_NEIGHBOR_ADVERTISEMENT 136
+
+#define ICMP6_FLAG_S (1 << 6)
+
+#define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1
+#define ICMP6_OPTION_TARGET_LINK_ADDRESS 2
+
+
+/* Macros. */
+#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
+#define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0])
+#define ICMPBUF ((struct uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN])
+#define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
+
+
+#if UIP_STATISTICS == 1
+struct uip_stats uip_stat;
+#define UIP_STAT(s) s
+#else
+#define UIP_STAT(s)
+#endif /* UIP_STATISTICS == 1 */
+
+#if UIP_LOGGING == 1
+#include <stdio.h>
+void uip_log(char *msg);
+#define UIP_LOG(m) uip_log(m)
+#else
+#define UIP_LOG(m)
+#endif /* UIP_LOGGING == 1 */
+
+#if ! UIP_ARCH_ADD32
+void
+uip_add32(u8_t *op32, u16_t op16)
+{
+ uip_acc32[3] = op32[3] + (op16 & 0xff);
+ uip_acc32[2] = op32[2] + (op16 >> 8);
+ uip_acc32[1] = op32[1];
+ uip_acc32[0] = op32[0];
+
+ if(uip_acc32[2] < (op16 >> 8)) {
+ ++uip_acc32[1];
+ if(uip_acc32[1] == 0) {
+ ++uip_acc32[0];
+ }
+ }
+
+
+ if(uip_acc32[3] < (op16 & 0xff)) {
+ ++uip_acc32[2];
+ if(uip_acc32[2] == 0) {
+ ++uip_acc32[1];
+ if(uip_acc32[1] == 0) {
+ ++uip_acc32[0];
+ }
+ }
+ }
+}
+
+#endif /* UIP_ARCH_ADD32 */
+
+#if ! UIP_ARCH_CHKSUM
+/*---------------------------------------------------------------------------*/
+static u16_t
+chksum(u16_t sum, const u8_t *data, u16_t len)
+{
+ u16_t t;
+ const u8_t *dataptr;
+ const u8_t *last_byte;
+
+ dataptr = data;
+ last_byte = data + len - 1;
+
+ while(dataptr < last_byte) { /* At least two more bytes */
+ t = (dataptr[0] << 8) + dataptr[1];
+ sum += t;
+ if(sum < t) {
+ sum++; /* carry */
+ }
+ dataptr += 2;
+ }
+
+ if(dataptr == last_byte) {
+ t = (dataptr[0] << 8) + 0;
+ sum += t;
+ if(sum < t) {
+ sum++; /* carry */
+ }
+ }
+
+ /* Return sum in host byte order. */
+ return sum;
+}
+/*---------------------------------------------------------------------------*/
+u16_t
+uip_chksum(u16_t *data, u16_t len)
+{
+ return htons(chksum(0, (u8_t *)data, len));
+}
+/*---------------------------------------------------------------------------*/
+#ifndef UIP_ARCH_IPCHKSUM
+u16_t
+uip_ipchksum(void)
+{
+ u16_t sum;
+
+ sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN);
+ DEBUG_PRINTF("uip_ipchksum: sum 0x%04x\n", sum);
+ return (sum == 0) ? 0xffff : htons(sum);
+}
+#endif
+/*---------------------------------------------------------------------------*/
+static u16_t
+upper_layer_chksum(u8_t proto)
+{
+ u16_t upper_layer_len;
+ u16_t sum;
+
+#if UIP_CONF_IPV6
+ upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]);
+#else /* UIP_CONF_IPV6 */
+ upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN;
+#endif /* UIP_CONF_IPV6 */
+
+ /* First sum pseudoheader. */
+
+ /* IP protocol and length fields. This addition cannot carry. */
+ sum = upper_layer_len + proto;
+ /* Sum IP source and destination addresses. */
+ sum = chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t));
+
+ /* Sum TCP header and data. */
+ sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN],
+ upper_layer_len);
+
+ return (sum == 0) ? 0xffff : htons(sum);
+}
+/*---------------------------------------------------------------------------*/
+#if UIP_CONF_IPV6
+u16_t
+uip_icmp6chksum(void)
+{
+ return upper_layer_chksum(UIP_PROTO_ICMP6);
+
+}
+#endif /* UIP_CONF_IPV6 */
+/*---------------------------------------------------------------------------*/
+u16_t
+uip_tcpchksum(void)
+{
+ return upper_layer_chksum(UIP_PROTO_TCP);
+}
+/*---------------------------------------------------------------------------*/
+#if UIP_UDP_CHECKSUMS
+u16_t
+uip_udpchksum(void)
+{
+ return upper_layer_chksum(UIP_PROTO_UDP);
+}
+#endif /* UIP_UDP_CHECKSUMS */
+#endif /* UIP_ARCH_CHKSUM */
+/*---------------------------------------------------------------------------*/
+void
+uip_init(void)
+{
+#ifdef UIP_TCP_LISTEN
+ for(c = 0; c < UIP_LISTENPORTS; ++c) {
+ uip_listenports[c] = 0;
+ }
+#endif
+ for(c = 0; c < UIP_CONNS; ++c) {
+ uip_conns[c].tcpstateflags = UIP_CLOSED;
+ }
+#if UIP_ACTIVE_OPEN
+ lastport = 1024;
+#endif /* UIP_ACTIVE_OPEN */
+
+#if UIP_UDP
+ for(c = 0; c < UIP_UDP_CONNS; ++c) {
+ uip_udp_conns[c].lport = 0;
+ }
+#endif /* UIP_UDP */
+
+
+ /* IPv4 initialization. */
+#if UIP_FIXEDADDR == 0
+ /* uip_hostaddr[0] = uip_hostaddr[1] = 0;*/
+#endif /* UIP_FIXEDADDR */
+
+}
+/*---------------------------------------------------------------------------*/
+#if UIP_ACTIVE_OPEN
+struct uip_conn *
+uip_connect(uip_ipaddr_t *ripaddr, u16_t rport)
+{
+ register struct uip_conn *conn, *cconn;
+
+ /* Find an unused local port. */
+ again:
+ ++lastport;
+
+ if(lastport >= 32000) {
+ lastport = 4096;
+ }
+
+ /* Check if this port is already in use, and if so try to find
+ another one. */
+ for(c = 0; c < UIP_CONNS; ++c) {
+ conn = &uip_conns[c];
+ if(conn->tcpstateflags != UIP_CLOSED &&
+ conn->lport == htons(lastport)) {
+ goto again;
+ }
+ }
+
+ conn = 0;
+ for(c = 0; c < UIP_CONNS; ++c) {
+ cconn = &uip_conns[c];
+ if(cconn->tcpstateflags == UIP_CLOSED) {
+ conn = cconn;
+ break;
+ }
+ if(cconn->tcpstateflags == UIP_TIME_WAIT) {
+ if(conn == 0 ||
+ cconn->timer > conn->timer) {
+ conn = cconn;
+ }
+ }
+ }
+
+ if(conn == 0) {
+ return 0;
+ }
+
+ conn->tcpstateflags = UIP_SYN_SENT;
+
+ conn->snd_nxt[0] = iss[0];
+ conn->snd_nxt[1] = iss[1];
+ conn->snd_nxt[2] = iss[2];
+ conn->snd_nxt[3] = iss[3];
+
+ conn->initialmss = conn->mss = UIP_TCP_MSS;
+
+ conn->len = 1; /* TCP length of the SYN is one. */
+ conn->nrtx = 0;
+ conn->timer = 1; /* Send the SYN next time around. */
+ conn->rto = UIP_RTO;
+ conn->sa = 0;
+ conn->sv = 16; /* Initial value of the RTT variance. */
+ conn->lport = htons(lastport);
+ conn->rport = rport;
+ uip_ipaddr_copy(&conn->ripaddr, ripaddr);
+
+ return conn;
+}
+#endif /* UIP_ACTIVE_OPEN */
+/*---------------------------------------------------------------------------*/
+#if UIP_UDP
+struct uip_udp_conn *
+uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport)
+{
+ register struct uip_udp_conn *conn;
+
+ /* Find an unused local port. */
+ again:
+ ++lastport;
+
+ if(lastport >= 32000) {
+ lastport = 4096;
+ }
+
+ for(c = 0; c < UIP_UDP_CONNS; ++c) {
+ if(uip_udp_conns[c].lport == htons(lastport)) {
+ goto again;
+ }
+ }
+
+
+ conn = 0;
+ for(c = 0; c < UIP_UDP_CONNS; ++c) {
+ if(uip_udp_conns[c].lport == 0) {
+ conn = &uip_udp_conns[c];
+ break;
+ }
+ }
+
+ if(conn == 0) {
+ return 0;
+ }
+
+ conn->lport = HTONS(lastport);
+ conn->rport = rport;
+ if(ripaddr == NULL) {
+ memset(conn->ripaddr, 0, sizeof(uip_ipaddr_t));
+ } else {
+ uip_ipaddr_copy(&conn->ripaddr, ripaddr);
+ }
+ conn->ttl = UIP_TTL;
+
+ return conn;
+}
+#endif /* UIP_UDP */
+/*---------------------------------------------------------------------------*/
+#ifdef UIP_TCP_LISTEN
+void
+uip_unlisten(u16_t port)
+{
+ for(c = 0; c < UIP_LISTENPORTS; ++c) {
+ if(uip_listenports[c] == port) {
+ uip_listenports[c] = 0;
+ return;
+ }
+ }
+}
+/*---------------------------------------------------------------------------*/
+void
+uip_listen(u16_t port)
+{
+ for(c = 0; c < UIP_LISTENPORTS; ++c) {
+ if(uip_listenports[c] == 0) {
+ uip_listenports[c] = port;
+ return;
+ }
+ }
+}
+#endif
+/*---------------------------------------------------------------------------*/
+/* XXX: IP fragment reassembly: not well-tested. */
+
+#if UIP_REASSEMBLY && !UIP_CONF_IPV6
+#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)
+static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];
+static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];
+static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f,
+ 0x0f, 0x07, 0x03, 0x01};
+static u16_t uip_reasslen;
+static u8_t uip_reassflags;
+#define UIP_REASS_FLAG_LASTFRAG 0x01
+static u8_t uip_reasstmr;
+
+#define IP_MF 0x20
+
+static u8_t
+uip_reass(void)
+{
+ u16_t offset, len;
+ u16_t i;
+
+ /* If ip_reasstmr is zero, no packet is present in the buffer, so we
+ write the IP header of the fragment into the reassembly
+ buffer. The timer is updated with the maximum age. */
+ if(uip_reasstmr == 0) {
+ memcpy(uip_reassbuf, &BUF->vhl, UIP_IPH_LEN);
+ uip_reasstmr = UIP_REASS_MAXAGE;
+ uip_reassflags = 0;
+ /* Clear the bitmap. */
+ memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap));
+ }
+
+ /* Check if the incoming fragment matches the one currently present
+ in the reasembly buffer. If so, we proceed with copying the
+ fragment into the buffer. */
+ if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&
+ BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&
+ BUF->destipaddr[0] == FBUF->destipaddr[0] &&
+ BUF->destipaddr[1] == FBUF->destipaddr[1] &&
+ BUF->ipid[0] == FBUF->ipid[0] &&
+ BUF->ipid[1] == FBUF->ipid[1]) {
+
+ len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4;
+ offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8;
+
+ /* If the offset or the offset + fragment length overflows the
+ reassembly buffer, we discard the entire packet. */
+ if(offset > UIP_REASS_BUFSIZE ||
+ offset + len > UIP_REASS_BUFSIZE) {
+ uip_reasstmr = 0;
+ goto nullreturn;
+ }
+
+ /* Copy the fragment into the reassembly buffer, at the right
+ offset. */
+ memcpy(&uip_reassbuf[UIP_IPH_LEN + offset],
+ (char *)BUF + (int)((BUF->vhl & 0x0f) * 4),
+ len);
+
+ /* Update the bitmap. */
+ if(offset / (8 * 8) == (offset + len) / (8 * 8)) {
+ /* If the two endpoints are in the same byte, we only update
+ that byte. */
+
+ uip_reassbitmap[offset / (8 * 8)] |=
+ bitmap_bits[(offset / 8 ) & 7] &
+ ~bitmap_bits[((offset + len) / 8 ) & 7];
+ } else {
+ /* If the two endpoints are in different bytes, we update the
+ bytes in the endpoints and fill the stuff inbetween with
+ 0xff. */
+ uip_reassbitmap[offset / (8 * 8)] |=
+ bitmap_bits[(offset / 8 ) & 7];
+ for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
+ uip_reassbitmap[i] = 0xff;
+ }
+ uip_reassbitmap[(offset + len) / (8 * 8)] |=
+ ~bitmap_bits[((offset + len) / 8 ) & 7];
+ }
+
+ /* If this fragment has the More Fragments flag set to zero, we
+ know that this is the last fragment, so we can calculate the
+ size of the entire packet. We also set the
+ IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
+ the final fragment. */
+
+ if((BUF->ipoffset[0] & IP_MF) == 0) {
+ uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
+ uip_reasslen = offset + len;
+ }
+
+ /* Finally, we check if we have a full packet in the buffer. We do
+ this by checking if we have the last fragment and if all bits
+ in the bitmap are set. */
+ if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
+ /* Check all bytes up to and including all but the last byte in
+ the bitmap. */
+ for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {
+ if(uip_reassbitmap[i] != 0xff) {
+ goto nullreturn;
+ }
+ }
+ /* Check the last byte in the bitmap. It should contain just the
+ right amount of bits. */
+ if(uip_reassbitmap[uip_reasslen / (8 * 8)] !=
+ (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {
+ goto nullreturn;
+ }
+
+ /* If we have come this far, we have a full packet in the
+ buffer, so we allocate a pbuf and copy the packet into it. We
+ also reset the timer. */
+ uip_reasstmr = 0;
+ memcpy(BUF, FBUF, uip_reasslen);
+
+ /* Pretend to be a "normal" (i.e., not fragmented) IP packet
+ from now on. */
+ BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
+ BUF->len[0] = uip_reasslen >> 8;
+ BUF->len[1] = uip_reasslen & 0xff;
+ BUF->ipchksum = 0;
+ BUF->ipchksum = ~(uip_ipchksum());
+
+ return uip_reasslen;
+ }
+ }
+
+ nullreturn:
+ return 0;
+}
+#endif /* UIP_REASSEMBLY */
+/*---------------------------------------------------------------------------*/
+static void
+uip_add_rcv_nxt(u16_t n)
+{
+ uip_add32(uip_conn->rcv_nxt, n);
+ uip_conn->rcv_nxt[0] = uip_acc32[0];
+ uip_conn->rcv_nxt[1] = uip_acc32[1];
+ uip_conn->rcv_nxt[2] = uip_acc32[2];
+ uip_conn->rcv_nxt[3] = uip_acc32[3];
+}
+/*---------------------------------------------------------------------------*/
+void
+uip_process(u8_t flag)
+{
+ register struct uip_conn *uip_connr = uip_conn;
+
+#if UIP_UDP
+ if(flag == UIP_UDP_SEND_CONN) {
+ goto udp_send;
+ }
+#endif /* UIP_UDP */
+
+ uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
+
+ /* Check if we were invoked because of a poll request for a
+ particular connection. */
+ if(flag == UIP_POLL_REQUEST) {
+ if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED &&
+ !uip_outstanding(uip_connr)) {
+ uip_flags = UIP_POLL;
+ UIP_APPCALL();
+ goto appsend;
+ }
+ goto drop;
+
+ /* Check if we were invoked because of the perodic timer fireing. */
+ } else if(flag == UIP_TIMER) {
+#if UIP_REASSEMBLY
+ if(uip_reasstmr != 0) {
+ --uip_reasstmr;
+ }
+#endif /* UIP_REASSEMBLY */
+ /* Increase the initial sequence number. */
+ if(++iss[3] == 0) {
+ if(++iss[2] == 0) {
+ if(++iss[1] == 0) {
+ ++iss[0];
+ }
+ }
+ }
+
+ /* Reset the length variables. */
+ uip_len = 0;
+ uip_slen = 0;
+
+ /* Check if the connection is in a state in which we simply wait
+ for the connection to time out. If so, we increase the
+ connection's timer and remove the connection if it times
+ out. */
+ if(uip_connr->tcpstateflags == UIP_TIME_WAIT ||
+ uip_connr->tcpstateflags == UIP_FIN_WAIT_2) {
+ ++(uip_connr->timer);
+ if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) {
+ uip_connr->tcpstateflags = UIP_CLOSED;
+ }
+ } else if(uip_connr->tcpstateflags != UIP_CLOSED) {
+ /* If the connection has outstanding data, we increase the
+ connection's timer and see if it has reached the RTO value
+ in which case we retransmit. */
+ if(uip_outstanding(uip_connr)) {
+ if(uip_connr->timer-- == 0) {
+ if(uip_connr->nrtx == UIP_MAXRTX ||
+ ((uip_connr->tcpstateflags == UIP_SYN_SENT ||
+ uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
+ uip_connr->nrtx == UIP_MAXSYNRTX)) {
+ uip_connr->tcpstateflags = UIP_CLOSED;
+
+ /* We call UIP_APPCALL() with uip_flags set to
+ UIP_TIMEDOUT to inform the application that the
+ connection has timed out. */
+ uip_flags = UIP_TIMEDOUT;
+ UIP_APPCALL();
+
+ /* We also send a reset packet to the remote host. */
+ BUF->flags = TCP_RST | TCP_ACK;
+ goto tcp_send_nodata;
+ }
+
+ /* Exponential backoff. */
+ uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
+ 4:
+ uip_connr->nrtx);
+ ++(uip_connr->nrtx);
+
+ /* Ok, so we need to retransmit. We do this differently
+ depending on which state we are in. In ESTABLISHED, we
+ call upon the application so that it may prepare the
+ data for the retransmit. In SYN_RCVD, we resend the
+ SYNACK that we sent earlier and in LAST_ACK we have to
+ retransmit our FINACK. */
+ UIP_STAT(++uip_stat.tcp.rexmit);
+ switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
+ case UIP_SYN_RCVD:
+ /* In the SYN_RCVD state, we should retransmit our
+ SYNACK. */
+ goto tcp_send_synack;
+
+#if UIP_ACTIVE_OPEN
+ case UIP_SYN_SENT:
+ /* In the SYN_SENT state, we retransmit out SYN. */
+ BUF->flags = 0;
+ goto tcp_send_syn;
+#endif /* UIP_ACTIVE_OPEN */
+
+ case UIP_ESTABLISHED:
+ /* In the ESTABLISHED state, we call upon the application
+ to do the actual retransmit after which we jump into
+ the code for sending out the packet (the apprexmit
+ label). */
+ uip_flags = UIP_REXMIT;
+ UIP_APPCALL();
+ goto apprexmit;
+
+ case UIP_FIN_WAIT_1:
+ case UIP_CLOSING:
+ case UIP_LAST_ACK:
+ /* In all these states we should retransmit a FINACK. */
+ goto tcp_send_finack;
+
+ }
+ }
+ } else if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) {
+ /* If there was no need for a retransmission, we poll the
+ application for new data. */
+ uip_flags = UIP_POLL;
+ UIP_APPCALL();
+ goto appsend;
+ }
+ }
+ goto drop;
+ }
+#if UIP_UDP
+ if(flag == UIP_UDP_TIMER) {
+ if(uip_udp_conn->lport != 0) {
+ uip_conn = NULL;
+ uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
+ uip_len = uip_slen = 0;
+ uip_flags = UIP_POLL;
+ UIP_UDP_APPCALL();
+ goto udp_send;
+ } else {
+ goto drop;
+ }
+ }
+#endif
+
+ /* This is where the input processing starts. */
+ UIP_STAT(++uip_stat.ip.recv);
+
+ /* Start of IP input header processing code. */
+
+#if UIP_CONF_IPV6
+ /* Check validity of the IP header. */
+ if((BUF->vtc & 0xf0) != 0x60) { /* IP version and header length. */
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.vhlerr);
+ UIP_LOG("ipv6: invalid version.");
+ goto drop;
+ }
+#else /* UIP_CONF_IPV6 */
+ /* Check validity of the IP header. */
+ if(BUF->vhl != 0x45) { /* IP version and header length. */
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.vhlerr);
+ UIP_LOG("ip: invalid version or header length.");
+ goto drop;
+ }
+#endif /* UIP_CONF_IPV6 */
+
+ /* Check the size of the packet. If the size reported to us in
+ uip_len is smaller the size reported in the IP header, we assume
+ that the packet has been corrupted in transit. If the size of
+ uip_len is larger than the size reported in the IP packet header,
+ the packet has been padded and we set uip_len to the correct
+ value.. */
+
+ if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) {
+ uip_len = (BUF->len[0] << 8) + BUF->len[1];
+#if UIP_CONF_IPV6
+ uip_len += 40; /* The length reported in the IPv6 header is the
+ length of the payload that follows the
+ header. However, uIP uses the uip_len variable
+ for holding the size of the entire packet,
+ including the IP header. For IPv4 this is not a
+ problem as the length field in the IPv4 header
+ contains the length of the entire packet. But
+ for IPv6 we need to add the size of the IPv6
+ header (40 bytes). */
+#endif /* UIP_CONF_IPV6 */
+ } else {
+ UIP_LOG("ip: packet shorter than reported in IP header.");
+ goto drop;
+ }
+
+#if !UIP_CONF_IPV6
+ /* Check the fragment flag. */
+ if((BUF->ipoffset[0] & 0x3f) != 0 ||
+ BUF->ipoffset[1] != 0) {
+#if UIP_REASSEMBLY
+ uip_len = uip_reass();
+ if(uip_len == 0) {
+ goto drop;
+ }
+#else /* UIP_REASSEMBLY */
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.fragerr);
+ UIP_LOG("ip: fragment dropped.");
+ goto drop;
+#endif /* UIP_REASSEMBLY */
+ }
+#endif /* UIP_CONF_IPV6 */
+
+ if(uip_ipaddr_cmp(uip_hostaddr, all_zeroes_addr)) {
+ /* If we are configured to use ping IP address configuration and
+ hasn't been assigned an IP address yet, we accept all ICMP
+ packets. */
+#if UIP_PINGADDRCONF && !UIP_CONF_IPV6
+ if(BUF->proto == UIP_PROTO_ICMP) {
+ UIP_LOG("ip: possible ping config packet received.");
+ goto icmp_input;
+ } else {
+ UIP_LOG("ip: packet dropped since no address assigned.");
+ goto drop;
+ }
+#endif /* UIP_PINGADDRCONF */
+
+ } else {
+ /* If IP broadcast support is configured, we check for a broadcast
+ UDP packet, which may be destined to us. */
+#if UIP_BROADCAST
+ DEBUG_PRINTF("UDP IP checksum 0x%04x\n", uip_ipchksum());
+ if(BUF->proto == UIP_PROTO_UDP &&
+ uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr)
+ /*&&
+ uip_ipchksum() == 0xffff*/) {
+ goto udp_input;
+ }
+#endif /* UIP_BROADCAST */
+
+ /* Check if the packet is destined for our IP address. */
+#if !UIP_CONF_IPV6
+ if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr)) {
+ UIP_STAT(++uip_stat.ip.drop);
+ goto drop;
+ }
+#else /* UIP_CONF_IPV6 */
+ /* For IPv6, packet reception is a little trickier as we need to
+ make sure that we listen to certain multicast addresses (all
+ hosts multicast address, and the solicited-node multicast
+ address) as well. However, we will cheat here and accept all
+ multicast packets that are sent to the ff02::/16 addresses. */
+ if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) &&
+ BUF->destipaddr[0] != HTONS(0xff02)) {
+ UIP_STAT(++uip_stat.ip.drop);
+ goto drop;
+ }
+#endif /* UIP_CONF_IPV6 */
+ }
+
+#if !UIP_CONF_IPV6
+ if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header
+ checksum. */
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.chkerr);
+ UIP_LOG("ip: bad checksum.");
+ goto drop;
+ }
+#endif /* UIP_CONF_IPV6 */
+
+ if(BUF->proto == UIP_PROTO_TCP) { /* Check for TCP packet. If so,
+ proceed with TCP input
+ processing. */
+ goto tcp_input;
+ }
+
+#if UIP_UDP
+ if(BUF->proto == UIP_PROTO_UDP) {
+ goto udp_input;
+ }
+#endif /* UIP_UDP */
+
+#if !UIP_CONF_IPV6
+ /* ICMPv4 processing code follows. */
+ if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from
+ here. */
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.protoerr);
+ UIP_LOG("ip: neither tcp nor icmp.");
+ goto drop;
+ }
+
+#if UIP_PINGADDRCONF
+ icmp_input:
+#endif /* UIP_PINGADDRCONF */
+ UIP_STAT(++uip_stat.icmp.recv);
+
+ /* ICMP echo (i.e., ping) processing. This is simple, we only change
+ the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP
+ checksum before we return the packet. */
+ if(ICMPBUF->type != ICMP_ECHO) {
+ UIP_STAT(++uip_stat.icmp.drop);
+ UIP_STAT(++uip_stat.icmp.typeerr);
+ UIP_LOG("icmp: not icmp echo.");
+ goto drop;
+ }
+
+ /* If we are configured to use ping IP address assignment, we use
+ the destination IP address of this ping packet and assign it to
+ ourself. */
+#if UIP_PINGADDRCONF
+ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
+ uip_hostaddr[0] = BUF->destipaddr[0];
+ uip_hostaddr[1] = BUF->destipaddr[1];
+ }
+#endif /* UIP_PINGADDRCONF */
+
+ ICMPBUF->type = ICMP_ECHO_REPLY;
+
+ if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) {
+ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;
+ } else {
+ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);
+ }
+
+ /* Swap IP addresses. */
+ uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
+ uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+
+ UIP_STAT(++uip_stat.icmp.sent);
+ goto send;
+
+ /* End of IPv4 input header processing code. */
+#else /* !UIP_CONF_IPV6 */
+
+ /* This is IPv6 ICMPv6 processing code. */
+ DEBUG_PRINTF("icmp6_input: length %d\n", uip_len);
+
+ if(BUF->proto != UIP_PROTO_ICMP6) { /* We only allow ICMPv6 packets from
+ here. */
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.protoerr);
+ UIP_LOG("ip: neither tcp nor icmp6.");
+ goto drop;
+ }
+
+ UIP_STAT(++uip_stat.icmp.recv);
+
+ /* If we get a neighbor solicitation for our address we should send
+ a neighbor advertisement message back. */
+ if(ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION) {
+ if(uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr)) {
+
+ if(ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) {
+ /* Save the sender's address in our neighbor list. */
+ uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2]));
+ }
+
+ /* We should now send a neighbor advertisement back to where the
+ neighbor solicication came from. */
+ ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT;
+ ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */
+
+ ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0;
+
+ uip_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr);
+ uip_ipaddr_copy(ICMPBUF->srcipaddr, uip_hostaddr);
+ ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS;
+ ICMPBUF->options[1] = 1; /* Options length, 1 = 8 bytes. */
+ memcpy(&(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr));
+ ICMPBUF->icmpchksum = 0;
+ ICMPBUF->icmpchksum = ~uip_icmp6chksum();
+ goto send;
+
+ }
+ goto drop;
+ } else if(ICMPBUF->type == ICMP6_ECHO) {
+ /* ICMP echo (i.e., ping) processing. This is simple, we only
+ change the ICMP type from ECHO to ECHO_REPLY and update the
+ ICMP checksum before we return the packet. */
+
+ ICMPBUF->type = ICMP6_ECHO_REPLY;
+
+ uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
+ uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+ ICMPBUF->icmpchksum = 0;
+ ICMPBUF->icmpchksum = ~uip_icmp6chksum();
+
+ UIP_STAT(++uip_stat.icmp.sent);
+ goto send;
+ } else {
+ DEBUG_PRINTF("Unknown icmp6 message type %d\n", ICMPBUF->type);
+ UIP_STAT(++uip_stat.icmp.drop);
+ UIP_STAT(++uip_stat.icmp.typeerr);
+ UIP_LOG("icmp: unknown ICMP message.");
+ goto drop;
+ }
+
+ /* End of IPv6 ICMP processing. */
+
+#endif /* !UIP_CONF_IPV6 */
+
+#if UIP_UDP
+ /* UDP input processing. */
+ udp_input:
+ /* UDP processing is really just a hack. We don't do anything to the
+ UDP/IP headers, but let the UDP application do all the hard
+ work. If the application sets uip_slen, it has a packet to
+ send. */
+#if UIP_UDP_CHECKSUMS
+ uip_len = uip_len - UIP_IPUDPH_LEN;
+ uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
+ if(UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff) {
+ UIP_STAT(++uip_stat.udp.drop);
+ UIP_STAT(++uip_stat.udp.chkerr);
+ UIP_LOG("udp: bad checksum.");
+ goto drop;
+ }
+#else /* UIP_UDP_CHECKSUMS */
+ uip_len = uip_len - UIP_IPUDPH_LEN;
+#endif /* UIP_UDP_CHECKSUMS */
+
+ /* Demultiplex this UDP packet between the UDP "connections". */
+ for(uip_udp_conn = &uip_udp_conns[0];
+ uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];
+ ++uip_udp_conn) {
+ /* If the local UDP port is non-zero, the connection is considered
+ to be used. If so, the local port number is checked against the
+ destination port number in the received packet. If the two port
+ numbers match, the remote port number is checked if the
+ connection is bound to a remote port. Finally, if the
+ connection is bound to a remote IP address, the source IP
+ address of the packet is checked. */
+ if(uip_udp_conn->lport != 0 &&
+ UDPBUF->destport == uip_udp_conn->lport &&
+ (uip_udp_conn->rport == 0 ||
+ UDPBUF->srcport == uip_udp_conn->rport) &&
+ (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||
+ uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||
+ uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) {
+ goto udp_found;
+ }
+ }
+ UIP_LOG("udp: no matching connection found");
+ goto drop;
+
+ udp_found:
+ uip_conn = NULL;
+ uip_flags = UIP_NEWDATA;
+ uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
+ uip_slen = 0;
+ UIP_UDP_APPCALL();
+ udp_send:
+ if(uip_slen == 0) {
+ goto drop;
+ }
+ uip_len = uip_slen + UIP_IPUDPH_LEN;
+
+#if UIP_CONF_IPV6
+ /* For IPv6, the IP length field does not include the IPv6 IP header
+ length. */
+ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
+ BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
+#else /* UIP_CONF_IPV6 */
+ BUF->len[0] = (uip_len >> 8);
+ BUF->len[1] = (uip_len & 0xff);
+#endif /* UIP_CONF_IPV6 */
+
+ BUF->ttl = uip_udp_conn->ttl;
+ BUF->proto = UIP_PROTO_UDP;
+
+ UDPBUF->udplen = HTONS(uip_slen + UIP_UDPH_LEN);
+ UDPBUF->udpchksum = 0;
+
+ BUF->srcport = uip_udp_conn->lport;
+ BUF->destport = uip_udp_conn->rport;
+
+ uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+ uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr);
+
+ uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
+
+#if UIP_UDP_CHECKSUMS
+ /* Calculate UDP checksum. */
+ UDPBUF->udpchksum = ~(uip_udpchksum());
+ if(UDPBUF->udpchksum == 0) {
+ UDPBUF->udpchksum = 0xffff;
+ }
+#endif /* UIP_UDP_CHECKSUMS */
+
+ goto ip_send_nolen;
+#endif /* UIP_UDP */
+
+ /* TCP input processing. */
+ tcp_input:
+ UIP_STAT(++uip_stat.tcp.recv);
+
+ /* Start of TCP input header processing code. */
+
+ if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP
+ checksum. */
+ UIP_STAT(++uip_stat.tcp.drop);
+ UIP_STAT(++uip_stat.tcp.chkerr);
+ UIP_LOG("tcp: bad checksum.");
+ goto drop;
+ }
+
+
+ /* Demultiplex this segment. */
+ /* First check any active connections. */
+ for(uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1];
+ ++uip_connr) {
+ if(uip_connr->tcpstateflags != UIP_CLOSED &&
+ BUF->destport == uip_connr->lport &&
+ BUF->srcport == uip_connr->rport &&
+ uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) {
+ goto found;
+ }
+ }
+
+ /* If we didn't find and active connection that expected the packet,
+ either this packet is an old duplicate, or this is a SYN packet
+ destined for a connection in LISTEN. If the SYN flag isn't set,
+ it is an old packet and we send a RST. */
+ if((BUF->flags & TCP_CTL) != TCP_SYN) {
+ goto reset;
+ }
+
+ tmp16 = BUF->destport;
+
+#ifdef UIP_TCP_LISTEN
+ /* Next, check listening connections. */
+ for(c = 0; c < UIP_LISTENPORTS; ++c) {
+ if(tmp16 == uip_listenports[c])
+ goto found_listen;
+ }
+#endif
+
+ /* No matching connection found, so we send a RST packet. */
+ UIP_STAT(++uip_stat.tcp.synrst);
+ reset:
+
+ /* We do not send resets in response to resets. */
+ if(BUF->flags & TCP_RST) {
+ goto drop;
+ }
+
+ UIP_STAT(++uip_stat.tcp.rst);
+
+ BUF->flags = TCP_RST | TCP_ACK;
+ uip_len = UIP_IPTCPH_LEN;
+ BUF->tcpoffset = 5 << 4;
+
+ /* Flip the seqno and ackno fields in the TCP header. */
+ c = BUF->seqno[3];
+ BUF->seqno[3] = BUF->ackno[3];
+ BUF->ackno[3] = c;
+
+ c = BUF->seqno[2];
+ BUF->seqno[2] = BUF->ackno[2];
+ BUF->ackno[2] = c;
+
+ c = BUF->seqno[1];
+ BUF->seqno[1] = BUF->ackno[1];
+ BUF->ackno[1] = c;
+
+ c = BUF->seqno[0];
+ BUF->seqno[0] = BUF->ackno[0];
+ BUF->ackno[0] = c;
+
+ /* We also have to increase the sequence number we are
+ acknowledging. If the least significant byte overflowed, we need
+ to propagate the carry to the other bytes as well. */
+ if(++BUF->ackno[3] == 0) {
+ if(++BUF->ackno[2] == 0) {
+ if(++BUF->ackno[1] == 0) {
+ ++BUF->ackno[0];
+ }
+ }
+ }
+
+ /* Swap port numbers. */
+ tmp16 = BUF->srcport;
+ BUF->srcport = BUF->destport;
+ BUF->destport = tmp16;
+
+ /* Swap IP addresses. */
+ uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
+ uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+
+ /* And send out the RST packet! */
+ goto tcp_send_noconn;
+
+#ifdef UIP_TCP_LISTEN
+ /* This label will be jumped to if we matched the incoming packet
+ with a connection in LISTEN. In that case, we should create a new
+ connection and send a SYNACK in return. */
+ found_listen:
+ /* First we check if there are any connections avaliable. Unused
+ connections are kept in the same table as used connections, but
+ unused ones have the tcpstate set to CLOSED. Also, connections in
+ TIME_WAIT are kept track of and we'll use the oldest one if no
+ CLOSED connections are found. Thanks to Eddie C. Dost for a very
+ nice algorithm for the TIME_WAIT search. */
+ uip_connr = 0;
+ for(c = 0; c < UIP_CONNS; ++c) {
+ if(uip_conns[c].tcpstateflags == UIP_CLOSED) {
+ uip_connr = &uip_conns[c];
+ break;
+ }
+ if(uip_conns[c].tcpstateflags == UIP_TIME_WAIT) {
+ if(uip_connr == 0 ||
+ uip_conns[c].timer > uip_connr->timer) {
+ uip_connr = &uip_conns[c];
+ }
+ }
+ }
+
+ if(uip_connr == 0) {
+ /* All connections are used already, we drop packet and hope that
+ the remote end will retransmit the packet at a time when we
+ have more spare connections. */
+ UIP_STAT(++uip_stat.tcp.syndrop);
+ UIP_LOG("tcp: found no unused connections.");
+ goto drop;
+ }
+ uip_conn = uip_connr;
+
+ /* Fill in the necessary fields for the new connection. */
+ uip_connr->rto = uip_connr->timer = UIP_RTO;
+ uip_connr->sa = 0;
+ uip_connr->sv = 4;
+ uip_connr->nrtx = 0;
+ uip_connr->lport = BUF->destport;
+ uip_connr->rport = BUF->srcport;
+ uip_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr);
+ uip_connr->tcpstateflags = UIP_SYN_RCVD;
+
+ uip_connr->snd_nxt[0] = iss[0];
+ uip_connr->snd_nxt[1] = iss[1];
+ uip_connr->snd_nxt[2] = iss[2];
+ uip_connr->snd_nxt[3] = iss[3];
+ uip_connr->len = 1;
+
+ /* rcv_nxt should be the seqno from the incoming packet + 1. */
+ uip_connr->rcv_nxt[3] = BUF->seqno[3];
+ uip_connr->rcv_nxt[2] = BUF->seqno[2];
+ uip_connr->rcv_nxt[1] = BUF->seqno[1];
+ uip_connr->rcv_nxt[0] = BUF->seqno[0];
+ uip_add_rcv_nxt(1);
+
+ /* Parse the TCP MSS option, if present. */
+ if((BUF->tcpoffset & 0xf0) > 0x50) {
+ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
+ opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
+ if(opt == TCP_OPT_END) {
+ /* End of options. */
+ break;
+ } else if(opt == TCP_OPT_NOOP) {
+ ++c;
+ /* NOP option. */
+ } else if(opt == TCP_OPT_MSS &&
+ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
+ /* An MSS option with the right option length. */
+ tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
+ (u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];
+ uip_connr->initialmss = uip_connr->mss =
+ tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
+
+ /* And we are done processing options. */
+ break;
+ } else {
+ /* All other options have a length field, so that we easily
+ can skip past them. */
+ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
+ /* If the length field is zero, the options are malformed
+ and we don't process them further. */
+ break;
+ }
+ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
+ }
+ }
+ }
+#endif
+
+ /* Our response will be a SYNACK. */
+#if UIP_ACTIVE_OPEN
+ tcp_send_synack:
+ BUF->flags = TCP_ACK;
+
+ tcp_send_syn:
+ BUF->flags |= TCP_SYN;
+#else /* UIP_ACTIVE_OPEN */
+ tcp_send_synack:
+ BUF->flags = TCP_SYN | TCP_ACK;
+#endif /* UIP_ACTIVE_OPEN */
+
+ /* We send out the TCP Maximum Segment Size option with our
+ SYNACK. */
+ BUF->optdata[0] = TCP_OPT_MSS;
+ BUF->optdata[1] = TCP_OPT_MSS_LEN;
+ BUF->optdata[2] = (UIP_TCP_MSS) / 256;
+ BUF->optdata[3] = (UIP_TCP_MSS) & 255;
+ uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN;
+ BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4;
+ goto tcp_send;
+
+ /* This label will be jumped to if we found an active connection. */
+ found:
+ uip_conn = uip_connr;
+ uip_flags = 0;
+ /* We do a very naive form of TCP reset processing; we just accept
+ any RST and kill our connection. We should in fact check if the
+ sequence number of this reset is wihtin our advertised window
+ before we accept the reset. */
+ if(BUF->flags & TCP_RST) {
+ uip_connr->tcpstateflags = UIP_CLOSED;
+ UIP_LOG("tcp: got reset, aborting connection.");
+ uip_flags = UIP_ABORT;
+ UIP_APPCALL();
+ goto drop;
+ }
+ /* Calculated the length of the data, if the application has sent
+ any data to us. */
+ c = (BUF->tcpoffset >> 4) << 2;
+ /* uip_len will contain the length of the actual TCP data. This is
+ calculated by subtracing the length of the TCP header (in
+ c) and the length of the IP header (20 bytes). */
+ uip_len = uip_len - c - UIP_IPH_LEN;
+
+ /* First, check if the sequence number of the incoming packet is
+ what we're expecting next. If not, we send out an ACK with the
+ correct numbers in. */
+ if(!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) &&
+ ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) {
+ if((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
+ (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
+ BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
+ BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
+ BUF->seqno[3] != uip_connr->rcv_nxt[3])) {
+ goto tcp_send_ack;
+ }
+ }
+
+ /* Next, check if the incoming segment acknowledges any outstanding
+ data. If so, we update the sequence number, reset the length of
+ the outstanding data, calculate RTT estimations, and reset the
+ retransmission timer. */
+ if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) {
+ uip_add32(uip_connr->snd_nxt, uip_connr->len);
+
+ if(BUF->ackno[0] == uip_acc32[0] &&
+ BUF->ackno[1] == uip_acc32[1] &&
+ BUF->ackno[2] == uip_acc32[2] &&
+ BUF->ackno[3] == uip_acc32[3]) {
+ /* Update sequence number. */
+ uip_connr->snd_nxt[0] = uip_acc32[0];
+ uip_connr->snd_nxt[1] = uip_acc32[1];
+ uip_connr->snd_nxt[2] = uip_acc32[2];
+ uip_connr->snd_nxt[3] = uip_acc32[3];
+
+
+ /* Do RTT estimation, unless we have done retransmissions. */
+ if(uip_connr->nrtx == 0) {
+ signed char m;
+ m = uip_connr->rto - uip_connr->timer;
+ /* This is taken directly from VJs original code in his paper */
+ m = m - (uip_connr->sa >> 3);
+ uip_connr->sa += m;
+ if(m < 0) {
+ m = -m;
+ }
+ m = m - (uip_connr->sv >> 2);
+ uip_connr->sv += m;
+ uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;
+
+ }
+ /* Set the acknowledged flag. */
+ uip_flags = UIP_ACKDATA;
+ /* Reset the retransmission timer. */
+ uip_connr->timer = uip_connr->rto;
+
+ /* Reset length of outstanding data. */
+ uip_connr->len = 0;
+ }
+
+ }
+
+ /* Do different things depending on in what state the connection is. */
+ switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
+ /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
+ implemented, since we force the application to close when the
+ peer sends a FIN (hence the application goes directly from
+ ESTABLISHED to LAST_ACK). */
+ case UIP_SYN_RCVD:
+ /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and
+ we are waiting for an ACK that acknowledges the data we sent
+ out the last time. Therefore, we want to have the UIP_ACKDATA
+ flag set. If so, we enter the ESTABLISHED state. */
+ if(uip_flags & UIP_ACKDATA) {
+ uip_connr->tcpstateflags = UIP_ESTABLISHED;
+ uip_flags = UIP_CONNECTED;
+ uip_connr->len = 0;
+ if(uip_len > 0) {
+ uip_flags |= UIP_NEWDATA;
+ uip_add_rcv_nxt(uip_len);
+ }
+ uip_slen = 0;
+ UIP_APPCALL();
+ goto appsend;
+ }
+ goto drop;
+#if UIP_ACTIVE_OPEN
+ case UIP_SYN_SENT:
+ /* In SYN_SENT, we wait for a SYNACK that is sent in response to
+ our SYN. The rcv_nxt is set to sequence number in the SYNACK
+ plus one, and we send an ACK. We move into the ESTABLISHED
+ state. */
+ if((uip_flags & UIP_ACKDATA) &&
+ (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) {
+
+ /* Parse the TCP MSS option, if present. */
+ if((BUF->tcpoffset & 0xf0) > 0x50) {
+ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
+ opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c];
+ if(opt == TCP_OPT_END) {
+ /* End of options. */
+ break;
+ } else if(opt == TCP_OPT_NOOP) {
+ ++c;
+ /* NOP option. */
+ } else if(opt == TCP_OPT_MSS &&
+ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
+ /* An MSS option with the right option length. */
+ tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
+ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
+ uip_connr->initialmss =
+ uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
+
+ /* And we are done processing options. */
+ break;
+ } else {
+ /* All other options have a length field, so that we easily
+ can skip past them. */
+ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
+ /* If the length field is zero, the options are malformed
+ and we don't process them further. */
+ break;
+ }
+ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
+ }
+ }
+ }
+ uip_connr->tcpstateflags = UIP_ESTABLISHED;
+ uip_connr->rcv_nxt[0] = BUF->seqno[0];
+ uip_connr->rcv_nxt[1] = BUF->seqno[1];
+ uip_connr->rcv_nxt[2] = BUF->seqno[2];
+ uip_connr->rcv_nxt[3] = BUF->seqno[3];
+ uip_add_rcv_nxt(1);
+ uip_flags = UIP_CONNECTED | UIP_NEWDATA;
+ uip_connr->len = 0;
+ uip_len = 0;
+ uip_slen = 0;
+ UIP_APPCALL();
+ goto appsend;
+ }
+ /* Inform the application that the connection failed */
+ uip_flags = UIP_ABORT;
+ UIP_APPCALL();
+ /* The connection is closed after we send the RST */
+ uip_conn->tcpstateflags = UIP_CLOSED;
+ goto reset;
+#endif /* UIP_ACTIVE_OPEN */
+
+ case UIP_ESTABLISHED:
+ /* In the ESTABLISHED state, we call upon the application to feed
+ data into the uip_buf. If the UIP_ACKDATA flag is set, the
+ application should put new data into the buffer, otherwise we are
+ retransmitting an old segment, and the application should put that
+ data into the buffer.
+
+ If the incoming packet is a FIN, we should close the connection on
+ this side as well, and we send out a FIN and enter the LAST_ACK
+ state. We require that there is no outstanding data; otherwise the
+ sequence numbers will be screwed up. */
+
+ if(BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
+ if(uip_outstanding(uip_connr)) {
+ goto drop;
+ }
+ uip_add_rcv_nxt(1 + uip_len);
+ uip_flags |= UIP_CLOSE;
+ if(uip_len > 0) {
+ uip_flags |= UIP_NEWDATA;
+ }
+ UIP_APPCALL();
+ uip_connr->len = 1;
+ uip_connr->tcpstateflags = UIP_LAST_ACK;
+ uip_connr->nrtx = 0;
+ tcp_send_finack:
+ BUF->flags = TCP_FIN | TCP_ACK;
+ goto tcp_send_nodata;
+ }
+
+ /* Check the URG flag. If this is set, the segment carries urgent
+ data that we must pass to the application. */
+ if((BUF->flags & TCP_URG) != 0) {
+#if UIP_URGDATA > 0
+ uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];
+ if(uip_urglen > uip_len) {
+ /* There is more urgent data in the next segment to come. */
+ uip_urglen = uip_len;
+ }
+ uip_add_rcv_nxt(uip_urglen);
+ uip_len -= uip_urglen;
+ uip_urgdata = uip_appdata;
+ uip_appdata += uip_urglen;
+ } else {
+ uip_urglen = 0;
+#else /* UIP_URGDATA > 0 */
+ uip_appdata = ((char *)uip_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]);
+ uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1];
+#endif /* UIP_URGDATA > 0 */
+ }
+
+ /* If uip_len > 0 we have TCP data in the packet, and we flag this
+ by setting the UIP_NEWDATA flag and update the sequence number
+ we acknowledge. If the application has stopped the dataflow
+ using uip_stop(), we must not accept any data packets from the
+ remote host. */
+ if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
+ uip_flags |= UIP_NEWDATA;
+ uip_add_rcv_nxt(uip_len);
+ }
+
+ /* Check if the available buffer space advertised by the other end
+ is smaller than the initial MSS for this connection. If so, we
+ set the current MSS to the window size to ensure that the
+ application does not send more data than the other end can
+ handle.
+
+ If the remote host advertises a zero window, we set the MSS to
+ the initial MSS so that the application will send an entire MSS
+ of data. This data will not be acknowledged by the receiver,
+ and the application will retransmit it. This is called the
+ "persistent timer" and uses the retransmission mechanim.
+ */
+ tmp16 = ((u16_t)BUF->wnd[0] << 8) + (u16_t)BUF->wnd[1];
+ if(tmp16 > uip_connr->initialmss ||
+ tmp16 == 0) {
+ tmp16 = uip_connr->initialmss;
+ }
+ uip_connr->mss = tmp16;
+
+ /* If this packet constitutes an ACK for outstanding data (flagged
+ by the UIP_ACKDATA flag, we should call the application since it
+ might want to send more data. If the incoming packet had data
+ from the peer (as flagged by the UIP_NEWDATA flag), the
+ application must also be notified.
+
+ When the application is called, the global variable uip_len
+ contains the length of the incoming data. The application can
+ access the incoming data through the global pointer
+ uip_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN
+ bytes into the uip_buf array.
+
+ If the application wishes to send any data, this data should be
+ put into the uip_appdata and the length of the data should be
+ put into uip_len. If the application don't have any data to
+ send, uip_len must be set to 0. */
+ if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) {
+ uip_slen = 0;
+ UIP_APPCALL();
+
+ appsend:
+
+ if(uip_flags & UIP_ABORT) {
+ uip_slen = 0;
+ uip_connr->tcpstateflags = UIP_CLOSED;
+ BUF->flags = TCP_RST | TCP_ACK;
+ goto tcp_send_nodata;
+ }
+
+ if(uip_flags & UIP_CLOSE) {
+ uip_slen = 0;
+ uip_connr->len = 1;
+ uip_connr->tcpstateflags = UIP_FIN_WAIT_1;
+ uip_connr->nrtx = 0;
+ BUF->flags = TCP_FIN | TCP_ACK;
+ goto tcp_send_nodata;
+ }
+
+ /* If uip_slen > 0, the application has data to be sent. */
+ if(uip_slen > 0) {
+
+ /* If the connection has acknowledged data, the contents of
+ the ->len variable should be discarded. */
+ if((uip_flags & UIP_ACKDATA) != 0) {
+ uip_connr->len = 0;
+ }
+
+ /* If the ->len variable is non-zero the connection has
+ already data in transit and cannot send anymore right
+ now. */
+ if(uip_connr->len == 0) {
+
+ /* The application cannot send more than what is allowed by
+ the mss (the minumum of the MSS and the available
+ window). */
+ if(uip_slen > uip_connr->mss) {
+ uip_slen = uip_connr->mss;
+ }
+
+ /* Remember how much data we send out now so that we know
+ when everything has been acknowledged. */
+ uip_connr->len = uip_slen;
+ } else {
+
+ /* If the application already had unacknowledged data, we
+ make sure that the application does not send (i.e.,
+ retransmit) out more than it previously sent out. */
+ uip_slen = uip_connr->len;
+ }
+ }
+ uip_connr->nrtx = 0;
+ apprexmit:
+ uip_appdata = uip_sappdata;
+
+ /* If the application has data to be sent, or if the incoming
+ packet had new data in it, we must send out a packet. */
+ if(uip_slen > 0 && uip_connr->len > 0) {
+ /* Add the length of the IP and TCP headers. */
+ uip_len = uip_connr->len + UIP_TCPIP_HLEN;
+ /* We always set the ACK flag in response packets. */
+ BUF->flags = TCP_ACK | TCP_PSH;
+ /* Send the packet. */
+ goto tcp_send_noopts;
+ }
+ /* If there is no data to send, just send out a pure ACK if
+ there is newdata. */
+ if(uip_flags & UIP_NEWDATA) {
+ uip_len = UIP_TCPIP_HLEN;
+ BUF->flags = TCP_ACK;
+ goto tcp_send_noopts;
+ }
+ }
+ goto drop;
+ case UIP_LAST_ACK:
+ /* We can close this connection if the peer has acknowledged our
+ FIN. This is indicated by the UIP_ACKDATA flag. */
+ if(uip_flags & UIP_ACKDATA) {
+ uip_connr->tcpstateflags = UIP_CLOSED;
+ uip_flags = UIP_CLOSE;
+ UIP_APPCALL();
+ }
+ break;
+
+ case UIP_FIN_WAIT_1:
+ /* The application has closed the connection, but the remote host
+ hasn't closed its end yet. Thus we do nothing but wait for a
+ FIN from the other side. */
+ if(uip_len > 0) {
+ uip_add_rcv_nxt(uip_len);
+ }
+ if(BUF->flags & TCP_FIN) {
+ if(uip_flags & UIP_ACKDATA) {
+ uip_connr->tcpstateflags = UIP_TIME_WAIT;
+ uip_connr->timer = 0;
+ uip_connr->len = 0;
+ } else {
+ uip_connr->tcpstateflags = UIP_CLOSING;
+ }
+ uip_add_rcv_nxt(1);
+ uip_flags = UIP_CLOSE;
+ UIP_APPCALL();
+ goto tcp_send_ack;
+ } else if(uip_flags & UIP_ACKDATA) {
+ uip_connr->tcpstateflags = UIP_FIN_WAIT_2;
+ uip_connr->len = 0;
+ goto drop;
+ }
+ if(uip_len > 0) {
+ goto tcp_send_ack;
+ }
+ goto drop;
+
+ case UIP_FIN_WAIT_2:
+ if(uip_len > 0) {
+ uip_add_rcv_nxt(uip_len);
+ }
+ if(BUF->flags & TCP_FIN) {
+ uip_connr->tcpstateflags = UIP_TIME_WAIT;
+ uip_connr->timer = 0;
+ uip_add_rcv_nxt(1);
+ uip_flags = UIP_CLOSE;
+ UIP_APPCALL();
+ goto tcp_send_ack;
+ }
+ if(uip_len > 0) {
+ goto tcp_send_ack;
+ }
+ goto drop;
+
+ case UIP_TIME_WAIT:
+ goto tcp_send_ack;
+
+ case UIP_CLOSING:
+ if(uip_flags & UIP_ACKDATA) {
+ uip_connr->tcpstateflags = UIP_TIME_WAIT;
+ uip_connr->timer = 0;
+ }
+ }
+ goto drop;
+
+
+ /* We jump here when we are ready to send the packet, and just want
+ to set the appropriate TCP sequence numbers in the TCP header. */
+ tcp_send_ack:
+ BUF->flags = TCP_ACK;
+ tcp_send_nodata:
+ uip_len = UIP_IPTCPH_LEN;
+ tcp_send_noopts:
+ BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4;
+ tcp_send:
+ /* We're done with the input processing. We are now ready to send a
+ reply. Our job is to fill in all the fields of the TCP and IP
+ headers before calculating the checksum and finally send the
+ packet. */
+ BUF->ackno[0] = uip_connr->rcv_nxt[0];
+ BUF->ackno[1] = uip_connr->rcv_nxt[1];
+ BUF->ackno[2] = uip_connr->rcv_nxt[2];
+ BUF->ackno[3] = uip_connr->rcv_nxt[3];
+
+ BUF->seqno[0] = uip_connr->snd_nxt[0];
+ BUF->seqno[1] = uip_connr->snd_nxt[1];
+ BUF->seqno[2] = uip_connr->snd_nxt[2];
+ BUF->seqno[3] = uip_connr->snd_nxt[3];
+
+ BUF->proto = UIP_PROTO_TCP;
+
+ BUF->srcport = uip_connr->lport;
+ BUF->destport = uip_connr->rport;
+
+ uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+ uip_ipaddr_copy(BUF->destipaddr, uip_connr->ripaddr);
+
+ if(uip_connr->tcpstateflags & UIP_STOPPED) {
+ /* If the connection has issued uip_stop(), we advertise a zero
+ window so that the remote host will stop sending data. */
+ BUF->wnd[0] = BUF->wnd[1] = 0;
+ } else {
+ BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);
+ BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);
+ }
+
+ tcp_send_noconn:
+ BUF->ttl = UIP_TTL;
+#if UIP_CONF_IPV6
+ /* For IPv6, the IP length field does not include the IPv6 IP header
+ length. */
+ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
+ BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
+#else /* UIP_CONF_IPV6 */
+ BUF->len[0] = (uip_len >> 8);
+ BUF->len[1] = (uip_len & 0xff);
+#endif /* UIP_CONF_IPV6 */
+
+ BUF->urgp[0] = BUF->urgp[1] = 0;
+
+ /* Calculate TCP checksum. */
+ BUF->tcpchksum = 0;
+ BUF->tcpchksum = ~(uip_tcpchksum());
+
+ ip_send_nolen:
+
+#if UIP_CONF_IPV6
+ BUF->vtc = 0x60;
+ BUF->tcflow = 0x00;
+ BUF->flow = 0x00;
+#else /* UIP_CONF_IPV6 */
+ BUF->vhl = 0x45;
+ BUF->tos = 0;
+ BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
+ ++ipid;
+ BUF->ipid[0] = ipid >> 8;
+ BUF->ipid[1] = ipid & 0xff;
+ /* Calculate IP checksum. */
+ BUF->ipchksum = 0;
+ BUF->ipchksum = ~(uip_ipchksum());
+ DEBUG_PRINTF("uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum());
+#endif /* UIP_CONF_IPV6 */
+
+ UIP_STAT(++uip_stat.tcp.sent);
+ send:
+ DEBUG_PRINTF("Sending packet with length %d (%d)\n", uip_len,
+ (BUF->len[0] << 8) | BUF->len[1]);
+
+ UIP_STAT(++uip_stat.ip.sent);
+ /* Return and let the caller do the actual transmission. */
+ uip_flags = 0;
+ return;
+ drop:
+ uip_len = 0;
+ uip_flags = 0;
+ return;
+}
+/*---------------------------------------------------------------------------*/
+u16_t
+htons(u16_t val)
+{
+ return HTONS(val);
+}
+/*---------------------------------------------------------------------------*/
+void
+uip_send(const void *data, int len)
+{
+ if(len > 0) {
+ uip_slen = len;
+ if(data != uip_sappdata) {
+ memcpy(uip_sappdata, (data), uip_slen);
+ }
+ }
+}
+/** @} */
diff --git a/uip/uip/uip.h b/uip/uip/uip.h
new file mode 100644
index 0000000..2fed1f6
--- /dev/null
+++ b/uip/uip/uip.h
@@ -0,0 +1,1603 @@
+
+/**
+ * \addtogroup uip
+ * @{
+ */
+
+/**
+ * \file
+ * Header file for the uIP TCP/IP stack.
+ * \author Adam Dunkels <adam@dunkels.com>
+ *
+ * The uIP TCP/IP stack header file contains definitions for a number
+ * of C macros that are used by uIP programs as well as internal uIP
+ * structures, TCP/IP header structures and function declarations.
+ *
+ */
+
+
+/*
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: uip.h,v 1.40 2006/06/08 07:12:07 adam Exp $
+ *
+ */
+
+#ifndef __UIP_H__
+#define __UIP_H__
+
+#include "uipopt.h"
+
+/**
+ * Repressentation of an IP address.
+ *
+ */
+typedef u16_t uip_ip4addr_t[2];
+typedef u16_t uip_ip6addr_t[8];
+#if UIP_CONF_IPV6
+typedef uip_ip6addr_t uip_ipaddr_t;
+#else /* UIP_CONF_IPV6 */
+typedef uip_ip4addr_t uip_ipaddr_t;
+#endif /* UIP_CONF_IPV6 */
+
+/*---------------------------------------------------------------------------*/
+/* First, the functions that should be called from the
+ * system. Initialization, the periodic timer and incoming packets are
+ * handled by the following three functions.
+ */
+
+/**
+ * \defgroup uipconffunc uIP configuration functions
+ * @{
+ *
+ * The uIP configuration functions are used for setting run-time
+ * parameters in uIP such as IP addresses.
+ */
+
+/**
+ * Set the IP address of this host.
+ *
+ * The IP address is represented as a 4-byte array where the first
+ * octet of the IP address is put in the first member of the 4-byte
+ * array.
+ *
+ * Example:
+ \code
+
+ uip_ipaddr_t addr;
+
+ uip_ipaddr(&addr, 192,168,1,2);
+ uip_sethostaddr(&addr);
+
+ \endcode
+ * \param addr A pointer to an IP address of type uip_ipaddr_t;
+ *
+ * \sa uip_ipaddr()
+ *
+ * \hideinitializer
+ */
+#define uip_sethostaddr(addr) uip_ipaddr_copy(uip_hostaddr, (addr))
+
+/**
+ * Get the IP address of this host.
+ *
+ * The IP address is represented as a 4-byte array where the first
+ * octet of the IP address is put in the first member of the 4-byte
+ * array.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t hostaddr;
+
+ uip_gethostaddr(&hostaddr);
+ \endcode
+ * \param addr A pointer to a uip_ipaddr_t variable that will be
+ * filled in with the currently configured IP address.
+ *
+ * \hideinitializer
+ */
+#define uip_gethostaddr(addr) uip_ipaddr_copy((addr), uip_hostaddr)
+
+/**
+ * Set the default router's IP address.
+ *
+ * \param addr A pointer to a uip_ipaddr_t variable containing the IP
+ * address of the default router.
+ *
+ * \sa uip_ipaddr()
+ *
+ * \hideinitializer
+ */
+#define uip_setdraddr(addr) uip_ipaddr_copy(uip_draddr, (addr))
+
+/**
+ * Set the netmask.
+ *
+ * \param addr A pointer to a uip_ipaddr_t variable containing the IP
+ * address of the netmask.
+ *
+ * \sa uip_ipaddr()
+ *
+ * \hideinitializer
+ */
+#define uip_setnetmask(addr) uip_ipaddr_copy(uip_netmask, (addr))
+
+
+/**
+ * Get the default router's IP address.
+ *
+ * \param addr A pointer to a uip_ipaddr_t variable that will be
+ * filled in with the IP address of the default router.
+ *
+ * \hideinitializer
+ */
+#define uip_getdraddr(addr) uip_ipaddr_copy((addr), uip_draddr)
+
+/**
+ * Get the netmask.
+ *
+ * \param addr A pointer to a uip_ipaddr_t variable that will be
+ * filled in with the value of the netmask.
+ *
+ * \hideinitializer
+ */
+#define uip_getnetmask(addr) uip_ipaddr_copy((addr), uip_netmask)
+
+/** @} */
+
+/**
+ * \defgroup uipinit uIP initialization functions
+ * @{
+ *
+ * The uIP initialization functions are used for booting uIP.
+ */
+
+/**
+ * uIP initialization function.
+ *
+ * This function should be called at boot up to initilize the uIP
+ * TCP/IP stack.
+ */
+void uip_init(void);
+
+/**
+ * uIP initialization function.
+ *
+ * This function may be used at boot time to set the initial ip_id.
+ */
+void uip_setipid(u16_t id);
+
+/** @} */
+
+/**
+ * \defgroup uipdevfunc uIP device driver functions
+ * @{
+ *
+ * These functions are used by a network device driver for interacting
+ * with uIP.
+ */
+
+/**
+ * Process an incoming packet.
+ *
+ * This function should be called when the device driver has received
+ * a packet from the network. The packet from the device driver must
+ * be present in the uip_buf buffer, and the length of the packet
+ * should be placed in the uip_len variable.
+ *
+ * When the function returns, there may be an outbound packet placed
+ * in the uip_buf packet buffer. If so, the uip_len variable is set to
+ * the length of the packet. If no packet is to be sent out, the
+ * uip_len variable is set to 0.
+ *
+ * The usual way of calling the function is presented by the source
+ * code below.
+ \code
+ uip_len = devicedriver_poll();
+ if(uip_len > 0) {
+ uip_input();
+ if(uip_len > 0) {
+ devicedriver_send();
+ }
+ }
+ \endcode
+ *
+ * \note If you are writing a uIP device driver that needs ARP
+ * (Address Resolution Protocol), e.g., when running uIP over
+ * Ethernet, you will need to call the uIP ARP code before calling
+ * this function:
+ \code
+ #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
+ uip_len = ethernet_devicedrver_poll();
+ if(uip_len > 0) {
+ if(BUF->type == HTONS(UIP_ETHTYPE_IP)) {
+ uip_arp_ipin();
+ uip_input();
+ if(uip_len > 0) {
+ uip_arp_out();
+ ethernet_devicedriver_send();
+ }
+ } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) {
+ uip_arp_arpin();
+ if(uip_len > 0) {
+ ethernet_devicedriver_send();
+ }
+ }
+ \endcode
+ *
+ * \hideinitializer
+ */
+#define uip_input() uip_process(UIP_DATA)
+
+/**
+ * Periodic processing for a connection identified by its number.
+ *
+ * This function does the necessary periodic processing (timers,
+ * polling) for a uIP TCP conneciton, and should be called when the
+ * periodic uIP timer goes off. It should be called for every
+ * connection, regardless of whether they are open of closed.
+ *
+ * When the function returns, it may have an outbound packet waiting
+ * for service in the uIP packet buffer, and if so the uip_len
+ * variable is set to a value larger than zero. The device driver
+ * should be called to send out the packet.
+ *
+ * The ususal way of calling the function is through a for() loop like
+ * this:
+ \code
+ for(i = 0; i < UIP_CONNS; ++i) {
+ uip_periodic(i);
+ if(uip_len > 0) {
+ devicedriver_send();
+ }
+ }
+ \endcode
+ *
+ * \note If you are writing a uIP device driver that needs ARP
+ * (Address Resolution Protocol), e.g., when running uIP over
+ * Ethernet, you will need to call the uip_arp_out() function before
+ * calling the device driver:
+ \code
+ for(i = 0; i < UIP_CONNS; ++i) {
+ uip_periodic(i);
+ if(uip_len > 0) {
+ uip_arp_out();
+ ethernet_devicedriver_send();
+ }
+ }
+ \endcode
+ *
+ * \param conn The number of the connection which is to be periodically polled.
+ *
+ * \hideinitializer
+ */
+#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \
+ uip_process(UIP_TIMER); } while (0)
+
+/**
+ *
+ *
+ */
+#define uip_conn_active(conn) (uip_conns[conn].tcpstateflags != UIP_CLOSED)
+
+/**
+ * Perform periodic processing for a connection identified by a pointer
+ * to its structure.
+ *
+ * Same as uip_periodic() but takes a pointer to the actual uip_conn
+ * struct instead of an integer as its argument. This function can be
+ * used to force periodic processing of a specific connection.
+ *
+ * \param conn A pointer to the uip_conn struct for the connection to
+ * be processed.
+ *
+ * \hideinitializer
+ */
+#define uip_periodic_conn(conn) do { uip_conn = conn; \
+ uip_process(UIP_TIMER); } while (0)
+
+/**
+ * Reuqest that a particular connection should be polled.
+ *
+ * Similar to uip_periodic_conn() but does not perform any timer
+ * processing. The application is polled for new data.
+ *
+ * \param conn A pointer to the uip_conn struct for the connection to
+ * be processed.
+ *
+ * \hideinitializer
+ */
+#define uip_poll_conn(conn) do { uip_conn = conn; \
+ uip_process(UIP_POLL_REQUEST); } while (0)
+
+
+#if UIP_UDP
+/**
+ * Periodic processing for a UDP connection identified by its number.
+ *
+ * This function is essentially the same as uip_periodic(), but for
+ * UDP connections. It is called in a similar fashion as the
+ * uip_periodic() function:
+ \code
+ for(i = 0; i < UIP_UDP_CONNS; i++) {
+ uip_udp_periodic(i);
+ if(uip_len > 0) {
+ devicedriver_send();
+ }
+ }
+ \endcode
+ *
+ * \note As for the uip_periodic() function, special care has to be
+ * taken when using uIP together with ARP and Ethernet:
+ \code
+ for(i = 0; i < UIP_UDP_CONNS; i++) {
+ uip_udp_periodic(i);
+ if(uip_len > 0) {
+ uip_arp_out();
+ ethernet_devicedriver_send();
+ }
+ }
+ \endcode
+ *
+ * \param conn The number of the UDP connection to be processed.
+ *
+ * \hideinitializer
+ */
+#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \
+ uip_process(UIP_UDP_TIMER); } while (0)
+
+/**
+ * Periodic processing for a UDP connection identified by a pointer to
+ * its structure.
+ *
+ * Same as uip_udp_periodic() but takes a pointer to the actual
+ * uip_conn struct instead of an integer as its argument. This
+ * function can be used to force periodic processing of a specific
+ * connection.
+ *
+ * \param conn A pointer to the uip_udp_conn struct for the connection
+ * to be processed.
+ *
+ * \hideinitializer
+ */
+#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \
+ uip_process(UIP_UDP_TIMER); } while (0)
+
+
+#endif /* UIP_UDP */
+
+/**
+ * The uIP packet buffer.
+ *
+ * The uip_buf array is used to hold incoming and outgoing
+ * packets. The device driver should place incoming data into this
+ * buffer. When sending data, the device driver should read the link
+ * level headers and the TCP/IP headers from this buffer. The size of
+ * the link level headers is configured by the UIP_LLH_LEN define.
+ *
+ * \note The application data need not be placed in this buffer, so
+ * the device driver must read it from the place pointed to by the
+ * uip_appdata pointer as illustrated by the following example:
+ \code
+ void
+ devicedriver_send(void)
+ {
+ hwsend(&uip_buf[0], UIP_LLH_LEN);
+ if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) {
+ hwsend(&uip_buf[UIP_LLH_LEN], uip_len - UIP_LLH_LEN);
+ } else {
+ hwsend(&uip_buf[UIP_LLH_LEN], UIP_TCPIP_HLEN);
+ hwsend(uip_appdata, uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN);
+ }
+ }
+ \endcode
+ */
+extern u8_t uip_buf[UIP_BUFSIZE+2];
+
+/** @} */
+
+/*---------------------------------------------------------------------------*/
+/* Functions that are used by the uIP application program. Opening and
+ * closing connections, sending and receiving data, etc. is all
+ * handled by the functions below.
+*/
+/**
+ * \defgroup uipappfunc uIP application functions
+ * @{
+ *
+ * Functions used by an application running of top of uIP.
+ */
+
+#ifdef UIP_TCP_LISTEN
+/**
+ * Start listening to the specified port.
+ *
+ * \note Since this function expects the port number in network byte
+ * order, a conversion using HTONS() or htons() is necessary.
+ *
+ \code
+ uip_listen(HTONS(80));
+ \endcode
+ *
+ * \param port A 16-bit port number in network byte order.
+ */
+void uip_listen(u16_t port);
+
+/**
+ * Stop listening to the specified port.
+ *
+ * \note Since this function expects the port number in network byte
+ * order, a conversion using HTONS() or htons() is necessary.
+ *
+ \code
+ uip_unlisten(HTONS(80));
+ \endcode
+ *
+ * \param port A 16-bit port number in network byte order.
+ */
+void uip_unlisten(u16_t port);
+#endif
+
+/**
+ * Connect to a remote host using TCP.
+ *
+ * This function is used to start a new connection to the specified
+ * port on the specied host. It allocates a new connection identifier,
+ * sets the connection to the SYN_SENT state and sets the
+ * retransmission timer to 0. This will cause a TCP SYN segment to be
+ * sent out the next time this connection is periodically processed,
+ * which usually is done within 0.5 seconds after the call to
+ * uip_connect().
+ *
+ * \note This function is avaliable only if support for active open
+ * has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h.
+ *
+ * \note Since this function requires the port number to be in network
+ * byte order, a conversion using HTONS() or htons() is necessary.
+ *
+ \code
+ uip_ipaddr_t ipaddr;
+
+ uip_ipaddr(&ipaddr, 192,168,1,2);
+ uip_connect(&ipaddr, HTONS(80));
+ \endcode
+ *
+ * \param ripaddr The IP address of the remote hot.
+ *
+ * \param port A 16-bit port number in network byte order.
+ *
+ * \return A pointer to the uIP connection identifier for the new connection,
+ * or NULL if no connection could be allocated.
+ *
+ */
+struct uip_conn *uip_connect(uip_ipaddr_t *ripaddr, u16_t port);
+
+
+
+/**
+ * \internal
+ *
+ * Check if a connection has outstanding (i.e., unacknowledged) data.
+ *
+ * \param conn A pointer to the uip_conn structure for the connection.
+ *
+ * \hideinitializer
+ */
+#define uip_outstanding(conn) ((conn)->len)
+
+/**
+ * Send data on the current connection.
+ *
+ * This function is used to send out a single segment of TCP
+ * data. Only applications that have been invoked by uIP for event
+ * processing can send data.
+ *
+ * The amount of data that actually is sent out after a call to this
+ * funcion is determined by the maximum amount of data TCP allows. uIP
+ * will automatically crop the data so that only the appropriate
+ * amount of data is sent. The function uip_mss() can be used to query
+ * uIP for the amount of data that actually will be sent.
+ *
+ * \note This function does not guarantee that the sent data will
+ * arrive at the destination. If the data is lost in the network, the
+ * application will be invoked with the uip_rexmit() event being
+ * set. The application will then have to resend the data using this
+ * function.
+ *
+ * \param data A pointer to the data which is to be sent.
+ *
+ * \param len The maximum amount of data bytes to be sent.
+ *
+ * \hideinitializer
+ */
+void uip_send(const void *data, int len);
+
+/**
+ * The length of any incoming data that is currently avaliable (if avaliable)
+ * in the uip_appdata buffer.
+ *
+ * The test function uip_data() must first be used to check if there
+ * is any data available at all.
+ *
+ * \hideinitializer
+ */
+/*void uip_datalen(void);*/
+#define uip_datalen() uip_len
+
+/**
+ * The length of any out-of-band data (urgent data) that has arrived
+ * on the connection.
+ *
+ * \note The configuration parameter UIP_URGDATA must be set for this
+ * function to be enabled.
+ *
+ * \hideinitializer
+ */
+#define uip_urgdatalen() uip_urglen
+
+/**
+ * Close the current connection.
+ *
+ * This function will close the current connection in a nice way.
+ *
+ * \hideinitializer
+ */
+#define uip_close() (uip_flags = UIP_CLOSE)
+
+/**
+ * Abort the current connection.
+ *
+ * This function will abort (reset) the current connection, and is
+ * usually used when an error has occured that prevents using the
+ * uip_close() function.
+ *
+ * \hideinitializer
+ */
+#define uip_abort() (uip_flags = UIP_ABORT)
+
+/**
+ * Tell the sending host to stop sending data.
+ *
+ * This function will close our receiver's window so that we stop
+ * receiving data for the current connection.
+ *
+ * \hideinitializer
+ */
+#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED)
+
+/**
+ * Find out if the current connection has been previously stopped with
+ * uip_stop().
+ *
+ * \hideinitializer
+ */
+#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED)
+
+/**
+ * Restart the current connection, if is has previously been stopped
+ * with uip_stop().
+ *
+ * This function will open the receiver's window again so that we
+ * start receiving data for the current connection.
+ *
+ * \hideinitializer
+ */
+#define uip_restart() do { uip_flags |= UIP_NEWDATA; \
+ uip_conn->tcpstateflags &= ~UIP_STOPPED; \
+ } while(0)
+
+
+/* uIP tests that can be made to determine in what state the current
+ connection is, and what the application function should do. */
+
+/**
+ * Is the current connection a UDP connection?
+ *
+ * This function checks whether the current connection is a UDP connection.
+ *
+ * \hideinitializer
+ *
+ */
+#define uip_udpconnection() (uip_conn == NULL)
+
+/**
+ * Is new incoming data available?
+ *
+ * Will reduce to non-zero if there is new data for the application
+ * present at the uip_appdata pointer. The size of the data is
+ * avaliable through the uip_len variable.
+ *
+ * \hideinitializer
+ */
+#define uip_newdata() (uip_flags & UIP_NEWDATA)
+
+/**
+ * Has previously sent data been acknowledged?
+ *
+ * Will reduce to non-zero if the previously sent data has been
+ * acknowledged by the remote host. This means that the application
+ * can send new data.
+ *
+ * \hideinitializer
+ */
+#define uip_acked() (uip_flags & UIP_ACKDATA)
+
+/**
+ * Has the connection just been connected?
+ *
+ * Reduces to non-zero if the current connection has been connected to
+ * a remote host. This will happen both if the connection has been
+ * actively opened (with uip_connect()) or passively opened (with
+ * uip_listen()).
+ *
+ * \hideinitializer
+ */
+#define uip_connected() (uip_flags & UIP_CONNECTED)
+
+/**
+ * Has the connection been closed by the other end?
+ *
+ * Is non-zero if the connection has been closed by the remote
+ * host. The application may then do the necessary clean-ups.
+ *
+ * \hideinitializer
+ */
+#define uip_closed() (uip_flags & UIP_CLOSE)
+
+/**
+ * Has the connection been aborted by the other end?
+ *
+ * Non-zero if the current connection has been aborted (reset) by the
+ * remote host.
+ *
+ * \hideinitializer
+ */
+#define uip_aborted() (uip_flags & UIP_ABORT)
+
+/**
+ * Has the connection timed out?
+ *
+ * Non-zero if the current connection has been aborted due to too many
+ * retransmissions.
+ *
+ * \hideinitializer
+ */
+#define uip_timedout() (uip_flags & UIP_TIMEDOUT)
+
+/**
+ * Do we need to retransmit previously data?
+ *
+ * Reduces to non-zero if the previously sent data has been lost in
+ * the network, and the application should retransmit it. The
+ * application should send the exact same data as it did the last
+ * time, using the uip_send() function.
+ *
+ * \hideinitializer
+ */
+#define uip_rexmit() (uip_flags & UIP_REXMIT)
+
+/**
+ * Is the connection being polled by uIP?
+ *
+ * Is non-zero if the reason the application is invoked is that the
+ * current connection has been idle for a while and should be
+ * polled.
+ *
+ * The polling event can be used for sending data without having to
+ * wait for the remote host to send data.
+ *
+ * \hideinitializer
+ */
+#define uip_poll() (uip_flags & UIP_POLL)
+
+/**
+ * Get the initial maxium segment size (MSS) of the current
+ * connection.
+ *
+ * \hideinitializer
+ */
+#define uip_initialmss() (uip_conn->initialmss)
+
+/**
+ * Get the current maxium segment size that can be sent on the current
+ * connection.
+ *
+ * The current maxiumum segment size that can be sent on the
+ * connection is computed from the receiver's window and the MSS of
+ * the connection (which also is available by calling
+ * uip_initialmss()).
+ *
+ * \hideinitializer
+ */
+#define uip_mss() (uip_conn->mss)
+
+/**
+ * Set up a new UDP connection.
+ *
+ * This function sets up a new UDP connection. The function will
+ * automatically allocate an unused local port for the new
+ * connection. However, another port can be chosen by using the
+ * uip_udp_bind() call, after the uip_udp_new() function has been
+ * called.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t addr;
+ struct uip_udp_conn *c;
+
+ uip_ipaddr(&addr, 192,168,2,1);
+ c = uip_udp_new(&addr, HTONS(12345));
+ if(c != NULL) {
+ uip_udp_bind(c, HTONS(12344));
+ }
+ \endcode
+ * \param ripaddr The IP address of the remote host.
+ *
+ * \param rport The remote port number in network byte order.
+ *
+ * \return The uip_udp_conn structure for the new connection or NULL
+ * if no connection could be allocated.
+ */
+struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
+
+/**
+ * Removed a UDP connection.
+ *
+ * \param conn A pointer to the uip_udp_conn structure for the connection.
+ *
+ * \hideinitializer
+ */
+#define uip_udp_remove(conn) (conn)->lport = 0
+
+/**
+ * Bind a UDP connection to a local port.
+ *
+ * \param conn A pointer to the uip_udp_conn structure for the
+ * connection.
+ *
+ * \param port The local port number, in network byte order.
+ *
+ * \hideinitializer
+ */
+#define uip_udp_bind(conn, port) (conn)->lport = port
+
+/**
+ * Send a UDP datagram of length len on the current connection.
+ *
+ * This function can only be called in response to a UDP event (poll
+ * or newdata). The data must be present in the uip_buf buffer, at the
+ * place pointed to by the uip_appdata pointer.
+ *
+ * \param len The length of the data in the uip_buf buffer.
+ *
+ * \hideinitializer
+ */
+#define uip_udp_send(len) uip_send((char *)uip_appdata, len)
+
+/** @} */
+
+/* uIP convenience and converting functions. */
+
+/**
+ * \defgroup uipconvfunc uIP conversion functions
+ * @{
+ *
+ * These functions can be used for converting between different data
+ * formats used by uIP.
+ */
+
+/**
+ * Construct an IP address from four bytes.
+ *
+ * This function constructs an IP address of the type that uIP handles
+ * internally from four bytes. The function is handy for specifying IP
+ * addresses to use with e.g. the uip_connect() function.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr;
+ struct uip_conn *c;
+
+ uip_ipaddr(&ipaddr, 192,168,1,2);
+ c = uip_connect(&ipaddr, HTONS(80));
+ \endcode
+ *
+ * \param addr A pointer to a uip_ipaddr_t variable that will be
+ * filled in with the IP address.
+ *
+ * \param addr0 The first octet of the IP address.
+ * \param addr1 The second octet of the IP address.
+ * \param addr2 The third octet of the IP address.
+ * \param addr3 The forth octet of the IP address.
+ *
+ * \hideinitializer
+ */
+#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \
+ ((u16_t *)(addr))[0] = HTONS(((addr0) << 8) | (addr1)); \
+ ((u16_t *)(addr))[1] = HTONS(((addr2) << 8) | (addr3)); \
+ } while(0)
+
+/**
+ * Construct an IPv6 address from eight 16-bit words.
+ *
+ * This function constructs an IPv6 address.
+ *
+ * \hideinitializer
+ */
+#define uip_ip6addr(addr, addr0,addr1,addr2,addr3,addr4,addr5,addr6,addr7) do { \
+ ((u16_t *)(addr))[0] = HTONS((addr0)); \
+ ((u16_t *)(addr))[1] = HTONS((addr1)); \
+ ((u16_t *)(addr))[2] = HTONS((addr2)); \
+ ((u16_t *)(addr))[3] = HTONS((addr3)); \
+ ((u16_t *)(addr))[4] = HTONS((addr4)); \
+ ((u16_t *)(addr))[5] = HTONS((addr5)); \
+ ((u16_t *)(addr))[6] = HTONS((addr6)); \
+ ((u16_t *)(addr))[7] = HTONS((addr7)); \
+ } while(0)
+
+/**
+ * Copy an IP address to another IP address.
+ *
+ * Copies an IP address from one place to another.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr1, ipaddr2;
+
+ uip_ipaddr(&ipaddr1, 192,16,1,2);
+ uip_ipaddr_copy(&ipaddr2, &ipaddr1);
+ \endcode
+ *
+ * \param dest The destination for the copy.
+ * \param src The source from where to copy.
+ *
+ * \hideinitializer
+ */
+#if !UIP_CONF_IPV6
+#define uip_ipaddr_copy(dest, src) do { \
+ ((u16_t *)dest)[0] = ((u16_t *)src)[0]; \
+ ((u16_t *)dest)[1] = ((u16_t *)src)[1]; \
+ } while(0)
+#else /* !UIP_CONF_IPV6 */
+#define uip_ipaddr_copy(dest, src) memcpy(dest, src, sizeof(uip_ip6addr_t))
+#endif /* !UIP_CONF_IPV6 */
+
+/**
+ * Compare two IP addresses
+ *
+ * Compares two IP addresses.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr1, ipaddr2;
+
+ uip_ipaddr(&ipaddr1, 192,16,1,2);
+ if(uip_ipaddr_cmp(&ipaddr2, &ipaddr1)) {
+ printf("They are the same");
+ }
+ \endcode
+ *
+ * \param addr1 The first IP address.
+ * \param addr2 The second IP address.
+ *
+ * \hideinitializer
+ */
+#if !UIP_CONF_IPV6
+#define uip_ipaddr_cmp(addr1, addr2) (((u16_t *)addr1)[0] == ((u16_t *)addr2)[0] && \
+ ((u16_t *)addr1)[1] == ((u16_t *)addr2)[1])
+#else /* !UIP_CONF_IPV6 */
+#define uip_ipaddr_cmp(addr1, addr2) (memcmp(addr1, addr2, sizeof(uip_ip6addr_t)) == 0)
+#endif /* !UIP_CONF_IPV6 */
+
+/**
+ * Compare two IP addresses with netmasks
+ *
+ * Compares two IP addresses with netmasks. The masks are used to mask
+ * out the bits that are to be compared.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr1, ipaddr2, mask;
+
+ uip_ipaddr(&mask, 255,255,255,0);
+ uip_ipaddr(&ipaddr1, 192,16,1,2);
+ uip_ipaddr(&ipaddr2, 192,16,1,3);
+ if(uip_ipaddr_maskcmp(&ipaddr1, &ipaddr2, &mask)) {
+ printf("They are the same");
+ }
+ \endcode
+ *
+ * \param addr1 The first IP address.
+ * \param addr2 The second IP address.
+ * \param mask The netmask.
+ *
+ * \hideinitializer
+ */
+#define uip_ipaddr_maskcmp(addr1, addr2, mask) \
+ (((((u16_t *)addr1)[0] & ((u16_t *)mask)[0]) == \
+ (((u16_t *)addr2)[0] & ((u16_t *)mask)[0])) && \
+ ((((u16_t *)addr1)[1] & ((u16_t *)mask)[1]) == \
+ (((u16_t *)addr2)[1] & ((u16_t *)mask)[1])))
+
+
+/**
+ * Mask out the network part of an IP address.
+ *
+ * Masks out the network part of an IP address, given the address and
+ * the netmask.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr1, ipaddr2, netmask;
+
+ uip_ipaddr(&ipaddr1, 192,16,1,2);
+ uip_ipaddr(&netmask, 255,255,255,0);
+ uip_ipaddr_mask(&ipaddr2, &ipaddr1, &netmask);
+ \endcode
+ *
+ * In the example above, the variable "ipaddr2" will contain the IP
+ * address 192.168.1.0.
+ *
+ * \param dest Where the result is to be placed.
+ * \param src The IP address.
+ * \param mask The netmask.
+ *
+ * \hideinitializer
+ */
+#define uip_ipaddr_mask(dest, src, mask) do { \
+ ((u16_t *)dest)[0] = ((u16_t *)src)[0] & ((u16_t *)mask)[0]; \
+ ((u16_t *)dest)[1] = ((u16_t *)src)[1] & ((u16_t *)mask)[1]; \
+ } while(0)
+
+/**
+ * Pick the first octet of an IP address.
+ *
+ * Picks out the first octet of an IP address.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr;
+ u8_t octet;
+
+ uip_ipaddr(&ipaddr, 1,2,3,4);
+ octet = uip_ipaddr1(&ipaddr);
+ \endcode
+ *
+ * In the example above, the variable "octet" will contain the value 1.
+ *
+ * \hideinitializer
+ */
+#define uip_ipaddr1(addr) (htons(((u16_t *)(addr))[0]) >> 8)
+
+/**
+ * Pick the second octet of an IP address.
+ *
+ * Picks out the second octet of an IP address.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr;
+ u8_t octet;
+
+ uip_ipaddr(&ipaddr, 1,2,3,4);
+ octet = uip_ipaddr2(&ipaddr);
+ \endcode
+ *
+ * In the example above, the variable "octet" will contain the value 2.
+ *
+ * \hideinitializer
+ */
+#define uip_ipaddr2(addr) (htons(((u16_t *)(addr))[0]) & 0xff)
+
+/**
+ * Pick the third octet of an IP address.
+ *
+ * Picks out the third octet of an IP address.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr;
+ u8_t octet;
+
+ uip_ipaddr(&ipaddr, 1,2,3,4);
+ octet = uip_ipaddr3(&ipaddr);
+ \endcode
+ *
+ * In the example above, the variable "octet" will contain the value 3.
+ *
+ * \hideinitializer
+ */
+#define uip_ipaddr3(addr) (htons(((u16_t *)(addr))[1]) >> 8)
+
+/**
+ * Pick the fourth octet of an IP address.
+ *
+ * Picks out the fourth octet of an IP address.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr;
+ u8_t octet;
+
+ uip_ipaddr(&ipaddr, 1,2,3,4);
+ octet = uip_ipaddr4(&ipaddr);
+ \endcode
+ *
+ * In the example above, the variable "octet" will contain the value 4.
+ *
+ * \hideinitializer
+ */
+#define uip_ipaddr4(addr) (htons(((u16_t *)(addr))[1]) & 0xff)
+
+/**
+ * Convert 16-bit quantity from host byte order to network byte order.
+ *
+ * This macro is primarily used for converting constants from host
+ * byte order to network byte order. For converting variables to
+ * network byte order, use the htons() function instead.
+ *
+ * \hideinitializer
+ */
+#ifndef HTONS
+# if UIP_BYTE_ORDER == UIP_BIG_ENDIAN
+# define HTONS(n) (n)
+# else /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */
+# define HTONS(n) (u16_t)((((u16_t) (n)) << 8) | (((u16_t) (n)) >> 8))
+# endif /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */
+#else
+#error "HTONS already defined!"
+#endif /* HTONS */
+
+/**
+ * Convert 16-bit quantity from host byte order to network byte order.
+ *
+ * This function is primarily used for converting variables from host
+ * byte order to network byte order. For converting constants to
+ * network byte order, use the HTONS() macro instead.
+ */
+#ifndef htons
+u16_t htons(u16_t val);
+#endif /* htons */
+#ifndef ntohs
+#define ntohs htons
+#endif
+
+/** @} */
+
+/**
+ * Pointer to the application data in the packet buffer.
+ *
+ * This pointer points to the application data when the application is
+ * called. If the application wishes to send data, the application may
+ * use this space to write the data into before calling uip_send().
+ */
+extern void *uip_appdata;
+
+#if UIP_URGDATA > 0
+/* u8_t *uip_urgdata:
+ *
+ * This pointer points to any urgent data that has been received. Only
+ * present if compiled with support for urgent data (UIP_URGDATA).
+ */
+extern void *uip_urgdata;
+#endif /* UIP_URGDATA > 0 */
+
+
+/**
+ * \defgroup uipdrivervars Variables used in uIP device drivers
+ * @{
+ *
+ * uIP has a few global variables that are used in device drivers for
+ * uIP.
+ */
+
+/**
+ * The length of the packet in the uip_buf buffer.
+ *
+ * The global variable uip_len holds the length of the packet in the
+ * uip_buf buffer.
+ *
+ * When the network device driver calls the uIP input function,
+ * uip_len should be set to the length of the packet in the uip_buf
+ * buffer.
+ *
+ * When sending packets, the device driver should use the contents of
+ * the uip_len variable to determine the length of the outgoing
+ * packet.
+ *
+ */
+extern u16_t uip_len;
+
+/** @} */
+
+#if UIP_URGDATA > 0
+extern u16_t uip_urglen, uip_surglen;
+#endif /* UIP_URGDATA > 0 */
+
+
+/**
+ * Representation of a uIP TCP connection.
+ *
+ * The uip_conn structure is used for identifying a connection. All
+ * but one field in the structure are to be considered read-only by an
+ * application. The only exception is the appstate field whos purpose
+ * is to let the application store application-specific state (e.g.,
+ * file pointers) for the connection. The type of this field is
+ * configured in the "uipopt.h" header file.
+ */
+struct uip_conn {
+ uip_ipaddr_t ripaddr; /**< The IP address of the remote host. */
+
+ u16_t lport; /**< The local TCP port, in network byte order. */
+ u16_t rport; /**< The local remote TCP port, in network byte
+ order. */
+
+ u8_t rcv_nxt[4]; /**< The sequence number that we expect to
+ receive next. */
+ u8_t snd_nxt[4]; /**< The sequence number that was last sent by
+ us. */
+ u16_t len; /**< Length of the data that was previously sent. */
+ u16_t mss; /**< Current maximum segment size for the
+ connection. */
+ u16_t initialmss; /**< Initial maximum segment size for the
+ connection. */
+ u8_t sa; /**< Retransmission time-out calculation state
+ variable. */
+ u8_t sv; /**< Retransmission time-out calculation state
+ variable. */
+ u8_t rto; /**< Retransmission time-out. */
+ u8_t tcpstateflags; /**< TCP state and flags. */
+ u8_t timer; /**< The retransmission timer. */
+ u8_t nrtx; /**< The number of retransmissions for the last
+ segment sent. */
+
+ /** The application state. */
+ uip_tcp_appstate_t appstate;
+};
+
+
+/**
+ * Pointer to the current TCP connection.
+ *
+ * The uip_conn pointer can be used to access the current TCP
+ * connection.
+ */
+extern struct uip_conn *uip_conn;
+/* The array containing all uIP connections. */
+extern struct uip_conn uip_conns[UIP_CONNS];
+/**
+ * \addtogroup uiparch
+ * @{
+ */
+
+/**
+ * 4-byte array used for the 32-bit sequence number calculations.
+ */
+extern u8_t uip_acc32[4];
+
+/** @} */
+
+
+#if UIP_UDP
+/**
+ * Representation of a uIP UDP connection.
+ */
+struct uip_udp_conn {
+ uip_ipaddr_t ripaddr; /**< The IP address of the remote peer. */
+ u16_t lport; /**< The local port number in network byte order. */
+ u16_t rport; /**< The remote port number in network byte order. */
+ u8_t ttl; /**< Default time-to-live. */
+
+ /** The application state. */
+ uip_udp_appstate_t appstate;
+};
+
+/**
+ * The current UDP connection.
+ */
+extern struct uip_udp_conn *uip_udp_conn;
+extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
+#endif /* UIP_UDP */
+
+/**
+ * The structure holding the TCP/IP statistics that are gathered if
+ * UIP_STATISTICS is set to 1.
+ *
+ */
+struct uip_stats {
+ struct {
+ uip_stats_t drop; /**< Number of dropped packets at the IP
+ layer. */
+ uip_stats_t recv; /**< Number of received packets at the IP
+ layer. */
+ uip_stats_t sent; /**< Number of sent packets at the IP
+ layer. */
+ uip_stats_t vhlerr; /**< Number of packets dropped due to wrong
+ IP version or header length. */
+ uip_stats_t hblenerr; /**< Number of packets dropped due to wrong
+ IP length, high byte. */
+ uip_stats_t lblenerr; /**< Number of packets dropped due to wrong
+ IP length, low byte. */
+ uip_stats_t fragerr; /**< Number of packets dropped since they
+ were IP fragments. */
+ uip_stats_t chkerr; /**< Number of packets dropped due to IP
+ checksum errors. */
+ uip_stats_t protoerr; /**< Number of packets dropped since they
+ were neither ICMP, UDP nor TCP. */
+ } ip; /**< IP statistics. */
+ struct {
+ uip_stats_t drop; /**< Number of dropped ICMP packets. */
+ uip_stats_t recv; /**< Number of received ICMP packets. */
+ uip_stats_t sent; /**< Number of sent ICMP packets. */
+ uip_stats_t typeerr; /**< Number of ICMP packets with a wrong
+ type. */
+ } icmp; /**< ICMP statistics. */
+ struct {
+ uip_stats_t drop; /**< Number of dropped TCP segments. */
+ uip_stats_t recv; /**< Number of recived TCP segments. */
+ uip_stats_t sent; /**< Number of sent TCP segments. */
+ uip_stats_t chkerr; /**< Number of TCP segments with a bad
+ checksum. */
+ uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK
+ number. */
+ uip_stats_t rst; /**< Number of recevied TCP RST (reset) segments. */
+ uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */
+ uip_stats_t syndrop; /**< Number of dropped SYNs due to too few
+ connections was avaliable. */
+ uip_stats_t synrst; /**< Number of SYNs for closed ports,
+ triggering a RST. */
+ } tcp; /**< TCP statistics. */
+#if UIP_UDP
+ struct {
+ uip_stats_t drop; /**< Number of dropped UDP segments. */
+ uip_stats_t recv; /**< Number of recived UDP segments. */
+ uip_stats_t sent; /**< Number of sent UDP segments. */
+ uip_stats_t chkerr; /**< Number of UDP segments with a bad
+ checksum. */
+ } udp; /**< UDP statistics. */
+#endif /* UIP_UDP */
+};
+
+/**
+ * The uIP TCP/IP statistics.
+ *
+ * This is the variable in which the uIP TCP/IP statistics are gathered.
+ */
+extern struct uip_stats uip_stat;
+
+
+/*---------------------------------------------------------------------------*/
+/* All the stuff below this point is internal to uIP and should not be
+ * used directly by an application or by a device driver.
+ */
+/*---------------------------------------------------------------------------*/
+/* u8_t uip_flags:
+ *
+ * When the application is called, uip_flags will contain the flags
+ * that are defined in this file. Please read below for more
+ * infomation.
+ */
+extern u8_t uip_flags;
+
+/* The following flags may be set in the global variable uip_flags
+ before calling the application callback. The UIP_ACKDATA,
+ UIP_NEWDATA, and UIP_CLOSE flags may both be set at the same time,
+ whereas the others are mutualy exclusive. Note that these flags
+ should *NOT* be accessed directly, but only through the uIP
+ functions/macros. */
+
+#define UIP_ACKDATA 1 /* Signifies that the outstanding data was
+ acked and the application should send
+ out new data instead of retransmitting
+ the last data. */
+#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent
+ us new data. */
+#define UIP_REXMIT 4 /* Tells the application to retransmit the
+ data that was last sent. */
+#define UIP_POLL 8 /* Used for polling the application, to
+ check if the application has data that
+ it wants to send. */
+#define UIP_CLOSE 16 /* The remote host has closed the
+ connection, thus the connection has
+ gone away. Or the application signals
+ that it wants to close the
+ connection. */
+#define UIP_ABORT 32 /* The remote host has aborted the
+ connection, thus the connection has
+ gone away. Or the application signals
+ that it wants to abort the
+ connection. */
+#define UIP_CONNECTED 64 /* We have got a connection from a remote
+ host and have set up a new connection
+ for it, or an active connection has
+ been successfully established. */
+
+#define UIP_TIMEDOUT 128 /* The connection has been aborted due to
+ too many retransmissions. */
+
+/* uip_process(flag):
+ *
+ * The actual uIP function which does all the work.
+ */
+void uip_process(u8_t flag);
+
+/* The following flags are passed as an argument to the uip_process()
+ function. They are used to distinguish between the two cases where
+ uip_process() is called. It can be called either because we have
+ incoming data that should be processed, or because the periodic
+ timer has fired. These values are never used directly, but only in
+ the macrose defined in this file. */
+
+#define UIP_DATA 1 /* Tells uIP that there is incoming
+ data in the uip_buf buffer. The
+ length of the data is stored in the
+ global variable uip_len. */
+#define UIP_TIMER 2 /* Tells uIP that the periodic timer
+ has fired. */
+#define UIP_POLL_REQUEST 3 /* Tells uIP that a connection should
+ be polled. */
+#define UIP_UDP_SEND_CONN 4 /* Tells uIP that a UDP datagram
+ should be constructed in the
+ uip_buf buffer. */
+#if UIP_UDP
+#define UIP_UDP_TIMER 5
+#endif /* UIP_UDP */
+
+/* The TCP states used in the uip_conn->tcpstateflags. */
+#define UIP_CLOSED 0
+#define UIP_SYN_RCVD 1
+#define UIP_SYN_SENT 2
+#define UIP_ESTABLISHED 3
+#define UIP_FIN_WAIT_1 4
+#define UIP_FIN_WAIT_2 5
+#define UIP_CLOSING 6
+#define UIP_TIME_WAIT 7
+#define UIP_LAST_ACK 8
+#define UIP_TS_MASK 15
+
+#define UIP_STOPPED 16
+
+/* The TCP and IP headers. */
+struct uip_tcpip_hdr {
+#if UIP_CONF_IPV6
+ /* IPv6 header. */
+ u8_t vtc,
+ tcflow;
+ u16_t flow;
+ u8_t len[2];
+ u8_t proto, ttl;
+ uip_ip6addr_t srcipaddr, destipaddr;
+#else /* UIP_CONF_IPV6 */
+ /* IPv4 header. */
+ u8_t vhl,
+ tos,
+ len[2],
+ ipid[2],
+ ipoffset[2],
+ ttl,
+ proto;
+ u16_t ipchksum;
+ u16_t srcipaddr[2],
+ destipaddr[2];
+#endif /* UIP_CONF_IPV6 */
+
+ /* TCP header. */
+ u16_t srcport,
+ destport;
+ u8_t seqno[4],
+ ackno[4],
+ tcpoffset,
+ flags,
+ wnd[2];
+ u16_t tcpchksum;
+ u8_t urgp[2];
+ u8_t optdata[4];
+};
+
+/* The ICMP and IP headers. */
+struct uip_icmpip_hdr {
+#if UIP_CONF_IPV6
+ /* IPv6 header. */
+ u8_t vtc,
+ tcf;
+ u16_t flow;
+ u8_t len[2];
+ u8_t proto, ttl;
+ uip_ip6addr_t srcipaddr, destipaddr;
+#else /* UIP_CONF_IPV6 */
+ /* IPv4 header. */
+ u8_t vhl,
+ tos,
+ len[2],
+ ipid[2],
+ ipoffset[2],
+ ttl,
+ proto;
+ u16_t ipchksum;
+ u16_t srcipaddr[2],
+ destipaddr[2];
+#endif /* UIP_CONF_IPV6 */
+
+ /* ICMP (echo) header. */
+ u8_t type, icode;
+ u16_t icmpchksum;
+#if !UIP_CONF_IPV6
+ u16_t id, seqno;
+#else /* !UIP_CONF_IPV6 */
+ u8_t flags, reserved1, reserved2, reserved3;
+ u8_t icmp6data[16];
+ u8_t options[1];
+#endif /* !UIP_CONF_IPV6 */
+};
+
+
+/* The UDP and IP headers. */
+struct uip_udpip_hdr {
+#if UIP_CONF_IPV6
+ /* IPv6 header. */
+ u8_t vtc,
+ tcf;
+ u16_t flow;
+ u8_t len[2];
+ u8_t proto, ttl;
+ uip_ip6addr_t srcipaddr, destipaddr;
+#else /* UIP_CONF_IPV6 */
+ /* IP header. */
+ u8_t vhl,
+ tos,
+ len[2],
+ ipid[2],
+ ipoffset[2],
+ ttl,
+ proto;
+ u16_t ipchksum;
+ u16_t srcipaddr[2],
+ destipaddr[2];
+#endif /* UIP_CONF_IPV6 */
+
+ /* UDP header. */
+ u16_t srcport,
+ destport;
+ u16_t udplen;
+ u16_t udpchksum;
+};
+
+
+
+/**
+ * The buffer size available for user data in the \ref uip_buf buffer.
+ *
+ * This macro holds the available size for user data in the \ref
+ * uip_buf buffer. The macro is intended to be used for checking
+ * bounds of available user data.
+ *
+ * Example:
+ \code
+ snprintf(uip_appdata, UIP_APPDATA_SIZE, "%u\n", i);
+ \endcode
+ *
+ * \hideinitializer
+ */
+#define UIP_APPDATA_SIZE (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN)
+
+
+#define UIP_PROTO_ICMP 1
+#define UIP_PROTO_TCP 6
+#define UIP_PROTO_UDP 17
+#define UIP_PROTO_ICMP6 58
+
+/* Header sizes. */
+#if UIP_CONF_IPV6
+#define UIP_IPH_LEN 40
+#else /* UIP_CONF_IPV6 */
+#define UIP_IPH_LEN 20 /* Size of IP header */
+#endif /* UIP_CONF_IPV6 */
+#define UIP_UDPH_LEN 8 /* Size of UDP header */
+#define UIP_TCPH_LEN 20 /* Size of TCP header */
+#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP +
+ UDP
+ header */
+#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP +
+ TCP
+ header */
+#define UIP_TCPIP_HLEN UIP_IPTCPH_LEN
+
+
+#if UIP_FIXEDADDR
+extern const uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr;
+#else /* UIP_FIXEDADDR */
+extern uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr;
+#endif /* UIP_FIXEDADDR */
+
+
+
+/**
+ * Representation of a 48-bit Ethernet address.
+ */
+struct uip_eth_addr {
+ u8_t addr[6];
+};
+
+/**
+ * Calculate the Internet checksum over a buffer.
+ *
+ * The Internet checksum is the one's complement of the one's
+ * complement sum of all 16-bit words in the buffer.
+ *
+ * See RFC1071.
+ *
+ * \param buf A pointer to the buffer over which the checksum is to be
+ * computed.
+ *
+ * \param len The length of the buffer over which the checksum is to
+ * be computed.
+ *
+ * \return The Internet checksum of the buffer.
+ */
+u16_t uip_chksum(u16_t *buf, u16_t len);
+
+/**
+ * Calculate the IP header checksum of the packet header in uip_buf.
+ *
+ * The IP header checksum is the Internet checksum of the 20 bytes of
+ * the IP header.
+ *
+ * \return The IP header checksum of the IP header in the uip_buf
+ * buffer.
+ */
+u16_t uip_ipchksum(void);
+
+/**
+ * Calculate the TCP checksum of the packet in uip_buf and uip_appdata.
+ *
+ * The TCP checksum is the Internet checksum of data contents of the
+ * TCP segment, and a pseudo-header as defined in RFC793.
+ *
+ * \return The TCP checksum of the TCP segment in uip_buf and pointed
+ * to by uip_appdata.
+ */
+u16_t uip_tcpchksum(void);
+
+/**
+ * Calculate the UDP checksum of the packet in uip_buf and uip_appdata.
+ *
+ * The UDP checksum is the Internet checksum of data contents of the
+ * UDP segment, and a pseudo-header as defined in RFC768.
+ *
+ * \return The UDP checksum of the UDP segment in uip_buf and pointed
+ * to by uip_appdata.
+ */
+u16_t uip_udpchksum(void);
+
+
+#endif /* __UIP_H__ */
+
+
+/** @} */
diff --git a/uip/uip/uip_arch.h b/uip/uip/uip_arch.h
new file mode 100644
index 0000000..71fd84b
--- /dev/null
+++ b/uip/uip/uip_arch.h
@@ -0,0 +1,138 @@
+/**
+ * \addtogroup uip
+ * {@
+ */
+
+/**
+ * \defgroup uiparch Architecture specific uIP functions
+ * @{
+ *
+ * The functions in the architecture specific module implement the IP
+ * check sum and 32-bit additions.
+ *
+ * The IP checksum calculation is the most computationally expensive
+ * operation in the TCP/IP stack and it therefore pays off to
+ * implement this in efficient assembler. The purpose of the uip-arch
+ * module is to let the checksum functions to be implemented in
+ * architecture specific assembler.
+ *
+ */
+
+/**
+ * \file
+ * Declarations of architecture specific functions.
+ * \author Adam Dunkels <adam@dunkels.com>
+ */
+
+/*
+ * Copyright (c) 2001, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: uip_arch.h,v 1.2 2006/06/07 09:15:19 adam Exp $
+ *
+ */
+
+#ifndef __UIP_ARCH_H__
+#define __UIP_ARCH_H__
+
+#include "uip.h"
+
+/**
+ * Carry out a 32-bit addition.
+ *
+ * Because not all architectures for which uIP is intended has native
+ * 32-bit arithmetic, uIP uses an external C function for doing the
+ * required 32-bit additions in the TCP protocol processing. This
+ * function should add the two arguments and place the result in the
+ * global variable uip_acc32.
+ *
+ * \note The 32-bit integer pointed to by the op32 parameter and the
+ * result in the uip_acc32 variable are in network byte order (big
+ * endian).
+ *
+ * \param op32 A pointer to a 4-byte array representing a 32-bit
+ * integer in network byte order (big endian).
+ *
+ * \param op16 A 16-bit integer in host byte order.
+ */
+void uip_add32(u8_t *op32, u16_t op16);
+
+/**
+ * Calculate the Internet checksum over a buffer.
+ *
+ * The Internet checksum is the one's complement of the one's
+ * complement sum of all 16-bit words in the buffer.
+ *
+ * See RFC1071.
+ *
+ * \note This function is not called in the current version of uIP,
+ * but future versions might make use of it.
+ *
+ * \param buf A pointer to the buffer over which the checksum is to be
+ * computed.
+ *
+ * \param len The length of the buffer over which the checksum is to
+ * be computed.
+ *
+ * \return The Internet checksum of the buffer.
+ */
+u16_t uip_chksum(u16_t *buf, u16_t len);
+
+/**
+ * Calculate the IP header checksum of the packet header in uip_buf.
+ *
+ * The IP header checksum is the Internet checksum of the 20 bytes of
+ * the IP header.
+ *
+ * \return The IP header checksum of the IP header in the uip_buf
+ * buffer.
+ */
+u16_t uip_ipchksum(void);
+
+/**
+ * Calculate the TCP checksum of the packet in uip_buf and uip_appdata.
+ *
+ * The TCP checksum is the Internet checksum of data contents of the
+ * TCP segment, and a pseudo-header as defined in RFC793.
+ *
+ * \note The uip_appdata pointer that points to the packet data may
+ * point anywhere in memory, so it is not possible to simply calculate
+ * the Internet checksum of the contents of the uip_buf buffer.
+ *
+ * \return The TCP checksum of the TCP segment in uip_buf and pointed
+ * to by uip_appdata.
+ */
+u16_t uip_tcpchksum(void);
+
+u16_t uip_udpchksum(void);
+
+/** @} */
+/** @} */
+
+#endif /* __UIP_ARCH_H__ */
diff --git a/uip/uip/uip_arp.c b/uip/uip/uip_arp.c
new file mode 100644
index 0000000..75ade64
--- /dev/null
+++ b/uip/uip/uip_arp.c
@@ -0,0 +1,423 @@
+/**
+ * \addtogroup uip
+ * @{
+ */
+
+/**
+ * \defgroup uiparp uIP Address Resolution Protocol
+ * @{
+ *
+ * The Address Resolution Protocol ARP is used for mapping between IP
+ * addresses and link level addresses such as the Ethernet MAC
+ * addresses. ARP uses broadcast queries to ask for the link level
+ * address of a known IP address and the host which is configured with
+ * the IP address for which the query was meant, will respond with its
+ * link level address.
+ *
+ * \note This ARP implementation only supports Ethernet.
+ */
+
+/**
+ * \file
+ * Implementation of the ARP Address Resolution Protocol.
+ * \author Adam Dunkels <adam@dunkels.com>
+ *
+ */
+
+/*
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: uip_arp.c,v 1.8 2006/06/02 23:36:21 adam Exp $
+ *
+ */
+
+
+#include "uip_arp.h"
+
+#include <string.h>
+
+struct arp_hdr {
+ struct uip_eth_hdr ethhdr;
+ u16_t hwtype;
+ u16_t protocol;
+ u8_t hwlen;
+ u8_t protolen;
+ u16_t opcode;
+ struct uip_eth_addr shwaddr;
+ u16_t sipaddr[2];
+ struct uip_eth_addr dhwaddr;
+ u16_t dipaddr[2];
+};
+
+struct ethip_hdr {
+ struct uip_eth_hdr ethhdr;
+ /* IP header. */
+ u8_t vhl,
+ tos,
+ len[2],
+ ipid[2],
+ ipoffset[2],
+ ttl,
+ proto;
+ u16_t ipchksum;
+ u16_t srcipaddr[2],
+ destipaddr[2];
+};
+
+#define ARP_REQUEST 1
+#define ARP_REPLY 2
+
+#define ARP_HWTYPE_ETH 1
+
+struct arp_entry {
+ u16_t ipaddr[2];
+ struct uip_eth_addr ethaddr;
+ u8_t time;
+};
+
+static const struct uip_eth_addr broadcast_ethaddr =
+ {{0xff,0xff,0xff,0xff,0xff,0xff}};
+static const u16_t broadcast_ipaddr[2] = {0xffff,0xffff};
+
+static struct arp_entry arp_table[UIP_ARPTAB_SIZE];
+static u16_t ipaddr[2];
+static u8_t i, c;
+
+static u8_t arptime;
+static u8_t tmpage;
+
+#define BUF ((struct arp_hdr *)&uip_buf[0])
+#define IPBUF ((struct ethip_hdr *)&uip_buf[0])
+/*-----------------------------------------------------------------------------------*/
+/**
+ * Initialize the ARP module.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+uip_arp_init(void)
+{
+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
+ memset(arp_table[i].ipaddr, 0, 4);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+/**
+ * Periodic ARP processing function.
+ *
+ * This function performs periodic timer processing in the ARP module
+ * and should be called at regular intervals. The recommended interval
+ * is 10 seconds between the calls.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+uip_arp_timer(void)
+{
+ struct arp_entry *tabptr;
+
+ ++arptime;
+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
+ tabptr = &arp_table[i];
+ if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 &&
+ arptime - tabptr->time >= UIP_ARP_MAXAGE) {
+ memset(tabptr->ipaddr, 0, 4);
+ }
+ }
+
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
+{
+ register struct arp_entry *tabptr;
+ /* Walk through the ARP mapping table and try to find an entry to
+ update. If none is found, the IP -> MAC address mapping is
+ inserted in the ARP table. */
+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
+
+ tabptr = &arp_table[i];
+ /* Only check those entries that are actually in use. */
+ if(tabptr->ipaddr[0] != 0 &&
+ tabptr->ipaddr[1] != 0) {
+
+ /* Check if the source IP address of the incoming packet matches
+ the IP address in this ARP table entry. */
+ if(ipaddr[0] == tabptr->ipaddr[0] &&
+ ipaddr[1] == tabptr->ipaddr[1]) {
+
+ /* An old entry found, update this and return. */
+ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
+ tabptr->time = arptime;
+
+ return;
+ }
+ }
+ }
+
+ /* If we get here, no existing ARP table entry was found, so we
+ create one. */
+
+ /* First, we try to find an unused entry in the ARP table. */
+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
+ tabptr = &arp_table[i];
+ if(tabptr->ipaddr[0] == 0 &&
+ tabptr->ipaddr[1] == 0) {
+ break;
+ }
+ }
+
+ /* If no unused entry is found, we try to find the oldest entry and
+ throw it away. */
+ if(i == UIP_ARPTAB_SIZE) {
+ tmpage = 0;
+ c = 0;
+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
+ tabptr = &arp_table[i];
+ if(arptime - tabptr->time > tmpage) {
+ tmpage = arptime - tabptr->time;
+ c = i;
+ }
+ }
+ i = c;
+ tabptr = &arp_table[i];
+ }
+
+ /* Now, i is the ARP table entry which we will fill with the new
+ information. */
+ memcpy(tabptr->ipaddr, ipaddr, 4);
+ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
+ tabptr->time = arptime;
+}
+/*-----------------------------------------------------------------------------------*/
+/**
+ * ARP processing for incoming IP packets
+ *
+ * This function should be called by the device driver when an IP
+ * packet has been received. The function will check if the address is
+ * in the ARP cache, and if so the ARP cache entry will be
+ * refreshed. If no ARP cache entry was found, a new one is created.
+ *
+ * This function expects an IP packet with a prepended Ethernet header
+ * in the uip_buf[] buffer, and the length of the packet in the global
+ * variable uip_len.
+ */
+/*-----------------------------------------------------------------------------------*/
+#if 0
+void
+uip_arp_ipin(void)
+{
+ uip_len -= sizeof(struct uip_eth_hdr);
+
+ /* Only insert/update an entry if the source IP address of the
+ incoming IP packet comes from a host on the local network. */
+ if((IPBUF->srcipaddr[0] & uip_netmask[0]) !=
+ (uip_hostaddr[0] & uip_netmask[0])) {
+ return;
+ }
+ if((IPBUF->srcipaddr[1] & uip_netmask[1]) !=
+ (uip_hostaddr[1] & uip_netmask[1])) {
+ return;
+ }
+ uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src));
+
+ return;
+}
+#endif /* 0 */
+/*-----------------------------------------------------------------------------------*/
+/**
+ * ARP processing for incoming ARP packets.
+ *
+ * This function should be called by the device driver when an ARP
+ * packet has been received. The function will act differently
+ * depending on the ARP packet type: if it is a reply for a request
+ * that we previously sent out, the ARP cache will be filled in with
+ * the values from the ARP reply. If the incoming ARP packet is an ARP
+ * request for our IP address, an ARP reply packet is created and put
+ * into the uip_buf[] buffer.
+ *
+ * When the function returns, the value of the global variable uip_len
+ * indicates whether the device driver should send out a packet or
+ * not. If uip_len is zero, no packet should be sent. If uip_len is
+ * non-zero, it contains the length of the outbound packet that is
+ * present in the uip_buf[] buffer.
+ *
+ * This function expects an ARP packet with a prepended Ethernet
+ * header in the uip_buf[] buffer, and the length of the packet in the
+ * global variable uip_len.
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+uip_arp_arpin(void)
+{
+
+ if(uip_len < sizeof(struct arp_hdr)) {
+ uip_len = 0;
+ return;
+ }
+ uip_len = 0;
+
+ switch(BUF->opcode) {
+ case HTONS(ARP_REQUEST):
+ /* ARP request. If it asked for our address, we send out a
+ reply. */
+ if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) {
+ /* First, we register the one who made the request in our ARP
+ table, since it is likely that we will do more communication
+ with this host in the future. */
+ uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
+
+ /* The reply opcode is 2. */
+ BUF->opcode = HTONS(2);
+
+ memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6);
+ memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
+ memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
+ memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6);
+
+ BUF->dipaddr[0] = BUF->sipaddr[0];
+ BUF->dipaddr[1] = BUF->sipaddr[1];
+ BUF->sipaddr[0] = uip_hostaddr[0];
+ BUF->sipaddr[1] = uip_hostaddr[1];
+
+ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
+ uip_len = sizeof(struct arp_hdr);
+ }
+ break;
+ case HTONS(ARP_REPLY):
+ /* ARP reply. We insert or update the ARP table if it was meant
+ for us. */
+ if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) {
+ uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
+ }
+ break;
+ }
+
+ return;
+}
+/*-----------------------------------------------------------------------------------*/
+/**
+ * Prepend Ethernet header to an outbound IP packet and see if we need
+ * to send out an ARP request.
+ *
+ * This function should be called before sending out an IP packet. The
+ * function checks the destination IP address of the IP packet to see
+ * what Ethernet MAC address that should be used as a destination MAC
+ * address on the Ethernet.
+ *
+ * If the destination IP address is in the local network (determined
+ * by logical ANDing of netmask and our IP address), the function
+ * checks the ARP cache to see if an entry for the destination IP
+ * address is found. If so, an Ethernet header is prepended and the
+ * function returns. If no ARP cache entry is found for the
+ * destination IP address, the packet in the uip_buf[] is replaced by
+ * an ARP request packet for the IP address. The IP packet is dropped
+ * and it is assumed that they higher level protocols (e.g., TCP)
+ * eventually will retransmit the dropped packet.
+ *
+ * If the destination IP address is not on the local network, the IP
+ * address of the default router is used instead.
+ *
+ * When the function returns, a packet is present in the uip_buf[]
+ * buffer, and the length of the packet is in the global variable
+ * uip_len.
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+uip_arp_out(void)
+{
+ struct arp_entry *tabptr;
+
+ /* Find the destination IP address in the ARP table and construct
+ the Ethernet header. If the destination IP addres isn't on the
+ local network, we use the default router's IP address instead.
+
+ If not ARP table entry is found, we overwrite the original IP
+ packet with an ARP request for the IP address. */
+
+ /* First check if destination is a local broadcast. */
+ if(uip_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr)) {
+ memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6);
+ } else {
+ /* Check if the destination address is on the local network. */
+ if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) {
+ /* Destination address was not on the local network, so we need to
+ use the default router's IP address instead of the destination
+ address when determining the MAC address. */
+ uip_ipaddr_copy(ipaddr, uip_draddr);
+ } else {
+ /* Else, we use the destination IP address. */
+ uip_ipaddr_copy(ipaddr, IPBUF->destipaddr);
+ }
+
+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
+ tabptr = &arp_table[i];
+ if(uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) {
+ break;
+ }
+ }
+
+ if(i == UIP_ARPTAB_SIZE) {
+ /* The destination address was not in our ARP table, so we
+ overwrite the IP packet with an ARP request. */
+
+ memset(BUF->ethhdr.dest.addr, 0xff, 6);
+ memset(BUF->dhwaddr.addr, 0x00, 6);
+ memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
+ memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
+
+ uip_ipaddr_copy(BUF->dipaddr, ipaddr);
+ uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr);
+ BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */
+ BUF->hwtype = HTONS(ARP_HWTYPE_ETH);
+ BUF->protocol = HTONS(UIP_ETHTYPE_IP);
+ BUF->hwlen = 6;
+ BUF->protolen = 4;
+ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
+
+ uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN];
+
+ uip_len = sizeof(struct arp_hdr);
+ return;
+ }
+
+ /* Build an ethernet header. */
+ memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6);
+ }
+ memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
+
+ IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP);
+
+ uip_len += sizeof(struct uip_eth_hdr);
+}
+/*-----------------------------------------------------------------------------------*/
+
+/** @} */
+/** @} */
diff --git a/uip/uip/uip_arp.h b/uip/uip/uip_arp.h
new file mode 100644
index 0000000..e32594d
--- /dev/null
+++ b/uip/uip/uip_arp.h
@@ -0,0 +1,144 @@
+/**
+ * \addtogroup uip
+ * @{
+ */
+
+/**
+ * \addtogroup uiparp
+ * @{
+ */
+
+/**
+ * \file
+ * Macros and definitions for the ARP module.
+ * \author Adam Dunkels <adam@dunkels.com>
+ */
+
+
+/*
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: uip_arp.h,v 1.5 2006/06/11 21:46:39 adam Exp $
+ *
+ */
+
+#ifndef __UIP_ARP_H__
+#define __UIP_ARP_H__
+
+#include "uip.h"
+
+
+extern struct uip_eth_addr uip_ethaddr;
+
+/**
+ * The Ethernet header.
+ */
+struct uip_eth_hdr {
+ struct uip_eth_addr dest;
+ struct uip_eth_addr src;
+ u16_t type;
+};
+
+#define UIP_ETHTYPE_ARP 0x0806
+#define UIP_ETHTYPE_IP 0x0800
+#define UIP_ETHTYPE_IP6 0x86dd
+
+
+/* The uip_arp_init() function must be called before any of the other
+ ARP functions. */
+void uip_arp_init(void);
+
+/* The uip_arp_ipin() function should be called whenever an IP packet
+ arrives from the Ethernet. This function refreshes the ARP table or
+ inserts a new mapping if none exists. The function assumes that an
+ IP packet with an Ethernet header is present in the uip_buf buffer
+ and that the length of the packet is in the uip_len variable. */
+/*void uip_arp_ipin(void);*/
+#define uip_arp_ipin()
+
+/* The uip_arp_arpin() should be called when an ARP packet is received
+ by the Ethernet driver. This function also assumes that the
+ Ethernet frame is present in the uip_buf buffer. When the
+ uip_arp_arpin() function returns, the contents of the uip_buf
+ buffer should be sent out on the Ethernet if the uip_len variable
+ is > 0. */
+void uip_arp_arpin(void);
+
+/* The uip_arp_out() function should be called when an IP packet
+ should be sent out on the Ethernet. This function creates an
+ Ethernet header before the IP header in the uip_buf buffer. The
+ Ethernet header will have the correct Ethernet MAC destination
+ address filled in if an ARP table entry for the destination IP
+ address (or the IP address of the default router) is present. If no
+ such table entry is found, the IP packet is overwritten with an ARP
+ request and we rely on TCP to retransmit the packet that was
+ overwritten. In any case, the uip_len variable holds the length of
+ the Ethernet frame that should be transmitted. */
+void uip_arp_out(void);
+
+/* The uip_arp_timer() function should be called every ten seconds. It
+ is responsible for flushing old entries in the ARP table. */
+void uip_arp_timer(void);
+
+/** @} */
+
+/**
+ * \addtogroup uipconffunc
+ * @{
+ */
+
+
+/**
+ * Specifiy the Ethernet MAC address.
+ *
+ * The ARP code needs to know the MAC address of the Ethernet card in
+ * order to be able to respond to ARP queries and to generate working
+ * Ethernet headers.
+ *
+ * \note This macro only specifies the Ethernet MAC address to the ARP
+ * code. It cannot be used to change the MAC address of the Ethernet
+ * card.
+ *
+ * \param eaddr A pointer to a struct uip_eth_addr containing the
+ * Ethernet MAC address of the Ethernet card.
+ *
+ * \hideinitializer
+ */
+#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \
+ uip_ethaddr.addr[1] = eaddr.addr[1];\
+ uip_ethaddr.addr[2] = eaddr.addr[2];\
+ uip_ethaddr.addr[3] = eaddr.addr[3];\
+ uip_ethaddr.addr[4] = eaddr.addr[4];\
+ uip_ethaddr.addr[5] = eaddr.addr[5];} while(0)
+
+/** @} */
+/** @} */
+
+#endif /* __UIP_ARP_H__ */
diff --git a/uip/uip/uiplib.c b/uip/uip/uiplib.c
new file mode 100644
index 0000000..cb5af2c
--- /dev/null
+++ b/uip/uip/uiplib.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2004, Adam Dunkels and the Swedish Institute of
+ * Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: uiplib.c,v 1.2 2006/06/12 08:00:31 adam Exp $
+ *
+ */
+
+
+#include "uip.h"
+#include "uiplib.h"
+
+
+/*-----------------------------------------------------------------------------------*/
+unsigned char
+uiplib_ipaddrconv(char *addrstr, unsigned char *ipaddr)
+{
+ unsigned char tmp;
+ char c;
+ unsigned char i, j;
+
+ tmp = 0;
+
+ for(i = 0; i < 4; ++i) {
+ j = 0;
+ do {
+ c = *addrstr;
+ ++j;
+ if(j > 4) {
+ return 0;
+ }
+ if(c == '.' || c == 0) {
+ *ipaddr = tmp;
+ ++ipaddr;
+ tmp = 0;
+ } else if(c >= '0' && c <= '9') {
+ tmp = (tmp * 10) + (c - '0');
+ } else {
+ return 0;
+ }
+ ++addrstr;
+ } while(c != '.' && c != 0);
+ }
+ return 1;
+}
+
+/*-----------------------------------------------------------------------------------*/
diff --git a/uip/uip/uiplib.h b/uip/uip/uiplib.h
new file mode 100644
index 0000000..c676849
--- /dev/null
+++ b/uip/uip/uiplib.h
@@ -0,0 +1,71 @@
+/**
+ * \file
+ * Various uIP library functions.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+/*
+ * Copyright (c) 2002, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: uiplib.h,v 1.1 2006/06/07 09:15:19 adam Exp $
+ *
+ */
+#ifndef __UIPLIB_H__
+#define __UIPLIB_H__
+
+/**
+ * \addtogroup uipconvfunc
+ * @{
+ */
+
+/**
+ * Convert a textual representation of an IP address to a numerical representation.
+ *
+ * This function takes a textual representation of an IP address in
+ * the form a.b.c.d and converts it into a 4-byte array that can be
+ * used by other uIP functions.
+ *
+ * \param addrstr A pointer to a string containing the IP address in
+ * textual form.
+ *
+ * \param addr A pointer to a 4-byte array that will be filled in with
+ * the numerical representation of the address.
+ *
+ * \retval 0 If the IP address could not be parsed.
+ * \retval Non-zero If the IP address was parsed.
+ */
+unsigned char uiplib_ipaddrconv(char *addrstr, unsigned char *addr);
+
+/** @} */
+
+#endif /* __UIPLIB_H__ */
diff --git a/uip/uip/uipopt.h b/uip/uip/uipopt.h
new file mode 100644
index 0000000..8feabf6
--- /dev/null
+++ b/uip/uip/uipopt.h
@@ -0,0 +1,544 @@
+/**
+ * \defgroup uipopt Configuration options for uIP
+ * @{
+ *
+ * uIP is configured using the per-project configuration file
+ * uipopt.h. This file contains all compile-time options for uIP and
+ * should be tweaked to match each specific project. The uIP
+ * distribution contains a documented example "uipopt.h" that can be
+ * copied and modified for each project.
+ *
+ * \note Most of the configuration options in the uipopt.h should not
+ * be changed, but rather the per-project uip-conf.h file.
+ */
+
+/**
+ * \file
+ * Configuration options for uIP.
+ * \author Adam Dunkels <adam@dunkels.com>
+ *
+ * This file is used for tweaking various configuration options for
+ * uIP. You should make a copy of this file into one of your project's
+ * directories instead of editing this example "uipopt.h" file that
+ * comes with the uIP distribution.
+ */
+
+/*
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: uipopt.h,v 1.4 2006/06/12 08:00:31 adam Exp $
+ *
+ */
+
+#ifndef __UIPOPT_H__
+#define __UIPOPT_H__
+
+#ifndef UIP_LITTLE_ENDIAN
+#define UIP_LITTLE_ENDIAN 3412
+#endif /* UIP_LITTLE_ENDIAN */
+#ifndef UIP_BIG_ENDIAN
+#define UIP_BIG_ENDIAN 1234
+#endif /* UIP_BIG_ENDIAN */
+
+#include "uip-conf.h"
+
+/*------------------------------------------------------------------------------*/
+
+/**
+ * \name Static configuration options
+ * @{
+ *
+ * These configuration options can be used for setting the IP address
+ * settings statically, but only if UIP_FIXEDADDR is set to 1. The
+ * configuration options for a specific node includes IP address,
+ * netmask and default router as well as the Ethernet address. The
+ * netmask, default router and Ethernet address are appliciable only
+ * if uIP should be run over Ethernet.
+ *
+ * All of these should be changed to suit your project.
+*/
+
+/**
+ * Determines if uIP should use a fixed IP address or not.
+ *
+ * If uIP should use a fixed IP address, the settings are set in the
+ * uipopt.h file. If not, the macros uip_sethostaddr(),
+ * uip_setdraddr() and uip_setnetmask() should be used instead.
+ *
+ * \hideinitializer
+ */
+#define UIP_FIXEDADDR 0
+
+/**
+ * Ping IP address asignment.
+ *
+ * uIP uses a "ping" packets for setting its own IP address if this
+ * option is set. If so, uIP will start with an empty IP address and
+ * the destination IP address of the first incoming "ping" (ICMP echo)
+ * packet will be used for setting the hosts IP address.
+ *
+ * \note This works only if UIP_FIXEDADDR is 0.
+ *
+ * \hideinitializer
+ */
+#ifdef UIP_CONF_PINGADDRCONF
+#define UIP_PINGADDRCONF UIP_CONF_PINGADDRCONF
+#else /* UIP_CONF_PINGADDRCONF */
+#define UIP_PINGADDRCONF 0
+#endif /* UIP_CONF_PINGADDRCONF */
+
+
+/**
+ * Specifies if the uIP ARP module should be compiled with a fixed
+ * Ethernet MAC address or not.
+ *
+ * If this configuration option is 0, the macro uip_setethaddr() can
+ * be used to specify the Ethernet address at run-time.
+ *
+ * \hideinitializer
+ */
+#define UIP_FIXEDETHADDR 0
+
+/** @} */
+/*------------------------------------------------------------------------------*/
+/**
+ * \name IP configuration options
+ * @{
+ *
+ */
+/**
+ * The IP TTL (time to live) of IP packets sent by uIP.
+ *
+ * This should normally not be changed.
+ */
+#define UIP_TTL 64
+
+/**
+ * Turn on support for IP packet reassembly.
+ *
+ * uIP supports reassembly of fragmented IP packets. This features
+ * requires an additonal amount of RAM to hold the reassembly buffer
+ * and the reassembly code size is approximately 700 bytes. The
+ * reassembly buffer is of the same size as the uip_buf buffer
+ * (configured by UIP_BUFSIZE).
+ *
+ * \note IP packet reassembly is not heavily tested.
+ *
+ * \hideinitializer
+ */
+#define UIP_REASSEMBLY 0
+
+/**
+ * The maximum time an IP fragment should wait in the reassembly
+ * buffer before it is dropped.
+ *
+ */
+#define UIP_REASS_MAXAGE 40
+
+/** @} */
+
+/*------------------------------------------------------------------------------*/
+/**
+ * \name UDP configuration options
+ * @{
+ */
+
+/**
+ * Toggles wether UDP support should be compiled in or not.
+ *
+ * \hideinitializer
+ */
+#ifdef UIP_CONF_UDP
+#define UIP_UDP UIP_CONF_UDP
+#else /* UIP_CONF_UDP */
+#define UIP_UDP 0
+#endif /* UIP_CONF_UDP */
+
+/**
+ * Toggles if UDP checksums should be used or not.
+ *
+ * \note Support for UDP checksums is currently not included in uIP,
+ * so this option has no function.
+ *
+ * \hideinitializer
+ */
+#ifdef UIP_CONF_UDP_CHECKSUMS
+#define UIP_UDP_CHECKSUMS UIP_CONF_UDP_CHECKSUMS
+#else
+#define UIP_UDP_CHECKSUMS 0
+#endif
+
+/**
+ * The maximum amount of concurrent UDP connections.
+ *
+ * \hideinitializer
+ */
+#ifdef UIP_CONF_UDP_CONNS
+#define UIP_UDP_CONNS UIP_CONF_UDP_CONNS
+#else /* UIP_CONF_UDP_CONNS */
+#define UIP_UDP_CONNS 10
+#endif /* UIP_CONF_UDP_CONNS */
+
+/**
+ * The name of the function that should be called when UDP datagrams arrive.
+ *
+ * \hideinitializer
+ */
+
+
+/** @} */
+/*------------------------------------------------------------------------------*/
+/**
+ * \name TCP configuration options
+ * @{
+ */
+
+/**
+ * Determines if support for opening connections from uIP should be
+ * compiled in.
+ *
+ * If the applications that are running on top of uIP for this project
+ * do not need to open outgoing TCP connections, this configration
+ * option can be turned off to reduce the code size of uIP.
+ *
+ * \hideinitializer
+ */
+#define UIP_ACTIVE_OPEN 1
+
+/**
+ * The maximum number of simultaneously open TCP connections.
+ *
+ * Since the TCP connections are statically allocated, turning this
+ * configuration knob down results in less RAM used. Each TCP
+ * connection requires approximatly 30 bytes of memory.
+ *
+ * \hideinitializer
+ */
+#ifndef UIP_CONF_MAX_CONNECTIONS
+#define UIP_CONNS 10
+#else /* UIP_CONF_MAX_CONNECTIONS */
+#define UIP_CONNS UIP_CONF_MAX_CONNECTIONS
+#endif /* UIP_CONF_MAX_CONNECTIONS */
+
+
+#ifdef UIP_CONF_TCP_LISTEN
+#define UIP_TCP_LISTEN
+#endif
+
+/**
+ * The maximum number of simultaneously listening TCP ports.
+ *
+ * Each listening TCP port requires 2 bytes of memory.
+ *
+ * \hideinitializer
+ */
+#ifndef UIP_CONF_MAX_LISTENPORTS
+#define UIP_LISTENPORTS 20
+#else /* UIP_CONF_MAX_LISTENPORTS */
+#define UIP_LISTENPORTS UIP_CONF_MAX_LISTENPORTS
+#endif /* UIP_CONF_MAX_LISTENPORTS */
+
+/**
+ * Determines if support for TCP urgent data notification should be
+ * compiled in.
+ *
+ * Urgent data (out-of-band data) is a rarely used TCP feature that
+ * very seldom would be required.
+ *
+ * \hideinitializer
+ */
+#define UIP_URGDATA 0
+
+/**
+ * The initial retransmission timeout counted in timer pulses.
+ *
+ * This should not be changed.
+ */
+#define UIP_RTO 3
+
+/**
+ * The maximum number of times a segment should be retransmitted
+ * before the connection should be aborted.
+ *
+ * This should not be changed.
+ */
+#define UIP_MAXRTX 8
+
+/**
+ * The maximum number of times a SYN segment should be retransmitted
+ * before a connection request should be deemed to have been
+ * unsuccessful.
+ *
+ * This should not need to be changed.
+ */
+#define UIP_MAXSYNRTX 5
+
+/**
+ * The TCP maximum segment size.
+ *
+ * This is should not be to set to more than
+ * UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN.
+ */
+/* 20081115 bkw: edited */
+#define UIP_TCP_MSS (160 - UIP_LLH_LEN - UIP_TCPIP_HLEN)
+
+/**
+ * The size of the advertised receiver's window.
+ *
+ * Should be set low (i.e., to the size of the uip_buf buffer) is the
+ * application is slow to process incoming data, or high (32768 bytes)
+ * if the application processes data quickly.
+ *
+ * \hideinitializer
+ */
+#ifndef UIP_CONF_RECEIVE_WINDOW
+#define UIP_RECEIVE_WINDOW UIP_TCP_MSS
+#else
+#define UIP_RECEIVE_WINDOW UIP_CONF_RECEIVE_WINDOW
+#endif
+
+/**
+ * How long a connection should stay in the TIME_WAIT state.
+ *
+ * This configiration option has no real implication, and it should be
+ * left untouched.
+ */
+#define UIP_TIME_WAIT_TIMEOUT 120
+
+
+/** @} */
+/*------------------------------------------------------------------------------*/
+/**
+ * \name ARP configuration options
+ * @{
+ */
+
+/**
+ * The size of the ARP table.
+ *
+ * This option should be set to a larger value if this uIP node will
+ * have many connections from the local network.
+ *
+ * \hideinitializer
+ */
+#ifdef UIP_CONF_ARPTAB_SIZE
+#define UIP_ARPTAB_SIZE UIP_CONF_ARPTAB_SIZE
+#else
+#define UIP_ARPTAB_SIZE 8
+#endif
+
+/**
+ * The maxium age of ARP table entries measured in 10ths of seconds.
+ *
+ * An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD
+ * default).
+ */
+#define UIP_ARP_MAXAGE 120
+
+/** @} */
+
+/*------------------------------------------------------------------------------*/
+
+/**
+ * \name General configuration options
+ * @{
+ */
+
+/**
+ * The size of the uIP packet buffer.
+ *
+ * The uIP packet buffer should not be smaller than 60 bytes, and does
+ * not need to be larger than 1500 bytes. Lower size results in lower
+ * TCP throughput, larger size results in higher TCP throughput.
+ *
+ * \hideinitializer
+ */
+#ifndef UIP_CONF_BUFFER_SIZE
+#define UIP_BUFSIZE 400
+#else /* UIP_CONF_BUFFER_SIZE */
+#define UIP_BUFSIZE UIP_CONF_BUFFER_SIZE
+#endif /* UIP_CONF_BUFFER_SIZE */
+
+
+/**
+ * Determines if statistics support should be compiled in.
+ *
+ * The statistics is useful for debugging and to show the user.
+ *
+ * \hideinitializer
+ */
+#ifndef UIP_CONF_STATISTICS
+#define UIP_STATISTICS 0
+#else /* UIP_CONF_STATISTICS */
+#define UIP_STATISTICS UIP_CONF_STATISTICS
+#endif /* UIP_CONF_STATISTICS */
+
+/**
+ * Determines if logging of certain events should be compiled in.
+ *
+ * This is useful mostly for debugging. The function uip_log()
+ * must be implemented to suit the architecture of the project, if
+ * logging is turned on.
+ *
+ * \hideinitializer
+ */
+#ifndef UIP_CONF_LOGGING
+#define UIP_LOGGING 0
+#else /* UIP_CONF_LOGGING */
+#define UIP_LOGGING UIP_CONF_LOGGING
+#endif /* UIP_CONF_LOGGING */
+
+/**
+ * Broadcast support.
+ *
+ * This flag configures IP broadcast support. This is useful only
+ * together with UDP.
+ *
+ * \hideinitializer
+ *
+ */
+#ifndef UIP_CONF_BROADCAST
+#define UIP_BROADCAST 0
+#else /* UIP_CONF_BROADCAST */
+#define UIP_BROADCAST UIP_CONF_BROADCAST
+#endif /* UIP_CONF_BROADCAST */
+
+/**
+ * Print out a uIP log message.
+ *
+ * This function must be implemented by the module that uses uIP, and
+ * is called by uIP whenever a log message is generated.
+ */
+void uip_log(char *msg);
+
+/**
+ * The link level header length.
+ *
+ * This is the offset into the uip_buf where the IP header can be
+ * found. For Ethernet, this should be set to 14. For SLIP, this
+ * should be set to 0.
+ *
+ * \hideinitializer
+ */
+#ifdef UIP_CONF_LLH_LEN
+#define UIP_LLH_LEN UIP_CONF_LLH_LEN
+#else /* UIP_CONF_LLH_LEN */
+#define UIP_LLH_LEN 14
+#endif /* UIP_CONF_LLH_LEN */
+
+/** @} */
+/*------------------------------------------------------------------------------*/
+/**
+ * \name CPU architecture configuration
+ * @{
+ *
+ * The CPU architecture configuration is where the endianess of the
+ * CPU on which uIP is to be run is specified. Most CPUs today are
+ * little endian, and the most notable exception are the Motorolas
+ * which are big endian. The BYTE_ORDER macro should be changed to
+ * reflect the CPU architecture on which uIP is to be run.
+ */
+
+/**
+ * The byte order of the CPU architecture on which uIP is to be run.
+ *
+ * This option can be either BIG_ENDIAN (Motorola byte order) or
+ * LITTLE_ENDIAN (Intel byte order).
+ *
+ * \hideinitializer
+ */
+#ifdef UIP_CONF_BYTE_ORDER
+#define UIP_BYTE_ORDER UIP_CONF_BYTE_ORDER
+#else /* UIP_CONF_BYTE_ORDER */
+#define UIP_BYTE_ORDER UIP_LITTLE_ENDIAN
+#endif /* UIP_CONF_BYTE_ORDER */
+
+/** @} */
+/*------------------------------------------------------------------------------*/
+
+/**
+ * \name Appication specific configurations
+ * @{
+ *
+ * An uIP application is implemented using a single application
+ * function that is called by uIP whenever a TCP/IP event occurs. The
+ * name of this function must be registered with uIP at compile time
+ * using the UIP_APPCALL definition.
+ *
+ * uIP applications can store the application state within the
+ * uip_conn structure by specifying the type of the application
+ * structure by typedef:ing the type uip_tcp_appstate_t and uip_udp_appstate_t.
+ *
+ * The file containing the definitions must be included in the
+ * uipopt.h file.
+ *
+ * The following example illustrates how this can look.
+ \code
+
+void httpd_appcall(void);
+#define UIP_APPCALL httpd_appcall
+
+struct httpd_state {
+ u8_t state;
+ u16_t count;
+ char *dataptr;
+ char *script;
+};
+typedef struct httpd_state uip_tcp_appstate_t
+ \endcode
+ */
+
+/**
+ * \var #define UIP_APPCALL
+ *
+ * The name of the application function that uIP should call in
+ * response to TCP/IP events.
+ *
+ */
+
+/**
+ * \var typedef uip_tcp_appstate_t
+ *
+ * The type of the application state that is to be stored in the
+ * uip_conn structure. This usually is typedef:ed to a struct holding
+ * application state information.
+ */
+
+/**
+ * \var typedef uip_udp_appstate_t
+ *
+ * The type of the application state that is to be stored in the
+ * uip_conn structure. This usually is typedef:ed to a struct holding
+ * application state information.
+ */
+/** @} */
+/** @} */
+
+#endif /* __UIPOPT_H__ */
diff --git a/uip/unix/Makefile b/uip/unix/Makefile
new file mode 100644
index 0000000..ed64927
--- /dev/null
+++ b/uip/unix/Makefile
@@ -0,0 +1,44 @@
+# Copyright (c) 2001, Adam Dunkels.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote
+# products derived from this software without specific prior
+# written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# This file is part of the uIP TCP/IP stack.
+#
+# $Id: Makefile,v 1.13 2006/06/11 21:55:03 adam Exp $
+#
+
+all: uip
+
+CC = gcc
+AR = ar
+APPS = webserver
+CFLAGS = -Wall -g -I../uip -I. -fpack-struct -Os
+-include ../uip/Makefile.include
+
+uip: $(addprefix $(OBJECTDIR)/, main.o tapdev.o clock-arch.o) apps.a uip.a
+
+clean:
+ rm -fr *.o *~ *core uip $(OBJECTDIR) *.a
diff --git a/uip/unix/clock-arch.c b/uip/unix/clock-arch.c
new file mode 100644
index 0000000..d140aaf
--- /dev/null
+++ b/uip/unix/clock-arch.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2006, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: clock-arch.c,v 1.2 2006/06/12 08:00:31 adam Exp $
+ */
+
+/**
+ * \file
+ * Implementation of architecture-specific clock functionality
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ */
+
+#include "clock-arch.h"
+#include <sys/time.h>
+
+/*---------------------------------------------------------------------------*/
+clock_time_t
+clock_time(void)
+{
+ struct timeval tv;
+ struct timezone tz;
+
+ gettimeofday(&tv, &tz);
+
+ return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+/*---------------------------------------------------------------------------*/
diff --git a/uip/unix/clock-arch.h b/uip/unix/clock-arch.h
new file mode 100644
index 0000000..e51eee9
--- /dev/null
+++ b/uip/unix/clock-arch.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2006, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: clock-arch.h,v 1.2 2006/06/12 08:00:31 adam Exp $
+ */
+
+#ifndef __CLOCK_ARCH_H__
+#define __CLOCK_ARCH_H__
+
+typedef int clock_time_t;
+#define CLOCK_CONF_SECOND 1000
+
+#endif /* __CLOCK_ARCH_H__ */
diff --git a/uip/unix/main.c b/uip/unix/main.c
new file mode 100644
index 0000000..e4130e9
--- /dev/null
+++ b/uip/unix/main.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2001, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Adam Dunkels.
+ * 4. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: main.c,v 1.16 2006/06/11 21:55:03 adam Exp $
+ *
+ */
+
+
+#include "uip.h"
+#include "uip_arp.h"
+#include "tapdev.h"
+
+#include "timer.h"
+
+#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
+
+#ifndef NULL
+#define NULL (void *)0
+#endif /* NULL */
+
+/*---------------------------------------------------------------------------*/
+int
+main(void)
+{
+ int i;
+ uip_ipaddr_t ipaddr;
+ struct timer periodic_timer, arp_timer;
+
+ timer_set(&periodic_timer, CLOCK_SECOND / 2);
+ timer_set(&arp_timer, CLOCK_SECOND * 10);
+
+ tapdev_init();
+ uip_init();
+
+ uip_ipaddr(ipaddr, 192,168,0,2);
+ uip_sethostaddr(ipaddr);
+ uip_ipaddr(ipaddr, 192,168,0,1);
+ uip_setdraddr(ipaddr);
+ uip_ipaddr(ipaddr, 255,255,255,0);
+ uip_setnetmask(ipaddr);
+
+ httpd_init();
+
+ /* telnetd_init();*/
+
+ /* hello_world_init();*/
+
+ /* {
+ u8_t mac[6] = {1,2,3,4,5,6};
+ dhcpc_init(&mac, 6);
+ }*/
+
+ /*uip_ipaddr(ipaddr, 127,0,0,1);
+ smtp_configure("localhost", ipaddr);
+ SMTP_SEND("adam@sics.se", NULL, "uip-testing@example.com",
+ "Testing SMTP from uIP",
+ "Test message sent by uIP\r\n");*/
+
+ /*
+ webclient_init();
+ resolv_init();
+ uip_ipaddr(ipaddr, 195,54,122,204);
+ resolv_conf(ipaddr);
+ resolv_query("www.sics.se");*/
+
+
+
+ while(1) {
+ uip_len = tapdev_read();
+ if(uip_len > 0) {
+ if(BUF->type == htons(UIP_ETHTYPE_IP)) {
+ uip_arp_ipin();
+ uip_input();
+ /* If the above function invocation resulted in data that
+ should be sent out on the network, the global variable
+ uip_len is set to a value > 0. */
+ if(uip_len > 0) {
+ uip_arp_out();
+ tapdev_send();
+ }
+ } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) {
+ uip_arp_arpin();
+ /* If the above function invocation resulted in data that
+ should be sent out on the network, the global variable
+ uip_len is set to a value > 0. */
+ if(uip_len > 0) {
+ tapdev_send();
+ }
+ }
+
+ } else if(timer_expired(&periodic_timer)) {
+ timer_reset(&periodic_timer);
+ for(i = 0; i < UIP_CONNS; i++) {
+ uip_periodic(i);
+ /* If the above function invocation resulted in data that
+ should be sent out on the network, the global variable
+ uip_len is set to a value > 0. */
+ if(uip_len > 0) {
+ uip_arp_out();
+ tapdev_send();
+ }
+ }
+
+#if UIP_UDP
+ for(i = 0; i < UIP_UDP_CONNS; i++) {
+ uip_udp_periodic(i);
+ /* If the above function invocation resulted in data that
+ should be sent out on the network, the global variable
+ uip_len is set to a value > 0. */
+ if(uip_len > 0) {
+ uip_arp_out();
+ tapdev_send();
+ }
+ }
+#endif /* UIP_UDP */
+
+ /* Call the ARP timer function every 10 seconds. */
+ if(timer_expired(&arp_timer)) {
+ timer_reset(&arp_timer);
+ uip_arp_timer();
+ }
+ }
+ }
+ return 0;
+}
+/*---------------------------------------------------------------------------*/
+void
+uip_log(char *m)
+{
+ printf("uIP log message: %s\n", m);
+}
+void
+resolv_found(char *name, u16_t *ipaddr)
+{
+ u16_t *ipaddr2;
+
+ if(ipaddr == NULL) {
+ printf("Host '%s' not found.\n", name);
+ } else {
+ printf("Found name '%s' = %d.%d.%d.%d\n", name,
+ htons(ipaddr[0]) >> 8,
+ htons(ipaddr[0]) & 0xff,
+ htons(ipaddr[1]) >> 8,
+ htons(ipaddr[1]) & 0xff);
+ /* webclient_get("www.sics.se", 80, "/~adam/uip");*/
+ }
+}
+#ifdef __DHCPC_H__
+void
+dhcpc_configured(const struct dhcpc_state *s)
+{
+ uip_sethostaddr(s->ipaddr);
+ uip_setnetmask(s->netmask);
+ uip_setdraddr(s->default_router);
+ resolv_conf(s->dnsaddr);
+}
+#endif /* __DHCPC_H__ */
+void
+smtp_done(unsigned char code)
+{
+ printf("SMTP done with code %d\n", code);
+}
+void
+webclient_closed(void)
+{
+ printf("Webclient: connection closed\n");
+}
+void
+webclient_aborted(void)
+{
+ printf("Webclient: connection aborted\n");
+}
+void
+webclient_timedout(void)
+{
+ printf("Webclient: connection timed out\n");
+}
+void
+webclient_connected(void)
+{
+ printf("Webclient: connected, waiting for data...\n");
+}
+void
+webclient_datahandler(char *data, u16_t len)
+{
+ printf("Webclient: got %d bytes of data.\n", len);
+}
+/*---------------------------------------------------------------------------*/
diff --git a/uip/unix/tapdev.c b/uip/unix/tapdev.c
new file mode 100644
index 0000000..417b288
--- /dev/null
+++ b/uip/unix/tapdev.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2001, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: tapdev.c,v 1.8 2006/06/07 08:39:58 adam Exp $
+ */
+
+#define UIP_DRIPADDR0 192
+#define UIP_DRIPADDR1 168
+#define UIP_DRIPADDR2 0
+#define UIP_DRIPADDR3 1
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+
+#ifdef linux
+#include <sys/ioctl.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#define DEVTAP "/dev/net/tun"
+#else /* linux */
+#define DEVTAP "/dev/tap0"
+#endif /* linux */
+
+#include "uip.h"
+
+static int drop = 0;
+static int fd;
+
+
+/*---------------------------------------------------------------------------*/
+void
+tapdev_init(void)
+{
+ char buf[1024];
+
+ fd = open(DEVTAP, O_RDWR);
+ if(fd == -1) {
+ perror("tapdev: tapdev_init: open");
+ exit(1);
+ }
+
+#ifdef linux
+ {
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
+ if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
+ perror(buf);
+ exit(1);
+ }
+ }
+#endif /* Linux */
+
+ snprintf(buf, sizeof(buf), "ifconfig tap0 inet %d.%d.%d.%d",
+ UIP_DRIPADDR0, UIP_DRIPADDR1, UIP_DRIPADDR2, UIP_DRIPADDR3);
+ system(buf);
+
+}
+/*---------------------------------------------------------------------------*/
+unsigned int
+tapdev_read(void)
+{
+ fd_set fdset;
+ struct timeval tv, now;
+ int ret;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000;
+
+
+ FD_ZERO(&fdset);
+ FD_SET(fd, &fdset);
+
+ ret = select(fd + 1, &fdset, NULL, NULL, &tv);
+ if(ret == 0) {
+ return 0;
+ }
+ ret = read(fd, uip_buf, UIP_BUFSIZE);
+ if(ret == -1) {
+ perror("tap_dev: tapdev_read: read");
+ }
+
+ /* printf("--- tap_dev: tapdev_read: read %d bytes\n", ret);*/
+ /* {
+ int i;
+ for(i = 0; i < 20; i++) {
+ printf("%x ", uip_buf[i]);
+ }
+ printf("\n");
+ }*/
+ /* check_checksum(uip_buf, ret);*/
+ return ret;
+}
+/*---------------------------------------------------------------------------*/
+void
+tapdev_send(void)
+{
+ int ret;
+ /* printf("tapdev_send: sending %d bytes\n", size);*/
+ /* check_checksum(uip_buf, size);*/
+
+ /* drop++;
+ if(drop % 8 == 7) {
+ printf("Dropped a packet!\n");
+ return;
+ }*/
+ ret = write(fd, uip_buf, uip_len);
+ if(ret == -1) {
+ perror("tap_dev: tapdev_send: writev");
+ exit(1);
+ }
+}
+/*---------------------------------------------------------------------------*/
diff --git a/uip/unix/tapdev.h b/uip/unix/tapdev.h
new file mode 100644
index 0000000..280bc52
--- /dev/null
+++ b/uip/unix/tapdev.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2001, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Adam Dunkels.
+ * 4. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: tapdev.h,v 1.1 2002/01/10 06:22:56 adam Exp $
+ *
+ */
+
+#ifndef __TAPDEV_H__
+#define __TAPDEV_H__
+
+void tapdev_init(void);
+unsigned int tapdev_read(void);
+void tapdev_send(void);
+
+#endif /* __TAPDEV_H__ */
diff --git a/uip/unix/uip-conf.h b/uip/unix/uip-conf.h
new file mode 100644
index 0000000..2878c85
--- /dev/null
+++ b/uip/unix/uip-conf.h
@@ -0,0 +1,157 @@
+/**
+ * \addtogroup uipopt
+ * @{
+ */
+
+/**
+ * \name Project-specific configuration options
+ * @{
+ *
+ * uIP has a number of configuration options that can be overridden
+ * for each project. These are kept in a project-specific uip-conf.h
+ * file and all configuration names have the prefix UIP_CONF.
+ */
+
+/*
+ * Copyright (c) 2006, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: uip-conf.h,v 1.6 2006/06/12 08:00:31 adam Exp $
+ */
+
+/**
+ * \file
+ * An example uIP configuration file
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ */
+
+#ifndef __UIP_CONF_H__
+#define __UIP_CONF_H__
+
+#include <inttypes.h>
+
+/**
+ * 8 bit datatype
+ *
+ * This typedef defines the 8-bit type used throughout uIP.
+ *
+ * \hideinitializer
+ */
+typedef uint8_t u8_t;
+
+/**
+ * 16 bit datatype
+ *
+ * This typedef defines the 16-bit type used throughout uIP.
+ *
+ * \hideinitializer
+ */
+typedef uint16_t u16_t;
+
+/**
+ * Statistics datatype
+ *
+ * This typedef defines the dataype used for keeping statistics in
+ * uIP.
+ *
+ * \hideinitializer
+ */
+typedef unsigned short uip_stats_t;
+
+/**
+ * Maximum number of TCP connections.
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_MAX_CONNECTIONS 40
+
+/**
+ * Maximum number of listening TCP ports.
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_MAX_LISTENPORTS 40
+
+/**
+ * uIP buffer size.
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_BUFFER_SIZE 420
+
+/**
+ * CPU byte order.
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_BYTE_ORDER LITTLE_ENDIAN
+
+/**
+ * Logging on or off
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_LOGGING 1
+
+/**
+ * UDP support on or off
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_UDP 0
+
+/**
+ * UDP checksums on or off
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_UDP_CHECKSUMS 1
+
+/**
+ * uIP statistics on or off
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_STATISTICS 1
+
+/* Here we include the header file for the application(s) we use in
+ our project. */
+/*#include "smtp.h"*/
+/*#include "hello-world.h"*/
+/*#include "telnetd.h"*/
+#include "webserver.h"
+/*#include "dhcpc.h"*/
+/*#include "resolv.h"*/
+/*#include "webclient.h"*/
+
+#endif /* __UIP_CONF_H__ */
+
+/** @} */
+/** @} */