diff --git a/.gitignore b/.gitignore
index 70d0b71..c8bf649 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,5 @@ main.8xk
main.bin
ti83pv116.sav
+
+tool/rabbitsign
diff --git a/Makefile b/Makefile
index ae18967..4b54f14 100644
--- a/Makefile
+++ b/Makefile
@@ -1,15 +1,19 @@
-CC=sdcc
-CFLAGS=-Ilib83 -c -mz80 --std-sdcc2x --no-std-crt0 --reserve-regs-iy --opt-code-size
+SDCC=sdcc
+SDCCFLAGS=-Ilib83 -c -mz80 --std-sdcc2x --no-std-crt0 --reserve-regs-iy --opt-code-size
OBJS=_crt0.rel clrscr.rel putchar.rel puts.rel exit.rel gotoxy.rel __assert_fail.rel \
getchar.rel put_int.rel ctype.rel memcpy.rel memset.rel memmove.rel memcmp.rel \
strcpy.rel strlen.rel strncpy.rel \
main.rel
-.PHONY: all clean try
+.PHONY: all clean try init
all: main.8xk
+init:
+ @echo "Compiling rabbitsign..."
+ @$(CC) tool/rabbitsign-src/*.c -o tool/rabbitsign -O2 -g -w -DPROTOTYPES
+
clean:
@rm -f obj/* main.ihx main.bin main.8xk
@@ -17,16 +21,16 @@ try: main.8xk
@tilem2 --rom=ti83pv116.bin
%.rel: lib83/%.c
- @echo "(lib) CC $<"
- @$(CC) $(CFLAGS) $< -o obj/$@
+ @echo "(lib) SDCC $<"
+ @$(SDCC) $(SDCCFLAGS) $< -o obj/$@
%.rel: %.c
- @echo "CC $<"
- @$(CC) $(CFLAGS) $< -o obj/$@
+ @echo "SDCC $<"
+ @$(SDCC) $(SDCCFLAGS) $< -o obj/$@
obj/main.ihx: $(OBJS)
- @echo "LD $@"
- @cd obj && $(CC) -mz80 --no-std-crt0 --code-loc 0x4000 --code-size 0x4000 --xram-loc 0x9D95 --xram-size 0x6060 $^ -o ../$@ && cd ..
+ @echo "SDCCLD $@"
+ @cd obj && $(SDCC) -mz80 --no-std-crt0 --code-loc 0x4000 --code-size 0x4000 --xram-loc 0x9D95 --xram-size 0x6060 $^ -o ../$@ && cd ..
main.bin: obj/main.ihx
@echo "IHX->BIN $@"
@@ -35,5 +39,5 @@ main.bin: obj/main.ihx
main.8xk: main.bin
@echo "SIGN $@"
- @rabbitsign -P -p -t 8xk -g $<
+ @tool/rabbitsign -P -p -t 8xk -g $<
diff --git a/README.md b/README.md
index 6a07a85..9a53d1e 100644
--- a/README.md
+++ b/README.md
@@ -4,11 +4,25 @@ A C programming SDK for the TI-83 calculator. Includes pre-configured build syst
## Requirements
-- SDCC
-- GNU Make
-- TilEm
-- RabbitSign
+- A GNU/Linux system.
## Status
WIP.
+
+## Usage
+
+Initialise the build environment:
+
+```bash
+git clone https://git.palaiologos.rocks/Palaiologos/ti83-sdk
+cd ti83-sdk
+make init
+make
+```
+
+Run the pre-supplied program:
+
+```bash
+make try
+```
diff --git a/tool/rabbitsign-src/app8x.c b/tool/rabbitsign-src/app8x.c
new file mode 100644
index 0000000..d114178
--- /dev/null
+++ b/tool/rabbitsign-src/app8x.c
@@ -0,0 +1,445 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#include "rabbitsign.h"
+#include "internal.h"
+#include "md5.h"
+
+/*
+ * Check/fix Flash app header and data.
+ *
+ * This function checks various parts of the application header which,
+ * if incorrect, are known to cause applications to be rejected by the
+ * calculator. Depending on the flags, this function will also fix
+ * incorrect header fields.
+ *
+ * Note that this function can also add padding to the end of the app.
+ * The entire signature must be stored on one page, so if there is not
+ * enough room on the final page of the app, an extra page needs to be
+ * added to hold the signature.
+ *
+ * In addition, some versions of the boot code have a bug which
+ * results in incorrect MD5 hashes for applications that are 55 bytes
+ * long mod 64; this function will add an extra padding byte to avoid
+ * that case.
+ */
+int rs_repair_ti8x_app(RSProgram* app, /* app to repair */
+ unsigned int flags) /* flags */
+{
+ unsigned long length, hdrstart, hdrsize, fieldstart, fieldsize, i;
+ unsigned char* hdr;
+ unsigned char dummy = 0;
+ int e, pagecount, addedpage = 0;
+
+ /* Various parts of the OS, as well as other software on the
+ calculator and PC, expect that every application begins with the
+ bytes 80 0F -- a "long" field. Some things may work for apps
+ with an 80 0E (or even 80 0D) field, but not everything. Please
+ stick with 80 0F. */
+
+ if (app->length < 6
+ || app->data[0] != 0x80
+ || app->data[1] != 0x0f) {
+ rs_error(NULL, app, "no app header found");
+ return RS_ERR_MISSING_HEADER;
+ }
+
+ /* Determine application length */
+
+ length = app->length;
+ rs_get_field_size(app->data, &hdrstart, &hdrsize);
+
+ /* If requested, remove the old signature (truncate the application
+ to its stated length.) */
+
+ if (flags & RS_REMOVE_OLD_SIGNATURE) {
+ if (length < hdrstart + hdrsize) {
+ rs_warning(NULL, app, "provided app data too short");
+ }
+ else {
+ if (length > hdrstart + hdrsize + 96)
+ rs_warning(NULL, app, "re-signing discards %lu bytes",
+ length - hdrstart - hdrsize);
+ length = hdrstart + hdrsize;
+ }
+ }
+ else if (hdrsize && hdrstart + hdrsize != length) {
+ rs_warning(NULL, app, "application length incorrect");
+ rs_warning(NULL, app, "(perhaps you meant to use -r?)");
+ }
+
+ /* If necessary, add an extra page to ensure that the signature
+ doesn't span a page boundary. */
+
+ if (((length + 69 + 0x3fff) >> 14) != ((length + 0x3fff) >> 14)) {
+ if (flags & (RS_ZEALOUSLY_PAD_APP | RS_IGNORE_ALL_WARNINGS)) {
+ rs_warning(NULL, app, "adding an extra page to hold app signature");
+ length = ((length + 0x4000) & ~0x3fff) + 1;
+ addedpage = 1;
+ }
+ else {
+ rs_error(NULL, app, "application ends too close to a page boundary");
+ return RS_ERR_FINAL_PAGE_TOO_LONG;
+ }
+ }
+
+ if ((e = rs_program_set_length(app, length)))
+ return e;
+
+ /* If the length is 55 mod 64, add an extra byte. (Note that, with
+ 512-bit keys, this can never cause a page overflow.) We use zero
+ for the padding value, rather than FF, so that our output matches
+ that of other tools. */
+
+ if ((length % 64) == 55) {
+ length++;
+ rs_message(2, NULL, app, "adding an extra byte due to boot code bugs");
+ if ((e = rs_program_append_data(app, &dummy, 1)))
+ return e;
+ }
+
+ /* Set app size header to the correct value */
+
+ hdrsize = length - hdrstart;
+ if (rs_set_field_size(app->data, hdrsize)) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, app, "application length header too small");
+ else {
+ rs_error(NULL, app, "application length header too small");
+ return RS_ERR_FIELD_TOO_SMALL;
+ }
+ }
+
+ /* Check/fix page count. This field is required to be present and
+ contain the correct number of pages. It must be one byte long
+ (some parts of the OS don't even check the length and assume it
+ is one byte long.) */
+
+ hdr = app->data + hdrstart;
+ if (hdrsize > 128)
+ hdrsize = 128;
+
+ if (rs_find_app_field(0x8080, hdr, hdrsize,
+ NULL, &fieldstart, &fieldsize)) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, app, "application has no page count field");
+ else {
+ rs_error(NULL, app, "application has no page count field");
+ return RS_ERR_MISSING_PAGE_COUNT;
+ }
+ }
+ else if (fieldsize != 1) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, app, "application has an invalid page count field");
+ else {
+ rs_error(NULL, app, "application has an invalid page count field");
+ return RS_ERR_INCORRECT_PAGE_COUNT;
+ }
+ }
+ else {
+ pagecount = ((length + 0x3fff) >> 14);
+
+ if (flags & RS_FIX_PAGE_COUNT) {
+ hdr[fieldstart] = pagecount;
+ }
+ else if (addedpage && hdr[fieldstart] == pagecount - 1) {
+ hdr[fieldstart] = pagecount;
+ }
+ else if (hdr[fieldstart] != pagecount) {
+ if (flags & RS_IGNORE_ALL_WARNINGS) {
+ rs_warning(NULL, app,
+ "application has an incorrect page count (actual: %lu)",
+ ((length + 0x3fff) >> 14));
+ hdr[fieldstart] = pagecount;
+ }
+ else {
+ rs_error(NULL, app,
+ "application has an incorrect page count (actual: %lu)",
+ ((length + 0x3fff) >> 14));
+ return RS_ERR_INCORRECT_PAGE_COUNT;
+ }
+ }
+ }
+
+ /* Check for key ID. This field is required to be present; it
+ determines which public key is used for validation. (The
+ contents of this field are usually thought of as a big-endian
+ integer, but to be more precise, they're really treated as a
+ binary string.) */
+
+ if (rs_find_app_field(0x8010, hdr, hdrsize, NULL, NULL, NULL)) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, app, "application has no key ID");
+ else {
+ rs_error(NULL, app, "application has no key ID");
+ return RS_ERR_MISSING_KEY_ID;
+ }
+ }
+
+ /* Check for date stamp. This seems to be required -- the OS will
+ use it to update its last-known date stamp if necessary -- and
+ should consist of an 032x field containing an 090x field,
+ followed by an 020x field containing the date stamp signature.
+ (The contents of the latter only matter if the date stamp is
+ "new.") */
+
+ if (rs_find_app_field(0x0320, hdr, hdrsize,
+ NULL, &fieldstart, &fieldsize)) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, app, "application has no date stamp");
+ else {
+ rs_error(NULL, app, "application has no date stamp");
+ return RS_ERR_MISSING_DATE_STAMP;
+ }
+ }
+ else if (rs_find_app_field(0x0900, hdr + fieldstart, fieldsize,
+ NULL, NULL, NULL)) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, app, "application has no date stamp");
+ else {
+ rs_error(NULL, app, "application has no date stamp");
+ return RS_ERR_MISSING_DATE_STAMP;
+ }
+ }
+ else if (hdr[fieldstart + fieldsize] != 0x02
+ || (hdr[fieldstart + fieldsize + 1] & 0xf0) != 0) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, app, "application has no date stamp signature");
+ else {
+ rs_error(NULL, app, "application has no date stamp signature");
+ return RS_ERR_MISSING_DATE_STAMP;
+ }
+ }
+
+ /* Check for program image field. This field indicates the end of
+ the header and the start of application code. Note, however,
+ that the OS handles this field in an exceedingly broken way. To
+ be safe, this must always be the last field of the header, and
+ should always be written as 80 7F followed by four length bytes.
+ The length bytes may be anything you like -- they're ignored. */
+
+ if (rs_find_app_field(0x8070, hdr, hdrsize,
+ NULL, NULL, NULL)) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, app, "application has no program image field");
+ else {
+ rs_error(NULL, app, "application has no program image field");
+ return RS_ERR_MISSING_PROGRAM_IMAGE;
+ }
+ }
+
+ /* Check for invalid pages (those beginning with FF.) An OS bug
+ means that such pages will end up being erased completely if
+ defragmenting requires the application to be moved in Flash. */
+
+ e = RS_SUCCESS;
+
+ for (i = 0; i < app->length; i += 0x4000) {
+ if (app->data[i] == 0xff) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, app, "page %ld begins with FFh", (i >> 14));
+ else {
+ rs_error(NULL, app, "page %ld begins with FFh", (i >> 14));
+ e = RS_ERR_INVALID_PROGRAM_DATA;
+ }
+ }
+ }
+
+ return e;
+}
+
+/*
+ * Compute signature for a Flash app.
+ *
+ * The app header should be checked and/or repaired by
+ * rs_repair_ti8x_app() prior to calling this function.
+ *
+ * There are four equally valid Rabin signatures for any application;
+ * rootnum determines which of the four should be used.
+ */
+int rs_sign_ti8x_app(RSProgram* app, /* app to sign */
+ RSKey* key, /* signing key */
+ int rootnum) /* signature number */
+{
+ md5_uint32 hash[4];
+ mpz_t hashv, sigv;
+ int f;
+ unsigned int lastpagelength;
+ unsigned char sigdata[512];
+ size_t siglength;
+ int e;
+
+ /* Check if app length is risky */
+
+ if ((app->length % 64) == 55) {
+ rs_warning(NULL, app, "application has length 55 mod 64");
+ rs_warning(NULL, app, "(this will fail to validate on TI-83+ BE)");
+ }
+
+ /* Compute signature */
+
+ md5_buffer((char*) app->data, app->length, hash);
+
+ mpz_init(hashv);
+ mpz_init(sigv);
+
+ mpz_import(hashv, 16, -1, 1, 0, 0, hash);
+ rs_message(2, NULL, app, "hash = %ZX", hashv);
+
+ if ((e = rs_sign_rabin(sigv, &f, hashv, rootnum, key))) {
+ mpz_clear(hashv);
+ mpz_clear(sigv);
+ return e;
+ }
+
+ rs_message(2, NULL, app, "sig = %ZX", sigv);
+ rs_message(2, NULL, app, "f = %d", f);
+
+ /* Write the square root value as an 022D field... */
+
+ sigdata[0] = 0x02;
+ sigdata[1] = 0x2d;
+ mpz_export(sigdata + 3, &siglength, -1, 1, 0, 0, sigv);
+ sigdata[2] = siglength & 0xff;
+ siglength += 3;
+
+ mpz_clear(hashv);
+ mpz_clear(sigv);
+
+ /* ...and append the f value as a big integer */
+
+ if (f == 0) {
+ sigdata[siglength++] = 0;
+ }
+ else {
+ sigdata[siglength++] = 1;
+ sigdata[siglength++] = f;
+ }
+
+ /* Add padding, but not too much (it seems to make some link
+ programs happier) */
+
+ lastpagelength = app->length & 0x3fff;
+
+ while (siglength < 96 && (lastpagelength + siglength) < 0x3fff)
+ sigdata[siglength++] = 0xff;
+
+ return rs_program_append_data(app, sigdata, siglength);
+}
+
+/*
+ * Validate a Flash app signature.
+ */
+int rs_validate_ti8x_app(const RSProgram* app, /* app to validate */
+ const RSKey* key) /* signing key */
+{
+ unsigned long length, hdrstart, hdrsize, fieldstart, fieldsize, i;
+ const unsigned char *hdr, *sig;
+ md5_uint32 hash[4];
+ mpz_t hashv, sigv;
+ int f, e, e2 = RS_SUCCESS;
+
+ if (app->length < 6) {
+ rs_error(NULL, app, "no app header found");
+ return RS_ERR_MISSING_HEADER;
+ }
+
+ rs_get_field_size(app->data, &hdrstart, &hdrsize);
+ length = hdrstart + hdrsize;
+ hdr = app->data + hdrstart;
+ if (hdrsize > 128)
+ hdrsize = 128;
+
+ if (((length + 0x3fff) >> 14) != ((app->length + 0x3fff) >> 14)
+ || length + 4 > app->length || length + 96 < app->length) {
+ rs_error(NULL, app, "incorrect application length");
+ return RS_ERR_INCORRECT_PROGRAM_SIZE;
+ }
+
+ if (rs_find_app_field(0x8070, hdr, hdrsize,
+ NULL, NULL, NULL)) {
+ rs_warning(NULL, app, "application has no program image field");
+ e2 = RS_ERR_MISSING_PROGRAM_IMAGE;
+ }
+
+ if (rs_find_app_field(0x8080, hdr, hdrsize,
+ NULL, &fieldstart, &fieldsize)) {
+ rs_warning(NULL, app, "application has no no page count field");
+ e2 = RS_ERR_MISSING_PAGE_COUNT;
+ }
+ else if (fieldsize != 1) {
+ rs_warning(NULL, app, "application has an invalid page count field");
+ e2 = RS_ERR_INCORRECT_PAGE_COUNT;
+ }
+ else if (hdr[fieldstart] != ((length + 0x3fff) >> 14)) {
+ rs_warning(NULL, app, "application has an incorrect page count field");
+ e2 = RS_ERR_INCORRECT_PAGE_COUNT;
+ }
+
+ if ((length % 64) == 55) {
+ rs_warning(NULL, app, "application has length 55 mod 64");
+ rs_warning(NULL, app, "(this will fail to validate on TI-83+ BE)");
+ e2 = RS_ERR_INVALID_PROGRAM_SIZE;
+ }
+
+ for (i = 0; i < app->length; i += 0x4000) {
+ if (app->data[i] == 0xff) {
+ rs_warning(NULL, app, "page %ld begins with FFh", (i >> 14));
+ e2 = RS_ERR_INVALID_PROGRAM_DATA;
+ }
+ }
+
+ md5_buffer((char*) app->data, length, &hash);
+
+ sig = app->data + length;
+ if (sig[0] != 0x02 || sig[1] != 0x2d) {
+ rs_error(NULL, app, "application does not have a Rabin signature");
+ return RS_ERR_MISSING_RABIN_SIGNATURE;
+ }
+ rs_get_field_size(sig, &fieldstart, &fieldsize);
+
+ mpz_init(sigv);
+ mpz_init(hashv);
+
+ mpz_import(hashv, 16, -1, 1, 0, 0, hash);
+ rs_message(2, NULL, app, "hash = %ZX", hashv);
+
+ mpz_import(sigv, fieldsize, -1, 1, 0, 0, sig + fieldstart);
+ rs_message(2, NULL, app, "sig = %ZX", sigv);
+
+ if (sig[fieldstart + fieldsize] == 0)
+ f = 0;
+ else
+ f = sig[fieldstart + fieldsize + 1];
+ rs_message(2, NULL, app, "f = %d", f);
+
+ e = rs_validate_rabin(sigv, f, hashv, key);
+ if (e == RS_SIGNATURE_INCORRECT)
+ rs_message(0, NULL, app, "application signature incorrect");
+
+ mpz_clear(sigv);
+ mpz_clear(hashv);
+ return (e ? e : e2);
+}
+
diff --git a/tool/rabbitsign-src/app9x.c b/tool/rabbitsign-src/app9x.c
new file mode 100644
index 0000000..9d0dda9
--- /dev/null
+++ b/tool/rabbitsign-src/app9x.c
@@ -0,0 +1,297 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#include "rabbitsign.h"
+#include "internal.h"
+#include "md5.h"
+
+/*
+ * Check/fix app/OS header and data.
+ *
+ * (This is something of a work in progress; a lot more
+ * experimentation would be useful to determine what exactly is
+ * required of app and OS headers on the 68k calculators.)
+ */
+static int repair_app(RSProgram* app, /* app to repair */
+ unsigned int flags, /* flags */
+ unsigned int type) /* field type */
+{
+ unsigned long length, hdrstart, hdrsize, fieldhead,
+ fieldstart, fieldsize;
+ unsigned char *hdr;
+ int e;
+
+ if (app->length < 6
+ || app->data[0] != type
+ || (app->data[1] & 0xf0) != 0) {
+ rs_error(NULL, app, "no app header found");
+ return RS_ERR_MISSING_HEADER;
+ }
+
+ /* Determine application length */
+
+ length = app->length;
+ rs_get_field_size(app->data, &hdrstart, &hdrsize);
+
+ /* If requested, remove the old signature (truncate the application
+ to its stated length.) */
+
+ if (flags & RS_REMOVE_OLD_SIGNATURE) {
+ if (length < hdrstart + hdrsize) {
+ rs_warning(NULL, app, "provided app data too short");
+ }
+ else {
+ if (length > hdrstart + hdrsize + 67)
+ rs_warning(NULL, app, "re-signing discards %lu bytes",
+ length - hdrstart - hdrsize);
+ length = hdrstart + hdrsize;
+ }
+ }
+ else if (hdrsize && hdrstart + hdrsize != length) {
+ rs_warning(NULL, app, "application length incorrect");
+ rs_warning(NULL, app, "(perhaps you meant to use -r?)");
+ }
+
+ if ((e = rs_program_set_length(app, length)))
+ return e;
+
+ /* Set app size header to the correct value */
+
+ hdrsize = length - hdrstart;
+ if (rs_set_field_size(app->data, hdrsize)) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, app, "cannot set application length");
+ else {
+ rs_error(NULL, app, "cannot set application length");
+ return RS_ERR_FIELD_TOO_SMALL;
+ }
+ }
+
+ /* Check for key ID */
+
+ hdr = app->data + hdrstart;
+ if (hdrsize > 128)
+ hdrsize = 128;
+
+ if (rs_find_app_field((type << 8) | 0x10, hdr, hdrsize,
+ NULL, NULL, NULL)) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, app, "application has no key ID");
+ else {
+ rs_error(NULL, app, "application has no key ID");
+ return RS_ERR_MISSING_KEY_ID;
+ }
+ }
+
+ /* Check for date stamp (note: I haven't actually tested whether
+ this is required, but it always seems to be present in both 68k
+ apps and OSes, and it is required for TI-83+ apps) */
+
+ if (rs_find_app_field(0x0320, hdr, hdrsize,
+ NULL, &fieldstart, &fieldsize)) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, app, "application has no date stamp");
+ else {
+ rs_error(NULL, app, "application has no date stamp");
+ return RS_ERR_MISSING_DATE_STAMP;
+ }
+ }
+ else if (rs_find_app_field(0x0900, hdr + fieldstart, fieldsize,
+ NULL, NULL, NULL)) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, app, "application has no date stamp");
+ else {
+ rs_error(NULL, app, "application has no date stamp");
+ return RS_ERR_MISSING_DATE_STAMP;
+ }
+ }
+ else if (hdr[fieldstart + fieldsize] != 0x02
+ || (hdr[fieldstart + fieldsize + 1] & 0xf0) != 0) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, app, "application has no date stamp signature");
+ else {
+ rs_error(NULL, app, "application has no date stamp signature");
+ return RS_ERR_MISSING_DATE_STAMP;
+ }
+ }
+
+ /* Check for program image field and fix length */
+
+ if (rs_find_app_field((type << 8) | 0x70, hdr, hdrsize,
+ &fieldhead, &fieldstart, &fieldsize)) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, app, "application has no program image field");
+ else {
+ rs_error(NULL, app, "application has no program image field");
+ return RS_ERR_MISSING_PROGRAM_IMAGE;
+ }
+ }
+ else {
+ if ((fieldstart + hdrstart) % 2) {
+ /* The OS appears to align apps so the start of the app header
+ is at an even address; if the application code itself is at
+ an odd address, bad stuff will happen. */
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, app, "application header is not a multiple of 2 bytes");
+ else {
+ rs_error(NULL, app, "application header is not a multiple of 2 bytes");
+ return RS_ERR_MISALIGNED_PROGRAM_IMAGE;
+ }
+ }
+
+ if (fieldsize && fieldstart + fieldsize != length - hdrstart)
+ rs_warning(NULL, app, "program image length incorrect");
+
+ if (rs_set_field_size(hdr + fieldhead, length - hdrstart - fieldstart)) {
+ rs_error(NULL, app, "cannot set program image length");
+ return RS_ERR_FIELD_TOO_SMALL;
+ }
+ }
+
+ return RS_SUCCESS;
+}
+
+/*
+ * Check/fix Flash app header and data.
+ */
+int rs_repair_ti9x_app(RSProgram* app, /* app to repair */
+ unsigned int flags) /* flags */
+{
+ return repair_app(app, flags, 0x81);
+}
+
+/*
+ * Check/fix OS header and data.
+ */
+int rs_repair_ti9x_os(RSProgram* app, /* app to repair */
+ unsigned int flags) /* flags */
+{
+ return repair_app(app, flags, 0x80);
+}
+
+/*
+ * Compute signature for a 68k app/OS.
+ *
+ * The app header should be checked and/or repaired by
+ * rs_repair_ti9x_app() prior to calling this function.
+ */
+int rs_sign_ti9x_app(RSProgram* app, /* app to sign */
+ RSKey* key) /* signing key */
+{
+ md5_uint32 hash[4];
+ mpz_t hashv, sigv;
+ unsigned char sigdata[512];
+ size_t siglength;
+ int e;
+
+ md5_buffer((char*) app->data, app->length, &hash);
+
+ mpz_init(hashv);
+ mpz_init(sigv);
+
+ mpz_import(hashv, 16, -1, 1, 0, 0, hash);
+ rs_message(2, NULL, app, "hash = %ZX", hashv);
+
+ if ((e = rs_sign_rsa(sigv, hashv, key))) {
+ mpz_clear(hashv);
+ mpz_clear(sigv);
+ return e;
+ }
+
+ rs_message(2, NULL, app, "sig = %ZX", sigv);
+
+ sigdata[0] = 0x02;
+ sigdata[1] = 0x0d;
+ mpz_export(sigdata + 3, &siglength, -1, 1, 0, 0, sigv);
+ sigdata[2] = siglength & 0xff;
+ siglength += 3;
+
+ return rs_program_append_data(app, sigdata, siglength);
+}
+
+/*
+ * Validate app/OS signature.
+ */
+int rs_validate_ti9x_app(const RSProgram* app, /* app to validate */
+ const RSKey* key) /* signing key */
+{
+ unsigned long length, hdrstart, hdrsize, fieldstart, fieldsize;
+ const unsigned char *hdr, *sig;
+ md5_uint32 hash[4];
+ mpz_t hashv, sigv;
+ int e, e2 = RS_SUCCESS;
+
+ if (app->length < 6) {
+ rs_error(NULL, app, "no app header found");
+ return RS_ERR_MISSING_HEADER;
+ }
+
+ rs_get_field_size(app->data, &hdrstart, &hdrsize);
+ length = hdrstart + hdrsize;
+ hdr = app->data + hdrstart;
+ if (hdrsize > 128)
+ hdrsize = 128;
+
+ if (length + 4 > app->length || length + 67 < app->length) {
+ rs_error(NULL, app, "incorrect application length");
+ return RS_ERR_INCORRECT_PROGRAM_SIZE;
+ }
+
+ if (rs_find_app_field((app->data[0] << 8) | 0x70, hdr, hdrsize,
+ NULL, &fieldstart, &fieldsize)) {
+ rs_warning(NULL, app, "application has no program image field");
+ e2 = RS_ERR_MISSING_PROGRAM_IMAGE;
+ }
+ else if ((fieldstart + hdrstart) % 2) {
+ rs_warning(NULL, app, "application header is not a multiple of 2 bytes");
+ e2 = RS_ERR_MISALIGNED_PROGRAM_IMAGE;
+ }
+
+ md5_buffer((char*) app->data, length, &hash);
+
+ sig = app->data + length;
+ if (sig[0] != 0x02 || (sig[1] & 0xf0) != 0x00) {
+ rs_error(NULL, app, "application does not have an RSA signature");
+ return RS_ERR_MISSING_RSA_SIGNATURE;
+ }
+ rs_get_field_size(sig, &fieldstart, &fieldsize);
+
+ mpz_init(sigv);
+ mpz_init(hashv);
+
+ mpz_import(hashv, 16, -1, 1, 0, 0, hash);
+ rs_message(2, NULL, app, "hash = %ZX", hashv);
+
+ mpz_import(sigv, fieldsize, -1, 1, 0, 0, sig + fieldstart);
+ rs_message(2, NULL, app, "sig = %ZX", sigv);
+
+ e = rs_validate_rsa(sigv, hashv, key);
+ if (e == RS_SIGNATURE_INCORRECT)
+ rs_message(0, NULL, app, "application signature incorrect");
+
+ mpz_clear(sigv);
+ mpz_clear(hashv);
+ return (e ? e : e2);
+}
+
diff --git a/tool/rabbitsign-src/apps.c b/tool/rabbitsign-src/apps.c
new file mode 100644
index 0000000..896674d
--- /dev/null
+++ b/tool/rabbitsign-src/apps.c
@@ -0,0 +1,85 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#include "rabbitsign.h"
+#include "internal.h"
+
+/*
+ * Check/fix program header and data.
+ */
+int rs_repair_program(RSProgram* prgm, /* app to repair */
+ unsigned int flags) /* flags */
+{
+ if (rs_calc_is_ti8x(prgm->calctype)) {
+ if (prgm->datatype == RS_DATA_OS)
+ return rs_repair_ti8x_os(prgm, flags);
+ else if (prgm->datatype == RS_DATA_APP)
+ return rs_repair_ti8x_app(prgm, flags);
+ }
+
+ if (rs_calc_is_ti9x(prgm->calctype)) {
+ if (prgm->datatype == RS_DATA_OS)
+ return rs_repair_ti9x_os(prgm, flags);
+ else if (prgm->datatype == RS_DATA_APP)
+ return rs_repair_ti9x_app(prgm, flags);
+ }
+
+ rs_error(NULL, prgm, "calc/data type (%X/%X) unrecognized",
+ prgm->calctype, prgm->datatype);
+ return RS_ERR_UNKNOWN_PROGRAM_TYPE;
+}
+
+/*
+ * Add a signature to the program.
+ */
+int rs_sign_program(RSProgram* prgm, /* app to sign */
+ RSKey* key, /* signing key */
+ int rootnum) /* signature number */
+{
+ if (rs_calc_is_ti8x(prgm->calctype)) {
+ if (prgm->datatype == RS_DATA_OS)
+ return rs_sign_ti8x_os(prgm, key);
+ else if (prgm->datatype == RS_DATA_APP)
+ return rs_sign_ti8x_app(prgm, key, rootnum);
+ }
+
+ return rs_sign_ti9x_app(prgm, key);
+}
+
+/*
+ * Validate program signature.
+ */
+int rs_validate_program(const RSProgram* prgm, /* app to validate */
+ const RSKey* key) /* signing key */
+{
+ if (rs_calc_is_ti8x(prgm->calctype)) {
+ if (prgm->datatype == RS_DATA_OS)
+ return rs_validate_ti8x_os(prgm, key);
+ else if (prgm->datatype == RS_DATA_APP)
+ return rs_validate_ti8x_app(prgm, key);
+ }
+
+ return rs_validate_ti9x_app(prgm, key);
+}
+
diff --git a/tool/rabbitsign-src/autokey.c b/tool/rabbitsign-src/autokey.c
new file mode 100644
index 0000000..23b4a5f
--- /dev/null
+++ b/tool/rabbitsign-src/autokey.c
@@ -0,0 +1,241 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#ifdef HAVE_STDLIB_H
+# include
+#endif
+
+#ifdef HAVE_STRING_H
+# include
+#else
+# ifdef HAVE_STRINGS_H
+# include
+# endif
+#endif
+
+#include "rabbitsign.h"
+#include "internal.h"
+#include "autokeys.h"
+
+/*
+ * Get key ID for the given program.
+ */
+unsigned long rs_program_get_key_id(const RSProgram* prgm)
+{
+ const unsigned char* hdr;
+ unsigned long hdrstart, hdrsize;
+
+ if (prgm->header_length > 0) {
+ hdr = prgm->header;
+ hdrsize = prgm->header_length;
+ }
+ else if (prgm->length > 0) {
+ hdr = prgm->data;
+ hdrsize = prgm->length;
+ if (hdrsize > 128)
+ hdrsize = 128;
+ }
+ else
+ return 0;
+
+ rs_get_field_size(hdr, &hdrstart, NULL);
+ hdrsize -= hdrstart;
+
+ if (hdr[0] == 0x81)
+ return rs_get_numeric_field(0x8110, hdr + hdrstart, hdrsize);
+ else
+ return rs_get_numeric_field(0x8010, hdr + hdrstart, hdrsize);
+}
+
+/*
+ * Try to load key from a file.
+ */
+static int try_key_file(RSKey* key, /* key structure to store result */
+ const char* a, /* first path element */
+ const char* b, /* second path element */
+ const char* c) /* third path element */
+{
+ char* s;
+ FILE* f;
+ int e;
+
+ s = rs_malloc(strlen(a) + strlen(b) + strlen(c) + 1);
+ if (!s)
+ return RS_ERR_OUT_OF_MEMORY;
+ strcpy(s, a);
+ strcat(s, b);
+ strcat(s, c);
+
+ f = fopen(s, "rt");
+ if (!f) {
+ rs_free(s);
+ return RS_ERR_KEY_NOT_FOUND;
+ }
+
+ if ((e = rs_read_key_file(key, f, s, 1))) {
+ fclose(f);
+ rs_free(s);
+ return e;
+ }
+
+ fclose(f);
+ rs_free(s);
+ return RS_SUCCESS;
+}
+
+/*
+ * Try to locate a given key file.
+ */
+static int find_key_file(RSKey* key, /* key structure to
+ store result */
+ const char* filename) /* file name to search
+ for */
+{
+ const char* p;
+ int e;
+
+ e = try_key_file(key, "", "", filename);
+ if (e != RS_ERR_KEY_NOT_FOUND)
+ return e;
+
+ if ((p = getenv("RABBITSIGN_KEY_DIR"))) {
+#if defined(__MSDOS__) || defined(__WIN32__)
+ e = try_key_file(key, p, "\\", filename);
+#else
+ e = try_key_file(key, p, "/", filename);
+#endif
+ if (e != RS_ERR_KEY_NOT_FOUND)
+ return e;
+ }
+
+#if defined(__MSDOS__) || defined(__WIN32__)
+ if ((p = getenv("TI83PLUSDIR"))) {
+ e = try_key_file(key, p, "\\Utils\\", filename);
+ if (e != RS_ERR_KEY_NOT_FOUND)
+ return e;
+ }
+#endif
+
+#ifdef SHARE_DIR
+ e = try_key_file(key, SHARE_DIR, "", filename);
+ if (e != RS_ERR_KEY_NOT_FOUND)
+ return e;
+#endif
+
+ return RS_ERR_KEY_NOT_FOUND;
+}
+
+/*
+ * Find key file for the given ID.
+ */
+int rs_key_find_for_id(RSKey* key, /* key structure to store
+ result */
+ unsigned long keyid, /* key ID to search for */
+ int publiconly) /* 1 = search for public
+ key only */
+{
+ static const char* fmts[] = { "%02lx.%s", "%02lX.%s",
+ "%04lx.%s", "%04lX.%s", NULL };
+ char buf[16];
+ int i, e;
+
+ mpz_set_ui(key->p, 0);
+ mpz_set_ui(key->q, 0);
+ mpz_set_ui(key->qinv, 0);
+ mpz_set_ui(key->d, 0);
+
+ if (keyid > 0xFF)
+ sprintf(buf, "%04lX", keyid);
+ else
+ sprintf(buf, "%02lX", keyid);
+
+ for (i = 0; known_priv_keys[i].n; i++) {
+ if (keyid == known_priv_keys[i].id) {
+ if ((e = rs_parse_key_value(key->n, known_priv_keys[i].n)))
+ return e;
+
+ if (known_priv_keys[i].p
+ && (e = rs_parse_key_value(key->p, known_priv_keys[i].p)))
+ return e;
+ if (known_priv_keys[i].q
+ && (e = rs_parse_key_value(key->q, known_priv_keys[i].q)))
+ return e;
+ if (known_priv_keys[i].d
+ && (e = rs_parse_key_value(key->d, known_priv_keys[i].d)))
+ return e;
+
+ rs_message(2, key, NULL, "Loaded builtin private key %s:", buf);
+ rs_message(2, key, NULL, " n = %ZX", key->n);
+ if (mpz_sgn(key->p))
+ rs_message(2, key, NULL, " p = %ZX", key->p);
+ if (mpz_sgn(key->q))
+ rs_message(2, key, NULL, " q = %ZX", key->q);
+ if (mpz_sgn(key->d))
+ rs_message(2, key, NULL, " d = %ZX", key->d);
+
+ key->id = keyid;
+ return 0;
+ }
+ }
+
+ if (publiconly) {
+ for (i = 0; known_pub_keys[i].n; i++) {
+ if (keyid == known_pub_keys[i].id) {
+ if ((e = rs_parse_key_value(key->n, known_pub_keys[i].n)))
+ return e;
+
+ rs_message(2, key, NULL, "Loaded builtin public key %s:", buf);
+ rs_message(2, key, NULL, " n = %ZX", key->n);
+
+ key->id = keyid;
+ return 0;
+ }
+ }
+ }
+
+ for (i = 0; fmts[i]; i++) {
+ sprintf(buf, fmts[i], keyid, "key");
+ e = find_key_file(key, buf);
+ if (e != RS_ERR_KEY_NOT_FOUND) {
+ if (e == 0 && !key->id)
+ key->id = keyid;
+ return e;
+ }
+ }
+
+ if (publiconly) {
+ for (i = 0; fmts[i]; i++) {
+ sprintf(buf, fmts[i], keyid, "pub");
+ e = find_key_file(key, buf);
+ if (e != RS_ERR_KEY_NOT_FOUND) {
+ if (e == 0 && !key->id)
+ key->id = keyid;
+ return e;
+ }
+ }
+ }
+
+ rs_error(NULL, NULL, "cannot find key file %s", buf);
+ return RS_ERR_KEY_NOT_FOUND;
+}
diff --git a/tool/rabbitsign-src/autokeys.h b/tool/rabbitsign-src/autokeys.h
new file mode 100644
index 0000000..9880eab
--- /dev/null
+++ b/tool/rabbitsign-src/autokeys.h
@@ -0,0 +1,47 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+struct pubkeyinfo {
+ unsigned long id;
+ const char* n;
+} known_pub_keys[] =
+ {{ 0x0101, "406104CDFAD955D41F1ECCB9B622007FE8BC75E8B28DA178334755FEF27C564D47B04FD82498C163B762991C68CF64E29236BC41A4C1BCB9793B6EE965407C74BC" },
+ { 0x0102, "4085F11FF810591B84875FDE4C92A5961CDD233A9B7ED76E8CFF65128C71420FCCC80E375DC8D2A8551AE2BEB9FD41654CE7B0A95E32BE9997750407904560BEFC" },
+ { 0x0103, "40ED0236FD3D8B0CBA88C1CECFA549F8A838CDBAC487F9253F6C67F20C9627984FEA0D0A0BA035424C7B9F5E702286CEDCC66D2DA93320F7071BF2C93C59DE6B91" },
+ { 0x010A, "4005D1EB8485AA14C983FFA04031B27C89950C3D7F4181FE603A353F48DE0933DFE1173BDD2E14FEB7325BAA35A12F21804DCFD30E56119C1305D348A77BCF448F" },
+ { 0x01, "40F78D55E9A40A92D11D5C1446BFCEA74C8368BE1A81B6BA1596970E6D5932D933B86FF3CEA6B381CE65F5E383BDB02C82F33B8190375D0B40DEF2F1FE3CCA49AD" },
+ { 0x02, "4081396D55C0989BC949FA30821FFE61C9441EDC3827D0E89EEE16DDEF697634B8E10B8B7F42FE7CC1A7478606D6D09F6FE96365E71E3D2AAA7C8D91068F1DFAF3" },
+ { 0x03, "40E7C21F66BD1116F2F4F691121F3330060E24C8C7A1858D49636E24E80015F3AA25C2F6033AB39067D453945ABD8A5F4CFAFADABAF8BA2BFB88895A04B5D47689" },
+ { 0x04, "408FE528B340EB1C88B505B2354BAADF47F3616D92CB532E7E5A2A0DFF1C4E4283CEEA2B2F7AD5F28B7E4BE4F3F4C99CABA0D98A8E5F2BE15E2AAC7CED0940EF82" },
+ { 0x08, "40110510EE17B0A300E2BB27441F266843EDB541BAC1077AC203CF18ABB7800F8F0E259495F80D863C49C4EE7E9FB1FE03488A140C7CD5A54CE148C8CE22B00783" },
+ { 0x0A, "40B11C71D4EA2C13C9AB2E501C6085FEC87FF3B88BFD783EAC43351E1B10F65AD31C79C1268F75051DC8FC008EBF593AE5912E8B653975C13127E2B60A0BEF5FEF" },
+ { 0, 0 }};
+
+struct privkeyinfo {
+ unsigned long id;
+ const char* n;
+ const char* p;
+ const char* q;
+ const char* d;
+} known_priv_keys[] =
+ {{ 0x0104, "40AD2431DA2297E4175EAC61A3154FA3D847115794DD330AB7FF36BA59FEDA195FEA7C16743BD7BCED8A0DA885E5E5C34D5BF20D0AB3EF9181ED39BA2C4D898E87",
+ "205B2E54E9B5C1FE26CE93261478D3873F3FC41BFFF1F5F934D7A5793A43C1C21C", "2197F7707B94079B73858720BF6D4909AB3BEDA1BA9B93112B041340A16ED597B604", 0 },
+ { 0x05, "406BABF27E9BF1826FD46CBF934E3360EF1F1D3D09D6C74E9DF78049D01A42F584BD383A10E64330C2EE6F1B1C5162789E91E94677900F85D98E7D99F49B30A2BF",
+ /* "20F59BA0274F1CA6231A882B053AAD9A2B80EBE9D2B6E9FD1CDCFCE1AD9D9414D3", "20DFED657A28DE2BFF75DE4F1AEBB7555859779DA38A671B7C76F81B50F02A6AE8", */
+ 0, 0, "40E131D6636091E0F0EB3F6444FA2DABB7744FD4DDCF54018AD906C38A0789180D05C7A9275A9149819B05F279F357CEF3A0C53855AF90992572E0F09E3DC2B970" },
+ { 0, 0, 0, 0, 0 }};
diff --git a/tool/rabbitsign-src/cmdline.c b/tool/rabbitsign-src/cmdline.c
new file mode 100644
index 0000000..af4cb45
--- /dev/null
+++ b/tool/rabbitsign-src/cmdline.c
@@ -0,0 +1,112 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#ifdef HAVE_STRING_H
+# include
+#else
+# ifdef HAVE_STRINGS_H
+# include
+# endif
+#endif
+
+#include "rabbitsign.h"
+#include "internal.h"
+
+#if !defined(strchr) && !defined(HAVE_STRCHR) && defined(HAVE_INDEX)
+# define strchr index
+#endif
+
+/*
+ * Parse and return next command line option.
+ */
+int rs_parse_cmdline(int argc, char** argv, const char* optstring,
+ int* i, int* j, const char** arg)
+{
+ char c;
+ char* p;
+
+ if (*i >= argc)
+ return RS_CMDLINE_FINISHED;
+
+ if (argv[*i][0] != '-' || argv[*i][1] == 0) {
+ *arg = argv[*i];
+ (*i)++;
+ *j = 1;
+ return RS_CMDLINE_FILENAME;
+ }
+
+ if (argv[*i][1] == '-') {
+ if (!strcasecmp(argv[*i], "--help")) {
+ (*i)++;
+ *j = 1;
+ return RS_CMDLINE_HELP;
+ }
+ else if (!strcasecmp(argv[*i], "--version")) {
+ (*i)++;
+ *j = 1;
+ return RS_CMDLINE_VERSION;
+ }
+ else {
+ rs_error(NULL, NULL, "unrecognized option %s (try --help)", argv[*i]);
+ return RS_CMDLINE_ERROR;
+ }
+ }
+
+ c = argv[*i][*j];
+
+ if (c == ':' || !(p = strchr(optstring, c))) {
+ rs_error(NULL, NULL, "unrecognized option -%c (try --help)", c);
+ return RS_CMDLINE_ERROR;
+ }
+
+ if (p[1] == ':') {
+ if (argv[*i][*j + 1]) {
+ *arg = &argv[*i][*j + 1];
+ (*i)++;
+ *j = 1;
+ return c;
+ }
+ else {
+ (*i) += 2;
+ *j = 1;
+ if (*i > argc) {
+ rs_error(NULL, NULL, "-%c: requires an argument", c);
+ return RS_CMDLINE_ERROR;
+ }
+ *arg = argv[*i - 1];
+ return c;
+ }
+ }
+ else {
+ if (argv[*i][*j + 1]) {
+ (*j)++;
+ }
+ else {
+ (*i)++;
+ *j = 1;
+ }
+ *arg = NULL;
+ return c;
+ }
+}
diff --git a/tool/rabbitsign-src/error.c b/tool/rabbitsign-src/error.c
new file mode 100644
index 0000000..031f2a0
--- /dev/null
+++ b/tool/rabbitsign-src/error.c
@@ -0,0 +1,131 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+
+#ifdef HAVE_STRING_H
+# include
+#else
+# ifdef HAVE_STRINGS_H
+# include
+# endif
+#endif
+
+#include "rabbitsign.h"
+#include "internal.h"
+
+static const char* progname;
+static int verbose;
+static RSMessageFunc errorfunc, messagefunc;
+static void *errorfuncdata, *messagefuncdata;
+
+void rs_set_progname(s)
+ const char* s;
+{
+ progname = s;
+}
+
+void rs_set_verbose(v)
+ int v;
+{
+ verbose = v;
+}
+
+void rs_set_error_func(RSMessageFunc func, void* data)
+{
+ errorfunc = func;
+ errorfuncdata = data;
+}
+
+void rs_set_message_func(RSMessageFunc func, void* data)
+{
+ messagefunc = func;
+ messagefuncdata = data;
+}
+
+static void print_message(const RSKey* key, const RSProgram* prgm,
+ const char* msg)
+{
+ if (prgm && prgm->filename)
+ fprintf(stderr, "%s: ", prgm->filename);
+ else if (key && key->filename)
+ fprintf(stderr, "%s: ", key->filename);
+ else if (progname)
+ fprintf(stderr, "%s: ", progname);
+ fputs(msg, stderr);
+ fputc('\n', stderr);
+}
+
+/* Display a critical error */
+void rs_error(const RSKey* key, const RSProgram* prgm, const char* fmt, ...)
+{
+ char msg[512];
+ va_list ap;
+
+ va_start(ap, fmt);
+ strcpy(msg, "error: ");
+ rs_vsnprintf(msg + 7, sizeof(msg) - 7, fmt, ap);
+ va_end(ap);
+
+ if (errorfunc)
+ (*errorfunc)(key, prgm, msg, errorfuncdata);
+ else
+ print_message(key, prgm, msg);
+}
+
+/* Display a warning message */
+void rs_warning(const RSKey* key, const RSProgram* prgm, const char* fmt, ...)
+{
+ char msg[512];
+ va_list ap;
+
+ va_start(ap, fmt);
+ strcpy(msg, "warning: ");
+ rs_vsnprintf(msg + 9, sizeof(msg) - 9, fmt, ap);
+ va_end(ap);
+
+ if (errorfunc)
+ (*errorfunc)(key, prgm, msg, errorfuncdata);
+ else
+ print_message(key, prgm, msg);
+}
+
+/* Display an informative message */
+void rs_message(int level, const RSKey* key, const RSProgram* prgm,
+ const char* fmt, ...)
+{
+ char msg[512];
+ va_list ap;
+
+ if (level > verbose)
+ return;
+
+ va_start(ap, fmt);
+ rs_vsnprintf(msg, sizeof(msg), fmt, ap);
+ va_end(ap);
+
+ if (messagefunc)
+ (*messagefunc)(key, prgm, msg, messagefuncdata);
+ else
+ print_message(key, prgm, msg);
+}
diff --git a/tool/rabbitsign-src/graphlink.c b/tool/rabbitsign-src/graphlink.c
new file mode 100644
index 0000000..06e6e3f
--- /dev/null
+++ b/tool/rabbitsign-src/graphlink.c
@@ -0,0 +1,118 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#ifdef HAVE_STRING_H
+# include
+#else
+# ifdef HAVE_STRINGS_H
+# include
+# endif
+#endif
+
+#ifdef TIME_WITH_SYS_TIME
+# include
+# include
+#else
+# ifdef TM_IN_SYS_TIME
+# include
+# else
+# include
+# endif
+#endif
+
+#include "rabbitsign.h"
+#include "internal.h"
+
+#define BCD(x) ((x) + 6 * ((x)/10))
+
+/*
+ * Write a TIFL header to a file.
+ */
+int rs_write_tifl_header(FILE* outfile, /* file to write to */
+ int is_hex, /* is file in hex format? */
+ int major, /* major version # */
+ int minor, /* minor version # */
+ int month, /* current month */
+ int day, /* current day */
+ int year, /* current year */
+ const char* name, /* name of program */
+ int calctype, /* calculator type */
+ int datatype, /* data type */
+ unsigned long filesize) /* size of data */
+{
+ unsigned char buf[78];
+ time_t t;
+ struct tm* tm;
+
+ memset(buf, 0, 78);
+
+ strcpy((char*) buf, "**TIFL**");
+
+ buf[8] = major;
+ buf[9] = minor;
+
+ if (is_hex) {
+ buf[10] = 0x01;
+ buf[11] = 0x88;
+ }
+ else {
+ buf[10] = 0;
+ buf[11] = 0;
+ }
+
+ if (!month && !day && !year) {
+ time(&t);
+ tm = localtime(&t);
+ month = tm->tm_mon + 1;
+ day = tm->tm_mday;
+ year = tm->tm_year + 1900;
+ }
+
+ buf[12] = BCD(month);
+ buf[13] = BCD(day);
+ buf[14] = BCD(year / 100);
+ buf[15] = BCD(year % 100);
+
+ buf[16] = strlen(name);
+ if (buf[16] > 8)
+ buf[16] = 8;
+
+ strncpy((char*) buf + 17, name, 8);
+
+ buf[48] = calctype;
+ buf[49] = datatype;
+
+ buf[74] = filesize & 0xff;
+ buf[75] = (filesize >> 8) & 0xff;
+ buf[76] = (filesize >> 16) & 0xff;
+ buf[77] = (filesize >> 24) & 0xff;
+
+ if (fwrite(buf, 1, 78, outfile) != 78) {
+ rs_error(NULL, NULL, "file I/O error");
+ return RS_ERR_FILE_IO;
+ }
+
+ return RS_SUCCESS;
+}
+
diff --git a/tool/rabbitsign-src/header.c b/tool/rabbitsign-src/header.c
new file mode 100644
index 0000000..36bbe5b
--- /dev/null
+++ b/tool/rabbitsign-src/header.c
@@ -0,0 +1,169 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#include "rabbitsign.h"
+#include "internal.h"
+
+/*
+ * Get length of a header field.
+ */
+void rs_get_field_size (const unsigned char* data, /* Data */
+ unsigned long* fieldstart, /* Offset to start
+ of field
+ contents */
+ unsigned long* fieldsize) /* Length of field
+ contents */
+{
+ switch (data[1] & 0x0f) {
+ case 0x0D:
+ if (fieldstart) *fieldstart = 3;
+ if (fieldsize) *fieldsize = data[2];
+ break;
+
+ case 0x0E:
+ if (fieldstart) *fieldstart = 4;
+ if (fieldsize) *fieldsize = ((data[2] << 8) | data[3]);
+ break;
+
+ case 0x0F:
+ if (fieldstart) *fieldstart = 6;
+ if (fieldsize) {
+ *fieldsize = (((unsigned long) data[2] << 24)
+ | ((unsigned long) data[3] << 16)
+ | ((unsigned long) data[4] << 8)
+ | (unsigned long) data[5]);
+ }
+ break;
+
+ default:
+ if (fieldstart) *fieldstart = 2;
+ if (fieldsize) *fieldsize = (data[1] & 0x0f);
+ break;
+ }
+}
+
+/* Set length of a header field. */
+int rs_set_field_size (unsigned char* data,
+ unsigned long fieldsize)
+{
+ switch (data[1] & 0x0f) {
+ case 0x0D:
+ if (fieldsize > 0xff)
+ return -1;
+ data[2] = fieldsize;
+ return 0;
+
+ case 0x0E:
+ if (fieldsize > 0xfffful)
+ return -1;
+ data[2] = (fieldsize >> 8) & 0xff;
+ data[3] = fieldsize & 0xff;
+ return 0;
+
+ case 0x0F:
+ if (fieldsize > 0xfffffffful)
+ return -1;
+ data[2] = (fieldsize >> 24) & 0xff;
+ data[3] = (fieldsize >> 16) & 0xff;
+ data[4] = (fieldsize >> 8) & 0xff;
+ data[5] = fieldsize & 0xff;
+ return 0;
+
+ default:
+ if (fieldsize > 0x0C)
+ return -1;
+ data[1] = (data[1] & 0xf0) | fieldsize;
+ return 0;
+ }
+}
+
+/*
+ * Find a given header field in the data.
+ */
+int rs_find_app_field(unsigned int type, /* Type of field to
+ search for (e.g.,
+ 0x8040 to search
+ for the name) */
+ const unsigned char* data, /* Data to search */
+ unsigned long length, /* Maximum length of
+ data to search */
+ unsigned long* fieldhead, /* Offset to field
+ type bytes, if
+ found */
+ unsigned long* fieldstart, /* Offset to start of
+ field contents, if
+ found */
+ unsigned long* fieldsize) /* Length of field
+ contents, if
+ found */
+{
+ unsigned char b1, b2;
+ unsigned long pos = 0;
+ unsigned long fstart, fsize;
+
+ b1 = ((type >> 8) & 0xff);
+ b2 = (type & 0xf0);
+
+ while (pos < length) {
+ if (data[pos] == b1 && (data[pos + 1] & 0xf0) == b2) {
+ rs_get_field_size(data + pos, &fstart, fieldsize);
+ if (fieldhead) *fieldhead = pos;
+ if (fieldstart) *fieldstart = pos + fstart;
+ return 0;
+ }
+
+ rs_get_field_size(data + pos, &fstart, &fsize);
+ pos += fstart + fsize;
+ }
+
+ return -1;
+}
+
+/*
+ * Get value of a numeric header field.
+ *
+ * Return 0 if field is not found, or if its contents are longer than
+ * 4 bytes.
+ */
+unsigned long rs_get_numeric_field (unsigned int type,
+ const unsigned char* data,
+ unsigned long length)
+{
+ unsigned long fstart, fsize, value;
+
+ if (rs_find_app_field(type, data, length, NULL, &fstart, &fsize))
+ return 0;
+
+ if (fsize > 4)
+ return 0;
+
+ value = 0;
+ while (fsize > 0) {
+ value <<= 8;
+ value |= data[fstart];
+ fstart++;
+ fsize--;
+ }
+ return value;
+}
diff --git a/tool/rabbitsign-src/input.c b/tool/rabbitsign-src/input.c
new file mode 100644
index 0000000..2f0ce37
--- /dev/null
+++ b/tool/rabbitsign-src/input.c
@@ -0,0 +1,520 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#ifdef HAVE_STRING_H
+# include
+#else
+# ifdef HAVE_STRINGS_H
+# include
+# endif
+#endif
+
+#include "rabbitsign.h"
+#include "internal.h"
+
+/*
+ * Determine the type of an unknown program, if possible.
+ */
+static void guess_type(RSProgram* prgm, int is_hex)
+{
+ const unsigned char* hdr;
+ unsigned long hdrstart, hdrsize, keyid, fieldstart, fieldsize;
+
+ /* Z80 OSes have a detached program header */
+
+ if (prgm->header_length > 2 && prgm->header[0] == 0x80) {
+ rs_get_field_size(prgm->header, &hdrstart, NULL);
+ hdr = prgm->header + hdrstart;
+ hdrsize = prgm->header_length - hdrstart;
+ keyid = rs_get_numeric_field(0x8010, hdr, hdrsize);
+
+ prgm->datatype = RS_DATA_OS;
+
+ if ((keyid & 0xff) == 0x02) {
+ prgm->calctype = RS_CALC_TI73;
+ }
+ else {
+ prgm->calctype = RS_CALC_TI83P;
+ }
+ }
+ else if (prgm->length > 2) {
+ rs_get_field_size(prgm->data, &hdrstart, NULL);
+ hdr = prgm->data + hdrstart;
+ hdrsize = prgm->length - hdrstart;
+ if (hdrsize > 128)
+ hdrsize = 128;
+
+ /* Z80 apps and 68k OSes have field type 0x8000 */
+
+ if (prgm->data[0] == 0x80 && (prgm->data[1] & 0xf0) == 0x00) {
+ keyid = rs_get_numeric_field(0x8010, hdr, hdrsize);
+
+ switch (keyid & 0xff) {
+ case 0x02:
+ prgm->calctype = RS_CALC_TI73;
+ prgm->datatype = RS_DATA_APP;
+ break;
+
+ case 0x04:
+ case 0x0A:
+ prgm->calctype = RS_CALC_TI83P;
+ prgm->datatype = RS_DATA_APP;
+ break;
+
+ case 0x03:
+ case 0x09:
+ prgm->calctype = RS_CALC_TI89;
+ prgm->datatype = RS_DATA_OS;
+ break;
+
+ case 0x01:
+ case 0x08:
+ prgm->calctype = RS_CALC_TI92P;
+ prgm->datatype = RS_DATA_OS;
+ break;
+
+ default:
+ if (is_hex) {
+ prgm->calctype = RS_CALC_TI83P;
+ prgm->datatype = RS_DATA_APP;
+ }
+ break;
+ }
+ }
+
+ /* 68k apps have field type 0x8100 */
+
+ else if (prgm->data[0] == 0x81 && (prgm->data[1] & 0xf0) == 0x00) {
+ keyid = rs_get_numeric_field(0x8110, hdr, hdrsize);
+ prgm->datatype = RS_DATA_APP;
+
+ switch (keyid & 0xff) {
+ case 0x03:
+ case 0x09:
+ prgm->calctype = RS_CALC_TI89;
+ break;
+
+ case 0x01:
+ case 0x08:
+ prgm->calctype = RS_CALC_TI92P;
+ break;
+ }
+ }
+
+ /* Certificates have field type 0x0300 */
+
+ else if (prgm->data[0] == 0x03 && (prgm->data[1] & 0xf0) == 0x00) {
+ prgm->datatype = RS_DATA_CERT;
+
+ if (!rs_find_app_field(0x0400, hdr, hdrsize,
+ NULL, &fieldstart, &fieldsize)
+ && fieldsize >= 1) {
+ switch (hdr[fieldstart]) {
+ case 0x02:
+ prgm->calctype = RS_CALC_TI73;
+ break;
+
+ case 0x04:
+ case 0x0A:
+ prgm->calctype = RS_CALC_TI83P;
+ break;
+
+ case 0x03:
+ case 0x09:
+ prgm->calctype = RS_CALC_TI89;
+ break;
+
+ case 0x01:
+ case 0x08:
+ prgm->calctype = RS_CALC_TI92P;
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Read the contents of a binary file into an RSProgram.
+ */
+static int read_file_binary(RSProgram* prgm,
+ FILE* f,
+ unsigned long filesize)
+{
+ unsigned char buf[1024];
+ size_t count;
+
+ if (filesize) {
+ while (filesize > 0) {
+ if (filesize > 1024)
+ count = fread(buf, 1, 1024, f);
+ else
+ count = fread(buf, 1, filesize, f);
+
+ if (count > 0)
+ rs_program_append_data(prgm, buf, count);
+ else
+ break;
+
+ filesize -= count;
+ }
+ }
+ else {
+ do {
+ count = fread(buf, 1, 1024, f);
+ if (count > 0) {
+ rs_program_append_data(prgm, buf, count);
+ }
+ } while (count > 0);
+ }
+
+ if (!prgm->calctype || !prgm->datatype)
+ guess_type(prgm, 0);
+ return RS_SUCCESS;
+}
+
+/*
+ * Find a given page in the list of page numbers (or add it to the
+ * end.)
+ */
+static int getpageidx(RSProgram* prgm, /* program */
+ unsigned int pagenum) /* page number */
+{
+ int i;
+ unsigned int* array;
+
+ for (i = 0; i < prgm->npagenums; i++)
+ if (prgm->pagenums[i] == pagenum)
+ return i;
+
+ if (!(array = rs_realloc(prgm->pagenums, (i + 1) * sizeof(unsigned int))))
+ return 0;
+ prgm->pagenums = array;
+ prgm->npagenums = i + 1;
+ prgm->pagenums[i] = pagenum;
+ return i;
+}
+
+/*
+ * Read an Intel/TI hex file into an RSProgram.
+ *
+ * Note that the first ':' is assumed to have been read already.
+ */
+static int read_file_hex(RSProgram* prgm,
+ FILE* f,
+ unsigned int flags)
+{
+ int c;
+ unsigned int nbytes, addr, rectype, sum, i, b, value;
+ unsigned int pagenum = 0, pageidx = 0, lastaddr = 0;
+ unsigned long offset;
+ unsigned char data[256];
+ unsigned char* sigp;
+ int nparts = 0;
+ int possibly_os_header = 1;
+
+ rs_free(prgm->pagenums);
+ if (!(prgm->pagenums = rs_malloc(sizeof(unsigned int))))
+ return RS_ERR_OUT_OF_MEMORY;
+ prgm->pagenums[0] = 0;
+ prgm->npagenums = 1;
+
+ while (!feof(f) && !ferror(f)) {
+ if (3 > fscanf(f, "%2X%4X%2X", &nbytes, &addr, &rectype)) {
+ rs_error(NULL, prgm, "invalid hex data (following %X:%X)",
+ pagenum, lastaddr);
+ return RS_ERR_HEX_SYNTAX;
+ }
+
+ /* Read data bytes */
+
+ sum = nbytes + addr + (addr >> 8) + rectype;
+ value = 0;
+ for (i = 0; i < nbytes; i++) {
+ if (1 > fscanf(f, "%2X", &b)) {
+ rs_error(NULL, prgm, "invalid hex data (at %X:%X)",
+ pagenum, addr);
+ return RS_ERR_HEX_SYNTAX;
+ }
+ data[i] = b;
+ sum += b;
+ value = (value << 8) + b;
+ }
+
+ /* Read checksum */
+
+ c = fgetc(f);
+ if (c == 'X') {
+ c = fgetc(f);
+ if (c != 'X') {
+ rs_error(NULL, prgm, "invalid hex data (at %X:%X)",
+ pagenum, addr);
+ return RS_ERR_HEX_SYNTAX;
+ }
+ }
+ else {
+ ungetc(c, f);
+ if (1 > fscanf(f, "%2X", &b)) {
+ rs_error(NULL, prgm, "invalid hex data (at %X:%X)",
+ pagenum, addr);
+ return RS_ERR_HEX_SYNTAX;
+ }
+ sum += b;
+ if (sum & 0xff)
+ rs_warning(NULL, prgm, "incorrect checksum (at %X:%X)",
+ pagenum, addr);
+ }
+
+ if (rectype == 0 && nbytes > 0) {
+ /* Record type 0: program data */
+
+ if (addr & 0xff00)
+ possibly_os_header = 0;
+
+ addr &= 0x3fff;
+
+ /* if program does not start at addr 0000 (or 4000), assume
+ unsorted */
+ if (addr && prgm->length == 0)
+ flags &= ~RS_INPUT_SORTED;
+
+ if ((flags & RS_INPUT_SORTED) && !addr && lastaddr) {
+ /* automatically switch to next page */
+ pagenum++;
+ pageidx = getpageidx(prgm, pagenum);
+ if (!pageidx)
+ return RS_ERR_OUT_OF_MEMORY;
+ }
+ else if (addr < lastaddr)
+ flags &= ~RS_INPUT_SORTED;
+
+ if (nparts == 2 && prgm->header_length) {
+ /* Reading an OS signature */
+ if (addr + nbytes > prgm->signature_length) {
+ if (!(sigp = rs_realloc(prgm->signature, addr + nbytes)))
+ return RS_ERR_OUT_OF_MEMORY;
+
+ prgm->signature = sigp;
+ if (addr > prgm->signature_length) {
+ memset(prgm->signature + prgm->signature_length, 0xff,
+ addr - prgm->signature_length);
+ }
+ prgm->signature_length = addr + nbytes;
+ }
+ memcpy(prgm->signature + addr, data, nbytes);
+ }
+ else {
+ /* Reading normal program data */
+ offset = ((unsigned long) pageidx << 14) | addr;
+ if (offset + nbytes <= prgm->length) {
+ memcpy(prgm->data + offset, data, nbytes);
+ }
+ else {
+ rs_program_set_length(prgm, offset);
+ rs_program_append_data(prgm, data, nbytes);
+ }
+ }
+
+ lastaddr = addr;
+ }
+ else if (rectype == 1) {
+ /* Record type 1: "end of file" */
+ nparts++;
+ if (nparts == 3 && prgm->header_length)
+ break;
+ }
+ else if (rectype == 2 || rectype == 4) {
+ /* Record type 2 or 4: extended address */
+ possibly_os_header = 0;
+ flags &= ~RS_INPUT_SORTED;
+ if (nparts < 2) {
+ pagenum = value;
+ pageidx = getpageidx(prgm, pagenum);
+ if (pagenum && !pageidx)
+ return RS_ERR_OUT_OF_MEMORY;
+ }
+ }
+
+ do {
+ c = fgetc(f);
+ } while (c == '\n' || c == '\r' || c == ' ');
+
+ if (c == EOF)
+ break;
+ else if (c != ':') {
+ if (rectype == 1)
+ break;
+ else {
+ rs_error(NULL, prgm, "invalid hex data (following %X:%X)",
+ pagenum, lastaddr);
+ return RS_ERR_HEX_SYNTAX;
+ }
+ }
+
+ if (rectype == 1 && nparts == 1 && prgm->length > 0
+ && possibly_os_header) {
+ /* Just finished reading OS header */
+ flags &= ~RS_INPUT_SORTED;
+ pagenum = pageidx = 0;
+
+ rs_free(prgm->header);
+ if (!(prgm->header = rs_malloc(prgm->length)))
+ return RS_ERR_OUT_OF_MEMORY;
+
+ memcpy(prgm->header, prgm->data, prgm->length);
+ prgm->header_length = prgm->length;
+ prgm->length = 0;
+ possibly_os_header = 0;
+ }
+ }
+
+ if (!prgm->calctype || !prgm->datatype)
+ guess_type(prgm, 1);
+ return RS_SUCCESS;
+}
+
+/*
+ * Check if calc/data type matches expected type (or any recognized
+ * type, if none was specified.)
+ */
+static int check_tifl_type(int calctype,
+ int datatype,
+ int calctype_expected,
+ int datatype_expected)
+{
+ if (calctype_expected) {
+ if (calctype_expected != calctype)
+ return 0;
+ }
+ else {
+ if (calctype != RS_CALC_TI73 && calctype != RS_CALC_TI83P
+ && calctype != RS_CALC_TI89 && calctype != RS_CALC_TI92P)
+ return 0;
+ }
+
+ if (datatype_expected) {
+ if (datatype_expected != datatype)
+ return 0;
+ }
+ else {
+ if (datatype != RS_DATA_APP && datatype != RS_DATA_OS)
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Read program contents from a file.
+ *
+ * Various file formats are supported:
+ *
+ * - Raw binary (must begin with the value 0x80 or 0x81)
+ * - Plain Intel/TI hex
+ * - Binary TIFL (89k, 89u, ...)
+ * - Hex TIFL (8xk, 8xu, ...)
+ *
+ * Note: on platforms where it matters, all input files must be opened
+ * in "binary" mode.
+ */
+int rs_read_program_file(RSProgram* prgm, /* program */
+ FILE* f, /* file */
+ const char* fname, /* file name */
+ unsigned int flags) /* option flags */
+{
+ int c;
+ unsigned char tiflbuf[78];
+ unsigned long tiflsize, i;
+ int e;
+
+ rs_program_set_length(prgm, 0);
+ prgm->header_length = 0;
+ prgm->signature_length = 0;
+ prgm->npagenums = 0;
+
+ rs_free(prgm->filename);
+ prgm->filename = rs_strdup(fname);
+ if (fname && !prgm->filename)
+ return RS_ERR_OUT_OF_MEMORY;
+
+ if (flags & RS_INPUT_BINARY)
+ return read_file_binary(prgm, f, 0);
+
+ c = fgetc(f);
+ if (c == 0x80 || c == 0x81) {
+ tiflbuf[0] = c;
+ if ((e = rs_program_append_data(prgm, tiflbuf, 1)))
+ return e;
+ return read_file_binary(prgm, f, 0);
+ }
+
+ while (!feof(f) && !ferror(f)) {
+ if (c == ':') {
+ return read_file_hex(prgm, f, flags);
+ }
+ else if (c == '*') {
+ if (fread(tiflbuf, 1, 78, f) < 78
+ || strncmp((char*) tiflbuf, "*TIFL**", 7)) {
+ rs_error(NULL, prgm, "unknown input file format");
+ return RS_ERR_UNKNOWN_FILE_FORMAT;
+ }
+
+ tiflsize = ((unsigned long) tiflbuf[73]
+ | ((unsigned long) tiflbuf[74] << 8)
+ | ((unsigned long) tiflbuf[75] << 16)
+ | ((unsigned long) tiflbuf[76] << 24));
+
+ if (check_tifl_type(tiflbuf[47], tiflbuf[48],
+ prgm->calctype, prgm->datatype)) {
+ prgm->calctype = tiflbuf[47];
+ prgm->datatype = tiflbuf[48];
+
+ if (tiflbuf[77] == ':')
+ return read_file_hex(prgm, f, 0);
+ else {
+ if ((e = rs_program_append_data(prgm, tiflbuf + 77, 1)))
+ return e;
+ return read_file_binary(prgm, f, tiflsize ? tiflsize - 1 : 0);
+ }
+ }
+ else {
+ /* extra data (license, certificate, etc.) -- ignore */
+ if (fseek(f, tiflsize - 1, SEEK_CUR)) {
+ for (i = 0; i < tiflsize - 1; i++) {
+ if (fgetc(f) == EOF) {
+ rs_error(NULL, prgm, "unexpected EOF");
+ return RS_ERR_UNKNOWN_FILE_FORMAT;
+ }
+ }
+ }
+ }
+ }
+
+ c = fgetc(f);
+ }
+
+ rs_error(NULL, prgm, "unknown input file format");
+ return RS_ERR_UNKNOWN_FILE_FORMAT;
+}
+
diff --git a/tool/rabbitsign-src/internal.h b/tool/rabbitsign-src/internal.h
new file mode 100644
index 0000000..d3fc1b5
--- /dev/null
+++ b/tool/rabbitsign-src/internal.h
@@ -0,0 +1,111 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __RABBITSIGN_INTERNAL_H__
+#define __RABBITSIGN_INTERNAL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**** Memory management (mem.c) ****/
+
+#define rs_malloc(nnn) rs_realloc(0, (nnn))
+#define rs_free(ppp) rs_realloc((ppp), 0)
+void* rs_realloc (void* ptr, unsigned long count) RS_ATTR_MALLOC;
+char* rs_strdup (const char* str) RS_ATTR_MALLOC;
+
+
+/**** Rabin signature functions (rabin.c) ****/
+
+/* Compute a Rabin signature and the useful value of f. */
+RSStatus rs_sign_rabin (mpz_t res, int* f, const mpz_t hash,
+ int rootnum, RSKey* key);
+
+/* Check that the given Rabin signature is valid. */
+RSStatus rs_validate_rabin (const mpz_t sig, int f, const mpz_t hash,
+ const RSKey* key);
+
+
+/**** RSA signature functions (rsa.c) ****/
+
+/* Compute an RSA signature. */
+RSStatus rs_sign_rsa (mpz_t res, const mpz_t hash, RSKey* key);
+
+/* Check that the given RSA signature is valid. */
+RSStatus rs_validate_rsa (const mpz_t sig, const mpz_t hash,
+ const RSKey* key);
+
+
+/**** TIFL file output (graphlink.c) ****/
+
+/* Write TIFL header to a file. */
+RSStatus rs_write_tifl_header (FILE* f, int is_hex, int major, int minor,
+ int month, int day, int year,
+ const char* name, int calctype, int datatype,
+ unsigned long filesize);
+
+
+/**** Type <-> string conversions (typestr.c) ****/
+
+/* Get default file suffix for a given calc/data type. */
+const char* rs_type_to_suffix (RSCalcType calctype, RSDataType datatype,
+ int hexonly);
+
+/* Get implied calc/data type for a given file suffix. */
+int rs_suffix_to_type (const char* suff, RSCalcType* calctype,
+ RSDataType* datatype);
+
+/* Get a human-readable description of a calculator type. */
+const char* rs_calc_type_to_string (RSCalcType calctype);
+
+/* Get a human-readable description of a data type. */
+const char* rs_data_type_to_string (RSDataType datatype);
+
+
+/**** Command line option parsing (cmdline.c) ****/
+
+#define RS_CMDLINE_FINISHED 0
+#define RS_CMDLINE_FILENAME '#'
+#define RS_CMDLINE_HELP '!'
+#define RS_CMDLINE_VERSION '@'
+#define RS_CMDLINE_ERROR '?'
+
+int rs_parse_cmdline(int argc, char** argv, const char* optstring,
+ int* i, int* j, const char** arg);
+
+
+/**** Error/message logging (error.c) ****/
+
+/* Display an error message */
+void rs_error (const RSKey* key, const RSProgram* prgm,
+ const char* fmt, ...) RS_ATTR_PRINTF(3,4);
+
+/* Display a warning message */
+void rs_warning (const RSKey* key, const RSProgram* prgm,
+ const char* fmt, ...) RS_ATTR_PRINTF(3,4);
+
+/* Display an informational message */
+void rs_message (int level, const RSKey* key, const RSProgram* prgm,
+ const char* fmt, ...) /*RS_ATTR_PRINTF(4,5)*/;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __RABBITSIGN_INTERNAL_H__ */
diff --git a/tool/rabbitsign-src/keys.c b/tool/rabbitsign-src/keys.c
new file mode 100644
index 0000000..d92f36b
--- /dev/null
+++ b/tool/rabbitsign-src/keys.c
@@ -0,0 +1,234 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#ifdef HAVE_STRING_H
+# include
+#else
+# ifdef HAVE_STRINGS_H
+# include
+# endif
+#endif
+
+#include "rabbitsign.h"
+#include "internal.h"
+
+/*
+ * Create a new key.
+ */
+RSKey* rs_key_new()
+{
+ RSKey* key = rs_malloc(sizeof(RSKey));
+
+ if (!key)
+ return NULL;
+
+ key->filename = NULL;
+ key->id = 0;
+ mpz_init(key->n);
+ mpz_init(key->p);
+ mpz_init(key->q);
+ mpz_init(key->qinv);
+ mpz_init(key->d);
+
+ return key;
+}
+
+/*
+ * Free a key.
+ */
+void rs_key_free(RSKey* key)
+{
+ if (!key)
+ return;
+
+ rs_free(key->filename);
+ mpz_clear(key->n);
+ mpz_clear(key->p);
+ mpz_clear(key->q);
+ mpz_clear(key->qinv);
+ mpz_clear(key->d);
+ rs_free(key);
+}
+
+/*
+ * Parse a number written in TI's hexadecimal key format.
+ */
+static int parse_value(mpz_t dest, /* mpz to store result */
+ const char* str) /* string to parse */
+{
+ unsigned int count, b, i;
+ int n;
+ unsigned char buf[256];
+
+ if (1 > sscanf(str, "%2X%n", &count, &n) || n != 2
+ || (count * 2 + 2) > strlen(str))
+ return 1;
+
+ for (i = 0; i < count; i++) {
+ if (1 > sscanf(str + 2 + 2 * i, "%2X%n", &b, &n) || n != 2)
+ return 1;
+ buf[i] = b;
+ }
+
+ mpz_import(dest, i, -1, 1, 0, 0, buf);
+ return 0;
+}
+
+/*
+ * Read key from a file.
+ *
+ * Two formats of key file are supported:
+ *
+ * "Rabin" style (the type used by the TI-83 Plus SDK) consists of
+ * three lines: the public key (n) followed by its two factors (p and
+ * q.)
+ *
+ * "RSA" style (the type used by the TI-89/92 Plus SDK) also consists
+ * of three lines: the key ID, the public key (n), and the signing
+ * exponent (d).
+ *
+ * In either case, if we are only interested in validating signatures,
+ * the private key may be omitted.
+ *
+ * Note that "Rabin" style key files can be used to generate RSA
+ * signatures, but not vice versa.
+ */
+int rs_read_key_file(RSKey* key, /* key structure */
+ FILE* f, /* file to read */
+ const char* fname, /* file name */
+ int verify) /* 1 = check key validity */
+{
+ char buf[1024];
+ mpz_t tmp;
+
+ rs_free(key->filename);
+ key->filename = rs_strdup(fname);
+ if (fname && !key->filename)
+ return RS_ERR_OUT_OF_MEMORY;
+
+ if (!fgets(buf, sizeof(buf), f)) {
+ rs_error(key, NULL, "invalid key file syntax");
+ return RS_ERR_KEY_SYNTAX;
+ }
+
+ if (strlen(buf) < 11) {
+ if (1 > sscanf(buf, "%lX", &key->id)) {
+ rs_error(key, NULL, "invalid key file syntax");
+ return RS_ERR_KEY_SYNTAX;
+ }
+
+ if (!fgets(buf, sizeof(buf), f)
+ || parse_value(key->n, buf)) {
+ rs_error(key, NULL, "invalid key file syntax");
+ return RS_ERR_KEY_SYNTAX;
+ }
+
+ if (!fgets(buf, sizeof(buf), f)
+ || parse_value(key->d, buf))
+ mpz_set_ui(key->d, 0);
+ else if (verify) {
+ /* We can't truly verify the key without factoring n (which is
+ possible, given d, but would take a bit of work.) Instead,
+ test the key by performing a single RSA encryption and
+ decryption. */
+ mpz_init(tmp);
+ mpz_set_ui(tmp, 17);
+ mpz_powm(tmp, tmp, tmp, key->n);
+ mpz_powm(tmp, tmp, key->d, key->n);
+ if (mpz_cmp_ui(tmp, 17)) {
+ mpz_clear(tmp);
+ rs_error(key, NULL, "private key incorrect (de != 1 mod phi(n))");
+ return RS_ERR_INVALID_KEY;
+ }
+ mpz_clear(tmp);
+ }
+
+ mpz_set_ui(key->p, 0);
+ mpz_set_ui(key->q, 0);
+ mpz_set_ui(key->qinv, 0);
+ }
+ else {
+ if (parse_value(key->n, buf)) {
+ rs_error(key, NULL, "invalid key file");
+ return RS_ERR_KEY_SYNTAX;
+ }
+
+ if (!fgets(buf, sizeof(buf), f)
+ || parse_value(key->p, buf)
+ || !fgets(buf, sizeof(buf), f)
+ || parse_value(key->q, buf)) {
+ mpz_set_ui(key->p, 0);
+ mpz_set_ui(key->q, 0);
+ }
+ else if (verify) {
+ /* Verify that p * q = n (of course, that doesn't guarantee that
+ these are the only factors of n.) */
+ mpz_init(tmp);
+ mpz_mul(tmp, key->p, key->q);
+ if (mpz_cmp(tmp, key->n)) {
+ mpz_clear(tmp);
+ rs_error(key, NULL, "private key incorrect (pq != n)");
+ return RS_ERR_INVALID_KEY;
+ }
+ mpz_clear(tmp);
+ }
+
+ mpz_set_ui(key->qinv, 0);
+ mpz_set_ui(key->d, 0);
+ key->id = 0;
+ }
+
+ if (mpz_sgn(key->p) && mpz_sgn(key->q)) {
+ rs_message(2, key, NULL, "Loaded Rabin/RSA private key:");
+ rs_message(2, key, NULL, " n = %ZX", key->n);
+ rs_message(2, key, NULL, " p = %ZX", key->p);
+ rs_message(2, key, NULL, " q = %ZX", key->q);
+ }
+ else if (mpz_sgn(key->d)) {
+ rs_message(2, key, NULL, "Loaded RSA private key:");
+ rs_message(2, key, NULL, " n = %ZX", key->n);
+ rs_message(2, key, NULL, " d = %ZX", key->d);
+ }
+ else {
+ rs_message(2, key, NULL, "Loaded public key:");
+ rs_message(2, key, NULL, " n = %ZX", key->n);
+ }
+
+ return RS_SUCCESS;
+}
+
+/*
+ * Parse a number written in TI's hexadecimal key format.
+ */
+int rs_parse_key_value(mpz_t dest, /* mpz to store result */
+ const char* str) /* string to parse */
+{
+ if (parse_value(dest, str)) {
+ rs_error(NULL, NULL, "invalid key value syntax");
+ return RS_ERR_KEY_SYNTAX;
+ }
+ else {
+ return RS_SUCCESS;
+ }
+}
diff --git a/tool/rabbitsign-src/md5.c b/tool/rabbitsign-src/md5.c
new file mode 100644
index 0000000..d742c54
--- /dev/null
+++ b/tool/rabbitsign-src/md5.c
@@ -0,0 +1,419 @@
+/* md5.c - Functions to compute MD5 message digest of files or memory blocks
+ according to the definition of MD5 in RFC 1321 from April 1992.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ NOTE: The canonical source of this file is maintained with the GNU C
+ Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Ulrich Drepper , 1995. */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#if STDC_HEADERS || defined _LIBC
+# include
+# include
+#else
+# ifndef HAVE_MEMCPY
+# define memcpy(d, s, n) bcopy ((s), (d), (n))
+# endif
+#endif
+
+#include "md5.h"
+
+#ifdef _LIBC
+# include
+# if __BYTE_ORDER == __BIG_ENDIAN
+# define WORDS_BIGENDIAN 1
+# endif
+#endif
+
+#ifdef WORDS_BIGENDIAN
+# define SWAP(n) \
+ (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
+#else
+# define SWAP(n) (n)
+#endif
+
+
+/* This array contains the bytes used to pad the buffer to the next
+ 64-byte boundary. (RFC 1321, 3.1: Step 1) */
+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
+
+
+/* Initialize structure containing state of computation.
+ (RFC 1321, 3.3: Step 3) */
+void
+md5_init_ctx (ctx)
+ struct md5_ctx *ctx;
+{
+ ctx->A = 0x67452301;
+ ctx->B = 0xefcdab89;
+ ctx->C = 0x98badcfe;
+ ctx->D = 0x10325476;
+
+ ctx->total[0] = ctx->total[1] = 0;
+ ctx->buflen = 0;
+}
+
+/* Put result from CTX in first 16 bytes following RESBUF. The result
+ must be in little endian byte order.
+
+ IMPORTANT: On some systems it is required that RESBUF is correctly
+ aligned for a 32 bits value. */
+void *
+md5_read_ctx (ctx, resbuf)
+ const struct md5_ctx *ctx;
+ void *resbuf;
+{
+ ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
+ ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
+ ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
+ ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
+
+ return resbuf;
+}
+
+/* Process the remaining bytes in the internal buffer and the usual
+ prolog according to the standard and write the result to RESBUF.
+
+ IMPORTANT: On some systems it is required that RESBUF is correctly
+ aligned for a 32 bits value. */
+void *
+md5_finish_ctx (ctx, resbuf)
+ struct md5_ctx *ctx;
+ void *resbuf;
+{
+ /* Take yet unprocessed bytes into account. */
+ md5_uint32 bytes = ctx->buflen;
+ size_t pad;
+
+ /* Now count remaining bytes. */
+ ctx->total[0] += bytes;
+ if (ctx->total[0] < bytes)
+ ++ctx->total[1];
+
+ pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
+ memcpy (&ctx->buffer[bytes], fillbuf, pad);
+
+ /* Put the 64-bit file length in *bits* at the end of the buffer. */
+ *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
+ *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
+ (ctx->total[0] >> 29));
+
+ /* Process last bytes. */
+ md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
+
+ return md5_read_ctx (ctx, resbuf);
+}
+
+/* Compute MD5 message digest for bytes read from STREAM. The
+ resulting message digest number will be written into the 16 bytes
+ beginning at RESBLOCK. */
+int
+md5_stream (stream, resblock)
+ FILE *stream;
+ void *resblock;
+{
+ /* Important: BLOCKSIZE must be a multiple of 64. */
+#define BLOCKSIZE 4096
+ struct md5_ctx ctx;
+ char buffer[BLOCKSIZE + 72];
+ size_t sum;
+
+ /* Initialize the computation context. */
+ md5_init_ctx (&ctx);
+
+ /* Iterate over full file contents. */
+ while (1)
+ {
+ /* We read the file in blocks of BLOCKSIZE bytes. One call of the
+ computation function processes the whole buffer so that with the
+ next round of the loop another block can be read. */
+ size_t n;
+ sum = 0;
+
+ /* Read block. Take care for partial reads. */
+ do
+ {
+ n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
+
+ sum += n;
+ }
+ while (sum < BLOCKSIZE && n != 0);
+ if (n == 0 && ferror (stream))
+ return 1;
+
+ /* If end of file is reached, end the loop. */
+ if (n == 0)
+ break;
+
+ /* Process buffer with BLOCKSIZE bytes. Note that
+ BLOCKSIZE % 64 == 0
+ */
+ md5_process_block (buffer, BLOCKSIZE, &ctx);
+ }
+
+ /* Add the last bytes if necessary. */
+ if (sum > 0)
+ md5_process_bytes (buffer, sum, &ctx);
+
+ /* Construct result in desired memory. */
+ md5_finish_ctx (&ctx, resblock);
+ return 0;
+}
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
+ result is always in little endian byte order, so that a byte-wise
+ output yields to the wanted ASCII representation of the message
+ digest. */
+void *
+md5_buffer (buffer, len, resblock)
+ const char *buffer;
+ size_t len;
+ void *resblock;
+{
+ struct md5_ctx ctx;
+
+ /* Initialize the computation context. */
+ md5_init_ctx (&ctx);
+
+ /* Process whole buffer but last len % 64 bytes. */
+ md5_process_bytes (buffer, len, &ctx);
+
+ /* Put result in desired memory area. */
+ return md5_finish_ctx (&ctx, resblock);
+}
+
+
+void
+md5_process_bytes (buffer, len, ctx)
+ const void *buffer;
+ size_t len;
+ struct md5_ctx *ctx;
+{
+ /* When we already have some bits in our internal buffer concatenate
+ both inputs first. */
+ if (ctx->buflen != 0)
+ {
+ size_t left_over = ctx->buflen;
+ size_t add = 128 - left_over > len ? len : 128 - left_over;
+
+ memcpy (&ctx->buffer[left_over], buffer, add);
+ ctx->buflen += add;
+
+ if (left_over + add > 64)
+ {
+ md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx);
+ /* The regions in the following copy operation cannot overlap. */
+ memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
+ (left_over + add) & 63);
+ ctx->buflen = (left_over + add) & 63;
+ }
+
+ buffer = (const char *) buffer + add;
+ len -= add;
+ }
+
+ /* Process available complete blocks. */
+ if (len > 64)
+ {
+ md5_process_block (buffer, len & ~63, ctx);
+ buffer = (const char *) buffer + (len & ~63);
+ len &= 63;
+ }
+
+ /* Move remaining bytes in internal buffer. */
+ if (len > 0)
+ {
+ memcpy (ctx->buffer, buffer, len);
+ ctx->buflen = len;
+ }
+}
+
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+ and defined in the RFC 1321. The first function is a little bit optimized
+ (as found in Colin Plumbs public domain implementation). */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) FF (d, b, c)
+#define FH(b, c, d) (b ^ c ^ d)
+#define FI(b, c, d) (c ^ (b | ~d))
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+ It is assumed that LEN % 64 == 0. */
+
+void
+md5_process_block (buffer, len, ctx)
+ const void *buffer;
+ size_t len;
+ struct md5_ctx *ctx;
+{
+ md5_uint32 correct_words[16];
+ const md5_uint32 *words = buffer;
+ size_t nwords = len / sizeof (md5_uint32);
+ const md5_uint32 *endp = words + nwords;
+ md5_uint32 A = ctx->A;
+ md5_uint32 B = ctx->B;
+ md5_uint32 C = ctx->C;
+ md5_uint32 D = ctx->D;
+
+ /* First increment the byte count. RFC 1321 specifies the possible
+ length of the file up to 2^64 bits. Here we only compute the
+ number of bytes. Do a double word increment. */
+ ctx->total[0] += len;
+ if (ctx->total[0] < len)
+ ++ctx->total[1];
+
+ /* Process all bytes in the buffer with 64 bytes in each round of
+ the loop. */
+ while (words < endp)
+ {
+ md5_uint32 *cwp = correct_words;
+ md5_uint32 A_save = A;
+ md5_uint32 B_save = B;
+ md5_uint32 C_save = C;
+ md5_uint32 D_save = D;
+
+ /* First round: using the given function, the context and a constant
+ the next context is computed. Because the algorithms processing
+ unit is a 32-bit word and it is determined to work on words in
+ little endian byte order we perhaps have to change the byte order
+ before the computation. To reduce the work for the next steps
+ we store the swapped words in the array CORRECT_WORDS. */
+
+#define OP(a, b, c, d, s, T) \
+ do \
+ { \
+ a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
+ ++words; \
+ CYCLIC (a, s); \
+ a += b; \
+ } \
+ while (0)
+
+ /* It is unfortunate that C does not provide an operator for
+ cyclic rotation. Hope the C compiler is smart enough. */
+#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
+
+ /* Before we start, one word to the strange constants.
+ They are defined in RFC 1321 as
+
+ T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
+ */
+
+ /* Round 1. */
+ OP (A, B, C, D, 7, 0xd76aa478);
+ OP (D, A, B, C, 12, 0xe8c7b756);
+ OP (C, D, A, B, 17, 0x242070db);
+ OP (B, C, D, A, 22, 0xc1bdceee);
+ OP (A, B, C, D, 7, 0xf57c0faf);
+ OP (D, A, B, C, 12, 0x4787c62a);
+ OP (C, D, A, B, 17, 0xa8304613);
+ OP (B, C, D, A, 22, 0xfd469501);
+ OP (A, B, C, D, 7, 0x698098d8);
+ OP (D, A, B, C, 12, 0x8b44f7af);
+ OP (C, D, A, B, 17, 0xffff5bb1);
+ OP (B, C, D, A, 22, 0x895cd7be);
+ OP (A, B, C, D, 7, 0x6b901122);
+ OP (D, A, B, C, 12, 0xfd987193);
+ OP (C, D, A, B, 17, 0xa679438e);
+ OP (B, C, D, A, 22, 0x49b40821);
+
+ /* For the second to fourth round we have the possibly swapped words
+ in CORRECT_WORDS. Redefine the macro to take an additional first
+ argument specifying the function to use. */
+#undef OP
+#define OP(f, a, b, c, d, k, s, T) \
+ do \
+ { \
+ a += f (b, c, d) + correct_words[k] + T; \
+ CYCLIC (a, s); \
+ a += b; \
+ } \
+ while (0)
+
+ /* Round 2. */
+ OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
+ OP (FG, D, A, B, C, 6, 9, 0xc040b340);
+ OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
+ OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
+ OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
+ OP (FG, D, A, B, C, 10, 9, 0x02441453);
+ OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
+ OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
+ OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
+ OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
+ OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
+ OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
+ OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
+ OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
+ OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
+ OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
+
+ /* Round 3. */
+ OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
+ OP (FH, D, A, B, C, 8, 11, 0x8771f681);
+ OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
+ OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
+ OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
+ OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
+ OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
+ OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
+ OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
+ OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
+ OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
+ OP (FH, B, C, D, A, 6, 23, 0x04881d05);
+ OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
+ OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
+ OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
+ OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
+
+ /* Round 4. */
+ OP (FI, A, B, C, D, 0, 6, 0xf4292244);
+ OP (FI, D, A, B, C, 7, 10, 0x432aff97);
+ OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
+ OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
+ OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
+ OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
+ OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
+ OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
+ OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
+ OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
+ OP (FI, C, D, A, B, 6, 15, 0xa3014314);
+ OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
+ OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
+ OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
+ OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
+ OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
+
+ /* Add the starting values of the context. */
+ A += A_save;
+ B += B_save;
+ C += C_save;
+ D += D_save;
+ }
+
+ /* Put checksum in context given as argument. */
+ ctx->A = A;
+ ctx->B = B;
+ ctx->C = C;
+ ctx->D = D;
+}
diff --git a/tool/rabbitsign-src/md5.h b/tool/rabbitsign-src/md5.h
new file mode 100644
index 0000000..ad97efc
--- /dev/null
+++ b/tool/rabbitsign-src/md5.h
@@ -0,0 +1,146 @@
+/* md5.h - Declaration of functions and data types used for MD5 sum
+ computing library functions.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ NOTE: The canonical source of this file is maintained with the GNU C
+ Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _MD5_H
+#define _MD5_H 1
+
+#include
+
+#if defined HAVE_LIMITS_H || _LIBC
+# include
+#endif
+
+/* The following contortions are an attempt to use the C preprocessor
+ to determine an unsigned integral type that is 32 bits wide. An
+ alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
+ doing that would require that the configure script compile and *run*
+ the resulting executable. Locally running cross-compiled executables
+ is usually not possible. */
+
+#ifdef _LIBC
+# include
+typedef u_int32_t md5_uint32;
+#else
+# if defined __STDC__ && __STDC__
+# define UINT_MAX_32_BITS 4294967295U
+# else
+# define UINT_MAX_32_BITS 0xFFFFFFFF
+# endif
+
+/* If UINT_MAX isn't defined, assume it's a 32-bit type.
+ This should be valid for all systems GNU cares about because
+ that doesn't include 16-bit systems, and only modern systems
+ (that certainly have ) have 64+-bit integral types. */
+
+# ifndef UINT_MAX
+# define UINT_MAX UINT_MAX_32_BITS
+# endif
+
+# if UINT_MAX == UINT_MAX_32_BITS
+ typedef unsigned int md5_uint32;
+# else
+# if USHRT_MAX == UINT_MAX_32_BITS
+ typedef unsigned short md5_uint32;
+# else
+# if ULONG_MAX == UINT_MAX_32_BITS
+ typedef unsigned long md5_uint32;
+# else
+ /* The following line is intended to evoke an error.
+ Using #error is not portable enough. */
+ "Cannot determine unsigned 32-bit data type."
+# endif
+# endif
+# endif
+#endif
+
+#undef __P
+#if defined (__STDC__) && __STDC__
+#define __P(x) x
+#else
+#define __P(x) ()
+#endif
+
+/* Structure to save state of computation between the single steps. */
+struct md5_ctx
+{
+ md5_uint32 A;
+ md5_uint32 B;
+ md5_uint32 C;
+ md5_uint32 D;
+
+ md5_uint32 total[2];
+ md5_uint32 buflen;
+ char buffer[128];
+};
+
+/*
+ * The following three functions are build up the low level used in
+ * the functions `md5_stream' and `md5_buffer'.
+ */
+
+/* Initialize structure containing state of computation.
+ (RFC 1321, 3.3: Step 3) */
+extern void md5_init_ctx __P ((struct md5_ctx *ctx));
+
+/* Starting with the result of former calls of this function (or the
+ initialization function update the context for the next LEN bytes
+ starting at BUFFER.
+ It is necessary that LEN is a multiple of 64!!! */
+extern void md5_process_block __P ((const void *buffer, size_t len,
+ struct md5_ctx *ctx));
+
+/* Starting with the result of former calls of this function (or the
+ initialization function update the context for the next LEN bytes
+ starting at BUFFER.
+ It is NOT required that LEN is a multiple of 64. */
+extern void md5_process_bytes __P ((const void *buffer, size_t len,
+ struct md5_ctx *ctx));
+
+/* Process the remaining bytes in the buffer and put result from CTX
+ in first 16 bytes following RESBUF. The result is always in little
+ endian byte order, so that a byte-wise output yields to the wanted
+ ASCII representation of the message digest.
+
+ IMPORTANT: On some systems it is required that RESBUF is correctly
+ aligned for a 32 bits value. */
+extern void *md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf));
+
+
+/* Put result from CTX in first 16 bytes following RESBUF. The result is
+ always in little endian byte order, so that a byte-wise output yields
+ to the wanted ASCII representation of the message digest.
+
+ IMPORTANT: On some systems it is required that RESBUF is correctly
+ aligned for a 32 bits value. */
+extern void *md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf));
+
+
+/* Compute MD5 message digest for bytes read from STREAM. The
+ resulting message digest number will be written into the 16 bytes
+ beginning at RESBLOCK. */
+extern int md5_stream __P ((FILE *stream, void *resblock));
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
+ result is always in little endian byte order, so that a byte-wise
+ output yields to the wanted ASCII representation of the message
+ digest. */
+extern void *md5_buffer __P ((const char *buffer, size_t len, void *resblock));
+
+#endif
diff --git a/tool/rabbitsign-src/mem.c b/tool/rabbitsign-src/mem.c
new file mode 100644
index 0000000..d65064b
--- /dev/null
+++ b/tool/rabbitsign-src/mem.c
@@ -0,0 +1,73 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#ifdef HAVE_STDLIB_H
+# include
+#endif
+
+#ifdef HAVE_STRING_H
+# include
+#else
+# ifdef HAVE_STRINGS_H
+# include
+# endif
+#endif
+
+#include "rabbitsign.h"
+#include "internal.h"
+
+void* rs_realloc(void* ptr, unsigned long count)
+{
+ void* p;
+
+ if (!count) {
+ if (ptr) {
+ free(ptr);
+ }
+ return NULL;
+ }
+
+ if (ptr)
+ p = realloc(ptr, count);
+ else
+ p = malloc(count);
+ if (!p)
+ rs_error(NULL, NULL, "out of memory (need %lu bytes)", count);
+ return p;
+}
+
+char* rs_strdup(const char* str)
+{
+ int n;
+ char* p;
+
+ if (!str)
+ return NULL;
+
+ n = strlen(str);
+ p = rs_malloc(n + 1);
+ if (p)
+ memcpy(p, str, n + 1);
+ return p;
+}
diff --git a/tool/rabbitsign-src/mpz.c b/tool/rabbitsign-src/mpz.c
new file mode 100644
index 0000000..2a38ef5
--- /dev/null
+++ b/tool/rabbitsign-src/mpz.c
@@ -0,0 +1,1026 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+
+#ifdef HAVE_STDLIB_H
+# include
+#endif
+
+#ifdef HAVE_ASSERT_H
+# include
+#else
+# define assert(xxx) if (!(xxx)) { \
+ fprintf(stderr, "mpz: assertion \"%s\" failed\n", #xxx); \
+ abort(); \
+ }
+#endif
+
+#include "mpz.h"
+
+/*
+ * This file contains multiple-precision arithmetic functions. These
+ * are equivalent to the corresponding GMP functions in the ways they
+ * are used by RabbitSign.
+ *
+ * HOWEVER, they are not by any means complete. They do not meet the
+ * specifications of the GMP functions; for the sake of portability
+ * and compactness they are vastly less efficient; and they may even
+ * have bugs.
+ */
+
+/*
+#define DBG(args...) if (1) \
+ do { \
+ gmp_fprintf(stderr, "mpz: " args); \
+ fputc('\n', stderr); \
+ } while (0)
+*/
+
+#define IDX(nnn, iii) (nnn)->m[iii]
+
+/* \
+ (*(__extension__ ({ \
+ int _ii = (iii); \
+ const struct _mpz* _nn = (nnn); \
+ assert(_nn->size <= _nn->size_alloc); \
+ assert(_ii >= 0); \
+ assert(((unsigned) _ii) < (_nn->size)); \
+ &(_nn->m[_ii]); })))
+*/
+
+static void* xrealloc(p, n)
+ void* p;
+ size_t n;
+{
+ void* res;
+
+ if (n <= 0)
+ n = 1;
+
+ if (p)
+ res = realloc(p, n);
+ else
+ res = malloc(n);
+
+ if (!res) {
+ fprintf(stderr,"mpz: out of memory (need %lu bytes)\n",
+ (unsigned long) n);
+ abort();
+ }
+ return res;
+}
+
+static inline void allocate_mpz(x)
+ mpz_t x;
+{
+ if (x->size_alloc < x->size) {
+ x->size_alloc = x->size;
+ x->m = (limb_t*) xrealloc(x->m, x->size_alloc * sizeof(limb_t));
+ }
+}
+
+static inline void zero_mpz(x)
+ mpz_t x;
+{
+ size_t i;
+ for (i = 0; i < x->size; i++)
+ IDX(x, i) = 0;
+}
+
+static inline void copyref_mpz(dest, src)
+ mpz_t dest;
+ const mpz_t src;
+{
+ dest->size = src->size;
+ dest->size_alloc = src->size_alloc;
+ dest->m = src->m;
+ dest->sign = src->sign;
+}
+
+static inline void reduce_mpz(x)
+ mpz_t x;
+{
+ while (x->size > 0 && IDX(x, (x->size) - 1) == 0)
+ x->size--;
+}
+
+/**************** Init / Clear ****************/
+
+void mpz_init(x)
+ mpz_t x;
+{
+ x->size = 0;
+ x->size_alloc = 0;
+ x->m = (limb_t*)0;
+ x->sign = 1;
+}
+
+void mpz_clear(x)
+ mpz_t x;
+{
+ if (x->m)
+ free(x->m);
+ mpz_init(x);
+}
+
+/**************** Setting ****************/
+
+void mpz_set(dest, src)
+ mpz_t dest;
+ const mpz_t src;
+{
+ size_t i;
+
+ dest->size = src->size;
+ allocate_mpz(dest);
+ dest->sign = src->sign;
+
+ for (i = 0; i < src->size; i++)
+ IDX(dest, i) = IDX(src, i);
+}
+
+void mpz_set_ui(dest, a)
+ mpz_t dest;
+ unsigned int a;
+{
+ if (a) {
+ dest->size = 1;
+ allocate_mpz(dest);
+ IDX(dest, 0) = a;
+ }
+ else
+ dest->size = 0;
+ dest->sign = 1;
+}
+
+unsigned int mpz_get_ui(a)
+ const mpz_t a;
+{
+ return IDX(a, 0);
+}
+
+static void mpz_swap(a, b)
+ mpz_t a;
+ mpz_t b;
+{
+ mpz_t temp;
+ copyref_mpz(temp, a);
+ copyref_mpz(a, b);
+ copyref_mpz(b, temp);
+}
+
+/**************** Import / Export ****************/
+
+void mpz_import(dest, count, order, size, endian, nails, op)
+ mpz_t dest;
+ size_t count;
+ int order; /* must be -1 (little endian structure) */
+ int size; /* must be 1 (bytes) */
+ int endian; /* must be 0 (native endian words, doesn't matter for bytes) */
+ size_t nails; /* must be 0 (no nails) */
+ const void* op;
+{
+ size_t i, j;
+
+ assert(order == -1);
+ assert(size == 1);
+ assert(endian == 0);
+ assert(nails == 0);
+
+ dest->size = (count + LIMB_BYTES - 1) / LIMB_BYTES;
+ allocate_mpz(dest);
+ dest->sign = 1;
+
+ for (i = 0; i < dest->size; i++) {
+ IDX(dest, i) = 0;
+ for (j = 0; j < LIMB_BYTES && ((i * LIMB_BYTES) + j) < count; j++) {
+ IDX(dest, i) |= ((unsigned char*)op)[(i * LIMB_BYTES) + j] << 8 * j;
+ }
+ }
+}
+
+void mpz_export(dest, count, order, size, endian, nails, op)
+ void* dest;
+ size_t* count;
+ int order; /* must be -1 (little endian structure) */
+ int size; /* must be 1 (bytes) */
+ int endian; /* must be 0 (native endian words, doesn't matter for bytes) */
+ size_t nails; /* must be 0 (no nails) */
+ const mpz_t op;
+{
+ size_t i, j;
+
+ assert(order == -1);
+ assert(size == 1);
+ assert(endian == 0);
+ assert(nails == 0);
+
+ for (i = 0; i < op->size; i++) {
+ for (j = 0; j < LIMB_BYTES; j++) {
+ ((unsigned char*)dest)[(i * LIMB_BYTES) + j] = IDX(op, i) >> 8 * j;
+ }
+ }
+ *count = op->size * LIMB_BYTES;
+}
+
+/**************** Comparison ****************/
+
+int mpz_sgn(a)
+ const mpz_t a;
+{
+ size_t i = a->size;
+
+ while (i > 0 && IDX(a, i - 1) == 0)
+ i--;
+
+ if (i == 0)
+ return 0;
+ else
+ return a->sign;
+}
+
+static int mpz_cmpabs(a, b)
+ const mpz_t a;
+ const mpz_t b;
+{
+ size_t sa = a->size;
+ size_t sb = b->size;
+
+ while (sa > 0 && IDX(a, sa - 1) == 0)
+ sa--;
+ while (sb > 0 && IDX(b, sb - 1) == 0)
+ sb--;
+
+ if (sa > sb)
+ return 1;
+ else if (sb > sa)
+ return -1;
+
+ while (sa > 0) {
+ if (IDX(a, sa - 1) > IDX(b, sa - 1))
+ return 1;
+ else if (IDX(a, sa - 1) < IDX(b, sa - 1))
+ return -1;
+ sa--;
+ }
+
+ return 0;
+}
+
+int mpz_cmp(a, b)
+ const mpz_t a;
+ const mpz_t b;
+{
+ size_t sa = a->size;
+ size_t sb = b->size;
+
+ while (sa > 0 && IDX(a, sa - 1) == 0)
+ sa--;
+ while (sb > 0 && IDX(b, sb - 1) == 0)
+ sb--;
+
+ if (sa == 0 && sb == 0)
+ return 0;
+ else if (sa == 0)
+ return -(b->sign);
+ else if (sb == 0)
+ return a->sign;
+ else if (a->sign != b->sign)
+ return a->sign;
+
+ return a->sign * mpz_cmpabs(a, b);
+}
+
+int mpz_cmp_ui(a, b)
+ const mpz_t a;
+ unsigned int b;
+{
+ size_t sa = a->size;
+
+ while (sa > 0 && IDX(a, sa - 1) == 0)
+ sa--;
+
+ if (sa == 0 && b == 0)
+ return 0;
+
+ if (sa == 1 && a->sign == 1) {
+ if (IDX(a, 0) > b)
+ return 1;
+ else if (IDX(a, 0) < b)
+ return -1;
+ else
+ return 0;
+ }
+
+ return (a->sign);
+}
+
+/**************** Addition / Subtraction ****************/
+
+static void mpz_addabs(dest, a, b)
+ mpz_t dest; /* != a, b */
+ const mpz_t a;
+ const mpz_t b;
+{
+ size_t i;
+ double_limb_t carry = 0;
+
+ if (a->size > b->size)
+ dest->size = a->size + 1;
+ else
+ dest->size = b->size + 1;
+ allocate_mpz(dest);
+
+ assert(dest != a);
+ assert(dest != b);
+
+ for (i = 0; i < a->size && i < b->size; i++) {
+ carry += IDX(a, i);
+ carry += IDX(b, i);
+ IDX(dest, i) = carry & LIMB_MASK;
+ carry >>= LIMB_BITS;
+ }
+
+ for (; i < a->size; i++) {
+ carry += IDX(a, i);
+ IDX(dest, i) = carry & LIMB_MASK;
+ carry >>= LIMB_BITS;
+ }
+
+ for (; i < b->size; i++) {
+ carry += IDX(b, i);
+ IDX(dest, i) = carry & LIMB_MASK;
+ carry >>= LIMB_BITS;
+ }
+ IDX(dest, i) = carry;
+}
+
+static void mpz_subabs(dest, a, b)
+ mpz_t dest; /* != b */
+ const mpz_t a;
+ const mpz_t b; /* must be <= a */
+{
+ size_t i;
+ signed_double_limb_t carry = 0;
+ dest->size = a->size;
+ allocate_mpz(dest);
+
+ assert(dest != b);
+
+ for (i = 0; i < a->size && i < b->size; i++) {
+ carry += IDX(a, i);
+ carry -= IDX(b, i);
+ IDX(dest, i) = carry & LIMB_MASK;
+ carry >>= LIMB_BITS;
+ }
+
+ for (; i < a->size; i++) {
+ carry += IDX(a, i);
+ IDX(dest, i) = carry & LIMB_MASK;
+ carry >>= LIMB_BITS;
+ }
+
+ assert(carry == 0);
+}
+
+void mpz_add(dest, a, b)
+ mpz_t dest;
+ const mpz_t a;
+ const mpz_t b;
+{
+ mpz_t temp;
+ mpz_init(temp);
+
+ if (a->sign == b->sign) {
+ temp->sign = a->sign;
+ mpz_addabs(temp, a, b);
+ }
+ else if (mpz_cmpabs(a, b) > 0) {
+ temp->sign = a->sign;
+ mpz_subabs(temp, a, b);
+ }
+ else {
+ temp->sign = b->sign;
+ mpz_subabs(temp, b, a);
+ }
+
+ reduce_mpz(temp);
+ mpz_clear(dest);
+ copyref_mpz(dest, temp);
+}
+
+void mpz_sub(dest, a, b)
+ mpz_t dest;
+ const mpz_t a;
+ const mpz_t b;
+{
+ mpz_t temp;
+ mpz_init(temp);
+
+ if (a->sign != b->sign) {
+ temp->sign = a->sign;
+ mpz_addabs(temp, a, b);
+ }
+ else if (mpz_cmpabs(a, b) > 0) {
+ temp->sign = a->sign;
+ mpz_subabs(temp, a, b);
+ }
+ else {
+ temp->sign = -(b->sign);
+ mpz_subabs(temp, b, a);
+ }
+
+ reduce_mpz(temp);
+ mpz_clear(dest);
+ copyref_mpz(dest, temp);
+}
+
+void mpz_add_ui(dest, a, b)
+ mpz_t dest;
+ const mpz_t a;
+ unsigned int b;
+{
+ size_t i;
+ mpz_t temp;
+ mpz_init(temp);
+
+ temp->size = a->size + 1;
+ temp->sign = a->sign;
+ allocate_mpz(temp);
+
+ for (i = 0; i < a->size; i++) {
+ IDX(temp, i) = IDX(a, i) + b;
+ b = (IDX(temp, i) < IDX(a, i)) ? 1 : 0;
+ }
+ IDX(temp, i) = b;
+
+ reduce_mpz(temp);
+ mpz_clear(dest);
+ copyref_mpz(dest, temp);
+}
+
+void mpz_sub_ui(dest, a, b)
+ mpz_t dest;
+ const mpz_t a;
+ unsigned int b;
+{
+ size_t i;
+ mpz_t temp;
+ mpz_init(temp);
+
+ temp->size = a->size;
+ temp->sign = a->sign;
+ allocate_mpz(temp);
+
+ for (i = 0; i < a->size; i++) {
+ IDX(temp, i) = IDX(a, i) - b;
+ b = (IDX(temp, i) > IDX(a, i)) ? 1 : 0;
+ }
+ assert(b == 0);
+
+ reduce_mpz(temp);
+ mpz_clear(dest);
+ copyref_mpz(dest, temp);
+}
+
+/**************** Multiplication ****************/
+
+void mpz_mul(dest, a, b)
+ mpz_t dest;
+ const mpz_t a;
+ const mpz_t b;
+{
+ double_limb_t carry = 0, newcarry;
+ size_t i, j, k;
+ mpz_t temp;
+ mpz_init(temp);
+
+ temp->size = a->size + b->size;
+ temp->sign = a->sign * b->sign;
+ allocate_mpz(temp);
+ zero_mpz(temp);
+
+ for (i = 0; i < a->size; i++) {
+ for (j = 0; j < b->size; j++) {
+ carry = IDX(a, i);
+ carry *= IDX(b, j);
+ for (k = i + j; k < temp->size && carry; k++) {
+ newcarry = carry + IDX(temp, k);
+ if (newcarry < carry) {
+ IDX(temp, k) = newcarry & LIMB_MASK;
+ carry = (newcarry >> LIMB_BITS) + LIMB_MASK + 1;
+ }
+ else {
+ IDX(temp, k) = newcarry & LIMB_MASK;
+ carry = (newcarry >> LIMB_BITS);
+ }
+ }
+ assert(carry == 0);
+ }
+ }
+
+ reduce_mpz(temp);
+ mpz_clear(dest);
+ copyref_mpz(dest, temp);
+}
+
+void mpz_mul_ui(dest, a, b)
+ mpz_t dest;
+ const mpz_t a;
+ unsigned int b; /* must be fairly small */
+{
+ double_limb_t carry = 0;
+ size_t i;
+ mpz_t temp;
+ mpz_init(temp);
+
+ temp->size = a->size + 1;
+ temp->sign = a->sign;
+ allocate_mpz(temp);
+
+ for (i = 0; i < a->size; i++) {
+ carry += (double_limb_t) IDX(a, i) * b;
+ IDX(temp, i) = carry & LIMB_MASK;
+ carry >>= LIMB_BITS;
+ }
+ IDX(temp, i) = carry & LIMB_MASK;
+
+ reduce_mpz(temp);
+ mpz_clear(dest);
+ copyref_mpz(dest, temp);
+}
+
+/**************** Division ****************/
+
+void mpz_fdiv_q_2exp(dest, a, b)
+ mpz_t dest;
+ const mpz_t a;
+ unsigned int b; /* must be <= LIMB_BITS */
+{
+ size_t i;
+ mpz_t temp;
+ mpz_init(temp);
+
+ assert(b <= LIMB_BITS);
+
+ temp->size = a->size;
+ temp->sign = a->sign;
+ allocate_mpz(temp);
+
+ if (a->size > 0) {
+ for (i = 0; i < (a->size - 1); i++) {
+ IDX(temp, i) = (((IDX(a, i) >> b) | (IDX(a, i + 1) << (LIMB_BITS - b)))
+ & LIMB_MASK);
+ }
+ IDX(temp, a->size - 1) = IDX(a, a->size - 1) >> b;
+ }
+
+ reduce_mpz(temp);
+ mpz_clear(dest);
+ copyref_mpz(dest, temp);
+}
+
+/**************** Division / Modulus ****************/
+
+static void mpz_setbit(dest, n)
+ mpz_t dest;
+ unsigned int n;
+{
+ size_t i, j;
+
+ i = n / LIMB_BITS + 1;
+
+ if (dest->size < i) {
+ j = dest->size;
+ dest->size = i;
+ allocate_mpz(dest);
+ while (j < i) {
+ IDX(dest, j) = 0;
+ j++;
+ }
+ }
+
+ IDX(dest, i - 1) |= (1 << (n % LIMB_BITS));
+}
+
+static void mpz_fdiv_qr(q, r, num, den)
+ mpz_t q;
+ mpz_t r;
+ const mpz_t num;
+ const mpz_t den;
+{
+ size_t shiftct = 0;
+ size_t i;
+ mpz_t remainder;
+ mpz_t quotient;
+ mpz_t shifted; /* shifted = mod * 2^(shiftct) */
+
+ mpz_init(remainder);
+ mpz_init(shifted);
+ if (q) {
+ mpz_init(quotient);
+ quotient->sign = num->sign * den->sign;
+ }
+
+ shifted->size = num->size;
+ allocate_mpz(shifted);
+
+ mpz_set(remainder, num);
+ mpz_set(shifted, den);
+
+ reduce_mpz(shifted);
+ assert(shifted->size > 0);
+
+ while (mpz_cmpabs(remainder, shifted) > 0) {
+ shifted->size++;
+ allocate_mpz(shifted);
+ for (i = shifted->size - 1; i > 0; i--)
+ IDX(shifted, i) = IDX(shifted, i - 1);
+ IDX(shifted, 0) = 0;
+ shiftct += LIMB_BITS;
+ }
+
+ while (shiftct != 0) {
+ if (mpz_cmpabs(remainder, shifted) >= 0) {
+ mpz_subabs(remainder, remainder, shifted);
+ reduce_mpz(remainder);
+ if (q)
+ mpz_setbit(quotient, shiftct);
+ }
+ mpz_fdiv_q_2exp(shifted, shifted, 1);
+ shiftct--;
+ }
+
+ if (mpz_cmpabs(remainder, den) >= 0) {
+ mpz_subabs(remainder, remainder, den);
+ if (q)
+ mpz_setbit(quotient, 0);
+ }
+
+ if (mpz_sgn(remainder) == -1) {
+ mpz_add(remainder, remainder, den);
+ if (q)
+ mpz_sub_ui(quotient, quotient, 1);
+ }
+
+ mpz_clear(shifted);
+ reduce_mpz(remainder);
+ mpz_clear(r);
+ copyref_mpz(r, remainder);
+
+ if (q) {
+ reduce_mpz(quotient);
+ mpz_clear(q);
+ copyref_mpz(q, quotient);
+ }
+}
+
+void mpz_mod(dest, a, mod)
+ mpz_t dest;
+ const mpz_t a;
+ const mpz_t mod;
+{
+ mpz_fdiv_qr(NULL, dest, a, mod);
+}
+
+/**************** Modular exponent ****************/
+
+void mpz_powm(dest, base, exp, mod)
+ mpz_t dest;
+ const mpz_t base;
+ const mpz_t exp;
+ const mpz_t mod;
+{
+ mpz_t exp_bits;
+ mpz_t base_power;
+ mpz_t temp;
+ mpz_init(exp_bits);
+ mpz_init(base_power);
+ mpz_init(temp);
+
+ mpz_set(exp_bits, exp);
+ mpz_set(base_power, base);
+ mpz_set_ui(temp, 1);
+
+ reduce_mpz(exp_bits);
+ assert(exp_bits->sign == 1 || exp_bits->size == 0);
+
+ while (exp_bits->size > 0) {
+ if (IDX(exp_bits, 0) & 1) {
+ mpz_mul(temp, temp, base_power);
+ mpz_mod(temp, temp, mod);
+ }
+ mpz_mul(base_power, base_power, base_power);
+ mpz_mod(base_power, base_power, mod);
+ mpz_fdiv_q_2exp(exp_bits, exp_bits, 1);
+ }
+
+ mpz_clear(exp_bits);
+ mpz_clear(base_power);
+ reduce_mpz(temp);
+ mpz_clear(dest);
+ copyref_mpz(dest, temp);
+}
+
+/**************** Legendre symbol ****************/
+
+int mpz_legendre(a, p)
+ const mpz_t a;
+ const mpz_t p;
+{
+ int x;
+ mpz_t exp;
+ mpz_t pow;
+ mpz_init(exp);
+ mpz_init(pow);
+
+ mpz_set(exp, p);
+ mpz_sub_ui(exp, exp, 1);
+ mpz_fdiv_q_2exp(exp, exp, 1);
+ mpz_powm(pow, a, exp, p);
+
+ if (pow->size == 1 && IDX(pow, 0) == 1)
+ x = 1;
+ else if (pow->size == 0)
+ x = 0;
+ else
+ x = -1;
+
+ mpz_clear(exp);
+ mpz_clear(pow);
+
+ return x;
+}
+
+/**************** GCD ****************/
+
+static void mpz_gcdext_main(g, ai, bi, a, b)
+ mpz_t g;
+ mpz_t ai;
+ mpz_t bi;
+ const mpz_t a;
+ const mpz_t b;
+{
+ mpz_t rem_last, rem_cur;
+ mpz_t ai_last, ai_cur;
+ mpz_t bi_last, bi_cur;
+ mpz_t q, temp;
+
+ mpz_init(rem_last);
+ mpz_init(rem_cur);
+ mpz_init(q);
+
+ mpz_set(rem_last, a);
+ mpz_set(rem_cur, b);
+
+ if (ai) {
+ mpz_init(ai_last);
+ mpz_init(ai_cur);
+ mpz_set_ui(ai_last, 1);
+ }
+
+ if (bi) {
+ mpz_init(bi_last);
+ mpz_init(bi_cur);
+ mpz_set_ui(bi_cur, 1);
+ }
+
+ assert(a->sign == 1 && a->size > 0);
+ assert(b->sign == 1 && b->size > 0);
+
+ while (1) {
+ mpz_fdiv_qr(q, rem_last, rem_last, rem_cur);
+ mpz_swap(rem_last, rem_cur);
+ if (!mpz_sgn(rem_cur))
+ break;
+
+ if (ai) {
+ mpz_init(temp);
+ mpz_mul(temp, q, ai_cur);
+ mpz_sub(temp, ai_last, temp);
+ mpz_clear(ai_last);
+ copyref_mpz(ai_last, ai_cur);
+ copyref_mpz(ai_cur, temp);
+ }
+
+ if (bi) {
+ mpz_init(temp);
+ mpz_mul(temp, q, bi_cur);
+ mpz_sub(temp, bi_last, temp);
+ mpz_clear(bi_last);
+ copyref_mpz(bi_last, bi_cur);
+ copyref_mpz(bi_cur, temp);
+ }
+ }
+
+ mpz_clear(g);
+ copyref_mpz(g, rem_last);
+ mpz_clear(rem_cur);
+ mpz_clear(q);
+
+ if (ai) {
+ mpz_clear(ai);
+ copyref_mpz(ai, ai_cur);
+ mpz_clear(ai_last);
+ }
+ if (bi) {
+ mpz_clear(bi);
+ copyref_mpz(bi, bi_cur);
+ mpz_clear(bi_last);
+ }
+}
+
+void mpz_gcdext(g, ai, bi, a, b)
+ mpz_t g;
+ mpz_t ai;
+ mpz_t bi;
+ const mpz_t a;
+ const mpz_t b;
+{
+ if (mpz_cmpabs(a, b) > 0)
+ mpz_gcdext_main(g, ai, bi, a, b);
+ else
+ mpz_gcdext_main(g, bi, ai, b, a);
+}
+
+/**************** Output ****************/
+
+#define PUTCH(bbb, sss, nnn, ccc) do { \
+ if ((sss) > 1) { \
+ *(bbb) = (ccc); \
+ (bbb)++; \
+ (sss)--; \
+ } \
+ (nnn)++; \
+ } while (0)
+
+static int putnum(char** buf, size_t* size, unsigned long value,
+ unsigned int base)
+{
+ unsigned long s;
+ unsigned int d;
+ int count = 0;
+
+ if (value == 0) {
+ PUTCH(*buf, *size, count, '0');
+ }
+ else {
+ s = value / base;
+ if (s)
+ count = putnum(buf, size, value / base, base);
+ d = value % base;
+ if (d < 10)
+ PUTCH(*buf, *size, count, d + '0');
+ else
+ PUTCH(*buf, *size, count, d + 'A' - 10);
+ }
+
+ return count;
+}
+
+/* Supported conversions:
+ %% %s %c %d %i %o %u %X %ld %li %lo %lu %lX %ZX
+ */
+
+int rs_vsnprintf(char* buf, size_t size, const char* fmt, va_list ap)
+{
+ int count = 0;
+ int argtype, convtype;
+ const char* strval;
+ long longval;
+ struct _mpz *mpval;
+ limb_t v, d;
+ size_t i;
+ int j;
+
+ while (fmt[0]) {
+ if (fmt[0] != '%') {
+ PUTCH(buf, size, count, fmt[0]);
+ fmt++;
+ }
+ else if (fmt[1] == '%') {
+ PUTCH(buf, size, count, '%');
+ fmt += 2;
+ }
+ else {
+ if (fmt[1] == 'l' || fmt[1] == 'Z') {
+ argtype = fmt[1];
+ convtype = fmt[2];
+ fmt += 3;
+ }
+ else {
+ argtype = 0;
+ convtype = fmt[1];
+ fmt += 2;
+ }
+
+ if (!convtype)
+ break;
+
+ if (convtype == 's') {
+ /* string argument */
+ strval = va_arg(ap, const char *);
+ if (!strval)
+ strval = "(NULL)";
+ while (*strval) {
+ PUTCH(buf, size, count, *strval);
+ strval++;
+ }
+ }
+ else if (convtype == 'c' || convtype == 'd' || convtype == 'i'
+ || convtype == 'u' || convtype == 'x' || convtype == 'X') {
+ if (argtype == 'Z') {
+ /* mpz argument -- always print in hexadecimal */
+ mpval = va_arg(ap, struct _mpz *);
+
+ if (mpval->sign < 0)
+ PUTCH(buf, size, count, '-');
+
+ v = IDX(mpval, mpval->size - 1);
+ count += putnum(&buf, &size, v, 16);
+
+ for (i = mpval->size - 1; i > 0; i--) {
+ v = IDX(mpval, i - 1);
+ for (j = LIMB_BITS - 4; j >= 0; j -= 4) {
+ d = ((v >> j) & 0x0f);
+ if (d < 10)
+ PUTCH(buf, size, count, d + '0');
+ else
+ PUTCH(buf, size, count, d + 'A' - 10);
+ }
+ }
+ }
+ else {
+ /* int or long argument */
+ if (argtype == 'l')
+ longval = va_arg(ap, long);
+ else
+ longval = va_arg(ap, int);
+
+ if (convtype == 'c') {
+ PUTCH(buf, size, count, (char) (unsigned char) longval);
+ }
+ else if (convtype == 'x' || convtype == 'X') {
+ count += putnum(&buf, &size, longval, 16);
+ }
+ else if (convtype == 'o') {
+ count += putnum(&buf, &size, longval, 8);
+ }
+ else if (convtype == 'u' || longval >= 0) {
+ count += putnum(&buf, &size, longval, 10);
+ }
+ else {
+ PUTCH(buf, size, count, '-');
+ count += putnum(&buf, &size, -longval, 10);
+ }
+ }
+ }
+ else {
+ fprintf(stderr, "*** ERROR: mpz: unsupported conversion '%%%c'",
+ convtype);
+ if (argtype)
+ PUTCH(buf, size, count, argtype);
+ PUTCH(buf, size, count, convtype);
+ }
+ }
+ }
+
+ if (size != 0)
+ *buf = 0;
+
+ return count;
+}
+
+int rs_snprintf(char* buf, size_t size, const char* fmt, ...)
+{
+ va_list ap;
+ int count;
+
+ va_start(ap, fmt);
+ count = rs_vsnprintf(buf, size, fmt, ap);
+ va_end(ap);
+
+ return count;
+}
+
diff --git a/tool/rabbitsign-src/mpz.h b/tool/rabbitsign-src/mpz.h
new file mode 100644
index 0000000..2eb2667
--- /dev/null
+++ b/tool/rabbitsign-src/mpz.h
@@ -0,0 +1,123 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __RABBITSIGN_MPZ_H__
+#define __RABBITSIGN_MPZ_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (SIZEOF_INT != 0) && (SIZEOF_LONG >= 2 * SIZEOF_INT)
+typedef unsigned int limb_t;
+typedef unsigned long double_limb_t;
+typedef signed long signed_double_limb_t;
+#else
+# if (SIZEOF_SHORT != 0) && (SIZEOF_INT >= 2 * SIZEOF_SHORT)
+typedef unsigned short limb_t;
+typedef unsigned int double_limb_t;
+typedef signed int signed_double_limb_t;
+# else
+typedef unsigned short limb_t;
+typedef unsigned long double_limb_t;
+typedef signed long signed_double_limb_t;
+# endif
+#endif
+
+#define LIMB_BITS (sizeof(limb_t)*8)
+#define LIMB_BYTES (sizeof(limb_t))
+#define LIMB_MASK ((((double_limb_t) 1) << LIMB_BITS) - 1)
+
+struct _mpz {
+ size_t size;
+ size_t size_alloc;
+ limb_t* m;
+ int sign;
+};
+
+typedef struct _mpz mpz_t[1];
+
+#undef __P
+#ifdef PROTOTYPES
+# define __P(x) x
+#else
+# define __P(x) ()
+#endif
+
+void mpz_init __P((mpz_t x));
+void mpz_clear __P((mpz_t x));
+
+/* Set */
+void mpz_set __P((mpz_t dest, const mpz_t src));
+void mpz_set_ui __P((mpz_t dest, unsigned int a));
+unsigned int mpz_get_ui __P((const mpz_t a));
+
+/* Import/export: assume order=-1, size=1, endian=0, nails=0 */
+void mpz_import __P((mpz_t dest, size_t count, int order, int size,
+ int endian, size_t nails, const void* op));
+void mpz_export __P((void* dest, size_t* count, int order, int size,
+ int endian, size_t nails, const mpz_t op));
+
+/* Check sign */
+int mpz_sgn __P((const mpz_t a));
+
+/* Compare */
+int mpz_cmp __P((const mpz_t a, const mpz_t b));
+int mpz_cmp_ui __P((const mpz_t a, unsigned int b));
+
+/* Add */
+void mpz_add __P((mpz_t dest, const mpz_t a, const mpz_t b));
+void mpz_add_ui __P((mpz_t dest, const mpz_t a, unsigned int b));
+
+/* Subtract */
+void mpz_sub __P((mpz_t dest, const mpz_t a, const mpz_t b));
+void mpz_sub_ui __P((mpz_t dest, const mpz_t a, unsigned int b));
+
+/* Multiply */
+void mpz_mul __P((mpz_t dest, const mpz_t a, const mpz_t b));
+void mpz_mul_ui __P((mpz_t dest, const mpz_t a, unsigned int b));
+
+/* Divide: requires b <= LIMB_BITS */
+void mpz_fdiv_q_2exp __P((mpz_t dest, const mpz_t a, unsigned int b));
+
+/* Modulus */
+void mpz_mod __P((mpz_t dest, const mpz_t a, const mpz_t mod));
+
+/* Modular exponent */
+void mpz_powm __P((mpz_t dest, const mpz_t base, const mpz_t exp,
+ const mpz_t mod));
+
+/* Legendre symbol */
+int mpz_legendre __P((const mpz_t a, const mpz_t p));
+
+/* Extended GCD */
+void mpz_gcdext __P((mpz_t g, mpz_t ai, mpz_t bi,
+ const mpz_t a, const mpz_t b));
+
+/* Output */
+int rs_snprintf __P((char* buf, size_t size, const char* fmt, ...));
+
+#ifdef va_start
+int rs_vsnprintf __P((char* buf, size_t size, const char* fmt, va_list ap));
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tool/rabbitsign-src/os8x.c b/tool/rabbitsign-src/os8x.c
new file mode 100644
index 0000000..b5e9ced
--- /dev/null
+++ b/tool/rabbitsign-src/os8x.c
@@ -0,0 +1,298 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#ifdef HAVE_STRING_H
+# include
+#else
+# ifdef HAVE_STRINGS_H
+# include
+# endif
+#endif
+
+#include "rabbitsign.h"
+#include "internal.h"
+#include "md5.h"
+
+/*
+ * Check/fix OS header fields and data.
+ *
+ * The OS header is much simpler than an application header, and its
+ * correctness is not as crucial to validation. The most important
+ * parts of the OS header are the key ID and (for newer calculators)
+ * the hardware compatibility level. There is no date stamp required.
+ * The page count is not required, and if present, is used only to
+ * display the transfer percentage (when using the 84+ boot code.)
+ *
+ * TI only sets the OS and program image size fields in their TI-73 OS
+ * headers. (Bizarrely, they are set in the true OS header, but not
+ * in the fake OS header that is transferred to page 1A. Furthermore,
+ * the OS size field is incorrect.) In any case, these fields appear
+ * to be ignored by all versions of the boot code.
+ */
+int rs_repair_ti8x_os(RSProgram* os, /* OS */
+ unsigned int flags) /* flags */
+{
+ unsigned long hdrstart, hdrsize, fieldhead, fieldstart,
+ fieldsize, ossize;
+ unsigned char* hdr;
+ int i;
+
+ /* Pad the OS to a multiple of 16384. (While strictly speaking we
+ could get away with only padding each page to a multiple of 256,
+ such "partial OSes" are not supported by most linking
+ software.) */
+
+ rs_program_set_length(os, ((os->length + 0x3fff) & ~0x3fff));
+
+ /* If no OS header was provided in the input, try to get a header
+ from page 1A instead */
+
+ if (os->header_length < 6
+ || os->header[0] != 0x80
+ || os->header[1] != 0x0f) {
+ for (i = 0; i < os->npagenums; i++) {
+ if (os->pagenums[i] == 0x1a) {
+ rs_free(os->header);
+ if (!(os->header = rs_malloc(256)))
+ return RS_ERR_OUT_OF_MEMORY;
+ memcpy(os->header, os->data + ((unsigned long) i << 14), 256);
+ os->header_length = 256;
+ break;
+ }
+ }
+ }
+
+ /* Clear old header/signature (not done on the TI-73 because
+ official TI-73 OSes contain a fake header; I don't recommend
+ doing this for third-party OSes) */
+
+ if (os->calctype != RS_CALC_TI73)
+ for (i = 0; i < os->npagenums; i++)
+ if (os->pagenums[i] == 0x1a)
+ memset(os->data + ((unsigned long) i << 14), 0xff, 512);
+
+ /* Fix header size. OS headers must always begin with an 800x field
+ and end with an 807x field (TI always uses 800F and 807F, as for
+ apps; I'm not sure whether it's required.) */
+
+ if (os->header_length < 6
+ || os->header[0] != 0x80
+ || (os->header[1] & 0xf0) != 0) {
+ rs_error(NULL, os, "no OS header found");
+ return RS_ERR_MISSING_HEADER;
+ }
+
+ rs_get_field_size(os->header, &hdrstart, NULL);
+ hdr = os->header + hdrstart;
+ hdrsize = os->header_length - hdrstart;
+
+ if (rs_find_app_field(0x8070, hdr, hdrsize,
+ &fieldhead, &fieldstart, &fieldsize)) {
+ rs_error(NULL, os, "OS header has no program image field");
+ return RS_ERR_MISSING_PROGRAM_IMAGE;
+ }
+
+ hdrsize = fieldstart;
+ os->header_length = hdrstart + hdrsize;
+
+ if ((os->header_length % 64) == 55) {
+ if (flags & RS_IGNORE_ALL_WARNINGS) {
+ rs_warning(NULL, os, "OS header has length 55 mod 64");
+ rs_warning(NULL, os, "(this will fail to validate on TI-83+ BE)");
+ }
+ else {
+ rs_error(NULL, os, "OS header has length 55 mod 64");
+ rs_error(NULL, os, "(this will fail to validate on TI-83+ BE)");
+ return RS_ERR_INVALID_PROGRAM_SIZE;
+ }
+ }
+
+ /* Fix OS / OS image sizes if requested */
+
+ if (flags & RS_FIX_OS_SIZE) {
+ ossize = os->length + hdrsize;
+ if (rs_set_field_size(os->header, ossize)) {
+ rs_error(NULL, os, "cannot set OS length");
+ return RS_ERR_FIELD_TOO_SMALL;
+ }
+
+ if (rs_set_field_size(hdr + fieldhead, os->length)) {
+ rs_error(NULL, os, "cannot set OS image length");
+ return RS_ERR_FIELD_TOO_SMALL;
+ }
+ }
+
+ /* Check for key ID */
+
+ if (rs_find_app_field(0x8010, hdr, hdrsize, NULL, NULL, NULL)) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, os, "OS header has no key ID field");
+ else {
+ rs_error(NULL, os, "OS header has no key ID field");
+ return RS_ERR_MISSING_KEY_ID;
+ }
+ }
+
+ /* Check/fix page count */
+
+ if (rs_find_app_field(0x8080, hdr, hdrsize,
+ NULL, &fieldstart, &fieldsize)) {
+ if (os->length != 14 * 0x4000L) {
+ rs_warning(NULL, os, "OS header has no page count field");
+ }
+ }
+ else if (fieldsize != 1) {
+ rs_warning(NULL, os, "OS header has an invalid page count field");
+ }
+ else if (flags & RS_FIX_PAGE_COUNT) {
+ hdr[fieldstart] = os->length >> 14;
+ }
+ else if (hdr[fieldstart] != (os->length >> 14)) {
+ rs_warning(NULL, os, "OS header has an incorrect page count field");
+ }
+
+ /* Check and reset validation flag bytes */
+
+ if (os->data[0x56] != 0xff && os->data[0x56] != 0x5a) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, os, "OS has invalid data at 0056h");
+ else {
+ rs_error(NULL, os, "OS has invalid data at 0056h");
+ return RS_ERR_INVALID_PROGRAM_DATA;
+ }
+ }
+
+ if (os->data[0x56] == 0x5a)
+ os->data[0x56] = 0xff;
+
+ if (os->data[0x57] != 0xff && os->data[0x57] != 0xa5) {
+ if (flags & RS_IGNORE_ALL_WARNINGS)
+ rs_warning(NULL, os, "OS has invalid data at 0057h");
+ else {
+ rs_error(NULL, os, "OS has invalid data at 0057h");
+ return RS_ERR_INVALID_PROGRAM_DATA;
+ }
+ }
+
+ if (os->data[0x57] == 0xff)
+ os->data[0x57] = 0xa5;
+
+ return RS_SUCCESS;
+}
+
+/*
+ * Compute signature for an OS.
+ */
+int rs_sign_ti8x_os(RSProgram* os, /* OS */
+ RSKey* key) /* signing key */
+{
+ struct md5_ctx ctx;
+ md5_uint32 hash[4];
+ mpz_t hashv, sigv;
+ unsigned char sigdata[512];
+ size_t siglength;
+ int e;
+
+ md5_init_ctx(&ctx);
+ md5_process_bytes(os->header, os->header_length, &ctx);
+ md5_process_bytes(os->data, os->length, &ctx);
+ md5_finish_ctx(&ctx, hash);
+
+ mpz_init(hashv);
+ mpz_init(sigv);
+
+ mpz_import(hashv, 16, -1, 1, 0, 0, hash);
+ rs_message(2, NULL, os, "hash = %ZX", hashv);
+
+ if ((e = rs_sign_rsa(sigv, hashv, key))) {
+ mpz_clear(hashv);
+ mpz_clear(sigv);
+ return e;
+ }
+
+ rs_message(2, NULL, os, "sig = %ZX", sigv);
+
+ sigdata[0] = 0x02;
+ sigdata[1] = 0x0d;
+ mpz_export(sigdata + 3, &siglength, -1, 1, 0, 0, sigv);
+ sigdata[2] = siglength & 0xff;
+ siglength += 3;
+
+ while (siglength < 96)
+ sigdata[siglength++] = 0xff;
+
+ rs_free(os->signature);
+ if (!(os->signature = rs_malloc(siglength)))
+ return RS_ERR_OUT_OF_MEMORY;
+
+ memcpy(os->signature, sigdata, siglength);
+ os->signature_length = siglength;
+ return RS_SUCCESS;
+}
+
+/*
+ * Validate OS signature.
+ */
+int rs_validate_ti8x_os(const RSProgram* os,
+ const RSKey* key)
+{
+ unsigned long fieldstart, fieldsize;
+ struct md5_ctx ctx;
+ md5_uint32 hash[4];
+ mpz_t hashv, sigv;
+ int e;
+
+ if (os->signature_length < 3) {
+ rs_error(NULL, os, "OS does not have a signature");
+ return RS_ERR_MISSING_RSA_SIGNATURE;
+ }
+
+ if (os->signature[0] != 0x02 || (os->signature[1] & 0xf0) != 0x00) {
+ rs_error(NULL, os, "OS does not have an RSA signature");
+ return RS_ERR_MISSING_RSA_SIGNATURE;
+ }
+ rs_get_field_size(os->signature, &fieldstart, &fieldsize);
+
+ md5_init_ctx(&ctx);
+ md5_process_bytes(os->header, os->header_length, &ctx);
+ md5_process_bytes(os->data, os->length, &ctx);
+ md5_finish_ctx(&ctx, hash);
+
+ mpz_init(hashv);
+ mpz_init(sigv);
+
+ mpz_import(hashv, 16, -1, 1, 0, 0, hash);
+ rs_message(2, NULL, os, "hash = %ZX", hashv);
+
+ mpz_import(sigv, fieldsize, -1, 1, 0, 0, os->signature + fieldstart);
+ rs_message(2, NULL, os, "sig = %ZX", sigv);
+
+ e = rs_validate_rsa(sigv, hashv, key);
+ if (e == RS_SIGNATURE_INCORRECT)
+ rs_message(0, NULL, os, "OS signature incorrect");
+
+ mpz_clear(hashv);
+ mpz_clear(sigv);
+ return e;
+}
diff --git a/tool/rabbitsign-src/output.c b/tool/rabbitsign-src/output.c
new file mode 100644
index 0000000..6004b9b
--- /dev/null
+++ b/tool/rabbitsign-src/output.c
@@ -0,0 +1,39 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#include "rabbitsign.h"
+
+/*
+ * Write program contents to a file.
+ */
+int rs_write_program_file(const RSProgram* prgm, FILE* f,
+ int month, int day, int year,
+ unsigned int flags)
+{
+ if (rs_calc_is_ti8x(prgm->calctype)
+ && (prgm->datatype == RS_DATA_OS || prgm->datatype == RS_DATA_APP))
+ return rs_write_ti8x_file(prgm, f, month, day, year, flags);
+ else
+ return rs_write_ti9x_file(prgm, f, month, day, year, flags);
+}
diff --git a/tool/rabbitsign-src/output8x.c b/tool/rabbitsign-src/output8x.c
new file mode 100644
index 0000000..d08f061
--- /dev/null
+++ b/tool/rabbitsign-src/output8x.c
@@ -0,0 +1,248 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#ifdef HAVE_STRING_H
+# include
+#else
+# ifdef HAVE_STRINGS_H
+# include
+# endif
+#endif
+
+#include "rabbitsign.h"
+#include "internal.h"
+
+/*
+ * Write a single record to an Intel hex file.
+ */
+static int write_hex_record(FILE* outfile, /* output file */
+ unsigned int nbytes, /* number of bytes */
+ unsigned int addr, /* address */
+ unsigned int type, /* record type */
+ unsigned char* data, /* data */
+ unsigned int flags, /* flags */
+ int final)
+{
+ char buf[256];
+ unsigned int i;
+ unsigned int sum;
+
+ sum = nbytes + addr + (addr >> 8) + type;
+ sprintf(buf, ":%02X%04X%02X", nbytes, addr, type);
+
+ for (i = 0; i < nbytes; i++) {
+ sprintf(buf + 9 + 2 * i, "%02X", data[i]);
+ sum += data[i];
+ }
+
+ sum = ((-sum) & 0xff);
+
+ sprintf(buf + 9 + 2 * i, "%02X", sum);
+
+ if (!final) {
+ if (flags & RS_OUTPUT_APPSIGN)
+ strcpy(buf + 11 + 2 * i, "\n");
+ else
+ strcpy(buf + 11 + 2 * i, "\r\n");
+ }
+
+ if (fputs(buf, outfile) == EOF) {
+ rs_error(NULL, NULL, "file I/O error");
+ return RS_ERR_FILE_IO;
+ }
+
+ return RS_SUCCESS;
+}
+
+/*
+ * Write a chunk of data to an Intel hex file.
+ */
+static int write_hex_data(FILE* outfile, /* output file */
+ unsigned long length, /* number of bytes */
+ unsigned long addr, /* starting address */
+ unsigned char* data, /* data */
+ unsigned int flags)
+{
+ unsigned int count;
+ int e;
+
+ while (length > 0) {
+ if (length < 0x20)
+ count = length;
+ else
+ count = 0x20;
+
+ if ((e = write_hex_record(outfile, count, addr, 0, data, flags, 0)))
+ return e;
+
+ length -= count;
+ addr += count;
+ data += count;
+ }
+
+ return RS_SUCCESS;
+}
+
+/*
+ * Write program to a .73k/.73u/.8xk/.8xu or .app file.
+ *
+ * If month = day = year = 0, use the current time.
+ *
+ * Note: on platforms where it matters, all output files must be
+ * opened in "binary" mode.
+ */
+int rs_write_ti8x_file(const RSProgram* prgm, /* program */
+ FILE* outfile, /* output file */
+ int month, /* timestamp month */
+ int day, /* timestamp day */
+ int year, /* timestamp year*/
+ unsigned int flags) /* flags */
+{
+ const unsigned char *hdr;
+ unsigned long hdrstart, hdrsize, fieldstart, fieldsize;
+ int major, minor, i;
+ unsigned long npages, nrecords, hexsize;
+ char name[9];
+ unsigned int pagenum, addr;
+ unsigned long count;
+ unsigned char pnbuf[2];
+ int e;
+
+ if (!(flags & RS_OUTPUT_HEX_ONLY)) {
+ if (prgm->header_length) {
+ hdr = prgm->header;
+ hdrsize = prgm->header_length;
+ }
+ else {
+ hdr = prgm->data;
+ hdrsize = prgm->length;
+ }
+
+ if (hdrsize >= 6) {
+ rs_get_field_size(hdr, &hdrstart, NULL);
+ hdr += hdrstart;
+ hdrsize -= hdrstart;
+ if (hdrsize > 128)
+ hdrsize = 128;
+
+ major = rs_get_numeric_field(0x8020, hdr, hdrsize);
+ minor = rs_get_numeric_field(0x8030, hdr, hdrsize);
+
+ if (prgm->datatype == RS_DATA_OS) {
+ if (prgm->calctype == RS_CALC_TI73)
+ strcpy(name, "BASECODE");
+ else
+ strcpy(name, "basecode");
+ }
+ else if (!rs_find_app_field(0x8040, hdr, hdrsize,
+ NULL, &fieldstart, &fieldsize)) {
+ if (fieldsize > 8)
+ fieldsize = 8;
+ strncpy(name, (char*) hdr + fieldstart, fieldsize);
+ name[fieldsize] = 0;
+ }
+ else {
+ name[0] = 0;
+ }
+ }
+ else {
+ major = minor = 0;
+ name[0] = 0;
+ }
+
+ npages = ((prgm->length + 0x3fff) >> 14);
+ nrecords = 1 + npages + ((prgm->length + 0x1f) >> 5);
+
+ if (prgm->header_length)
+ nrecords += 1 + ((prgm->header_length + 0x1f) >> 5);
+ if (prgm->signature_length)
+ nrecords += 1 + ((prgm->signature_length + 0x1f) >> 5);
+
+ if (flags & RS_OUTPUT_APPSIGN) {
+ hexsize = (npages * 4
+ + prgm->length * 2
+ + prgm->header_length * 2
+ + prgm->signature_length * 2
+ + nrecords * 12 - 1);
+ }
+ else {
+ hexsize = (npages * 4
+ + prgm->length * 2
+ + prgm->header_length * 2
+ + prgm->signature_length * 2
+ + nrecords * 13 - 2);
+ }
+
+ if ((e = rs_write_tifl_header(outfile, 1, major, minor,
+ month, day, year, name,
+ prgm->calctype, prgm->datatype,
+ hexsize)))
+ return e;
+ }
+
+ if (prgm->header_length) {
+ if ((e = write_hex_data(outfile, prgm->header_length, 0,
+ prgm->header, flags)))
+ return e;
+ if ((e = write_hex_record(outfile, 0, 0, 1, NULL, flags, 0)))
+ return e;
+ }
+
+ for (i = 0; ((unsigned long) i << 14) < prgm->length; i++) {
+ if (i < prgm->npagenums)
+ pagenum = prgm->pagenums[i];
+ else
+ pagenum = i;
+
+ if (pagenum == 0 && prgm->header_length)
+ addr = 0;
+ else
+ addr = 0x4000;
+
+ pnbuf[0] = (pagenum >> 8) & 0xff;
+ pnbuf[1] = pagenum & 0xff;
+
+ if ((e = write_hex_record(outfile, 2, 0, 2, pnbuf, flags, 0)))
+ return e;
+
+ count = prgm->length - i * 0x4000;
+ if (count > 0x4000)
+ count = 0x4000;
+
+ if ((e = write_hex_data(outfile, count, addr,
+ prgm->data + i * 0x4000, flags)))
+ return e;
+ }
+
+ if (prgm->signature_length) {
+ if ((e = write_hex_record(outfile, 0, 0, 1, NULL, flags, 0)))
+ return e;
+ if ((e = write_hex_data(outfile, prgm->signature_length, 0,
+ prgm->signature, flags)))
+ return e;
+ }
+
+ return write_hex_record(outfile, 0, 0, 1, NULL, flags, 1);
+}
+
diff --git a/tool/rabbitsign-src/output9x.c b/tool/rabbitsign-src/output9x.c
new file mode 100644
index 0000000..d765abe
--- /dev/null
+++ b/tool/rabbitsign-src/output9x.c
@@ -0,0 +1,96 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#ifdef HAVE_STRING_H
+# include
+#else
+# ifdef HAVE_STRINGS_H
+# include
+# endif
+#endif
+
+#include "rabbitsign.h"
+#include "internal.h"
+
+/*
+ * Write program to a .89k/.89u/.9xk/.9xu file.
+ *
+ * If month = day = year = 0, use the current time.
+ *
+ * Note: on platforms where it matters, all output files must be
+ * opened in "binary" mode.
+ */
+int rs_write_ti9x_file(const RSProgram* prgm, /* program */
+ FILE* outfile, /* output file */
+ int month, /* timestamp month */
+ int day, /* timestamp day */
+ int year, /* timestamp year*/
+ unsigned int flags RS_ATTR_UNUSED)
+{
+ const unsigned char *hdr;
+ unsigned long hdrstart, hdrsize, fieldstart, fieldsize;
+ char name[9];
+ int e;
+
+ if (prgm->length >= 6) {
+ rs_get_field_size(prgm->data, &hdrstart, &hdrsize);
+ hdr = prgm->data + hdrstart;
+ if (hdrsize > 128)
+ hdrsize = 128;
+
+ if (prgm->datatype == RS_DATA_OS) {
+ strcpy(name, "basecode");
+ }
+ else if (!rs_find_app_field(0x8140, hdr, hdrsize,
+ NULL, &fieldstart, &fieldsize)) {
+ if (fieldsize > 8)
+ fieldsize = 8;
+ strncpy(name, (char*) hdr + fieldstart, fieldsize);
+ name[fieldsize] = 0;
+ }
+ else {
+ name[0] = 0;
+ }
+ }
+ else {
+ name[0] = 0;
+ }
+
+ /* Note: the "version" header fields used in TI's 68k apps and
+ OSes seem to have no relation to the actual version numbers. */
+
+ if ((e = rs_write_tifl_header(outfile, 0, 0, 0,
+ month, day, year, name,
+ prgm->calctype, prgm->datatype,
+ prgm->length)))
+ return e;
+
+ if (fwrite(prgm->data, 1, prgm->length, outfile) != prgm->length) {
+ rs_error(NULL, NULL, "file I/O error");
+ return RS_ERR_FILE_IO;
+ }
+
+ return RS_SUCCESS;
+}
+
diff --git a/tool/rabbitsign-src/program.c b/tool/rabbitsign-src/program.c
new file mode 100644
index 0000000..e7cf140
--- /dev/null
+++ b/tool/rabbitsign-src/program.c
@@ -0,0 +1,187 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#ifdef HAVE_STRING_H
+# include
+#else
+# ifdef HAVE_STRINGS_H
+# include
+# endif
+#endif
+
+#include "rabbitsign.h"
+#include "internal.h"
+
+/*
+ * Create a new program.
+ */
+RSProgram* rs_program_new()
+{
+ RSProgram* prgm = rs_malloc(sizeof(RSProgram));
+
+ if (!prgm)
+ return NULL;
+
+ prgm->filename = NULL;
+ prgm->calctype = 0;
+ prgm->datatype = 0;
+ prgm->data = NULL;
+ prgm->length = 0;
+ prgm->length_a = 0;
+ prgm->header = NULL;
+ prgm->header_length = 0;
+ prgm->signature = NULL;
+ prgm->signature_length = 0;
+ prgm->pagenums = NULL;
+ prgm->npagenums = 0;
+
+ return prgm;
+}
+
+/*
+ * Create a new program by wrapping an existing data buffer.
+ *
+ * If buffer_size is zero, data will be copied from the source buffer
+ * into the new program.
+ *
+ * If buffer_size is nonzero, then the source buffer must have been
+ * allocated using malloc(); buffer_size is the total amount of memory
+ * allocated. The data will not be copied, and the new program object
+ * assumes ownership of the buffer.
+ */
+RSProgram* rs_program_new_with_data(RSCalcType ctype, /* calc type */
+ RSDataType dtype, /* data type */
+ void* data, /* source buffer */
+ unsigned long length, /* length of data */
+ unsigned long buffer_size) /* amount of
+ memory
+ allocated */
+{
+ RSProgram* prgm = rs_program_new();
+
+ if (!prgm)
+ return NULL;
+
+ prgm->calctype = ctype;
+ prgm->datatype = dtype;
+
+ if (data) {
+ if (buffer_size) {
+ prgm->data = data;
+ prgm->length = length;
+ prgm->length_a = buffer_size;
+ }
+ else {
+ if (rs_program_append_data(prgm, data, length)) {
+ rs_program_free(prgm);
+ return NULL;
+ }
+ }
+ }
+
+ return prgm;
+}
+
+/*
+ * Free program data.
+ */
+void rs_program_free(RSProgram* prgm)
+{
+ if (!prgm)
+ return;
+
+ rs_free(prgm->filename);
+ rs_free(prgm->data);
+ rs_free(prgm->header);
+ rs_free(prgm->signature);
+ rs_free(prgm->pagenums);
+ rs_free(prgm);
+}
+
+/*
+ * Truncate or extend program.
+ *
+ * If length is less than the program's current length, the program is
+ * truncated. If length is greater than the current size of the
+ * program, additional space is added. The extra space is padded with
+ * 0xFF, with the exception of bytes that fall at the start of a page.
+ */
+int rs_program_set_length(RSProgram* prgm, /* program */
+ unsigned long length) /* new length of program */
+{
+ unsigned long length_a, i;
+ unsigned char* dptr;
+
+ if (length <= prgm->length) {
+ prgm->length = length;
+ return RS_SUCCESS;
+ }
+ else {
+ if (length > prgm->length_a) {
+ length_a = length + 16384;
+
+ dptr = rs_realloc(prgm->data, length_a);
+ if (!dptr)
+ return RS_ERR_OUT_OF_MEMORY;
+ prgm->data = dptr;
+ prgm->length_a = length_a;
+ }
+
+ memset(prgm->data + prgm->length, 0xff, length - prgm->length);
+
+ for (i = ((prgm->length + 0x3fff) & ~0x3fff);
+ i < length;
+ i += 0x4000)
+ prgm->data[i] = 0x42;
+
+ prgm->length = length;
+ return RS_SUCCESS;
+ }
+}
+
+/*
+ * Add data to the end of the program.
+ */
+int rs_program_append_data(RSProgram* prgm, /* program */
+ const unsigned char* data, /* data */
+ unsigned long length) /* size of data */
+{
+ unsigned long nlength, length_a;
+ unsigned char* dptr;
+
+ nlength = prgm->length + length;
+ if (nlength > prgm->length_a) {
+ length_a = nlength + 16384;
+
+ dptr = rs_realloc(prgm->data, length_a);
+ if (!dptr)
+ return RS_ERR_OUT_OF_MEMORY;
+ prgm->data = dptr;
+ prgm->length_a = length_a;
+ }
+
+ memcpy(prgm->data + prgm->length, data, length);
+ prgm->length = nlength;
+ return RS_SUCCESS;
+}
diff --git a/tool/rabbitsign-src/rabbitsign.c b/tool/rabbitsign-src/rabbitsign.c
new file mode 100644
index 0000000..94877de
--- /dev/null
+++ b/tool/rabbitsign-src/rabbitsign.c
@@ -0,0 +1,463 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#ifdef HAVE_STDLIB_H
+# include
+#endif
+
+#ifdef HAVE_STRING_H
+# include
+#else
+# ifdef HAVE_STRINGS_H
+# include
+# endif
+#endif
+
+#include "rabbitsign.h"
+#include "internal.h"
+
+#if !defined(strcasecmp) && !defined(HAVE_STRCASECMP)
+# ifdef HAVE_STRICMP
+# define strcasecmp stricmp
+# else
+# define strcasecmp strcmp
+# endif
+#endif
+
+#if !defined(strrchr) && !defined(HAVE_STRRCHR) && defined(HAVE_RINDEX)
+# define strrchr rindex
+#endif
+
+static const char* getbasename(const char* f)
+{
+ const char *p;
+
+ if ((p = strrchr(f, '/')))
+ f = p + 1;
+
+#if defined(__MSDOS__) || defined(__WIN32__)
+ if ((p = strrchr(f, '\\')))
+ f = p + 1;
+#endif
+
+ return f;
+}
+
+static const char* usage[]={
+ "Usage: %s [options] app-file ...\n",
+ "Where options may include:\n",
+ " -a: appsign compatibility mode (Unix-style output)\n",
+ " -b: read raw binary data (default: auto-detect)\n",
+ " -c: check existing app signatures rather than signing\n",
+ " -f: force signing despite errors\n",
+ " -g: write app in GraphLink (XXk) format\n",
+ " -k KEYFILE: use specified key file\n",
+ " -K NUM: use specified key ID (hexadecimal)\n",
+ " -n: do not alter the app header\n",
+ " -o OUTFILE: write to specified output file (default is .app\n",
+ " or .8xk)\n",
+ " -p: fix the pages field if found\n",
+ " -P: add an extra page if necessary\n",
+ " -q: suppress warning messages\n",
+ " -r: re-sign a previously signed app (i.e. strip off all\n",
+ " data beyond that indicated by the size header)\n",
+ " -R R: specify the root to use (0, 1, 2, or 3) (default is 0)\n",
+ " -t TYPE: specify program type (e.g. 8xk, 73u)\n",
+ " -u: assume plain hex input is unsorted (default is sorted)\n",
+ " -v: be verbose (-vv for even more verbosity)\n",
+ " --help: describe options\n",
+ " --version: print version info\n",
+ NULL};
+
+int main(int argc, char** argv)
+{
+ unsigned int flags = (RS_INPUT_SORTED | RS_OUTPUT_HEX_ONLY);
+
+ int rootnum = 0; /* which of the four valid signatures
+ to generate
+
+ 0 = standard (r,s)
+ 1 = (-r,s)
+ 2 = (r,-s)
+ 3 = (-r,-s) */
+
+ int rawmode = 0; /* 0 = fix app headers
+ 1 = sign "raw" data */
+
+ int valmode = 0; /* 0 = sign apps
+ 1 = validate apps */
+
+ const char* infilename; /* file name for input */
+
+ const char* outfilename = NULL; /* file name for output */
+
+ const char* keyfilename = NULL; /* file name for key */
+
+ int verbose = 0; /* -1 = quiet (errors only)
+ 0 = default (warnings + errors)
+ 1 = verbose (print file names / status)
+ 2 = very verbose (details of computation) */
+
+ static const char optstring[] = "abcfgk:K:no:pPqrR:t:uv";
+ const char *progname;
+ int i, j, c, e;
+ const char* arg;
+ char *tempname;
+
+ FILE* infile;
+ FILE* outfile;
+ RSKey* key;
+ RSProgram* prgm;
+ unsigned long keyid = 0, appkeyid;
+ RSCalcType ctype = RS_CALC_UNKNOWN;
+ RSDataType dtype = RS_DATA_UNKNOWN;
+
+ char *ptr;
+ const char *ext;
+ int invalidapps = 0;
+
+ progname = getbasename(argv[0]);
+ rs_set_progname(progname);
+
+ if (argc == 1) {
+ fprintf(stderr, usage[0], progname);
+ for (i = 1; usage[i]; i++)
+ fputs(usage[i], stderr);
+ return 5;
+ }
+
+ i = j = 1;
+ while ((c = rs_parse_cmdline(argc, argv, optstring, &i, &j, &arg))) {
+ switch (c) {
+ case RS_CMDLINE_HELP:
+ printf(usage[0], progname);
+ for (i = 1; usage[i]; i++)
+ fputs(usage[i], stdout);
+ return 0;
+
+ case RS_CMDLINE_VERSION:
+ printf("rabbitsign\n");
+ fputs("Copyright (C) 2009 Benjamin Moody\n", stdout);
+ fputs("This program is free software. ", stdout);
+ fputs("There is NO WARRANTY of any kind.\n", stdout);
+ return 0;
+
+ case 'o':
+ outfilename = arg;
+ break;
+
+ case 'k':
+ keyfilename = arg;
+ break;
+
+ case 'K':
+ if (!sscanf(arg, "%lx", &keyid)) {
+ fprintf(stderr, "%s: -K: invalid argument %s\n", progname, arg);
+ return 5;
+ }
+ break;
+
+ case 'b':
+ flags |= RS_INPUT_BINARY;
+ break;
+
+ case 'u':
+ flags &= ~RS_INPUT_SORTED;
+ break;
+
+ case 'f':
+ flags |= RS_IGNORE_ALL_WARNINGS;
+ break;
+
+ case 'g':
+ flags &= ~RS_OUTPUT_HEX_ONLY;
+ break;
+
+ case 'a':
+ flags |= RS_OUTPUT_APPSIGN;
+ break;
+
+ case 'R':
+ if (!sscanf(arg, "%d", &rootnum)) {
+ fprintf(stderr, "%s: -R: invalid argument %s\n", progname, arg);
+ return 5;
+ }
+ break;
+
+ case 't':
+ if (rs_suffix_to_type(arg, &ctype, &dtype)) {
+ fprintf(stderr, "%s: unrecognized file type %s\n", progname, arg);
+ return 5;
+ }
+ break;
+
+ case 'n':
+ rawmode = 1;
+ break;
+
+ case 'r':
+ flags |= RS_REMOVE_OLD_SIGNATURE;
+ break;
+
+ case 'P':
+ flags |= RS_ZEALOUSLY_PAD_APP;
+ break;
+
+ case 'p':
+ flags |= RS_FIX_PAGE_COUNT;
+ break;
+
+ case 'c':
+ valmode = 1;
+ break;
+
+ case 'v':
+ verbose++;
+ break;
+
+ case 'q':
+ verbose--;
+ break;
+
+ case RS_CMDLINE_FILENAME:
+ break;
+
+ case RS_CMDLINE_ERROR:
+ return 5;
+
+ default:
+ fprintf(stderr, "%s: internal error: unknown option -%c\n",
+ progname, c);
+ abort();
+ }
+ }
+
+ rs_set_verbose(verbose);
+
+ if (outfilename && (ptr = strrchr(outfilename, '.'))
+ && !rs_suffix_to_type(ptr + 1, NULL, NULL))
+ flags &= ~RS_OUTPUT_HEX_ONLY;
+
+
+ /* Read key file (if manually specified) */
+
+ key = rs_key_new();
+
+ if (keyfilename) {
+ infile = fopen(keyfilename, "rb");
+ if (!infile) {
+ perror(keyfilename);
+ rs_key_free(key);
+ return 3;
+ }
+ if (rs_read_key_file(key, infile, keyfilename, 1)) {
+ fclose(infile);
+ rs_key_free(key);
+ return 3;
+ }
+ fclose(infile);
+ }
+ else if (keyid) {
+ if (rs_key_find_for_id(key, keyid, valmode)) {
+ rs_key_free(key);
+ return 3;
+ }
+ }
+
+ /* Process applications */
+
+ i = j = 1;
+ while ((c = rs_parse_cmdline(argc, argv, optstring, &i, &j, &arg))) {
+ if (c != RS_CMDLINE_FILENAME)
+ continue;
+
+ /* Read input file */
+
+ if (strcmp(arg, "-")) {
+ infilename = arg;
+ infile = fopen(arg, "rb");
+ if (!infile) {
+ perror(arg);
+ rs_key_free(key);
+ return 4;
+ }
+ }
+ else {
+ infilename = "(standard input)";
+ infile = stdin;
+ }
+
+ prgm = rs_program_new();
+
+ if (ctype && dtype) {
+ prgm->calctype = ctype;
+ prgm->datatype = dtype;
+ }
+ else if ((ptr = strrchr(infilename, '.'))) {
+ rs_suffix_to_type(ptr + 1, &prgm->calctype, &prgm->datatype);
+ }
+
+ if (rs_read_program_file(prgm, infile, infilename, flags)) {
+ rs_program_free(prgm);
+ rs_key_free(key);
+ if (infile != stdin)
+ fclose(infile);
+ return 4;
+ }
+ if (infile != stdin)
+ fclose(infile);
+
+ /* Read key file (if automatic) */
+
+ if (!keyfilename && !keyid) {
+ appkeyid = rs_program_get_key_id(prgm);
+ if (!appkeyid) {
+ fprintf(stderr, "%s: unable to determine key ID\n", infilename);
+ rs_program_free(prgm);
+ rs_key_free(key);
+ return 3;
+ }
+
+ if (appkeyid != key->id) {
+ if (rs_key_find_for_id(key, appkeyid, valmode)) {
+ rs_program_free(prgm);
+ rs_key_free(key);
+ return 3;
+ }
+ }
+ }
+
+ if (valmode) {
+ /* Validate application */
+ if (verbose > 0)
+ fprintf(stderr, "Validating %s %s %s...\n",
+ rs_calc_type_to_string(prgm->calctype),
+ rs_data_type_to_string(prgm->datatype),
+ infilename);
+
+ if (rs_validate_program(prgm, key))
+ invalidapps++;
+ }
+ else {
+ /* Sign application */
+ if (verbose > 0)
+ fprintf(stderr, "Signing %s %s %s...\n",
+ rs_calc_type_to_string(prgm->calctype),
+ rs_data_type_to_string(prgm->datatype),
+ infilename);
+
+ if (!rawmode) {
+ if ((e = rs_repair_program(prgm, flags))) {
+ if (!(flags & RS_IGNORE_ALL_WARNINGS)
+ && e < RS_ERR_CRITICAL)
+ fprintf(stderr, "(use -f to override)\n");
+ rs_program_free(prgm);
+ rs_key_free(key);
+ return 2;
+ }
+ }
+ if (rs_sign_program(prgm, key, rootnum)) {
+ rs_program_free(prgm);
+ rs_key_free(key);
+ return 2;
+ }
+
+ /* Generate output file name */
+
+ if (outfilename) {
+ if (strcmp(outfilename, "-")) {
+ outfile = fopen(outfilename, "wb");
+ if (!outfile) {
+ perror(outfilename);
+ rs_program_free(prgm);
+ rs_key_free(key);
+ return 4;
+ }
+ }
+ else {
+ outfile = stdout;
+ }
+ }
+ else if (infile == stdin) {
+ outfile = stdout;
+ }
+ else {
+ ext = rs_type_to_suffix(prgm->calctype, prgm->datatype,
+ (flags & RS_OUTPUT_HEX_ONLY));
+
+ tempname = rs_malloc(strlen(infilename) + 32);
+ if (!tempname) {
+ rs_program_free(prgm);
+ rs_key_free(key);
+ return 4;
+ }
+ strcpy(tempname, infilename);
+
+ ptr = strrchr(tempname, '.');
+ if (!ptr) {
+ strcat(tempname, ".");
+ strcat(tempname, ext);
+ }
+ else if (strcasecmp(ptr + 1, ext)) {
+ strcpy(ptr + 1, ext);
+ }
+ else {
+ strcpy(ptr, "-signed.");
+ strcat(ptr, ext);
+ }
+
+ outfile = fopen(tempname, "wb");
+ if (!outfile) {
+ perror(tempname);
+ rs_free(tempname);
+ rs_program_free(prgm);
+ rs_key_free(key);
+ return 4;
+ }
+ rs_free(tempname);
+ }
+
+ /* Write signed application to output file */
+
+ if (rs_write_program_file(prgm, outfile, 0, 0, 0, flags)) {
+ if (outfile != stdout)
+ fclose(outfile);
+ rs_program_free(prgm);
+ rs_key_free(key);
+ return 4;
+ }
+
+ if (outfile != stdout)
+ fclose(outfile);
+ }
+ rs_program_free(prgm);
+ }
+
+ rs_key_free(key);
+
+ if (invalidapps)
+ return 1;
+ else
+ return 0;
+}
diff --git a/tool/rabbitsign-src/rabbitsign.h b/tool/rabbitsign-src/rabbitsign.h
new file mode 100644
index 0000000..6c2b7b1
--- /dev/null
+++ b/tool/rabbitsign-src/rabbitsign.h
@@ -0,0 +1,342 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __RABBITSIGN_H__
+#define __RABBITSIGN_H__
+
+#ifdef HAVE_GMP_H
+# include
+# define rs_snprintf gmp_snprintf
+# define rs_vsnprintf gmp_vsnprintf
+#else
+# include "mpz.h"
+#endif
+
+#if __GNUC__ >= 3
+# define RS_ATTR_PURE __attribute__((pure))
+# define RS_ATTR_MALLOC __attribute__((malloc))
+# define RS_ATTR_UNUSED __attribute__((unused))
+# define RS_ATTR_PRINTF(f,i) __attribute__((format(printf,f,i)))
+#else
+# define RS_ATTR_PURE
+# define RS_ATTR_MALLOC
+# define RS_ATTR_UNUSED
+# define RS_ATTR_PRINTF(f,i)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Calculator types */
+typedef enum _RSCalcType {
+ RS_CALC_UNKNOWN = 0,
+ RS_CALC_TI73 = 0x74,
+ RS_CALC_TI83P = 0x73,
+ RS_CALC_TI89 = 0x98,
+ RS_CALC_TI92P = 0x88
+} RSCalcType;
+
+#define rs_calc_is_ti8x(ttt) ((ttt) == RS_CALC_TI73 || (ttt) == RS_CALC_TI83P)
+#define rs_calc_is_ti9x(ttt) ((ttt) == RS_CALC_TI89 || (ttt) == RS_CALC_TI92P)
+
+/* Data types */
+typedef enum _RSDataType {
+ RS_DATA_UNKNOWN = 0,
+ RS_DATA_OS = 0x23,
+ RS_DATA_APP = 0x24,
+ RS_DATA_CERT = 0x25
+} RSDataType;
+
+/* Flags for app signing */
+typedef enum _RSRepairFlags {
+ RS_IGNORE_ALL_WARNINGS = 1,
+ RS_REMOVE_OLD_SIGNATURE = 2, /* Remove existing signature */
+ RS_FIX_PAGE_COUNT = 4, /* Fix page count header field */
+ RS_FIX_OS_SIZE = 8, /* Fix size in OS header */
+ RS_ZEALOUSLY_PAD_APP = 16 /* Pad application with an extra
+ page if necessary */
+} RSRepairFlags;
+
+/* Flags for file input */
+typedef enum _RSInputFlags {
+ RS_INPUT_BINARY = 32, /* Assume input is raw binary
+ data */
+ RS_INPUT_SORTED = 64 /* Assume plain hex input is sorted
+ (implicit page switch) */
+} RSInputFlags;
+
+/* Flags for file output */
+typedef enum _RSOutputFlags {
+ RS_OUTPUT_HEX_ONLY = 128, /* Write plain hex (.app) format */
+ RS_OUTPUT_APPSIGN = 256 /* Write hex data in
+ appsign-compatible format */
+} RSOutputFlags;
+
+/* Encryption key structure */
+typedef struct _RSKey {
+ char* filename; /* Filename */
+ unsigned long id; /* Key ID */
+ mpz_t n; /* Modulus (public key) */
+ mpz_t p; /* First factor */
+ mpz_t q; /* Second factor */
+ mpz_t qinv; /* q^-1 mod p (for Rabin)
+ (rs_sign_rabin() will calculate
+ this based on p and q, if
+ needed) */
+ mpz_t d; /* Signing exponent (for RSA)
+ (rs_sign_rsa() will calculate this
+ based on p and q, if needed) */
+} RSKey;
+
+/* Program data structure */
+typedef struct _RSProgram {
+ char* filename; /* Filename */
+ RSCalcType calctype; /* Calculator type */
+ RSDataType datatype; /* Program data type */
+ unsigned char* data; /* Program data */
+ unsigned long length; /* Length of program data */
+ unsigned long length_a; /* Size of buffer allocated */
+
+ /* Additional metadata (only used by TI-8x OS) */
+ unsigned char* header; /* OS header */
+ unsigned int header_length; /* Length of OS header */
+ unsigned char* signature; /* OS signature */
+ unsigned int signature_length; /* Length of OS signature */
+ unsigned int* pagenums; /* List of page numbers */
+ int npagenums; /* Number of page numbers */
+} RSProgram;
+
+/* Status codes */
+typedef enum _RSStatus {
+ RS_SUCCESS = 0,
+
+ RS_ERR_MISSING_PAGE_COUNT,
+ RS_ERR_MISSING_KEY_ID,
+ RS_ERR_MISSING_DATE_STAMP,
+ RS_ERR_MISSING_PROGRAM_IMAGE,
+ RS_ERR_MISALIGNED_PROGRAM_IMAGE,
+ RS_ERR_INVALID_PROGRAM_DATA,
+ RS_ERR_INVALID_PROGRAM_SIZE,
+ RS_ERR_INCORRECT_PAGE_COUNT,
+ RS_ERR_FINAL_PAGE_TOO_LONG,
+ RS_ERR_FIELD_TOO_SMALL,
+
+ RS_ERR_CRITICAL = 1000,
+
+ RS_ERR_OUT_OF_MEMORY,
+ RS_ERR_FILE_IO,
+ RS_ERR_HEX_SYNTAX,
+ RS_ERR_UNKNOWN_FILE_FORMAT,
+ RS_ERR_UNKNOWN_PROGRAM_TYPE,
+ RS_ERR_MISSING_HEADER,
+ RS_ERR_MISSING_RABIN_SIGNATURE,
+ RS_ERR_MISSING_RSA_SIGNATURE,
+ RS_ERR_INCORRECT_PROGRAM_SIZE,
+ RS_ERR_KEY_NOT_FOUND,
+ RS_ERR_KEY_SYNTAX,
+ RS_ERR_INVALID_KEY,
+ RS_ERR_MISSING_PUBLIC_KEY,
+ RS_ERR_MISSING_PRIVATE_KEY,
+ RS_ERR_UNSUITABLE_RABIN_KEY,
+ RS_ERR_UNSUITABLE_RSA_KEY,
+
+ RS_SIGNATURE_INCORRECT = -1
+} RSStatus;
+
+
+/**** Key handling (keys.c) ****/
+
+/* Create a new key. */
+RSKey* rs_key_new (void) RS_ATTR_MALLOC;
+
+/* Free a key. */
+void rs_key_free (RSKey* key);
+
+/* Read key from a file. */
+RSStatus rs_read_key_file (RSKey* key, FILE* f,
+ const char* fname, int verify);
+
+/* Parse a number written in TI's hexadecimal key format. */
+RSStatus rs_parse_key_value (mpz_t dest, const char* str);
+
+
+/**** Program data manipulation (program.c) ****/
+
+/* Create a new program. */
+RSProgram* rs_program_new (void) RS_ATTR_MALLOC;
+
+/* Create a new program from an existing data buffer. */
+RSProgram* rs_program_new_with_data (RSCalcType ctype, RSDataType dtype,
+ void* data, unsigned long length,
+ unsigned long buffer_size)
+ RS_ATTR_MALLOC;
+
+/* Free program data. */
+void rs_program_free (RSProgram* prgm);
+
+/* Truncate or extend program. */
+RSStatus rs_program_set_length (RSProgram* prgm, unsigned long length);
+
+/* Add data to the end of the program. */
+RSStatus rs_program_append_data (RSProgram* prgm, const unsigned char* data,
+ unsigned long length);
+
+
+/**** Search for key file (autokey.c) ****/
+
+/* Get key ID for the given program. */
+unsigned long rs_program_get_key_id (const RSProgram* prgm) RS_ATTR_PURE;
+
+/* Find key file for the given ID. */
+RSStatus rs_key_find_for_id (RSKey* key, unsigned long keyid, int publiconly);
+
+
+/**** Program signing and validation (apps.c) ****/
+
+/* Check/fix program header and data. */
+RSStatus rs_repair_program (RSProgram* prgm, RSRepairFlags flags);
+
+/* Add a signature to the program. */
+RSStatus rs_sign_program (RSProgram* prgm, RSKey* key, int rootnum);
+
+/* Validate program signature. */
+RSStatus rs_validate_program (const RSProgram* prgm, const RSKey* key);
+
+
+/**** TI-73/83+/84+ app signing (app8x.c) ****/
+
+/* Check/fix Flash app header and data. */
+RSStatus rs_repair_ti8x_app (RSProgram* app, RSRepairFlags flags);
+
+/* Add a signature to a Flash app. */
+RSStatus rs_sign_ti8x_app (RSProgram* app, RSKey* key, int rootnum);
+
+/* Validate Flash app signature. */
+RSStatus rs_validate_ti8x_app (const RSProgram* app, const RSKey* key);
+
+
+/**** TI-73/83+/84+ OS signing (os8x.c) ****/
+
+/* Check/fix OS header and data. */
+RSStatus rs_repair_ti8x_os (RSProgram* os, RSRepairFlags flags);
+
+/* Add a signature to an OS. */
+RSStatus rs_sign_ti8x_os (RSProgram* os, RSKey* key);
+
+/* Validate OS signature. */
+RSStatus rs_validate_ti8x_os (const RSProgram* os, const RSKey* key);
+
+
+/**** TI-89/92+ app/OS signing (app9x.c) ****/
+
+/* Check/fix Flash app header and data. */
+RSStatus rs_repair_ti9x_app (RSProgram* app, RSRepairFlags flags);
+
+/* Check/fix OS header and data. */
+RSStatus rs_repair_ti9x_os (RSProgram* app, RSRepairFlags flags);
+
+/* Add a signature to a 68k app/OS. */
+RSStatus rs_sign_ti9x_app (RSProgram* app, RSKey* key);
+
+/* Validate app/OS signature. */
+RSStatus rs_validate_ti9x_app (const RSProgram* app, const RSKey* key);
+
+#define rs_sign_ti9x_os rs_sign_ti9x_app
+#define rs_validate_ti9x_os rs_validate_ti9x_app
+
+
+/**** File input (input.c) ****/
+
+/* Read program contents from a file. */
+RSStatus rs_read_program_file (RSProgram* prgm, FILE* f,
+ const char* fname, RSInputFlags flags);
+
+
+/**** File output (output.c) ****/
+
+/* Write program contents to a file. */
+RSStatus rs_write_program_file(const RSProgram* prgm, FILE* f,
+ int month, int day, int year,
+ RSOutputFlags flags);
+
+
+/**** Hex file output (output8x.c) ****/
+
+/* Write program to a .73k/.73u/.8xk/.8xu or .app file. */
+RSStatus rs_write_ti8x_file (const RSProgram* prgm, FILE* f,
+ int month, int day, int year,
+ RSOutputFlags flags);
+
+
+/**** Binary file output (output9x.c) ****/
+
+/* Write program to a .89k/.89u/.9xk/.9xu file. */
+RSStatus rs_write_ti9x_file (const RSProgram* prgm, FILE* f,
+ int month, int day, int year,
+ RSOutputFlags flags);
+
+
+/**** App header/certificate utility functions (header.c) ****/
+
+/* Get length of a header field. */
+void rs_get_field_size (const unsigned char* data,
+ unsigned long* fieldstart,
+ unsigned long* fieldsize);
+
+/* Set length of a header field. */
+int rs_set_field_size (unsigned char* data,
+ unsigned long fieldsize);
+
+/* Find a given header field in the data. */
+int rs_find_app_field (unsigned int type,
+ const unsigned char* data,
+ unsigned long length,
+ unsigned long* fieldhead,
+ unsigned long* fieldstart,
+ unsigned long* fieldsize);
+
+/* Get value of a numeric header field. */
+unsigned long rs_get_numeric_field (unsigned int type,
+ const unsigned char* data,
+ unsigned long length) RS_ATTR_PURE;
+
+
+/**** Error/message logging (error.c) ****/
+
+typedef void (*RSMessageFunc) (const RSKey*, const RSProgram*,
+ const char*, void*);
+
+/* Set program name */
+void rs_set_progname (const char* s);
+
+/* Set verbosity level */
+void rs_set_verbose (int v);
+
+/* Set error logging function */
+void rs_set_error_func (RSMessageFunc func, void* data);
+
+/* Set message logging function */
+void rs_set_message_func (RSMessageFunc func, void* data);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __RABBITSIGN_H__ */
diff --git a/tool/rabbitsign-src/rabin.c b/tool/rabbitsign-src/rabin.c
new file mode 100644
index 0000000..aaa599c
--- /dev/null
+++ b/tool/rabbitsign-src/rabin.c
@@ -0,0 +1,425 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#include "rabbitsign.h"
+#include "internal.h"
+
+/*
+ * Compute square root of x modulo p, where p === 3 (mod 4).
+ *
+ * (Assume that (x|p) = 1.)
+ *
+ * Notice that:
+ *
+ * p = 4k + 3
+ *
+ * x^[(p-1)/2] = x^(2k+1) = (x|p) = 1
+ *
+ * x^(2k+2) = x
+ *
+ * [x^(k+1)]^2 = x
+ *
+ * so x^(k+1) = x^[(p+1)/4] is a square root of x.
+ */
+static void mpz_sqrtm_3 (mpz_t res, /* mpz to store result */
+ const mpz_t x, /* number to get square root of */
+ const mpz_t p) /* prime modulus === 3 (mod 4) */
+{
+ mpz_add_ui(res, p, 1);
+ mpz_fdiv_q_2exp(res, res, 2); /* (p + 1)/4 */
+ mpz_powm(res, x, res, p);
+}
+
+
+/*
+ * Compute square root of x modulo p, where p === 5 (mod 8).
+ *
+ * (Assume that (x|p) = 1.)
+ *
+ * Notice that:
+ *
+ * p = 4k + 1
+ *
+ * x^[(p-1)/2] = x^(2k) = (x|p) = 1
+ *
+ * x^[(k+1)/2]^2 * x^(4k-1) = x^(5k) = x^k
+ *
+ * Since x^k^2 = 1, x^k = +/- 1.
+ *
+ * CASE 1:
+ * If x^k = 1, x^[(k+1)/2]^2 = x, so x^[(k+1)/2] = x^[(p+3)/8] is
+ * the square root of x.
+ *
+ * CASE 2:
+ * Otherwise, x^[(k+1)/2]^2 = -x; we need to find a square root of
+ * -1.
+ *
+ * Since (2|p) = -1, 2^[(p-1)/2] = 2^(2k) = -1, so (2^k)^2 = -1
+ *
+ * (x^[(k+1)/2] * 2^k)^2 = -x * -1 = x
+ *
+ * so x^[(k+1)/2] * 2^k = x^[(p+3)/8] * 2^[(p-1)/4] is the square
+ * root of x.
+ */
+static void mpz_sqrtm_5 (mpz_t res, /* mpz to store result */
+ const mpz_t x, /* number to get square root of */
+ const mpz_t p) /* prime modulus === 5 (mod 8) */
+{
+ mpz_t a, b;
+ mpz_init(a);
+ mpz_init(b);
+
+ mpz_add_ui(a, p, 3);
+ mpz_fdiv_q_2exp(b, a, 3);
+ mpz_powm(res, x, b, p); /* x ^ (p+3)/8 */
+
+ /* Check if res^2 = x */
+ mpz_mul(a, res, res);
+ mpz_sub(b, a, x);
+ mpz_mod(a, b, p);
+
+ if (0 != mpz_sgn(a)) {
+ mpz_sub_ui(a, p, 1);
+ mpz_fdiv_q_2exp(b, a, 2);
+ mpz_set_ui(a, 2);
+ mpz_powm(a, a, b, p); /* 2 ^ (p-1)/4 */
+ mpz_mul(res, res, a);
+ }
+
+ mpz_clear(a);
+ mpz_clear(b);
+}
+
+
+/*
+ * Compute square root of x modulo p.
+ *
+ * This still won't work with p === 1 mod 8, but then, TI's system
+ * won't work at all for 50% of apps if one of your factors is 1 mod
+ * 8. (See the discussion of f values below.)
+ *
+ */
+static void mpz_sqrtm (mpz_t res, /* mpz to store result */
+ const mpz_t x, /* number to get square root of */
+ const mpz_t p) /* prime modulus === 3, 5, or 7
+ (mod 8) */
+{
+ if ((mpz_get_ui(p) % 8) == 5)
+ mpz_sqrtm_5(res, x, p);
+ else
+ mpz_sqrtm_3(res, x, p);
+}
+
+
+/*
+ * Compute x s.t. x === r (mod p) and x === s (mod q).
+ *
+ * We compute this as:
+ *
+ * [(r-s) * q^-1 mod p] * q + s
+ *
+ */
+static void mpz_crt(mpz_t res, /* mpz to store result */
+ const mpz_t r, /* root modulo p */
+ const mpz_t s, /* root modulo q */
+ const mpz_t p, /* first modulus */
+ const mpz_t q, /* second modulus */
+ const mpz_t qinv) /* q^(p-2) mod p */
+{
+ /* ((r - s) */
+ mpz_sub(res, r, s);
+
+ /* * q^-1) */
+ mpz_mul(res, res, qinv);
+ mpz_mod(res, res, p);
+
+ /* * q + s */
+ mpz_mul(res, res, q);
+ mpz_add(res, res, s);
+}
+
+/*
+ * Compute the T_f transform modulo n.
+ *
+ * Because only one quarter of the possible hashes can be signed with
+ * a given key, we need to transform the hash. First, we want to
+ * ensure that the result is nonzero, so we shift the hash by 8 bits
+ * and add a 1 to the end. The resulting number is called m'.
+ *
+ * Second, we want to multiply it by a number k whose Legendre symbols
+ * (k|p) and (k|q) are known, so that (km'|p) = (k|p)(m'|p) = 1 and
+ * (km'|q) = (k|q)(km'|q) = 1. Since we need both to be true
+ * simultaneously, regardless of the values of (m'|p) and (m'|q), we
+ * clearly need four possible values of k.
+ *
+ * As it happens, TI's keys all follow a precise format: they all have
+ * p === 3 and q === 7 (mod 8). As a result, we know that
+ *
+ * (-1|p) = (-1|q) = -1
+ *
+ * (2|p) = -1, (2|q) = 1
+ *
+ * So TI has defined the following transformation functions:
+ *
+ * T_0(x) = -2x'
+ * T_1(x) = -x'
+ * T_2(x) = x'
+ * T_3(x) = 2x'
+ *
+ * where x' = 256x + 1.
+ *
+ * In the usual case of p === 3 and q === 7 (mod 8), then, two of the
+ * possible (T_f(m)|p) will equal 1:
+ *
+ * If (m'|p) = 1, then (T_0(m)|p) = (T_2(m)|p) = 1.
+ * If (m'|p) = -1, then (T_1(m)|p) = (T_3(m)|p) = 1.
+ *
+ * Two of the possible (T_f(m)|q) will equal 1:
+ *
+ * If (m'|q) = 1, then (T_2(m)|q) = (T_3(m)|q) = 1.
+ * If (m'|q) = -1, then (T_0(m)|q) = (T_1(m)|q) = 1.
+ *
+ * Thus we can choose exactly one f value with
+ * (T_f(m)|p) = (T_f(m)|q) = 1.
+ *
+ * If r === 5 (mod 8) is a prime, (-1|r) = 1, while (2|r) = -1. Thus
+ * a similar logic holds:
+ *
+ * If (m'|r) = 1, then (T_1(m)|r) = (T_2(m)|r) = 1.
+ * If (m'|r) = -1, then (T_0(m)|r) = (T_3(m)|r) = 1.
+ *
+ * So if {p,q} === {3,5}, {5,7}, or {3,7} (mod 8), given any m, we can
+ * pick an f with (T_f(m)|p) = (T_f(m)|q) = 1.
+ *
+ */
+static void applyf(mpz_t res, /* mpz to store result */
+ const mpz_t m, /* MD5 hash */
+ const mpz_t n, /* public key */
+ int f) /* f (0, 1, 2, 3) */
+{
+ mpz_mul_ui(res, m, 256);
+ mpz_add_ui(res, res, 1);
+
+ switch (f) {
+ case 0:
+ mpz_add(res, res, res);
+ case 1:
+ mpz_sub(res, n, res);
+ break;
+ case 2:
+ break;
+ case 3:
+ mpz_add(res, res, res);
+ break;
+ }
+}
+
+/*
+ * Compute the Rabin signature with a given f.
+ */
+static void rabsigf(mpz_t res, /* mpz to store result */
+ const mpz_t m, /* MD5 hash */
+ const mpz_t n, /* public key */
+ const mpz_t p, /* first factor */
+ const mpz_t q, /* second factor */
+ const mpz_t qinv, /* q^(p-2) mod p */
+ int f, /* f (0, 1, 2, 3) */
+ int rootnum) /* root number (0, 1, 2, 3) */
+{
+ mpz_t mm;
+ mpz_t r,s;
+
+ mpz_init(r);
+ mpz_init(s);
+ mpz_init(mm);
+
+ applyf(mm, m, n, f);
+
+ mpz_sqrtm(r, mm, p);
+ mpz_sqrtm(s, mm, q);
+
+ if (rootnum & 1) {
+ mpz_sub(r, p, r);
+ }
+
+ if (rootnum & 2) {
+ mpz_sub(s, q, s);
+ }
+
+ mpz_crt(res, r, s, p, q, qinv);
+
+ mpz_clear(r);
+ mpz_clear(s);
+ mpz_clear(mm);
+}
+
+/*
+ * Table of f values.
+ *
+ * Remember that
+ *
+ * f = 0 corresponds to multiplying by -2
+ * f = 1 corresponds to multiplying by -1
+ * f = 2 corresponds to multiplying by 1
+ * f = 3 corresponds to multiplying by 2
+ */
+static const int ftab[36] = {
+ /************* (m'|p) = (m'|q) = 1 */
+ /********** (m'|p) = -1, (m'|q) = 1 */
+ /****** (m'|p) = 1, (m'|q) = -1 */
+ /*** (m'|p) = (m'|q) = -1 */
+
+ /* p === 3, q === 3 */
+ 2, 99, 99,1, /* (-1|p) = (-1|q) = -1 ==> if both -1, multiply by -1 */
+
+ /* p === 3, q === 5 */
+ 2, 1, 0, 3, /* (-1|p) = -1, (-1|q) = 1 ==> if (m'|p) = -1, multiply by -1 */
+ /* (-2|p) = 1, (-2|q) = -1 ==> if (m'|q) = -1, multiply by -2 */
+
+ /* p === 3, q === 7 */
+ 2, 3, 0, 1, /* (2|p) = -1, (2|q) = 1 ==> if (m'|p) = -1, multiply by 2 */
+ /* (-2|p) = 1, (-2|q) = -1 ==> if (m'|q) = -1, multiply by -2 */
+
+ /* p === 5, q === 3 */
+ 2, 0, 1, 3,
+
+ /* p === 5, q === 5 */
+ 2, 99, 99,3, /* (2|p) = (2|q) = -1 ==> if both -1, multiply by 2 */
+
+ /* p === 5, q === 7 */
+ 2, 3, 1, 0, /* (2|p) = -1, (2|q) = 1 ==> if (m'|p) = -1, multiply by 2 */
+ /* (-1|p) = 1, (-1|q) = -1 ==> if (m'|q) = -1, multiply by -1 */
+
+ /* p === 7, q === 3 */
+ 2, 0, 3, 1,
+
+ /* p === 7, q === 5 */
+ 2, 1, 3, 0,
+
+ /* p === 7, q === 7 */
+ 2, 99, 99,1 /* (-1|p) = (-1|q) = -1 ==> if both -1, multiply by -1 */
+};
+
+/*
+ * Compute the Rabin signature and the useful value of f.
+ */
+int rs_sign_rabin(mpz_t res, /* mpz to store signature */
+ int* f, /* f value chosen */
+ const mpz_t hash, /* MD5 hash of app */
+ int rootnum, /* root number (0, 1, 2, 3) */
+ RSKey* key) /* key structure */
+{
+ mpz_t mm;
+ int mLp, mLq;
+ int pm8, qm8;
+
+ if (!mpz_sgn(key->n)) {
+ rs_error(key, NULL, "unable to sign: public key missing");
+ return RS_ERR_MISSING_PUBLIC_KEY;
+ }
+
+ if (!mpz_sgn(key->p) || !mpz_sgn(key->q)) {
+ rs_error(key, NULL, "unable to sign: private key missing");
+ return RS_ERR_MISSING_PRIVATE_KEY;
+ }
+
+ mpz_init(mm);
+
+ /* Calculate q^-1 if necessary */
+
+ if (!mpz_sgn(key->qinv)) {
+#ifndef USE_MPZ_GCDEXT
+ mpz_sub_ui(mm, key->p, 2);
+ mpz_powm(key->qinv, key->q, mm, key->p);
+#else
+ mpz_gcdext(mm, key->qinv, NULL, key->q, key->p);
+ if (mpz_cmp_ui(mm, 1)) {
+ mpz_clear(mm);
+ rs_error(key, NULL, "unable to sign: unsuitable key");
+ return RS_ERR_UNSUITABLE_RABIN_KEY;
+ }
+#endif
+ }
+
+ applyf(mm, hash, key->n, 2);
+
+ mLp = mpz_legendre(mm, key->p);
+ mLq = mpz_legendre(mm, key->q);
+
+ pm8 = mpz_get_ui(key->p) % 8;
+ qm8 = mpz_get_ui(key->q) % 8;
+
+ if (pm8 == 1 || qm8 == 1 || (pm8 % 2) == 0 || (qm8 % 2) == 0) {
+ mpz_clear(mm);
+ rs_error(key, NULL, "unable to sign: unsuitable key");
+ return RS_ERR_UNSUITABLE_RABIN_KEY;
+ }
+
+ *f = ftab[(mLp == 1 ? 0 : 1) +
+ (mLq == 1 ? 0 : 2) +
+ (((qm8 - 3) / 2) * 4) +
+ (((pm8 - 3) / 2) * 12)];
+
+ if (*f == 99) {
+ mpz_clear(mm);
+ rs_error(key, NULL, "unable to sign: unsuitable key");
+ return RS_ERR_UNSUITABLE_RABIN_KEY;
+ }
+
+ rabsigf(res, hash, key->n, key->p, key->q, key->qinv, *f, rootnum);
+ mpz_clear(mm);
+ return RS_SUCCESS;
+}
+
+/* Check that the given Rabin signature is valid. */
+int rs_validate_rabin (const mpz_t sig, /* purported signature of app */
+ int f, /* f value */
+ const mpz_t hash, /* MD5 hash of app */
+ const RSKey* key) /* key structure */
+{
+ mpz_t a, b;
+ int result;
+
+ if (!mpz_sgn(key->n)) {
+ rs_error(key, NULL, "unable to validate: public key missing");
+ return RS_ERR_MISSING_PUBLIC_KEY;
+ }
+
+ if (f < 0 || f > 3)
+ return RS_SIGNATURE_INCORRECT;
+
+ mpz_init(a);
+ mpz_init(b);
+
+ mpz_mul(a, sig, sig);
+ mpz_mod(a, a, key->n);
+
+ applyf(b, hash, key->n, f);
+
+ result = mpz_cmp(a, b);
+
+ mpz_clear(a);
+ mpz_clear(b);
+ return (result ? RS_SIGNATURE_INCORRECT : RS_SUCCESS);
+}
diff --git a/tool/rabbitsign-src/rsa.c b/tool/rabbitsign-src/rsa.c
new file mode 100644
index 0000000..05139a9
--- /dev/null
+++ b/tool/rabbitsign-src/rsa.c
@@ -0,0 +1,137 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#include "rabbitsign.h"
+#include "internal.h"
+
+#define VALIDATION_EXPONENT 17
+
+/*
+ * Calculate the RSA signing exponent.
+ *
+ * The validation exponent, e, is 17 for all TI-related RSA
+ * signatures. The signing exponent, d, depends on n, and is
+ * calculated so that e * d === 1 (mod (p-1)(q-1)).
+ *
+ * (This means that for any number x,
+ *
+ * x^(e * d) = x * x^[k0 * (p-1)] === x * 1 (mod p),
+ *
+ * and likewise
+ *
+ * x^(e * d) = x * x^[k1 * (q-1)] === x * 1 (mod q).
+ *
+ * Therefore (Chinese remainder theorem) x^(e * d) === x (mod n).
+ *
+ * Note that there is no way of calculating d without knowing the
+ * factors of n; this is a key point in the security of RSA.)
+ */
+static int get_exponent(mpz_t res, /* mpz to store result */
+ int e, /* validation exponent */
+ const mpz_t p, /* first factor */
+ const mpz_t q) /* second fatctor */
+{
+ mpz_t a, b;
+ mpz_init(a);
+ mpz_init(b);
+
+ mpz_sub_ui(a, p, 1);
+ mpz_sub_ui(b, q, 1);
+ mpz_mul(a, a, b);
+
+ mpz_set_ui(b, e);
+
+ mpz_gcdext(b, res, NULL, b, a);
+ if (mpz_cmp_ui(b, 1)) {
+ mpz_clear(a);
+ mpz_clear(b);
+ return RS_ERR_UNSUITABLE_RSA_KEY;
+ }
+
+ mpz_mod(res, res, a);
+
+ mpz_clear(a);
+ mpz_clear(b);
+ return RS_SUCCESS;
+}
+
+/*
+ * Compute an RSA signature.
+ *
+ * This is simply the hash raised to the d-th power mod n (where d is
+ * defined above.)
+ */
+int rs_sign_rsa(mpz_t res, /* mpz to store signature */
+ const mpz_t hash, /* MD5 hash of app */
+ RSKey* key) /* key structure */
+{
+ if (!mpz_sgn(key->n)) {
+ rs_error(key, NULL, "unable to sign: public key missing");
+ return RS_ERR_MISSING_PUBLIC_KEY;
+ }
+
+ if (!mpz_sgn(key->d)) {
+ if (!mpz_sgn(key->p) || !mpz_sgn(key->q)) {
+ rs_error(key, NULL, "unable to sign: private key missing");
+ return RS_ERR_MISSING_PRIVATE_KEY;
+ }
+ if (get_exponent(key->d, VALIDATION_EXPONENT, key->p, key->q)) {
+ rs_error(key, NULL, "unable to sign: unsuitable key");
+ return RS_ERR_UNSUITABLE_RSA_KEY;
+ }
+ }
+
+ mpz_powm(res, hash, key->d, key->n);
+ return RS_SUCCESS;
+}
+
+/*
+ * Check that the given RSA signature is valid.
+ *
+ * To do this, we raise the signature to the 17th power mod n, and see
+ * if it matches the hash.
+ */
+int rs_validate_rsa(const mpz_t sig, /* purported signature of app */
+ const mpz_t hash, /* MD5 hash of app */
+ const RSKey* key) /* key structure */
+{
+ mpz_t e, m;
+ int result;
+
+ if (!mpz_sgn(key->n)) {
+ rs_error(key, NULL, "unable to validate: public key missing");
+ return RS_ERR_MISSING_PUBLIC_KEY;
+ }
+
+ mpz_init(e);
+ mpz_init(m);
+
+ mpz_set_ui(e, VALIDATION_EXPONENT);
+ mpz_powm(m, sig, e, key->n);
+ result = mpz_cmp(hash, m);
+
+ mpz_clear(e);
+ mpz_clear(m);
+ return (result ? RS_SIGNATURE_INCORRECT : RS_SUCCESS);
+}
diff --git a/tool/rabbitsign-src/typestr.c b/tool/rabbitsign-src/typestr.c
new file mode 100644
index 0000000..00bfb92
--- /dev/null
+++ b/tool/rabbitsign-src/typestr.c
@@ -0,0 +1,161 @@
+/*
+ * RabbitSign - Tools for signing TI graphing calculator software
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+
+#ifdef HAVE_STRING_H
+# include
+#else
+# ifdef HAVE_STRINGS_H
+# include
+# endif
+#endif
+
+#include "rabbitsign.h"
+#include "internal.h"
+
+/*
+ * Get default file suffix for a given calc/data type.
+ */
+const char* rs_type_to_suffix(RSCalcType calctype, /* calculator type */
+ RSDataType datatype, /* program data type */
+ int hexonly) /* 1 = plain hex output */
+{
+ if (calctype == RS_CALC_TI73) {
+ if (datatype == RS_DATA_APP)
+ return (hexonly ? "app" : "73k");
+ else if (datatype == RS_DATA_OS)
+ return (hexonly ? "hex" : "73u");
+ else if (datatype == RS_DATA_CERT)
+ return "73q";
+ }
+ else if (calctype == RS_CALC_TI83P) {
+ if (datatype == RS_DATA_APP)
+ return (hexonly ? "app" : "8xk");
+ else if (datatype == RS_DATA_OS)
+ return (hexonly ? "hex" : "8xu");
+ else if (datatype == RS_DATA_CERT)
+ return "8xq";
+ }
+ else if (calctype == RS_CALC_TI89) {
+ if (datatype == RS_DATA_APP)
+ return "89k";
+ else if (datatype == RS_DATA_OS)
+ return "89u";
+ else if (datatype == RS_DATA_CERT)
+ return "89q";
+ }
+ else if (calctype == RS_CALC_TI92P) {
+ if (datatype == RS_DATA_APP)
+ return "9xk";
+ else if (datatype == RS_DATA_OS)
+ return "9xu";
+ else if (datatype == RS_DATA_CERT)
+ return "9xq";
+ }
+
+ return "sig";
+}
+
+/*
+ * Get implied calc/data type for a given file suffix.
+ */
+int rs_suffix_to_type(const char* suff, /* file suffix (not
+ including .) */
+ RSCalcType* calctype, /* implied calculator
+ type */
+ RSDataType* datatype) /* implied program type */
+{
+ int calc, data;
+
+ if (strlen(suff) != 3)
+ return -1;
+
+ if (suff[0] == '7' && suff[1] == '3')
+ calc = RS_CALC_TI73;
+ else if (suff[0] == '8' && (suff[1] == 'x' || suff[1] == 'X'))
+ calc = RS_CALC_TI83P;
+ else if (suff[0] == '8' && suff[1] == '9')
+ calc = RS_CALC_TI89;
+ else if (suff[0] == '9' && (suff[1] == 'x' || suff[1] == 'X'))
+ calc = RS_CALC_TI92P;
+ else if ((suff[0] == 'v' || suff[0] == 'V') && suff[1] == '2')
+ calc = RS_CALC_TI92P;
+ else
+ return -1;
+
+ if (suff[2] == 'k' || suff[2] == 'K')
+ data = RS_DATA_APP;
+ else if (suff[2] == 'u' || suff[2] == 'U')
+ data = RS_DATA_OS;
+ else if (suff[2] == 'q' || suff[2] == 'Q')
+ data = RS_DATA_CERT;
+ else
+ return -1;
+
+ if (calctype) *calctype = calc;
+ if (datatype) *datatype = data;
+ return 0;
+}
+
+/*
+ * Get a human-readable description of a calculator type.
+ */
+const char* rs_calc_type_to_string(RSCalcType calctype)
+{
+ switch (calctype) {
+ case RS_CALC_TI73:
+ return "TI-73";
+
+ case RS_CALC_TI83P:
+ return "TI-83/84 Plus";
+
+ case RS_CALC_TI89:
+ return "TI-89";
+
+ case RS_CALC_TI92P:
+ return "TI-92 Plus/Voyage 200";
+
+ default:
+ return "unknown";
+ }
+}
+
+/*
+ * Get a human-readable description of a data type.
+ */
+const char* rs_data_type_to_string(RSDataType datatype)
+{
+ switch (datatype) {
+ case RS_DATA_OS:
+ return "OS";
+
+ case RS_DATA_APP:
+ return "application";
+
+ case RS_DATA_CERT:
+ return "certificate";
+
+ default:
+ return "program";
+ }
+}
diff --git a/tool/tilem-src/CHANGELOG b/tool/tilem-src/CHANGELOG
new file mode 100644
index 0000000..78a8f7f
--- /dev/null
+++ b/tool/tilem-src/CHANGELOG
@@ -0,0 +1,316 @@
+/* This file only contains the changelog for the gui/doc/data, some things could be missing (core changes...)*/
+/* This changelog was started when I started to work on TilEm2 */
+
+/* contra-sh :
+* ---18/08/09---
+* - Draw the TI83
+* - Copy from testemu.c : Create the savname, Open the Rom, Get the model, Draw the lcdscreen (no animation for the moment)
+* - Function event OnDestroy
+* - Modification of the Makefile (I hope it's good !? If you can control this... thx)
+* - LEARNING HOW COMMIT !! :D
+* ---19/08/09---
+* - New structure TilemCalcSkin : define the different filenames for the SkinSet (4 pieces).
+* - Draw the other models _automatically_ . ;D
+* ---20/08/09---
+* - Create skin.c
+* - Create gui.h (equivalent of tilem.h for the gui directory)
+* - Move the code struct in gui.h and TilemCalcSkin* tilem_guess_skin_set(TilemCalc* calc) into skin.c (only one call in the main file to define the skin set) ;D
+* - Detect a keyboard event (function keyboard_event() in skin.c actually).No treatment.
+* - Detect an event click on mouse
+* ---21/08/09---
+* - Get the x and y values when click on mouse (now it will be easy to know how key is click on the pixmap, todo in priority : detect right click)
+* ---24/08/09---
+* - Detect right click.
+* ---26/08/09---
+* - New function : TilemKeyMap* tilem_guess_key_map(int id).Choose a TilemKeyMap with an id given in parameter.
+* ---27/08/09---
+* - Extract the choice of the key_map from the mouse_event function.Execute only one time and it's more properly (and it will be easier to add the possibility to manage many skins and many keymaps).
+* ---01/09/09---
+* - Choose automatically the key_list. The TilemKeyList is already included in the TilemKeyMap structure...
+* - New structure TilemKeyCoord (old TilemKeyMap).TilemKeyMap already contains TilemKeyCoord and TilemKeyList...
+* ---08/09/09---
+* - New function tilem_set_coord to change the keypad coord.
+* - New file event.c to group the GDKevent handling.
+* - New function tilem_set_skin to change the skin.
+* ---10/09/09---
+* - Add the right click menu :D (0 signal connected without OnDestroy).Largely inspired from Tilem 0.973 and http://www.linux-france.org/article/devl/gtk/gtk_tut-11.html was a great inspiration too.
+* ---21/09/09---
+* - Aouch I had seen that the left click doesn't work now! Problem : two callback for the only one button_press_event. (sorry for this version...)
+* ---22/09/09---
+* - Correction : only one callback now. mouse_event contains the create_menu and the gtk_menu_popup. (lot of time was spent on this problem)*
+* ---23/09/09---
+* - Change TilemKeyCoord to the 82 stats skin.Change Event.c too.
+* ---06/10/09---
+* - Beginning the correction : change the method for testing coordinates clicks (one line now) . The coordinates will be imported from a file soon.
+* ---20/11/09---
+* - After 1 week to learn Tiemu skin format...I have made my own Tilem skin Generator.Inspired from skinedit.It just generate compatible file with 0 coordinates values, and an default lcd coordinates.Not really necessary but very useful for testing and for learning how this f****** skin format works.It will be called skintool for the moment.
+* ---27/11/09---
+* - After blocking a problem for a week grrr... I succeed to adapt the TiEmu skinloader to TilEm (skinops.c and skinops.h).Little modifications
+* ---28/11/09---
+* - The mouse_event function now use a SKIN_INFOS struct. So delete TilemKeyCoord struct.
+* ---02/12/09---
+* - Add a GtkFileSelection (access by right click menu) and try to load another skin with this method.
+* ---03/12/09---
+* - Create a GLOBAL_SKIN_INFOS that contains a KEY_LIST struct (old TilemKeyList) and a SKIN_INFOS struct.
+* ---04/12/09---
+* - Delete the TilemKeyCoord, TilemKeyMap, TilemCalcSkin and TilemKeyList structs...
+* ---05/12/09---
+* - The GtkWidget *pWindow creation was moved from testemu2.c to event.c .The function is called GtkWidget* Draw_Screen(GLOBAL_SKIN_INFOS *gsi);
+* ---07/12/09---
+* - New feature : TilEm could load a skin by the right_click_menu ! It use GtkWidget* ReDraw_Screen(GLOBAL_SKIN_INFOS *gsi) in event.c. WAOUH !
+* ---08/12/09---
+* - Move Draw_Screen, ReDraw_Screen and create_menus in a new screen.c file. Change Makefile.
+* ---14/12/09---
+* - New feature : add a popup rom type selector (radio button) at the start of tilem. Showed but not used for the moment.
+* - Connect the thread (no animation yet). Thanks to the "battle programming" 's spirit (hey bob ^^)
+* ---18/12/09---
+* - Launch the interactivity with emulation core. Could print into the draw area.
+* ---09/03/10---
+* - Restart working on this program ;D
+* ---11/03/10---
+* - I finally succeeded to connect the core. To print something into the lcd screen ! WahoOO ! This day is a great day !
+* - I succeded to type numbers etc...
+* - And now it works very well !! (the "button-release-event" is not catched by pWindow but by pLayout)
+* ---15/03/10---
+* - Create the scan_click function.Return wich keys was clicked.Print debug infos.
+* - Create the debuginfos.h to group the ifdef for debugging. (different level and different type of debug msg)
+* ---17/03/10---
+* - Create the rom_choose_popup function to replace choose_rom_type.It use GtkDialog instead of GtkWindow.
+* - rom_choose_popup _freeze_ the system... and get wich radio button is selected. So it will be easy to create the good emu.calc (and choose the default skin).
+* ---18/03/10---
+* - Resize the (printed) lcd area (gsi->emu->lcdwin) to fit(perfectly) into the skin.
+* - Replace a lot of printf by D****_L*_A* to easily switch what debug infos were printed.
+* - Try to make a nice debugging output (frames in ASCII ^^) :p
+* - WahooOO , load a skin works perfectly.You can easily change skin _while running_, no error, no warning.
+* - Could load automatically the good skin and run the good core using the choose_rom_popup() function and choose_skin_filename() function.
+* ---30/03/10---
+* - Create skin for following models : 73, 81, 82, 83+ and 84+.
+* - Fix bug in tool.c .Modification of tool.c to create radio button more properly.
+* ---31/03/10---
+* - Create skin for following model : 83 . Based on my own calc (take a foto with my iphone 3GS :D)
+* ---01/04/10---
+* - New feature : Save calc state and load state. State are stored in a separate dir called sav/ . (using benjamin 's function)
+* - New feature : Change view to see only the lcd. I finally choose to add it into a GtkLayout. So you can maximize it, but there was problem with add_event.
+* ---02/04/10---
+* - Add popup function to just print error message.You must give the message and gsi as parameter, and it run a modal dialog.
+* - Some cleaning.
+* ---23/04/10---
+* - Add config.c file to manage config.dat (create, read, modif etc...).
+* ---31/05/10---
+* - Start from scratch a totally new debugger :D.Just draw button with nice GtkImages.Actually in essai2 directory.
+* - Get and resize pixmaps (png) to 36 * 36 pixels for the debugger.
+* ---01/06/10---
+* - Add the debugger to tilem. Load registers values.
+* - Add a new feature : switch the top level window "borderless".It can be switch by clicking on right click menu entry.
+* ---02/06/10---
+* - Create the GtkTreeView (debugger).
+* - Refresh register on click.
+* ---05/08/10---
+* - More than one month without working on tilem...Only commit old modif, and skn/README file.
+* - Refresh stack on click (number of entry is correct but value not)
+* ---06/08/10---
+* - Working on a new system of configuration file.The config.dat is now a binary file (as .skn but totally differennt). At start, a CONFIG_INFOS struct is filling, then when clicking on right menu, this struct is modified, then when you stop tilem, config.dat is writed on disc.
+* ---09/08/10---
+* - Correction of the SEG_FAULT (never use sizeof(char*) inside malloc, strlen(char*) is better :P).
+* ---10/08/10---
+* - Working on a new config file called romconfig.dat (inspired from config.dat) using to do not ask for model each time tilem is started.
+* - It works :D
+* ---12/08/10---
+* - NEW feature : Can load a file using libticalcs2 (inspired from the wokr of Benjamin Moody). Basically it works, but it's not OK. (many bugs)
+* - Drop the deprecated GtkFileSelection.Use GtkFileChooser instead. :)
+* ---13/08/10---
+* - NEW feature : Add the screenshot feature.
+* ---17/08/10---
+* - Change the ti84plus.skn (old was really ugly).
+* - Add doc/ directory : add romconfig_file_format.txt and skinconfig_file_format.txt.
+* ---18/08/10---
+* - Correct the bug in link.c (unlock mutex ...)
+* - Start working on macro handling : Always do the same things to load and launch a file into an emulator become quickly noisy for the programmer (1 time, 10 times, 30 times, 50 times...argh!). Simply record a sequence and play it to test a program, this is one solution. (feature request from Guillaume Hoffman gh@gmail.com).
+* ---19/08/10---
+* - The macro feature works including loading file (very important). The implementation is very basic (record and read a text file) so many bug could (should?) appear. But I wait to see how it will be use.
+* ---20/08/10--
+* - Better implementation of GtkFileChooser (to be cleaner).
+* - Some work on macro (no seg fault now ^^).
+* - Add a Save state... entry in right click menu (no need to stop tilem to save state)
+* - Add a Play macro with GtkFileChooser (to play another macro than play.txt).
+* - Fix minor bug in GtkFileChooser (forget to init a char* to NULL).
+* ---23/08/10---
+* - Add a new args handler using getop library (add -m for macro and -k for skin).
+* ---06/09/10---
+* - NEW feature : could print the lcd content into the terminal. So useless but so funny ;) (feature request from Guillaume Hoffman).
+* - The output is saved into a file called lcd_content.txt.
+* ---08/09/10---
+* - Could choose wich char to display. This not really works as I want, but this is not a really important feature (works 1/2)
+* - Add an option at startup (-l). Could now start in skinless mode.
+* ---04/10/10---
+* - Start working on animated gif. Some research on GIF file format. Oops it will be hard, file is encoded (!).
+* ---09/10/10---
+* - Creation of 1 little static gif file seems working, but always no LZW encoding.
+* ---12/10/10---
+* - Finally I decided to use external source to encode the pix data.I use a file called "gifencode.c" by Hans Dinsen-Hansen and Michael A. Mayer. And it works !!!
+* ---14/10/10---
+* - It works ! It works !!! Tilem2 is now able to generate animated gif, functions are currently working (but totally buggy) and it successfully create animated gif :)
+* - Need to be integrated (and lot of debug).I commit it just to save it...Wait another commit to really use this feature :P
+* ---01/02/11---
+* - Starting to work on a new config file using glibc to do not hard code keypad values.
+* - And it works !!!! (but only load one keypad model currently)
+* - Add the other models into keylist.ini (but the content is completely false). Change scan_click method (correct a bug) to use kp->nb_of_buttons. Only need to give correct value into the keylist.ini file. For the rest it's seems ok.
+* ---07/02/11---
+* - Start to work on config.ini. A new generation config file using GKeyFile library (glib). Add some work in essai4 directory.
+* ---08/02/11---
+* - Remove romconfig.c romconfig.h config.c config.h (handle binary config file). Remove ROM_CONFIG_INFOS and CONFIG_INFOS from gsi.
+* - Add a new config.c and config.h file to handle config (last rom used, default skin to load, etc...). It uses glib GKeyFile library.
+* - Fix the macro bug pointed by Benjamin.
+* ---15/02/11---
+* - Replace correct copyright/licence informations into skinops.* .Sorry for the inconvenience.
+* ---16/02/11---
+* - Fix an important mistake into the gif creator function (palette should be before gif frame information).
+* ---18/02/11---
+* - Connect a timer to automatically add frame to a animated screenshot (using screenshot box).
+* ---14/03/11---
+* - Improve default skin choice.
+* - Define the skin's basedir into the config.ini. Add a universal getter into config.c .
+* ---19/03/11---
+* - Add a bouncy progress bar to show the link status (send file).
+* - Add a file saver.
+* - Create a new TilemCmdlineArgs structure.
+* ---07/04/11---
+* - Drop deprecated gtkitemfactory
+* - Prepare GT3 migration
+* ---10/04/11---
+* - Benjamin add a configure script and all associated things (Makefile.in, config.h etc...).
+* - Fix dependency and a lot of cleaning.
+* - Benjamin add a lot of function to handle data directory.
+* ---13/04/11---
+* - Completely refactoring the screenshot window. New preview possibility.
+* - Add some cool features for screenshot menu (replay from file, preview animation, preview screenshot, 2 gtkfilechooserbutton, change default folders etc...).
+* - Remove old pix directory.
+* - Benjamin begins to work on new debugger.Add a menu, some basic actions.
+* ---15/04/11---
+* - Benjamin add a set of function to handle user defined icons. A lot of improvement on the debugger (add step action, pause).
+* - Use tilem logo as default background in the screenshot menu, add some pix into the shared data directory.
+* - Remove old debugger pix.
+* - Add GtkSpinnerAnimation in the screenshot menu. Improve look and feel (fix fill/expand properties for the box, size of the widgets etc...).
+* ---17/04/11---
+* - Benjamin add a ti83p symbol file which allow to replace flag values by theirs labels in the debugger (and more other things). Debugger looks like very good.
+* ---19/04/11---
+* - I've added a ti83 symbol file (but it could contains some mistakes...). Flags are correctly printed for my loved ti83 regular ;)
+* ---27/04/11---
+* - Root window size could be forced (but the ratio could be strand if you specify stanges values ... Because ration is calculated on the start width and heigth).
+* ---02/05/11---
+* - Add the icons for the right click menu (stock icons currently).
+* - Export all menu related code in a separate file called menu.c. It could maybe be done by UI in the future, but it works fine as it for the moment ;)
+* - Add drag and drop support for loading files :) :) :) :) :) (code is currently really ugly)
+* ---09/05/11---
+* - Create a new TilemGuiStateFlags structure ot group the running state of the gui (skinless, recording macro, etc...) and export it into TilemCalcEmu instead GLOBAL_SKIN_INFOS.
+* - Completely remove GLOBAL_SKIN_INFOS structure from tilem2.
+* ---10/05/11---
+* - Change strutures to look like a object oriented model. But in some case it's not really well implemented.
+* ---11/05/11---
+* - Refactor a lot of gif header's code.
+* ---12/05/11---
+* - I finally found what's wrong in my gif creation. So I can do multicolor gif now.
+* ---14/05/11---
+* - We have finally completely reorganized the code to drop GLOBAL_SKIN_INFOS, and rename a lot of stuff including files (emuwin instead screen by example).
+* - Benjamin have imported his nice filedlg functions (filedlg.c) from flashbook ui (see it on SF.net). Now use it for the entire code.
+* ---14/05/11---
+* - Refactor the gif creation to separate clearly which value can be modified, which one are magic number etc... Create separate functions for each task.
+* - Benjamin begins to work on animation (instead of writing file while recording it). It provides a wonderful objects to handle screenshot.
+* ---15/05/11---
+* - Add a doxyfile for generating documentation including callgraphs.
+* - Improvement to keybindings (Benjamin).
+* ---16/05/11---
+* - Add some preliminary work on get var stuff. Only dirlist and allow user to retrieve a var using cmd line but it works. The list is printed in a tree view.
+* - Add multi drag and drop feature.
+* ---19/05/11---
+* - Add functions for animations (Benjamin). Could now save a animation into a gif file.
+* - Improve screenshot menu by setting some buttons inactives depending the current state of screenshot creation.
+* - Add combo box for size to screenshot menu.
+* ---21/05/11---
+* - A lot of improvement on screenshot menu (Benjamin). Settings are now independent of screenshot dialog. Default directory for output.
+* - Add mnemonic label to screenshot menu buttons (Benjamin).
+* ---22/05/11---
+* - Benjamin redesign the entire menu popup to use the better GtkAction system. Now there's keybindings for menu and code is really beautiful and shorter.
+* - Add grayscale option to screenshot menu (Benjamin).
+* ---23/05/11---
+* - Save the last rom opened and use it at startup if no rom is given.
+* - Allow user to load another rom while running.
+* - Refactor the entire macro creation to separate creation from writing as TilemAnimation does. Code is cleaner and simply better.
+* ---25/05/11---
+* - Add an option to change animation speed. The current printed animation is updated on change.
+* ---26/05/11---
+* - Add an option to change foreground and background color. No visual feedback.
+* ---27/05/11---
+* - Correct some stuff (see mailing list to know why). And add a palette setter in animation.c and a visual feedback when foreground/background color are changed.
+* - Some other minor improvement.
+* ---19/09/11---
+* - Restart working on tilem2 after holidays:)
+* - Add new file getvar.c to handle get var function (receiving var from calc to PC).
+* ---20/09/11---
+* - Some improvement to the rcvmenu.
+* ---22/09/11---
+* - Add the ti83pfr.skn file. This skin is for ti83plus.fr. The creator is Claude Clerc (aka claudiux). He donates the skin under GPL v3+ licence.Thanks to him !!!
+* ---11/10/11---
+* - Correct the getvar.c code to work correctly. Add columns to the tree view.
+* - Add app receive handling. Set index column invisible.
+* ---12/10/11---
+* - Some corrections : receive dialog is transcient. Receive dialog is not destroyed when closed just hided. New refresh button to refresh var/app list.
+* - Use a separate thread to receive files.
+* ---14/10/11---
+* - Add a feature to list ti82 and ti85 entries. User must prepare manually the link. Can't save a ti82 or ti85 entry (when selected in the rcvdialog).
+* - Lot of bug, code is really ugly. No error handling. The prepare_for_link_receive is not working. etc...
+* ---11/11/11---
+* - Benjamin add a totally new prefs dialog. Some unused function (print lcd in terminal by example) are deleted.
+* ---12/11/11---
+* - Working on ns silent get var.
+* ---14/11/11---
+* - New files : emucore.c and emucore.h .
+* - Benjamin adds a totally new core task manager in the gui. Begin to convert the send files function to use it.
+* - Use this task manager for macro. There's a little priority problem when a macro load a file. Load a file then run a macro at startup works fine.
+* ---15/11/11---
+* - Receive non silent vars : Benjamin get it working!
+* - Remove unused getvar.c file.
+* ---16/11/11---
+* - Allow multiple selection and multiple receive file. Need to fix a segfault (tomorow... xD).
+* ---17/11/11---
+* - Repare the file loading inside a macro (it was broken by new task manager).
+* - Delete a lot of unused functions/printf.
+* - Remove debuginfo.h file.
+* ---22/11/11---
+* - Benjamin finished the last things left to do on receive dialog. Nice!
+* ---25/11/11---
+* - New command line parser. Now tilem2 uses g_option from the glib instead of getopt. Easy handling of long options. Do not need to take care about correct parsing. A lot of new options are provided but not implemented !
+* - Delete args.c (old _but working well _ cmd line parser using getopt) and TilemCmdlineArgs structure from gui.h.
+* - Add the possibility to getvar a file at startup. I had to use a weird solution to do this with task manager. But it's working :)
+* ---12/12/11---
+* - Benjamin do a lot of improvements on file chooser (filters, ...).
+* ---22/12/11---
+* - Benjamin fix certificate patching.
+* ---19/03/12---
+* - Icons are finally commited into the trunk. These pictures are originaly designed by Scott Zeid and modified by me. No .desktop and icons installer for the moment.
+* - Scott, thank you a lot for these wonderful pictures!
+* ---21/03/12---
+* - Adding documentation (LaTeX). The documentation is not finished yet. Lot of pictures added.
+* ---24/04/12---
+* - Benjamin added some correction to install properly the icons.
+* ---27/04/12---
+* - Some modifications on the configure script because something was failing on my debian wheezy. It works fine yet (using squeeze and gtk/glib downgraded packages and some minor modifications on configure scripts).
+* ---03/05/12---
+* - Reverting changes on the configure script because it was not the fault of configure script.
+* ---07/05/12---
+* - Update doc (add "basic task" chapter).
+* - Update .desktop files.
+* ---08/05/12---
+* - Benjamin added a rule to install in the $HOME directory.
+* - Benjamin added MIME type files.
+* ---09/05/12---
+* - Benjamin added a piece of documentation about "getting ROM".
+* ---11/05/12---
+* - Add an huge explanation for debugger part into the documentation.
+* ---13/05/12---
+* - Add some screenshot documentation.
+* ---15/05/12---
+* - Benjamin add README, THANKS and COPYING file.
+* - Update screenshot doc.
+*/
+
diff --git a/tool/tilem-src/COPYING b/tool/tilem-src/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/tool/tilem-src/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/tool/tilem-src/INSTALL b/tool/tilem-src/INSTALL
new file mode 100644
index 0000000..84008d7
--- /dev/null
+++ b/tool/tilem-src/INSTALL
@@ -0,0 +1,53 @@
+ Installing TilEm
+ ------------------
+
+To compile TilEm, you will need:
+
+ * a standard C compiler
+
+ * the GTK+ library, version 2.6.0 or later
+
+ * the libticalcs2 library (part of the TiLP project), and its
+ dependencies (libticables2, libtifiles2, and libticonv)
+
+Some OS distributions package the "development files" separately from
+the libraries themselves; you need both. If you are using Debian (or
+a related distribution, such as Ubuntu or Mint), install the packages
+'build-essential', 'libticalcs-dev', and 'libgtk2.0-dev'.
+
+If these packages aren't available from your package manager, you'll
+need to compile them yourself; see the TiLP website for more
+information (http://lpg.ticalc.org/prj_tilp/).
+
+Mac OS X has not been tested by the TilEm team, but if TiLP works,
+TilEm should, too. Please let us know if you do get it to work.
+
+Once the above dependencies are installed, open a terminal and 'cd' to
+the directory containing this INSTALL file. Then run
+
+ ./configure
+
+which will check whether you have all of the necessary software
+installed, and figure out how to compile TilEm for your particular
+system. If configure is successful, you can then run
+
+ make
+
+to compile TilEm. Finally, you can run
+
+ sudo make install
+
+to install it (or run 'make install' as the superuser.) The program
+will be installed in '/usr/local/bin/', and data files will be
+installed in '/usr/local/share/tilem2/'. Alternatively, you can run
+
+ make install-home
+
+to install TilEm in your own home directory ('$HOME/bin/', with data
+files stored in '$HOME/.local/share/tilem2/'), which does not require
+superuser privileges. (If $HOME/bin didn't exist already, you might
+have to run 'export PATH=$HOME/bin:$PATH', or log out and log back in,
+before running TilEm.)
+
+Once TilEm is installed, start it by running 'tilem2', or through your
+system's applications menu.
diff --git a/tool/tilem-src/KEYS b/tool/tilem-src/KEYS
new file mode 100644
index 0000000..d547d84
--- /dev/null
+++ b/tool/tilem-src/KEYS
@@ -0,0 +1,270 @@
+KEYBOARD BINDINGS
+
+ This list shows the default keyboard controls for TilEm. You can
+ modify these, if you like, by editing 'keybindings.ini'. (Place the
+ modified version of keybindings.ini in your TilEm configuration
+ directory - $HOME/.config/tilem2/ on Unix, or
+ $PROFILE\Local Settings\Application Data\tilem2 on Windows.)
+
+ In the following list:
+ S = Shift
+ C = Control
+ ↑ = 2nd
+ α = Alpha
+
+ ² in the TI-82/83 column indicates that the key is only for the TI-82.
+ ³ indicates that it is only for the TI-83/TI-83 Plus/TI-84 Plus.
+
+ Key TI-73 TI-76.fr TI-81 TI-82/83 TI-85/86
+ ──────────────────────────────────────────────────────────────────────────────
+ F12 ON ON ON ON ON
+ S+F12 ↑ [OFF] ↑ [OFF] ↑ [OFF] ↑ [OFF] ↑ [OFF]
+
+ Up Up Up Up Up Up
+ Down Down Down Down Down Down
+ Left Left Left Left Left Left
+ Right Right Right Right Right Right
+ S+Up ↑ Up ↑ Up ↑ Up ↑ Up ↑ Up
+ S+Down ↑ Down ↑ Down ↑ Down ↑ Down ↑ Down
+ Home ↑ Left ↑ Left ↑ Left ↑ Left
+ End ↑ Right ↑ Right ↑ Right ↑ Right
+ PageUp α Up ³
+ PageDown α Down ³
+
+ F1 Y= f(x)= Y= Y= F1
+ F2 WINDOW fenêtre RANGE WINDOW F2
+ F3 ZOOM zoom ZOOM ZOOM F3
+ F4 TRACE trace TRACE TRACE F4
+ F5 GRAPH graphe GRAPH GRAPH F5
+ S+F1 ↑ [PLOT] ↑ [gr stat] ↑ Y= ↑ [STAT PLT] ↑ [M1]
+ S+F2 ↑ [TBLSET] ↑ [déf tab] ↑ RANGE ↑ [TBLSET] ↑ [M2]
+ S+F3 ↑ [FORMAT] ↑ [format] ↑ ZOOM ↑ [FORMAT] ↑ [M3]
+ S+F4 ↑ TRACE ↑ [calculs] ↑ TRACE ↑ [CALC] ↑ [M4]
+ S+F5 ↑ [TABLE] ↑ [table] ↑ GRAPH ↑ [TABLE] ↑ [M5]
+ PageDown MORE
+
+ Tab 2nd 2nde 2nd 2nd 2nd
+ ' or Menu ↑ [TEXT] texte Alpha Alpha Alpha
+
+ Insert ↑ [INS] ↑ [insérer] INS ↑ [INS] ↑ [INS]
+ Delete DEL suppr DEL DEL DEL
+ Backspace Left, DEL Left, suppr Left, DEL Left, DEL Left, DEL
+ C+Backspace CLEAR annul CLEAR CLEAR CLEAR
+ or C+Delete
+
+ Escape CLEAR annul CLEAR CLEAR EXIT
+ S+Escape ↑ [QUIT] ↑ [quitter] ↑ [QUIT] ↑ [QUIT] ↑ [QUIT]
+
+ F6 math MATH MATH GRAPH
+ F7 APPS angle MATRX MATRX/APPS STAT
+ F8 PRGM prgm PRGM PRGM PRGM
+ F9 var VARS VARS CUSTOM
+ F10 stats STAT
+ F11 MODE mode MODE MODE ↑ [MODE]
+ c CONST
+ d DRAW
+ l LIST
+ m MATH
+ p prgm PRGM PRGM
+ C+Tab ↑ [CATALOG] ↑ [catalog] ↑ [CATALOG]³ ↑ [CATALOG]
+
+ _ UNIT
+ | or ½ a/b
+ f F◂▸D
+ a Ab/c◂▸d/e
+ s SIMP
+ % %
+
+ | ↑ [ABS] ↑ [ABS] ²
+ s sin SIN SIN
+ c cos COS COS
+ t tan TAN TAN
+ o log LOG LOG
+ l ln LN LN
+
+ u ↑ [uₙ] ↑ [u] ³
+ v ↑ [vₙ] ↑ [v] ³
+ w ↑ [wₙ] ↑ [w] ³
+ u ↑ [Uₙ₋₁] ²
+ v ↑ [Vₙ₋₁] ²
+ n ↑ [n] ²
+
+ C+1 or \ ↑ [x⁻¹] x⁻¹ x⁻¹ x⁻¹ ↑ [x⁻¹]
+ C+2 or ² x² x² x² x² x²
+ ( ( ( ( ( (
+ ) ) ( ) ) )
+ { ↑ [{] ↑ [{]
+ } ↑ [}] ↑ [}]
+ [ ↑ [[] ↑ [[]
+ ] ↑ []] ↑ []]
+ ^ ^ ^ ^ ^ ^
+ / ÷ ÷ ÷ ÷ ÷
+ * × × × × ×
+ - - - - - -
+ + + + + + +
+ , , , α [,] , ,
+
+ > STO▸ STO▸ STO▸ STO▸ STO▸
+ < ↑ [RCL] ↑ [rappel] ↑ STO▸ ↑ [RCL] ↑ [RCL]
+
+ 0 - 9 0 - 9 0 - 9 0 - 9 0 - 9 0 - 9
+ . . . . . .
+ ~ or ± (-) (-) (-) (-) (-)
+ & or € ↑ [EE] ↑ […×10ⁿ] EE ↑ [EE] EE
+
+ x X x,n X|T X,T,θ,n
+ $ ↑ [ANS] ↑ [rép] ↑ [ANS] ↑ [ANS] ↑ [ANS]
+ # ↑ [π] ↑ [π] ↑ [π] ↑ [π] ↑ [π]
+ e ↑ [e] ↑ [e] ³
+ i ↑ [i] ³
+
+ A - Z α [A]-[Z] α [A]-[Z] α [A]-[Z]
+ a - z ↑α [a]-[z]
+ Space α [space] α [space] α [space]
+ @ α [θ] α [θ]
+ " α ["] α ["]
+ ? α [?] α [?]
+ : α [:] ↑ [:]
+ = α [=]
+
+ Return ENTER entrer ENTER ENTER ENTER
+ S+Return ↑ [ENTRY] ↑ [précéd] ↑ [ENTRY] ↑ [ENTRY] ↑ [ENTRY]
+ ──────────────────────────────────────────────────────────────────────────────
+
+ For the TI-83 Plus and TI-84 Plus, in addition to the keys listed
+ above for the TI-83, pressing Shift+letter while Caps Lock is enabled
+ will type a lowercase letter (Alpha, Alpha, letter.) Lowercase mode
+ will need to be enabled on the calculator for this to work; it's not
+ enabled by default, but there are many assembly programs that can do
+ so.
+
+
+KEYPAD CHARTS
+
+ TI-73 TI-76.fr
+
+ ╭──────┬──────┬──────┬──────┬──────╮ ╭──────┬──────┬──────┬──────┬──────╮
+ │S+F1 │S+F2 │S+F3 │S+F4 │S+F5 │ │S+F1 │S+F2 │S+F3 │S+F4 │S+F5 │
+ │F1 │F2 │F3 │F4 │F5 │ │F1 │F2 │F3 │F4 │F5 │
+ ╰──────┴──────┴──────┴────┬─┴──┬───╯ ╰──────┴──────┴──────┴────┬─┴──┬───╯
+ ╭──────┬──────┬──────╮ │S+Up│ ╭──────┬──────┬──────╮ │S+Up│
+ │ │S+Esc │Ins ├────┤Up ├─────╮ │ │S+Esc │Ins ├────┤Up ├─────╮
+ │Tab │F11 │Del │Home├────┤End │ │Tab │F11 │Del │Home├────┤End │
+ ├──────┼──────┼──────┤Left├────┤Right│ ├──────┼──────┼──────┤Left├────┤Right│
+ │' │ │ ├────┤S+Dn├─────╯ │ │ │ ├────┤S+Dn├─────╯
+ │m │d │l │ │Down│ │' │x │F10 │ │Down│
+ ├──────┼──────┼──────┼────┴─┬──┴───╮ ├──────┼──────┼──────┼────┴─┬──┴───╮
+ │ │& │C+Tab │ │ │ │ │ │ │ │ │
+ │C+2 │^ │F8 │F7 │Esc │ │F6 │F7 │F8 │F9 │Esc │
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │ │\ │# │ │ │ │ │ │ │ │# │
+ │_ │| │f │a │c │ │\ │s │c │t │^ │
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │ │ │ │ │ │ │ │& │{ │} │e │
+ │s │% │( │) │/ │ │C+2 │, │( │) │/ │
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │ │ │ │ │ │ │ │u │v │w │ │
+ │x │7 │8 │9 │* │ │o │7 │8 │9 │* │
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │ │ │ │ │ │ │ │ │ │ │ │
+ │, │4 │5 │6 │- │ │l │4 │5 │6 │- │
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │< │ │ │ │ │ │< │ │ │ │ │
+ │> │1 │2 │3 │+ │ │> │1 │2 │3 │+ │
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │S+F12 │ │ │$ │S+Ret │ │S+F12 │C+Tab │ │$ │S+Ret │
+ │F12 │0 │. │~ │Ret │ │F12 │0 │. │~ │Ret │
+ ╰──────┴──────┴──────┴──────┴──────╯ ╰──────┴──────┴──────┴──────┴──────╯
+
+
+ TI-81 TI-82
+
+ ╭──────┬──────┬──────┬──────┬──────╮ ╭──────┬──────┬──────┬──────┬──────╮
+ │S+F1 │S+F2 │S+F3 │S+F4 │S+F5 │ │S+F1 │S+F2 │S+F3 │S+F4 │S+F5 │
+ │F1 │F2 │F3 │F4 │F5 │ │F1 │F2 │F3 │F4 │F5 │
+ ╰──────┴──────┴──────┴────┬─┴──┬───╯ ╰──────┴──────┴──────┴────┬─┴──┬───╯
+ ╭──────┬──────┬──────╮ │S+Up│ ╭──────┬──────┬──────╮ │S+Up│
+ │ │ │ ├────┤Up ├─────╮ │ │S+Esc │Ins ├────┤Up ├─────╮
+ │Tab │Ins │Del │ ├────┤ │ │Tab │F11 │Del │Home├────┤End │
+ ├──────┼──────┼──────┤Left├────┤Right│ ├──────┼──────┼──────┤Left├────┤Right│
+ │ │ │ ├────┤S+Dn├─────╯ │ │ │ ├────┤S+Dn├─────╯
+ │' │x │F11 │ │Down│ │' │x │F10 │ │Down│
+ ├──────┼──────┼──────┼────┴─┬──┴───╮ ├──────┼──────┼──────┼────┴─┬──┴───╮
+ │ │ │ │ │S+Esc │ │ │ │ │ │ │
+ │F6 │F7 │F8 │F9 │Esc │ │F6 │F7 │F8 │F9 │Esc │
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │| │ │ │ │# │ │| │ │ │ │# │
+ │\ │s │c │t │^ │ │\ │s │c │t │^ │
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │ │ │ │ │ │ │ │& │{ │} │ │
+ │C+2 │& │( │) │/ │ │C+2 │, │( │) │/ │
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │ │ │ │ │ │ │ │u │v │n │[ │
+ │o │7 │8 │9 │* │ │o │7 │8 │9 │* │
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │ │ │ │ │ │ │ │ │ │ │] │
+ │l │4 │5 │6 │- │ │l │4 │5 │6 │- │
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │< │ │ │ │ │ │< │ │ │ │ │
+ │> │1 │2 │3 │+ │ │> │1 │2 │3 │+ │
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │S+F12 │ │ │$ │S+Ret │ │S+F12 │ │ │$ │S+Ret │
+ │F12 │0 │. │~ │Ret │ │F12 │0 │. │~ │Ret │
+ ╰──────┴──────┴──────┴──────┴──────╯ ╰──────┴──────┴──────┴──────┴──────╯
+
+ Not shown: Not shown:
+ A-Z Alpha, [A]-[Z] A-Z Alpha, [A]-[Z]
+ @ Alpha, 3 @ Alpha, 3
+ " Alpha, + " Alpha, +
+ Space Alpha, 0 Space Alpha, 0
+ , Alpha, . : Alpha, .
+ ? Alpha, (-) ? Alpha, (-)
+
+
+ TI-83 / TI-83 Plus / TI-84 Plus TI-85 / TI-86
+
+ ╭──────┬──────┬──────┬──────┬──────╮ ╭──────┬──────┬──────┬──────┬──────╮
+ │S+F1 │S+F2 │S+F3 │S+F4 │S+F5 │ │S+F1 │S+F2 │S+F3 │S+F4 │S+F5 │
+ │F1 │F2 │F3 │F4 │F5 │ │F1 │F2 │F3 │F4 │F5 │
+ ╰──────┴──────┴──────┴────┬─┴──┬───╯ ╰──────┴──────┴──────┴────┬─┴──┬───╯
+ ╭──────┬──────┬──────╮ │S+Up│ ╭──────┬──────┬──────╮ │S+Up│
+ │ │S+Esc │Ins ├────┤Up ├─────╮ │ │S+Esc │F11 ├────┤Up ├─────╮
+ │Tab │F11 │Del │Home├────┤End │ │Tab │Esc │PgDn │Home├────┤End │
+ ├──────┼──────┼──────┤Left├────┤Right│ ├──────┼──────┼──────┤Left├────┤Right│
+ │ │ │ ├────┤S+Dn├─────╯ │ │ │Ins ├────┤S+Dn├─────╯
+ │' │x │F10 │ │Down│ │' │ │Del │ │Down│
+ ├──────┼──────┼──────┼────┴─┬──┴───╮ ├──────┼──────┼──────┼────┴─┬──┴───╮
+ │ │ │ │ │ │ │ │ │ │C+Tab │ │
+ │F6 │F7 │F8 │F9 │Esc │ │F6 │F7 │F8 │F9 │C+BkSp│
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │ │ │ │ │# │ │ │ │ │ │# │
+ │\ │s │c │t │^ │ │ │ │ │ │^ │
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │ │& │{ │} │e │ │ │\ │[ │] │ │
+ │C+2 │, │( │) │/ │ │ │& │( │) │/ │
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │ │u │v │w │[ │ │ │ │ │ │ │
+ │o │7 │8 │9 │* │ │C+2 │7 │8 │9 │* │
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │ │ │ │ │] │ │ │ │ │ │ │
+ │l │4 │5 │6 │- │ │, │4 │5 │6 │- │
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │< │ │ │ │ │ │< │ │ │ │ │
+ │> │1 │2 │3 │+ │ │> │1 │2 │3 │+ │
+ ├──────┼──────┼──────┼──────┼──────┤ ├──────┼──────┼──────┼──────┼──────┤
+ │S+F12 │C+Tab │i │$ │S+Ret │ │S+F12 │ │: │$ │S+Ret │
+ │F12 │0 │. │~ │Ret │ │F12 │0 │. │~ │Ret │
+ ╰──────┴──────┴──────┴──────┴──────╯ ╰──────┴──────┴──────┴──────┴──────╯
+
+ Not shown: Not shown:
+ PageUp Alpha, Up A-Z Alpha, [A]-[Z]
+ PageDown Alpha, Down a-z 2nd, Alpha, [a]-[z]
+ A-Z Alpha, [A]-[Z] Space Alpha, (-)
+ @ Alpha, 3 = Alpha, Sto▸
+ " Alpha, +
+ Space Alpha, 0
+ : Alpha, .
+ ? Alpha, (-)
+
+ TI-83 Plus / TI-84 Plus only:
+ CapsLock + Shift + a-z = Alpha, Alpha, [a]-[z]
diff --git a/tool/tilem-src/Makefile.in b/tool/tilem-src/Makefile.in
new file mode 100644
index 0000000..77de808
--- /dev/null
+++ b/tool/tilem-src/Makefile.in
@@ -0,0 +1,91 @@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datarootdir = @datarootdir@
+bindir = @bindir@
+datadir = @datadir@
+pkgdatadir = @datadir@/tilem2
+mandir = @mandir@
+
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+@SET_MAKE@
+SHELL = @SHELL@
+
+INSTALL = @INSTALL@
+
+distname = @PACKAGE_TARNAME@-@PACKAGE_VERSION@
+
+distfiles = CHANGELOG COPYING INSTALL KEYS NEWS README THANKS TODO \
+ aclocal.m4 config.h.in configure configure.ac install-sh \
+ Makefile.in \
+ data/Makefile.in \
+ data/keybindings.ini \
+ data/desktop/*.desktop data/desktop/*.xml \
+ data/icons/hicolor/index.theme data/icons/hicolor/*/*/*.png \
+ data/icons-svg/*.svg \
+ data/skins/README data/skins/*.skn \
+ data/symbols/*.sym \
+ db/Makefile.in db/*.c db/*.h \
+ emu/Makefile.in emu/*.c emu/*.h emu/x*/*.c emu/x*/*.h \
+ gui/Makefile.in gui/*.c gui/*.h gui/*.ico gui/*.rc.in \
+ installer/win32/Makefile.in \
+ installer/win32/installer.nsi.in installer/win32/gtkrc \
+ installer/win32/COPYING-ZLIB installer/win32/COPYING-PIXMAN
+
+all:
+ cd emu && $(MAKE)
+ cd db && $(MAKE)
+ cd gui && $(MAKE)
+
+clean:
+ cd emu && $(MAKE) clean
+ cd db && $(MAKE) clean
+ cd gui && $(MAKE) clean
+ cd installer/win32 && $(MAKE) clean
+
+install: all
+ cd gui && $(MAKE) install
+ cd data && $(MAKE) install
+
+uninstall:
+ cd gui && $(MAKE) uninstall
+ cd data && $(MAKE) uninstall
+
+install-home: all
+ $(MAKE) install \
+ bindir=$(HOME)/bin \
+ datarootdir=$${XDG_DATA_HOME:-$(HOME)/.local/share}
+
+uninstall-home:
+ $(MAKE) uninstall \
+ bindir=$(HOME)/bin \
+ datarootdir=$${XDG_DATA_HOME:-$(HOME)/.local/share}
+
+distclean: clean
+ rm -f config.status config.log config.h configure.lineno
+ rm -rf autom4te.cache
+ rm -f installer/win32/Makefile installer/win32/installer.nsi
+ rm -f gui/tilem2.rc
+ rm -f Makefile emu/Makefile db/Makefile gui/Makefile data/Makefile
+
+dist:
+ rm -rf $(distname)
+ mkdir $(distname)
+ set -e ; files=`cd $(srcdir) ; echo $(distfiles)` ; \
+ for f in $$files ; do \
+ dir=`echo $(distname)/$$f | sed 's,/[^/]*$$,,'` ; \
+ [ -d $$dir ] || $(INSTALL) -d $$dir ; \
+ cp -p $(srcdir)/$$f $$dir ; \
+ done
+ tar cv $(distname) | bzip2 -c -9 > $(distname).tar.bz2
+
+Makefile: Makefile.in config.status
+ $(SHELL) ./config.status
+
+config.status: configure
+ $(SHELL) ./config.status --recheck
+
+.PRECIOUS: Makefile config.status
+.PHONY: all clean dist distclean install install-home uninstall uninstall-home
diff --git a/tool/tilem-src/NEWS b/tool/tilem-src/NEWS
new file mode 100644
index 0000000..45ef967
--- /dev/null
+++ b/tool/tilem-src/NEWS
@@ -0,0 +1,73 @@
+ Version History
+ -----------------
+
+2012-06-07 -- version 2.0
+
+ This is the first official release of the "new" TilEm. Much of the
+ old TilEm code has been rewritten, and there are many improvements
+ (and probably some new bugs.)
+
+ Please note, if you have used older versions of TilEm:
+
+ * Your existing ROM files and settings in ~/.TilEm will not be
+ used (in fact, you can keep TilEm 0.97x installed alongside
+ TilEm 2.0 if you wish.) TilEm 2.0 no longer uses a "library" of
+ ROM files; you can store ROM files anywhere you like.
+
+ * TilEm 2.0 uses a new format for calculator state (SAV) files.
+ State files created by TilEm 0.97x can be loaded by TilEm 2.0,
+ but if you then save the state, it will be stored in the new
+ format, which older versions of TilEm will not support.
+
+ New features and bugs fixed since version 0.975 include:
+
+ * All code that was covered by the Z80em license has been removed.
+
+ * Support for the TI-81 (both hardware versions) and TI-76.fr, and
+ experimental support for the TI-Nspire's TI-84 Plus emulation
+ mode.
+
+ * Many hardware emulation improvements for all calculator models.
+ In particular, major improvements have been made concerning Z80
+ interrupts, timers, the LCD driver, and the link port.
+
+ * The emulator window uses TiEmu-format skin files.
+
+ * Greatly improved grayscale emulation.
+
+ * Commands for saving still screenshots (in PNG, BMP, JPEG, or GIF
+ format) and animations (GIF format only.)
+
+ * Keypad macros can be recorded and replayed.
+
+ * Programs and/or ROM files can be loaded from the command line.
+
+ * Link I/O uses libticalcs2, which allows all types of variables,
+ as well as Flash apps and OSes, to be transferred through the
+ link port. For the TI-81, PRG files can be transferred to and
+ from the calculator memory directly.
+
+ * TilEm does not consume 100% of the host CPU when idle.
+
+ * Improved disassembler (macros; distinct "labels" and "romcalls";
+ named IY flags.)
+
+ * The debugger offers a "Finish Subroutine" command. In addition,
+ the "Step Over" command behaves more sensibly.
+
+ * Breakpoints can be set on absolute memory addresses, and on Z80
+ opcodes.
+
+ * Many minor improvements.
+
+ Features of 0.975 that are not yet supported in TilEm 2.0 include:
+
+ * External link cables.
+
+ * Custom symbol files in the disassembler.
+
+ * Program counter history tracking.
+
+ Most of the new code is due to Benjamin Moody (floppusmaximus) and
+ Thibault Duponchelle (contra-sh). See THANKS for a full list of
+ contributors.
diff --git a/tool/tilem-src/README b/tool/tilem-src/README
new file mode 100644
index 0000000..bcd613c
--- /dev/null
+++ b/tool/tilem-src/README
@@ -0,0 +1,92 @@
+ TilEm
+ -------
+
+TilEm is an emulator and debugger for Texas Instruments Z80-based
+graphing calculators. It can emulate any of the following calculator
+models:
+
+ TI-73 / TI-73 Explorer
+ TI-76.fr
+ TI-81
+ TI-82
+ TI-82 STATS / TI-82 STATS.fr
+ TI-83
+ TI-83 Plus / TI-83 Plus Silver Edition / TI-83 Plus.fr
+ TI-84 Plus / TI-84 Plus Silver Edition / TI-84 pocket.fr
+ TI-85
+ TI-86
+
+TilEm fully supports all known versions of the above calculators (as
+of 2012), and attempts to reproduce the behavior of the original
+calculator hardware as faithfully as possible.
+
+In addition, TilEm can emulate the TI-Nspire's virtual TI-84 Plus
+mode. This is currently experimental, and some programs may not work
+correctly.
+
+TilEm runs on the X Window System on GNU/Linux and other Unix-like
+platforms, as well as on Microsoft Windows, and any other platform
+supported by the GTK+ library.
+
+
+ Installation
+ --------------
+Packages for Microsoft Windows are available from the TilEm project
+website (http://lpg.ticalc.org/prj_tilem/). For other platforms, you
+will need to compile TilEm from source; please see the file 'INSTALL'
+in the source package.
+
+
+ Using TilEm
+ -------------
+TilEm requires a copy of the operating system from the calculator
+model(s) you wish to emulate. This file is called a "ROM image",
+since the calculator OS was traditionally stored in Read-Only Memory.
+ROM images are copyrighted by TI and may not be distributed without
+permission. See the TilEm User's Manual for more information about
+how to create a ROM image.
+
+The main TilEm window shows an image of the calculator (if possible -
+we are still missing background images for a few models.) Clicking
+with the left mouse button presses a key; clicking with the middle
+button presses a key and holds it down. Clicking with the right
+button, or pressing Shift+F10, opens the menu.
+
+When you run TilEm for the first time, it will ask you to select a ROM
+image to use. The file you select will be used by default the next
+time you run TilEm. You can switch to a different ROM image by
+right-clicking and selecting "Open Calculator".
+
+The state of the emulated calculator is not saved by default; to save
+the state, right-click and select "Save Calculator". The state is
+saved to a ".sav" file, stored in the same directory as the ROM image.
+
+You can send program and variable files to the emulated calculator,
+either by dragging and dropping them from your file manager, or by
+right-clicking and selecting "Send File". To retrieve program or
+variable files from the calculator, select "Receive File".
+
+Other features of TilEm include:
+
+ - A debugger for assembly programs
+ - Capturing screenshots, both normal and animated
+ - Recording and replaying keystroke macros
+
+For more information, see the TilEm User's Manual:
+ http://lpg.ticalc.org/prj_tilem2/doc.html
+
+
+ About this program
+ --------------------
+Many people deserve credit for helping to make this program possible.
+See the file 'THANKS'.
+
+This program is free software, which means that you are allowed to
+modify it, and to distribute it (or your modified version) to others.
+When you received this program, you should also have been offered a
+complete copy of its source code. For more information, see the file
+'COPYING'.
+
+You can contact the authors at .
+Please let us know of any problems you encounter, or ideas for how we
+could make TilEm better.
diff --git a/tool/tilem-src/THANKS b/tool/tilem-src/THANKS
new file mode 100644
index 0000000..b76e949
--- /dev/null
+++ b/tool/tilem-src/THANKS
@@ -0,0 +1,37 @@
+ Thanks
+ --------
+The current maintainers of TilEm are Thibault Duponchelle and Benjamin
+Moody, but many other people have played a part in making this program
+possible.
+
+The original TilEm was written in 2001 by Julien Solignac. The
+current version is partially based on the original, but large portions
+have been rewritten, starting in 2009, by Benjamin Moody and Thibault
+Duponchelle. Portions of the hardware emulation code are also due to
+Luc Bruant.
+
+The code for reading skin files is based on code from TiEmu, written
+by Julien Blache. The GIF compression code is based on whirlgif,
+written by Hans Dinsen-Hansen and Michael A. Mayer.
+
+Thanks to Claude Clerc for the photo of his TI-83 Plus, and to Danilo
+Šegan for the photo of his TI-86, which we have used as skins. Thanks
+to Scott Zeid for the design of the program icon.
+
+TilEm uses the TiLP libraries (libticalcs2, libticables2, libtifiles2,
+and libticonv) to send and receive variables. Thanks are due to the
+current maintainer of TiLP, Lionel Debroux, for his assistance, as
+well as to all of the past maintainers of TiLP, including Romain
+Liévin, Kevin Kofler, and Julien Blache.
+
+Finally, this program would never have been possible without the
+efforts of countless programmers and researchers over the years to
+discover and document the inner workings of the calculator hardware.
+The following people deserve special recognition for their research:
+Randy Compton, Tijl Coosemans, Brian Coventry, Dan Eble, Dan
+Englender, Dines Justesen, Julien Lasson, Mattias Lindqvist, James
+Montelongo, Michael Vincent, Brandon Wilson, and Joerg Woerner.
+
+(Thibault) In addition of above:
+Thanks to Michael Nock and Guillaume Hoffman for testing, feature request and encouragement.
+Thanks to Xavier Andreani for his encouragement.
diff --git a/tool/tilem-src/TODO b/tool/tilem-src/TODO
new file mode 100644
index 0000000..53b4599
--- /dev/null
+++ b/tool/tilem-src/TODO
@@ -0,0 +1,7 @@
+- Linking between 2 tilem instances
+- Sound
+- Rewrite macro (parser and tokens).
+- Add scripting (lua or something else?)
+- Teacher mode (record keys pressed and produce a picture file with keys icons)
+
+
diff --git a/tool/tilem-src/aclocal.m4 b/tool/tilem-src/aclocal.m4
new file mode 100644
index 0000000..af3c83d
--- /dev/null
+++ b/tool/tilem-src/aclocal.m4
@@ -0,0 +1,173 @@
+# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+# serial 1 (pkg-config-0.24)
+#
+# Copyright © 2004 Scott James Remnant .
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=m4_default([$1], [0.9.0])
+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ PKG_CONFIG=""
+ fi
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists. Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+# only at the first occurence in configure.ac, so if the first place
+# it's called might be skipped (such as if it is within an "if", you
+# have to call PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+ m4_default([$2], [:])
+m4_ifvaln([$3], [else
+ $3])dnl
+fi])
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes ],
+ [pkg_failed=yes])
+ else
+ pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+ AC_MSG_RESULT([no])
+ _PKG_SHORT_ERRORS_SUPPORTED
+ if test $_pkg_short_errors_supported = yes; then
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
+ else
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+ m4_default([$4], [AC_MSG_ERROR(
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT])[]dnl
+ ])
+elif test $pkg_failed = untried; then
+ AC_MSG_RESULT([no])
+ m4_default([$4], [AC_MSG_FAILURE(
+[The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see .])[]dnl
+ ])
+else
+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+ AC_MSG_RESULT([yes])
+ $3
+fi[]dnl
+])# PKG_CHECK_MODULES
+
diff --git a/tool/tilem-src/config.h.in b/tool/tilem-src/config.h.in
new file mode 100644
index 0000000..f2aa9aa
--- /dev/null
+++ b/tool/tilem-src/config.h.in
@@ -0,0 +1,91 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if the system has the type `uintptr_t'. */
+#undef HAVE_UINTPTR_T
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+# undef WORDS_BIGENDIAN
+# endif
+#endif
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to the equivalent of the C99 'restrict' keyword, or to
+ nothing if this is not supported. Do not define if restrict is
+ supported directly. */
+#undef restrict
+/* Work around a bug in Sun C++: it does not support _Restrict or
+ __restrict__, even though the corresponding Sun C compiler ends up with
+ "#define restrict _Restrict" or "#define restrict __restrict__" in the
+ previous line. Perhaps some future version of Sun C++ will work with
+ restrict; if so, hopefully it defines __RESTRICT like Sun C does. */
+#if defined __SUNPRO_CC && !defined __RESTRICT
+# define _Restrict
+# define __restrict__
+#endif
+
+/* Define to the type of an unsigned integer type wide enough to hold a
+ pointer, if such a type exists, and if the system does not define it. */
+#undef uintptr_t
diff --git a/tool/tilem-src/configure b/tool/tilem-src/configure
new file mode 100755
index 0000000..cc4e5ad
--- /dev/null
+++ b/tool/tilem-src/configure
@@ -0,0 +1,6127 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.68 for TilEm 2.0.
+#
+# Report bugs to .
+#
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ # We cannot yet assume a decent shell, so we have to provide a
+ # neutralization value for shells without unset; and this also
+ # works around shells that cannot unset nonexistent variables.
+ # Preserve -v and -x to the replacement shell.
+ BASH_ENV=/dev/null
+ ENV=/dev/null
+ (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+ export CONFIG_SHELL
+ case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+ esac
+ exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org and
+$0: tilem-devel@lists.sourceforge.net about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 &1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='TilEm'
+PACKAGE_TARNAME='tilem'
+PACKAGE_VERSION='2.0'
+PACKAGE_STRING='TilEm 2.0'
+PACKAGE_BUGREPORT='tilem-devel@lists.sourceforge.net'
+PACKAGE_URL='http://tilem.sourceforge.net/'
+
+ac_unique_file="emu/tilem.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include
+#ifdef HAVE_SYS_TYPES_H
+# include
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include
+#endif
+#ifdef STDC_HEADERS
+# include
+# include
+#else
+# ifdef HAVE_STDLIB_H
+# include
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include
+# endif
+# include
+#endif
+#ifdef HAVE_STRINGS_H
+# include
+#endif
+#ifdef HAVE_INTTYPES_H
+# include
+#endif
+#ifdef HAVE_STDINT_H
+# include
+#endif
+#ifdef HAVE_UNISTD_H
+# include
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+EGREP
+GREP
+DLLPATH
+TICALCS_BINDIR
+GTK_BINDIR
+LN_S
+MAKENSIS
+WINDRES
+OBJDUMP
+STRIP
+TICALCS_LIBS
+TICALCS_CFLAGS
+gui_extra_objects
+GUI_LDFLAGS
+GTK_LIBS
+GTK_CFLAGS
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+PKG_CONFIG
+UPDATE_MIME_DATABASE
+UPDATE_DESKTOP_DATABASE
+SET_MAKE
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+RANLIB
+AR_FLAGS
+AR
+OPT_CFLAGS
+CPP
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_gtk_deprecated
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+OPT_CFLAGS
+AR
+AR_FLAGS
+RANLIB
+PKG_CONFIG
+PKG_CONFIG_PATH
+PKG_CONFIG_LIBDIR
+GTK_CFLAGS
+GTK_LIBS
+TICALCS_CFLAGS
+TICALCS_LIBS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used" >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures TilEm 2.0 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/tilem]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of TilEm 2.0:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --disable-gtk-deprecated
+ Disable deprecated GTK+ API
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L if you have libraries in a
+ nonstandard directory
+ LIBS libraries to pass to the linker, e.g. -l
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if
+ you have headers in a nonstandard directory
+ CPP C preprocessor
+ OPT_CFLAGS Additional C compiler flags used for optimizing critical areas
+ of the code (default: -O3 if using GCC)
+ AR Static library archiver
+ AR_FLAGS Flags to pass to ar to build a static library
+ RANLIB Program to make a static library linkable
+ PKG_CONFIG path to pkg-config utility
+ PKG_CONFIG_PATH
+ directories to add to pkg-config's search path
+ PKG_CONFIG_LIBDIR
+ path overriding pkg-config's built-in search path
+ GTK_CFLAGS C compiler flags for GTK, overriding pkg-config
+ GTK_LIBS linker flags for GTK, overriding pkg-config
+ TICALCS_CFLAGS
+ C compiler flags for TICALCS, overriding pkg-config
+ TICALCS_LIBS
+ linker flags for TICALCS, overriding pkg-config
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to .
+TilEm home page: .
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+TilEm configure 2.0
+generated by GNU Autoconf 2.68
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ $as_test_x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case declares $2.
+ For example, HP-UX 11i declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer to if __STDC__ is defined, since
+ exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include
+#else
+# include
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by TilEm $as_me 2.0, which was
+generated by GNU Autoconf 2.68. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+# Checks for programs
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+#include
+#include
+#include
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer to if __STDC__ is defined, since
+ # exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include
+#else
+# include
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer to if __STDC__ is defined, since
+ # exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include
+#else
+# include
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+if test "x$GCC" = "xyes" ; then
+ CFLAGS="$CFLAGS -W -Wall -Wwrite-strings"
+ if test "x$OPT_CFLAGS" = "x" ; then
+ OPT_CFLAGS="-O3"
+ fi
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_AR="ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_AR" = x; then
+ AR="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+
+
+if test "x$AR_FLAGS" = "x" ; then
+ AR_FLAGS=cru
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ SET_MAKE=
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+# Extract the first word of "update-desktop-database", so it can be a program name with args.
+set dummy update-desktop-database; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_UPDATE_DESKTOP_DATABASE+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$UPDATE_DESKTOP_DATABASE"; then
+ ac_cv_prog_UPDATE_DESKTOP_DATABASE="$UPDATE_DESKTOP_DATABASE" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_UPDATE_DESKTOP_DATABASE="update-desktop-database"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_UPDATE_DESKTOP_DATABASE" && ac_cv_prog_UPDATE_DESKTOP_DATABASE=":"
+fi
+fi
+UPDATE_DESKTOP_DATABASE=$ac_cv_prog_UPDATE_DESKTOP_DATABASE
+if test -n "$UPDATE_DESKTOP_DATABASE"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $UPDATE_DESKTOP_DATABASE" >&5
+$as_echo "$UPDATE_DESKTOP_DATABASE" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "update-mime-database", so it can be a program name with args.
+set dummy update-mime-database; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_UPDATE_MIME_DATABASE+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$UPDATE_MIME_DATABASE"; then
+ ac_cv_prog_UPDATE_MIME_DATABASE="$UPDATE_MIME_DATABASE" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_UPDATE_MIME_DATABASE="update-mime-database"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_UPDATE_MIME_DATABASE" && ac_cv_prog_UPDATE_MIME_DATABASE=":"
+fi
+fi
+UPDATE_MIME_DATABASE=$ac_cv_prog_UPDATE_MIME_DATABASE
+if test -n "$UPDATE_MIME_DATABASE"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $UPDATE_MIME_DATABASE" >&5
+$as_echo "$UPDATE_MIME_DATABASE" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+# Checks for libraries
+
+
+
+# GLib and GTK+
+
+
+
+
+
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+ ac_pt_PKG_CONFIG=$PKG_CONFIG
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $ac_pt_PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_pt_PKG_CONFIG" = x; then
+ PKG_CONFIG=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ PKG_CONFIG=$ac_pt_PKG_CONFIG
+ fi
+else
+ PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=0.9.0
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ PKG_CONFIG=""
+ fi
+fi
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK" >&5
+$as_echo_n "checking for GTK... " >&6; }
+
+if test -n "$GTK_CFLAGS"; then
+ pkg_cv_GTK_CFLAGS="$GTK_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-2.0 >= 2.6.0
+ glib-2.0 >= 2.12.0
+ gthread-2.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "gtk+-2.0 >= 2.6.0
+ glib-2.0 >= 2.12.0
+ gthread-2.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GTK_CFLAGS=`$PKG_CONFIG --cflags "gtk+-2.0 >= 2.6.0
+ glib-2.0 >= 2.12.0
+ gthread-2.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$GTK_LIBS"; then
+ pkg_cv_GTK_LIBS="$GTK_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-2.0 >= 2.6.0
+ glib-2.0 >= 2.12.0
+ gthread-2.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "gtk+-2.0 >= 2.6.0
+ glib-2.0 >= 2.12.0
+ gthread-2.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GTK_LIBS=`$PKG_CONFIG --libs "gtk+-2.0 >= 2.6.0
+ glib-2.0 >= 2.12.0
+ gthread-2.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ GTK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gtk+-2.0 >= 2.6.0
+ glib-2.0 >= 2.12.0
+ gthread-2.0" 2>&1`
+ else
+ GTK_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gtk+-2.0 >= 2.6.0
+ glib-2.0 >= 2.12.0
+ gthread-2.0" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$GTK_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (gtk+-2.0 >= 2.6.0
+ glib-2.0 >= 2.12.0
+ gthread-2.0) were not met:
+
+$GTK_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables GTK_CFLAGS
+and GTK_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables GTK_CFLAGS
+and GTK_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see .
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ GTK_CFLAGS=$pkg_cv_GTK_CFLAGS
+ GTK_LIBS=$pkg_cv_GTK_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+# Check whether --enable-gtk-deprecated was given.
+if test "${enable_gtk_deprecated+set}" = set; then :
+ enableval=$enable_gtk_deprecated; enable_gtk_deprecated=$enableval
+else
+ enable_gtk_deprecated=yes
+fi
+
+if test "x$enable_gtk_deprecated" = "xno" ; then
+ GTK_CFLAGS="$GTK_CFLAGS -DG_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGSEAL_ENABLE"
+fi
+
+# If using the native Windows version of GTK+, be sure to use
+# -mms-bitfields for all compilation. Also, use -mwindows for linking
+# GUI programs.
+
+# (If not using pkg-config, you're on your own)
+
+if test "x$PKG_CONFIG" != "x" ; then
+ gtk_target=`$PKG_CONFIG --variable=target gtk+-2.0`
+fi
+
+if test "x$gtk_target" = "xwin32" && test "x$GCC" = "xyes" ; then
+ CFLAGS="$CFLAGS -mms-bitfields"
+ GUI_LDFLAGS="-mwindows"
+ LIBS="-lcomdlg32 -lshell32 -lole32 $LIBS"
+ gui_extra_objects="tilem2rc.o"
+else
+ GUI_LDFLAGS=""
+ gui_extra_objects=""
+fi
+
+
+
+
+
+ save_cflags="$CFLAGS"
+ save_libs="$LIBS"
+ CFLAGS="$CFLAGS $GTK_CFLAGS"
+ LIBS="$LIBS $GTK_LIBS"
+
+ac_fn_c_check_func "$LINENO" "gtk_init" "ac_cv_func_gtk_init"
+if test "x$ac_cv_func_gtk_init" = xyes; then :
+ have_gtk=yes
+else
+ have_gtk=no
+fi
+
+ CFLAGS="$save_cflags"
+ LIBS="$save_libs"
+
+if test "x$have_gtk" != "xyes" ; then
+ as_fn_error $? "GTK+ 2.x libraries not found or not usable.
+You must install a recent version of GTK+ 2.x, including the
+-dev/-devel packages if appropriate." "$LINENO" 5
+fi
+
+# Libticalcs2 and related libraries
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for TICALCS" >&5
+$as_echo_n "checking for TICALCS... " >&6; }
+
+if test -n "$TICALCS_CFLAGS"; then
+ pkg_cv_TICALCS_CFLAGS="$TICALCS_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ticalcs2 ticables2 tifiles2 ticonv\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "ticalcs2 ticables2 tifiles2 ticonv") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_TICALCS_CFLAGS=`$PKG_CONFIG --cflags "ticalcs2 ticables2 tifiles2 ticonv" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$TICALCS_LIBS"; then
+ pkg_cv_TICALCS_LIBS="$TICALCS_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ticalcs2 ticables2 tifiles2 ticonv\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "ticalcs2 ticables2 tifiles2 ticonv") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_TICALCS_LIBS=`$PKG_CONFIG --libs "ticalcs2 ticables2 tifiles2 ticonv" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ TICALCS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "ticalcs2 ticables2 tifiles2 ticonv" 2>&1`
+ else
+ TICALCS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "ticalcs2 ticables2 tifiles2 ticonv" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$TICALCS_PKG_ERRORS" >&5
+
+ have_ticalcs=no
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ have_ticalcs=no
+else
+ TICALCS_CFLAGS=$pkg_cv_TICALCS_CFLAGS
+ TICALCS_LIBS=$pkg_cv_TICALCS_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ have_ticalcs=maybe
+fi
+
+if test "x$have_ticalcs" = "xmaybe" ; then
+
+ save_cflags="$CFLAGS"
+ save_libs="$LIBS"
+ CFLAGS="$CFLAGS $TICALCS_CFLAGS"
+ LIBS="$LIBS $TICALCS_LIBS"
+ ac_fn_c_check_func "$LINENO" "ticalcs_library_init" "ac_cv_func_ticalcs_library_init"
+if test "x$ac_cv_func_ticalcs_library_init" = xyes; then :
+ have_ticalcs=yes
+else
+ have_ticalcs=no
+fi
+
+ CFLAGS="$save_cflags"
+ LIBS="$save_libs"
+
+fi
+
+if test "x$have_ticalcs" != "xyes" ; then
+ as_fn_error $? "libticalcs2 not found or not usable.
+
+$TICALCS_PKG_ERRORS
+
+You must install libticalcs2, libticables2, libtifiles2, and libticonv
+(including the -dev/-devel packages if appropriate.) These libraries
+are available from .
+
+If you have installed the libraries in a non-standard location (or if
+you're cross-compiling), you will need to add the location of
+ticalcs2.pc to your PKG_CONFIG_PATH environment variable, or set the
+TICALCS_CFLAGS and TICALCS_LIBS environment variables by hand." "$LINENO" 5
+fi
+
+# Tools used for building the Windows installer
+
+if test "x$gtk_target" = "xwin32" ; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OBJDUMP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$OBJDUMP"; then
+ ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+$as_echo "$OBJDUMP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+ ac_ct_OBJDUMP=$OBJDUMP
+ # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_OBJDUMP"; then
+ ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_OBJDUMP="objdump"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+$as_echo "$ac_ct_OBJDUMP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_OBJDUMP" = x; then
+ OBJDUMP="objdump"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OBJDUMP=$ac_ct_OBJDUMP
+ fi
+else
+ OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args.
+set dummy ${ac_tool_prefix}windres; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_WINDRES+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$WINDRES"; then
+ ac_cv_prog_WINDRES="$WINDRES" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_WINDRES="${ac_tool_prefix}windres"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+WINDRES=$ac_cv_prog_WINDRES
+if test -n "$WINDRES"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WINDRES" >&5
+$as_echo "$WINDRES" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_WINDRES"; then
+ ac_ct_WINDRES=$WINDRES
+ # Extract the first word of "windres", so it can be a program name with args.
+set dummy windres; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_WINDRES+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_WINDRES"; then
+ ac_cv_prog_ac_ct_WINDRES="$ac_ct_WINDRES" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_WINDRES="windres"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_WINDRES=$ac_cv_prog_ac_ct_WINDRES
+if test -n "$ac_ct_WINDRES"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_WINDRES" >&5
+$as_echo "$ac_ct_WINDRES" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_WINDRES" = x; then
+ WINDRES="windres"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ WINDRES=$ac_ct_WINDRES
+ fi
+else
+ WINDRES="$ac_cv_prog_WINDRES"
+fi
+
+ # Extract the first word of "makensis", so it can be a program name with args.
+set dummy makensis; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_MAKENSIS+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$MAKENSIS"; then
+ ac_cv_prog_MAKENSIS="$MAKENSIS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_MAKENSIS="makensis"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+MAKENSIS=$ac_cv_prog_MAKENSIS
+if test -n "$MAKENSIS"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKENSIS" >&5
+$as_echo "$MAKENSIS" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find GTK+ runtime libraries" >&5
+$as_echo_n "checking where to find GTK+ runtime libraries... " >&6; }
+ if test "x$GTK_BINDIR" = "x" ; then
+ prefix=`$PKG_CONFIG --variable=exec_prefix gtk+-2.0`
+ test "x$prefix" != "x" && GTK_BINDIR="$prefix/bin"
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTK_BINDIR" >&5
+$as_echo "$GTK_BINDIR" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find ticalcs2 runtime libraries" >&5
+$as_echo_n "checking where to find ticalcs2 runtime libraries... " >&6; }
+ if test "x$TICALCS_BINDIR" = "x" ; then
+ prefix=`$PKG_CONFIG --variable=exec_prefix ticalcs2`
+ test "x$prefix" != "x" && TICALCS_BINDIR="$prefix/bin"
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TICALCS_BINDIR" >&5
+$as_echo "$TICALCS_BINDIR" >&6; }
+
+ if test "x$DLLPATH" = "x" ; then
+ DLLPATH='${GTK_BINDIR}'$PATH_SEPARATOR'${TICALCS_BINDIR}'
+ fi
+
+
+
+fi
+
+# Checks for header files
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+#include
+#include
+#include
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+#include
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+
+# Checks for system and compiler characteristics
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if ${ac_cv_c_bigendian+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_bigendian=unknown
+ # See if we're dealing with a universal compiler.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __APPLE_CC__
+ not a universal capable compiler
+ #endif
+ typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ # Check for potential -arch flags. It is not universal unless
+ # there are at least two -arch flags with different values.
+ ac_arch=
+ ac_prev=
+ for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+ if test -n "$ac_prev"; then
+ case $ac_word in
+ i?86 | x86_64 | ppc | ppc64)
+ if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+ ac_arch=$ac_word
+ else
+ ac_cv_c_bigendian=universal
+ break
+ fi
+ ;;
+ esac
+ ac_prev=
+ elif test "x$ac_word" = "x-arch"; then
+ ac_prev=arch
+ fi
+ done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if sys/param.h defines the BYTE_ORDER macro.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+ #include
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+ && LITTLE_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+ #include
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to _BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # Compile a test program.
+ if test "$cross_compiling" = yes; then :
+ # Try to guess by grepping values from an object file.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+short int ascii_mm[] =
+ { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+ short int ascii_ii[] =
+ { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+ int use_ascii (int i) {
+ return ascii_mm[i] + ascii_ii[i];
+ }
+ short int ebcdic_ii[] =
+ { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+ short int ebcdic_mm[] =
+ { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+ int use_ebcdic (int i) {
+ return ebcdic_mm[i] + ebcdic_ii[i];
+ }
+ extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+ ac_cv_c_bigendian=yes
+ fi
+ if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+ u.l = 1;
+ return u.c[sizeof (long int) - 1] == 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_c_bigendian=no
+else
+ ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+ yes)
+ $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+ no)
+ ;; #(
+ universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+ ;; #(
+ *)
+ as_fn_error $? "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+if ${ac_cv_c_inline+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_inline=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
+$as_echo "$ac_cv_c_inline" >&6; }
+
+case $ac_cv_c_inline in
+ inline | yes) ;;
+ *)
+ case $ac_cv_c_inline in
+ no) ac_val=;;
+ *) ac_val=$ac_cv_c_inline;;
+ esac
+ cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+ ;;
+esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5
+$as_echo_n "checking for C/C++ restrict keyword... " >&6; }
+if ${ac_cv_c_restrict+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_restrict=no
+ # The order here caters to the fact that C++ does not require restrict.
+ for ac_kw in __restrict __restrict__ _Restrict restrict; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+typedef int * int_ptr;
+ int foo (int_ptr $ac_kw ip) {
+ return ip[0];
+ }
+int
+main ()
+{
+int s[1];
+ int * $ac_kw t = s;
+ t[0] = 0;
+ return foo(t)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_restrict=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_restrict" != no && break
+ done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_restrict" >&5
+$as_echo "$ac_cv_c_restrict" >&6; }
+
+ case $ac_cv_c_restrict in
+ restrict) ;;
+ no) $as_echo "#define restrict /**/" >>confdefs.h
+ ;;
+ *) cat >>confdefs.h <<_ACEOF
+#define restrict $ac_cv_c_restrict
+_ACEOF
+ ;;
+ esac
+
+
+ ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "$ac_includes_default"
+if test "x$ac_cv_type_uintptr_t" = xyes; then :
+
+$as_echo "#define HAVE_UINTPTR_T 1" >>confdefs.h
+
+else
+ for ac_type in 'unsigned int' 'unsigned long int' \
+ 'unsigned long long int'; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($ac_type))];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+cat >>confdefs.h <<_ACEOF
+#define uintptr_t $ac_type
+_ACEOF
+
+ ac_type=
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test -z "$ac_type" && break
+ done
+fi
+
+
+
+# Output
+
+ac_config_headers="$ac_config_headers config.h"
+
+ac_config_files="$ac_config_files Makefile emu/Makefile db/Makefile data/Makefile gui/Makefile gui/tilem2.rc installer/win32/Makefile installer/win32/installer.nsi"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by TilEm $as_me 2.0, which was
+generated by GNU Autoconf 2.68. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to .
+TilEm home page: ."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+TilEm config.status 2.0
+configured by $0, generated by GNU Autoconf 2.68,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "emu/Makefile") CONFIG_FILES="$CONFIG_FILES emu/Makefile" ;;
+ "db/Makefile") CONFIG_FILES="$CONFIG_FILES db/Makefile" ;;
+ "data/Makefile") CONFIG_FILES="$CONFIG_FILES data/Makefile" ;;
+ "gui/Makefile") CONFIG_FILES="$CONFIG_FILES gui/Makefile" ;;
+ "gui/tilem2.rc") CONFIG_FILES="$CONFIG_FILES gui/tilem2.rc" ;;
+ "installer/win32/Makefile") CONFIG_FILES="$CONFIG_FILES installer/win32/Makefile" ;;
+ "installer/win32/installer.nsi") CONFIG_FILES="$CONFIG_FILES installer/win32/installer.nsi" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' >$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' >$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+ ;;
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/tool/tilem-src/configure.ac b/tool/tilem-src/configure.ac
new file mode 100644
index 0000000..88e2306
--- /dev/null
+++ b/tool/tilem-src/configure.ac
@@ -0,0 +1,172 @@
+AC_PREREQ(2.67)
+AC_INIT([TilEm], [2.0], [tilem-devel@lists.sourceforge.net],
+ [tilem], [http://tilem.sourceforge.net/])
+AC_CONFIG_SRCDIR([emu/tilem.h])
+
+# Checks for programs
+
+AC_PROG_CC
+AC_PROG_CPP
+AC_ARG_VAR(OPT_CFLAGS,
+ [Additional C compiler flags used for optimizing critical areas of
+ the code (default: -O3 if using GCC)])
+if test "x$GCC" = "xyes" ; then
+ CFLAGS="$CFLAGS -W -Wall -Wwrite-strings"
+ if test "x$OPT_CFLAGS" = "x" ; then
+ OPT_CFLAGS="-O3"
+ fi
+fi
+
+AC_CHECK_TOOL(AR, [ar], [false])
+AC_ARG_VAR(AR, [Static library archiver])
+AC_ARG_VAR(AR_FLAGS, [Flags to pass to ar to build a static library])
+if test "x$AR_FLAGS" = "x" ; then
+ AR_FLAGS=cru
+fi
+
+AC_PROG_RANLIB
+AC_ARG_VAR(RANLIB, [Program to make a static library linkable])
+
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+
+AC_CHECK_PROG([UPDATE_DESKTOP_DATABASE],
+ [update-desktop-database], [update-desktop-database], [:])
+AC_CHECK_PROG([UPDATE_MIME_DATABASE],
+ [update-mime-database], [update-mime-database], [:])
+
+# Checks for libraries
+
+m4_define(with_flags, [
+ save_cflags="$CFLAGS"
+ save_libs="$LIBS"
+ CFLAGS="$CFLAGS $$1_CFLAGS"
+ LIBS="$LIBS $$1_LIBS"
+ $2
+ CFLAGS="$save_cflags"
+ LIBS="$save_libs"
+])
+
+# GLib and GTK+
+
+PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.6.0
+ glib-2.0 >= 2.12.0
+ gthread-2.0)
+
+AC_ARG_ENABLE([gtk-deprecated],
+ AS_HELP_STRING([--disable-gtk-deprecated], [Disable deprecated GTK+ API]),
+ [ enable_gtk_deprecated=$enableval ], [ enable_gtk_deprecated=yes ])
+if test "x$enable_gtk_deprecated" = "xno" ; then
+ GTK_CFLAGS="$GTK_CFLAGS -DG_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGSEAL_ENABLE"
+fi
+
+# If using the native Windows version of GTK+, be sure to use
+# -mms-bitfields for all compilation. Also, use -mwindows for linking
+# GUI programs.
+
+# (If not using pkg-config, you're on your own)
+
+if test "x$PKG_CONFIG" != "x" ; then
+ gtk_target=`$PKG_CONFIG --variable=target gtk+-2.0`
+fi
+
+if test "x$gtk_target" = "xwin32" && test "x$GCC" = "xyes" ; then
+ CFLAGS="$CFLAGS -mms-bitfields"
+ GUI_LDFLAGS="-mwindows"
+ LIBS="-lcomdlg32 -lshell32 -lole32 $LIBS"
+ gui_extra_objects="tilem2rc.o"
+else
+ GUI_LDFLAGS=""
+ gui_extra_objects=""
+fi
+
+AC_SUBST(GUI_LDFLAGS)
+AC_SUBST(gui_extra_objects)
+
+with_flags(GTK,
+ [ AC_CHECK_FUNC(gtk_init, [ have_gtk=yes ], [ have_gtk=no ]) ])
+if test "x$have_gtk" != "xyes" ; then
+ AC_MSG_ERROR([GTK+ 2.x libraries not found or not usable.
+You must install a recent version of GTK+ 2.x, including the
+-dev/-devel packages if appropriate.])
+fi
+
+# Libticalcs2 and related libraries
+
+PKG_CHECK_MODULES(TICALCS, ticalcs2 ticables2 tifiles2 ticonv,
+ [ have_ticalcs=maybe ], [ have_ticalcs=no ])
+
+if test "x$have_ticalcs" = "xmaybe" ; then
+ with_flags(TICALCS,
+ [ AC_CHECK_FUNC(ticalcs_library_init, [ have_ticalcs=yes ], [ have_ticalcs=no ]) ])
+fi
+
+if test "x$have_ticalcs" != "xyes" ; then
+ AC_MSG_ERROR([libticalcs2 not found or not usable.
+
+$TICALCS_PKG_ERRORS
+
+You must install libticalcs2, libticables2, libtifiles2, and libticonv
+(including the -dev/-devel packages if appropriate.) These libraries
+are available from .
+
+If you have installed the libraries in a non-standard location (or if
+you're cross-compiling), you will need to add the location of
+ticalcs2.pc to your PKG_CONFIG_PATH environment variable, or set the
+TICALCS_CFLAGS and TICALCS_LIBS environment variables by hand.])
+fi
+
+# Tools used for building the Windows installer
+
+if test "x$gtk_target" = "xwin32" ; then
+ AC_CHECK_TOOL([STRIP], [strip], [:])
+ AC_CHECK_TOOL([OBJDUMP], [objdump], [objdump])
+ AC_CHECK_TOOL([WINDRES], [windres], [windres])
+ AC_CHECK_PROG([MAKENSIS], [makensis], [makensis])
+ AC_PROG_LN_S
+
+ AC_MSG_CHECKING([where to find GTK+ runtime libraries])
+ if test "x$GTK_BINDIR" = "x" ; then
+ prefix=`$PKG_CONFIG --variable=exec_prefix gtk+-2.0`
+ test "x$prefix" != "x" && GTK_BINDIR="$prefix/bin"
+ fi
+ AC_MSG_RESULT([$GTK_BINDIR])
+
+ AC_MSG_CHECKING([where to find ticalcs2 runtime libraries])
+ if test "x$TICALCS_BINDIR" = "x" ; then
+ prefix=`$PKG_CONFIG --variable=exec_prefix ticalcs2`
+ test "x$prefix" != "x" && TICALCS_BINDIR="$prefix/bin"
+ fi
+ AC_MSG_RESULT([$TICALCS_BINDIR])
+
+ if test "x$DLLPATH" = "x" ; then
+ DLLPATH='${GTK_BINDIR}'$PATH_SEPARATOR'${TICALCS_BINDIR}'
+ fi
+ AC_SUBST(GTK_BINDIR)
+ AC_SUBST(TICALCS_BINDIR)
+ AC_SUBST(DLLPATH)
+fi
+
+# Checks for header files
+
+AC_HEADER_STDC
+
+# Checks for system and compiler characteristics
+
+AC_C_BIGENDIAN
+AC_C_INLINE
+AC_C_RESTRICT
+AC_TYPE_UINTPTR_T
+
+# Output
+
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_FILES([Makefile
+ emu/Makefile
+ db/Makefile
+ data/Makefile
+ gui/Makefile
+ gui/tilem2.rc
+ installer/win32/Makefile
+ installer/win32/installer.nsi])
+AC_OUTPUT
diff --git a/tool/tilem-src/data/Makefile.in b/tool/tilem-src/data/Makefile.in
new file mode 100644
index 0000000..c41e175
--- /dev/null
+++ b/tool/tilem-src/data/Makefile.in
@@ -0,0 +1,114 @@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datarootdir = @datarootdir@
+bindir = @bindir@
+datadir = @datadir@
+pkgdatadir = @datadir@/tilem2
+mandir = @mandir@
+icondir = @datadir@/icons
+applicationsdir = @datadir@/applications
+mimedir = @datadir@/mime
+
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+@SET_MAKE@
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+SHELL = @SHELL@
+UPDATE_DESKTOP_DATABASE = @UPDATE_DESKTOP_DATABASE@
+UPDATE_MIME_DATABASE = @UPDATE_MIME_DATABASE@
+
+# Custom action and status icons go in these directories. These icons
+# are only used by TilEm, so they are installed in DATADIR/tilem2/icons.
+pkg_icondirs = hicolor/16x16/actions \
+ hicolor/16x16/status \
+ hicolor/24x24/actions
+
+# Application icons go in these directories; these icons will be
+# installed in DATADIR/icons so they are visible to other programs
+# (e.g. desktop application menus.)
+shared_icondirs = hicolor/16x16/apps \
+ hicolor/22x22/apps \
+ hicolor/24x24/apps \
+ hicolor/32x32/apps \
+ hicolor/48x48/apps
+
+all:
+ @echo 'Nothing to do'
+
+install:
+ $(INSTALL) -d -m 755 $(DESTDIR)$(pkgdatadir)
+ $(INSTALL_DATA) $(srcdir)/keybindings.ini $(DESTDIR)$(pkgdatadir)
+ $(INSTALL) -d -m 755 $(DESTDIR)$(pkgdatadir)/symbols
+ set -e ; for i in $(srcdir)/symbols/*.sym ; do \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(pkgdatadir)/symbols ; \
+ done
+ $(INSTALL) -d -m 755 $(DESTDIR)$(pkgdatadir)/skins
+ set -e ; for i in $(srcdir)/skins/*.skn ; do \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(pkgdatadir)/skins ; \
+ done
+ set -e ; for i in $(pkg_icondirs) ; do \
+ $(INSTALL) -d -m 755 $(DESTDIR)$(pkgdatadir)/icons/$$i ; \
+ for j in $(srcdir)/icons/$$i/*.png ; do \
+ $(INSTALL_DATA) $$j $(DESTDIR)$(pkgdatadir)/icons/$$i ; \
+ done ; \
+ done
+ set -e ; for i in $(shared_icondirs) ; do \
+ $(INSTALL) -d -m 755 $(DESTDIR)$(icondir)/$$i ; \
+ for j in $(srcdir)/icons/$$i/*.png ; do \
+ $(INSTALL_DATA) $$j $(DESTDIR)$(icondir)/$$i ; \
+ done ; \
+ done
+ $(INSTALL_DATA) $(srcdir)/icons/hicolor/index.theme $(DESTDIR)$(pkgdatadir)/icons/hicolor
+ $(INSTALL) -d -m 755 $(DESTDIR)$(applicationsdir)
+ $(INSTALL_DATA) $(srcdir)/desktop/tilem2.desktop $(DESTDIR)$(applicationsdir)
+ $(INSTALL) -d -m 755 $(DESTDIR)$(mimedir)/packages
+ $(INSTALL_DATA) $(srcdir)/desktop/tilem2.xml $(DESTDIR)$(mimedir)/packages
+ [ -n "$(DESTDIR)" ] || $(UPDATE_DESKTOP_DATABASE) $(applicationsdir)
+ [ -n "$(DESTDIR)" ] || $(UPDATE_MIME_DATABASE) $(mimedir)
+
+uninstall:
+ rm -f $(DESTDIR)$(pkgdatadir)/keybindings.ini
+ set -e ; for i in $(srcdir)/symbols/*.sym ; do \
+ rm -f $(DESTDIR)$(pkgdatadir)/symbols/`basename $$i` ; \
+ done
+ set -e ; for i in $(srcdir)/skins/*.skn ; do \
+ rm -f $(DESTDIR)$(pkgdatadir)/skins/`basename $$i` ; \
+ done
+ set -e ; for i in $(pkg_icondirs) ; do \
+ for j in $(srcdir)/icons/$$i/*.png ; do \
+ rm -f $(DESTDIR)$(pkgdatadir)/icons/$$i/`basename $$j` ; \
+ done ; \
+ done
+ set -e ; for i in $(shared_icondirs) ; do \
+ for j in $(srcdir)/icons/$$i/*.png ; do \
+ rm -f $(DESTDIR)$(icondir)/$$i/`basename $$j` ; \
+ done ; \
+ done
+ -for i in $(pkg_icondirs) ; do \
+ rmdir $(DESTDIR)$(pkgdatadir)/icons/$$i ; \
+ done
+ -rmdir $(DESTDIR)$(pkgdatadir)/icons/hicolor/16x16
+ -rmdir $(DESTDIR)$(pkgdatadir)/icons/hicolor/24x24
+ rm -f $(DESTDIR)$(pkgdatadir)/icons/hicolor/index.theme
+ -rmdir $(DESTDIR)$(pkgdatadir)/icons/hicolor
+ -rmdir $(DESTDIR)$(pkgdatadir)/icons
+ -rmdir $(DESTDIR)$(pkgdatadir)/symbols
+ -rmdir $(DESTDIR)$(pkgdatadir)/skins
+ -rmdir $(DESTDIR)$(pkgdatadir)
+ rm -f $(DESTDIR)$(applicationsdir)/tilem2.desktop
+ rm -f $(DESTDIR)$(mimedir)/packages/tilem2.xml
+ [ -n "$(DESTDIR)" ] || $(UPDATE_DESKTOP_DATABASE) $(applicationsdir)
+ [ -n "$(DESTDIR)" ] || $(UPDATE_MIME_DATABASE) $(mimedir)
+
+Makefile: Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status
+
+$(top_builddir)/config.status: $(top_srcdir)/configure
+ cd $(top_builddir) && $(SHELL) ./config.status --recheck
+
+.PRECIOUS: Makefile $(top_builddir)/config.status
+.PHONY: all install uninstall
diff --git a/tool/tilem-src/data/desktop/tilem2.desktop b/tool/tilem-src/data/desktop/tilem2.desktop
new file mode 100644
index 0000000..8118c97
--- /dev/null
+++ b/tool/tilem-src/data/desktop/tilem2.desktop
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Name=TilEm
+Comment=Graphing calculator emulator
+Exec=tilem2 %F
+Icon=tilem
+MimeType=application/x-tigroup;application/x-ti73-variables;application/x-ti73-program;application/x-ti73-backup;application/x-ti73-app;application/x-ti73-os;application/x-ti81-program;application/x-ti82-variables;application/x-ti82-program;application/x-ti82-backup;application/x-ti83-variables;application/x-ti83-program;application/x-ti83-backup;application/x-ti83plus-variables;application/x-ti83plus-program;application/x-ti83plus-app;application/x-ti83plus-os;application/x-ti85-variables;application/x-ti85-program;application/x-ti85-backup;application/x-ti86-variables;application/x-ti86-program;application/x-ti86-backup;
+StartupNotify=true
+Terminal=false
+Type=Application
+Categories=Education;Science;Math;Emulator;
diff --git a/tool/tilem-src/data/desktop/tilem2.xml b/tool/tilem-src/data/desktop/tilem2.xml
new file mode 100644
index 0000000..7dae83c
--- /dev/null
+++ b/tool/tilem-src/data/desktop/tilem2.xml
@@ -0,0 +1,322 @@
+
+
+
+
+ TI calculator group file
+
+
+
+
+ TI-73 variable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TI-73 program
+
+
+
+
+
+
+
+
+
+
+
+ TI-73 memory backup
+
+
+
+
+
+
+
+
+
+
+ TI-73 Flash application
+
+
+
+
+
+
+
+
+ TI-73 operating system
+
+
+
+
+
+
+
+
+
+ TI-81 program
+
+
+
+
+
+
+
+ TI-82 variable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TI-82 program
+
+
+
+
+
+
+
+
+
+
+
+ TI-82 memory backup
+
+
+
+
+
+
+
+
+
+
+
+ TI-83 variable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TI-83 program
+
+
+
+
+
+
+
+
+
+
+
+ TI-83 memory backup
+
+
+
+
+
+
+
+
+
+
+
+ TI-83/84 Plus variable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TI-83/84 Plus program
+
+
+
+
+
+
+
+
+
+
+
+ TI-83/84 Plus Flash application
+
+
+
+
+
+
+
+
+ TI-83/84 Plus operating system
+
+
+
+
+
+
+
+
+
+ TI-85 variable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TI-85 program
+
+
+
+
+
+
+
+
+
+
+
+ TI-85 memory backup
+
+
+
+
+
+
+
+
+
+
+
+ TI-86 variable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TI-86 program
+
+
+
+
+
+
+
+
+
+
+
+ TI-86 memory backup
+
+
+
+
+
+
+
+
+
+
diff --git a/tool/tilem-src/data/icons-svg/breakpoint.svg b/tool/tilem-src/data/icons-svg/breakpoint.svg
new file mode 100644
index 0000000..e3c55fb
--- /dev/null
+++ b/tool/tilem-src/data/icons-svg/breakpoint.svg
@@ -0,0 +1,123 @@
+
+
+
+
diff --git a/tool/tilem-src/data/icons-svg/pc-arrow.svg b/tool/tilem-src/data/icons-svg/pc-arrow.svg
new file mode 100644
index 0000000..13874e3
--- /dev/null
+++ b/tool/tilem-src/data/icons-svg/pc-arrow.svg
@@ -0,0 +1,159 @@
+
+
+
+
diff --git a/tool/tilem-src/data/icons-svg/stepicons-16.svg b/tool/tilem-src/data/icons-svg/stepicons-16.svg
new file mode 100644
index 0000000..c89f3e4
--- /dev/null
+++ b/tool/tilem-src/data/icons-svg/stepicons-16.svg
@@ -0,0 +1,217 @@
+
+
+
+
diff --git a/tool/tilem-src/data/icons-svg/stepicons-24.svg b/tool/tilem-src/data/icons-svg/stepicons-24.svg
new file mode 100644
index 0000000..d4b9f4b
--- /dev/null
+++ b/tool/tilem-src/data/icons-svg/stepicons-24.svg
@@ -0,0 +1,389 @@
+
+
+
+
diff --git a/tool/tilem-src/data/icons/hicolor/16x16/actions/tilem-db-finish.png b/tool/tilem-src/data/icons/hicolor/16x16/actions/tilem-db-finish.png
new file mode 100644
index 0000000..bd51d31
Binary files /dev/null and b/tool/tilem-src/data/icons/hicolor/16x16/actions/tilem-db-finish.png differ
diff --git a/tool/tilem-src/data/icons/hicolor/16x16/actions/tilem-db-step-over.png b/tool/tilem-src/data/icons/hicolor/16x16/actions/tilem-db-step-over.png
new file mode 100644
index 0000000..19f79af
Binary files /dev/null and b/tool/tilem-src/data/icons/hicolor/16x16/actions/tilem-db-step-over.png differ
diff --git a/tool/tilem-src/data/icons/hicolor/16x16/actions/tilem-db-step.png b/tool/tilem-src/data/icons/hicolor/16x16/actions/tilem-db-step.png
new file mode 100644
index 0000000..4b8e1d7
Binary files /dev/null and b/tool/tilem-src/data/icons/hicolor/16x16/actions/tilem-db-step.png differ
diff --git a/tool/tilem-src/data/icons/hicolor/16x16/apps/tilem.png b/tool/tilem-src/data/icons/hicolor/16x16/apps/tilem.png
new file mode 100644
index 0000000..0023cd9
Binary files /dev/null and b/tool/tilem-src/data/icons/hicolor/16x16/apps/tilem.png differ
diff --git a/tool/tilem-src/data/icons/hicolor/16x16/status/tilem-disasm-break-pc.png b/tool/tilem-src/data/icons/hicolor/16x16/status/tilem-disasm-break-pc.png
new file mode 100644
index 0000000..35aaa06
Binary files /dev/null and b/tool/tilem-src/data/icons/hicolor/16x16/status/tilem-disasm-break-pc.png differ
diff --git a/tool/tilem-src/data/icons/hicolor/16x16/status/tilem-disasm-break.png b/tool/tilem-src/data/icons/hicolor/16x16/status/tilem-disasm-break.png
new file mode 100644
index 0000000..9e9dc33
Binary files /dev/null and b/tool/tilem-src/data/icons/hicolor/16x16/status/tilem-disasm-break.png differ
diff --git a/tool/tilem-src/data/icons/hicolor/16x16/status/tilem-disasm-pc.png b/tool/tilem-src/data/icons/hicolor/16x16/status/tilem-disasm-pc.png
new file mode 100644
index 0000000..e6c5594
Binary files /dev/null and b/tool/tilem-src/data/icons/hicolor/16x16/status/tilem-disasm-pc.png differ
diff --git a/tool/tilem-src/data/icons/hicolor/22x22/apps/tilem.png b/tool/tilem-src/data/icons/hicolor/22x22/apps/tilem.png
new file mode 100644
index 0000000..59a0a9b
Binary files /dev/null and b/tool/tilem-src/data/icons/hicolor/22x22/apps/tilem.png differ
diff --git a/tool/tilem-src/data/icons/hicolor/24x24/actions/tilem-db-finish.png b/tool/tilem-src/data/icons/hicolor/24x24/actions/tilem-db-finish.png
new file mode 100644
index 0000000..8eeb723
Binary files /dev/null and b/tool/tilem-src/data/icons/hicolor/24x24/actions/tilem-db-finish.png differ
diff --git a/tool/tilem-src/data/icons/hicolor/24x24/actions/tilem-db-step-over.png b/tool/tilem-src/data/icons/hicolor/24x24/actions/tilem-db-step-over.png
new file mode 100644
index 0000000..d78ffe4
Binary files /dev/null and b/tool/tilem-src/data/icons/hicolor/24x24/actions/tilem-db-step-over.png differ
diff --git a/tool/tilem-src/data/icons/hicolor/24x24/actions/tilem-db-step.png b/tool/tilem-src/data/icons/hicolor/24x24/actions/tilem-db-step.png
new file mode 100644
index 0000000..96b9f9d
Binary files /dev/null and b/tool/tilem-src/data/icons/hicolor/24x24/actions/tilem-db-step.png differ
diff --git a/tool/tilem-src/data/icons/hicolor/24x24/apps/tilem.png b/tool/tilem-src/data/icons/hicolor/24x24/apps/tilem.png
new file mode 100644
index 0000000..6e19b2a
Binary files /dev/null and b/tool/tilem-src/data/icons/hicolor/24x24/apps/tilem.png differ
diff --git a/tool/tilem-src/data/icons/hicolor/32x32/apps/tilem.png b/tool/tilem-src/data/icons/hicolor/32x32/apps/tilem.png
new file mode 100644
index 0000000..8014816
Binary files /dev/null and b/tool/tilem-src/data/icons/hicolor/32x32/apps/tilem.png differ
diff --git a/tool/tilem-src/data/icons/hicolor/48x48/apps/tilem.png b/tool/tilem-src/data/icons/hicolor/48x48/apps/tilem.png
new file mode 100644
index 0000000..852b196
Binary files /dev/null and b/tool/tilem-src/data/icons/hicolor/48x48/apps/tilem.png differ
diff --git a/tool/tilem-src/data/icons/hicolor/index.theme b/tool/tilem-src/data/icons/hicolor/index.theme
new file mode 100644
index 0000000..cbb495c
--- /dev/null
+++ b/tool/tilem-src/data/icons/hicolor/index.theme
@@ -0,0 +1,44 @@
+[Icon Theme]
+Name=hicolor
+Comment=Default Theme
+Directories=16x16/actions,16x16/apps,16x16/status,22x22/apps,24x24/actions,24x24/apps,32x32/apps,48x48/apps
+
+[16x16/actions]
+Size=16
+Context=Actions
+Type=Threshold
+
+[16x16/apps]
+Size=16
+Context=Applications
+Type=Threshold
+
+[16x16/status]
+Size=16
+Context=Status
+Type=Threshold
+
+[22x22/apps]
+Size=22
+Context=Applications
+Type=Threshold
+
+[24x24/actions]
+Size=24
+Context=Actions
+Type=Threshold
+
+[24x24/apps]
+Size=24
+Context=Applications
+Type=Threshold
+
+[32x32/apps]
+Size=32
+Context=Applications
+Type=Threshold
+
+[48x48/apps]
+Size=48
+Context=Applications
+Type=Threshold
diff --git a/tool/tilem-src/data/keybindings.ini b/tool/tilem-src/data/keybindings.ini
new file mode 100644
index 0000000..64f3583
--- /dev/null
+++ b/tool/tilem-src/data/keybindings.ini
@@ -0,0 +1,555 @@
+[common]
+Up = Up
+KP_Up = Up
+Down = Down
+KP_Down = Down
+Left = Left
+KP_Left = Left
+Right = Right
+KP_Right = Right
+Shift+Up = 2nd, Up
+Shift+Down = 2nd, Down
+Tab = 2nd
+KP_Tab = 2nd
+ISO_Left_Tab = 2nd
+Delete = Del
+KP_Delete = Del
+BackSpace = Left, Del
+Ctrl+BackSpace = Clear
+Ctrl+Delete = Clear
+Ctrl+KP_Delete = Clear
+0 = 0
+KP_0 = 0
+1 = 1
+KP_1 = 1
+2 = 2
+KP_2 = 2
+3 = 3
+KP_3 = 3
+4 = 4
+KP_4 = 4
+5 = 5
+KP_5 = 5
+6 = 6
+KP_6 = 6
+7 = 7
+KP_7 = 7
+8 = 8
+KP_8 = 8
+9 = 9
+KP_9 = 9
+period = DecPnt
+KP_Decimal = DecPnt
+asciitilde = Chs
+dead_tilde = Chs
+plusminus = Chs
+Shift+KP_Subtract = Chs
+dollar = 2nd, Chs
+plus = Add
+KP_Add = Add
+minus = Sub
+KP_Subtract = Sub
+asterisk = Mul
+KP_Multiply = Mul
+slash = Div
+KP_Divide = Div
+asciicircum = Power
+dead_circumflex = Power
+twosuperior = Square
+Ctrl+2 = Square
+parenleft = LParen
+parenright = RParen
+greater = Store
+less = 2nd, Store
+F12 = On
+Shift+F12 = 2nd, On
+Return = Enter
+KP_Enter = Enter
+ISO_Enter = Enter
+Shift+Return = 2nd, Enter
+Shift+KP_Enter = 2nd, Enter
+Shift+ISO_Enter = 2nd, Enter
+
+[ti73]
+INHERIT = common
+F1 = YEqu
+F2 = Window
+F3 = Zoom
+F4 = Trace
+F5 = Graph
+Shift+F1 = 2nd, YEqu
+Shift+F2 = 2nd, Window
+Shift+F3 = 2nd, Zoom
+Shift+F4 = 2nd, Trace
+Shift+F5 = 2nd, Graph
+Home = 2nd, Left
+End = 2nd, Right
+F11 = Mode
+Shift+Escape = 2nd, Mode
+Insert = 2nd, Del
+KP_Insert = 2nd, Del
+m = Math
+Menu = 2nd, Math
+apostrophe = 2nd, Math
+d = Draw
+l = List
+ampersand = 2nd, Power
+EuroSign = 2nd, Power
+F8 = Prgm
+p = Prgm
+Ctrl+Tab = 2nd, Prgm
+Ctrl+KP_Tab = 2nd, Prgm
+Ctrl+ISO_Left_Tab = 2nd, Prgm
+F7 = Apps
+Escape = Clear
+underscore = Unit
+bar = FracSlash
+brokenbar = FracSlash
+onehalf = FracSlash
+backslash = 2nd, FracSlash
+onesuperior = 2nd, FracSlash
+Ctrl+1 = 2nd, FracSlash
+f = FracDec
+numbersign = 2nd, FracDec
+a = MixSimp
+c = Const
+s = Simp
+percent = Percent
+x = VarX
+comma = Comma
+
+[ti76]
+INHERIT = common
+F1 = YEqu
+F2 = Window
+F3 = Zoom
+F4 = Trace
+F5 = Graph
+Shift+F1 = 2nd, YEqu
+Shift+F2 = 2nd, Window
+Shift+F3 = 2nd, Zoom
+Shift+F4 = 2nd, Trace
+Shift+F5 = 2nd, Graph
+Home = 2nd, Left
+KP_Home = 2nd, Left
+End = 2nd, Right
+KP_End = 2nd, Right
+F11 = Mode
+Shift+Escape = 2nd, Mode
+Insert = 2nd, Del
+KP_Insert = 2nd, Del
+Menu = Alpha
+apostrophe = Alpha
+x = Graphvar
+F10 = Stat
+F6 = Math
+F7 = Matrix
+F8 = Prgm
+F9 = Vars
+Escape = Clear
+backslash = Recip
+onesuperior = Recip
+Ctrl+1 = Recip
+s = Sin
+c = Cos
+t = Tan
+numbersign = 2nd, Power
+comma = Comma
+ampersand = 2nd, Comma
+EuroSign = 2nd, Comma
+braceleft = 2nd, LParen
+braceright = 2nd, RParen
+e = 2nd, Div
+o = Log
+u = 2nd, 7
+v = 2nd, 8
+w = 2nd, 9
+l = Ln
+p = Prgm
+Ctrl+Tab = 2nd, 0
+Ctrl+KP_Tab = 2nd, 0
+Ctrl+ISO_Left_Tab = 2nd, 0
+
+[ti81]
+INHERIT = common
+F1 = YEqu
+F2 = Range
+F3 = Zoom
+F4 = Trace
+F5 = Graph
+Shift+F1 = 2nd, YEqu
+Shift+F2 = 2nd, Range
+Shift+F3 = 2nd, Zoom
+Shift+F4 = 2nd, Trace
+Shift+F5 = 2nd, Graph
+Insert = Ins
+KP_Insert = Ins
+Menu = Alpha
+apostrophe = Alpha
+x = Graphvar
+F11 = Mode
+F6 = Math
+F7 = Matrix
+F8 = Prgm
+F9 = Vars
+Escape = Clear
+Shift+Escape = 2nd, Clear
+backslash = Recip
+onesuperior = Recip
+Ctrl+1 = Recip
+bar = 2nd, Recip
+brokenbar = 2nd, Recip
+s = Sin
+c = Cos
+t = Tan
+p = Prgm
+numbersign = 2nd, Power
+ampersand = EE
+EuroSign = EE
+o = Log
+l = Ln
+A = Alpha, Math
+B = Alpha, Matrix
+C = Alpha, Prgm
+D = Alpha, Recip
+E = Alpha, Sin
+F = Alpha, Cos
+G = Alpha, Tan
+H = Alpha, Power
+I = Alpha, Square
+J = Alpha, EE
+K = Alpha, LParen
+L = Alpha, RParen
+M = Alpha, Div
+N = Alpha, Log
+O = Alpha, 7
+P = Alpha, 8
+Q = Alpha, 9
+R = Alpha, Mul
+S = Alpha, Ln
+T = Alpha, 4
+U = Alpha, 5
+V = Alpha, 6
+W = Alpha, Sub
+X = Alpha, Store
+Y = Alpha, 1
+Z = Alpha, 2
+at = Alpha, 3
+quotedbl = Alpha, Add
+space = Alpha, 0
+comma = Alpha, DecPnt
+question = Alpha, Chs
+
+[ti82]
+INHERIT = common
+F1 = YEqu
+F2 = Window
+F3 = Zoom
+F4 = Trace
+F5 = Graph
+Shift+F1 = 2nd, YEqu
+Shift+F2 = 2nd, Window
+Shift+F3 = 2nd, Zoom
+Shift+F4 = 2nd, Trace
+Shift+F5 = 2nd, Graph
+Home = 2nd, Left
+KP_Home = 2nd, Left
+End = 2nd, Right
+KP_End = 2nd, Right
+F11 = Mode
+Shift+Escape = 2nd, Mode
+Insert = 2nd, Del
+KP_Insert = 2nd, Del
+Menu = Alpha
+apostrophe = Alpha
+x = Graphvar
+F10 = Stat
+F6 = Math
+F7 = Matrix
+F8 = Prgm
+F9 = Vars
+Escape = Clear
+backslash = Recip
+onesuperior = Recip
+Ctrl+1 = Recip
+bar = 2nd, Recip
+brokenbar = 2nd, Recip
+s = Sin
+c = Cos
+t = Tan
+numbersign = 2nd, Power
+comma = Comma
+ampersand = 2nd, Comma
+EuroSign = 2nd, Comma
+braceleft = 2nd, LParen
+braceright = 2nd, RParen
+o = Log
+u = 2nd, 7
+v = 2nd, 8
+n = 2nd, 9
+bracketleft = 2nd, Mul
+l = Ln
+p = Prgm
+bracketright = 2nd, Sub
+A = Alpha, Math
+B = Alpha, Matrix
+C = Alpha, Prgm
+D = Alpha, Recip
+E = Alpha, Sin
+F = Alpha, Cos
+G = Alpha, Tan
+H = Alpha, Power
+I = Alpha, Square
+J = Alpha, Comma
+K = Alpha, LParen
+L = Alpha, RParen
+M = Alpha, Div
+N = Alpha, Log
+O = Alpha, 7
+P = Alpha, 8
+Q = Alpha, 9
+R = Alpha, Mul
+S = Alpha, Ln
+T = Alpha, 4
+U = Alpha, 5
+V = Alpha, 6
+W = Alpha, Sub
+X = Alpha, Store
+Y = Alpha, 1
+Z = Alpha, 2
+at = Alpha, 3
+quotedbl = Alpha, Add
+space = Alpha, 0
+colon = Alpha, DecPnt
+question = Alpha, Chs
+
+[ti83]
+INHERIT = common
+F1 = YEqu
+F2 = Window
+F3 = Zoom
+F4 = Trace
+F5 = Graph
+Shift+F1 = 2nd, YEqu
+Shift+F2 = 2nd, Window
+Shift+F3 = 2nd, Zoom
+Shift+F4 = 2nd, Trace
+Shift+F5 = 2nd, Graph
+Home = 2nd, Left
+KP_Home = 2nd, Left
+End = 2nd, Right
+KP_End = 2nd, Right
+Page_Up = Alpha, Up
+KP_Page_Up = Alpha, Up
+Page_Down = Alpha, Down
+KP_Page_Down = Alpha, Down
+F11 = Mode
+Shift+Escape = 2nd, Mode
+Insert = 2nd, Del
+KP_Insert = 2nd, Del
+Menu = Alpha
+apostrophe = Alpha
+x = Graphvar
+F10 = Stat
+F6 = Math
+F7 = Matrix
+F8 = Prgm
+F9 = Vars
+Escape = Clear
+backslash = Recip
+onesuperior = Recip
+Ctrl+1 = Recip
+s = Sin
+c = Cos
+t = Tan
+numbersign = 2nd, Power
+comma = Comma
+ampersand = 2nd, Comma
+EuroSign = 2nd, Comma
+braceleft = 2nd, LParen
+braceright = 2nd, RParen
+e = 2nd, Div
+o = Log
+u = 2nd, 7
+v = 2nd, 8
+w = 2nd, 9
+p = Prgm
+bracketleft = 2nd, Mul
+l = Ln
+bracketright = 2nd, Sub
+Ctrl+Tab = 2nd, 0
+Ctrl+KP_Tab = 2nd, 0
+Ctrl+ISO_Left_Tab = 2nd, 0
+i = 2nd, DecPnt
+A = Alpha, Math
+B = Alpha, Matrix
+C = Alpha, Prgm
+D = Alpha, Recip
+E = Alpha, Sin
+F = Alpha, Cos
+G = Alpha, Tan
+H = Alpha, Power
+I = Alpha, Square
+J = Alpha, Comma
+K = Alpha, LParen
+L = Alpha, RParen
+M = Alpha, Div
+N = Alpha, Log
+O = Alpha, 7
+P = Alpha, 8
+Q = Alpha, 9
+R = Alpha, Mul
+S = Alpha, Ln
+T = Alpha, 4
+U = Alpha, 5
+V = Alpha, 6
+W = Alpha, Sub
+X = Alpha, Store
+Y = Alpha, 1
+Z = Alpha, 2
+at = Alpha, 3
+quotedbl = Alpha, Add
+space = Alpha, 0
+colon = Alpha, DecPnt
+question = Alpha, Chs
+
+[ti83p]
+INHERIT = ti83
+CapsLock+a = Alpha, Alpha, Math
+CapsLock+b = Alpha, Alpha, Apps
+CapsLock+c = Alpha, Alpha, Prgm
+CapsLock+d = Alpha, Alpha, Recip
+CapsLock+e = Alpha, Alpha, Sin
+CapsLock+f = Alpha, Alpha, Cos
+CapsLock+g = Alpha, Alpha, Tan
+CapsLock+h = Alpha, Alpha, Power
+CapsLock+i = Alpha, Alpha, Square
+CapsLock+j = Alpha, Alpha, Comma
+CapsLock+k = Alpha, Alpha, LParen
+CapsLock+l = Alpha, Alpha, RParen
+CapsLock+m = Alpha, Alpha, Div
+CapsLock+n = Alpha, Alpha, Log
+CapsLock+o = Alpha, Alpha, 7
+CapsLock+p = Alpha, Alpha, 8
+CapsLock+q = Alpha, Alpha, 9
+CapsLock+r = Alpha, Alpha, Mul
+CapsLock+s = Alpha, Alpha, Ln
+CapsLock+t = Alpha, Alpha, 4
+CapsLock+u = Alpha, Alpha, 5
+CapsLock+v = Alpha, Alpha, 6
+CapsLock+w = Alpha, Alpha, Sub
+CapsLock+x = Alpha, Alpha, Store
+CapsLock+y = Alpha, Alpha, 1
+CapsLock+z = Alpha, Alpha, 2
+
+[ti83pse]
+INHERIT = ti83p
+
+[ti84p]
+INHERIT = ti83p
+
+[ti84pse]
+INHERIT = ti83p
+
+[ti84pns]
+INHERIT = ti83p
+
+[ti85]
+INHERIT = common
+F1 = F1
+F2 = F2
+F3 = F3
+F4 = F4
+F5 = F5
+Shift+F1 = 2nd, F1
+Shift+F2 = 2nd, F2
+Shift+F3 = 2nd, F3
+Shift+F4 = 2nd, F4
+Shift+F5 = 2nd, F5
+Home = 2nd, Left
+KP_Home = 2nd, Left
+End = 2nd, Right
+KP_End = 2nd, Right
+Escape = Exit
+Shift+Escape = 2nd, Exit
+Page_Down = More
+KP_Page_Down = More
+F11 = 2nd, More
+Menu = Alpha
+apostrophe = Alpha
+Insert = 2nd, Del
+KP_Insert = 2nd, Del
+F6 = Graph
+F7 = Stat
+F8 = Prgm
+F9 = Custom
+Ctrl+Tab = 2nd, Custom
+Ctrl+KP_Tab = 2nd, Custom
+Ctrl+ISO_Left_Tab = 2nd, Custom
+numbersign = 2nd, Power
+ampersand = EE
+EuroSign = EE
+backslash = 2nd, EE
+onesuperior = 2nd, EE
+Ctrl+1 = 2nd, EE
+bracketleft = 2nd, LParen
+bracketright = 2nd, RParen
+comma = Comma
+colon = 2nd, DecPnt
+A = Alpha, Log
+B = Alpha, Sin
+C = Alpha, Cos
+D = Alpha, Tan
+E = Alpha, Power
+F = Alpha, Ln
+G = Alpha, EE
+H = Alpha, LParen
+I = Alpha, RParen
+J = Alpha, Div
+K = Alpha, Square
+L = Alpha, 7
+M = Alpha, 8
+N = Alpha, 9
+O = Alpha, Mul
+P = Alpha, Comma
+Q = Alpha, 4
+R = Alpha, 5
+S = Alpha, 6
+T = Alpha, Sub
+U = Alpha, 1
+V = Alpha, 2
+W = Alpha, 3
+X = Alpha, Add
+Y = Alpha, 0
+Z = Alpha, DecPnt
+space = Alpha, Chs
+equal = Alpha, Store
+a = 2nd, Alpha, Log
+b = 2nd, Alpha, Sin
+c = 2nd, Alpha, Cos
+d = 2nd, Alpha, Tan
+e = 2nd, Alpha, Power
+f = 2nd, Alpha, Ln
+g = 2nd, Alpha, EE
+h = 2nd, Alpha, LParen
+i = 2nd, Alpha, RParen
+j = 2nd, Alpha, Div
+k = 2nd, Alpha, Square
+l = 2nd, Alpha, 7
+m = 2nd, Alpha, 8
+n = 2nd, Alpha, 9
+o = 2nd, Alpha, Mul
+p = 2nd, Alpha, Comma
+q = 2nd, Alpha, 4
+r = 2nd, Alpha, 5
+s = 2nd, Alpha, 6
+t = 2nd, Alpha, Sub
+u = 2nd, Alpha, 1
+v = 2nd, Alpha, 2
+w = 2nd, Alpha, 3
+x = 2nd, Alpha, Add
+y = 2nd, Alpha, 0
+z = 2nd, Alpha, DecPnt
+
+[ti86]
+INHERIT = ti85
diff --git a/tool/tilem-src/data/skins/README b/tool/tilem-src/data/skins/README
new file mode 100644
index 0000000..4b4028d
--- /dev/null
+++ b/tool/tilem-src/data/skins/README
@@ -0,0 +1,45 @@
+** About the format : **
+
+When I started to work on tilem 2, I firstly decided to use the old tilem format (4 pixs around a lcd).
+But that's not a good idea, and the new skin creation is too hard like this ... :(
+
+Finally, we (with Benjamin) have choosen the Tiemu skin format:
+This format consists in a binary file containing skin information (author, name, model, size etc...) and in the second part :the image data.
+With this format, it becomes really simple and fun to create a skin.
+Tiemu Skinedit works perfectly for tilem 2 (how do you think I 've created these "officials skins :P).
+I hope this new format will pleased to you.
+
+Thank you Julien Blache for his help and his authorization to use Tiemu skin format and skinops.c/skinops.h files.
+Thank you Romain Lievin too.
+
+
+
+** About the image source : **
+
+To find free files to generate skins is not so easy :|
+A part was found on wikimedia (god bless wikimedia)
+Some other are created and donated by tilem2 users :)
+Some other are just my own calc.
+
+For the source of the pictures :
+ti81.skn = GFDL wikimedia.commons
+ti82.skn = GFDL wikimedia.commons
+TI82stats.skn = GFDL wikimedia.commons
+ti83.skn = My TI83 !!!
+ti83p.skn = GFDL wikimedia.commons
+ti83pfr.skn = GPL v3+ given by Claude Clerc (aka claudiux). It's his calc. Thanks to him !!!
+ti84p.skn = My TI84plus !!!
+ti84p2.skn = Mine.
+ti86.skn = LGPL v2.1. Picture given by Danilo Segan. I've resized with the gimp and I've done the skin (the skin given by Danilo was perfect but too big).Thanks to him !!!
+...
+...
+Your contribution ...
+Your contribution ...
+Your contribution ...
+...
+...
+...
+
+Have fun with tilem 2 ;)
+
+Thibault Duponchelle (aka contra-sh)
diff --git a/tool/tilem-src/data/skins/ti76.skn b/tool/tilem-src/data/skins/ti76.skn
new file mode 100644
index 0000000..2f5958b
Binary files /dev/null and b/tool/tilem-src/data/skins/ti76.skn differ
diff --git a/tool/tilem-src/data/skins/ti81.skn b/tool/tilem-src/data/skins/ti81.skn
new file mode 100644
index 0000000..6c1ab92
Binary files /dev/null and b/tool/tilem-src/data/skins/ti81.skn differ
diff --git a/tool/tilem-src/data/skins/ti82.skn b/tool/tilem-src/data/skins/ti82.skn
new file mode 100644
index 0000000..6d3a080
Binary files /dev/null and b/tool/tilem-src/data/skins/ti82.skn differ
diff --git a/tool/tilem-src/data/skins/ti82stats.skn b/tool/tilem-src/data/skins/ti82stats.skn
new file mode 100644
index 0000000..e89827b
Binary files /dev/null and b/tool/tilem-src/data/skins/ti82stats.skn differ
diff --git a/tool/tilem-src/data/skins/ti83.skn b/tool/tilem-src/data/skins/ti83.skn
new file mode 100644
index 0000000..6cbbe6b
Binary files /dev/null and b/tool/tilem-src/data/skins/ti83.skn differ
diff --git a/tool/tilem-src/data/skins/ti83p.skn b/tool/tilem-src/data/skins/ti83p.skn
new file mode 100644
index 0000000..5c97529
Binary files /dev/null and b/tool/tilem-src/data/skins/ti83p.skn differ
diff --git a/tool/tilem-src/data/skins/ti83pfr.skn b/tool/tilem-src/data/skins/ti83pfr.skn
new file mode 100644
index 0000000..0866be2
Binary files /dev/null and b/tool/tilem-src/data/skins/ti83pfr.skn differ
diff --git a/tool/tilem-src/data/skins/ti84p.skn b/tool/tilem-src/data/skins/ti84p.skn
new file mode 100644
index 0000000..c58d544
Binary files /dev/null and b/tool/tilem-src/data/skins/ti84p.skn differ
diff --git a/tool/tilem-src/data/skins/ti84p2.skn b/tool/tilem-src/data/skins/ti84p2.skn
new file mode 100644
index 0000000..5913805
Binary files /dev/null and b/tool/tilem-src/data/skins/ti84p2.skn differ
diff --git a/tool/tilem-src/data/skins/ti86.skn b/tool/tilem-src/data/skins/ti86.skn
new file mode 100644
index 0000000..3377aeb
Binary files /dev/null and b/tool/tilem-src/data/skins/ti86.skn differ
diff --git a/tool/tilem-src/data/symbols/ti82.sym b/tool/tilem-src/data/symbols/ti82.sym
new file mode 100644
index 0000000..4c8afd0
--- /dev/null
+++ b/tool/tilem-src/data/symbols/ti82.sym
@@ -0,0 +1,939 @@
+[macros]
+0CD748D ROM_CALL~%j
+
+[labels]
+0008 rOP1TOOP2
+0010 rFINDSYM
+0018 rPUSHREALO1
+0020 rMOV9TOOP1
+0028 rFPMULT
+0030 rFPADD
+0033 _LdHLind
+004F _SetTblGraphDraw
+0095 _CpHLDE
+00A1 _DivHLBy10
+00A3 _DivHLByA
+
+012B _ApdSetup
+0131 _KbdScan
+01B8 _KEY_READ
+01C7 _STORE_KEY
+01D4 _GetCSC
+01E8 _CanAlphIns
+020D _coorMon
+0213 _Mon
+0220 _MonForceKey
+02B5 _sendKPress
+033C _JForceCmdNoChar
+033D _JForceCmd
+0355 _resetStacks
+0368 _sysErrHandler
+0374 _newContext
+0385 _newContext0
+0462 _PPutAwayPrompt
+046D _PPutAway
+0473 _PutAway
+04B4 _Redisp
+04B9 _SizeWind
+04CA _ErrorEP
+04DC _callMain
+04ED _monErrHand
+
+10C2 _SinCosRad
+10C6 _Sin
+10CA _Cos
+10CE _Tan
+14AA _SinHCosH
+14AE _TanH
+14B2 _CosH
+14B6 _SinH
+154D _ACosRad
+1553 _ATanRad
+1556 _ATan2Rad
+1558 _ATan2Rad_83
+155E _ASinRad
+1563 _ACos
+156D _ATan
+15CD _ATan2_83
+1570 _ATan2
+1575 _ASin
+1787 _ATanH
+17D4 _ASinH
+17E2 _ACosH
+18E7 _HLTimes9
+18F1 _CkOP1Real
+18F7 _Angle
+18FF _CpOP4OP3
+1907 _Mov9OP2Cp
+190C _AbsO1O2Cp
+1912 _CpOP1OP2
+1955 _OP3ToOP4
+195E _OP1ToOP4
+1967 _OP2ToOP4
+1970 _OP4ToOP2
+1979 _OP3ToOP2
+1981 _OP1ToOP3
+1989 _OP5ToOP2
+1991 _OP5ToOP6
+1999 _OP5ToOP4
+19A1 _OP1ToOP2
+19A9 _OP6ToOP2
+19B1 _OP6ToOP1
+19B6 _OP4ToOP1
+19BB _OP5ToOP1
+19C0 _OP3ToOP1
+19C5 _OP4ToOP5
+19CD _OP3ToOP5
+19D5 _OP2ToOP5
+19DD _OP2ToOP6
+19E5 _OP1ToOP6
+19ED _OP1ToOP5
+19F5 _OP2ToOP1
+19FB _Mov11B
+19FD _Mov10B
+19FF _Mov9B
+1A01 _Mov8B
+1A03 _Mov7B
+1A05 _Mov6B
+1A07 _Mov5B
+1A09 _Mov4B
+1A0B _Mov3B
+1A0D _Mov2B
+1A54 _OP2ToOP3
+1A5C _OP4ToOP3
+1A61 _OP5ToOP3
+1A66 _OP4ToOP6
+1A6E _Mov9ToOP1
+1A73 _Mov9OP1OP2
+1A74 _Mov9ToOP2
+1A79 _MovFrOP1
+1A7E _OP4Set1
+1A83 _OP3Set1
+1A88 _OP2Set8
+1A8F _OP2Set5
+1A96 _OP2Set4
+1A9D _OP2Set3
+1AA5 _OP1Set1
+1AAA _OP1Set4
+1AB1 _OP1Set3
+1AB8 _OP3Set2
+1ABD _OP1Set2
+1AC2 _OP2Set2
+1AC5 _SetNum2
+1AC9 _SetMant1
+1ACD _OP2Set1
+1AD0 _SetNum1
+1AD2 _SetNum
+1AD7 _SetNumA
+1AD8 _SetMant
+1ADC _Zero16D
+1ADD _Set16A
+1ADE _Set14A
+1ADF _Set14D
+1AED _OP4Set0
+1AF2 _OP3Set0
+1AF7 _OP2Set0
+1AFC _OP1Set0
+1AFF _SetNum0
+1B07 _ZeroOP1
+1B0C _ZeroOP2
+1B11 _ZeroOP3
+1B14 _ZeroOP
+1B1C _ClrLp
+1B23 _ShRAcc
+1B2B _ShLAcc
+1B39 _ShR18
+1B3A _ShR18A
+1B42 _ShR16
+1B43 _ShR16A
+1B46 _ShR14
+1B76 _ShL16
+1B7A _ShL14
+1C2D _Add16D
+1C33 _Add14D
+1CA2 _Sub16D
+1CA8 _Sub14D
+1CEB _OP2ExOP6
+1CF0 _OP5ExOP6
+1CF8 _OP1ExOP5
+1CFD _OP1ExOP6
+1D02 _OP2ExOP4
+1D07 _OP2ExOP5
+1D0F _OP1ExOP3
+1D14 _OP1ExOP4
+1D19 _OP1ExOP2
+1D21 _ExLp
+1D2B _CkOP1FP0
+1D30 _CkOP2FP0
+1D39 _PosNo0Int
+1D3F _CkPosInt
+1D48 _CkInt
+1D4F _CkOdd
+1DD5 _GetCon1
+1DDA _GetCon
+1E48 _ExpToHex
+1E52 _OP1ExpToDec
+1E9A _CkOP2Pos
+1EA0 _CkOP1Pos
+1EA6 _ClrOP2S
+1EAB _ClrOP1S
+1EB2 _FDiv100
+1EB5 _FDiv10
+1EC0 _DecO1Exp
+1EC8 _IncO1Exp
+1ECB _IncExp
+1ED0 _CkValidNum
+1EF2 _GetExp
+1EFE _HTimesL
+1F0F _EOP1NotReal
+1F16 _PrgmBangName
+1F1B _PrgmPoundName
+1F3E _ThetaName
+1F42 _RName
+1F46 _RegEqName
+1F4C _RecurNName
+1F57 _XName
+1F5B _YName
+1F5F _TName
+1F61 _RealName
+1F6A _SetEStoFPS
+1F71 _ChkTempDirt
+1F94 _OP1MOP2Exp
+1F9E _OP1ExpMDE
+1FB2 _ChkErrBreak
+1FCC _IsA2ByteTok
+1FE3 _GetLastEntry
+1FFE _GetLastEntryPtr
+2014 _REGRCLRCHNG
+2057 _CheckSplitFlag
+2083 _ResetWinTop
+209C _SetYUp
+20A6 _SetXUp
+20AB _MemChk
+20BD _CmpPrgNamLen1
+20C0 _CmpPrgNamLen
+20D1 _FindProgSym
+2124 _ChkFindSym
+2129 _FindSym
+2258 _InsertMem
+2262 _InsertMemA
+227D _EnoughMem
+22AE _CmpMemNeed
+22C3 _CreatePVar4
+22E2 _CreatePVar3
+230F _CreateVar3
+2333 _CreateReal
+2339 _CreateTRList
+233F _CreateRList
+235B _CreateTRMat
+2361 _CreateRMat
+2369 _CreateTStrng
+236F _CreateStrng
+237D _Create0Equ
+2382 _CreateTEqu
+2388 _CreateEqu
+238C _CreatePict
+2393 _CreateGDB
+2397 _CreateProg
+239B _ChkDel
+23A4 _ChkDelA
+23DF _AdjParser
+2400 _AdjMath
+2455 _AdjM7
+2531 _DelMemA
+2547 _DelVar
+2548 _DelVarIO
+258D _DelMem
+2590 _DelVar3D
+2593 _DelVar3C
+25BB _DelVar3DC
+2612 _AdjSymPtrs
+2695 _DataSizeA
+2699 _DataSize
+26C1 _PopRealO6
+26C6 _PopRealO5
+26CB _PopRealO4
+26D0 _PopRealO3
+26D5 _PopRealO2
+26DA _PopRealO1
+26DD _PopReal
+26E3 _FPopCplx
+26E6 _FPopReal
+26E9 _FPopFPS
+26F1 _DeallocFPS
+26F4 _DeallocFPS1
+26FF _AllocFPS
+2702 _AllocFPS1
+270B _PushRealO6
+2710 _PushRealO5
+2715 _PushRealO4
+271A _PushRealO3
+271F _PushRealO2
+2724 _PushRealO1
+2727 _PushReal
+273B _CpyTo1FPS11
+273E _CpyFPS11
+2745 _CpyTo1FPS5
+2748 _CpyFPS5
+274F _CpyTo1FPS6
+2752 _CpyFPS6
+2759 _CpyTo2FPS4
+275C _CpyFPS4
+2763 _CpyTo6FPS3
+2768 _CpyTo2FPS3
+276D _CpyTo1FPS3
+2770 _CpyFPS3
+277C _CpyTo3FPS2
+2783 _CpyTo5FPST
+2788 _CpyTo6FPST
+278D _CpyTo4FPST
+2792 _CpyTo3FPST
+2797 _CpyTo2FPST
+279C _CpyTo1FPST
+279F _CpyFPST
+27A4 _CpyStack
+27AB _CpyTo3FPS1
+27B0 _CpyTo2FPS1
+27B5 _CpyTo1FPS1
+27B8 _CpyFPS1
+27BF _CpyTo2FPS2
+27C4 _CpyTo1FPS2
+27C7 _CpyFPS2
+27CE _CpyO3ToFPST
+27D3 _CpyO2ToFPST
+27D8 _CpyO6ToFPST
+27DD _CpyO1ToFPST
+27E0 _CpyToFPST
+27E5 _CpyToStack
+27ED _CpyO5ToFPS1
+27F2 _CpyO1ToFPS1
+27F5 _CpyToFPS1
+27FC _CpyO2ToFPS2
+2801 _CpyO3ToFPS2
+2806 _CpyO6ToFPS2
+280B _CpyO1ToFPS2
+280E _CpyToFPS2
+2815 _CpyO5ToFPS3
+281A _CpyO1ToFPS3
+281D _CpyToFPS3
+2824 _CpyO1ToFPS4
+2827 _CpyToFPS4
+282E _ErrNotEnoughMem
+283D _FPSMinus9
+2840 _HLMinus9
+2845 _ErrOverflow
+2849 _ErrDivBy0
+284D _ErrSingularMat
+2851 _ErrDomain
+2855 _ErrIncrement
+2859 _ErrSyntax
+285D _ErrMode
+2861 _ErrDataType
+2865 _ErrReserved
+2869 _ErrArgument
+286D _ErrDimMismatch
+2871 _ErrDimension
+2875 _ErrUndefined
+2879 _ErrMemory
+287D _ErrMemoryNE
+2881 _ErrInvalid
+2885 _ErrIllegalNest
+2889 _ErrBound
+288D _ErrGraphRange
+2891 _ErrZoom
+2895 _ErrBreak
+2899 _ErrStat
+289D _ErrSolver
+28A1 _ErrIterations
+28A5 _ErrBadGuess
+28A9 _ErrTolTooSmall
+28AD _ErrStatPlot
+28B1 _ErrLink
+28B3 _JError
+28B6 _JErrorNo
+28DC _noErrorEntry
+28DD _pushErrorHandler
+2903 _popErrorHandler
+2913 _StrLength
+2926 _StrCopy
+292E _StrCat
+295B _IsInSet
+
+2E46 ___bank_call
+2E6D ___bank_ret
+2E75 ___bank_jump
+
+2E86 _PutTokString
+# 2E8C _DispYPrompt2 ?
+2E92 _SetupDispEq
+2E98 _BufPeek2
+2EAA _CloseEquField
+2EB0 _BufToBtm
+2EB6 _CursorLeft
+2EBC _SetEmptyEditEqu
+# 2ECE DOREFFLAGS02 ?
+2EEC _PrevEq
+2EF2 _DarkLine
+2F1C _CursorDown
+2F22 _JPromptCursor
+2F34 _GrphPars
+2F3A _PlotPars
+2F40 _ParseInp
+2F46 _InitPFlgs
+2F4C _OP2Set60
+2F58 _StoTheta
+2F5E _StoR
+2F64 _StoY
+2F6A _StoT
+2F70 _StoX
+2F7C _RclAns
+2F82 _RclY
+2F88 _StMatEl
+2F8E _StLstVecEl
+2F94 _GetDEPtr
+2FA0 _WScrollRight
+2FA6 _WScrollLeft
+2FAC _WScrollUp
+2FB8 _RclToQueue
+2FBE _FORSEQINIT
+2FC4 _PDspGrph
+2FCA _GRDECODA
+2FDC _XYCent
+2FE2 _ZmInt
+2FE8 _CopyRng
+2FEE _ZooDefault
+2FF4 _ZmTrig
+# 2FFA _ZmFit ?
+# 3000 _ZmPrev ?
+# 3006 _ZmDecml ?
+# 300C _ZmUsr ?
+# 3012 _SetUZm ?
+# 3024 _DrawCmd ?
+302A _InvCmd
+3030 _TraceOff
+304E _FNDDB
+3054 _NextEq
+305A _SetFuncM
+3060 _SetPolM
+3066 _SetParM
+306C _SetSeqM
+307E _TanLnF
+# 3084 _ShadeCmd ?
+309C _PointCmd
+30A2 _PixelCmd
+30A8 _ChkTextCurs
+30AE _FormToTok
+30B4 _GDispToken
+30BA _UnLineCmd
+30C0 _LineCmd
+30CC _VertCmd
+30D2 _HorizCmd
+30DE _FormERealTok
+30F0 _RclSysTok
+30F6 _FormEReal
+30FC _OP1toEdit
+310E _IsAtTop
+3114 _ToggleIns
+311A _BufReplace
+3120 _StoSysTok
+3126 _SetupEditEqu
+3132 _RecallEd
+313E _SetupBuffer
+3144 _CreateNumEditBuf
+314A _CallCommon
+3150 _CommonKeys
+3156 _Leftmore
+315C _fDel
+3162 _fClear
+3168 _fInsDisp02
+3180 _CloseEditBufNoR
+3186 _ReleaseBuffer
+31AA _numError02
+31B0 _SetupEditCmd
+31B6 _CursorToOffset
+31BC _RstGFlags
+31C2 _RclVarToEdit
+31C8 _BufInsert
+31CE _BufToTop
+31DA _IsEditEmpty
+31E6 _DisarmScroll
+31EC _SetEmptyEditPtr
+31F2 _FormDisp
+3216 _JCursorRight
+321C _JCursorUp
+3228 _JCursorFirst
+322E _JCursorLast
+323A _BufDelete
+3258 _RclEntryToEdit
+325E _InsDisp
+3270 _RclVarToEditPtr
+3276 _FormScrollUp
+327C _FormMatrix
+3294 _FormReal
+32D4 _DispTail
+3312 _RclX
+3318 _SaveParse
+331E _GetParse
+3330 _CpyTo2ES1
+3336 _CpyTo6ES1
+333C _CpyTo1ES1
+3342 _CpyTo3ES1
+3348 _CpyTo3ES2
+334E _CpyTo2ES2
+3354 _CpyTo1ES2
+335A _CpyTo2ES3
+3360 _CpyTo1ES3
+3366 _CpyTo3ES4
+336C _CpyTo6ES4
+3372 _CpyTo2ES4
+3378 _CpyTo1ES4
+337E _CpyTo2ES5
+3384 _CpyTo1ES5
+338A _CpyTo4EST
+3390 _CpyTo2EST
+3396 _CpyTo1EST
+339C _CpyTo2ES6
+33A2 _CpyTo1ES6
+33A8 _CpyTo2ES7
+33AE _CpyTo1ES7
+33B4 _CpyTo2ES8
+33BA _CpyTo1ES8
+33C0 _CpyTo1ES9
+33C6 _CpyTo2ES9
+33CC _CpyTo2ES10
+33D2 _CpyTo1ES10
+33D8 _CpyES10
+33DE _CpyTo2ES11
+33E4 _CpyTo1ES11
+33EA _CpyTo2ES12
+33F0 _CpyTo1ES12
+33F6 _CpyTo2ES13
+33FC _CpyTo1ES13
+3402 _CpyTo1ES14
+3408 _CpyTo1ES16
+340E _CpyTo1ES17
+3414 _CpyTo1ES18
+341A _CpyTo1ES15
+3420 _CpyTo2ES15
+3426 _CpyO1ToEST
+342C _CpyO1ToES1
+3432 _CpyO6ToES1
+3438 _CpyO6ToES4
+343E _CpyO1ToES2
+3444 _CpyO2ToES2
+344A _CpyO1ToES3
+3450 _CpyO1ToES4
+3456 _CpyO1ToES5
+345C _CpyO1ToES6
+3462 _CpyO1ToES7
+3468 _CpyO2ToES1
+346E _CpyO2ToES4
+3474 _CpyO2ToES7
+347A _CpyO1ToES8
+3480 _CpyO1ToES9
+3486 _CpyO1ToES10
+348C _CpyO1ToES11
+3492 _CpyO1ToES12
+3498 _CpyO1ToES13
+349E _CpyO1ToES14
+34A4 _CpyO1ToES15
+34AA _PixelTest
+# 34BC _DFMIN2 ?
+3504 _RestoreErrNo
+3516 _StoN
+351C _ParseOff
+3522 _RclN
+354C _Random
+3552 _StoRand
+3558 _GetL3TOP1A
+355E _GetL1ToOP1
+3564 _GetL1TOP1A
+356A _GetLToOP1
+3570 _GetLToOP2
+3576 _GetL2TOP1A
+3582 _PutToLA1
+3588 _PutToL
+35A0 _ConvOP1
+35AC _GetM1ToOP1A
+35B2 _GetMToOP1
+35B8 _PutToM1A
+35BE _PutToMA1
+35C4 _PutToMat
+35D0 _AdrMEle
+35D6 _AdrLEle
+35DC _RclVarSym
+35E2 _StoOther
+35E8 _RedimMat
+35EE _IncLstSize
+35F4 _InsertList
+35FA _DelListEl
+3600 _EditProg
+3606 _CloseProg
+360C _ClrGraphRef
+3612 _FixTempCnt
+3618 _SaveData
+361E _RestoreData
+3624 _CleanAll
+362A _MoveToNextSym
+3630 _DispErrorScreen
+3660 _GrRedisp
+3690 _FindAlphaUp
+3696 _FindAlphaDn
+369C _RestoreDisp
+36A2 _LoadMenuNum
+36A8 _LoadMenuNumL
+36AE _RstrSmallText
+36B4 _ConvKeyToTok
+36BA _GrLabels
+36CC _NBCursor
+36D2 _IsEditFull
+36D8 _IsAtBtm
+36DE _ShowCursor
+36E4 _BufLeft
+36EA _BufPeek
+36F0 _BufRight
+36F6 _FDispBOL
+36FC _FDispBOL1
+3702 _SetWinAbove
+3708 _GetPrevTok
+370E _StringWidth
+371A _DispEOW
+3720 _BufPeek1
+372C _BufPeek3
+3732 _ReadDisp2
+3738 _PutMap
+373E _PutPS
+3744 _WPutPS
+374A _PutBuf
+3750 _PutBuf1
+3756 _WPutC
+375C _WPutS
+3762 _WPutSEOL
+3768 _WHomeUp
+376E _SetNumWindow
+377A _NewLine
+3780 _MoveDown
+3786 _ScrollUp
+3792 _ShrinkWindow
+3798 _MoveUp
+379E _ScrollDown
+37A4 _ClrScrnFull
+37AA _ClrTxtShd
+37B6 _EraseEOL
+37C8 _GetCurLoc
+37CE _VPutMap
+37D4 _VPutS
+37DA _VPutSNG
+37E0 _SaveCmdShadow
+37EC _SaveShadow
+37F8 _RstrShadow
+37FE _RstrCurRow
+3804 _RstrUnderMenu
+380A _RstrBotRow
+3810 _SaveTR
+3816 _RestoreTR
+381C _GetTokLen
+3822 _GetTokString
+3828 _PUTBPATBUF2
+382E _PUTBPATBUF
+3834 _putbPAT
+383A _putcCheckScroll
+3840 _DispEOL
+3846 _FDispEOL
+384C _TblScreenDn
+3852 _TblScreenUp
+3858 _TOTOSTRP
+385E _SetVarName
+386A _DispDone
+3870 _FinishOutput
+3876 _ClrLCD
+387C _DispHL
+3894 _CreateTemp
+389A _ClrLCDFull
+38A0 _LoadNoEEntry
+38AC _GrBufCpy
+38BE _AbortPrgmode
+38CA _ClrScrn
+38E2 _StoAns
+38E8 _GrReset
+38F4 _RandInit
+38FA _PutS
+3900 _HomeUp
+3912 _CoorDisp
+3918 _RunIndicOff
+391E _CursorOn
+3924 _GetKey
+392A _BlinkGCur
+3930 _RunIndicOn
+# 3936 _PullDownChk ?
+393C _TokToKey
+3942 _GrPutAway
+3948 _PopCx
+39C6 _SaveOScreen
+39CC _CurBlink
+39D2 _PutC
+
+## note: following ROM calls are not correctly handled by
+## SNG on ROM 19.006
+
+31E0 _CloseEditEqu
+3246 _DispHead
+324C _BufClear
+32BE _Send1BErr
+# 32C4
+# 32CA
+# 32D0
+# 32D6
+32DC _KeyScnLnk
+37B0 _ClrWindow
+37C2 _EraseEOW
+38B8 _RstrPartial
+38C4 _HideCursor
+38D6 _LCD_DriverOn
+38DC _RstrOScreen
+390C _CursorOff
+
+## note: following ROM calls are not correctly handled by
+## SNG on ROM 19.0
+
+050C _AppInit
+0684 _initialize
+07F3 _LCD_BUSY
+0801 _Min
+080A _Max
+0818 _AbsO1PAbsO2
+0820 _Intgr
+0836 _Trunc
+083A _InvSub
+083F _Times2
+0842 _Plus1
+0847 _Minus1
+084A _FPSub
+0851 _FPAdd
+0905 _DToR
+090E _RToD
+0917 _Cube
+091C _TimesPt5
+0924 _FPSquare
+0925 _FPMult
+
+## note: following ROM calls are not correctly handled by
+## any current shells on ROM 19.0
+
+0A1B _LJRnd
+0A5D _InvOP1S
+0A6D _InvOP2S
+0A83 _Frac
+0AD0 _FPRecip
+0AD4 _FPDiv
+0BA1 _SqRoot
+0C69 _Int
+0C6B _Round
+0C4F _RndGuard
+# 0CDF _Factorial ?
+0D27 _LnX
+0D2B _LogX
+0E63 _LJNoRnd
+0F03 _EToX
+0F0D _TenX
+
+8000 kbdScanCode
+8001 kbdLGSC
+8002 kbdPSC
+8003 kbdWUR
+8004 kbdDebncCnt
+8005 kbdKey
+8006 kbdGetKy
+8007 keyExtend
+8008 contrast
+8009 apdSubTimer
+800A apdTimer
+800B curTime
+800C curRow
+800D curCol
+800E curUnder
+800F curY
+# 8010 curType ?
+8011 curXRow
+# 801A tokVarPtr ?
+# 801C tokLen ?
+801E indicMem
+8026 indicCounter
+8027 indicBusy
+8028 OP1
+8033 OP2
+803E OP3
+8049 OP4
+8054 OP5
+805F OP6
+806A progToEdit
+8072 nameBuff
+807D iMathPtr1
+807F iMathPtr2
+8081 iMathPtr3
+8083 iMathPtr4
+8085 iMathPtr5
+8087 chkDelPtr1
+8089 chkDelPtr2
+808B insDelPtr
+808D upDownPtr
+808F textShadow
+810F textShadCur
+8111 textShadTop
+8112 textShadAlph
+8113 textShadIns
+8114 cxMain
+8116 cxPPutAway
+8118 cxPutAway
+811A cxRedisp
+811C cxErrorEP
+811E cxSizeWind
+8120 cxPage
+8121 cxCurApp
+8122 cxPrev
+8131 monQH
+8132 monQT
+# 8133 monQueue ?
+8143 onSP
+8145 onCheckSum
+8161 menuActive
+8163 menuCurrent
+81F0 ioFlag
+81F2 sndRecState
+81F3 ioErrState
+81F4 header
+81FD ioData
+8209 bakHeader
+8215 penCol
+8216 penRow
+8217 rclQueue
+8219 errNo
+821A errSP
+821C errOffset
+8228 saveSScreen
+8528 flags
+8549 curGStyle
+854A curGY
+854B curGX
+854C curGY2
+854D curGX2
+# 8551 XOffset ?
+# 8552 YOffset ?
+8553 lcdTallP
+8554 pixWideP
+8557 lastEntryStk
+85D7 numLastEntries
+85D8 currLastEntry
+# 85E1 ORGXMIN ?
+8691 Xmin
+86AC Ymin
+874E deltaX
+8757 deltaY
+8760 shortX
+8769 shortY
+8774 XOutDat
+8778 YOutDat
+# 877A inputSym ?
+877C inputDat
+88AE ES
+88B8 plotSScreen
+8BB8 seed1
+8BC1 seed2
+8BCA parseVar
+8BD3 begPC
+8BD5 curPC
+8BD7 endPC
+8BDF cmdShadow
+8C5F cmdShadCur
+8C65 editTop
+8C67 editCursor
+8C69 editTail
+8C6B editBtm
+8C71 editSym
+# 8C73 editDat ?
+8C8D modePtr
+8C8F winTop
+8C90 winBtm
+8C91 winLeftEdge
+8C92 winLeft
+8C94 winAbove
+8C96 winRow
+8C98 winCol
+8C9A fmtDigits
+8CF2 fmtMatSym
+8CF4 fmtMatMem
+# 8CF6 EQS ?
+8CFF delAdjAmt
+8D06 chkDelPtr3
+8D08 chkDelPtr4
+8D0A tempMem
+8D0C fpBase
+8D0E FPS
+8D10 OPBase
+8D12 OPS
+8D14 pTempCnt
+8D16 cleanTmp
+8D18 pTemp
+8D24 userMem
+FE6E symTable
+
+[flags]
+00 kbdFlags
+2,00 trigDeg,trigFlags
+3,00 kbdSCR,kbdFlags
+4,00 kbdKeyPress,kbdFlags
+01 editFlags
+2,01 editOpen,editFlags
+02 plotFlags
+1,02 plotLoc,plotFlags
+2,02 plotDisp,plotFlags
+4,02 grfFuncM,grfModeFlags
+5,02 grfPolarM,grfModeFlags
+6,02 grfParamM,grfModeFlags
+7,02 grfRecurM,grfModeFlags
+03 graphFlags
+0,03 graphDraw,graphFlags
+2,03 graphCursor,graphFlags
+04 grfDBFlags
+5,04 grfNoAxis,grfDBFlags
+5,04 grfLabel,grfDBFlags
+05 textFlags
+1,05 textEraseBelow,textFlags
+2,05 textScrolled,textFlags
+3,05 textInverse,textFlags
+4,05 textInsMode,textFlags
+08 apdFlags
+2,08 apdAble,apdFlags
+3,08 apdRunning,apdFlags
+09 onFlags
+3,09 onRunning,onFlags
+4,09 onInterrupt,onFlags
+0C curFlags
+2,0C curAble,curFlags
+3,0C curOn,curFlags
+4,0C curLock,curFlags
+0D appFlags
+1,0D appTextSave,appFlags
+2,0D appAutoScroll,appFlags
+5,0D appCurGraphic,appFlags
+6,0D appCurWord,appFlags
+11 promptFlags
+0,11 promptEdit,promptFlags
+12 indicFlags
+0,12 indicRun,indicFlags
+1,12 indicInUse,indicFlags
+2,12 indicOnly,indicFlags
+3,12 shift2nd,shiftFlags
+4,12 shiftAlpha,shiftFlags
+5,12 shiftLwrAlph,shiftFlags
+6,12 shiftALock,shiftFlags
+7,12 shiftKeepAlph,shiftFlags
+13 tblFlags
+6,13 reTable,tblFlags
+14 sGrFlags
+0,14 grfSplit,sGrFlags
+1,14 grfSChanged,sGrFlags
+2,14 grfSplitOverride,sGrFlags
+7,14 textWrite,sGrFlags
+15 newIndicFlags
+1,15 saIndic,newIndicFlags
diff --git a/tool/tilem-src/data/symbols/ti83.sym b/tool/tilem-src/data/symbols/ti83.sym
new file mode 100644
index 0000000..70df089
--- /dev/null
+++ b/tool/tilem-src/data/symbols/ti83.sym
@@ -0,0 +1,1307 @@
+[macros]
+# Nothing currently
+
+[labels]
+0008 rOP1TOOP2
+0010 rFINDSYM
+0018 rPUSHREALO1
+0020 rMOV9TOOP1
+0028 rFPMULT
+0030 rFPADD
+
+8000 kbdScanCode
+8001 kbdLGSC
+8002 kbdPSC
+8003 kbdWUR
+8004 kbdDebncCnt
+8005 kbdKey
+8006 kbdGetKy
+8007 keyExtend
+8008 contrast
+8009 apdSubTimer
+800a apdTimer
+800b curTime
+800c curRow
+800d curCol
+800e curOffset
+800f curUnder
+8010 curY
+8012 curXRow
+801a lFont_record
+8022 sFont_record
+802f indicMem
+8037 indicCounter
+8038 indicBusy
+8039 OP1
+8044 OP2
+804f OP3
+805a OP4
+8065 OP5
+8070 OP6
+8080 progToEdit
+8088 nameBuff
+8094 iMathPtr1
+8096 iMathPtr2
+8098 iMathPtr3
+809a iMathPtr4
+809c iMathPtr5
+809e chkDelPtr1
+80a0 chkDelPtr2
+80a2 insDelPtr
+80a4 upDownPtr
+80ac asm_data_ptr1
+80ae asm_data_ptr2
+80c8 asm_ind_call
+80c9 textShadow
+8149 textShadCur
+814b textShadTop
+814c textShadAlph
+814d textShadIns
+814e cxMain
+8150 cxPPutAway
+8152 cxPutAway
+8154 cxRedisp
+8156 cxErrorEP
+8158 cxSizeWind
+815a cxPage
+815b cxCurApp
+815c cxPrev
+817d onSP
+817f onCheckSum
+819d menuActive
+819f menuCurrent
+822d ioFlag
+822f sndRecState
+8230 ioErrState
+8231 header
+823a ioData
+8246 bakHeader
+8252 penCol
+8253 penRow
+8254 rclQueue
+8256 errNo
+8257 errSP
+8259 errOffset
+8265 saveSScreen
+8565 usermem_offset
+8567 flags
+858f statVars
+886c curGStyle
+886d curGY
+886e curGX
+886f curGY2
+8870 curGX2
+8871 freeSaveY
+8872 freeSaveX
+88F6 XOffset
+88F7 YOffset
+88F8 lcdTallP
+88F9 pixWideP
+88FA pixWide_m_1
+88FB pixWide_m_2
+88FE lastEntryStk
+897E numLastEntries
+897F currLastEntry
+8AA5 Xmin
+8AB7 Xscl
+8AC0 Ymin
+8AD2 Yscl
+8C3B deltaX
+8C44 deltaY
+8C4D shortX
+8C56 shortY
+8C77 XOutDat
+8C7B YOutDat
+8C7F inputDat
+8DEB ES
+8e29 plotSScreen
+913B parseVar
+9144 begPC
+9146 curPC
+9148 endPC
+9157 cmdShadow
+91D7 cmdShadCur
+91DB cmdCursor
+91DD editTop
+91DF editCursor
+91E1 editTail
+91E3 editBtm
+91EF editSym
+91F1 editDat
+928C modePtr
+928E winTop
+928F winBtm
+9290 winLeftEdge
+9291 winLeft
+9293 winAbove
+9295 winRow
+9297 winCol
+92F1 fmtMatSym
+92F3 fmtMatMem
+92F5 EQS
+92FE delAdjAmt
+9305 chkDelPtr3
+9307 chkDelPtr4
+9309 tempMem
+930B fpBase
+930D FPS
+930F OPBase
+9311 OPS
+9313 pTempCnt
+9315 cleanTmp
+9317 pTemp
+9319 progPtr
+9327 userMem
+0fe6e symTable
+
+# System routines (page C)
+4000 _ldHLind
+4004 _cphlde
+4008 _divHLBy10
+400c _divHLbyA
+4010 _kbdScan
+4014 _getcsc
+4018 _coorMon
+401b _mon
+401e _monForceKey
+4021 _sendKPress
+4024 _JforceCmdNoChaR
+4027 _JforceCmd
+402a _sysErrHandler
+402e _newContext
+4032 _newContext0
+4036 _A2PointHLind
+403a _PointHLind
+403e _PPutAwayPrompt
+4042 _PPutAway
+4046 _PutAway
+404a _SizeWind
+404e _ErrorEP
+4052 _callMain
+4056 _monErrHand
+405a _appInit
+405e _appInitIfDec
+4062 _Initialize
+4066 _lcd_busy
+406a _Min
+406e _Max
+4072 _AbsO1PAbsO2
+4076 _Intgr
+407a _Trunc
+407e _InvSub
+4082 _Times2
+4086 _Plus1
+408a _Minus1
+408e _FPSub
+4092 _FPAdd
+4096 _DToR
+409a _RToD
+409e _Cube
+40a2 _TimesPt5
+40a6 _FPSquare
+40aa _FPMult
+40ae _LJRnd
+40b2 _InvOP1SC
+40b6 _InvOP1S
+40ba _InvOP2S
+40be _Frac
+40c2 _FPRecip
+40c6 _FPDiv
+40ca _SqRoot
+40ce _RndGuard
+40d2 _RnFx
+40d6 _Int
+40da _Round
+40de _LnX
+40e2 _LogX
+40e6 _LJNoRnd
+40ea _EToX
+40ee _TenX
+40f2 _SinCosRad
+40f6 _Sin
+40fa _Cos
+40fe _Tan
+4102 _SinHCosH
+4106 _TanH
+410a _CosH
+410e _SinH
+4112 _ACosRad
+4116 _ATanRad
+411a _ATan2Rad
+411e _ASinRad
+4122 _ACos
+4126 _ATan
+412a _ASin
+412e _ATan2
+4132 _ATanH
+4136 _ASinH
+413a _ACosH
+413e _PToR
+4142 _RToP
+4146 _HLTimes9
+414a _CkOP1Cplx
+414e _CkOP1Real
+4152 _Angle
+4156 _COP1Set0
+415a _CpOP4OP3
+415e _Mov9OP2Cp
+4162 _AbsO1O2Cp
+4166 _CpOP1OP2
+416a _OP3ToOP4
+416e _OP1ToOP4
+4172 _OP2ToOP4
+4176 _OP4ToOP2
+417a _OP3ToOP2
+417e _OP1ToOP3
+4182 _OP5ToOP2
+4186 _OP5ToOP6
+418a _OP5ToOP4
+418e _OP1ToOP2
+4192 _OP6ToOP2
+4196 _OP6ToOP1
+419a _OP4ToOP1
+419e _OP5ToOP1
+41a2 _OP3ToOP1
+41a6 _OP6ToOP5
+41aa _OP4ToOP5
+41ae _OP3ToOP5
+41b2 _OP2ToOP5
+41b6 _OP2ToOP6
+41ba _OP1ToOP6
+41be _OP1ToOP5
+41c2 _OP2ToOP1
+41c6 _MovREG
+41ca _Mov10B
+41ce _Mov9B
+41d2 _Mov18
+41d6 _Mov8B
+41da _Mov7B
+41de _Mov14
+41e2 _Mov6B
+41e6 _Mov5B
+41ea _Mov4B
+41ee _Mov3B
+41f2 _Mov2B
+41f6 _OP2ToOP3
+41fa _OP4ToOP3
+41fe _OP5ToOP3
+4202 _OP4ToOP6
+4206 _Mov9ToOP1
+420a _Mov9OP1OP2
+420e _Mov9ToOP2
+4212 _MovFrOP1
+4216 _OP4Set1
+421a _OP3Set1
+421e _OP2Set8
+4222 _OP2Set5
+4226 _OP2SetA
+422a _OP2Set4
+422e _OP2Set3
+4232 _OP1Set1
+4236 _OP1Set4
+423a _OP1Set3
+423e _OP3Set2
+4242 _OP1Set2
+4246 _OP2Set2
+424a _SetNum2
+424e _SetMant1
+4252 _OP2Set1
+4256 _SetNum1
+425a _SetNum
+425e _SetNumA
+4262 _SetMant
+4266 _Zero16D
+426a _Set16A
+426e _Set14A
+4272 _Set14D
+4276 _OP5Set0
+427a _OP4Set0
+427e _OP3Set0
+4282 _OP2Set0
+4286 _OP1Set0
+428a _SetNum0
+428e _ZeroOP1
+4292 _ZeroOP2
+4296 _ZeroOP3
+429a _ZeroOP
+429e _ClrLp
+42a2 _ShRAcc
+42a6 _ShLAcc
+42aa _ShR18
+42ae _ShR18A
+42b2 _ShR16
+42b6 _ShR14
+42ba _ShL16
+42be _ShL14
+42c2 _SRDO1
+42c6 _SHRDRND
+42ca _MANTPA
+42ce _ADDPROP
+42d2 _ADDPROPLP
+42d6 _Add16D
+42da _Add14D
+42de _Sub16D
+42e2 _Sub14D
+42e6 _OP2ExOP6
+42ea _OP5ExOP6
+42ee _OP1ExOP5
+42f2 _OP1ExOP6
+42f6 _OP2ExOP4
+42fa _OP2ExOP5
+42fe _OP1ExOP3
+4302 _OP1ExOP4
+4306 _OP1ExOP2
+430a _ExLp
+430e _CkOP1C0
+4312 _CkOP1FP0
+4316 _CkOP2FP0
+431a _PosNo0Int
+431e _CkPosInt
+4322 _CkInt
+4326 _CkOdd
+432a _CkOP1M
+432e _GetCon1
+4332 _GetCon
+4336 _PIDIV2
+433a _PIDIV4
+433e _TWOPI
+4342 _PICON
+4346 _PIDIV4A
+434a _PIDIV2A
+434e _ExpToHex
+4352 _OP1ExpToDec
+4356 _CkOP2Pos
+435a _CkOP1Pos
+435e _ClrOP2S
+4362 _ClrOP1S
+4366 _FDiv100
+436a _FDiv10
+436e _DecO1Exp
+4372 _IncO1Exp
+4376 _IncExp
+437a _CkValidNum
+437e _GetExp
+4382 _HTimesL
+4386 _EOP1NotReal
+438a _ThetaName
+438e _RName
+4392 _RegEqName
+4396 _RecurNName
+439a _XName
+439e _YName
+43a2 _TName
+43a6 _RealName
+43aa _SETesTOfps
+43ae _ChkTempDirt
+43b2 _OP1MOP2Exp
+43b6 _OP1EXPMDE
+43ba _ChkErrBreak
+43be _IsA2ByteTok
+43c2 _GetLastEntry
+43c6 _GetLastEntryPtr
+43ca _REGRCLRCHNG
+43ce _ResetWinTop
+43d2 _SetYUp
+43d6 _SetXUp
+43da _ISO1NONTLSTorPROG
+43de _ISO1NONTEMPLST
+43e2 _IS_A_LSTorCLST
+43e6 _Chk_HL_999
+43ea _EQU_or_NEWEQU
+43ee _GET_PLUS1_SAVE
+43f2 _ErrD_OP1NotPos
+43f6 _ErrD_OP1Not_R
+43fa _ErrD_OP1NotPosInt
+43fe _ErrD_OP1_LE_0
+4402 _ErrD_OP1_0
+4406 _Findsym_Get_Size
+440a _Sto_StatVar
+440e _Rcl_StatVar
+4412 _CkOP2Real
+4416 _Get_X_Indirect
+441a _MemChk
+441e _CmpPrgNamLen1
+4422 _CmpPrgNamLen
+4426 _FindProgSym
+442a _ChkFindSym
+442e _FindSym
+4432 _InsertMem
+4436 _InsertMemA
+443a _EnoughMem
+443e _CmpMemNeed
+4442 _CREATEPVAR4
+4446 _CREATEPVAR3
+444a _CREATEVAR3
+444e _CreateCplx
+4452 _CreateReal
+4456 _CreateTRList
+445a _CreateRList
+445e _CreateTCList
+4462 _CreateCList
+4466 _CreateTRMat
+446a _CreateRMat
+446e _CreateTStrng
+4472 _CreateStrng
+4476 _Create0Equ
+447a _CreateTEqu
+447e _CreateEqu
+4482 _CreatePict
+4486 _CreateGDB
+448a _CreateProg
+448e _ChkDel
+4492 _ChkDelA
+4496 _AdjParser
+449a _AdjMath
+449e _AdjM7
+44a2 _DelMemA
+44a6 _Get_Form_Num
+44aa _DelVar
+44ae _DelVarIO
+44b2 _DelMem
+44b6 _DelVar3D
+44ba _DelVar3C
+44be _DelVar3DC
+44c2 _Sym_Prog_Non_T_Lst
+44c6 _AdjSymPtrs
+44ca _DataSizeA
+44ce _DataSize
+44d2 _PopMCplxO1
+44d6 _PopMCplx
+44da _MovCplx
+44de _PopOP5
+44e2 _PopOP3
+44e6 _PopOP1
+44ea _PopRealO6
+44ee _PopRealO5
+44f2 _PopRealO4
+44f6 _PopRealO3
+44fa _PopRealO2
+44fe _PopRealO1
+4502 _PopReal
+4506 _FPopCplx
+450a _FPopReal
+450e _FPopFPS
+4512 _DeallocFPS
+4516 _DeallocFPS1
+451a _AllocFPS
+451e _AllocFPS1
+4522 _PushRealO6
+4526 _PushRealO5
+452a _PushRealO4
+452e _PushRealO3
+4532 _PushRealO2
+4536 _PushRealO1
+453a _PushReal
+453e _PushOP5
+4542 _PushOP3
+4546 _PushMCplxO3
+454a _PushOP1
+454e _PushMCplxO1
+4552 _PushMCplx
+4556 _ExMCplxO1
+455a _Exch9
+455e _CpyTo1FPS11
+4562 _CpyTo2FPS5
+4566 _CpyTo1FPS5
+456a _CpyTo2FPS6
+456e _CpyTo1FPS6
+4572 _CpyTo2FPS7
+4576 _CpyTo1FPS7
+457a _CpyTo1FPS8
+457e _CpyTo2FPS8
+4582 _CpyTo1FPS10
+4586 _CpyTo1FPS9
+458a _CpyTo2FPS4
+458e _CpyTo6FPS3
+4592 _CpyTo6FPS2
+4596 _CpyTo2FPS3
+459a _CpyCTo1FPS3
+459e _CpyTo1FPS3
+45a2 _CpyFPS3
+45a6 _CpyTo1FPS4
+45aa _CpyTo3FPS2
+45ae _CpyTo5FPST
+45b2 _CpyTo6FPST
+45b6 _CpyTo4FPST
+45ba _CpyTo3FPST
+45be _CpyTo2FPST
+45c2 _CpyTo1FPST
+45c6 _CpyFPST
+45ca _CpySTACK
+45ce _CpyTo3FPS1
+45d2 _CpyTo2FPS1
+45d6 _CpyTo1FPS1
+45da _CpyFPS1
+45de _CpyTo2FPS2
+45e2 _CpyTo1FPS2
+45e6 _CpyFPS2
+45ea _CpyO3ToFPST
+45ee _CpyO2ToFPST
+45f2 _CpyO6ToFPST
+45f6 _CpyO1ToFPST
+45fa _CpyToFPST
+45fe _CpyToSTACK
+4602 _CpyO3ToFPS1
+4606 _CpyO5ToFPS1
+460a _CpyO2ToFPS1
+460e _CpyO1ToFPS1
+4612 _CpyToFPS1
+4616 _CpyO2ToFPS2
+461a _CpyO3ToFPS2
+461e _CpyO6ToFPS2
+4622 _CpyO1ToFPS2
+4626 _CpyToFPS2
+462a _CpyO5ToFPS3
+462e _CpyO2ToFPS3
+4632 _CpyO1ToFPS3
+4636 _CpyToFPS3
+463a _CpyO1ToFPS6
+463e _CpyO1ToFPS7
+4642 _CpyO1ToFPS5
+4646 _CpyO2ToFPS4
+464a _CpyO1ToFPS4
+464e _ErrNotEnoughMem
+4652 _FPSMinus9
+4656 _HLMinus9
+465a _ErrOverflow
+465d _ErrDivBy0
+4660 _ErrSingularMat
+4663 _ErrDomain
+4666 _ErrIncrement
+4669 _ErrNon_Real
+466c _ErrSyntax
+466f _ErrDataType
+4672 _ErrArgument
+4675 _ErrDimMismatch
+4678 _ErrDimension
+467b _ErrUndefined
+467e _ErrMemory
+4681 _ErrInvalid
+4684 _ErrBreak
+4687 _ErrStat
+468a _ErrSignChange
+468d _ErrIterations
+4690 _ErrBadGuess
+4693 _ErrTolTooSmall
+4696 _ErrStatPlot
+4699 _ErrLinkXmit
+469c _JError
+469f _JErrorNo
+46a2 _noErrorEntry
+46a5 _pushErrorHandlER
+46a9 _popErrorHandleR
+46ad _strCopy
+46b1 _strCat
+46b5 _isInSet
+46b9 _sDone
+46bd _serrort
+46c1 _sNameEq
+46c5 _sUnderScr
+46c9 _sFAIL
+46cd _sName
+46d1 _sOK
+46d5 _seqn
+46d9 _Sselect
+46dd _STransmit
+46e1 _SRECURN
+46e5 _GEQNAMEA
+46e9 _RECNAME
+46ed ___bank_call
+46f1 ___bank_ret
+46f5 ___bank_jump
+46f9 ___bank_entry
+46fd _ReadDisp2
+4701 _putmap
+4705 _putc
+4709 _dispHL
+470d _puts
+4711 _putpsb
+4715 _putps
+4719 _wputps
+471d _putbuf
+4721 _putbuf1
+4725 _wputc
+4729 _wputs
+472d _wputsEOL
+4731 _wdispEOL
+4735 _whomeUp
+4739 _setNumWindow
+473d _newline
+4741 _moveDown
+4745 _scrollUp
+4749 _shrinkWindow
+474d _moveUp
+4751 _scrollDown
+4755 _clrLCDFull
+4759 _clrLCD
+475d _clrScrnFull
+4761 _clrScrn
+4765 _clrTxtShd
+4769 _clrWindow
+476d _eraseEOL
+4771 _eraseEOW
+4775 _homeUp
+4779 _getcurloc
+477d _vputmap
+4781 _vputs
+4785 _vputsn
+4789 _vputsnG
+478d _vputsnT
+4791 _runIndicOn
+4795 _runIndicOff
+4799 _saveCmdShadow
+479d _saveShadow
+47a1 _rstrShadow
+47a5 _rstrpartial
+47a9 _rstrCurRow
+47ad _rstrUnderMenu
+47b1 _rstrbotrow
+47b5 _saveTR
+47b9 _restoreTR
+47bd _GetKeyPress
+47c1 _GetTokLen
+47c5 _Get_Tok_Strng
+47c9 _GetTokString
+47cd _PUTBPATBUF2
+47d1 _PUTBPATBUF
+47d5 _putbPAT
+47d9 _putcCheckScrolL
+47dd _dispEOL
+47e1 _fdispEOL
+47e5 _MAKEROWCMD
+47e9 _TOTOSTRP
+47ed _SETVARNAME
+47f1 _dispDone
+47f5 _finishoutput
+47f9 _curBlink
+47fd _cursorOff
+4801 _hideCursor
+4805 _cursorOn
+4809 _showCursor
+480d _KeyToString
+4811 _PullDownChk
+4815 _MenuCatCommon
+4819 _ZIfCatalog
+481d _ZIfMatrixMenu
+4821 _loadCurCat
+4825 _NCifprgmedmode
+4829 _LoadMenuNum
+482d _LoadMenuNumL
+4831 _MenuEdKey
+4835 _MenCatRet
+4839 _notalphnum
+483d _SaveSavedFlags
+4841 _SetMenuFlags
+4845 _RstrSomeFlags
+4849 _RstrSmallText
+484d _dispListName
+4851 _SeeIfErrorCx
+4855 _RstrOScreen
+4859 _SaveOscreen
+485d _DispLAlphaName
+4861 _AbortPrgmode
+4865 _Is_FullCntx
+4869 _AdrMRow
+486d _AdrMEle
+4871 _GetMatOP1A
+4875 _GetM1ToOP1
+4879 _GetM1TOP1A
+487d _GetMToOP1
+4881 _PutToM1A
+4885 _PutToMA1
+4889 _PutToMat
+488d _Mat_El_Div
+4891 _CMatFun
+4895 _RowEch_Poly
+4899 _RowEchelon
+489d _AdrLEle
+48a1 _GetL1ToOP1
+48a5 _GetL1TOP1A
+48a9 _GetLToOP1
+48ad _GetL1ToOP2
+48b1 _GetL1TOP2A
+48b5 _GetL2TOP1A
+48b9 _PutToLA1
+48bd _PutToL
+48c1 _MaxMinLst
+48c5 _LLow
+48c9 _LHigh
+48cd _LSum
+48d1 _CumSum
+48d5 _ToFrac
+48d9 _SeqSet
+48dd _SeqSolve
+48e1 _Cmp_Num_Init
+48e5 _BinOpExec
+48e9 _EXMEAN1
+48ed _SET2MVLPTRS
+48f1 _SETMAT1
+48f5 _CreateTList
+48f9 _UnOpExec
+48fd _ThreeExec
+4901 _RestoreErrNo
+4904 _FourExec
+4908 _FiveExec
+490c _CpyTo2ES1
+4910 _CpyTo6ES1
+4914 _CpyTo1ES1
+4918 _CpyTo3ES1
+491c _CpyTo3ES2
+4920 _CpyTo2ES2
+4924 _CpyTo1ES2
+4928 _CpyTo2ES3
+492c _CpyTo1ES3
+4930 _CpyTo3ES4
+4934 _CpyTo6ES3
+4938 _CpyTo2ES4
+493c _CpyTo1ES4
+4940 _CpyTo2ES5
+4944 _CpyTo1ES5
+4948 _CpyTo4EST
+494c _CpyTo2EST
+4950 _CpyTo1EST
+4954 _CpyTo2ES6
+4958 _CpyTo1ES6
+495c _CpyTo2ES7
+4960 _CpyTo1ES7
+4964 _CpyTo2ES8
+4968 _CpyTo1ES8
+496c _CpyTo1ES9
+4970 _CpyTo2ES9
+4974 _CpyTo2ES10
+4978 _CpyTo1ES10
+497c _CpyTo2ES11
+4980 _CpyTo1ES11
+4984 _CpyTo2ES12
+4988 _CpyTo1ES12
+498c _CpyTo2ES13
+4990 _CpyTo1ES13
+4994 _CpyTo1ES14
+4998 _CpyTo1ES16
+499c _CpyTo1ES17
+49a0 _CpyTo1ES18
+49a4 _CpyTo1ES15
+49a8 _CpyTo2ES15
+49ac _CpyO1ToEST
+49b0 _CpyO1ToES1
+49b4 _CpyO6ToES1
+49b8 _CpyO6ToES3
+49bc _CpyO1ToES2
+49c0 _CpyO2ToES2
+49c4 _CpyO1ToES3
+49c8 _CpyO1ToES4
+49cc _CpyO1ToES5
+49d0 _CpyO1ToES6
+49d4 _CpyO1ToES7
+49d8 _CpyO2ToES4
+49dc _CpyO2ToES5
+49e0 _CpyO2ToES6
+49e4 _CpyO2ToES7
+49e8 _CpyO2ToES8
+49ec _CpyO2ToES9
+49f0 _CpyO1ToES8
+49f4 _CpyO1ToES9
+49f8 _CpyO1ToES10
+49fc _CpyO1ToES11
+4a00 _CpyO1ToES12
+4a04 _CpyO1ToES13
+4a08 _CpyO1ToES14
+4a0c _CpyO1ToES15
+4a10 _EVALF3A
+4a14 COMPLEX_EXEC
+4a18 _GetK
+4a1c _setTitlE
+4a20 _dispVarVal
+4a24 _RecallEd
+4a28 _setupBuffer
+4a2c _createNumEditBUF
+4a30 _CallCommon
+4a34 _CommonKeys
+4a37 _Leftmore
+4a3a _fDel
+4a3e _fClear
+4a42 _finsDisp
+4a45 _FinsDisp02
+4a49 _setIndicator
+4a4d _CloseEditBufNo
+4a51 _releaseBuffer
+4a55 _varnameToOP1hl
+4a59 _nameToOP1
+4a5d _numPPutAway
+4a61 _numRedisp
+4a65 _numError02
+4a68 _Load_SFont
+4a6c _SFont_Len
+4a70 _InitNumVec
+4a74 _SetXXOP1
+4a78 _SetXXOP2
+4a7c _SetXXXXOP2
+4a80 _UCLineS
+4a84 _CLine
+4a88 _CLineS
+4a8c _XRooty
+4a90 _YToX
+4a94 _ZmStats
+4a98 _POINT_STAT_HLP
+4a9c _DRAWSPLOT
+4aa0 _INITNEWTRACEP
+4aa4 _SPLOTCOORD
+4aa8 _SPLOTRIGHT
+4aac _SPLOTLEFT
+4ab0 _CMPBOXINFO
+4ab4 _NEXTPLOT
+4ab8 _PREVPLOT
+4abc _CLRPREVPLOT
+4ac0 _PUT_INDEX_LST
+4ac4 _GET_INDEX_LST
+4ac8 _HEAP_SORT
+4acc _STOGDB2
+4ad0 _RCLGDB2
+4ad4 _CircCmd
+4ad8 _GrphCirc
+4adc _Mov18B
+4ae0 _DarkLine
+4ae4 _ILine
+4ae8 _IPoint
+4aec _XYRndBoth
+4af0 _XYRnd
+4af4 _CheckTOP
+4af8 _CheckXY
+4afc _DarkPnt
+4b00 _CPointS
+4b04 _WtoV
+4b08 _VtoWHLDE
+4b0c _XItoF
+4b10 _YFtoI
+4b14 _XFtoI
+4b18 _TraceOff
+4b1c _GrRedisp
+4b20 _GDispToken
+4b24 _GRDECODA
+4b28 _LABCOOR
+4b2c _COORDISP
+4b30 _TMPEQUNOSRC
+4b34 _GrLabels
+4b38 _YPixSet
+4b3c _XPixSet
+4b40 _CopyRng
+4b44 _VALCUR
+4b48 _GrPutAway
+4b4c _RstGFlags
+4b50 _GRReset
+4b54 _XYCent
+4b58 _ZoomXYCmd
+4b5c _CPTDELY
+4b60 _CPTDELX
+4b64 _SetFuncM
+4b68 _SetSeqM
+4b6c _SetPolM
+4b70 _SetParM
+4b74 _ZmInt
+4b78 _ZmDecml
+4b7c _ZmPrev
+4b80 _ZmUsr
+4b84 _SetUZm
+4b88 _ZmFit
+4b8c _ZmSquare
+4b90 _ZmTrig
+4b94 _SetXMinMax
+4b98 _ZooDefault
+4b9c _GrBufCpy
+4ba0 _DrawSplitLine
+4ba4 _RestoreDisp
+4ba8 _FNDDB
+4bac _ALLEQ
+4bb0 _fndallseleq
+4bb4 _NEXTEQ
+4bb8 _PREVEQ
+4bbc _BlinkGCur
+4bc0 _NBCURSOR
+4bc4 _StatMark
+4bc8 _ChkTextCurs
+4bcc _Regraph
+4bd0 _DOREFFLAGS02
+4bd4 _InitNSeq
+4bd8 _YRES
+4bdc _PLOTPTXY2
+4be0 _Ceiling
+4be4 _PutXY
+4be7 _Putequno
+4beb _PDspGrph
+4bef _HorizCmd
+4bf3 _VertCmd
+4bf7 _LineCmd
+4bfb _UnLineCmd
+4bff _PointCmd
+4c03 _PixelTest
+4c07 _PixelCmd
+4c0b _TanLnF
+4c0f _DrawCmd_Init
+4c13 _DrawCmd
+4c17 _ShadeCmd
+4c1b _InvCmd
+4c1f _StatShade
+4c23 _dspmattable
+4c27 _dsplsts
+4c2b _closeEditBuf
+4c2f _parseEditBuf
+4c33 _putsm
+4c37 _DspCurTbl
+4c3b _DspGrTbl
+4c3f _ZeroTemplate
+4c43 _settblrefs
+4c47 _dispTblBot
+4c4b _DispTblTop
+4c4f _dispTblbody
+4c53 _VPutBlank
+4c57 _TblTrace
+4c5b _dispListNameY
+4c5f _CurNameLength
+4c63 _NameToBuf
+4c67 _jpromptcursor
+4c6a _bufLeft
+4c6e _bufRight
+4c72 _bufInsert
+4c76 _bufQueueChar
+4c7a _bufReplace
+4c7e _bufDelete
+4c82 _bufPeek
+4c86 _bufPeek1
+4c8a _bufPeek2
+4c8e _bufPeek3
+4c92 _BufToBtm
+4c96 _setupEditEqu
+4c9a _bufToTop
+4c9e _isEditFull
+4ca2 _isEditEmpty
+4ca6 _isAtTop
+4caa _isAtBtm
+4cae _bufClear
+4cb2 _JcursorFirst
+4cb5 _JcursorLast
+4cb8 _cursorLeft
+4cbc _JcursorRight
+4cbf _JcursorUp
+4cc2 _cursorDown
+4cc6 _cursorToOffset
+4cca _insDisp
+4cce _FDISPBOL1
+4cd2 _FDISPBOL
+4cd6 _dispEOW
+4cda _dispHead
+4cde _dispTail
+4ce2 _PutTokString
+4ce6 _setupEditCmd
+4cea _setEmptyEditEqU
+4cee _setEmptyEditPtR
+4cf2 _closeEditEqu
+4cf6 _toggleIns
+4cfa _GetPrevTok
+4cfe _getkey
+4d02 _canIndic
+4d06 _LCD_DriverOn
+4d0a _DFMIN2
+4d0e _formDisp
+4d12 _formMatrix
+4d16 _wscrollLeft
+4d1a _wscrollUp
+4d1e _wscrollDown
+4d22 _wscrollRight
+4d26 _formEReal
+4d2a _formERealTOK
+4d2e _formDCplx
+4d32 _formReal
+4d36 _formScrollUp
+4d3a _setwinabove
+4d3e _disarmScroll
+4d42 _OP1toEdit
+4d46 _MinToEdit
+4d4a _rclVarToEdit
+4d4e _rclVarToEditPtR
+4d52 _RclEntryToEdit
+4d56 _rclToQueue
+4d5a _FormToTok
+4d5e _Disp_Interval
+4d62 _DisplstName
+4d66 _dispSLstNameHL
+4d6a _EditEqu
+4d6e _closeEquField
+4d72 _AutoSelect
+4d76 _DISPYEOS
+4d7a _dispNumEOS
+4d7e _setupdispeq
+4d82 _dispForward
+4d86 _DispYPrompt2
+4d8a _stringwidth
+4d8e _dispErrorScreeN
+4d92 _PopCx
+4d96 _loadnoeentry
+4d9a _SaveScreen
+4d9e _RetScreen
+4da2 _RetScreenErr
+4da6 _SplitChange
+4daa _SolveRedisp
+4dae _SolveDisp
+4db2 _itemName
+4db6 _SetNorm_Vals
+4dba _SetVert_Vals
+4dbe _ConvKeyToTok
+4dc2 _KeyToTokNew2B
+4dc6 _KeyToTok2Byte
+4dca _TokToKey
+4dce _Load_LFont
+4dd2 _Send1BErr
+4dd6 _GetVarCmd
+4dda _SendVarCmd
+4dde _PrintScreen
+4de2 _KeyScnLnk
+4de6 _IOResetAll
+4dea _DelRes
+4dee _ConvLCtoLR
+4df2 _RedimMat
+4df6 _IncLstSize
+4dfa _insertlist
+4dfe _dellistel
+4e02 _EditProg
+4e06 _CloseProg
+4e0a _ClrGraphRef
+4e0e _FixTempCnt
+4e12 _SaveData
+4e16 _RestoreData
+4e1a _FindAlphaup
+4e1e _FindAlphadn
+4e22 _CmpSyms
+4e26 _CreateTemp
+4e2a _CleanAll
+4e2e _MoveToNextSym
+4e32 _ConvLRtoLC
+4e36 _TblScreenDn
+4e3a _TblScreenUp
+4e3e _ScreenUp
+4e42 _ScreenUpDown
+4e46 _ZifRclHandler
+4e4a _zifrclkapp
+4e4e _rclkeyRtn
+4e52 _RclKey
+4e55 _RclRegEq_Call
+4e59 _RclRegEq
+4e5c _initNamePrompt
+4e60 _NamePrompt2
+4e64 _CatalogChk
+4e68 _clrTR
+4e6c _Quad
+4e70 _GraphQuad
+4e74 _BC2NonReal
+4e78 _ErrNonReal
+4e7c _Write_Text
+4e80 _FORSEQINIT
+4e84 _GrphPars
+4e88 _PlotPars
+4e8c _PARSEinp
+4e90 _PARSEOFF
+4e94 _PARSESCAN
+4e98 _GetParse
+4e9c _SaveParse
+4ea0 _InitPFlgs
+4ea4 _CkEndLinErr
+4ea8 _OP2Set60
+4eac _GetStatPtr
+4eb0 _Cmp_StatPtr
+4eb4 _VarSysAdr
+4eb8 _StoSysTok
+4ebc _StoAns
+4ec0 _StoTheta
+4ec4 _StoR
+4ec8 _StoY
+4ecc _StoN
+4ed0 _StoT
+4ed4 _StoX
+4ed8 _StoOther
+4edc _RCLANS
+4ee0 _RclY
+4ee4 _RclN
+4ee8 _RclX
+4eec _RclVarSym
+4ef0 _RclSysTok
+4ef4 _StMatEl
+4ef8 _StLstVecEl
+4efc _ConvOP1
+4f00 _isaletter
+4f04 _Find_Parse_ForMULA
+4f08 _Parse_Formula
+4f0c _StrngEnt1
+4f15 _GetNumLet
+4f1e _Init_Prog_List
+4f27 _PRGRDLP
+4f30 _VarEnt
+4f39 _RclStat
+4f42 _ParseLoop
+4f4b _ParseOnC
+4f52 _ParseOn
+4f5a _ParseCmd
+4f61 _StoType
+4f6a _CreatePair
+4f73 _PushNum
+4f7c _IncCurPCErrEnd
+4f85 _ErrEnd
+4f8e _CommaErrF
+4f97 _CommaErr
+4fa0 _StEqArg2
+4fa9 _StEqArg
+4fb2 _InpArg
+4fbb _StEqArg3
+4fc4 _NxtFetch
+4fcd _CkFetchVar
+4fd6 _FetchVarA
+4fdf PARSER_EXEC
+4fe3 _FetchVar
+4fec _CkEndLin
+4ff5 _CkEndExp
+4ffe _CkParsEnd
+5007 _StoTypeArg
+5010 _ConvDim
+5019 _ConvDim00
+5022 _AheadEqual
+502b _ParsAheadS
+5034 _ParsAhead
+503d _AnsName
+5046 _StoCmpReals
+504f _GetDEPtr
+5058 _Push2BOper
+5061 _Pop2BOper
+506a _PushOper
+5073 _PopOper
+507c _Find_E_Undef
+5085 _StTmpEq
+508e _FindEOL
+5097 _BrkInc
+50a0 _IncFetch
+50a9 _CurFetch
+50b2 PGMIO_EXEC
+50b6 _Random
+50ba _StoRand
+50be _RandInit
+50c2 _resetStacks
+50c6 _Factorial
+50ca _YOnOff
+50ce _EqSelUnsel
+50d2 _ITSOLVER
+50d6 _GRITSOLVER
+50da _ITSOLVERB
+50de _ITSOLVERNB
+50e2 _ExTest_INT
+50e6 _Dist_Fun
+50ea _LogGamma
+50ee _OneVar
+50f2 _OneVarS_0
+50f6 _ORDSTAT
+50fa _INITSTATANS2
+50fe _ANOVA_SPEC
+5102 _EXEC_ASSEMBLY
+5106 _outputExpr
+510a _CentCursor
+5113 _Text
+511c _FINISHSPEC
+5125 _TRCYFUNC
+512e _Rcl_Seq_X
+5137 _RclSeq2
+5140 _GRPPutAway
+5149 _CkValDelX
+5152 _CkValDelta
+515b _GrBufClr
+5164 _GrBufCpy_V
+516d _FndSelEq
+5176 _ClrGraphXY
+517f _Next_Y_Style
+5188 GRAPH_EXEC
+518c _PLOTPT
+5195 _NEWINDEP
+519e _Axes
+51a7 _setPenX
+51b0 _setPenY
+51b9 _setPenT
+51c2 _Tan_Equ_Disp
+51cb _putAns
+51d4 _DispOP1A
+51dd _MathTanLn
+51e6 _EndDraw
+51ef IO_EXEC
+52e5 EXECUTE_Z80
+
+[flags]
+00 kbdFlags
+2,00 trigDeg,trigFlags
+3,00 kbdSCR,kbdFlags
+4,00 kbdKeyPress,kbdFlags
+01 editFlags
+2,01 editOpen,editFlags
+4,01 monAbandon,monFlags
+02 plotFlags
+1,02 plotLoc,plotFlags
+2,02 plotDisp,plotFlags
+4,02 grfFuncM,grfModeFlags
+5,02 grfPolarM,grfModeFlags
+6,02 grfParamM,grfModeFlags
+7,02 grfRecurM,grfModeFlags
+03 graphFlags
+0,03 graphDraw,graphFlags
+2,03 graphCursor,graphFlags
+04 grfDBFlags
+0,04 grfDot,grfDBFlags
+1,04 grfSimul,grfDBFlags
+2,04 grfGrid,grfDBFlags
+3,04 grfPolar,grfDBFlags
+4,04 grfNoCoord,grfDBFlags
+5,04 grfNoAxis,grfDBFlags
+6,04 grfLabel,grfDBFlags
+05 textFlags
+1,05 textEraseBelow,textFlags
+2,05 textScrolled,textFlags
+3,05 textInverse,textFlags
+08 apdFlags
+2,08 apdAble,apdFlags
+3,08 apdRunning,apdFlags
+09 onFlags
+3,09 onRunnings,onFlags
+4,09 onInterrupt,onFlags
+6,09 statsValid,statFlags
+10 fmtFlags
+0,0A fmtExponent,fmtFlags
+1,0A fmtEng,fmtFlags
+5,0A fmtReal,fmtFlags
+6,0A fmtRect,fmtFlags
+7,0A fmtPolar,fmtFlags
+0c curFlags
+2,0C curAble,curFlags
+3,0C curOn,curFlags
+4,0C curLock,curFlags
+0d appFlags
+1,0D appTextSave,appFlags
+2,0D appAutoScroll,appFlags
+11 plotFlag2
+3,11 expr_param,plotFlag2
+4,11 expr_writing,plotFlag2
+12 indicFlags
+0,12 indicRun,indicFlags
+1,12 indicInUse,indicFlags
+2,12 indicOnly,indicFlags
+3,12 shift2nd,shiftFlags
+4,12 shiftAlpha,shiftFlags
+6,12 shiftALock,shiftFlags
+13 tblFlags
+4,13 AutoFill,tblFlags
+5,13 AutoCalc,tblFlags
+14 sGrFlags
+0,14 grfSplit,sGrFlags
+1,14 VertSplit,sGrFlags
+2,14 grfSChanged,sGrFlags
+3,14 grfSplitOverride,sGrFlags
+4,14 write_on_graph,sGrFlags
+6,14 cmp_mod_box,sGrFlags
+7,14 textWrite,sGrFlags
+15 newIndicFlags
+1,15 saIndic,newIndicFlags
+0,1D gkKeyRepeating,gkFlag
+21 asm_flag1
+22 asm_flag1
+23 asm_flag1
diff --git a/tool/tilem-src/data/symbols/ti83p.sym b/tool/tilem-src/data/symbols/ti83p.sym
new file mode 100644
index 0000000..086215a
--- /dev/null
+++ b/tool/tilem-src/data/symbols/ti83p.sym
@@ -0,0 +1,2327 @@
+[macros]
+0EF B_CALL~%c
+0CD5000 B_JUMP~%c
+0EDED DB~$ED,$ED,%b,%b
+
+[labels]
+0008 rOP1TOOP2
+000B LCD_BUSY_QUICK
+0010 rFINDSYM
+0018 rPUSHREALO1
+0020 rMOV9TOOP1
+0028 rBR_CALL
+0030 rFPADD
+0050 BRT_JUMP0
+0059 APP_PUSH_ERRORH
+005C APP_POP_ERRORH
+
+[romcalls]
+4000 JErrorNo
+4003 FontHook
+4006 LocalizeHook
+4009 LdHLind
+400c CpHLDE
+400f DivHLBy10
+4012 DivHLByA
+4015 KbdScan
+4018 GetCSC
+401b coorMon
+401e Mon
+4021 monForceKey
+4024 SendKPress
+4027 JForceCmdNoChar
+402a JForceCmd
+402d sysErrHandler
+4030 newContext
+4033 newContext0
+4036 PPutAwayPrompt
+4039 PPutAway
+403c PutAway
+403f SizeWind
+4042 ErrorEP
+4045 callMain
+4048 monErrHand
+404b AppInit
+404e initialize
+4051 LCD_BUSY
+4054 Min
+4057 Max
+405a AbsO1PAbsO2
+405d Intgr
+4060 Trunc
+4063 InvSub
+4066 Times2
+4069 Plus1
+406c Minus1
+406f FPSub
+4072 FPAdd
+4075 DToR
+4078 RToD
+407b Cube
+407e TimesPt5
+4081 FPSquare
+4084 FPMult
+4087 LJRnd
+408a InvOP1SC
+408d InvOP1S
+4090 InvOP2S
+4093 Frac
+4096 FPRecip
+4099 FPDiv
+409c SqRoot
+409f RndGuard
+40a2 RnFx
+40a5 Int
+40a8 Round
+40ab LnX
+40ae LogX
+40b1 LJNoRnd
+40b4 EToX
+40b7 TenX
+40ba SinCosRad
+40bd Sin
+40c0 Cos
+40c3 Tan
+40c6 SinHCosH
+40c9 TanH
+40cc CosH
+40cf SinH
+40d2 ACosRad
+40d5 ATanRad
+40d8 ATan2Rad
+40db ASinRad
+40de ACos
+40e1 ATan
+40e4 ASin
+40e7 ATan2
+40ea ATanH
+40ed ASinH
+40f0 ACosH
+40f3 PToR
+40f6 RToP
+40f9 HLTimes9
+40fc CkOP1Cplx
+40ff CkOP1Real
+4102 Angle
+4105 COP1Set0
+4108 CpOP4OP3
+410b Mov9OP2Cp
+410e AbsO1O2Cp
+4111 CpOP1OP2
+4114 OP3ToOP4
+4117 OP1ToOP4
+411a OP2ToOP4
+411d OP4ToOP2
+4120 OP3ToOP2
+4123 OP1ToOP3
+4126 OP5ToOP2
+4129 OP5ToOP6
+412c OP5ToOP4
+412f OP1ToOP2
+4132 OP6ToOP2
+4135 OP6ToOP1
+4138 OP4ToOP1
+413b OP5ToOP1
+413e OP3ToOP1
+4141 OP6ToOP5
+4144 OP4ToOP5
+4147 OP3ToOP5
+414a OP2ToOP5
+414d OP2ToOP6
+4150 OP1ToOP6
+4153 OP1ToOP5
+4156 OP2ToOP1
+4159 Mov11B
+415c Mov10B
+415f Mov9B
+4162 Mov18
+4165 Mov8B
+4168 Mov7B
+416b Mov14
+416e OP2ToOP3
+4171 OP4ToOP3
+4174 OP5ToOP3
+4177 OP4ToOP6
+417a Mov9ToOP1
+417d Mov9OP1OP2
+4180 Mov9ToOP2
+4183 MovFrOP1
+4186 OP4Set1
+4189 OP3Set1
+418c OP2Set8
+418f OP2Set5
+4192 OP2SetA
+4195 OP2Set4
+4198 OP2Set3
+419b OP1Set1
+419e OP1Set4
+41a1 OP1Set3
+41a4 OP3Set2
+41a7 OP1Set2
+41aa OP2Set2
+41ad OP2Set1
+41b0 Zero16D
+41b3 OP5Set0
+41b6 OP4Set0
+41b9 OP3Set0
+41bc OP2Set0
+41bf OP1Set0
+41c2 SetNum0
+41c5 ZeroOP1
+41c8 ZeroOP2
+41cb ZeroOP3
+41ce ZeroOP
+41d1 ClrLp
+41d4 ShRAcc
+41d7 ShLAcc
+41da ShR18
+41dd ShR18A
+41e0 ShR16
+41e3 ShR14
+41e6 ShL16
+41e9 ShL14
+41ec SRDO1
+41ef ShRDRnd
+41f2 MantPA
+41f5 ADDPROP
+41f8 ADDPROPLP
+41fb Add16D
+41fe Add14D
+4201 Sub16D
+4204 Sub14D
+4207 OP2ExOP6
+420a OP5ExOP6
+420d OP1ExOP5
+4210 OP1ExOP6
+4213 OP2ExOP4
+4216 OP2ExOP5
+4219 OP1ExOP3
+421c OP1ExOP4
+421f OP1ExOP2
+4222 ExLp
+4225 CkOP1C0
+4228 CkOP1FP0
+422b CkOP2FP0
+422e PosNo0Int
+4231 CkPosInt
+4234 CkInt
+4237 CkOdd
+423a CkOP1M
+423d GetConOP1
+4240 GetConOP2
+4243 PIDIV2
+4246 PIDIV4
+4249 TWOPI
+424c PICON
+424f ExpToHex
+4252 OP1ExpToDec
+4255 CkOP2Pos
+4258 CkOP1Pos
+425b ClrOP2S
+425e ClrOP1S
+4261 FDiv100
+4264 FDiv10
+4267 DecO1Exp
+426a IncO1Exp
+426d IncExp
+4270 CkValidNum
+4273 GetExp
+4276 HTimesL
+4279 EOP1NotReal
+427c ThetaName
+427f RName
+4282 RegEqName
+4285 RecurNName
+4288 XName
+428b YName
+428e TName
+4291 RealName
+4294 SetEStoFPS
+4297 ChkTempDirt
+429a OP1MOP2Exp
+429d OP1ExpMDE
+42a0 ChkErrBreak
+42a3 IsA2ByteTok
+42a6 GetLastEntry
+42a9 GetLastEntryPtr
+42ac RegrClrChng
+42af ResetWinTop
+42b2 SetYUp
+42b5 SetXUp
+42b8 IsO1NonTLstOrProg
+42bb IsO1NonTempLst
+42be Is_A_LstOrCLst
+42c1 Chk_HL_999
+42c4 Equ_or_NewEqu
+42c7 ErrD_OP1NotPos
+42ca ErrD_OP1Not_R
+42cd ErrD_OP1NotPosInt
+42d0 ErrD_OP1_LE_0
+42d3 ErrD_OP1_0
+42d6 FindSym_Get_Size
+42d9 Sto_StatVar
+42dc Rcl_StatVar
+42df CkOP2Real
+42e2 Get_X_Indirect
+42e5 MemChk
+42e8 CmpPrgNamLen1
+42eb CmpPrgNamLen
+42ee FindProgSym
+42f1 ChkFindSym
+42f4 FindSym
+42f7 InsertMem
+42fa InsertMemA
+42fd EnoughMem
+4300 CmpMemNeed
+4303 CreatePVar4
+4306 CreatePVar3
+4309 CreateVar3
+430c CreateCplx
+430f CreateReal
+4312 CreateTRList
+4315 CreateRList
+4318 CreateTCList
+431b CreateCList
+431e CreateTRMat
+4321 CreateRMat
+4324 CreateTStrng
+4327 CreateStrng
+432a Create0Equ
+432d CreateTEqu
+4330 CreateEqu
+4333 CreatePict
+4336 CreateGDB
+4339 CreateProg
+433c ChkDel
+433f ChkDelA
+4342 AdjParser
+4345 AdjMath
+4348 AdjM7
+434b DelMemA
+434e Get_Form_Num
+4351 DelVar
+4354 DelVarIO
+4357 DelMem
+435a DelVar3D
+435d DelVar3C
+4360 DelVar3DC
+4363 Sym_Prog_Non_T_Lst
+4366 AdjSymPtrs
+4369 DataSizeA
+436c DataSize
+436f PopMCplxO1
+4372 PopMCplx
+4375 MovCplx
+4378 PopOP5
+437b PopOP3
+437e PopOP1
+4381 PopRealO6
+4384 PopRealO5
+4387 PopRealO4
+438a PopRealO3
+438d PopRealO2
+4390 PopRealO1
+4393 PopReal
+4396 FPopCplx
+4399 FPopReal
+439c FPopFPS
+439f DeallocFPS
+43a2 DeallocFPS1
+43a5 AllocFPS
+43a8 AllocFPS1
+43ab PushRealO6
+43ae PushRealO5
+43b1 PushRealO4
+43b4 PushRealO3
+43b7 PushRealO2
+43ba PushRealO1
+43bd PushReal
+43c0 PushOP5
+43c3 PushOP3
+43c6 PushMCplxO3
+43c9 PushOP1
+43cc PushMCplxOP1
+43cf PushMCplx
+43d2 ExMCplxO1
+43d5 Exch9
+43d8 CpyTo1FPS11
+43db CpyTo2FPS5
+43de CpyTo1FPS5
+43e1 CpyTo2FPS6
+43e4 CpyTo1FPS6
+43e7 CpyTo2FPS7
+43ea CpyTo1FPS7
+43ed CpyTo1FPS8
+43f0 CpyTo2FPS8
+43f3 CpyTo1FPS10
+43f6 CpyTo1FPS9
+43f9 CpyTo2FPS4
+43fc CpyTo6FPS3
+43ff CpyTo6FPS2
+4402 CpyTo2FPS3
+4405 CpyCTo1FPS3
+4408 CpyTo1FPS3
+440b CpyFPS3
+440e CpyTo1FPS4
+4411 CpyTo3FPS2
+4414 CpyTo5FPST
+4417 CpyTo6FPST
+441a CpyTo4FPST
+441d CpyTo3FPST
+4420 CpyTo2FPST
+4423 CpyTo1FPST
+4426 CpyFPST
+4429 CpyStack
+442c CpyTo3FPS1
+442f CpyTo2FPS1
+4432 CpyTo1FPS1
+4435 CpyFPS1
+4438 CpyTo2FPS2
+443b CpyTo1FPS2
+443e CpyFPS2
+4441 CpyO3ToFPST
+4444 CpyO2ToFPST
+4447 CpyO6ToFPST
+444a CpyO1ToFPST
+444d CpyToFPST
+4450 CpyToStack
+4453 CpyO3ToFPS1
+4456 CpyO5ToFPS1
+4459 CpyO2ToFPS1
+445c CpyO1ToFPS1
+445f CpyToFPS1
+4462 CpyO2ToFPS2
+4465 CpyO3ToFPS2
+4468 CpyO6ToFPS2
+446b CpyO1ToFPS2
+446e CpyToFPS2
+4471 CpyO5ToFPS3
+4474 CpyO2ToFPS3
+4477 CpyO1ToFPS3
+447a CpyToFPS3
+447d CpyO1ToFPS6
+4480 CpyO1ToFPS7
+4483 CpyO1ToFPS5
+4486 CpyO2ToFPS4
+4489 CpyO1ToFPS4
+448c ErrNotEnoughMem
+448f FPSMinus9
+4492 HLMinus9
+4495 ErrOverflow
+4498 ErrDivBy0
+449b ErrSingularMat
+449e ErrDomain
+44a1 ErrIncrement
+44a4 ErrNon_Real
+44a7 ErrSyntax
+44aa ErrDataType
+44ad ErrArgument
+44b0 ErrDimMismatch
+44b3 ErrDimension
+44b6 ErrUndefined
+44b9 ErrMemory
+44bc ErrInvalid
+44bf ErrBreak
+44c2 ErrStat
+44c5 ErrSignChange
+44c8 ErrIterations
+44cb ErrBadGuess
+44ce ErrTolTooSmall
+44d1 ErrStatPlot
+44d4 ErrLinkXmit
+44d7 JError
+44da noErrorEntry
+44dd pushErrorHandler
+44e0 popErrorHandler
+44e3 StrCopy
+44e6 StrCat
+44e9 IsInSet
+44ec GEQNAMEA
+44ef RECNAME
+44f2 __bank_call
+44f5 __bank_ret
+44f8 __bank_jump
+44fb __bank_entry
+44fe ReadDisp2
+4501 PutMap
+4504 PutC
+4507 DispHL
+450a PutS
+450d PutPSB
+4510 PutPS
+4513 WPutPS
+4516 PutBuf
+4519 PutBuf1
+451c WPutC
+451f WPutS
+4522 WPutSEOL
+4525 WDispEOL
+4528 WHomeUp
+452b SetNumWindow
+452e NewLine
+4531 MoveDown
+4534 ScrollUp
+4537 ShrinkWindow
+453a MoveUp
+453d ScrollDown
+4540 ClrLCDFull
+4543 ClrLCD
+4546 ClrScrnFull
+4549 ClrScrn
+454c ClrTxtShd
+454f ClrWindow
+4552 EraseEOL
+4555 EraseEOW
+4558 HomeUp
+455b GetCurLoc
+455e VPutMap
+4561 VPutS
+4564 VPutSN
+4567 VPutSNG
+456a VPutSNT
+456d RunIndicOn
+4570 RunIndicOff
+4573 SaveCmdShadow
+4576 SaveShadow
+4579 RstrShadow
+457c RstrPartial
+457f RstrCurRow
+4582 RstrUnderMenu
+4585 RstrBotRow
+4588 SaveTR
+458b RestoreTR
+458e GetKeyPress
+4591 GetTokLen
+4594 Get_Tok_Strng
+4597 GetTokString
+459a PUTBPATBUF2
+459d PUTBPATBUF
+45a0 PUTBPAT
+45a3 putcCheckScroll
+45a6 DispEOL
+45a9 fdispEOL
+45ac MakeRowCmd
+45af TOTOSTRP
+45b2 SetVarName
+45b5 DispDone
+45b8 FinishOutput
+45bb CurBlink
+45be CursorOff
+45c1 HideCursor
+45c4 CursorOn
+45c7 ShowCursor
+45ca KeyToString
+45cd PullDownChk
+45d0 MenuCatCommon
+45d3 LoadCurCat
+45d6 NCifprgmedmode
+45d9 LoadMenuNum
+45dc LoadMenuNumL
+ 45df
+45e2 MenCatRet
+45e5 NotAlphNum
+45e8 SaveSavedFlags
+45eb SetMenuFlags
+45ee RstrSomeFlags
+45f1 RstrSmallText
+45f4 DispListName
+45f7 RstrOScreen
+45fa SaveOScreen
+45fd DispLAlphaName
+4600 AbortPrgmode
+4603 Is_FullCntx
+4606 AdrMRow
+4609 AdrMEle
+460c GetMatOP1A
+460f GetM1ToOP1
+4612 GetM1TOP1A
+4615 GetMToOP1
+4618 PutToM1A
+461b PutToMa1
+461e PutToMat
+4621 Mat_El_Div
+4624 CMATFUN
+4627 RowEch_Poly
+462a RowEchelon
+462d AdrLEle
+4630 GetL1ToOP1
+4633 GetL1TOP1A
+4636 GetLToOP1
+4639 GetL1TOOP2
+463c GetL1TOP2A
+463f GetL2TOP1A
+4642 PutToLA1
+4645 PutToL
+4648 MaxMinLst
+464b LLow
+464e LHigh
+4651 LSum
+4654 CumSum
+4657 ToFrac
+465a SeqSet
+465d SeqSolve
+4660 Cmp_Num_Init
+4663 BinOPExec
+4666 ExMean1
+4669 Set2MVLPtrs
+466c SetMat1
+466f CreateTList
+4672 UnOPExec
+4675 ThreeExec
+4678 RestoreErrNo
+467b FourExec
+467e FiveExec
+4681 CpyTo2ES1
+4684 CpyTo6ES1
+4687 CpyTo1ES1
+468a CpyTo3ES1
+468d CpyTo3ES2
+4690 CpyTo2ES2
+4693 CpyTo1ES2
+4696 CpyTo2ES3
+4699 CpyTo1ES3
+469c CpyTo3ES4
+469f CpyTo6ES3
+46a2 CpyTo2ES4
+46a5 CpyTo1ES4
+46a8 CpyTo2ES5
+46ab CpyTo1ES5
+46ae CpyTo4EST
+46b1 CpyTo2EST
+46b4 CpyTo1EST
+46b7 CpyTo2ES6
+46ba CpyTo1ES6
+46bd CpyTo2ES7
+46c0 CpyTo1ES7
+46c3 CpyTo2ES8
+46c6 CpyTo1ES8
+46c9 CpyTo1ES9
+46cc CpyTo2ES9
+46cf CpyTo2ES10
+46d2 CpyTo1ES10
+46d5 CpyTo2ES11
+46d8 CpyTo1ES11
+46db CpyTo2ES12
+46de CpyTo1ES12
+46e1 CpyTo2ES13
+46e4 CpyTo1ES13
+46e7 CpyTo1ES14
+46ea CpyTo1ES16
+46ed CpyTo1ES17
+46f0 CpyTo1ES18
+46f3 CpyTo1ES15
+46f6 CpyTo2ES15
+46f9 CpyO1ToEST
+46fc CpyO1ToES1
+46ff CpyO6ToES1
+4702 CpyO6ToES3
+4705 CpyO1ToES2
+4708 CpyO2ToES2
+470b CpyO1ToES3
+470e CpyO1ToES4
+4711 CpyO1ToES5
+4714 CpyO1ToES6
+4717 CpyO1ToES7
+471a CpyO2ToES4
+471d CpyO2ToES5
+4720 CpyO2ToES6
+4723 CpyO2ToES7
+4726 CpyO2ToES8
+4729 CpyO2ToES9
+472c CpyO1ToES8
+472f CpyO1ToES9
+4732 CpyO1ToES10
+4735 CpyO1ToES11
+4738 CpyO1ToES12
+473b CpyO1ToES13
+473e CpyO1ToES14
+4741 EvalF3A
+4744 GetK
+4747 SetTitle
+474a DispVarVal
+474d RecallEd
+4750 SetupBuffer
+4753 CreateNumEditBuf
+4756 CallCommon
+4759 CommonKeys
+475c Leftmore
+475f fDel
+4762 fClear
+4765 fInsDisp
+4768 fInsDisp02
+476b SetIndicator
+476e CloseEditBufNoR
+4771 ReleaseBuffer
+4774 VarNameToOP1HL
+4777 NameToOP1
+477a numPPutAway
+477d numRedisp
+4780 numError02
+4783 Load_SFont
+4786 SFont_Len
+4789 InitNumVec
+478c SetXXOP1
+478f SetXXOP2
+4792 SetXXXXOP2
+4795 UCLineS
+4798 CLine
+479b CLineS
+479e XRootY
+47a1 YToX
+47a4 ZmStats
+47a7 Point_Stat_Hlp
+47aa DrawSPlot
+47ad InitNewTraceP
+47b0 SPlotCoord
+47b3 SPlotRight
+47b6 SPlotLeft
+47b9 CmpBoxInfo
+47bc NextPlot
+47bf PrevPlot
+47c2 ClrPrevPlot
+47c5 Put_Index_Lst
+47c8 Get_Index_Lst
+47cb Heap_Sort
+47ce StoGDB2
+47d1 RclGDB2
+47d4 CircCmd
+47d7 GrphCirc
+47da Mov18B
+47dd DarkLine
+47e0 ILine
+47e3 IPoint
+47e6 XYRndBoth
+47e9 XYRnd
+47ec CheckTop
+47ef CheckXY
+47f2 DarkPnt
+47f5 CPointS
+47f8 WToV
+47fb VtoWHLDE
+47fe Xitof
+4801 YftoI
+4804 XftoI
+4807 TraceOff
+480a GrRedisp
+480d GDispToken
+4810 GRDECODA
+4813 LabCoor
+4816 CoorDisp
+4819 TmpEquNoSrc
+481c GrLabels
+481f YPixSet
+4822 XPixSet
+4825 CopyRng
+4828 ValCur
+482b GrPutAway
+482e RstGFlags
+4831 GrReset
+4834 XYCent
+4837 ZoomXYCmd
+483a CptDelY
+483d CptDelX
+4840 SetFuncM
+4843 SetSeqM
+4846 SetPolM
+4849 SetParM
+484c ZmInt
+484f ZmDecml
+4852 ZmPrev
+4855 ZmUsr
+4858 SetUZm
+485b ZmFit
+485e ZmSquare
+4861 ZmTrig
+4864 SetXMinMax
+4867 ZooDefault
+486a GrBufCpy
+486d DrawSplitLine
+4870 RestoreDisp
+4873 FNDDB
+4876 AllEq
+4879 FndAllSelEq
+487c NextEq
+487f PrevEq
+4882 BlinkGCur
+4885 NBCursor
+4888 StatMark
+488b ChkTextCurs
+488e Regraph
+4891 DoRefFlags02
+4894 YRes
+4897 PlotPtXY2
+489a Ceiling
+489d PutXY
+48a0 PutEquNo
+48a3 PDspGrph
+48a6 HorizCmd
+48a9 VertCmd
+48ac LineCmd
+48af UnLineCmd
+48b2 PointCmd
+48b5 PixelTest
+48b8 PixelCmd
+48bb TanLnF
+48be DrawCmd_Init
+48c1 DrawCmd
+48c4 ShadeCmd
+48c7 InvCmd
+48ca StatShade
+48cd DspMatTable
+48d0 DspLsts
+48d3 CloseEditBuf
+48d6 ParseEditBuf
+48d9 PutSM
+48dc DspCurTbl
+48df DspGrTbl
+48e2 ZeroTemplate
+48e5 SetTblRefs
+48e8 DispTblBot
+48eb DispTblTop
+48ee DispTblBody
+48f1 VPutBlank
+48f4 TblTrace
+48f7 DispListNameY
+48fa CurNameLength
+48fd NameToBuf
+4900 JPromptCursor
+4903 BufLeft
+4906 BufRight
+4909 BufInsert
+490c BufQueueChar
+490f BufReplace
+4912 BufDelete
+4915 BufPeek
+4918 BufPeek1
+491b BufPeek2
+491e BufPeek3
+4921 BufToBtm
+4924 SetupEditEqu
+4927 BufToTop
+492a IsEditFull
+492d IsEditEmpty
+4930 IsAtTop
+4933 IsAtBtm
+4936 BufClear
+4939 JCursorFirst
+493c JCursorLast
+493f CursorLeft
+4942 JCursorRight
+4945 JCursorUp
+4948 CursorDown
+494b CursorToOffset
+494e InsDisp
+4951 FDispBOL1
+4954 FDispBOL
+4957 DispEOW
+495a DispHead
+495d DispTail
+4960 PutTokString
+4963 SetupEditCmd
+4966 SetEmptyEditEqu
+4969 SetEmptyEditPtr
+496c CloseEditEqu
+496f GetPrevTok
+4972 GetKey
+4975 CanIndic
+4978 LCD_DRIVERON
+497b DFMIN2
+497e FormDisp
+4981 FormMatrix
+4984 WScrollLeft
+4987 WScrollUp
+498a WScrollDown
+498d WScrollRight
+4990 FormEReal
+4993 FormERealTok
+4996 FormDCplx
+4999 FormReal
+499c FormScrollUp
+499f SetWinAbove
+49a2 DisarmScroll
+49a5 OP1toEdit
+49a8 MinToEdit
+49ab RclVarToEdit
+49ae RclVarToEditPtr
+49b1 RclEntryToEdit
+49b4 RclToQueue
+49b7 FormToTok
+49ba Disp_Interval
+49bd DispLstName
+49c0 DispSLstNameHL
+49c3 EditEqu
+49c6 CloseEquField
+49c9 AutoSelect
+49cc DispYEOS
+49cf DispNumEOS
+49d2 SetupDispEq
+49d5 DispForward
+49d8 DispYPrompt2
+49db StringWidth
+49de DispErrorScreen
+49e1 PopCx
+49e4 LoadNoEEntry
+49e7 SaveScreen
+49ea RetScreen
+49ed RetScreenErr
+49f0 CheckSplitFlag
+49f3 SolveRedisp
+49f6 SolveDisp
+49f9 ItemName
+49fc SetNorm_Vals
+49ff SetVert_Vals
+4a02 ConvKeyToTok
+4a05 KeyToTokNew2B
+4a08 KeyToTok2Byte
+4a0b TokToKey
+4a0e Send1BErr
+4a11 GetVarCmd
+4a14 SendVarCmd
+4a17 PrintScreen
+4a1a KeyScnLnk
+4a1d IOResetAll
+4a20 DelRes
+4a23 ConvLcToLr
+4a26 RedimMat
+4a29 IncLstSize
+4a2c InsertList
+4a2f DelListEl
+4a32 EditProg
+4a35 CloseProg
+4a38 ClrGraphRef
+4a3b FixTempCnt
+4a3e SaveData
+4a41 RestoreData
+4a44 FindAlphaUp
+4a47 FindAlphaDn
+4a4a CmpSyms
+4a4d CreateTemp
+4a50 CleanAll
+4a53 MoveToNextSym
+4a56 ConvLrToLc
+4a59 TblScreenDn
+4a5c TblScreenUp
+4a5f ScreenUp
+4a62 ScreenUpDown
+4a65 ZIfRclHandler
+4a68 ZIfRclKApp
+4a6b RclKey
+4a6e RclKey2
+4a71 RclRegEq
+4a74 RclRegEq2
+4a77 InitNamePrompt
+4a7a NamePrompt2
+4a7d CatalogChk
+4a80 ClrTR
+4a83 Quad
+4a86 GraphQuad
+4a89 BC2NonReal
+4a8c ErrNonReal
+4a8f Write_Text
+4a92 ForSeqInit
+4a95 GrphPars
+4a98 PlotPars
+4a9b ParseInp
+4a9e ParseOff
+4aa1 ParseScan
+4aa4 GetParse
+4aa7 SaveParse
+4aaa InitPFlgs
+4aad CkEndLinErr
+4ab0 OP2Set60
+4ab3 GetStatPtr
+4ab6 Cmp_StatPtr
+4ab9 VarSysAdr
+4abc StoSysTok
+4abf StoAns
+4ac2 StoTheta
+4ac5 StoR
+4ac8 StoY
+4acb StoN
+4ace StoT
+4ad1 StoX
+4ad4 StoOther
+4ad7 RclAns
+4ada RclY
+4add RclN
+4ae0 RclX
+4ae3 RclVarSym
+4ae6 RclSysTok
+4ae9 StMatEl
+4aec StLstVecEl
+4aef ConvOP1
+4af2 Find_Parse_Formula
+4af5 Parse_Formula
+4af8 StrngEnt1
+4afb PrgRdLp
+4afe VarEnt
+4b01 ParseOnC
+4b04 ParseOn
+4b07 ParseCmd
+4b0a StoType
+4b0d CreatePair
+4b10 PushNum
+4b13 IncCurPCErrEnd
+4b16 ErrEnd
+4b19 CommaErrF
+4b1c CommaErr
+4b1f StEqArg2
+4b22 StEqArg
+4b25 InpArg
+4b28 StEqArg3
+4b2b NxtFetch
+4b2e CkFetchVar
+4b31 FetchVarA
+4b34 FetchVar
+4b37 CkEndLin
+4b3a CkEndExp
+4b3d CkParsEnd
+4b40 StoTypeArg
+4b43 ConvDim
+4b46 ConvDim00
+4b49 AheadEqual
+4b4c ParsAheadS
+4b4f ParsAhead
+4b52 AnsName
+4b55 StoCmpReals
+4b58 GetDEPtr
+4b5b Push2BOper
+4b5e Pop2BOper
+4b61 PushOper
+4b64 PopOper
+4b67 Find_E_UndefOrArchived
+4b6a StTmpEq
+4b6d FindEOL
+4b70 BrkInc
+4b73 IncFetch
+4b76 CurFetch
+4b79 Random
+4b7c StoRand
+4b7f RandInit
+4b82 ResetStacks
+4b85 Factorial
+4b88 YOnOff
+4b8b EqSelUnsel
+4b8e ITSOLVER
+4b91 GRITSOLVER
+4b94 ITSOLVERB
+4b97 ITSOLVERNB
+4b9a ExTest_INT
+4b9d Dist_Fun
+4ba0 LogGamma
+4ba3 OneVar
+4ba6 OneVarS_0
+4ba9 OrdStat
+4bac InitStatAns2
+4baf ANOVA_Spec
+4bb2 OutputExpr
+4bb5 CentCursor
+4bb8 Text
+4bbb FinishSpec
+4bbe TRCYFUNC
+4bc1 Rcl_Seq_X
+4bc4 RclSeq2
+4bc7 GrPPutAway
+4bca CkValDelX
+4bcd CkValDelta
+4bd0 GrBufClr
+4bd3 GrBufCpy_V
+4bd6 FndSelEq
+4bd9 ClrGraphXY
+4bdc Next_Y_Style
+4bdf PlotPt
+4be2 NewIndep
+4be5 Axes
+4be8 SetPenX
+4beb SetPenY
+4bee SetPenT
+4bf1 Tan_Equ_Disp
+4bf4 PutAns
+4bf7 DispOP1A
+4bfa MathTanLn
+4bfd EndDraw
+4c00 SetTblGraphDraw
+4c03 StartDialog
+4c06 DialogInit
+4c09 GetDialogNumOP1
+4c0c SetDialogNumOP1
+4c0f GetDialogNumHL
+ 4c12
+4c15 SetDialogKeyOverride
+4c18 ResDialogKeyOverride
+4c1b ForceDialogKeypress
+4c1e DialogStartGetKey
+4c21 StartDialog_Override
+4c24 CallDialogCallback
+4c27 SetDialogCallback
+4c2a ResDialogCallback
+4c2d CopyDialogNum
+4c30 MemClear
+4c33 MemSet
+4c36 ReloadAppEntryVecs
+4c39 PointOn
+4c3c ExecuteNewPrgm
+4c3f StrLength
+4c42 UserPutMap
+4c45 GetCurrentPageSub
+4c48 FindAppUp
+4c4b FindAppDn
+4c4e FindApp
+4c51 ExecuteApp
+4c54 MonReset
+ 4c57
+ 4c5a
+ 4c5d
+4c60 IBounds
+4c63 IOffset
+4c66 DrawCirc2
+4c69 CanAlphIns
+4c6c Redisp
+4c6f GetBaseVer
+4c72 SetFP0
+4c75 AppGetCbl
+4c78 AppGetCalc
+4c7b SaveDisp
+4c7e SetIgnoreKey
+4c81 SetSendThisKeyBack
+4c84 DisableApd
+4c87 EnableApd
+ 4c8a
+ 4c8d
+4c90 forcecmd
+4c93 ApdSetup
+4c96 Get_NumKey
+4c99 AppSetup
+4c9c HandleLinkActivity
+ 4c9f
+4ca2 ReleaseSedit
+4ca5 initsmalleditline
+4ca8 startsmalledit
+ 4cab
+4cae SGetTokString
+4cb1 LoadPattern
+4cb4 SStringLength
+ 4cb7
+ 4cba
+4cbd DoNothing
+ 4cc0
+ 4cc3
+ 4cc6
+ 4cc9
+ 4ccc
+4ccf SmallEditEraseEOL
+ 4cd2
+ 4cd5
+ 4cd8
+4cdb initsmalleditBox
+ 4cde
+4ce1 EmptyHook
+ 4ce4
+ 4ce7
+ 4cea
+4ced ClearRow
+ 4cf0
+4cf3 SetupSmallEditCursor
+ 4cf6
+ 4cf9
+ 4cfc
+ 4cff
+ 4d02
+ 4d05
+ 4d08
+ 4d0b
+ 4d0e
+ 4d11
+ 4d14
+ 4d17
+ 4d1a
+ 4d1d
+ 4d20
+ 4d23
+4d26 AppScreenUpDown
+4d29 AppScreenUpDown1
+ 4d2c
+4d2f initsmalleditlinevar
+4d32 initsmalleditlineop1
+4d35 initsmalleditboxvar
+4d38 initsmalleditboxop1
+ 4d3b
+ 4d3e
+4d41 ErrCustom1
+4d44 ErrCustom2
+4d47 AppStartMouse
+ 4d4a
+ 4d4d
+ 4d50
+4d53 AppEraseMouse
+ 4d56
+4d59 ATimes12
+4d5c ClearRect
+4d5f InvertRect
+4d62 FillRect
+4d65 AppUpdateMouse
+ 4d68
+ 4d6b
+4d6e initcellbox
+4d71 drawcell
+ 4d74
+4d77 invertcell
+4d7a setcelloverride
+4d7d DrawRectBorder
+4d80 ClearCell
+4d83 covercell
+4d86 EraseRectBorder
+4d89 FillRectPattern
+4d8c DrawRectBorderClear
+ 4d8f
+ 4d92
+4d95 VerticalLine
+4d98 IBoundsFull
+4d9b DisplayImage
+ 4d9e
+ 4da1
+ 4da4
+ 4da7
+ 4daa
+ 4dad
+ 4db0
+ 4db3
+ 4db6
+ 4db9
+ 4dbc
+ 4dbf
+ 4dc2
+ 4dc5
+4dc8 CPoint
+4dcb DeleteApp
+ 4dce
+4dd1 setmodecellflag
+4dd4 resetmodecellflag
+4dd7 ismodecellset
+4dda getmodecellflag
+ 4ddd
+4de0 CellBoxManager
+4de3 startnewcell
+ 4de6
+4de9 CellCursorHandle
+ 4dec
+ 4def
+4df2 ClearCurCell
+4df5 drawcurcell
+4df8 invertcurcell
+4dfb covercurcell
+4dfe BlinkCell
+4e01 BlinkCellNoLookUp
+4e04 BlinkCurCell
+4e07 BlinkCellToOn
+4e0a BlinkCellToOnNoLookUp
+4e0d BlinkCurCellToOn
+4e10 BlinkCellToOff
+4e13 BlinkCellToOffNoLookUp
+4e16 BlinkCurCellToOff
+4e19 getcurmodecellflag
+ 4e1c
+4e1f startsmalleditreturn
+ 4e22
+ 4e25
+4e28 CellkHandle
+4e2b errchkalphabox
+ 4e2e
+ 4e31
+ 4e34
+ 4e37
+4e3a eraseallcells
+4e3d iscurmodecellset
+ 4e40
+4e43 initalphabox
+ 4e46
+ 4e49
+4e4c drawblnkcell
+4e4f ClearBlnkCell
+4e52 invertblnkcell
+ 4e55
+ 4e58
+ 4e5b
+ 4e5e
+ 4e61
+ 4e64
+4e67 HorizontalLine
+4e6a CreateAppVar
+4e6d CreateProtProg
+4e70 CreateVar
+4e73 AsmComp
+4e76 GetAsmSize
+4e79 SquishPrgm
+4e7c ExecutePrgm
+4e7f ChkFindSymAsm
+4e82 ParsePrgmName
+4e85 CSub
+4e88 CAdd
+4e8b CSquare
+4e8e CMult
+4e91 CRecip
+4e94 CDiv
+4e97 CAbs
+4e9a CSqrAbs
+4e9d CSqRoot
+4ea0 CLN
+4ea3 CLog
+4ea6 CTenX
+4ea9 CEtoX
+4eac CXrootY
+ 4eaf
+4eb2 CYtoX
+4eb5 Conj
+4eb8 CMltByReal
+4ebb CDivByReal
+4ebe CTrunc
+4ec1 CFrac
+4ec4 CIntgr
+4ec7 SendHeaderPacket
+4eca CancelTransmission
+4ecd SendScreenContents
+4ed0 SendRAMVarData
+4ed3 SendRAMCmd
+4ed6 SendPacket
+4ed9 ReceiveAck
+4edc Send4BytePacket
+4edf SendDataByte
+4ee2 Send4Bytes
+4ee5 SendAByte
+4ee8 SendCByte
+4eeb GetSmallPacket
+4eee GetDataPacket
+4ef1 SendAck
+4ef4 Get4Bytes
+4ef7 Get3Bytes
+4efa Rec1stByte
+4efd Rec1stByteNC
+4f00 ContinueGetByte
+4f03 RecAByteIO
+4f06 ReceiveVar
+4f09 ReceiveVarData2
+4f0c ReceiveVarData
+4f0f SrchVLstUp
+4f12 SrchVLstDn
+4f15 SendVariable
+4f18 Get4BytesCursor
+4f1b Get4BytesNC
+ 4f1e
+4f21 SendDirectoryContents
+4f24 SendReadyPacket
+ 4f27
+ 4f2a
+ 4f2d
+4f30 SendApplication
+4f33 SendOSHeader
+4f36 SendOSPage
+4f39 SendOS
+4f3c FlashWriteDisable
+4f3f SendCmd
+4f42 SendOSSignature
+4f45 Disp
+4f48 SendGetKeyPress
+4f4b RejectCommand
+4f4e CheckLinkLines
+4f51 GetHookByte
+4f54 LoadBIndPaged
+4f57 CursorHook
+4f5a LibraryHook
+4f5d RawKeyHook
+4f60 SetCursorHook
+4f63 SetLibraryHook
+4f66 SetRawKeyHook
+4f69 ClrCursorHook
+4f6c ClrLibraryHook
+4f6f ClrRawKeyHook
+4f72 ResetHookBytes
+4f75 AdjustAllHooks
+4f78 GetKeyHook
+4f7b SetGetKeyHook
+4f7e ClrGetKeyHook
+4f81 LinkActivityHook
+4f84 SetLinkActivityHook
+4f87 ClrLinkActivityHook
+ 4f8a
+4f8d SetCatalog2Hook
+4f90 ClrCatalog2Hook
+4f93 SetLocalizeHook
+4f96 ClrLocalizeHook
+4f99 SetTokenHook
+4f9c ClrTokenHook
+ 4f9f
+ 4fa2
+ 4fa5
+4fa8 Bit_VertSplit
+4fab SetHomeScreenHook
+4fae ClrHomeScreenHook
+4fb1 SetWindowHook
+4fb4 ClrWindowHook
+4fb7 SetGraphHook
+4fba ClrGraphHook
+ 4fbd
+ 4fc0
+ 4fc3
+4fc6 DelVarArc
+4fc9 DelVarNoArc
+4fcc SetAllPlots
+4fcf SetYEquHook
+4fd2 ClrYEquHook
+4fd5 ForceYEqu
+4fd8 Arc_Unarc
+4fdb ArchiveVar
+4fde UnarchiveVar
+4fe1 ResDialogKeyOverride
+4fe4 SetFontHook
+4fe7 ClrFontHook
+4fea SetRegraphHook
+4fed ClrRegraphHook
+4ff0 RegraphHook
+4ff3 SetTraceHook
+4ff6 ClrTraceHook
+4ff9 TraceHook
+ 4ffc
+ 4fff
+5002 JForceGraphNoKey
+5005 JForceGraphKey
+5008 PowerOff
+500b GetKeyRetOff
+500e FindGroupSym
+5011 FillBasePageTable
+5014 ArcChk
+5017 FlashToRam
+501a LoadDEIndPaged
+501d LoadCIndPaged
+5020 SetupPagedPtr
+5023 PagedGet
+5026 SetParserHook
+5029 ClrParserHook
+502c SetAppChangeHook
+502f ClrAppChangeHook
+5032 SetDrawingHook
+5035 ClrDrawingHook
+5038 IPoint_NoHook
+503b ILine_NoHook
+503e CLineS_NoHook
+5041 DeleteTempPrograms
+5044 SetCatalog1Hook
+5047 ClrCatalog1Hook
+504a SetHelpHook
+504d ClrHelpHook
+ 5050
+ 5053
+ 5056
+5059 Catalog2Hook
+505c Catalog1Hook
+ 505f
+ 5062
+5065 DispMenuTitle
+ 5068
+506b SetCxRedispHook
+506e ClrCxRedispHook
+5071 BufCpy
+5074 BufClr
+ 5077
+ 507a
+ 507d
+5080 DisplayVarInfo
+5083 SetMenuHook
+5086 ClrMenuHook
+5089 GetBCOffsetIX
+ 508c
+508f ForceFullScreen
+5092 GetVariableData
+5095 FindSwapSector
+5098 CopyFlashPage
+509b FindAppNumPages
+509e HLMinus5
+50a1 SendArcPacket
+50a4 ForceGraphKeypress
+ 50a7
+50aa FormBase
+ 50ad
+50b0 IsFragmented
+50b3 Chk_Batt_Low
+50b6 Chk_Batt_Low2
+
+## OS 1.10
+50b9 Arc_Unarc2
+
+## OS 1.13
+50bc GetAppBasePage
+50bf SetExSpeed
+ 50c2
+50c5 GroupAllVars
+50c8 UngroupVar
+50cb WriteToFlash
+50ce SetSilentLinkHook
+50d1 ClrSilentLinkHook
+50d4 TwoVarSet
+ 50d7
+ 50da
+50dd GetSysInfo
+50e0 NZIf83Plus
+50e3 LinkStatus
+
+## OS 1.15
+ 50e6
+50e9 DBusKeyScn
+
+## OS 2.21
+50ec RunAppLib
+50ef FindSpecialAppHeader
+ 50f2
+ 50f5
+ 50f8
+50fb GetVarCmdUSB
+
+## OS 2.30
+ 50fe
+ 5101
+ 5104
+ 5107
+510a GetVarVersion
+ 510d
+ 5110
+ 5113
+ 5116
+ 5119
+ 511c
+ 511f
+5122 InvertTextInsMode
+ 5125
+5128 ResetDefaults
+ 512b
+512e DispHeader
+5131 ForceGroup
+ 5134
+ 5137
+ 513a
+ 513d
+ 5140
+5143 GetRelSeconds
+5146 DisableClock
+5149 EnableClock
+514c GetDayOfWeek
+514f GetDate
+5152 FormDate
+5155 GetDateFmt
+5158 FormDateString
+515b GetTime
+515e FormTime
+5161 GetTimeFmt
+5164 FormTimeString
+5167 GetClockStatus
+516a SetDateMkList
+516d SetDateFmt
+5170 SetTimeMkList
+5173 SetTimeFmt
+5176 GetAbsSeconds
+5179 AbsSecondsToTimeList
+ 517c
+517f ClrWindowAndFlags
+5182 SetMachineID
+5185 ResetLists
+ 5188
+ 518b
+ 518e
+5191 ExecLib
+ 5194
+ 5197
+ 519a
+519d OpenLib
+51a0 WaitEnterKey
+ 51a3
+ 51a6
+ 51a9
+ 51ac
+ 51af
+ 51b2
+ 51b5
+51b8 IsOP1Resid
+ 51bb
+ 51be
+ 51c1
+ 51c4
+51c7 DispAboutScreen
+51ca ChkHelpHookVer
+51cd Disp32
+ 51d0
+ 51d3
+ 51d6
+ 51d9
+51dc DrawTableEditor
+ 51df
+ 51e2
+ 51e5
+ 51e8
+ 51eb
+ 51ee
+51f1 MatrixName
+ 51f4
+ 51f7
+ 51fa
+ 51fd
+ 5200
+ 5203
+ 5206
+ 5209
+ 520c
+ 520f
+ 5212
+ 5215
+ 5218
+ 521b
+ 521e
+5221 Chk_Batt_Level
+ 5224
+ 5227
+ 522a
+ 522d
+ 5230
+5233 GoToLastRow
+5236 RectBorder
+ 5239
+ 523c
+ 523f
+5242 LoadA5
+ 5245
+5248 NamedListToOP1
+ 524b
+ 524e
+ 5251
+ 5254
+ 5257
+ 525a
+ 525d
+ 5260
+ 5263
+ 5266
+5269 CheckUSBAutoLaunchHeader
+ 526c
+ 526f
+ 5272
+ 5275
+ 5278
+ 527b
+ 527e
+ 5281
+5284 SetVertGraphActive
+5287 ClearVertGraphActive
+528a SetUSBHook
+528d ClrUSBHook
+5290 InitUSBDevice
+5293 KillUSBPeripheral
+ 5296
+ 5299
+529c GraphLine
+ 529f
+ 52a2
+ 52a5
+ 52a8
+ 52ab
+ 52ae
+52b1 ZifTableEditor
+ 52b4
+ 52b7
+ 52ba
+52bd FindAppName
+ 52c0
+ 52c3
+ 52c6
+52c9 BufCpyCustom
+ 52cc
+
+## OS 2.40
+ 52cf
+ 52d2
+ 52d5
+ 52d8
+ 52db
+ 52de
+ 52e1
+52e4 DelVarSym
+52e7 FindAppUpNoCase
+52ea FindAppDnNoCase
+52ed DeleteInvalidApps
+52f0 DeleteApp_Link
+ 52f3
+52f6 SetAppRestrictions
+52f9 RemoveAppRestrictions
+52fc CheckAppRestrictions
+52ff DispAppRestrictions
+5302 SetupHome
+ 5305
+ 5308
+ 530b
+ 530e
+ 5311
+5314 PolarEquToOP1
+ 5317
+ 531a
+531d GetRestrictionsOptions
+5320 DispResetComplete
+ 5323
+5326 FindAppCustom
+5329 ClearGraphStyles
+
+## Boot
+8018 MD5Final
+801B RSAValidate
+801E BigNumCompare
+8021 WriteAByteUnsafe
+8024 EraseFlash
+8027 FindFirstCertificateField
+802A ZeroToCertificate
+802D GetCertificateEnd
+8030 FindGroupedField
+8033 DoNothing0
+8036 DoNothing1
+8039 DoNothing2
+803C DoNothing3
+803F DoNothing4
+8042 ATimesE
+8045 ATimesDE
+8048 DivHLByE
+804B DivHLByDE
+8051 LoadAIndPaged
+8054 FlashToRAM2
+8057 GetCertificateStart
+805A GetFieldSize
+805D FindSubField
+8060 EraseCertificateSector
+8063 CheckHeaderKey
+806C Load_BootLFontV2
+806F Load_BootLFontV
+8072 OSReceive
+8075 FindOSHeaderSubField
+8078 FindNextCertificateField
+807B RecAByteBoot
+807E GetCalcSerial
+8084 EraseFlashPage
+8087 WriteFlashUnsafe
+808A DispBootVer
+808D MD5Init
+8090 MD5Update
+8093 MarkOSInvalid
+8096 FindAppKey
+8099 MarkOSValid
+809C CheckOSValid
+809F SetupAppPubKey
+80A2 RabinValidate
+80A5 TransformHash
+80A8 IsAppFreeware
+80AB FindAppHeaderSubField
+80AE RecalcValidationBytes
+80B1 Div32ByDE
+80B4 FindSimpleGroupedField
+80B7 GetBootVer
+80BA GetHWVer
+80BD XorA
+80C0 RSAValidateBigB
+80C3 ProdNrPart1
+80C6 WriteAByteSafe
+80C9 WriteFlashSafe
+80CC SetupDateStampPubKey
+80CF SetAppLimit
+80D2 BatteryError
+
+## 84+ Boot
+80E4 USBBootMainLoop
+80E7 DisplaySysMessage
+80EA NewLine2
+80ED DisplaySysErrorAndTurnOff
+80F0 CheckBattery
+80F3 CheckBattery46
+80F6 OSReceiveUSB
+80F9 OSPacketSetup
+80FC ForceReboot
+80FF SetupOSPubKey
+8102 CheckHeaderKeyHL
+
+[labels]
+8000 ramStart
+8000 appData
+8100 ramCode
+822F ramCodeEnd
+8230 baseAppBrTab
+8251 bootTemp
+8269 MD5Length
+8292 MD5Hash
+82A3 appSearchPage
+82A5 tempSwapArea
+83A5 MD5Buffer
+838D appID
+83ED ramReturnData
+83EE arcInfo
+8406 savedArcInfo
+8432 appInfo
+843C appBank_jump
+843E appPage
+843F kbdScanCode
+8440 kbdLGSC
+8441 kbdPSC
+8442 kbdWUR
+8443 kbdDebncCnt
+8444 kbdKey
+8445 kbdGetKy
+8446 keyExtend
+8447 contrast
+8448 apdSubTimer
+8449 apdTimer
+844A curTime
+844B curRow
+844C curCol
+844D curOffset
+844E curUnder
+844F curY
+8450 curType
+8451 curXRow
+8452 prevDData
+845A lFont_record
+8462 sFont_record
+846A tokVarPtr
+846C tokLen
+846E indicMem
+8476 indicCounter
+8477 indicBusy
+8478 OP1
+8483 OP2
+848E OP3
+8499 OP4
+84A4 OP5
+84AF OP6
+84BF progToEdit
+84C7 nameBuff
+84D2 equ_edit_save
+84D3 iMathPtr1
+84D5 iMathPtr2
+84D7 iMathPtr3
+84D9 iMathPtr4
+84DB iMathPtr5
+84DD chkDelPtr1
+84DF chkDelPtr2
+84E1 insDelPtr
+84E3 upDownPtr
+84E5 fOutDat
+84EB asm_data_ptr1
+84ED asm_data_ptr2
+84EF asm_sym_ptr1
+84F1 asm_sym_ptr2
+84F3 asm_ram
+8507 asm_ind_call
+8508 textShadow
+8588 textShadCur
+858A textShadTop
+858B textShadAlph
+858C textShadIns
+858D cxMain
+858F cxPPutAway
+8591 cxPutAway
+8593 cxRedisp
+8595 cxErrorEP
+8597 cxSizeWind
+8599 cxPage
+859A cxCurApp
+859B cxPrev
+85AA monQH
+85AB monQT
+85AC monQueue
+85BC onSP
+85BE onCheckSum
+85C0 promptRow
+85C1 promptCol
+85C2 promptIns
+85C3 promptShift
+85C4 promptRet
+85C6 promptValid
+85C8 promptTop
+85CA promptCursor
+85CC promptTail
+85CE promptBtm
+85D0 varType
+85D1 varCurrent
+85D9 varClass
+85DA catCurrent
+85DC menuActive
+85DD menuAppDepth
+85DE menuCurrent
+85E8 progCurrent
+85FE userMenuSA
+865F ioPrompt
+8660 RectFillPHeight
+8660 dImageWidth
+8661 RectFillPWidth
+8662 RectFillPattern
+8670 ioFlag
+8672 sndRecState
+8673 ioErrState
+8674 header
+867D ioData
+8689 ioNewData
+868B bakHeader
+86B7 calc_id
+86D7 penCol
+86D8 penRow
+86D9 rclQueue
+86DB rclQueueEnd
+86DD errNo
+86DE errSP
+86E0 errOffset
+86EC saveSScreen
+89EC usermem_offset
+89EE bstCounter
+89F0 flags
+8A3A statVars
+8C17 anovaf_vars
+8C4D infVars
+8D17 curGStyle
+8D18 curGY
+8D19 curGX
+8D1A curGY2
+8D1B curGX2
+8D1C freeSaveY
+8D1D freeSaveX
+8DA1 XOffset
+8DA2 YOffset
+8DA3 lcdTallP
+8DA4 pixWideP
+8DA5 pixWide_m_1
+8DA6 pixWide_m_2
+8DA7 lastEntryPtr
+8DA9 lastEntryStk
+8E29 numLastEntries
+8E2A currLastEntry
+8E67 curInc
+8E6A ORGXMIN
+8EB4 uThetMin
+8EBD uThetMax
+8EC6 uThetStep
+8ECF uTmin
+8ED8 uTmax
+8EE1 uTStep
+8E7E uXmin
+8E87 uXmax
+8E90 uXscl
+8E99 uYmin
+8EA2 uYmax
+8EAB uYscl
+8EEA uPlotStart
+8EF3 unMax
+8EFC uu0
+8F05 uv0
+8F0E unMin
+8F17 uu02
+8F20 uv02
+8F29 uw0
+8F32 uPlotStep
+8F3B uXres
+8F44 uw02
+8F50 Xmin
+8F59 Xmax
+8F62 Xscl
+8F6B Ymin
+8F74 Ymax
+8F7D Yscl
+8FB3 Tstep
+8FBC PlotStart
+8FC5 nMax
+8FCE u0
+8FD7 v0
+8FE0 nMin
+8FE9 u02
+8FF2 v02
+8FFB w0
+9004 PlotStep
+900D XresO
+9016 w02
+901F un1
+9028 un2
+9031 vn1
+903A vn2
+9043 wn1
+904C wn2
+9055 fin_N
+905E fin_I
+9067 fin_PV
+9070 fin_PMT
+9079 fin_FV
+9082 fin_PY
+908B fin_CY
+9094 cal_N
+909D cal_I
+90A6 cal_PV
+90AF cal_PMT
+90B8 cal_FV
+90C1 cal_PY
+90D3 smallEditRAM
+9151 Xres_int
+913F XFact
+9148 YFact
+9152 deltaX
+915B deltaY
+9164 shortX
+916D shortY
+9176 lower
+917F upper
+8F86 ThetaMin
+8F8F ThetaMax
+8F98 ThetaStep
+8FA1 TminPar
+8FAA TmaxPar
+918C XOutSym
+918E XOutDat
+9190 YOutSym
+9192 YOutDat
+9194 inputSym
+9196 inputDat
+9198 prevData
+92C9 P1Type
+92CA SavX1List
+92CF SavY1List
+92D4 SavF1List
+92D9 P1FrqOnOff
+92DA P2Type
+92DB SavX2List
+92E0 SavY2List
+92E5 SavF2List
+92EA P2FrqOnOff
+92EB P3Type
+92EC SavX3List
+92F1 SavY3List
+92F6 SavF3List
+92FB P3FrqOnOff
+92B3 TblMin
+92BC TblStep
+9302 ES
+9340 plotSScreen
+9640 seed1
+9649 seed2
+9652 parseVar
+965B begPC
+965D curPC
+965F endPC
+9776 GY1
+9777 GY2
+9778 GY3
+9779 GY4
+977A GY5
+977B GY6
+977C GY7
+977D GY8
+977E GY9
+977F GY0
+9780 GX1
+9781 GX2
+9782 GX3
+9783 GX4
+9784 GX5
+9785 GX6
+9786 GR1
+9787 GR2
+9788 GR3
+9789 GR4
+978A GR5
+978B GR6
+978C GU
+978D GV
+978E GW
+966E cmdShadow
+96EE cmdShadCur
+96F0 cmdShadAlph
+96F1 cmdShadIns
+96F2 cmdCursor
+96F4 editTop
+96F6 editCursor
+96F8 editTail
+96FA editBtm
+9706 editSym
+9708 editDat
+97A3 modePtr
+97A5 winTop
+97A6 winBtm
+97A7 winLeftEdge
+97A8 winLeft
+97AA winAbove
+97AC winRow
+97AE winCol
+97B0 fmtDigits
+97B1 fmtString
+97F2 fmtConv
+9804 fmtLeft
+9806 fmtIndex
+9808 fmtMatSym
+980A fmtMatMem
+980C EQS
+9815 delAdjAmt
+9818 tSymPtr1
+981A tSymPtr2
+981C chkDelPtr3
+981E chkDelPtr4
+9820 tempMem
+9822 fpBase
+9824 FPS
+9826 OPBase
+9828 OPS
+982A pTempCnt
+982C cleanTmp
+982E pTemp
+9830 progPtr
+9832 newDataPtr
+9834 pagedCount
+9835 pagedPN
+9836 pagedGetPtr
+9838 pagedPutPtr
+983A pagedBuf
+984D appErr1
+985A appErr2
+9867 flashByte1
+9868 flashByte2
+9869 freeArcBlock
+986B arcPage
+986C arcPtr
+9870 appRawKeyHandle
+9872 appBackUpScreen
+9B72 customHeight
+9B73 localLanguage
+9B78 linkActivityHookPtr
+9B7C cursorHookPtr
+9B80 libraryHookPtr
+9B84 rawKeyHookPtr
+9B88 getKeyHookPtr
+9B8C homescreenHookPtr
+9B90 windowHookPtr
+9B94 graphHookPtr
+9B98 yEquHookPtr
+9B9C fontHookPtr
+9BA0 regraphHookPtr
+9BA4 drawingHookPtr
+9BA8 traceHookPtr
+9BAC parserHookPtr
+9BB0 appChangeHookPtr
+9BB4 catalog1HookPtr
+9BB8 helpHookPtr
+9BBC cxRedispHookPtr
+9BC0 menuHookPtr
+9BC4 catalog2HookPtr
+9BC8 tokenHookPtr
+9BCC localizeHookPtr
+9BD0 silentLinkHookPtr
+9BD4 usbHookPtr
+9C06 baseAppBrTab2
+9CB0 DBKeyScanCode
+9CB1 DBKeyRptCtr
+9D65 localTokStr
+9D76 keyForStr
+9D77 keyToStrRam
+9D88 sedMonSp
+9D8A bpSave
+9D95 userMem
+0FE66 symTable
+
+[flags]
+00 kbdFlags
+0,00 inDelete,ioDelFlag
+2,00 trigDeg,trigFlags
+3,00 kbdSCR,kbdFlags
+4,00 kbdKeyPress,kbdFlags
+5,00 donePrgm,doneFlags
+01 editFlags
+2,01 editOpen,editFlags
+4,01 monAbandon,monFlags
+02 plotFlags
+0,02 plotTrace,plotFlags
+1,02 plotLoc,plotFlags
+2,02 plotDisp,plotFlags
+4,02 grfFuncM,grfModeFlags
+5,02 grfPolarM,grfModeFlags
+6,02 grfParamM,grfModeFlags
+7,02 grfRecurM,grfModeFlags
+03 graphFlags
+0,03 graphDraw,graphFlags
+1,03 graphProg,graphFlags
+04 grfDBFlags
+0,04 grfDot,grfDBFlags
+1,04 grfSimul,grfDBFlags
+2,04 grfGrid,grfDBFlags
+3,04 grfPolar,grfDBFlags
+4,04 grfNoCoord,grfDBFlags
+5,04 grfNoAxis,grfDBFlags
+6,04 grfLabel,grfDBFlags
+05 textFlags
+1,05 textEraseBelow,textFlags
+2,05 textScrolled,textFlags
+3,05 textInverse,textFlags
+4,05 textInsMode,textFlags
+07 ParsFlag2
+0,07 numOP1,ParsFlag2
+08 apdFlags
+0,08 preClrForMode,newDispF
+2,08 apdAble,apdFlags
+3,08 apdRunning,apdFlags
+09 onFlags
+0,09 appWantAlphaUpDn,alphaUpDnFlag
+3,09 onRunning,onFlags
+4,09 onInterrupt,onFlags
+6,09 statsValid,statFlags
+7,09 statANSDISP,statFlags
+0A fmtFlags
+0,0A fmtExponent,fmtFlags
+1,0A fmtEng,fmtFlags
+2,0A fmtHex,fmtFlags
+3,0A fmtOct,fmtFlags
+4,0A fmtBin,fmtFlags
+5,0A fmtReal,fmtFlags
+6,0A fmtRect,fmtFlags
+7,0A fmtPolar,fmtFlags
+0B fmtOverride
+0,0B fmtExponent,fmtOverride
+1,0B fmtEng,fmtOverride
+2,0B fmtHex,fmtOverride
+3,0B fmtOct,fmtOverride
+4,0B fmtBin,fmtOverride
+5,0B fmtReal,fmtOverride
+6,0B fmtRect,fmtOverride
+7,0B fmtPolar,fmtOverride
+0C curFlags
+0,0C fmtEdit,fmtEditFlags
+2,0C curAble,curFlags
+3,0C curOn,curFlags
+4,0C curLock,curFlags
+5,0C cmdVirgin,cmdFlags
+0D appFlags
+0,0D appWantIntrpt,appFlags
+1,0D appTextSave,appFlags
+2,0D appAutoScroll,appFlags
+3,0D appMenus,appFlags
+4,0D appLockMenus,appFlags
+5,0D appCurGraphic,appFlags
+6,0D appCurWord,appFlags
+7,0D appExit,appFlags
+0E rclFlags
+7,0E rclQueueActive
+0F seqFlags
+0,0F webMode,seqFlags
+1,0F webVert,seqFlags
+2,0F sequv,seqFlags
+3,0F seqvw,seqFlags
+4,0F sequw,seqFlags
+11 promptFlags
+0,11 promptEdit,promptFlags
+3,11 expr_param,plotFlag2
+4,11 expr_writing,plotFlag2
+12 shiftFlags
+0,12 indicRun,indicFlags
+1,12 indicInUse,indicFlags
+2,12 indicOnly,indicFlags
+3,12 shift2nd,shiftFlags
+4,12 shiftAlpha,shiftFlags
+5,12 shiftLwrAlph,shiftFlags
+6,12 shiftALock,shiftFlags
+7,12 shiftKeepAlph,shiftFlags
+13 tblFlags
+4,13 autoFill,tblFlags
+5,13 autoCalc,tblFlags
+6,13 reTable,tblFlags
+14 sGrFlags
+0,14 grfSplit,sGrFlags
+1,14 vertSplit,sGrFlags
+2,14 grfSChanged,sGrFlags
+3,14 grfSplitOverride,sGrFlags
+4,14 write_on_graph,sGrFlags
+5,14 g_style_active,sGrFlags
+6,14 cmp_mod_box,sGrFlags
+7,14 textWrite,sGrFlags
+15 newIndicFlags
+0,15 extraIndic,newIndicFlags
+1,15 saIndic,newIndicFlags
+16 newFlags2
+5,16 noRestores,newFlags2
+17 smartFlags
+0,17 smartGraph,smartFlags
+1,17 smartGraph_inv,smartFlags
+1A more_Flags
+2,1A No_Del_Stat,more_Flags
+0,1D gkKeyRepeating,gkFlag
+21 asm_Flag1
+22 asm_Flag2
+23 asm_Flag3
+24 appLwrCaseFlag
+1,24 comFailed,getSendFlg
+3,24 lwrCaseActive,appLwrCaseFlag
+26 groupFlags
+1,26 inGroup,groupFlags
+28 apiFlag
+0,28 appAllowContext,apiFlag
+4,28 appRunning,apiFlag
+7,28 appRetOffKey,apiFlag
+29 apiFlg2
+2A apiFlg3
+2B apiFlg4
+2,2B fullScrnDraw,apiFlg4
+2C apiFlg5
+0,2C appWantDiagonalKeys,apiFlg5
+2E xapFlag0
+2F xapFlag1
+30 xapFlag2
+31 xapFlag3
+32 fontFlags
+2,32 fracDrawLFont,fontFlags
+3,32 fracTallLFont,fontFlags
+6,32 drawLFont,fontFlags
+7,32 customFont,fontFlags
+33 hookFlags0
+0,33 alt_On,scriptFlag
+1,33 alt_Off,scriptFlag
+2,33 useRclQueueEnd,rclFlag2
+3,33 ignoreBPLink,backGroundLink
+4,33 linkActivityHookActive,linkActivityHookFlag
+34 hookFlags1
+0,34 getKeyHookActive,getKeyHookFlag
+1,34 libraryHookActive,libraryHookFlag
+4,34 homescreenHookActive,homescreenHookFlag
+5,34 rawKeyHookActive,rawKeyHookFlag
+6,34 catalog2HookActive,catalog2HookFlag
+7,34 cursorHookActive,cursorHookFlag
+35 hookFlags2
+0,35 tokenHookActive,tokenHookFlag
+1,35 localizeHookActive,localizeHookFlag
+2,35 windowHookActive,windowHookFlag
+3,35 graphHookActive,graphHookFlag
+4,35 yEquHookActive,yEquHookFlag
+5,35 fontHookActive,fontHookFlag
+6,35 regraphHookActive,regraphHookFlag
+7,35 drawingHookActive,drawingHookFlag
+36 hookFlags3
+0,36 traceHookActive,traceHookFlag
+1,36 parserHookActive,parserHookFlag
+2,36 appChangeHookActive,appChangeHookFlag
+3,36 catalog1HookActive,catalog1HookFlag
+4,36 helpHookActive,helpHookFlag
+5,36 cxRedispHookActive,cxRedispHookFlag
+6,36 menuHookActive,menuHookFlag
+7,36 silentLinkHookActive,silentLinkHookFlag
+37 hookAutoFlags1
+38 hookAutoFlags2
+39 hookAutoFlags3
+3A hookFlags4
+0,3A usbHookActive,usbHookFlag
+3C plotFlag3
+0,3C bufferOnly,plotFlag3
+4,3C useFastCirc,plotFlag3
+3D DBKeyFlags
+0,3D leftShiftPressed,DBKeyFlags
+1,3D rightShiftPressed,DBKeyFlags
+2,3D diamondPressed,DBKeyFlags
+3,3D squarePressed,DBKeyFlags
+4,3D repeatMost,DBKeyFlags
+5,3D haveDBKey,DBKeyFlags
+6,3D keyDefaultsF,DBKeyFlags
+7,3D HWLinkErrF,DBKeyFlags
+3E openLibFlag
+4,3E openLibActive,openLibFlag
+3F clockFlags
+0,3F clockNotMonthFirst,clockFlags
+1,3F clockYearFirst,clockFlags
+2,3F clock24Hour,clockFlags
+4,3F clockFmtASCII,clockFlags
diff --git a/tool/tilem-src/data/symbols/ti85.sym b/tool/tilem-src/data/symbols/ti85.sym
new file mode 100644
index 0000000..4cab7ed
--- /dev/null
+++ b/tool/tilem-src/data/symbols/ti85.sym
@@ -0,0 +1,254 @@
+[macros]
+0CD098C ROM_CALL~%C
+0CD0C8C CALL_~Z,prgm+%j
+0CD0F8C CALL_~prgm+%j
+0CD128C CALL_~NZ,prgm+%j
+0CD188C CALL_~C,prgm+%j
+0CD1E8C CALL_~NC,prgm+%j
+0CD248C JUMP_~Z,prgm+%j
+0CD278C JUMP_~prgm+%j
+0CD2A8C JUMP_~NZ,prgm+%j
+0CD308C JUMP_~C,prgm+%j
+0CD368C JUMP_~NC,prgm+%j
+0CDC88C RCALL_~%j
+
+[romcalls]
+00 TX_CHARPUT
+01 D_LT_STR
+02 M_CHARPUT
+03 D_ZM_STR
+04 D_LM_STR
+05 GET_T_CUR
+06 SCROLL_UP
+07 TR_CHARPUT
+08 CLEARLCD
+09 D_HL_DECI
+0A CLEARTEXT
+0B D_ZT_STR
+0C BUSY_OFF
+0D BUSY_ON
+80 FIND_PIXEL
+
+[labels]
+0008 rOP1TOOP2
+0010 rFINDSYM
+0018 rPUSHOP1
+0020 rMOV10TOOP1
+0028 rFPMULT
+0030 rFPADD
+
+0033 LD_HL_MHL
+008E CP_HL_DE
+009A UNPACK_HL
+01A2 READ_KEYPAD
+01B1 STORE_KEY
+01BE GET_KEY
+0115 UPDATE_APD
+0168 READ_KEY
+
+8000 kbdScanCode
+8001 kbdLGSC
+8002 kbdPSC
+8003 kbdWUR
+8004 kbdDebncCnt
+8005 kbdKey
+8006 kbdGetKy
+8007 contrast
+8008 apdSubTimer
+8009 apdTimer
+800A apdWarmUp
+800B curTime
+800C curRow
+800D curCol
+800E curUnder
+800F undelBufLen
+8010 undelBuf
+# 8074 tokVarPtr?
+# 8076 tokLen?
+8078 indicMem
+8080 indicCounter
+8081 indicBusy
+8082 OP1
+808D OP2
+8098 OP3
+80A3 OP4
+80AE OP5
+80B9 OP6
+80C6 iMathPtr1
+80C8 iMathPtr2
+80CA iMathPtr3
+80CC iMathPtr4
+80CE iMathPtr5
+# 80D0 chkDelPtr1?
+# 80D2 chkDelPtr2?
+# 80D4 insDelPtr?
+# 80D6 upDownPtr?
+80DF textShadow
+8187 textShadCur
+# 8189 textShadTop?
+# 818A textShadAlph?
+# 818B textShadIns?
+818C textAccent
+818D cxMain
+# 818F cxPPutAway?
+# 8191 cxPutAway?
+# 8193 cxRedisp?
+# 8195 cxErrorEP?
+8197 cxSizeWind
+8199 cxPage
+# 819A cxCurApp?
+819B cxPrev
+# 81AA monQH?
+# 81AB monQT?
+# 81AC monQueue?
+81BC onSP
+81BE onCheckSum
+81DD menuActive
+8333 penCol
+8334 penRow
+# 8335 rclQueue?
+8337 errNo
+8338 errSP
+# 833A errOffset?
+8346 flags
+8364 stCounter
+# 85E3 XOutDat?
+# 85E7 YOutDat?
+# 85EB inputDat?
+8629 ES
+8641 plotSScreen
+8A41 seed1
+8A4B seed2
+# 8A56 parseVar?
+8A5F begPC
+8A61 curPC
+8A63 endPC
+8A6B cmdShadow
+# 8B27 editDat?
+8B2D modePtr
+8B2F winTop
+8B30 winBtm
+8B31 winLeftEdge
+8B32 winLeft
+8B34 winAbove
+8B36 winRow
+# 8B38 winCol?
+8B3A fmtDigits
+# 8B96 fmtMatMem?
+# 8B98 EQS?
+8BD2 delAdjAmt
+8BDD tempMem
+8BDF fpBase
+8BE1 FPS
+8BE3 OPBase
+8BE5 OPS
+# 8BE7 pTempCnt?
+# 8BE9 cleanTmp?
+8BEB pTemp
+8BF7 userMem
+0FA6F symTable
+0FC00 videoRAM
+
+## ZShell
+8C3C PROGRAM_ADDR
+8C3E ROM_VERS
+8C3F ZSHELL_VER
+8C40 ZS_BITS
+
+## Usgard
+8E8B ORGSP
+8EA2 USGSHELL
+8EAB VATName
+8EB4 DEST_ADDR
+8EB4 PAGE1ADDR
+8EB6 PAGE2ADDR
+8C08 PROG_BYTE
+8C41 TX_CHARPUT
+8C44 D_LT_STR
+8C47 M_CHARPUT
+8C4A D_ZM_STR
+8C4D D_LM_STR
+# 8C50 SCROLL_UP
+# 8C53 TR_CHARPUT
+# 8C56 CLEARLCD
+# 8C59 D_HL_DECI
+# 8C5C CLEARTEXT
+# 8C5F D_ZT_STR
+# 8C62 BUSY_OFF
+# 8C65 BUSY_ON
+# 8C68 RANDOM
+8C6B FIND_PIXEL
+8C77 FREEMEM
+8C7A VAR_LENGTH
+8C7D ASCIIZ_LEN
+8C80 NEG_BC
+8C83 MUL_HL
+8C8C COPY_STRING
+8C9B USGARD_INT_INSTALL
+8C9E USGARD_INT_REMOVE
+8CA1 USGARD_INT_CLEAN
+8C95 APPEND
+8C98 UNAPPEND
+8CCB CHECK_APPEND
+8CA4 VAR_NEW
+8CA7 VAR_DELETE
+8CAA VAR_EXEC
+8CAD VAR_GET
+8CB0 VAR_RESIZE
+8CCE RELOC
+8CD1 DERELOC
+8CD7 RELOC_TAB
+8CB3 SEARCH_VAT
+8CB6 OTH_SHUTDOWN
+8CB9 DM_HL_DECI
+8CBC OTH_PAUSE
+8CBF OTH_CLEAR
+8CC2 OTH_EXIT
+8CC5 OTH_ARROW
+8CD4 OTH_FILL
+
+## Rigel
+# 8C50 GET_T_CUR
+# 8C53 SCROLL_UP
+# 8C56 TR_CHARPUT
+# 8C59 CLEARLCD
+# 8C5C D_HL_DECI
+# 8C5F CLEARTEXT
+# 8C62 D_ZT_STR
+# 8C65 BUSY_OFF
+# 8C68 BUSY_ON
+8C6E RIGEL_INT_INSTALL
+8C71 RIGEL_INT_REMOVE
+8C06 VAR_SEARCH
+
+[flags]
+00 kbdFlags
+2,00 trigDeg,trigFlags
+3,00 kbdSCR,kbdFlags
+4,00 kbdKeyPress,kbdFlags
+05 textFlags
+2,05 textScrolled,textFlags
+3,05 textInverse,textFlags
+4,05 textInsMode,textFlags
+08 apdFlags
+2,08 apdAble,apdFlags
+3,08 apdRunning,apdFlags
+09 onFlags
+3,09 onRunning,onFlags
+4,09 onInterrupt,onFlags
+0C curFlags
+2,0C curAble,curFlags
+3,0C curOn,curFlags
+4,0C curLock,curFlags
+0D appFlags
+1,0D appTextSave,appFlags
+5,0D appCurGraphic,appFlags
+6,0D appCurWord,appFlags
+12 indicFlags
+0,12 indicRun,indicFlags
+2,12 indicOnly,indicFlags
+3,12 shift2nd,shiftFlags
+4,12 shiftAlpha,shiftFlags
+5,12 shiftLwrAlph,shiftFlags
+6,12 shiftALock,shiftFlags
+7,12 shiftKeepAlph,shiftFlags
diff --git a/tool/tilem-src/data/symbols/ti86.sym b/tool/tilem-src/data/symbols/ti86.sym
new file mode 100644
index 0000000..5fb2cf3
--- /dev/null
+++ b/tool/tilem-src/data/symbols/ti86.sym
@@ -0,0 +1,1112 @@
+[labels]
+0008 rOP1TOOP2
+0010 rFINDSYM
+0018 rPUSHOP1
+0020 rMOV10TOOP1
+0028 rFPMULT
+0030 rFPADD
+
+4010 _ldhlind
+4028 _chkON
+402C _bitgrffuncm
+4030 _bitgrfpolarm
+4034 _bitgrfparamm
+4038 _bitgrfrecurm
+403C _cphlde
+4040 _put_colon
+4044 _divHLby10
+4048 _divHLbyA
+404C _divAHLby10
+4058 _timeout
+4060 _resetAPD
+4064 _scan_code
+4068 _get_key
+409C _jforcecmdnochar
+40B5 _pPutAwayPrompt
+40BD _call_cxPPutAway
+40C1 _call_cxPutAway
+40C5 _call_cxSizeWind
+40C9 _call_cxErrorEP
+40CD _call_cxMain
+40D1 _cxNull
+40D2 _p_cxNull
+40DD _err_handler
+40E1 _set_cx_100
+40E5 _set_cx_50
+40E9 _set_cx_dec
+40ED _set_context
+4101 _off
+4109 _reset
+4119 _removTok
+412D _errAxes
+4130 _errFldOrder
+4133 _errStatPlot
+4136 _errOverflow
+4139 _errDivBy0
+413c _errSingularMat
+413f _errDomain
+4142 _errIncrement
+4145 _errSyntax
+4148 _errNumberBase
+414B _errMode
+414e _errDataType
+4151 _errArgument
+4154 _errDimMismatch
+4157 _errDimension
+415A _errUndefined
+4169 _errReserved
+416c _errInvalid
+416f _errIllegalNest
+4172 _errBound
+4175 _errGraphWindow
+4178 _errZoom
+417b _errBreak
+417e _errStat
+4181 _errConversion
+4184 _errSolver
+4187 _errIterations
+418a _errBadGuess
+418d _errDifEqSetup
+4190 _errPoly
+4193 _errTolNotMet
+4196 _errLink
+4199 _errorA
+419C _error
+41A1 _instError
+41A4 _removError
+41B7 _ld_de_fp0
+41BB _ld_de_fp1
+41BF _mulHL10
+41C3 _ckop1cplx
+41C7 _ckcplx
+41CB _ckop1real
+41FB _cpop1op2
+4203 _op3toop4
+4207 _op1toop4
+420B _op2toop4
+420F _movtoop4
+4213 _op4toop2
+4217 _op4toop3
+421B _op3toop2
+421F _op1toop3
+4223 _movfrop1
+4227 _op5toop2
+422B _op5toop6
+422F _op5toop4
+4233 _op1toop2
+4237 _movtoop2
+423B _op6toop2
+423F _op6toop1
+4243 _op4toop1
+4247 _op5toop1
+424B _op3toop1
+424F _op4toop5
+4253 _op3toop5
+4257 _op2toop5
+425B _movtoop5
+425F _op2toop6
+4263 _op1toop6
+4267 _movtoop6
+426B _op1toop5
+426F _op2toop1
+4273 _movtoop1
+4277 _mov11b
+427B _mov10b
+427F _mov9b
+4283 _mov9b_
+4287 _mov8b
+428B _mov7b
+428F _mov7b_
+4293 _mov6b
+4297 _mov5b
+429B _mov4b
+429F _mov3b
+42A3 _mov2b
+42A7 _op4toop2m
+42CB _op2toop3
+42CF _movtoop3
+42D3 _op4toop6
+42D7 _mov10toop1
+42DB _mov10toop1op2
+42DF _mov10toop2
+42E3 _movfroop1
+42E7 _op4set1
+42EB _op3set1
+42EF _op2set8
+42F7 _op2set5
+42FB _op2set4
+4303 _op2set3
+430F _op1set1
+4313 _op1set4
+4317 _op1set3
+431B _op3set2
+431F _op1set2
+4323 _op2set2
+432F _op2set1
+4343 _ld_hl_8z
+4347 _ld_hl_8a
+434B _ld_hlplus1_7a
+434F _ld_hl_7a
+4353 _op4set0
+4357 _op3set0
+435B _op2set0
+435F _op1set0
+4363 _ld_hl_fp0
+4367 _zeroop1m
+436B _zeroop1
+436F _zeroop2
+4373 _zeroop3
+4377 _ld_hl_11z
+437B _ld_hl_bz
+4383 _shracc
+438B _shlacc
+446F _ex_op2_op6
+4473 _ex_op5_op6
+4477 _ex_op1_op5
+447B _ex_op1_op6
+447F _ex_op2_op4
+4483 _ex_op2_op5
+4487 _ex_op1_op3
+448B _ex_op1_op4
+448F _ex_op1_op2
+449B _ckop1fp0
+44A3 _ckop2fp0
+44B3 _ckop1int
+44B7 _ckint
+44BB _ckop1odd
+44BF _ckodd
+450B _ckop2pos
+450F _ckop1pos
+4513 _absop2
+4527 _inco1exp
+4547 _HtimesL
+458F _findsym_error
+45E3 _invsub
+45EB _PLUS1
+45EF _inc_ptr_ade
+45F3 _ex_ahl_bde
+460B _get_size_word
+4613 _setXXop1
+4617 _setXXop2
+461B _setXXXXop2
+462F _load_ram_ahl
+4633 _conv_ahl
+4637 _inc_ptr_ahl
+463B _dec_ptr_ahl
+463F _inc_ptr_bde
+4643 _dec_ptr_bde
+4647 _set_abs_src_addr
+464B _get_free_mem
+464F _set_mm_num_bytes
+4657 _round_OP1
+46AF _check_asm
+46B7 _jump_table
+46BB _memchk
+46BF _dec_ptr_ade
+46C3 _getb_ahl
+46C7 _cp_ahl_bde
+46CB _findsym
+46D3 _copy_fwd
+46D7 _del_temp_vars
+46EB _createreal
+46EF _createrconst
+46F3 _createcconst
+46F7 _createcplx
+46FB _creatervect_temp
+46FF _creatervect
+4703 _createcvect_temp
+4707 _createcvect
+470B _createrlist_temp
+470F _createrlist
+4713 _createclist_temp
+4717 _createclist
+471B _creatermat_temp
+471F _creatermat
+4723 _createcmat_temp
+4727 _createcmat
+472B _createstrng_temp
+472F _createstrng
+4733 _createequ_temp
+4737 _createequ
+473B _createpict
+474F _createprog
+475B _copy_bkwd
+475F _delvar
+476F _update_VAT_ptrs
+477B _get_size
+477F _get_var_size
+4783 _push_bc_OPS
+4787 _check_STACK_mem
+478B _pop_bc_OPS
+478F _push_a_OPS
+4793 _pop_a_OPS
+479F _popop1
+47A3 _poprealo6
+47A7 _poprealo5
+47AB _poprealo4
+47AF _poprealo3
+47A3 _poprealo2
+47A7 _poprealo1
+47CB _sub_FPS_20
+47CF _sub_FPS_10
+47D3 _sub_FPS_bc
+47DB _deallocfps1
+47E3 _ram_page_1
+47E7 _load_ram_OPS
+47EB _load_ram_ES
+47EF _load_ram_FPS
+47F3 _ram_page_7
+4813 _pushrealo1
+4893 _cpyto2fpst
+4897 _cpyto1fpst
+48AF _cpyto2fps1
+48C3 _cpyto2fps2
+48D7 _cpyo2tofpst
+48DB _cpyo6tofpst
+48DF _cpyo1tofpst
+48E3 _cpydetofpst
+48E7 _cpydetohlt
+48EB _cpydetohlc
+48EF _cpyo5tofps2
+48F3 _cpyo2tofpsto1tofps1
+48F7 _cpyo1tofps1
+48FB _cpydetofps1
+48FF _cpydetohl1
+4903 _cpyo2tofps2
+4907 _cpyo3tofps2
+490B _cpyo6tofps2
+490F _cpyo1tofps2
+4913 _cpydetofps2
+4917 _cpydetohl2
+491B _cpyo5tofps3
+491F _cpyo2tofps2o1tofps3
+4923 _cpyo1tofps3
+4927 _cpydetofps3
+492B _cpydetohl3
+492F _cpyo1tofps4
+4933 _cpydetofps4
+4937 _cpydetohl4
+493B _cpyo1tofps6
+493F _cpyo1tofps7
+4943 _cpyo1tofps8
+494F _ask_self_test
+4953 _self_test
+4957 _strlen
+495B _strcpy
+495F _strcat
+4963 _strcmp
+496B _find_bit
+498C _cursorOff
+4994 _cursorOn
+49A0 _reset_MATH
+49B0 _disp_GRAPH
+49DC _flushallmenus
+49E8 _disp_menu
+4A0A _exec_pg1
+4A27 _putmap
+4A2B _putc
+4A33 _dispAHL
+4A37 _puts
+4A3B _putps
+4A5F _newline
+4A7E _clrLCD
+4A82 _clrScrn
+4A86 _clrWindow
+4A8A _clrLine
+4A95 _homeup
+4AA1 _vputmap
+4AA5 _vputs
+4AA9 _vputsn
+4AAD _runindicon
+4AB1 _runindicoff
+4AB5 _clrText
+4B1B _exec_pg2
+4B1F _binopexec1
+4B93 _tofrac
+4B9F _gfudydx
+4C2F _INTOP1
+4C3F _ahl_plus_2_pg3
+4C47 _exec_basic
+4C9F _stoAns
+4CB3 _stoY
+4CBB _stoX
+4CBF _stoOther
+4CDF _rclY
+4CE3 _rclX
+4CE7 _rclVarSym
+4D13 _get_token
+4D1B _get_varname
+4D3F _disp
+4D43 _pause
+4D6F _PDspGrph
+4D73 _horizCmd
+4D77 _vertCmd
+4DAF _unpack_hex
+4E39 _grbufcpy
+4E51 _ILine
+4E59 _IPoint
+4E71 _geqnamea
+4FA8 _set_app_title
+514B _FindAlphaUp
+514F _FindAlphaDn
+515B _dispOP1
+515F _dispDone
+5191 _formReal
+51E9 _CLine
+5209 _get_abs_src_addr
+521D _get_word_ahl
+5221 _set_word_ahl
+5235 _abs_mov10toop1
+5239 _abs_mov10toop1_noset
+523D _abs_mov10b_set_d
+5249 _abs_mov10b
+5241 _abs_movfrop1_set_d
+5245 _abs_movfrop1
+5285 _set_abs_dest_addr
+52B5 _RcPicGrph
+52ED _mm_ldir
+52F1 _mm_lddr
+5369 _get_statvar
+5371 _getky
+5398 _low_battery
+5464 _mov10op2add
+5468 _INTGR
+5470 _MINUS1
+5474 _FPSUB
+5478 _FPADD
+5484 _TIMESPT5
+5488 _FPSQUARE
+548C _FPMULT
+5490 _invop1op2
+5494 _invop1s
+5498 _invop2s
+549C _FRAC
+54A4 _FPRECIP
+54A8 _FPDIV
+54AC _SQROOT
+54B0 _SQROOTP
+54BC _RNDGUARD
+54C0 _ROUND
+54C4 _LNX
+54C8 _LNXP
+54CC _LOGXP
+54D0 _LOGX
+54D4 _ETOX
+54D8 _TENX
+54E0 _SIN
+54E4 _COS
+54E8 _TAN
+54F0 _TANH
+54F4 _COSH
+54F8 _SINH
+5508 _ACOS
+550C _ACOSP
+5510 _ATAN
+5514 _ASIN
+551C _ATANH
+5524 _ASINH
+5528 _ACOSH
+5538 _YTOX
+5544 _randint
+5567 _writeb_inc_ahl
+5577 _convop1
+557B _set_mode
+55a3 _asmComp
+55AA _getkey
+55DA _random
+5643 _vputspace
+569D _get_char
+56A1 _get_vchar
+56EA _call_user_on
+56ED _call_user_off
+56F0 _call_sqrtexpr
+56F3 _call_sqrtparse
+56F6 _call_sqrtexec
+56F9 _call_sqrtform
+56FC _call_sqrtcmdtok
+56FF _call_sqrthome
+5702 _call_sqrtkey
+5705 _call_sqrtgrf
+5718 _exec_pg4
+5714 _exec_pg3
+571C _linkExec
+5730 _exec_assembly
+5732 _errNoSignChng
+575C _instTok
+
+0C000 _kbdScanCode
+0C001 _kbdLGSC
+0C002 _kbdPSC
+0C003 _kbdWUR
+0C004 _kbdDebncCnt
+0C005 _kbdkey
+0C006 _kbdGetKy
+0C007 _keyextend
+0C008 _contrast
+0C009 _APDSubTimer
+0C00A _APDTimer
+0C00B _APDWarmUp
+0C00C _viet
+0C00E _curTime
+0C00F _curRow
+0C010 _curCol
+0C011 _curUnder
+0C012 _undelBufLen
+0C013 _undelBuf
+0C077 _P_tokVarPtr
+0C07A _toklen
+0C07C _TOK_B3
+0C07D _DETOK_H3
+0C07E _MEMPRE_H3
+0C07F _indicMem
+0C087 _indicCounter
+0C088 _indicBusy
+0C089 _OP1
+0C08A _OP1EXPM
+0C08B _OP1EXPL
+0C08C _OP1M
+0C093 _OP1EXT
+0C094 _LOGKP
+0C094 _OP2
+0C095 _OP2EXPM
+0C096 _OP2EXPL
+0C097 _OP2M
+0C09E _OP2EXT
+0C09F _OP3
+0C09F _LOGKM
+0C0A0 _OP3EXPM
+0C0A1 _OP3EXPL
+0C0A2 _OP3M
+0C0A9 _OP3EXT
+0C0AA _CORDFLG1
+0C0AA _OP4
+0C0AB _OP4EXPM
+0C0AC _OP4EXPL
+0C0AD _OP4M
+0C0B4 _OP4EXT
+0C0B5 _EK
+0C0B5 _CORDFLG
+0C0B5 _OP5
+0C0B6 _OP5EXPM
+0C0B6 _SF
+0C0B6 _EL
+0C0B7 _OP5EXPL
+0C0B7 _EM
+0C0B8 _OP5M
+0C0B8 _EMM1
+0C0B9 _EITS
+0C0BA _ENM2
+0C0BB _ENA
+0C0BC _EEN
+0C0BF _OP5EXT
+0C0C0 _EN
+0C0C0 _OP6
+0C0C1 _EJ
+0C0C1 _OP6EXPM
+0C0C2 _OP6EXPL
+0C0C2 _EEI
+0C0C3 _OP6M
+0C0C5 _ELOW
+0C0C6 _EIGH
+0C0CA _OP6EXT
+0C0CC _OP7
+0C0D7 _CPLXTRG
+0C0D7 _IOFLAG
+0C0D8 _P_IMATHPTR1
+0C0DB _P_IMATHPTR2
+0C0DE _P_IMATHPTR3
+0C0E1 _P_IMATHPTR4
+0C0E4 _P_IMATHPTR5
+0C0E7 _CHKDELPTR1
+0C0E7 _P_CHKDELPTR1
+0C0EA _P_CHKDELPTR2
+0C0ED _P_INSDELPTR
+0C0F0 _P_UPDOWNPTR
+0C0F3 _STDRNGSGN
+0C0F4 _POLRNGSGN
+0C0F5 _PARRNGSGN
+0C0F6 _DIFRNDSGN
+0C0F7 _USRRNGSGN
+0C0F8 _STATSGN
+0C0F9 _textShadow
+0C1A1 _textShadCur
+0C1A3 _textShadTop
+0C1A4 _textShadAlph
+0C1A5 _textShadIns
+0C1A6 _textAccent
+0C1A7 _cxMain
+0C1A9 _cxPPutAway
+0C1AB _cxPutAway
+0C1AD _cxRedisp
+0C1AF _cxErrorEP
+0C1B1 _cxSizeWind
+0C1B3 _cxPage
+0C1B4 _CXCURAPP
+0C1B5 _cxPrev
+0C1C4 _monQH
+0C1C5 _monQT
+0C1C6 _monQueue
+0C1D6 _onSP
+0C1D8 _onCheckSum
+0C1DA _promptRow
+0C1DB _promptCol
+0C1DC _promptIns
+0C1DD _promptShift
+0C1DE _promptRet
+0C1E0 _promptValid
+0C1E2 _P_promptTop
+0C1E5 _P_promptCursor
+0C1E8 _P_promptTail
+0C1EB _P_promptBtm
+0C1EE _varType
+0C1EF _varCurrent
+0C1F8 _varFAFlags
+0C1FA _varClass
+0C1FB _catCurrent
+0C1FD _menuActive
+0C1FE _menu2Hilite
+0C1FF _menuSingle
+0C201 _menuAppStack
+0C20D _menuAppPtr
+0C20F _menuAppDepth
+0C210 _menuSysStack
+0C21C _menuSysPtr
+0C21E _menuSysDepth
+0C21F _menuPrvStack
+0C22B _menuPrvPtr
+0C22D _menuPrvDepth
+0C22E _m2i
+0C242 _menuDyn1
+0C26A _menuDyn5
+0C274 _userMenu1
+0C275 _userMenuTitle
+0C27C _userMenu2
+0C284 _userMenu3
+0C28C _userMenu4
+0C294 _userMenu5
+0C29C _userMenuSA
+0C31C _XSTATSAV
+0C324 _ioPrompt
+0C326 _YSTATSAV
+0C330 _FSTATSAV
+0C33A _IOSNDTYP
+0C33B _SNDRECSTATE
+0C33C _IOERRSTATE
+0C33D _HEADER
+0C346 _IODATA
+0C352 _BAKHEADER
+0C35B _TBLRNGSGN
+0C35C _calc_id
+0C37C _penCol
+0C37D _penRow
+0C37E _P_RCLQUEUE
+0C381 _ERRNO
+0C382 _ERRSP
+0C384 _errOffset
+0C386 _ram_to_use
+0C390 _offerr_sav_bc
+0C392 _ABS_SRC_ADDR
+0C395 _ABS_DEST_ADDR
+0C398 _MM_NUM_BYTES
+0C39B _mm_tmp1
+0C39D _mm_tmp2
+0C39F _mm_tmp3
+0C3A1 _mm_tmp4
+0C3A3 _mm_tmp5
+0C3A5 _ram_cache
+0C3E5 _Flags
+0C40A _ram_to_use1
+0C414 _statReg
+0C415 _STATVARS
+0C555 _STCounter
+0C555 _curgstyle
+0C556 _curGY
+0C557 _curGX
+0C558 _curGY2
+0C559 _curGX2
+0C55A _curgstyle_save
+0C55B _curgstylesave
+0C55C _plotflagsave
+0C55D _XMINPTR
+0C55F _XMAXPTR
+0C561 _XSCLPTR
+0C563 _YMINPTR
+0C565 _YMAXPTR
+0C567 _YSCLPTR
+0C569 _DIF1STCURINC
+0C56B _TRACEPLOT
+0C56C _BOXPLOTINFO
+0C56D _SCURINC
+0C56F _CURINC
+0C571 _YPIXEL
+0C572 _ORGXMIN
+0C57C _PANSHIFT
+0C586 _USRRNGSIZE
+0C588 _UTHETMIN
+0C58D _STSP
+0C58D _STRAMStart
+0C592 _UTHETMAX
+0C59C _UTHETSTEP
+0C5A6 _UTPLOT
+0C5B0 _UTMIN
+0C5BA _UTMAX
+0C5C4 _UTSTEP
+0C5CE _UXMIN
+0C5D8 _UXMAX
+0C5E2 _UXSCL
+0C5EC _UYMIN
+0C5F6 _UYMAX
+0C600 _UYSCL
+0C60A _UXRES
+0C614 _XRES_INT
+0C615 _HDERIV
+0C61F _TOL
+0C629 _XFACT
+0C633 _YFACT
+0C63D _DELTAX
+0C647 _DELTAY
+0C651 _SHORTX
+0C65B _SHORTY
+0C665 _FUNRNGSIZE
+0C667 _FLAGSF
+0C668 _XMINF
+0C672 _XMAXF
+0C67C _XSCLF
+0C686 _YMINF
+0C690 _YMAXF
+0C69A _YSCLF
+0C6A4 _LOWER
+0C6AE _UPPER
+0C6B8 _XRES
+0C6C2 _POLRNGSIZE
+0C6C4 _FLAGSPOL
+0C6C5 _THETAMIN
+0C6CF _THETAMAX
+0C6D9 _THETASTEP
+0C6E3 _XMINPOL
+0C6ED _XMAXPOL
+0C6F7 _XSCLPOL
+0C701 _YMINPOL
+0C70B _YMAXPOL
+0C715 _YSCLPOL
+0C71F _PARRNGSIZE
+0C721 _FLAGSPAR
+0C722 _TMINPAR
+0C72C _TMAXPAR
+0C736 _TSTEPPAR
+0C740 _XMINPAR
+0C74A _XMAXPAR
+0C754 _XSCLPAR
+0C75E _YMINPAR
+0C768 _YMAXPAR
+0C772 _YSCLPAR
+0C77C _DIFRNGSIZE
+0C77E _FLAGSDIF
+0C77F _TOLERDIF
+0C789 _TPLOTDIF
+0C793 _TMINDIF
+0C79D _TMAXDIF
+0C7A7 _TSTEPDIF
+0C7B1 _XMINDIF
+0C7BB _XMAXDIF
+0C7C5 _XSCLDIF
+0C7CF _YMINDIF
+0C7D9 _YMAXDIF
+0C7E3 _YSCLDIF
+0C7ED _XAXISDIF
+0C7EE _YAXISDIF
+0C7EF _SLOPEF_EQU
+0C7F0 _DIRF_X
+0C7F1 _DIRF_Y
+0C7F2 _DIRF_TIME
+0C7FC _FRES
+0C806 _INTS
+0C810 _DNEQ
+0C811 _P_XOUTSYM
+0C814 _P_XOUTDAT
+0C817 _P_YOUTSYM
+0C81A _P_YOUTDAT
+0C81D _P_INPUTSYM
+0C820 _P_INPUTDAT
+0C823 _P_FOUTDAT
+0C826 _PREVDATA
+0C862 _PREVDATA_EXT
+0C86C _P1TYPE
+0C86D _SavX1List
+0C876 _SavY1List
+0C87F _SavF1List
+0C888 _P1FRQONOFF
+0C889 _P2TYPE
+0C88A _SavX2List
+0C893 _SavY2List
+0C89C _SavF2List
+0C8A5 _P2FRQONOFF
+0C8A6 _P3TYPE
+0C8A7 _SavX3List
+0C8B0 _SavY3List
+0C8B9 _SavF3List
+0C8C2 _P3FRQONOFF
+0C8C3 _oldtype
+0C8C4 _oldxlist
+0C8CD _oldylist
+0C8D6 _oldflist
+0C8D6 _uppery
+0C8DF _oldonoff
+0C8E0 _tblpsrow
+0C8E1 _tblscroll
+0C8E3 _INPUTDAT_PG0
+0C8ED _TblLine
+0C8F7 _OldTblMin
+0C901 _TBLRNGSIZE
+0C903 _TblMin
+0C90D _TblStep
+0C917 _TABLESGN
+0C918 _TableYPtr
+0C919 _curTblcol
+0C91A _curTblrow
+0C91B _dspTblcol
+0C91C _dspTblrow
+0C91D _higTblcol
+0C91E _higTblrow
+0C920 _TABLEXDATA
+0C920 _TBLMATRIX
+0C95C _TABLEYDATA
+0C9D4 _TABLETEMPLATE
+0C9D5 _SavedEqTok
+0C9D7 _SavedEqNum1
+0C9D8 _SavedEqTok1
+0C9DA _SaveAppFlags
+0C9DB _SaveCurFlags
+0C9DC _SaveCurGstyle
+0C9DD _SaveGraphFlags
+0C9DE _evalflevel
+0C9DF _TmpMatCols
+0C9DF _ES
+0C9E0 _TmpMatRows
+0C9E1 _P_DERIVPTR
+0C9E4 _DTMPThresh
+0C9E6 _ELCPLXLCNT
+0C9E8 _DERIVLEVEL
+0C9E9 _P_DIFFEQPTR
+0C9EB _P_DSOLVPTR
+0C9EE _SOLVAR
+0C9F7 _P_QUADPTR
+0C9FA _plotSScreen
+0CDFA _SEED1
+0CE04 _SEED2
+0CE0E _PARSEVAR
+0CE18 _P_BEGPC
+0CE1B _P_CURPC
+0CE1E _P_ENDPC
+0CE21 _ELCNT
+0CE23 _COLCNT
+0CE24 _ROWCNT
+0CE25 _LCOUNT
+0CE27 _EOS_ASAP_2ND
+0CE28 _EXEC_CONV_SAVE
+0CE2A _LASTENTRYPTR
+0CE2C _LASTENTRYSTK
+0CEAC _numlastentries
+0CEAD _currlastentry
+0CEAE _FREESAVEY
+0CEAF _FREESAVEX
+0CEB0 _STRACESAVE_TYPE
+0CEB1 _STRACESAVE
+0CEB3 _TRACESAVE
+0CEB5 _DIF_T_SAVE
+0CEBF _A_B_SAVE
+0CEC0 _A_B_TYPE
+0CEC1 _GS_DELX
+0CEC2 _GS_D1_YINC
+0CEC3 _GS_D2_YINC
+0CEC4 _GS_DELY
+0CEC5 _GS_MAX_Y_PIX
+0CEC6 _CURRENT_STYLE
+0CEC7 _CL_X1
+0CEC8 _CL_X2
+0CEC9 _CL_Y_DAT
+0CECB _PREV_POINT
+0CECD _RESSAVE
+0CECE _DREQU_X
+0CECF _DREQU_XINIT
+0CED9 _DREQU_Y
+0CEDA _DREQU_YINIT
+0CEE4 _DREQU_XLIST
+0CEE7 _DREQU_YLIST
+0CEEA _DREQU_tLIST
+0CEED _DREQU_COUNT
+0CEEF _GY1
+0CF21 _GX1
+0CF53 _GR1
+0CF85 _GQ1
+0CF8A _EQU_EDIT_SAVE
+0CF8B _FORMULA_BITMAP
+0CFAB _MENUCMD_M2I
+0CFAB _cmdShadow
+0CFC9 _MENUCMD_ITEMS
+0D041 _MENUCMD_NUMROWS
+0D042 _MENUCMD_CURROW
+0D053 _cmdShadCur
+0D055 _cmdShadAlph
+0D056 _cmdShadIns
+0D057 _cmdCursor
+0D059 _P_editTop
+0D05C _P_EDITCURSOR
+0D05F _P_editTail
+0D062 _P_editBtm
+0D065 _curmatcol
+0D066 _curmatrow
+0D067 _curlstrow
+0D069 _numedTbl
+0D069 _curlistel
+0D06A _curlstrowh
+0D06B _higmatcol
+0D06C _higmatrow
+0D06D _higlstrow
+0D06F _maxdsprow
+0D070 _ForCurMat
+0D070 _higlstrowh
+0D072 _ForDspCol
+0D074 _forerrornum
+0D075 _P_editSym
+0D078 _P_editDat
+0D07B _DspMatCol
+0D07C _DspMatRow
+0D07D _TmpMatCol
+0D07E _TmpMatRow
+0D07F _numoflist
+0D080 _num1stlist
+0D081 _NumCurList
+0D082 _STATED_CUT_COL
+0D083 _listnamebuffer
+0D12E _LastName
+0D137 _modeRoot
+0D139 _modeCount
+0D13A _modeItem
+0D13B _modePtr
+0D13D _winTop
+0D13E _winBtm
+0D13F _winLeftEdge
+0D140 _winLeft
+0D142 _winAbove
+0D144 _winRow
+0D146 _winCol
+0D148 _fmtDigits
+0D149 _fmtString
+0D18A _fmtConv
+0D19E _fmtLeft
+0D1A0 _fmtIndex
+0D1A2 _P_fmtMatSym
+0D1A5 _P_fmtMatMem
+0D1A8 _EQS
+0D1AA _LSTINDEX
+0D1AC _LSTSIZE
+0D1AE _EQUINDEX
+0D1B0 _order
+0D1B1 _xnamesav
+0D1BA _ynamesav
+0D1C3 _CustMType
+0D1C3 _MCustM
+0D1C4 _CustMLen
+0D1C5 _CustMSav
+0D1E3 _custmnames
+0D279 _VARSAVECNT
+0D27A _DELADJAMT
+0D27D _TEMPINPUT
+0D27E _TSYMPTR1
+0D280 _TSYMPTR2
+0D282 _P_CHKDELPTR3
+0D285 _P_CHKDELPTR4
+0D288 _P_TEMPMEM
+0D28B _FPBASE
+0D28D _FPS
+0D28F _OPBASE
+0D291 _OPS
+0D293 _PTempCnt
+0D295 _CLEANTMP
+0D297 _P_PTEMP
+0D29A _PTEMP_END
+0D29D _FREE_MEM
+0D2A0 _newdataptr
+0D2A3 _SavBotRow
+0D2B8 _curstatplot
+0D2B9 _curstatplotprompt
+0D2BA _difeqfieldmode
+0D2BB _matedoldtype
+0D2BC _modesave1
+0D2BD _statansfirst
+0D2BF _statanslast
+0D2C1 _statanscur
+0D2C3 _charmap
+0D2CB _altcharmap
+0D2D3 _toktmp1
+0D2D4 _toktmp2
+0D2D5 _IOSAVOP1
+0D2DF _DELVAR_SAV_F
+0D2E0 _DEL_SAV_OP1
+0D2EB _alt_asm_exec_btm
+0D2ED _altlfontptr
+0D2F0 _altsfontptr
+0D2F3 _altonptr
+0D2F6 _altslinkptr
+0D2F9 _alt_ret_status
+0D2FA _alt_ret_jmp_page
+0D2FB _alt_ret_jmp_addr
+0D2FD _alt_int_chksum
+0D2FE _alt_interrupt_exec
+0D3C6 _alt_slink_chksum
+0D3C7 _alt_slink_exec
+0D48F _alt_on_chksum
+0D490 _alt_on_exec
+0D558 _alt_off_chksum
+0D559 _alt_off_exec
+0D621 _altram_end
+0D621 _asm_exec_btm
+0D623 _ASAP_IND
+0D624 _asm_reg_af
+0D625 _asm_reg_a
+0D626 _asm_reg_l
+0D626 _asm_reg_hl
+0D627 _asm_reg_h
+0D628 _asm_reg_bc
+0D628 _asm_reg_c
+0D629 _asm_reg_b
+0D62A _asm_reg_de
+0D62A _asm_reg_e
+0D62B _asm_reg_d
+0D62C _mPrgmMATH
+0D64C _mMath
+0D65A _mMath_asap1
+0D65C _mMath_asap2
+0D65E _mMath_asap3
+0D66C _iASAP1
+0D678 _iASAP2
+0D684 _iASAP3
+0D690 _iASAP4
+0D69C _iASAP5
+0D6A8 _iASAP6
+0D6B4 _iASAP7
+0D6C0 _iASAP8
+0D6CC _iASAP9
+0D6D8 _asapnames
+0D6D8 _asap_nl1
+0D6E1 _asap_nl2
+0D6EA _asap_nl3
+0D6FC _asapvar
+0D706 _tokspell_asap1
+0D706 _tokspelltblptr
+0D708 _tokspell_asap2
+0D70A _tokspell_asap3
+0D70E _numtokens
+0D70E _numtok_asap1
+0D70F _numtok_asap2
+0D710 _numtok_asap3
+0D712 _eostblptr
+0D712 _eostbl_asap1
+0D714 _eostbl_asap2
+0D716 _eostbl_asap3
+0D71A _Amenu_offset
+0D722 _reinstall_asap1
+0D722 _reinstall_vec
+0D724 _reinstall_asap2
+0D726 _reinstall_asap3
+0D72A _asap1_ram
+0D734 _asap2_ram
+0D73E _asap3_ram
+0D748 _checkStart
+0D748 _asm_exec_ram
+
+[flags]
+00 trigflags
+2,00 trigdeg,trigflags
+00 doneflags
+5,00 donePrgm,doneflags
+02 plotflags
+1,02 plotloc,plotflags
+2,02 plotdisp,plotflags
+02 grfmodeflags
+4,02 grffuncm,grfmodeflags
+5,02 grfpolarm,grfmodeflags
+6,02 grfparamm,grfmodeflags
+7,02 grfrecurm,grfmodeflags
+03 graphflags
+0,03 graphdraw,graphflags
+2,03 graphcursor,graphflags
+04 grfdbflags
+0,04 grfdot,grfdbflags
+1,04 grfsimul,grfdbflags
+2,04 grfgrid,grfdbflags
+3,04 grfpolar,grfdbflags
+4,04 grfnocoord,grfdbflags
+5,04 grfnoaxis,grfdbflags
+6,04 grflabel,grfdbflags
+05 textflags
+1,05 textEraseBelow,textflags
+2,05 textScrolled,textflags
+3,05 textInverse,textflags
+06 parsflag
+07 parsflag2
+0,06 numop1,parsflag2
+08 apdflags
+2,08 apdable,apdflags
+3,08 apdlock,apdflags
+4,08 apdwarmstart,apdflags
+09 onflags
+3,09 onRunning,onflags
+4,09 onInterrupt,onflags
+0A fmtflags
+0,0A fmtExponent,fmtflags
+1,0A fmtEng,fmtflags
+2,0A fmtHex,fmtflags
+3,0A fmtOct,fmtflags
+4,0A fmtBin,fmtflags
+0C curflags
+2,0C curAble,curflags
+3,0C curOn,curflags
+4,0C curLock,curflags
+0D appflags
+1,0D appTextSave,appflags
+2,0D appAutoScroll,appflags
+12 indicflags
+0,12 indicRun,indicflags
+2,12 indicOnly,indicflags
+12 shiftflags
+3,12 shift2nd,shiftflags
+4,12 shiftAlpha,shiftflags
+5,12 shiftLwrAlph,shiftflags
+6,12 shiftALock,shiftflags
+16 asap_cmd_flag
+7,16 ex_asap_cmd,asap_cmd_flag
+17 NewDispf
+6,17 ProgramExecuting,NewDispf
+18 new_grf_flgs
+6,18 textwrite,new_grf_flgs
+1D statflags
+6,1D statsvalid,statflags
+1F anumeditflgs
+2,1F ex_asm_module,anumeditflgs
+23 exceptionflg
+0,23 alt_font,exceptionflg
+1,23 alt_vfont,exceptionflg
+2,23 alt_int,exceptionflg
+3,23 alt_on,exceptionflg
+4,23 alt_link,exceptionflg
+5,23 alt_sqrt,exceptionflg
+6,23 alt_grphexpr,exceptionflg
+7,23 alt_off,exceptionflg
+24 exceptionflg2
+0,24 alt_parse,exceptionflg2
+1,24 alt_form,exceptionflg2
+2,24 alt_exec,exceptionflg2
+4,24 alt_home,exceptionflg2
+5,24 alt_cmdtok,exceptionflg2
+6,24 alt_key,exceptionflg2
+7,24 alt_grf,exceptionflg2
+28 asm_flag1
+29 asm_flag2
+2A asm_flag3
+2B asm_flag4
+2C asm_flag5
+2D asm_flag6
+2E asm_flag7
+
diff --git a/tool/tilem-src/db/Makefile.in b/tool/tilem-src/db/Makefile.in
new file mode 100644
index 0000000..89f981b
--- /dev/null
+++ b/tool/tilem-src/db/Makefile.in
@@ -0,0 +1,59 @@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datarootdir = @datarootdir@
+bindir = @bindir@
+datadir = @datadir@
+pkgdatadir = @datadir@/tilem2
+mandir = @mandir@
+
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+@SET_MAKE@
+
+AR = @AR@
+CC = @CC@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+DEFS = @DEFS@
+RANLIB = @RANLIB@
+SHELL = @SHELL@
+
+objects = disasm.o listing.o lstfile.o
+
+compile = $(CC) -I$(top_builddir) -I$(top_srcdir)/emu -I$(srcdir) $(CFLAGS) $(CPPFLAGS) $(DEFS)
+
+all: libtilemdb.a
+
+libtilemdb.a: $(objects)
+ $(AR) cru libtilemdb.a $(objects)
+ $(RANLIB) libtilemdb.a
+
+# Disassembler
+
+disasm.o: disasm.c tilemdb.h ../emu/tilem.h ../config.h
+ $(compile) -c $(srcdir)/disasm.c
+
+# Listing file management
+
+listing.o: listing.c tilemdb.h ../emu/tilem.h ../config.h
+ $(compile) -c $(srcdir)/listing.c
+
+lstfile.o: lstfile.c tilemdb.h ../emu/tilem.h ../config.h
+ $(compile) -c $(srcdir)/lstfile.c
+
+
+clean:
+ rm -f *.o
+ rm -f libtilemdb.a
+
+
+Makefile: Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status
+
+$(top_builddir)/config.status: $(top_srcdir)/configure
+ cd $(top_builddir) && $(SHELL) ./config.status --recheck
+
+.PRECIOUS: Makefile $(top_builddir)/config.status
+.PHONY: all clean
diff --git a/tool/tilem-src/db/disasm.c b/tool/tilem-src/db/disasm.c
new file mode 100644
index 0000000..3326d85
--- /dev/null
+++ b/tool/tilem-src/db/disasm.c
@@ -0,0 +1,1084 @@
+/*
+ * libtilemdb - Utilities for debugging Z80 assembly programs
+ *
+ * Copyright (C) 2010 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+#include
+#include
+#include "tilemdb.h"
+
+typedef struct _TilemDisasmSymbol {
+ char* name;
+ dword value;
+} TilemDisasmSymbol;
+
+typedef struct _TilemDisasmSymTable {
+ int nsyms;
+ int nsyms_a;
+ TilemDisasmSymbol* syms;
+} TilemDisasmSymTable;
+
+struct _TilemDisasm {
+ TilemDisasmSymTable labels;
+ TilemDisasmSymTable romcalls;
+ TilemDisasmSymTable flags;
+ TilemDisasmSymTable macros;
+};
+
+TilemDisasm* tilem_disasm_new()
+{
+ TilemDisasm* dasm = tilem_new0(TilemDisasm, 1);
+ dasm->labels.syms = NULL;
+ dasm->romcalls.syms = NULL;
+ dasm->flags.syms = NULL;
+ dasm->macros.syms = NULL;
+ return dasm;
+}
+
+static void tilem_disasm_sym_table_free(TilemDisasmSymTable* stab)
+{
+ int i;
+
+ for (i = 0; i < stab->nsyms; i++)
+ tilem_free(stab->syms[i].name);
+ tilem_free(stab->syms);
+}
+
+void tilem_disasm_free(TilemDisasm* dasm)
+{
+ if (!dasm)
+ return;
+
+ tilem_disasm_sym_table_free(&dasm->labels);
+ tilem_disasm_sym_table_free(&dasm->romcalls);
+ tilem_disasm_sym_table_free(&dasm->flags);
+ tilem_disasm_sym_table_free(&dasm->macros);
+ tilem_free(dasm);
+}
+
+/* Find symbol in the given table, if any */
+static TilemDisasmSymbol* find_symbol(const TilemDisasmSymTable* stab,
+ dword value)
+{
+ int start, end, i;
+
+ start = 0;
+ end = stab->nsyms;
+ while (start < end) {
+ i = (start + end) / 2;
+ if (stab->syms[i].value == value)
+ return &stab->syms[i];
+ else if (stab->syms[i].value <= value)
+ start = i + 1;
+ else
+ end = i;
+ }
+ return NULL;
+}
+
+/* Find previous symbol in the given table, if any */
+static TilemDisasmSymbol* find_prev_symbol(const TilemDisasmSymTable* stab,
+ dword value)
+{
+ int start, end, i;
+
+ start = 0;
+ end = stab->nsyms;
+ while (start < end) {
+ i = (start + end) / 2;
+ if (stab->syms[i].value <= value)
+ start = i + 1;
+ else
+ end = i;
+ }
+ if (start > 0)
+ return &stab->syms[start - 1];
+ else
+ return NULL;
+}
+
+/* Find symbol with given name */
+static TilemDisasmSymbol* find_symbol_by_name(const TilemDisasmSymTable* stab,
+ const char* name)
+{
+ int i;
+ for (i = 0; i < stab->nsyms; i++)
+ if (!strcmp(stab->syms[i].name, name))
+ return &stab->syms[i];
+ return NULL;
+}
+
+/* Find a given symbol in the table, or create a new one */
+static TilemDisasmSymbol* add_symbol(TilemDisasmSymTable* stab,
+ dword value)
+{
+ int start, end, i;
+ TilemDisasmSymbol* syms;
+
+ start = 0;
+ end = stab->nsyms;
+
+ while (start < end) {
+ i = (start + end) / 2;
+ if (stab->syms[i].value == value)
+ return &stab->syms[i];
+ else if (stab->syms[i].value < value)
+ start = i + 1;
+ else
+ end = i;
+ }
+
+ /* insert new label into the array */
+ if (stab->nsyms < stab->nsyms_a) {
+ if (start < stab->nsyms)
+ memmove(&stab->syms[start + 1], &stab->syms[start],
+ ((stab->nsyms - start)
+ * sizeof(TilemDisasmSymbol)));
+ }
+ else {
+ stab->nsyms_a = (stab->nsyms + 1) * 2;
+ syms = tilem_new(TilemDisasmSymbol, stab->nsyms_a);
+ if (start > 0)
+ memcpy(syms, stab->syms,
+ start * sizeof(TilemDisasmSymbol));
+ if (start < stab->nsyms)
+ memcpy(syms + start + 1, stab->syms + start,
+ ((stab->nsyms - start)
+ * sizeof(TilemDisasmSymbol)));
+ tilem_free(stab->syms);
+ stab->syms = syms;
+ }
+
+ stab->nsyms++;
+
+ stab->syms[start].value = value;
+ stab->syms[start].name = NULL;
+ return &stab->syms[start];
+}
+
+/* Remove a symbol from the table */
+static void del_symbol(TilemDisasmSymTable* stab,
+ TilemDisasmSymbol* sym)
+{
+ int n = sym - stab->syms;
+
+ tilem_free(sym->name);
+
+ if (n < stab->nsyms - 1) {
+ memmove(sym, sym + 1,
+ (stab->nsyms - n - 1) * sizeof(TilemDisasmSymbol));
+ }
+
+ stab->nsyms--;
+}
+
+static void set_symbol(TilemDisasmSymTable* stab,
+ const char* name, dword value)
+{
+ TilemDisasmSymbol* sym;
+
+ if ((sym = find_symbol_by_name(stab, name))) {
+ if (sym->value == value)
+ return;
+ else
+ del_symbol(stab, sym);
+ }
+
+ sym = add_symbol(stab, value);
+ tilem_free(sym->name);
+ sym->name = tilem_new_atomic(char, strlen(name) + 1);
+ strcpy(sym->name, name);
+}
+
+static char* skipws(char* p)
+{
+ while (*p == ' ' || *p == '\t')
+ p++;
+ return p;
+}
+
+static char* skipwc(char* p)
+{
+ while ((unsigned char) *p > ' ')
+ p++;
+ return p;
+}
+
+static int parse_sym_value(const char* text, dword* value)
+{
+ char* p;
+ dword x;
+
+ if (text[0] >= '0' && text[0] <= '7' && text[1] == ',') {
+ x = strtol(text + 2, &p, 16);
+ *value = 0x1000 + (x << 4) + (text[0] - '0');
+ }
+ else {
+ *value = strtol(text, &p, 16);
+ }
+
+ return (p != text && *p == 0);
+}
+
+static int parse_sym_line(TilemDisasmSymTable* stab, char* line)
+{
+ char *w1end, *w2start, *w2end, *name;
+ dword value;
+
+ if (line[0] == '#' || line[0] == ';')
+ return 1;
+
+ w1end = skipwc(line);
+ w2start = skipws(w1end);
+ w2end = skipwc(w2start);
+
+ if (w1end == line || w2start == w1end || w2end == w2start)
+ return 1;
+ if (*w2end)
+ return 1;
+
+ *w1end = *w2end = 0;
+
+ if (*line >= '0' && *line <= '9') {
+ name = w2start;
+ if (!parse_sym_value(line, &value))
+ return 1;
+ }
+ else {
+ name = line;
+ if (!parse_sym_value(w2start, &value))
+ return 1;
+ }
+
+ set_symbol(stab, name, value);
+ return 0;
+}
+
+int tilem_disasm_read_symbol_file(TilemDisasm* dasm, FILE* symfile)
+{
+ char buf[1024];
+ char* p;
+ TilemDisasmSymTable* curtbl;
+ int status = 1;
+
+ curtbl = &dasm->labels;
+
+ while (fgets(buf, sizeof(buf), symfile)) {
+ p = buf + strlen(buf);
+ while (p != buf && (p[-1] == '\n' || p[-1] == '\r'))
+ p--;
+ *p = 0;
+
+ if (!strcmp(buf, "[labels]"))
+ curtbl = &dasm->labels;
+ else if (!strcmp(buf, "[romcalls]"))
+ curtbl = &dasm->romcalls;
+ else if (!strcmp(buf, "[flags]"))
+ curtbl = &dasm->flags;
+ else if (!strcmp(buf, "[macros]"))
+ curtbl = &dasm->macros;
+ else if (!parse_sym_line(curtbl, buf))
+ status = 0;
+ }
+
+ return status;
+}
+
+void tilem_disasm_set_label(TilemDisasm* dasm, const char* name,
+ dword value)
+{
+ set_symbol(&dasm->labels, name, value);
+}
+
+int tilem_disasm_get_label(const TilemDisasm* dasm, const char* name,
+ dword* value)
+{
+ TilemDisasmSymbol* sym = find_symbol_by_name(&dasm->labels, name);
+
+ if (!sym)
+ return 0;
+ else if (value)
+ *value = sym->value;
+ return 1;
+}
+
+const char* tilem_disasm_get_label_at_address(const TilemDisasm* dasm,
+ dword addr)
+{
+ TilemDisasmSymbol* sym = find_symbol(&dasm->labels, addr);
+
+ if (sym)
+ return sym->name;
+ else
+ return NULL;
+}
+
+typedef struct _TilemDisasmInstruction {
+ int length;
+ const char* pattern;
+} TilemDisasmInstruction;
+
+static const TilemDisasmInstruction insts_main[256] = {
+ {1,"NOP"}, {3,"LD~BC,%w"}, {1,"LD~(BC),A"}, {1,"INC~BC"},
+ {1,"INC~B"}, {1,"DEC~B"}, {2,"LD~B,%b"}, {1,"RLCA"},
+ {1,"EX~AF,AF'"}, {1,"ADD~HL,BC"}, {1,"LD~A,(BC)"}, {1,"DEC~BC"},
+ {1,"INC~C"}, {1,"DEC~C"}, {2,"LD~C,%b"}, {1,"RRCA"},
+ {2,"DJNZ~%r"}, {3,"LD~DE,%w"}, {1,"LD~(DE),A"}, {1,"INC~DE"},
+ {1,"INC~D"}, {1,"DEC~D"}, {2,"LD~D,%b"}, {1,"RLA"},
+ {2,"JR~%r"}, {1,"ADD~HL,DE"}, {1,"LD~A,(DE)"}, {1,"DEC~DE"},
+ {1,"INC~E"}, {1,"DEC~E"}, {2,"LD~E,%b"}, {1,"RRA"},
+ {2,"JR~NZ,%r"}, {3,"LD~HL,%w"}, {3,"LD~(%a),HL"}, {1,"INC~HL"},
+ {1,"INC~H"}, {1,"DEC~H"}, {2,"LD~H,%b"}, {1,"DAA"},
+ {2,"JR~Z,%r"}, {1,"ADD~HL,HL"}, {3,"LD~HL,(%a)"}, {1,"DEC~HL"},
+ {1,"INC~L"}, {1,"DEC~L"}, {2,"LD~L,%b"}, {1,"CPL"},
+ {2,"JR~NC,%r"}, {3,"LD~SP,%w"}, {3,"LD~(%a),A"}, {1,"INC~SP"},
+ {1,"INC~(HL)"}, {1,"DEC~(HL)"}, {2,"LD~(HL),%b"}, {1,"SCF"},
+ {2,"JR~C,%r"}, {1,"ADD~HL,SP"}, {3,"LD~A,(%a)"}, {1,"DEC~SP"},
+ {1,"INC~A"}, {1,"DEC~A"}, {2,"LD~A,%b"}, {1,"CCF"},
+
+ {1,"LD~B,B"}, {1,"LD~B,C"}, {1,"LD~B,D"}, {1,"LD~B,E"},
+ {1,"LD~B,H"}, {1,"LD~B,L"}, {1,"LD~B,(HL)"}, {1,"LD~B,A"},
+ {1,"LD~C,B"}, {1,"LD~C,C"}, {1,"LD~C,D"}, {1,"LD~C,E"},
+ {1,"LD~C,H"}, {1,"LD~C,L"}, {1,"LD~C,(HL)"}, {1,"LD~C,A"},
+ {1,"LD~D,B"}, {1,"LD~D,C"}, {1,"LD~D,D"}, {1,"LD~D,E"},
+ {1,"LD~D,H"}, {1,"LD~D,L"}, {1,"LD~D,(HL)"}, {1,"LD~D,A"},
+ {1,"LD~E,B"}, {1,"LD~E,C"}, {1,"LD~E,D"}, {1,"LD~E,E"},
+ {1,"LD~E,H"}, {1,"LD~E,L"}, {1,"LD~E,(HL)"}, {1,"LD~E,A"},
+ {1,"LD~H,B"}, {1,"LD~H,C"}, {1,"LD~H,D"}, {1,"LD~H,E"},
+ {1,"LD~H,H"}, {1,"LD~H,L"}, {1,"LD~H,(HL)"}, {1,"LD~H,A"},
+ {1,"LD~L,B"}, {1,"LD~L,C"}, {1,"LD~L,D"}, {1,"LD~L,E"},
+ {1,"LD~L,H"}, {1,"LD~L,L"}, {1,"LD~L,(HL)"}, {1,"LD~L,A"},
+ {1,"LD~(HL),B"}, {1,"LD~(HL),C"}, {1,"LD~(HL),D"}, {1,"LD~(HL),E"},
+ {1,"LD~(HL),H"}, {1,"LD~(HL),L"}, {1,"HALT"}, {1,"LD~(HL),A"},
+ {1,"LD~A,B"}, {1,"LD~A,C"}, {1,"LD~A,D"}, {1,"LD~A,E"},
+ {1,"LD~A,H"}, {1,"LD~A,L"}, {1,"LD~A,(HL)"}, {1,"LD~A,A"},
+
+ {1,"ADD~A,B"}, {1,"ADD~A,C"}, {1,"ADD~A,D"}, {1,"ADD~A,E"},
+ {1,"ADD~A,H"}, {1,"ADD~A,L"}, {1,"ADD~A,(HL)"}, {1,"ADD~A,A"},
+ {1,"ADC~A,B"}, {1,"ADC~A,C"}, {1,"ADC~A,D"}, {1,"ADC~A,E"},
+ {1,"ADC~A,H"}, {1,"ADC~A,L"}, {1,"ADC~A,(HL)"}, {1,"ADC~A,A"},
+ {1,"SUB~B"}, {1,"SUB~C"}, {1,"SUB~D"}, {1,"SUB~E"},
+ {1,"SUB~H"}, {1,"SUB~L"}, {1,"SUB~(HL)"}, {1,"SUB~A"},
+ {1,"SBC~A,B"}, {1,"SBC~A,C"}, {1,"SBC~A,D"}, {1,"SBC~A,E"},
+ {1,"SBC~A,H"}, {1,"SBC~A,L"}, {1,"SBC~A,(HL)"}, {1,"SBC~A,A"},
+ {1,"AND~B"}, {1,"AND~C"}, {1,"AND~D"}, {1,"AND~E"},
+ {1,"AND~H"}, {1,"AND~L"}, {1,"AND~(HL)"}, {1,"AND~A"},
+ {1,"XOR~B"}, {1,"XOR~C"}, {1,"XOR~D"}, {1,"XOR~E"},
+ {1,"XOR~H"}, {1,"XOR~L"}, {1,"XOR~(HL)"}, {1,"XOR~A"},
+ {1,"OR~B"}, {1,"OR~C"}, {1,"OR~D"}, {1,"OR~E"},
+ {1,"OR~H"}, {1,"OR~L"}, {1,"OR~(HL)"}, {1,"OR~A"},
+ {1,"CP~B"}, {1,"CP~C"}, {1,"CP~D"}, {1,"CP~E"},
+ {1,"CP~H"}, {1,"CP~L"}, {1,"CP~(HL)"}, {1,"CP~A"},
+
+ {1,"RET~NZ"}, {1,"POP~BC"}, {3,"JP~NZ,%j"}, {3,"JP~%j"},
+ {3,"CALL~NZ,%j"}, {1,"PUSH~BC"}, {2,"ADD~A,%b"}, {1,"RST~%z"},
+ {1,"RET~Z"}, {1,"RET"}, {3,"JP~Z,%j"}, {1,0},
+ {3,"CALL~Z,%j"}, {3,"CALL~%j"}, {2,"ADC~A,%b"}, {1,"RST~%z"},
+ {1,"RET~NC"}, {1,"POP~DE"}, {3,"JP~NC,%j"}, {2,"OUT~(%b),A"},
+ {3,"CALL~NC,%j"}, {1,"PUSH~DE"}, {2,"SUB~%b"}, {1,"RST~%z"},
+ {1,"RET~C"}, {1,"EXX"}, {3,"JP~C,%j"}, {2,"IN~A,(%b)"},
+ {3,"CALL~C,%j"}, {1,0}, {2,"SBC~A,%b"}, {1,"RST~%z"},
+ {1,"RET~PO"}, {1,"POP~HL"}, {3,"JP~PO,%j"}, {1,"EX~(SP),HL"},
+ {3,"CALL~PO,%j"}, {1,"PUSH~HL"}, {2,"AND~%b"}, {1,"RST~%z"},
+ {1,"RET~PE"}, {1,"JP~(HL)"}, {3,"JP~PE,%j"}, {1,"EX~DE,HL"},
+ {3,"CALL~PE,%j"}, {1,0}, {2,"XOR~%b"}, {1,"RST~%z"},
+ {1,"RET~P"}, {1,"POP~AF"}, {3,"JP~P,%j"}, {1,"DI"},
+ {3,"CALL~P,%j"}, {1,"PUSH~AF"}, {2,"OR~%b"}, {1,"RST~%z"},
+ {1,"RET~M"}, {1,"LD~SP,HL"}, {3,"JP~M,%j"}, {1,"EI"},
+ {3,"CALL~M,%j"}, {1,0}, {2,"CP~%b"}, {1,"RST~%z"}};
+
+static const TilemDisasmInstruction insts_ddfd[256] = {
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {1,0}, {2,"ADD~%i,BC"}, {1,0}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {1,0}, {2,"ADD~%i,DE"}, {1,0}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {1,0}, {4,"LD~%i,%w"}, {4,"LD~(%a),%i"}, {2,"INC~%i"},
+ {2,"INC~%iH"}, {2,"DEC~%iH"}, {3,"LD~%iH,%b"}, {1,0},
+ {1,0}, {2,"ADD~%i,%i"}, {4,"LD~%i,(%a)"}, {2,"DEC~%i"},
+ {2,"INC~%iL"}, {2,"DEC~%iL"}, {3,"LD~%iL,%b"}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {3,"INC~(%i%s)"}, {3,"DEC~(%i%s)"}, {4,"LD~(%i%s),%b"}, {1,0},
+ {1,0}, {2,"ADD~%i,SP"}, {1,0}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {2,"LD~B,%iH"}, {2,"LD~B,%iL"}, {3,"LD~B,(%i%s)"}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {2,"LD~C,%iH"}, {2,"LD~C,%iL"}, {3,"LD~C,(%i%s)"}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {2,"LD~D,%iH"}, {2,"LD~D,%iL"}, {3,"LD~D,(%i%s)"}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {2,"LD~E,%iH"}, {2,"LD~E,%iL"}, {3,"LD~E,(%i%s)"}, {1,0},
+ {2,"LD~%iH,B"}, {2,"LD~%iH,C"}, {2,"LD~%iH,D"}, {2,"LD~%iH,E"},
+ {2,"LD~%iH,%iH"}, {2,"LD~%iH,%iL"}, {3,"LD~H,(%i%s)"}, {2,"LD~%iH,A"},
+ {2,"LD~%iL,B"}, {2,"LD~%iL,C"}, {2,"LD~%iL,D"}, {2,"LD~%iL,E"},
+ {2,"LD~%iL,%iH"}, {2,"LD~%iL,%iL"}, {3,"LD~L,(%i%s)"}, {2,"LD~%iL,A"},
+ {3,"LD~(%i%s),B"}, {3,"LD~(%i%s),C"}, {3,"LD~(%i%s),D"}, {3,"LD~(%i%s),E"},
+ {3,"LD~(%i%s),H"}, {3,"LD~(%i%s),L"}, {1,0}, {3,"LD~(%i%s),A"},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {2,"LD~A,%iH"}, {2,"LD~A,%iL"}, {3,"LD~A,(%i%s)"}, {1,0},
+
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {2,"ADD~A,%iH"}, {2,"ADD~A,%iL"}, {3,"ADD~A,(%i%s)"}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {2,"ADC~A,%iH"}, {2,"ADC~A,%iL"}, {3,"ADC~A,(%i%s)"}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {2,"SUB~%iH"}, {2,"SUB~%iL"}, {3,"SUB~(%i%s)"}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {2,"SBC~A,%iH"}, {2,"SBC~A,%iL"}, {3,"SBC~A,(%i%s)"}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {2,"AND~%iH"}, {2,"AND~%iL"}, {3,"AND~(%i%s)"}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {2,"XOR~%iH"}, {2,"XOR~%iL"}, {3,"XOR~(%i%s)"}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {2,"OR~%iH"}, {2,"OR~%iL"}, {3,"OR~(%i%s)"}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {2,"CP~%iH"}, {2,"CP~%iL"}, {3,"CP~(%i%s)"}, {1,0},
+
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {1,0}, {2,"POP~%i"}, {1,0}, {2,"EX~(SP),%i"},
+ {1,0}, {2,"PUSH~%i"}, {1,0}, {1,0},
+ {1,0}, {2,"JP~(%i)"}, {1,0}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0},
+ {1,0}, {2,"LD~SP,%i"}, {1,0}, {1,0},
+ {1,0}, {1,0}, {1,0}, {1,0}};
+
+static const TilemDisasmInstruction insts_cb[256] = {
+ {2,"RLC~B"}, {2,"RLC~C"}, {2,"RLC~D"}, {2,"RLC~E"},
+ {2,"RLC~H"}, {2,"RLC~L"}, {2,"RLC~(HL)"}, {2,"RLC~A"},
+ {2,"RRC~B"}, {2,"RRC~C"}, {2,"RRC~D"}, {2,"RRC~E"},
+ {2,"RRC~H"}, {2,"RRC~L"}, {2,"RRC~(HL)"}, {2,"RRC~A"},
+ {2,"RL~B"}, {2,"RL~C"}, {2,"RL~D"}, {2,"RL~E"},
+ {2,"RL~H"}, {2,"RL~L"}, {2,"RL~(HL)"}, {2,"RL~A"},
+ {2,"RR~B"}, {2,"RR~C"}, {2,"RR~D"}, {2,"RR~E"},
+ {2,"RR~H"}, {2,"RR~L"}, {2,"RR~(HL)"}, {2,"RR~A"},
+ {2,"SLA~B"}, {2,"SLA~C"}, {2,"SLA~D"}, {2,"SLA~E"},
+ {2,"SLA~H"}, {2,"SLA~L"}, {2,"SLA~(HL)"}, {2,"SLA~A"},
+ {2,"SRA~B"}, {2,"SRA~C"}, {2,"SRA~D"}, {2,"SRA~E"},
+ {2,"SRA~H"}, {2,"SRA~L"}, {2,"SRA~(HL)"}, {2,"SRA~A"},
+ {2,"SLIA~B"}, {2,"SLIA~C"}, {2,"SLIA~D"}, {2,"SLIA~E"},
+ {2,"SLIA~H"}, {2,"SLIA~L"}, {2,"SLIA~(HL)"}, {2,"SLIA~A"},
+ {2,"SRL~B"}, {2,"SRL~C"}, {2,"SRL~D"}, {2,"SRL~E"},
+ {2,"SRL~H"}, {2,"SRL~L"}, {2,"SRL~(HL)"}, {2,"SRL~A"},
+
+ {2,"BIT~0,B"}, {2,"BIT~0,C"}, {2,"BIT~0,D"}, {2,"BIT~0,E"},
+ {2,"BIT~0,H"}, {2,"BIT~0,L"}, {2,"BIT~0,(HL)"}, {2,"BIT~0,A"},
+ {2,"BIT~1,B"}, {2,"BIT~1,C"}, {2,"BIT~1,D"}, {2,"BIT~1,E"},
+ {2,"BIT~1,H"}, {2,"BIT~1,L"}, {2,"BIT~1,(HL)"}, {2,"BIT~1,A"},
+ {2,"BIT~2,B"}, {2,"BIT~2,C"}, {2,"BIT~2,D"}, {2,"BIT~2,E"},
+ {2,"BIT~2,H"}, {2,"BIT~2,L"}, {2,"BIT~2,(HL)"}, {2,"BIT~2,A"},
+ {2,"BIT~3,B"}, {2,"BIT~3,C"}, {2,"BIT~3,D"}, {2,"BIT~3,E"},
+ {2,"BIT~3,H"}, {2,"BIT~3,L"}, {2,"BIT~3,(HL)"}, {2,"BIT~3,A"},
+ {2,"BIT~4,B"}, {2,"BIT~4,C"}, {2,"BIT~4,D"}, {2,"BIT~4,E"},
+ {2,"BIT~4,H"}, {2,"BIT~4,L"}, {2,"BIT~4,(HL)"}, {2,"BIT~4,A"},
+ {2,"BIT~5,B"}, {2,"BIT~5,C"}, {2,"BIT~5,D"}, {2,"BIT~5,E"},
+ {2,"BIT~5,H"}, {2,"BIT~5,L"}, {2,"BIT~5,(HL)"}, {2,"BIT~5,A"},
+ {2,"BIT~6,B"}, {2,"BIT~6,C"}, {2,"BIT~6,D"}, {2,"BIT~6,E"},
+ {2,"BIT~6,H"}, {2,"BIT~6,L"}, {2,"BIT~6,(HL)"}, {2,"BIT~6,A"},
+ {2,"BIT~7,B"}, {2,"BIT~7,C"}, {2,"BIT~7,D"}, {2,"BIT~7,E"},
+ {2,"BIT~7,H"}, {2,"BIT~7,L"}, {2,"BIT~7,(HL)"}, {2,"BIT~7,A"},
+
+ {2,"RES~0,B"}, {2,"RES~0,C"}, {2,"RES~0,D"}, {2,"RES~0,E"},
+ {2,"RES~0,H"}, {2,"RES~0,L"}, {2,"RES~0,(HL)"}, {2,"RES~0,A"},
+ {2,"RES~1,B"}, {2,"RES~1,C"}, {2,"RES~1,D"}, {2,"RES~1,E"},
+ {2,"RES~1,H"}, {2,"RES~1,L"}, {2,"RES~1,(HL)"}, {2,"RES~1,A"},
+ {2,"RES~2,B"}, {2,"RES~2,C"}, {2,"RES~2,D"}, {2,"RES~2,E"},
+ {2,"RES~2,H"}, {2,"RES~2,L"}, {2,"RES~2,(HL)"}, {2,"RES~2,A"},
+ {2,"RES~3,B"}, {2,"RES~3,C"}, {2,"RES~3,D"}, {2,"RES~3,E"},
+ {2,"RES~3,H"}, {2,"RES~3,L"}, {2,"RES~3,(HL)"}, {2,"RES~3,A"},
+ {2,"RES~4,B"}, {2,"RES~4,C"}, {2,"RES~4,D"}, {2,"RES~4,E"},
+ {2,"RES~4,H"}, {2,"RES~4,L"}, {2,"RES~4,(HL)"}, {2,"RES~4,A"},
+ {2,"RES~5,B"}, {2,"RES~5,C"}, {2,"RES~5,D"}, {2,"RES~5,E"},
+ {2,"RES~5,H"}, {2,"RES~5,L"}, {2,"RES~5,(HL)"}, {2,"RES~5,A"},
+ {2,"RES~6,B"}, {2,"RES~6,C"}, {2,"RES~6,D"}, {2,"RES~6,E"},
+ {2,"RES~6,H"}, {2,"RES~6,L"}, {2,"RES~6,(HL)"}, {2,"RES~6,A"},
+ {2,"RES~7,B"}, {2,"RES~7,C"}, {2,"RES~7,D"}, {2,"RES~7,E"},
+ {2,"RES~7,H"}, {2,"RES~7,L"}, {2,"RES~7,(HL)"}, {2,"RES~7,A"},
+
+ {2,"SET~0,B"}, {2,"SET~0,C"}, {2,"SET~0,D"}, {2,"SET~0,E"},
+ {2,"SET~0,H"}, {2,"SET~0,L"}, {2,"SET~0,(HL)"}, {2,"SET~0,A"},
+ {2,"SET~1,B"}, {2,"SET~1,C"}, {2,"SET~1,D"}, {2,"SET~1,E"},
+ {2,"SET~1,H"}, {2,"SET~1,L"}, {2,"SET~1,(HL)"}, {2,"SET~1,A"},
+ {2,"SET~2,B"}, {2,"SET~2,C"}, {2,"SET~2,D"}, {2,"SET~2,E"},
+ {2,"SET~2,H"}, {2,"SET~2,L"}, {2,"SET~2,(HL)"}, {2,"SET~2,A"},
+ {2,"SET~3,B"}, {2,"SET~3,C"}, {2,"SET~3,D"}, {2,"SET~3,E"},
+ {2,"SET~3,H"}, {2,"SET~3,L"}, {2,"SET~3,(HL)"}, {2,"SET~3,A"},
+ {2,"SET~4,B"}, {2,"SET~4,C"}, {2,"SET~4,D"}, {2,"SET~4,E"},
+ {2,"SET~4,H"}, {2,"SET~4,L"}, {2,"SET~4,(HL)"}, {2,"SET~4,A"},
+ {2,"SET~5,B"}, {2,"SET~5,C"}, {2,"SET~5,D"}, {2,"SET~5,E"},
+ {2,"SET~5,H"}, {2,"SET~5,L"}, {2,"SET~5,(HL)"}, {2,"SET~5,A"},
+ {2,"SET~6,B"}, {2,"SET~6,C"}, {2,"SET~6,D"}, {2,"SET~6,E"},
+ {2,"SET~6,H"}, {2,"SET~6,L"}, {2,"SET~6,(HL)"}, {2,"SET~6,A"},
+ {2,"SET~7,B"}, {2,"SET~7,C"}, {2,"SET~7,D"}, {2,"SET~7,E"},
+ {2,"SET~7,H"}, {2,"SET~7,L"}, {2,"SET~7,(HL)"}, {2,"SET~7,A"}};
+
+static const TilemDisasmInstruction insts_ddfdcb[256] = {
+ {4,"RLC~B,(%i%s)"}, {4,"RLC~C,(%i%s)"}, {4,"RLC~D,(%i%s)"}, {4,"RLC~E,(%i%s)"},
+ {4,"RLC~H,(%i%s)"}, {4,"RLC~L,(%i%s)"}, {4,"RLC~(%i%s)"}, {4,"RLC~A,(%i%s)"},
+ {4,"RRC~B,(%i%s)"}, {4,"RRC~C,(%i%s)"}, {4,"RRC~D,(%i%s)"}, {4,"RRC~E,(%i%s)"},
+ {4,"RRC~H,(%i%s)"}, {4,"RRC~L,(%i%s)"}, {4,"RRC~(%i%s)"}, {4,"RRC~A,(%i%s)"},
+ {4,"RL~B,(%i%s)"}, {4,"RL~C,(%i%s)"}, {4,"RL~D,(%i%s)"}, {4,"RL~E,(%i%s)"},
+ {4,"RL~H,(%i%s)"}, {4,"RL~L,(%i%s)"}, {4,"RL~(%i%s)"}, {4,"RL~A,(%i%s)"},
+ {4,"RR~B,(%i%s)"}, {4,"RR~C,(%i%s)"}, {4,"RR~D,(%i%s)"}, {4,"RR~E,(%i%s)"},
+ {4,"RR~H,(%i%s)"}, {4,"RR~L,(%i%s)"}, {4,"RR~(%i%s)"}, {4,"RR~A,(%i%s)"},
+ {4,"SLA~B,(%i%s)"}, {4,"SLA~C,(%i%s)"}, {4,"SLA~D,(%i%s)"}, {4,"SLA~E,(%i%s)"},
+ {4,"SLA~H,(%i%s)"}, {4,"SLA~L,(%i%s)"}, {4,"SLA~(%i%s)"}, {4,"SLA~A,(%i%s)"},
+ {4,"SRA~B,(%i%s)"}, {4,"SRA~C,(%i%s)"}, {4,"SRA~D,(%i%s)"}, {4,"SRA~E,(%i%s)"},
+ {4,"SRA~H,(%i%s)"}, {4,"SRA~L,(%i%s)"}, {4,"SRA~(%i%s)"}, {4,"SRA~A,(%i%s)"},
+ {4,"SLIA~B,(%i%s)"}, {4,"SLIA~C,(%i%s)"}, {4,"SLIA~D,(%i%s)"}, {4,"SLIA~E,(%i%s)"},
+ {4,"SLIA~H,(%i%s)"}, {4,"SLIA~L,(%i%s)"}, {4,"SLIA~(%i%s)"}, {4,"SLIA~A,(%i%s)"},
+ {4,"SRL~B,(%i%s)"}, {4,"SRL~C,(%i%s)"}, {4,"SRL~D,(%i%s)"}, {4,"SRL~E,(%i%s)"},
+ {4,"SRL~H,(%i%s)"}, {4,"SRL~L,(%i%s)"}, {4,"SRL~(%i%s)"}, {4,"SRL~A,(%i%s)"},
+
+ {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f*"},
+ {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f"}, {4,"BIT~%f*"},
+ {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f*"},
+ {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f"}, {4,"BIT~%f*"},
+ {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f*"},
+ {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f"}, {4,"BIT~%f*"},
+ {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f*"},
+ {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f"}, {4,"BIT~%f*"},
+ {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f*"},
+ {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f"}, {4,"BIT~%f*"},
+ {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f*"},
+ {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f"}, {4,"BIT~%f*"},
+ {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f*"},
+ {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f"}, {4,"BIT~%f*"},
+ {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f*"},
+ {4,"BIT~%f*"}, {4,"BIT~%f*"}, {4,"BIT~%f"}, {4,"BIT~%f*"},
+
+ {4,"RES~0,B,(%i%s)"}, {4,"RES~0,C,(%i%s)"}, {4,"RES~0,D,(%i%s)"}, {4,"RES~0,E,(%i%s)"},
+ {4,"RES~0,H,(%i%s)"}, {4,"RES~0,L,(%i%s)"}, {4,"RES~%f"}, {4,"RES~0,A,(%i%s)"},
+ {4,"RES~1,B,(%i%s)"}, {4,"RES~1,C,(%i%s)"}, {4,"RES~1,D,(%i%s)"}, {4,"RES~1,E,(%i%s)"},
+ {4,"RES~1,H,(%i%s)"}, {4,"RES~1,L,(%i%s)"}, {4,"RES~%f"}, {4,"RES~1,A,(%i%s)"},
+ {4,"RES~2,B,(%i%s)"}, {4,"RES~2,C,(%i%s)"}, {4,"RES~2,D,(%i%s)"}, {4,"RES~2,E,(%i%s)"},
+ {4,"RES~2,H,(%i%s)"}, {4,"RES~2,L,(%i%s)"}, {4,"RES~%f"}, {4,"RES~2,A,(%i%s)"},
+ {4,"RES~3,B,(%i%s)"}, {4,"RES~3,C,(%i%s)"}, {4,"RES~3,D,(%i%s)"}, {4,"RES~3,E,(%i%s)"},
+ {4,"RES~3,H,(%i%s)"}, {4,"RES~3,L,(%i%s)"}, {4,"RES~%f"}, {4,"RES~3,A,(%i%s)"},
+ {4,"RES~4,B,(%i%s)"}, {4,"RES~4,C,(%i%s)"}, {4,"RES~4,D,(%i%s)"}, {4,"RES~4,E,(%i%s)"},
+ {4,"RES~4,H,(%i%s)"}, {4,"RES~4,L,(%i%s)"}, {4,"RES~%f"}, {4,"RES~4,A,(%i%s)"},
+ {4,"RES~5,B,(%i%s)"}, {4,"RES~5,C,(%i%s)"}, {4,"RES~5,D,(%i%s)"}, {4,"RES~5,E,(%i%s)"},
+ {4,"RES~5,H,(%i%s)"}, {4,"RES~5,L,(%i%s)"}, {4,"RES~%f"}, {4,"RES~5,A,(%i%s)"},
+ {4,"RES~6,B,(%i%s)"}, {4,"RES~6,C,(%i%s)"}, {4,"RES~6,D,(%i%s)"}, {4,"RES~6,E,(%i%s)"},
+ {4,"RES~6,H,(%i%s)"}, {4,"RES~6,L,(%i%s)"}, {4,"RES~%f"}, {4,"RES~6,A,(%i%s)"},
+ {4,"RES~7,B,(%i%s)"}, {4,"RES~7,C,(%i%s)"}, {4,"RES~7,D,(%i%s)"}, {4,"RES~7,E,(%i%s)"},
+ {4,"RES~7,H,(%i%s)"}, {4,"RES~7,L,(%i%s)"}, {4,"RES~%f"}, {4,"RES~7,A,(%i%s)"},
+
+ {4,"SET~0,B,(%i%s)"}, {4,"SET~0,C,(%i%s)"}, {4,"SET~0,D,(%i%s)"}, {4,"SET~0,E,(%i%s)"},
+ {4,"SET~0,H,(%i%s)"}, {4,"SET~0,L,(%i%s)"}, {4,"SET~%f"}, {4,"SET~0,A,(%i%s)"},
+ {4,"SET~1,B,(%i%s)"}, {4,"SET~1,C,(%i%s)"}, {4,"SET~1,D,(%i%s)"}, {4,"SET~1,E,(%i%s)"},
+ {4,"SET~1,H,(%i%s)"}, {4,"SET~1,L,(%i%s)"}, {4,"SET~%f"}, {4,"SET~1,A,(%i%s)"},
+ {4,"SET~2,B,(%i%s)"}, {4,"SET~2,C,(%i%s)"}, {4,"SET~2,D,(%i%s)"}, {4,"SET~2,E,(%i%s)"},
+ {4,"SET~2,H,(%i%s)"}, {4,"SET~2,L,(%i%s)"}, {4,"SET~%f"}, {4,"SET~2,A,(%i%s)"},
+ {4,"SET~3,B,(%i%s)"}, {4,"SET~3,C,(%i%s)"}, {4,"SET~3,D,(%i%s)"}, {4,"SET~3,E,(%i%s)"},
+ {4,"SET~3,H,(%i%s)"}, {4,"SET~3,L,(%i%s)"}, {4,"SET~%f"}, {4,"SET~3,A,(%i%s)"},
+ {4,"SET~4,B,(%i%s)"}, {4,"SET~4,C,(%i%s)"}, {4,"SET~4,D,(%i%s)"}, {4,"SET~4,E,(%i%s)"},
+ {4,"SET~4,H,(%i%s)"}, {4,"SET~4,L,(%i%s)"}, {4,"SET~%f"}, {4,"SET~4,A,(%i%s)"},
+ {4,"SET~5,B,(%i%s)"}, {4,"SET~5,C,(%i%s)"}, {4,"SET~5,D,(%i%s)"}, {4,"SET~5,E,(%i%s)"},
+ {4,"SET~5,H,(%i%s)"}, {4,"SET~5,L,(%i%s)"}, {4,"SET~%f"}, {4,"SET~5,A,(%i%s)"},
+ {4,"SET~6,B,(%i%s)"}, {4,"SET~6,C,(%i%s)"}, {4,"SET~6,D,(%i%s)"}, {4,"SET~6,E,(%i%s)"},
+ {4,"SET~6,H,(%i%s)"}, {4,"SET~6,L,(%i%s)"}, {4,"SET~%f"}, {4,"SET~6,A,(%i%s)"},
+ {4,"SET~7,B,(%i%s)"}, {4,"SET~7,C,(%i%s)"}, {4,"SET~7,D,(%i%s)"}, {4,"SET~7,E,(%i%s)"},
+ {4,"SET~7,H,(%i%s)"}, {4,"SET~7,L,(%i%s)"}, {4,"SET~%f"}, {4,"SET~7,A,(%i%s)"}};
+
+static const TilemDisasmInstruction insts_ed[256] = {
+ {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0},
+
+ {2,"IN~B,(C)"}, {2,"OUT~(C),B"}, {2,"SBC~HL,BC"}, {4,"LD~(%a),BC"},
+ {2,"NEG"}, {2,"RETN"}, {2,"IM~0"}, {2,"LD~I,A"},
+ {2,"IN~C,(C)"}, {2,"OUT~(C),C"}, {2,"ADC~HL,BC"}, {4,"LD~BC,(%a)"},
+ {2,"NEG*"}, {2,"RETI"}, {2,"IM~0*"}, {2,"LD~R,A"},
+ {2,"IN~D,(C)"}, {2,"OUT~(C),D"}, {2,"SBC~HL,DE"}, {4,"LD~(%a),DE"},
+ {2,"NEG*"}, {2,"RETN*"}, {2,"IM~1"}, {2,"LD~A,I"},
+ {2,"IN~E,(C)"}, {2,"OUT~(C),E"}, {2,"ADC~HL,DE"}, {4,"LD~DE,(%a)"},
+ {2,"NEG*"}, {2,"RETN*"}, {2,"IM~2"}, {2,"LD~A,R"},
+ {2,"IN~H,(C)"}, {2,"OUT~(C),H"}, {2,"SBC~HL,HL"}, {4,"LD~(%a),HL*"},
+ {2,"NEG*"}, {2,"RETN*"}, {2,"IM~0*"}, {2,"RRD"},
+ {2,"IN~L,(C)"}, {2,"OUT~(C),L"}, {2,"ADC~HL,HL"}, {4,"LD~HL,(%a)*"},
+ {2,"NEG*"}, {2,"RETN*"}, {2,"IM~0*"}, {2,"RLD"},
+ {2,"IN~(C)"}, {2,"OUT~(C),0"}, {2,"SBC~HL,SP"}, {4,"LD~(%a),SP"},
+ {2,"NEG*"}, {2,"RETN*"}, {2,"IM~1*"}, {2,0},
+ {2,"IN~A,(C)"}, {2,"OUT~(C),A"}, {2,"ADC~HL,SP"}, {4,"LD~SP,(%a)"},
+ {2,"NEG*"}, {2,"RETN*"}, {2,"IM~2*"}, {2,0},
+
+ {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0},
+ {2,"LDI"}, {2,"CPI"}, {2,"INI"}, {2,"OUTI"},
+ {2,0}, {2,0}, {2,0}, {2,0},
+ {2,"LDD"}, {2,"CPD"}, {2,"IND"}, {2,"OUTD"},
+ {2,0}, {2,0}, {2,0}, {2,0},
+ {2,"LDIR"}, {2,"CPIR"}, {2,"INIR"}, {2,"OTIR"},
+ {2,0}, {2,0}, {2,0}, {2,0},
+ {2,"LDDR"}, {2,"CPDR"}, {2,"INDR"}, {2,"OTDR"},
+ {2,0}, {2,0}, {2,0}, {2,0},
+
+ {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0},
+ {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}, {2,0}};
+
+/* Count number of bytes of arguments for a given instruction/macro
+ pattern */
+static int pattern_arg_size(const char* pattern)
+{
+ char* p;
+ int count = 0, offs;
+
+ while (*pattern) {
+ if (*pattern != '%')
+ pattern++;
+ else {
+ pattern++;
+
+ if (*pattern >= '0' && *pattern <= '9') {
+ offs = strtol(pattern, &p, 10);
+ pattern = p;
+ }
+ else {
+ offs = count;
+ }
+
+ switch (*pattern) {
+ case 0:
+ pattern--;
+ break;
+
+ case 'b':
+ case 'C':
+ case 'r':
+ case 's':
+ offs++;
+ break;
+
+ case 'a':
+ case 'c':
+ case 'f':
+ case 'j':
+ case 'w':
+ offs += 2;
+ break;
+ }
+
+ pattern++;
+ if (offs > count)
+ count = offs;
+ }
+ }
+
+ return count;
+}
+
+static void get_instruction_info(const TilemDisasm* dasm,
+ const byte* instr,
+ int* length, int* argbase,
+ const char** pattern)
+{
+ const TilemDisasmSymbol* sym;
+ const TilemDisasmInstruction* ii;
+ dword mvalue;
+ int i;
+
+ mvalue = 0;
+ for (i = 0; i < 4; i++) {
+ mvalue = (mvalue << 8) | instr[i];
+ if ((sym = find_symbol(&dasm->macros, mvalue))) {
+ *pattern = sym->name;
+ *length = i + 1 + pattern_arg_size(sym->name);
+ *argbase = i + 1;
+ return;
+ }
+ }
+
+ if (instr[0] == 0xed) {
+ ii = &insts_ed[instr[1]];
+ *argbase = 2;
+ }
+ else if (instr[0] == 0xdd || instr[0] == 0xfd) {
+ if (instr[1] == 0xcb) {
+ ii = &insts_ddfdcb[instr[3]];
+ }
+ else {
+ ii = &insts_ddfd[instr[1]];
+ }
+ *argbase = 2;
+ }
+ else if (instr[0] == 0xcb) {
+ ii = &insts_cb[instr[1]];
+ *argbase = 2;
+ }
+ else {
+ ii = &insts_main[instr[0]];
+ *argbase = 1;
+ }
+
+ *length = ii->length;
+
+ if (ii->pattern) {
+ *pattern = ii->pattern;
+ }
+ else {
+ *argbase = 0;
+ if (ii->length == 1)
+ *pattern = "DB~%b";
+ else
+ *pattern = "DB~%b,%b";
+ }
+}
+
+static void TILEM_ATTR_PRINTF(3, 4)
+printv(char** buf, int* bsize, const char* fmt, ...)
+{
+ va_list ap;
+ int n;
+
+ if (*bsize == 0)
+ return;
+
+ va_start(ap, fmt);
+ n = vsnprintf(*buf, *bsize, fmt, ap);
+ va_end(ap);
+
+ if (n >= *bsize) {
+ *buf += *bsize - 1;
+ **buf = 0;
+ *bsize = 0;
+ }
+ else {
+ *buf += n;
+ **buf = 0;
+ *bsize -= n;
+ }
+}
+
+static void print_byte(char** buf, int* bsize, unsigned int b)
+{
+ printv(buf, bsize, "$%02X", b);
+}
+
+static void print_word(const TilemDisasm* dasm, char** buf, int* bsize,
+ dword w, int autonum, int autodiff)
+{
+ TilemDisasmSymbol* sym;
+
+ if (autonum && w < 0x100) {
+ printv(buf, bsize, "$%04X", w);
+ return;
+ }
+
+ sym = find_prev_symbol(&dasm->labels, w);
+
+ if (sym && !strcmp(sym->name, "flags")) {
+ w -= sym->value;
+ sym = find_symbol(&dasm->flags, w);
+ if (sym) {
+ printv(buf, bsize, "flags + %s", sym->name);
+ }
+ else {
+ printv(buf, bsize, "flags + $%02X", w);
+ }
+ }
+ else if (sym && w == sym->value) {
+ printv(buf, bsize, "%s", sym->name);
+ }
+ else if (sym && autodiff && w > 0x8000 && w - sym->value < 64) {
+ printv(buf, bsize, "%s + %d", sym->name, w - sym->value);
+ }
+ else {
+ printv(buf, bsize, "$%04X", w);
+ }
+}
+
+static void print_romcall(const TilemDisasm* dasm, char** buf, int* bsize,
+ dword w)
+{
+ TilemDisasmSymbol* sym;
+
+ sym = find_symbol(&dasm->romcalls, w);
+ if (sym) {
+ printv(buf, bsize, "%s", sym->name);
+ }
+ else {
+ printv(buf, bsize, "$%04X", w);
+ }
+}
+
+static void print_flag(const TilemDisasm* dasm, char** buf, int* bsize,
+ unsigned int bit, unsigned int offset,
+ unsigned int prefix)
+{
+ TilemDisasmSymbol* sym;
+ int i;
+
+ if (prefix == 0xfd) {
+ sym = find_symbol(&dasm->flags, 0x1000 + (offset << 4) + bit);
+ if (sym) {
+ for (i = 0; sym->name[i]; i++) {
+ printv(buf, bsize, "%c", sym->name[i]);
+ if (sym->name[i] == ',')
+ printv(buf, bsize, " (IY + ");
+ }
+ printv(buf, bsize, ")");
+ return;
+ }
+
+ sym = find_symbol(&dasm->flags, offset);
+ if (sym) {
+ printv(buf, bsize, "%d, (IY + %s)", bit, sym->name);
+ return;
+ }
+ }
+
+ printv(buf, bsize, "%d, (%s", bit, (prefix == 0xfd ? "IY" : "IX"));
+
+ if (offset & 0x80) {
+ printv(buf, bsize, " - $%02X", 0x100 - offset);
+ }
+ else if (offset) {
+ printv(buf, bsize, " + $%02X", offset);
+ }
+
+ printv(buf, bsize, ")");
+}
+
+static void disassemble_pattern(const TilemDisasm* dasm, const char* pattern,
+ const byte* ibuf, dword pc, int argbase,
+ char** buf, int* bsize)
+{
+ int argidx, offs;
+ char* p;
+ dword w;
+ TilemDisasmSymbol* sym;
+
+ argidx = argbase;
+
+ while (*bsize && *pattern) {
+ if (*pattern == '~')
+ printv(buf, bsize, "\t");
+ else if (*pattern == ',') {
+ printv(buf, bsize, ", ");
+ }
+ else if (*pattern != '%') {
+ printv(buf, bsize, "%c", *pattern);
+ }
+ else {
+ pattern++;
+ if (*pattern >= '0' && *pattern <= '9') {
+ offs = argbase + strtol(pattern, &p, 10);
+ pattern = p;
+ }
+ else {
+ offs = argidx;
+ }
+
+ switch (*pattern) {
+ case 0:
+ pattern--;
+ break;
+
+ case '%':
+ printv(buf, bsize, "%%");
+ break;
+
+ case 'a':
+ /* %a: word value, always an address */
+ w = ibuf[offs] | (ibuf[offs + 1] << 8);
+ print_word(dasm, buf, bsize, w, 0, 1);
+ offs += 2;
+ break;
+
+ case 'b':
+ /* %b: byte value */
+ print_byte(buf, bsize, ibuf[offs]);
+ offs++;
+ break;
+
+ case 'c':
+ /* %c: word value, always a ROM call number */
+ w = ibuf[offs] | (ibuf[offs + 1] << 8);
+ print_romcall(dasm, buf, bsize, w);
+ offs += 2;
+ break;
+
+ case 'C':
+ /* %C: byte value, always a ROM call number */
+ print_romcall(dasm, buf, bsize, ibuf[offs]);
+ offs++;
+ break;
+
+ case 'f':
+ /* %f: flag value */
+ print_flag(dasm, buf, bsize,
+ (ibuf[offs + 1] >> 3) & 7,
+ ibuf[offs], ibuf[0]);
+ offs += 2;
+ break;
+
+ case 'i':
+ /* %i: IX or IY by instruction prefix */
+ if (ibuf[0] == 0xdd)
+ printv(buf, bsize, "IX");
+ else
+ printv(buf, bsize, "IY");
+ break;
+
+ case 'j':
+ /* %j: word value, always a jump address */
+ w = ibuf[offs] | (ibuf[offs + 1] << 8);
+ print_word(dasm, buf, bsize, w, 0, 0);
+ offs += 2;
+ break;
+
+ case 'r':
+ /* %r: one-byte PC-relative value */
+ if (ibuf[offs] & 0x80)
+ w = pc + offs - 0xff + ibuf[offs];
+ else
+ w = pc + offs + 1 + ibuf[offs];
+ print_word(dasm, buf, bsize, w, 0, 0);
+ offs++;
+ break;
+
+ case 's':
+ /* %s: one-byte signed displacement */
+ if (ibuf[0] == 0xfd
+ && (sym = find_symbol(&dasm->flags,
+ ibuf[offs]))) {
+ printv(buf, bsize, " + %s", sym->name);
+ }
+ else if (ibuf[offs] & 0x80) {
+ printv(buf, bsize, " - ");
+ print_byte(buf, bsize,
+ 0x100 - ibuf[offs]);
+ }
+ else if (ibuf[offs]) {
+ printv(buf, bsize, " + ");
+ print_byte(buf, bsize, ibuf[offs]);
+ }
+ offs++;
+ break;
+
+ case 'w':
+ /* %w: word value */
+ w = ibuf[offs] | (ibuf[offs + 1] << 8);
+ print_word(dasm, buf, bsize, w, 1, 1);
+ offs += 2;
+ break;
+
+ case 'z':
+ /* %z: RST target address */
+ print_word(dasm, buf, bsize, ibuf[0] & 0x38,
+ 0, 0);
+ break;
+ }
+ if (offs > argidx)
+ argidx = offs;
+ }
+
+ pattern++;
+ }
+}
+
+void tilem_disasm_disassemble(const TilemDisasm* dasm, TilemCalc* calc,
+ int phys, dword addr, dword* nextaddr,
+ char* buffer, int bufsize)
+{
+ byte ibuf[64];
+ dword a, addr_l, max;
+ int length, argbase, i;
+ const char* pattern;
+
+ if (phys) {
+ max = calc->hw.romsize + calc->hw.ramsize;
+ for (i = 0; i < 4; i++) {
+ a = (addr + i) % max;
+ ibuf[i] = calc->mem[a];
+ }
+
+ addr_l = (*calc->hw.mem_ptol)(calc, addr);
+ if (addr_l == 0xffffffff)
+ addr_l = (addr & 0x3fff) | 0x4000;
+ }
+ else {
+ max = 0x10000;
+ for (i = 0; i < 4; i++) {
+ a = (addr + i) & 0xffff;
+ ibuf[i] = calc->mem[(*calc->hw.mem_ltop)(calc, a)];
+ }
+
+ addr_l = addr;
+ }
+
+ get_instruction_info(dasm, ibuf, &length, &argbase, &pattern);
+
+ if (phys) {
+ for (i = 0; i < length; i++) {
+ ibuf[i] = calc->mem[addr];
+ addr = (addr + 1) % max;
+ }
+ }
+ else {
+ for (i = 0; i < length; i++) {
+ ibuf[i] = calc->mem[(*calc->hw.mem_ltop)(calc, addr)];
+ addr = (addr + 1) & 0xffff;
+ }
+ }
+
+ if (nextaddr)
+ *nextaddr = addr;
+
+ if (buffer) {
+ disassemble_pattern(dasm, pattern, ibuf, addr_l, argbase,
+ &buffer, &bufsize);
+ }
+}
diff --git a/tool/tilem-src/db/listing.c b/tool/tilem-src/db/listing.c
new file mode 100644
index 0000000..3936d6c
--- /dev/null
+++ b/tool/tilem-src/db/listing.c
@@ -0,0 +1,379 @@
+/*
+ * libtilemdb - Utilities for debugging Z80 assembly programs
+ *
+ * Copyright (C) 2010 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+#include
+#include "tilemdb.h"
+
+struct _TilemListingLineCache {
+ dword minaddr;
+ dword maxaddr;
+ int* order;
+};
+
+static void sort_lines(TilemListing* lst,
+ int start, int end)
+{
+ int pivot, ncstart, ncend, n;
+ dword addr, pivotaddr;
+ int* order = lst->linecache->order;
+
+ pivot = order[start];
+ pivotaddr = lst->lines[pivot].address;
+
+ ncstart = start + 1;
+ ncend = end;
+
+ while (ncstart < ncend) {
+ n = order[ncstart];
+ addr = lst->lines[n].address;
+ if (addr < pivotaddr) {
+ ncstart++;
+ }
+ else {
+ order[ncstart] = order[ncend - 1];
+ order[ncend - 1] = n;
+ ncend--;
+ }
+ }
+
+ ncstart--;
+ order[start] = order[ncstart];
+ order[ncstart] = pivot;
+
+ if (ncstart > start + 1)
+ sort_lines(lst, start, ncstart);
+ if (end > ncend + 1)
+ sort_lines(lst, ncend, end);
+}
+
+static void ensure_order(TilemListing* lst)
+{
+ int i;
+
+ if (lst->nlines == 0) {
+ lst->linecache->minaddr = 0xffff;
+ lst->linecache->maxaddr = 0;
+ }
+ else if (!lst->linecache->order) {
+ lst->linecache->order = tilem_new_atomic(int, lst->nlines);
+ for (i = 0; i < lst->nlines; i++)
+ lst->linecache->order[i] = i;
+ sort_lines(lst, 0, lst->nlines);
+
+ i = lst->linecache->order[0];
+ lst->linecache->minaddr = lst->lines[i].address;
+ i = lst->linecache->order[lst->nlines - 1];
+ lst->linecache->maxaddr = lst->lines[i].address;
+ }
+}
+
+static void order_destroyed(TilemListing* lst)
+{
+ tilem_free(lst->linecache->order);
+ lst->linecache->order = NULL;
+}
+
+static int first_at_addr(TilemListing* lst, dword addr)
+{
+ int start, end, i;
+
+ start = 0;
+ end = lst->nlines;
+ while (start < end) {
+ i = (start + end) / 2;
+ if (lst->lines[lst->linecache->order[i]].address < addr)
+ start = i + 1;
+ else
+ end = i;
+ }
+ return start;
+}
+
+TilemListing* tilem_listing_new()
+{
+ TilemListing* lst = tilem_new0(TilemListing, 1);
+ lst->lines = NULL;
+ lst->linecache = tilem_new0(TilemListingLineCache, 1);
+ lst->linecache->order = NULL;
+ return lst;
+}
+
+void tilem_listing_free(TilemListing* lst)
+{
+ int i;
+
+ if (!lst)
+ return;
+
+ for (i = 0; i < lst->nlines; i++)
+ tilem_free(lst->lines[i].text);
+ tilem_free(lst->lines);
+ tilem_free(lst->linecache->order);
+ tilem_free(lst->linecache);
+ tilem_free(lst);
+}
+
+void tilem_listing_file_clear(TilemListing* lst)
+{
+ order_destroyed(lst);
+ lst->nlines = 0;
+ lst->nlines_a = 0;
+ tilem_free(lst->lines);
+ lst->lines = NULL;
+}
+
+void tilem_listing_append_line(TilemListing* lst, int srclinenum, dword address,
+ int depth, int datasize, const byte* data,
+ const char* text, int is_expansion)
+{
+ TilemListingLine* line;
+ int i;
+
+ order_destroyed(lst);
+ lst->nlines++;
+ if (lst->nlines >= lst->nlines_a) {
+ lst->nlines_a = lst->nlines * 2;
+ lst->lines = tilem_renew(TilemListingLine,
+ lst->lines, lst->nlines_a);
+ }
+
+ line = &lst->lines[lst->nlines - 1];
+
+ line->listing = lst;
+ line->srclinenum = srclinenum;
+ line->address = address & 0xffff;
+ line->depth = depth;
+
+ if (datasize > TILEM_MAX_LINE_BYTES)
+ datasize = TILEM_MAX_LINE_BYTES;
+
+ line->datasize = datasize;
+ for (i = 0; i < datasize; i++)
+ line->data[i] = data[i];
+
+ if (text) {
+ line->text = tilem_new_atomic(char, strlen(text) + 1);
+ strcpy(line->text, text);
+
+ if ((text[0] >= 'A' && text[0] <= 'Z')
+ || (text[0] >= 'a' && text[0] <= 'z')
+ || (text[0] & 0x80))
+ line->is_label = 1;
+ else
+ line->is_label = 0;
+ }
+ else {
+ line->text = NULL;
+ line->is_label = 0;
+ }
+
+ line->is_expansion = is_expansion;
+}
+
+void tilem_listing_get_address_range(TilemListing* lst, dword* min, dword* max)
+{
+ ensure_order(lst);
+ if (min)
+ *min = lst->linecache->minaddr;
+ if (max)
+ *max = lst->linecache->maxaddr;
+}
+
+TilemListingLine* tilem_listing_line_get_next(TilemListingLine* line)
+{
+ if (!line)
+ return NULL;
+
+ if (line != line->listing->lines + line->listing->nlines)
+ return line + 1;
+ else
+ return NULL;
+}
+
+TilemListingLine* tilem_listing_line_get_prev(TilemListingLine* line)
+{
+ if (!line)
+ return NULL;
+
+ if (line != line->listing->lines)
+ return line - 1;
+ else
+ return NULL;
+
+}
+
+TilemListingLine* tilem_listing_get_loaded_line_at_addr(TilemListing* lst,
+ dword address,
+ TilemCalc* calc,
+ int match_internal)
+{
+ int i;
+ TilemListingLine *line;
+
+ ensure_order(lst);
+ i = first_at_addr(lst, address + 1);
+
+ while (--i >= 0) {
+ line = &lst->lines[lst->linecache->order[i]];
+
+ if (match_internal) {
+ if (line->address + TILEM_MAX_LINE_BYTES <= address)
+ return NULL;
+ else if (line->address + line->datasize <= address)
+ continue;
+ }
+ else {
+ if (line->address != address)
+ return NULL;
+ }
+
+ if (tilem_listing_line_is_loaded(line, calc))
+ return line;
+ }
+ return NULL;
+}
+
+static inline unsigned int getbyte(TilemCalc* calc, dword addr)
+{
+ dword pa = (*calc->hw.mem_ltop)(calc, addr & 0xffff);
+ return calc->mem[pa];
+}
+
+static inline int line_load_count(const TilemListingLine* line, TilemCalc* calc)
+{
+ int i, n;
+
+ for (i = n = 0; i < line->datasize; i++)
+ if (getbyte(calc, line->address + i) == line->data[i])
+ n++;
+ return n;
+}
+
+static inline TilemListingLine* get_next_local(TilemListingLine* line)
+{
+ TilemListingLine* nline = tilem_listing_line_get_next(line);
+
+ if (nline && nline->address != line->address + line->datasize)
+ return NULL;
+ else
+ return nline;
+}
+
+static inline TilemListingLine* get_prev_local(TilemListingLine* line)
+{
+ TilemListingLine* nline = tilem_listing_line_get_prev(line);
+
+ if (nline && nline->address != line->address + line->datasize)
+ return NULL;
+ else
+ return nline;
+}
+
+int tilem_listing_line_is_loaded(TilemListingLine* line, TilemCalc* calc)
+{
+ int nbytes, ngood;
+ TilemListingLine *nline;
+
+ while (line->datasize == 0 && (nline = get_next_local(line)))
+ line = nline;
+
+ if (line_load_count(line, calc) != line->datasize)
+ return 0;
+ else {
+ nbytes = ngood = line->datasize;
+
+ nline = line;
+ while ((nline = get_next_local(nline))
+ && nline->address < line->address + 32) {
+ nbytes += nline->datasize;
+ ngood += line_load_count(nline, calc);
+ }
+
+ nline = line;
+ while ((nline = get_prev_local(nline))
+ && line->address < nline->address + 32) {
+ nbytes += nline->datasize;
+ ngood += line_load_count(nline, calc);
+ }
+
+ return (ngood > nbytes / 2);
+ }
+}
+
+static int bptest_listing_line(TilemCalc* calc, dword addr TILEM_ATTR_UNUSED,
+ void* data)
+{
+ return tilem_listing_line_is_loaded(data, calc);
+}
+
+int tilem_listing_line_add_breakpoint(TilemListingLine* line,
+ TilemCalc* calc, int bptype,
+ int match_internal)
+{
+ dword max;
+
+ if (match_internal && line->datasize > 0)
+ max = line->address + line->datasize - 1;
+ else
+ max = line->address;
+
+ return tilem_z80_add_breakpoint(calc, bptype, line->address, max,
+ 0xffff, &bptest_listing_line,
+ (void*) line);
+}
+
+static int bptest_listing_int(TilemCalc* calc, dword addr, void* data)
+{
+ TilemListing* lst = data;
+
+ if (tilem_listing_get_loaded_line_at_addr(lst, addr, calc, 1))
+ return 1;
+ else
+ return 0;
+}
+
+static int bptest_listing_top(TilemCalc* calc, dword addr, void* data)
+{
+ TilemListing* lst = data;
+
+ if (tilem_listing_get_loaded_line_at_addr(lst, addr, calc, 0))
+ return 1;
+ else
+ return 0;
+}
+
+int tilem_listing_add_breakpoint(TilemListing* lst, TilemCalc* calc,
+ int bptype, int match_internal)
+{
+ dword min, max;
+
+ tilem_listing_get_address_range(lst, &min, &max);
+ return tilem_z80_add_breakpoint(calc, bptype, min, max, 0xffff,
+ (match_internal
+ ? &bptest_listing_int
+ : &bptest_listing_top), lst);
+}
+
diff --git a/tool/tilem-src/db/lstfile.c b/tool/tilem-src/db/lstfile.c
new file mode 100644
index 0000000..938ce1c
--- /dev/null
+++ b/tool/tilem-src/db/lstfile.c
@@ -0,0 +1,384 @@
+/*
+ * libtilemdb - Utilities for debugging Z80 assembly programs
+ *
+ * Copyright (C) 2010 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+#include
+#include
+#include "tilemdb.h"
+
+/* Test if TEXT contains a correctly-formatted number WIDTH characters
+ wide. If PAD = 0, number is padded on left with zeroes; if PAD =
+ 1, number is padded on left with spaces; if PAD = -1, number is
+ padded on right with spaces. */
+static int match_num(const char* text, int width, int pad, int base,
+ int* value)
+{
+ int start, end;
+ char* p;
+
+ if ((int) strlen(text) < width)
+ return 0;
+
+ start = 0;
+ while (start < width && text[start] == ' ')
+ start++;
+
+ end = width;
+ while (end > start && text[end - 1] == ' ')
+ end--;
+
+ if (start == end)
+ return 0;
+
+ if (pad != 1 && start != 0)
+ return 0;
+
+ if (pad != -1 && end != width)
+ return 0;
+
+ if (pad != 0 && text[start] == '0' && start != end - 1)
+ return 0;
+
+ *value = strtol(text + start, &p, base);
+
+ return (p == text + end);
+}
+
+/* Test if string exactly matches a printf-like format string.
+ %d, %x match decimal and hex integers;
+ %s matches any string of exactly that width. */
+static int match_pattern(const char* text, const char* pattern, int* datasize,
+ byte* data, ...)
+{
+ int width, pad, value, *ip;
+ char **sp;
+ char *end;
+ va_list ap;
+ int failed = 0, lastdb = 0;
+
+ va_start(ap, data);
+
+ *datasize = 0;
+
+ while (!failed && *pattern) {
+ if (*pattern != '%') {
+ if (*text == *pattern)
+ text++;
+ else
+ failed = 1;
+ pattern++;
+ }
+ else {
+ pattern++;
+ if (*pattern == '0') {
+ pad = 0;
+ pattern++;
+ }
+ else if (*pattern == '-') {
+ pad = -1;
+ pattern++;
+ }
+ else
+ pad = 1;
+
+ width = strtol(pattern, &end, 10);
+ pattern = end;
+ if (!width)
+ width = strlen(text);
+ else if (width > (int) strlen(text)) {
+ failed = 1;
+ break;
+ }
+
+ switch (*pattern) {
+ case '%':
+ if (*text == '%')
+ text++;
+ else
+ failed = 1;
+ break;
+
+ case 'B':
+ if (text[0] == ' ' && text[1] == ' ') {
+ lastdb = 1;
+ text += 2;
+ break;
+ }
+ case 'b':
+ if (match_num(text, width, pad, 16, &value)
+ && !lastdb) {
+ data[*datasize] = value;
+ (*datasize)++;
+ text += width;
+ }
+ else {
+ failed = 1;
+ }
+ break;
+
+ case 'd':
+ ip = va_arg(ap, int *);
+ if (match_num(text, width, pad, 10, ip)) {
+ text += width;
+ }
+ else {
+ failed = 1;
+ }
+ break;
+
+ case 'x':
+ ip = va_arg(ap, int *);
+ if (match_num(text, width, pad, 16, ip)) {
+ text += width;
+ }
+ else {
+ failed = 1;
+ }
+ break;
+
+ case 's':
+ sp = va_arg(ap, char **);
+ *sp = (char*) text;
+ text += width;
+ break;
+ }
+ pattern++;
+ }
+ }
+
+ va_end(ap);
+
+ return (!failed && *text == 0);
+}
+
+static int get_tasm_depth(const char* s)
+{
+ if (!strncmp(s, "+++", 3))
+ return 4;
+ else if (!strncmp(s, "++ ", 3))
+ return 3;
+ else if (!strncmp(s, "+ ", 3))
+ return 2;
+ else if (!strncmp(s, " ", 3))
+ return 1;
+ else
+ return 0;
+}
+
+static int parse_listing(const char* line, int* linenum, int* addr, int* depth,
+ int* datasize, byte* data, char** text, int* isexp,
+ const TilemListingLine* prevline)
+{
+ int dummy;
+ char *p, *q;
+
+ /* tasm */
+
+ if (match_pattern(line, "%04d%3s%04x%1s%02B %02B %02B %02B %s",
+ datasize, data, linenum, &p, addr, &q, text)) {
+ *depth = get_tasm_depth(p);
+ *isexp = 0;
+ return 1;
+ }
+ if (match_pattern(line, "%04d%3s%04x%1s%02b %02b %02b ",
+ datasize, data, linenum, &p, addr, &q)
+ || match_pattern(line, "%04d%3s%04x%1s%02b %02b ",
+ datasize, data, linenum, &p, addr, &q)
+ || match_pattern(line, "%04d%3s%04x%1s%02b ",
+ datasize, data, linenum, &p, addr, &q)) {
+ *depth = get_tasm_depth(p);
+ *text = NULL;
+ *isexp = 0;
+ return 1;
+ }
+
+ /* zmasm */
+
+ if (match_pattern(line, "%08x %02B %02B %02B %02B %02B %02B %4s %5d %s",
+ datasize, data, addr, &p, linenum, text)
+ && p[0] >= 'A' && p[0] <= 'Z') {
+ *depth = p[0] - 'A' + 1;
+ *isexp = (p[1] == '+');
+ return 1;
+ }
+ if (match_pattern(line, "%08x %02B %02B %02B %02B %02B %02B %4s %5d",
+ datasize, data, addr, &p, linenum)
+ && p[0] >= 'A' && p[0] <= 'Z') {
+ *text = NULL;
+ *depth = p[0] - 'A' + 1;
+ *isexp = (p[1] == '+');
+ return 1;
+ }
+ if (match_pattern(line, " %4s %5d %s",
+ datasize, data, &p, linenum, text)
+ && p[0] >= 'A' && p[0] <= 'Z') {
+ *addr = prevline->address + prevline->datasize;
+ *depth = p[0] - 'A' + 1;
+ *isexp = (p[1] == '+');
+ return 1;
+ }
+ if (match_pattern(line, " %08x %4s %5d %s",
+ datasize, data, &dummy, &p, linenum, text)
+ && p[0] >= 'A' && p[0] <= 'Z') {
+ *addr = prevline->address + prevline->datasize;
+ *depth = p[0] - 'A' + 1;
+ *isexp = (p[1] == '+');
+ return 1;
+ }
+
+ /* spasm - old and new versions */
+
+ if (match_pattern(line, "%5d %04x: %02b %02b %02b %02b %s",
+ datasize, data, linenum, addr, text)
+ || match_pattern(line, "%5d %04x: %02b %02b %02b - %s",
+ datasize, data, linenum, addr, text)
+ || match_pattern(line, "%5d %04x: %02b %02b - - %s",
+ datasize, data, linenum, addr, text)
+ || match_pattern(line, "%5d %04x: %02b - - - %s",
+ datasize, data, linenum, addr, text)
+ || match_pattern(line, "%5d %04x: - - - - %s",
+ datasize, data, linenum, addr, text)
+
+ || match_pattern(line, "%5d %02x:%04x %02b %02b %02b %02b %s",
+ datasize, data, linenum, &dummy, addr, text)
+ || match_pattern(line, "%5d %02x:%04x %02b %02b %02b - %s",
+ datasize, data, linenum, &dummy, addr, text)
+ || match_pattern(line, "%5d %02x:%04x %02b %02b - - %s",
+ datasize, data, linenum, &dummy, addr, text)
+ || match_pattern(line, "%5d %02x:%04x %02b - - - %s",
+ datasize, data, linenum, &dummy, addr, text)
+ || match_pattern(line, "%5d %02x:%04x - - - - %s",
+ datasize, data, linenum, &dummy, addr, text)) {
+ *depth = *isexp = 0;
+ return 1;
+ }
+ if (match_pattern(line, " %02b %02b %02b %02b %s",
+ datasize, data, text)
+ || match_pattern(line, " %02b %02b %02b - %s",
+ datasize, data, text)
+ || match_pattern(line, " %02b %02b - - %s",
+ datasize, data, text)
+ || match_pattern(line, " %02b - - - %s",
+ datasize, data, text)
+
+ || match_pattern(line, " %02b %02b %02b %02b %s",
+ datasize, data, text)
+ || match_pattern(line, " %02b %02b %02b - %s",
+ datasize, data, text)
+ || match_pattern(line, " %02b %02b - - %s",
+ datasize, data, text)
+ || match_pattern(line, " %02b - - - %s",
+ datasize, data, text)) {
+ *linenum = prevline->srclinenum;
+ *addr = prevline->address + prevline->datasize;
+ *depth = *isexp = 0;
+ return 1;
+ }
+
+ /* tpasm or miniasm */
+
+ if (match_pattern(line, "%-5d %08x %02B %02B %02B %02B %02B %2s%s",
+ datasize, data, linenum, addr, &p, text)
+ || match_pattern(line, "%5d %08x %02B %02B %02B %02B %02B %2s%s",
+ datasize, data, linenum, addr, &p, text)) {
+ *depth = 0;
+ *isexp = (*p == 'm' || *p == 'a');
+ return 1;
+ }
+ if (match_pattern(line, "%-5d %08x (%08x) %2s%s",
+ datasize, data, linenum, addr, &dummy, &p, text)
+ || match_pattern(line, "%5d %08x (%08x) %2s%s",
+ datasize, data, linenum, addr, &dummy, &p, text)) {
+ *depth = 0;
+ *isexp = (*p == 'm' || *p == 'a');
+ return 1;
+ }
+ if (match_pattern(line, " %02B %02B %02B %02B %02B %1s",
+ datasize, data, &p)) {
+ *text = NULL;
+ *linenum = prevline->srclinenum;
+ *addr = prevline->address + prevline->datasize;
+ *depth = 0;
+ *isexp = (*p == 'm' || *p == 'a');
+ return 1;
+ }
+ if (match_pattern(line, " %02b %02b %02b %02b %02b",
+ datasize, data)
+ || match_pattern(line, " %02b %02b %02b %02b",
+ datasize, data)
+ || match_pattern(line, " %02b %02b %02b",
+ datasize, data)
+ || match_pattern(line, " %02b %02b",
+ datasize, data)
+ || match_pattern(line, " %02b",
+ datasize, data)) {
+ *text = NULL;
+ *linenum = prevline->srclinenum;
+ *addr = prevline->address + prevline->datasize;
+ *depth = *isexp = 0;
+ return 1;
+ }
+
+ printf("***\t%s\n", line);
+
+ return 0;
+}
+
+int tilem_listing_read_file(TilemListing* lst, FILE* lstfile)
+{
+ char buf[1024];
+ int linenum, addr, depth, isexp, datasize;
+ byte data[TILEM_MAX_LINE_BYTES];
+ char *text;
+ int i, status = 1;
+ TilemListingLine prevline;
+
+ prevline.text = NULL;
+ prevline.srclinenum = 0;
+ prevline.address = 0xffffffff;
+ prevline.depth = 0;
+ prevline.datasize = 0;
+
+ while (fgets(buf, sizeof(buf), lstfile)) {
+ i = strlen(buf);
+ while (i > 0 && (buf[i - 1] == '\r' || buf[i - 1] == '\n'))
+ i--;
+ buf[i] = 0;
+
+ if (parse_listing(buf, &linenum, &addr, &depth, &datasize,
+ data, &text, &isexp, &prevline)) {
+
+ if (linenum)
+ status = 0;
+
+ tilem_listing_append_line(lst, linenum, addr, depth,
+ datasize, data, text, isexp);
+ prevline = lst->lines[lst->nlines - 1];
+ }
+ }
+
+ return status;
+}
+
diff --git a/tool/tilem-src/db/tilemdb.h b/tool/tilem-src/db/tilemdb.h
new file mode 100644
index 0000000..daef3dc
--- /dev/null
+++ b/tool/tilem-src/db/tilemdb.h
@@ -0,0 +1,149 @@
+/*
+ * libtilemdb - Utilities for debugging Z80 assembly programs
+ *
+ * Copyright (C) 2010 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifndef _TILEMDB_H
+#define _TILEMDB_H
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Disassembler */
+
+typedef struct _TilemDisasm TilemDisasm;
+
+/* Create a new disassembly context. */
+TilemDisasm* tilem_disasm_new(void);
+
+/* Free a disassembly context. */
+void tilem_disasm_free(TilemDisasm* dasm);
+
+/* Read symbols from SYMFILE. */
+int tilem_disasm_read_symbol_file(TilemDisasm* dasm, FILE* symfile);
+
+/* Set symbol NAME to value VALUE. */
+void tilem_disasm_set_label(TilemDisasm* dasm, const char* name,
+ dword value);
+
+/* Check if symbol NAME is defined. If symbol is defined and VALUE is
+ non-null, set *VALUE to symbol's value. */
+int tilem_disasm_get_label(const TilemDisasm* dasm, const char* name,
+ dword* value);
+
+/* Check if a label is defined at the given address. */
+const char* tilem_disasm_get_label_at_address(const TilemDisasm* dasm,
+ dword addr);
+
+/* Disassemble a line starting at address ADDR. Store text (up to
+ BUFSIZE characters) in BUFFER, and set *NEXTADDR to the address of
+ the following line. If PHYS is 0, use logical addresses; otherwise
+ use physical addresses. */
+void tilem_disasm_disassemble(const TilemDisasm* dasm, TilemCalc* calc,
+ int phys, dword addr, dword* nextaddr,
+ char* buffer, int bufsize);
+
+
+/* Assembly listing files */
+
+typedef struct _TilemListing TilemListing;
+typedef struct _TilemListingLine TilemListingLine;
+typedef struct _TilemListingLineCache TilemListingLineCache;
+
+#define TILEM_MAX_LINE_BYTES 6
+
+struct _TilemListingLine {
+ TilemListing* listing; /* Listing to which this line
+ belongs */
+ char* text; /* Text of source line */
+ int srclinenum; /* Line number in original
+ source file */
+ dword address; /* Address */
+ int depth; /* Source file inclusion
+ depth */
+ byte datasize; /* Number of data bytes */
+ unsigned is_label : 1; /* = 1 if line appears to
+ contain a label */
+ unsigned is_expansion : 1; /* = 1 if line is part of a
+ macro expansion */
+ byte data[TILEM_MAX_LINE_BYTES]; /* Data bytes on this line */
+};
+
+struct _TilemListing {
+ int nlines;
+ int nlines_a;
+ TilemListingLine* lines;
+ TilemListingLineCache* linecache;
+};
+
+/* Create new assembly listing. */
+TilemListing* tilem_listing_new(void);
+
+/* Free listing data. */
+void tilem_listing_free(TilemListing* lst);
+
+/* Clear listing file contents. */
+void tilem_listing_clear(TilemListing* lst);
+
+/* Add a line to the end of the listing file. */
+void tilem_listing_append_line(TilemListing* lst, int srclinenum, dword address,
+ int depth, int datasize, const byte* data,
+ const char* text, int is_expansion);
+
+/* Calculate minimum and maximum address used by a listing file. */
+void tilem_listing_get_address_range(TilemListing* lst, dword* min, dword* max);
+
+/* Get next line, if any. */
+TilemListingLine* tilem_listing_line_get_next(TilemListingLine* line);
+
+/* Get previous line, if any. */
+TilemListingLine* tilem_listing_line_get_prev(TilemListingLine* line);
+
+/* Find the line (if any) currently loaded at the given address. If
+ MATCH_INTERNAL = 0, find only lines that begin at that address. */
+TilemListingLine* tilem_listing_get_loaded_line_at_addr(TilemListing* lst,
+ dword address,
+ TilemCalc* calc,
+ int match_internal);
+
+/* Check if given line is currently loaded (and mapped into Z80 memory
+ space.) */
+int tilem_listing_line_is_loaded(TilemListingLine* line, TilemCalc* calc);
+
+/* Set a breakpoint to be triggered on the given line. */
+int tilem_listing_line_add_breakpoint(TilemListingLine* line,
+ TilemCalc* calc, int bptype,
+ int match_internal);
+
+/* Set a breakpoint to be triggered on any line in the listing. */
+int tilem_listing_add_breakpoint(TilemListing* lst, TilemCalc* calc,
+ int bptype, int match_internal);
+
+/* Read assembly listing from LSTFILE. */
+int tilem_listing_read_file(TilemListing* lst, FILE* lstfile);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tool/tilem-src/emu/Makefile.in b/tool/tilem-src/emu/Makefile.in
new file mode 100644
index 0000000..915d6d8
--- /dev/null
+++ b/tool/tilem-src/emu/Makefile.in
@@ -0,0 +1,218 @@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datarootdir = @datarootdir@
+bindir = @bindir@
+datadir = @datadir@
+pkgdatadir = @datadir@/tilem2
+mandir = @mandir@
+
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+@SET_MAKE@
+
+AR = @AR@
+CC = @CC@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+DEFS = @DEFS@
+OPT_CFLAGS = @OPT_CFLAGS@
+RANLIB = @RANLIB@
+SHELL = @SHELL@
+
+core_objects = calcs.o z80.o state.o rom.o flash.o link.o keypad.o lcd.o \
+ cert.o md5.o timers.o monolcd.o graylcd.o grayimage.o graycolor.o
+
+x7_objects = x7_init.o x7_io.o x7_memory.o x7_subcore.o
+x1_objects = x1_init.o x1_io.o x1_memory.o x1_subcore.o
+x2_objects = x2_init.o x2_io.o x2_memory.o x2_subcore.o
+x3_objects = x3_init.o x3_io.o x3_memory.o x3_subcore.o
+xp_objects = xp_init.o xp_io.o xp_memory.o xp_subcore.o
+xs_objects = xs_init.o xs_io.o xs_memory.o xs_subcore.o
+x4_objects = x4_init.o x4_io.o x4_memory.o x4_subcore.o
+xz_objects = xz_init.o xz_io.o xz_memory.o xz_subcore.o
+xn_objects = xn_init.o xn_io.o xn_memory.o xn_subcore.o
+x5_objects = x5_init.o x5_io.o x5_memory.o x5_subcore.o
+x6_objects = x6_init.o x6_io.o x6_memory.o x6_subcore.o
+
+objects = $(core_objects) $(x7_objects) $(x1_objects) $(x2_objects) \
+ $(x3_objects) $(xp_objects) $(xs_objects) $(x4_objects) $(xz_objects) \
+ $(xn_objects) $(x5_objects) $(x6_objects)
+
+compile = $(CC) -I$(top_builddir) -I$(srcdir) $(CFLAGS) $(CPPFLAGS) $(DEFS) $(OPT_CFLAGS)
+
+all: libtilemcore.a
+
+libtilemcore.a: $(objects)
+ $(AR) cru libtilemcore.a $(objects)
+ $(RANLIB) libtilemcore.a
+
+# Main emulator core
+
+calcs.o: calcs.c tilem.h z80.h ../config.h
+ $(compile) -c $(srcdir)/calcs.c
+z80.o: z80.c z80.h z80cmds.h z80main.h z80cb.h z80ddfd.h z80ed.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/z80.c
+state.o: state.c tilem.h z80.h ../config.h
+ $(compile) -c $(srcdir)/state.c
+rom.o: rom.c tilem.h ../config.h
+ $(compile) -c $(srcdir)/rom.c
+flash.o: flash.c tilem.h ../config.h
+ $(compile) -c $(srcdir)/flash.c
+link.o: link.c tilem.h ../config.h
+ $(compile) -c $(srcdir)/link.c
+keypad.o: keypad.c tilem.h scancodes.h ../config.h
+ $(compile) -c $(srcdir)/keypad.c
+lcd.o: lcd.c tilem.h ../config.h
+ $(compile) -c $(srcdir)/lcd.c
+cert.o: cert.c tilem.h ../config.h
+ $(compile) -c $(srcdir)/cert.c
+md5.o: md5.c tilem.h ../config.h
+ $(compile) -c $(srcdir)/md5.c
+timers.o: timers.c tilem.h ../config.h
+ $(compile) -c $(srcdir)/timers.c
+monolcd.o: monolcd.c tilem.h ../config.h
+ $(compile) -c $(srcdir)/monolcd.c
+graylcd.o: graylcd.c tilem.h graylcd.h ../config.h
+ $(compile) -c $(srcdir)/graylcd.c
+grayimage.o: grayimage.c tilem.h graylcd.h ../config.h
+ $(compile) -c $(srcdir)/grayimage.c
+graycolor.o: graycolor.c tilem.h ../config.h
+ $(compile) -c $(srcdir)/graycolor.c
+
+# TI-73
+
+x7_init.o: x7/x7_init.c x7/x7.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x7/x7_init.c
+x7_io.o: x7/x7_io.c x7/x7.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x7/x7_io.c
+x7_memory.o: x7/x7_memory.c x7/x7.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x7/x7_memory.c
+x7_subcore.o: x7/x7_subcore.c x7/x7.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x7/x7_subcore.c
+
+# TI-81
+
+x1_init.o: x1/x1_init.c x1/x1.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x1/x1_init.c
+x1_io.o: x1/x1_io.c x1/x1.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x1/x1_io.c
+x1_memory.o: x1/x1_memory.c x1/x1.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x1/x1_memory.c
+x1_subcore.o: x1/x1_subcore.c x1/x1.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x1/x1_subcore.c
+
+# TI-82
+
+x2_init.o: x2/x2_init.c x2/x2.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x2/x2_init.c
+x2_io.o: x2/x2_io.c x2/x2.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x2/x2_io.c
+x2_memory.o: x2/x2_memory.c x2/x2.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x2/x2_memory.c
+x2_subcore.o: x2/x2_subcore.c x2/x2.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x2/x2_subcore.c
+
+# TI-83
+
+x3_init.o: x3/x3_init.c x3/x3.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x3/x3_init.c
+x3_io.o: x3/x3_io.c x3/x3.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x3/x3_io.c
+x3_memory.o: x3/x3_memory.c x3/x3.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x3/x3_memory.c
+x3_subcore.o: x3/x3_subcore.c x3/x3.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x3/x3_subcore.c
+
+# TI-83 Plus
+
+xp_init.o: xp/xp_init.c xp/xp.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/xp/xp_init.c
+xp_io.o: xp/xp_io.c xp/xp.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/xp/xp_io.c
+xp_memory.o: xp/xp_memory.c xp/xp.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/xp/xp_memory.c
+xp_subcore.o: xp/xp_subcore.c xp/xp.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/xp/xp_subcore.c
+
+# TI-83 Plus SE
+
+xs_init.o: xs/xs_init.c xs/xs.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/xs/xs_init.c
+xs_io.o: xs/xs_io.c xs/xs.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/xs/xs_io.c
+xs_memory.o: xs/xs_memory.c xs/xs.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/xs/xs_memory.c
+xs_subcore.o: xs/xs_subcore.c xs/xs.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/xs/xs_subcore.c
+
+# TI-84 Plus
+
+x4_init.o: x4/x4_init.c x4/x4.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x4/x4_init.c
+x4_io.o: x4/x4_io.c x4/x4.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x4/x4_io.c
+x4_memory.o: x4/x4_memory.c x4/x4.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x4/x4_memory.c
+x4_subcore.o: x4/x4_subcore.c x4/x4.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x4/x4_subcore.c
+
+# TI-84 Plus SE
+
+xz_init.o: xz/xz_init.c xz/xz.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/xz/xz_init.c
+xz_io.o: xz/xz_io.c xz/xz.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/xz/xz_io.c
+xz_memory.o: xz/xz_memory.c xz/xz.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/xz/xz_memory.c
+xz_subcore.o: xz/xz_subcore.c xz/xz.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/xz/xz_subcore.c
+
+# TI-Nspire 84 Plus emulator
+
+xn_init.o: xn/xn_init.c xn/xn.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/xn/xn_init.c
+xn_io.o: xn/xn_io.c xn/xn.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/xn/xn_io.c
+xn_memory.o: xn/xn_memory.c xn/xn.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/xn/xn_memory.c
+xn_subcore.o: xn/xn_subcore.c xn/xn.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/xn/xn_subcore.c
+
+# TI-85
+
+x5_init.o: x5/x5_init.c x5/x5.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x5/x5_init.c
+x5_io.o: x5/x5_io.c x5/x5.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x5/x5_io.c
+x5_memory.o: x5/x5_memory.c x5/x5.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x5/x5_memory.c
+x5_subcore.o: x5/x5_subcore.c x5/x5.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x5/x5_subcore.c
+
+# TI-86
+
+x6_init.o: x6/x6_init.c x6/x6.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x6/x6_init.c
+x6_io.o: x6/x6_io.c x6/x6.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x6/x6_io.c
+x6_memory.o: x6/x6_memory.c x6/x6.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x6/x6_memory.c
+x6_subcore.o: x6/x6_subcore.c x6/x6.h tilem.h ../config.h
+ $(compile) -c $(srcdir)/x6/x6_subcore.c
+
+
+clean:
+ rm -f *.o
+ rm -f libtilemcore.a
+
+
+Makefile: Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status
+
+$(top_builddir)/config.status: $(top_srcdir)/configure
+ cd $(top_builddir) && $(SHELL) ./config.status --recheck
+
+.PRECIOUS: Makefile $(top_builddir)/config.status
+.PHONY: clean all
diff --git a/tool/tilem-src/emu/calcs.c b/tool/tilem-src/emu/calcs.c
new file mode 100644
index 0000000..b251f60
--- /dev/null
+++ b/tool/tilem-src/emu/calcs.c
@@ -0,0 +1,186 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+#include "tilem.h"
+#include "z80.h"
+
+extern const TilemHardware hardware_ti73, hardware_ti76,
+ hardware_ti81, hardware_ti82, hardware_ti83,
+ hardware_ti83p, hardware_ti83pse, hardware_ti84p,
+ hardware_ti84pse, hardware_ti84pns,
+ hardware_ti85, hardware_ti86;
+
+const TilemHardware* hwmodels[] = {
+ &hardware_ti73,
+ &hardware_ti76,
+ &hardware_ti81,
+ &hardware_ti82,
+ &hardware_ti83,
+ &hardware_ti83p,
+ &hardware_ti83pse,
+ &hardware_ti84p,
+ &hardware_ti84pse,
+ &hardware_ti84pns,
+ &hardware_ti85,
+ &hardware_ti86 };
+
+#define NUM_MODELS (sizeof(hwmodels) / sizeof(TilemHardware*))
+
+void tilem_get_supported_hardware(const TilemHardware*** models,
+ int* nmodels)
+{
+ *models = hwmodels;
+ *nmodels = NUM_MODELS;
+}
+
+void tilem_calc_reset(TilemCalc* calc)
+{
+ tilem_z80_reset(calc);
+ tilem_lcd_reset(calc);
+ tilem_linkport_reset(calc);
+ tilem_keypad_reset(calc);
+ tilem_flash_reset(calc);
+ tilem_md5_assist_reset(calc);
+ tilem_user_timers_reset(calc);
+ if (calc->hw.reset)
+ (*calc->hw.reset)(calc);
+}
+
+TilemCalc* tilem_calc_new(char id)
+{
+ int i;
+ TilemCalc* calc;
+ dword msize;
+
+ for (i = 0; i < (int) NUM_MODELS; i++) {
+ if (hwmodels[i]->model_id == id) {
+ calc = tilem_try_new0(TilemCalc, 1);
+ if (!calc) {
+ return NULL;
+ }
+
+ calc->hw = *hwmodels[i];
+
+ calc->poweronhalt = 1;
+ calc->battery = 60;
+ calc->hwregs = tilem_try_new_atomic(dword, calc->hw.nhwregs);
+ if (!calc->hwregs) {
+ tilem_free(calc);
+ return NULL;
+ }
+
+ memset(calc->hwregs, 0, calc->hw.nhwregs * sizeof(dword));
+
+ msize = (calc->hw.romsize + calc->hw.ramsize
+ + calc->hw.lcdmemsize);
+
+ calc->mem = tilem_try_new_atomic(byte, msize);
+ if (!calc->mem) {
+ tilem_free(calc->hwregs);
+ tilem_free(calc);
+ return NULL;
+ }
+
+ calc->ram = calc->mem + calc->hw.romsize;
+ calc->lcdmem = calc->ram + calc->hw.ramsize;
+
+ memset(calc->ram, 0, msize - calc->hw.romsize);
+
+ calc->lcd.emuflags = TILEM_LCD_REQUIRE_DELAY;
+ calc->flash.emuflags = TILEM_FLASH_REQUIRE_DELAY;
+
+ tilem_calc_reset(calc);
+ return calc;
+ }
+ }
+
+ fprintf(stderr, "INTERNAL ERROR: invalid model ID '%c'\n", id);
+ return NULL;
+}
+
+TilemCalc* tilem_calc_copy(TilemCalc* calc)
+{
+ TilemCalc* newcalc;
+ dword msize;
+
+ newcalc = tilem_try_new(TilemCalc, 1);
+ if (!newcalc)
+ return NULL;
+ memcpy(newcalc, calc, sizeof(TilemCalc));
+
+ newcalc->hwregs = tilem_try_new_atomic(dword, calc->hw.nhwregs);
+ if (!newcalc->hwregs) {
+ tilem_free(newcalc);
+ return NULL;
+ }
+ memcpy(newcalc->hwregs, calc->hwregs, calc->hw.nhwregs * sizeof(dword));
+
+ newcalc->z80.timers = tilem_try_new(TilemZ80Timer,
+ newcalc->z80.ntimers);
+ if (!newcalc->z80.timers) {
+ tilem_free(newcalc->hwregs);
+ tilem_free(newcalc);
+ return NULL;
+ }
+ memcpy(newcalc->z80.timers, calc->z80.timers,
+ newcalc->z80.ntimers * sizeof(TilemZ80Timer));
+
+ newcalc->z80.breakpoints = tilem_try_new(TilemZ80Breakpoint,
+ newcalc->z80.nbreakpoints);
+ if (!newcalc->z80.breakpoints) {
+ tilem_free(newcalc->z80.timers);
+ tilem_free(newcalc->hwregs);
+ tilem_free(newcalc);
+ return NULL;
+ }
+ memcpy(newcalc->z80.breakpoints, calc->z80.breakpoints,
+ newcalc->z80.nbreakpoints * sizeof(TilemZ80Breakpoint));
+
+ msize = (calc->hw.romsize + calc->hw.ramsize + calc->hw.lcdmemsize);
+ newcalc->mem = tilem_try_new_atomic(byte, msize);
+ if (!newcalc->mem) {
+ tilem_free(newcalc->z80.breakpoints);
+ tilem_free(newcalc->z80.timers);
+ tilem_free(newcalc->hwregs);
+ tilem_free(newcalc);
+ return NULL;
+ }
+ memcpy(newcalc->mem, calc->mem, msize * sizeof(byte));
+
+ newcalc->ram = newcalc->mem + calc->hw.romsize;
+ newcalc->lcdmem = newcalc->ram + calc->hw.ramsize;
+
+ return newcalc;
+}
+
+void tilem_calc_free(TilemCalc* calc)
+{
+ tilem_free(calc->mem);
+ tilem_free(calc->hwregs);
+ tilem_free(calc->z80.breakpoints);
+ tilem_free(calc->z80.timers);
+ tilem_free(calc);
+}
diff --git a/tool/tilem-src/emu/cert.c b/tool/tilem-src/emu/cert.c
new file mode 100644
index 0000000..5c2375c
--- /dev/null
+++ b/tool/tilem-src/emu/cert.c
@@ -0,0 +1,136 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2009-2011 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+#include "tilem.h"
+
+static int certificate_valid(byte* cert)
+{
+ int i, n;
+
+ if (cert[0] != 0)
+ return 0;
+
+ i = 1;
+
+ /* check that the actual certificate area consists of valid
+ certificate fields */
+ while (cert[i] <= 0x0F) {
+ switch (cert[i + 1] & 0x0F) {
+ case 0x0D:
+ n = cert[i + 2] + 3;
+ break;
+ case 0x0E:
+ n = (cert[i + 2] << 8) + cert[i + 3] + 4;
+ break;
+ case 0x0F:
+ n = 6;
+ break;
+ default:
+ n = (cert[i + 1] & 0xf) + 2;
+ }
+ i += n;
+ if (i >= 0x2000)
+ return 0;
+ }
+
+ /* check that the fields end with FF */
+ if (cert[i] != 0xFF)
+ return 0;
+
+ /* if there are fields present, assume the certificate is OK */
+ if (i > 1)
+ return 1;
+
+ /* no fields present -> this could be an incompletely-patched
+ certificate from an older version of TilEm; verify that the
+ next 4k bytes are truly empty */
+ while (i < 0x1000) {
+ if (cert[i] != 0xFF)
+ return 0;
+ i++;
+ }
+
+ return 1;
+}
+
+void tilem_calc_fix_certificate(TilemCalc* calc, byte* cert,
+ int app_start, int app_end,
+ unsigned exptab_offset)
+{
+ int i, base, max_apps, page;
+ unsigned insttab_offset = 0x1fe0;
+
+ /* If the ROM was dumped from an unpatched OS, the certificate
+ needs to be patched for some calculator functions to
+ work. */
+
+ /* First, check if the certificate is already valid */
+
+ if (cert[0x2000] == 0)
+ base = 0x2000;
+ else
+ base = 0;
+
+ if (certificate_valid(cert + base)) {
+ return;
+ }
+
+ tilem_message(calc, "Repairing certificate area...");
+
+ memset(cert, 0xff, 16384);
+
+ cert[0] = 0;
+
+ cert[insttab_offset] = 0xfe;
+
+ if (app_start < app_end)
+ max_apps = app_end - app_start + 1;
+ else
+ max_apps = app_start - app_end + 1;
+
+ for (i = 0; i < max_apps; i++) {
+ if (app_start < app_end)
+ page = app_start + i;
+ else
+ page = app_start - i;
+
+ /* Clear installed bit / set expiration count for
+ existing apps. (If this incorrectly detects pages
+ that aren't really apps, don't worry about it;
+ better to err on the side of caution.) */
+ if (calc->mem[page << 14] != 0x80
+ || calc->mem[(page << 14) + 1] != 0x0f)
+ continue;
+
+ tilem_message(calc, "Found application at page %02x (index %d)",
+ page, i);
+
+ cert[insttab_offset + ((i + 1) / 8)] &= ~(1 << ((i + 1) % 8));
+
+ cert[exptab_offset + 2 * i] = 0x80;
+ cert[exptab_offset + 2 * i + 1] = 0x00;
+ }
+}
diff --git a/tool/tilem-src/emu/flash.c b/tool/tilem-src/emu/flash.c
new file mode 100644
index 0000000..eefef6f
--- /dev/null
+++ b/tool/tilem-src/emu/flash.c
@@ -0,0 +1,326 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2001 Solignac Julien
+ * Copyright (C) 2004-2012 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include "tilem.h"
+
+#define FLASH_READ 0
+#define FLASH_AA 1
+#define FLASH_55 2
+#define FLASH_PROG 3
+#define FLASH_ERASE 4
+#define FLASH_ERAA 5
+#define FLASH_ER55 6
+#define FLASH_ERROR 7
+#define FLASH_FASTMODE 8
+#define FLASH_FASTPROG 9
+#define FLASH_FASTEXIT 10
+
+#define FLASH_BUSY_PROGRAM 1
+#define FLASH_BUSY_ERASE_WAIT 2
+#define FLASH_BUSY_ERASE 3
+
+/* Still to do:
+ - autoselect
+ - erase suspend
+ - fast program
+ - CFI
+ */
+
+#define WARN(xxx) \
+ tilem_warning(calc, "Flash error (" xxx ")")
+#define WARN2(xxx, yyy, zzz) \
+ tilem_warning(calc, "Flash error (" xxx ")", (yyy), (zzz))
+
+void tilem_flash_reset(TilemCalc* calc)
+{
+ calc->flash.unlock = 0;
+ calc->flash.state = FLASH_READ;
+ calc->flash.busy = 0;
+}
+
+void tilem_flash_delay_timer(TilemCalc* calc, void* data TILEM_ATTR_UNUSED)
+{
+ if (calc->flash.busy == FLASH_BUSY_ERASE_WAIT) {
+ calc->flash.busy = FLASH_BUSY_ERASE;
+ tilem_z80_set_timer(calc, TILEM_TIMER_FLASH_DELAY,
+ 200000, 0, 1);
+ }
+ else {
+ calc->flash.busy = 0;
+ }
+}
+
+#ifdef DISABLE_FLASH_DELAY
+# define set_busy(fl, bm, t)
+#else
+static inline void set_busy(TilemCalc* calc, int busymode, int time)
+{
+ if (!(calc->flash.emuflags & TILEM_FLASH_REQUIRE_DELAY))
+ return;
+
+ calc->flash.busy = busymode;
+ tilem_z80_set_timer(calc, TILEM_TIMER_FLASH_DELAY,
+ time, 0, 1);
+}
+#endif
+
+static inline void program_byte(TilemCalc* calc, dword a, byte v)
+{
+ calc->mem[a] &= v;
+ calc->flash.progaddr = a;
+ calc->flash.progbyte = v;
+
+ if (calc->mem[a] != v) {
+ WARN2("bad program %02x over %02x", v, calc->mem[a]);
+ calc->flash.state = FLASH_ERROR;
+ }
+ else {
+ calc->flash.state = FLASH_READ;
+ }
+
+ set_busy(calc, FLASH_BUSY_PROGRAM, 7);
+}
+
+static inline void erase_sector(TilemCalc* calc, dword a, dword l)
+{
+ dword i;
+
+ calc->flash.progaddr = a;
+ for (i = 0; i < l; i++)
+ calc->mem[a + i]=0xFF;
+ calc->flash.state = FLASH_READ;
+
+ set_busy(calc, FLASH_BUSY_ERASE_WAIT, 50);
+}
+
+static const TilemFlashSector* get_sector(TilemCalc* calc, dword pa)
+{
+ int i;
+ const TilemFlashSector* sec;
+
+ for (i = 0; i < calc->hw.nflashsectors; i++) {
+ sec = &calc->hw.flashsectors[i];
+ if (pa >= sec->start && pa < sec->start + sec->size)
+ return sec;
+ }
+
+ return NULL;
+}
+
+static int sector_writable(TilemCalc* calc, const TilemFlashSector* sec)
+{
+ return !(sec->protectgroup & ~calc->flash.overridegroup);
+}
+
+byte tilem_flash_read_byte(TilemCalc* calc, dword pa)
+{
+ byte value;
+
+ if (calc->flash.busy == FLASH_BUSY_PROGRAM) {
+ if (pa != calc->flash.progaddr)
+ WARN("reading from Flash while programming");
+ value = (~calc->flash.progbyte & 0x80);
+ value |= calc->flash.toggles;
+ calc->flash.toggles ^= 0x40;
+ return (value);
+ }
+ else if (calc->flash.busy == FLASH_BUSY_ERASE) {
+ if ((pa >> 16) != (calc->flash.progaddr >> 16))
+ WARN("reading from Flash while erasing");
+ value = calc->flash.toggles | 0x08;
+ calc->flash.toggles ^= 0x44;
+ return (value);
+ }
+ else if (calc->flash.busy == FLASH_BUSY_ERASE_WAIT) {
+ if ((pa >> 16) != (calc->flash.progaddr >> 16))
+ WARN("reading from Flash while erasing");
+ value = calc->flash.toggles;
+ calc->flash.toggles ^= 0x44;
+ return (value);
+ }
+
+ if (calc->flash.state == FLASH_ERROR) {
+ value = ((~calc->flash.progbyte & 0x80) | 0x20);
+ value |= calc->flash.toggles;
+ calc->flash.toggles ^= 0x40;
+ return (value);
+ }
+ else if (calc->flash.state == FLASH_FASTMODE) {
+ return (calc->mem[pa]);
+ }
+ else if (calc->flash.state == FLASH_READ) {
+ return (calc->mem[pa]);
+ }
+ else {
+ WARN("reading during program/erase sequence");
+ calc->flash.state = FLASH_READ;
+ return (calc->mem[pa]);
+ }
+}
+
+void tilem_flash_erase_address(TilemCalc* calc, dword pa)
+{
+ const TilemFlashSector* sec = get_sector(calc, pa);
+
+ if (sector_writable(calc, sec)) {
+ tilem_message(calc, "Erasing Flash sector at %06x", pa);
+ erase_sector(calc, sec->start, sec->size);
+ }
+ else {
+ WARN("erasing protected sector");
+ }
+}
+
+void tilem_flash_write_byte(TilemCalc* calc, dword pa, byte v)
+{
+ int oldstate;
+ int i;
+ const TilemFlashSector* sec;
+
+ if (!calc->flash.unlock)
+ return;
+
+#ifndef DISABLE_FLASH_DELAY
+ if (calc->flash.busy == FLASH_BUSY_PROGRAM
+ || calc->flash.busy == FLASH_BUSY_ERASE)
+ return;
+#endif
+
+ oldstate = calc->flash.state;
+ calc->flash.state = FLASH_READ;
+
+ switch (oldstate) {
+ case FLASH_READ:
+ if (((pa&0xFFF) == 0xAAA) && (v == 0xAA))
+ calc->flash.state = FLASH_AA;
+ return;
+
+ case FLASH_AA:
+ if (((pa&0xFFF) == 0x555) && (v == 0x55))
+ calc->flash.state = FLASH_55;
+ else if (v != 0xF0) {
+ WARN2("undefined command %02x->%06x after AA", v, pa);
+ }
+ return;
+
+ case FLASH_55:
+ if ((pa&0xFFF) == 0xAAA) {
+ switch (v) {
+ case 0x10:
+ case 0x30:
+ WARN("attempt to erase without pre-erase");
+ return;
+ case 0x20:
+ //WARN("entering fast mode");
+ calc->flash.state = FLASH_FASTMODE;
+ return;
+ case 0x80:
+ calc->flash.state = FLASH_ERASE;
+ return;
+ case 0x90:
+ WARN("autoselect is not implemented");
+ return;
+ case 0xA0:
+ calc->flash.state = FLASH_PROG;
+ return;
+ }
+ }
+ if (v != 0xF0)
+ WARN2("undefined command %02x->%06x after AA,55", v, pa);
+ return;
+
+ case FLASH_PROG:
+ sec = get_sector(calc, pa);
+ if (!sector_writable(calc, sec))
+ WARN("programming protected sector");
+ else
+ program_byte(calc, pa, v);
+ return;
+
+ case FLASH_FASTMODE:
+ //WARN2("fast mode cmd %02x->%06x", v, pa);
+ if ( v == 0x90 )
+ calc->flash.state = FLASH_FASTEXIT;
+ else if ( v == 0xA0 )
+ calc->flash.state = FLASH_FASTPROG;
+ else
+ // TODO : figure out whether mixing is allowed on real HW
+ WARN2("mixing fast programming with regular programming : %02x->%06x", v, pa);
+ return;
+
+ case FLASH_FASTPROG:
+ //WARN2("fast prog %02x->%06x", v, pa);
+ sec = get_sector(calc, pa);
+ if (!sector_writable(calc, sec))
+ WARN("programming protected sector");
+ else
+ program_byte(calc, pa, v);
+ calc->flash.state = FLASH_FASTMODE;
+ return;
+
+ case FLASH_FASTEXIT:
+ //WARN("leaving fast mode");
+ if ( v != 0xF0 )
+ {
+ WARN2("undefined command %02x->%06x after fast mode pre-exit 90", v, pa);
+ // TODO : figure out whether fast mode remains in such a case
+ calc->flash.state = FLASH_FASTMODE;
+ }
+ return;
+
+ case FLASH_ERASE:
+ if (((pa&0xFFF) == 0xAAA) && (v == 0xAA))
+ calc->flash.state = FLASH_ERAA;
+ else if (v != 0xF0)
+ WARN2("undefined command %02x->%06x after pre-erase", v, pa);
+ return;
+
+ case FLASH_ERAA:
+ if (((pa&0xFFF) == 0x555) && (v == 0x55))
+ calc->flash.state = FLASH_ER55;
+ else if (v != 0xF0)
+ WARN2("undefined command %02x->%06x after pre-erase AA", v, pa);
+ return;
+
+ case FLASH_ER55:
+ if (((pa&0xFFF) == 0xAAA) && v==0x10) {
+ tilem_message(calc, "Erasing entire Flash chip");
+
+ for (i = 0; i < calc->hw.nflashsectors; i++) {
+ sec = &calc->hw.flashsectors[i];
+ if (sector_writable(calc, sec))
+ erase_sector(calc, sec->start,
+ sec->size);
+ }
+ }
+ else if (v == 0x30) {
+ tilem_flash_erase_address(calc, pa);
+ }
+ else if (v != 0xF0)
+ WARN2("undefined command %02x->%06x after pre-erase AA,55", v, pa);
+ return;
+ }
+}
diff --git a/tool/tilem-src/emu/graycolor.c b/tool/tilem-src/emu/graycolor.c
new file mode 100644
index 0000000..5864c0b
--- /dev/null
+++ b/tool/tilem-src/emu/graycolor.c
@@ -0,0 +1,90 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2010 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+#include "tilem.h"
+
+dword* tilem_color_palette_new(int rlight, int glight, int blight,
+ int rdark, int gdark, int bdark,
+ double gamma)
+{
+ dword* pal = tilem_new_atomic(dword, 256);
+ double r0, g0, b0, dr, dg, db;
+ double igamma = 1.0 / gamma;
+ double s = (1.0 / 255.0);
+ int r, g, b, i;
+
+ r0 = pow(rlight * s, gamma);
+ g0 = pow(glight * s, gamma);
+ b0 = pow(blight * s, gamma);
+ dr = (pow(rdark * s, gamma) - r0) * s;
+ dg = (pow(gdark * s, gamma) - g0) * s;
+ db = (pow(bdark * s, gamma) - b0) * s;
+
+ pal[0] = (rlight << 16) | (glight << 8) | blight;
+
+ for (i = 1; i < 255; i++) {
+ r = pow(r0 + i * dr, igamma) * 255.0 + 0.5;
+ if (r < 0) r = 0;
+ if (r > 255) r = 255;
+
+ g = pow(g0 + i * dg, igamma) * 255.0 + 0.5;
+ if (g < 0) g = 0;
+ if (g > 255) g = 255;
+
+ b = pow(b0 + i * db, igamma) * 255.0 + 0.5;
+ if (b < 0) b = 0;
+ if (b > 255) b = 255;
+
+ pal[i] = (r << 16) | (g << 8) | b;
+ }
+
+ pal[255] = (rdark << 16) | (gdark << 8) | bdark;
+
+ return pal;
+}
+
+byte* tilem_color_palette_new_packed(int rlight, int glight, int blight,
+ int rdark, int gdark, int bdark,
+ double gamma)
+{
+ dword* palette;
+ byte* packed;
+ int i;
+
+ palette = tilem_color_palette_new(rlight, glight, blight,
+ rdark, gdark, bdark, gamma);
+
+ packed = tilem_new_atomic(byte, 256 * 3);
+ for (i = 0; i < 256; i++) {
+ packed[i * 3] = palette[i] >> 16;
+ packed[i * 3 + 1] = palette[i] >> 8;
+ packed[i * 3 + 2] = palette[i];
+ }
+
+ tilem_free(palette);
+
+ return packed;
+}
diff --git a/tool/tilem-src/emu/grayimage.c b/tool/tilem-src/emu/grayimage.c
new file mode 100644
index 0000000..46ee275
--- /dev/null
+++ b/tool/tilem-src/emu/grayimage.c
@@ -0,0 +1,324 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2010-2011 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+#include "tilem.h"
+
+/* Scale the input buffer, multiply by F * INCOUNT, and add to the
+ output buffer (which must be an exact multiple of the size of the
+ input buffer.) */
+static inline void add_scale1d_exact(const byte * restrict in, int incount,
+ unsigned int * restrict out,
+ int outcount, int f)
+{
+ int i, j;
+
+ for (i = 0; i < incount; i++) {
+ for (j = 0; j < outcount / incount; j++) {
+ *out += *in * f * incount;
+ out++;
+ }
+ in++;
+ }
+}
+
+/* Scale a 1-dimensional buffer, multiply by F * INCOUNT, and add to
+ the output buffer. */
+static inline void add_scale1d_smooth(const byte * restrict in, int incount,
+ unsigned int * restrict out,
+ int outcount, int f)
+{
+ int in_rem, out_rem;
+ unsigned int outv;
+ int i;
+
+ in_rem = outcount;
+ out_rem = incount;
+ outv = 0;
+ i = outcount;
+ while (i > 0) {
+ if (in_rem < out_rem) {
+ out_rem -= in_rem;
+ outv += in_rem * *in * f;
+ in++;
+ in_rem = outcount;
+ }
+ else {
+ in_rem -= out_rem;
+ outv += out_rem * *in * f;
+ *out += outv;
+ outv = 0;
+ out++;
+ out_rem = incount;
+ i--;
+ }
+ }
+}
+
+/* Scale a 2-dimensional buffer, multiply by INWIDTH * INHEIGHT, and
+ store in the output buffer. */
+static void scale2d_smooth(const byte * restrict in,
+ int inwidth, int inheight, int inrowstride,
+ unsigned int * restrict out,
+ int outwidth, int outheight, int outrowstride)
+{
+ int in_rem, out_rem;
+ int i;
+
+ memset(out, 0, outrowstride * outheight * sizeof(int));
+
+ in_rem = outheight;
+ out_rem = inheight;
+ i = outheight;
+ while (i > 0) {
+ if (in_rem < out_rem) {
+ if (in_rem) {
+ if (outwidth % inwidth)
+ add_scale1d_smooth(in, inwidth, out,
+ outwidth, in_rem);
+ else
+ add_scale1d_exact(in, inwidth, out,
+ outwidth, in_rem);
+ }
+ out_rem -= in_rem;
+ in += inrowstride;
+ in_rem = outheight;
+ }
+ else {
+ in_rem -= out_rem;
+ if (outwidth % inwidth)
+ add_scale1d_smooth(in, inwidth, out, outwidth,
+ out_rem);
+ else
+ add_scale1d_exact(in, inwidth, out, outwidth,
+ out_rem);
+ out += outrowstride;
+ out_rem = inheight;
+ i--;
+ }
+ }
+}
+
+/* Quickly scale a 1-dimensional buffer and store in the output
+ buffer. */
+static inline void scale1d_fast(const byte * restrict in, int incount,
+ byte * restrict out, int outcount)
+{
+ int i, e;
+
+ e = outcount - incount / 2;
+ i = outcount;
+ while (i > 0) {
+ if (e >= 0) {
+ *out = *in;
+ out++;
+ e -= incount;
+ i--;
+ }
+ else {
+ e += outcount;
+ in++;
+ }
+ }
+}
+
+/* Quickly scale a 2-dimensional buffer and store in the output
+ buffer. */
+static void scale2d_fast(const byte * restrict in,
+ int inwidth, int inheight, int inrowstride,
+ byte * restrict out,
+ int outwidth, int outheight, int outrowstride)
+{
+ int i, e;
+
+ e = outheight - inheight / 2;
+ i = outheight;
+ while (i > 0) {
+ if (e >= 0) {
+ scale1d_fast(in, inwidth, out, outwidth);
+ out += outrowstride;
+ e -= inheight;
+ i--;
+ }
+ else {
+ e += outheight;
+ in += inrowstride;
+ }
+ }
+}
+
+/* Determine range of linear pixel values corresponding to a given
+ contrast level. */
+static void get_contrast_settings(unsigned int contrast,
+ int *cbase, int *cfact)
+{
+ if (contrast < 32) {
+ *cbase = 0;
+ *cfact = contrast * 8;
+ }
+ else {
+ *cbase = (contrast - 32) * 8;
+ *cfact = 255 - *cbase;
+ }
+}
+
+#define GETSCALEBUF(ttt, www, hhh) \
+ ((ttt *) alloc_scalebuf(buf, (www) * (hhh) * sizeof(ttt)))
+
+static void* alloc_scalebuf(TilemLCDBuffer *buf, unsigned int size)
+{
+ if (TILEM_UNLIKELY(size > buf->tmpbufsize)) {
+ buf->tmpbufsize = size;
+ tilem_free(buf->tmpbuf);
+ buf->tmpbuf = tilem_malloc_atomic(size);
+ }
+
+ return buf->tmpbuf;
+}
+
+void tilem_draw_lcd_image_indexed(TilemLCDBuffer * restrict buf,
+ byte * restrict buffer,
+ int imgwidth, int imgheight,
+ int rowstride, int scaletype)
+{
+ int dwidth = buf->width;
+ int dheight = buf->height;
+ int i, j, v;
+ unsigned int * restrict ibuf;
+ int cbase, cfact;
+ byte cindex[129];
+
+ if (dwidth == 0 || dheight == 0 || buf->contrast == 0) {
+ for (i = 0; i < imgheight; i++) {
+ for (j = 0; j < imgwidth; j++)
+ buffer[j] = 0;
+ buffer += rowstride;
+ }
+ return;
+ }
+
+ get_contrast_settings(buf->contrast, &cbase, &cfact);
+
+ for (i = 0; i <= 128; i++)
+ cindex[i] = ((i * cfact) >> 7) + cbase;
+
+ if (scaletype == TILEM_SCALE_FAST
+ || (imgwidth % dwidth == 0 && imgheight % dheight == 0)) {
+ scale2d_fast(buf->data, dwidth, dheight, buf->rowstride,
+ buffer, imgwidth, imgheight, rowstride);
+
+ for (i = 0; i < imgwidth * imgheight; i++)
+ buffer[i] = cindex[buffer[i]];
+ }
+ else {
+ ibuf = GETSCALEBUF(unsigned int, imgwidth, imgheight);
+
+ scale2d_smooth(buf->data, dwidth, dheight, buf->rowstride,
+ ibuf, imgwidth, imgheight, imgwidth);
+
+ for (i = 0; i < imgheight; i++) {
+ for (j = 0; j < imgwidth; j++) {
+ v = ibuf[j] / (dwidth * dheight);
+ buffer[j] = cindex[v];
+ }
+ ibuf += imgwidth;
+ buffer += rowstride;
+ }
+ }
+}
+
+void tilem_draw_lcd_image_rgb(TilemLCDBuffer * restrict buf,
+ byte * restrict buffer,
+ int imgwidth, int imgheight, int rowstride,
+ int pixbytes, const dword * restrict palette,
+ int scaletype)
+{
+ int dwidth = buf->width;
+ int dheight = buf->height;
+ int i, j, v;
+ int padbytes = rowstride - (imgwidth * pixbytes);
+ byte * restrict bbuf;
+ unsigned int * restrict ibuf;
+ int cbase, cfact;
+ dword cpalette[129];
+
+ if (dwidth == 0 || dheight == 0 || buf->contrast == 0) {
+ for (i = 0; i < imgheight; i++) {
+ for (j = 0; j < imgwidth; j++) {
+ buffer[0] = palette[0] >> 16;
+ buffer[1] = palette[0] >> 8;
+ buffer[2] = palette[0];
+ buffer += pixbytes;
+ }
+ buffer += padbytes;
+ }
+ return;
+ }
+
+ get_contrast_settings(buf->contrast, &cbase, &cfact);
+
+ for (i = 0; i <= 128; i++) {
+ v = ((i * cfact) >> 7) + cbase;
+ cpalette[i] = palette[v];
+ }
+
+ if (scaletype == TILEM_SCALE_FAST
+ || (imgwidth % dwidth == 0 && imgheight % dheight == 0)) {
+ bbuf = GETSCALEBUF(byte, imgwidth, imgheight);
+
+ scale2d_fast(buf->data, dwidth, dheight, buf->rowstride,
+ bbuf, imgwidth, imgheight, imgwidth);
+
+ for (i = 0; i < imgheight; i++) {
+ for (j = 0; j < imgwidth; j++) {
+ v = bbuf[j];
+ buffer[0] = cpalette[v] >> 16;
+ buffer[1] = cpalette[v] >> 8;
+ buffer[2] = cpalette[v];
+ buffer += pixbytes;
+ }
+ bbuf += imgwidth;
+ buffer += padbytes;
+ }
+ }
+ else {
+ ibuf = GETSCALEBUF(unsigned int, imgwidth, imgheight);
+
+ scale2d_smooth(buf->data, dwidth, dheight, buf->rowstride,
+ ibuf, imgwidth, imgheight, imgwidth);
+
+ for (i = 0; i < imgheight; i++) {
+ for (j = 0; j < imgwidth; j++) {
+ v = (ibuf[j] / (dwidth * dheight));
+ buffer[0] = cpalette[v] >> 16;
+ buffer[1] = cpalette[v] >> 8;
+ buffer[2] = cpalette[v];
+ buffer += pixbytes;
+ }
+ ibuf += imgwidth;
+ buffer += padbytes;
+ }
+ }
+}
diff --git a/tool/tilem-src/emu/graylcd.c b/tool/tilem-src/emu/graylcd.c
new file mode 100644
index 0000000..d27ddcc
--- /dev/null
+++ b/tool/tilem-src/emu/graylcd.c
@@ -0,0 +1,263 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2010-2011 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+#include "tilem.h"
+#include "graylcd.h"
+
+/* Read screen contents and update pixels that have changed */
+static void tmr_screen_update(TilemCalc *calc, void *data)
+{
+ TilemGrayLCD *glcd = data;
+ byte *np, *op, nb, ob, d;
+ int i, j, n;
+ dword delta;
+
+ glcd->t++;
+
+ if (calc->z80.lastlcdwrite == glcd->lcdupdatetime)
+ return;
+ glcd->lcdupdatetime = calc->z80.lastlcdwrite;
+
+ (*calc->hw.get_lcd)(calc, glcd->newbits);
+
+ np = glcd->newbits;
+ op = glcd->oldbits;
+ glcd->oldbits = np;
+ glcd->newbits = op;
+ n = 0;
+
+ for (i = 0; i < glcd->bwidth * glcd->height; i++) {
+ nb = *np;
+ ob = *op;
+ d = nb ^ ob;
+ for (j = 0; j < 8; j++) {
+ if (d & (0x80 >> j)) {
+ delta = glcd->t - glcd->tchange[n];
+ glcd->tchange[n] = glcd->t;
+
+ if (ob & (0x80 >> j)) {
+ glcd->curpixels[n].ndark += delta;
+ glcd->curpixels[n].ndarkseg++;
+ }
+ else {
+ glcd->curpixels[n].nlight += delta;
+ glcd->curpixels[n].nlightseg++;
+ }
+ }
+ n++;
+ }
+
+ np++;
+ op++;
+ }
+}
+
+TilemGrayLCD* tilem_gray_lcd_new(TilemCalc *calc, int windowsize, int sampleint)
+{
+ TilemGrayLCD *glcd = tilem_new(TilemGrayLCD, 1);
+ int nbytes, npixels, i;
+
+ glcd->bwidth = (calc->hw.lcdwidth + 7) / 8;
+ glcd->height = calc->hw.lcdheight;
+ nbytes = glcd->bwidth * glcd->height;
+ npixels = nbytes * 8;
+
+ glcd->oldbits = tilem_new_atomic(byte, nbytes);
+ glcd->newbits = tilem_new_atomic(byte, nbytes);
+ glcd->tchange = tilem_new_atomic(dword, npixels);
+ glcd->tframestart = tilem_new_atomic(dword, windowsize);
+ glcd->framestamp = tilem_new_atomic(dword, windowsize);
+ glcd->curpixels = tilem_new_atomic(TilemGrayLCDPixel, npixels);
+ glcd->framebasepixels = tilem_new_atomic(TilemGrayLCDPixel,
+ npixels * windowsize);
+
+ memset(glcd->oldbits, 0, nbytes);
+ memset(glcd->tchange, 0, npixels * sizeof(dword));
+ memset(glcd->tframestart, 0, windowsize * sizeof(dword));
+ memset(glcd->curpixels, 0, npixels * sizeof(TilemGrayLCDPixel));
+ memset(glcd->framebasepixels, 0, (npixels * windowsize
+ * sizeof(TilemGrayLCDPixel)));
+
+ glcd->calc = calc;
+ glcd->timer_id = tilem_z80_add_timer(calc, sampleint / 2, sampleint, 1,
+ &tmr_screen_update, glcd);
+
+ /* assign arbitrary but unique timestamps to the initial n
+ frames */
+ for (i = 0; i < windowsize; i++)
+ glcd->framestamp[i] = calc->z80.lastlcdwrite - i;
+
+ glcd->lcdupdatetime = calc->z80.lastlcdwrite - 1;
+ glcd->t = 0;
+ glcd->windowsize = windowsize;
+ glcd->sampleint = sampleint;
+ glcd->framenum = 0;
+
+ return glcd;
+}
+
+void tilem_gray_lcd_free(TilemGrayLCD *glcd)
+{
+ tilem_z80_remove_timer(glcd->calc, glcd->timer_id);
+
+ tilem_free(glcd->oldbits);
+ tilem_free(glcd->newbits);
+ tilem_free(glcd->tchange);
+ tilem_free(glcd->tframestart);
+ tilem_free(glcd->framestamp);
+ tilem_free(glcd->curpixels);
+ tilem_free(glcd->framebasepixels);
+ tilem_free(glcd);
+}
+
+/* Update levelbuf with values based on the accumulated grayscale
+ data */
+void tilem_gray_lcd_get_frame(TilemGrayLCD * restrict glcd,
+ TilemLCDBuffer * restrict buf)
+{
+ int i, j, n;
+ unsigned int current, delta, fd, fl;
+ word ndark, nlight, ndarkseg, nlightseg;
+ dword tbase, tlimit;
+ dword lastwrite;
+ byte * restrict bp;
+ byte * restrict op;
+ TilemGrayLCDPixel * restrict pix;
+ TilemGrayLCDPixel * restrict basepix;
+ dword * restrict tchange;
+
+ if (TILEM_UNLIKELY(buf->height != glcd->height
+ || buf->rowstride != glcd->bwidth * 8)) {
+ /* reallocate data buffer */
+ tilem_free(buf->data);
+ buf->data = tilem_new_atomic(byte,
+ glcd->height * glcd->bwidth * 8);
+ buf->rowstride = glcd->bwidth * 8;
+ buf->height = glcd->height;
+ }
+
+ buf->width = glcd->calc->hw.lcdwidth;
+
+ if (!glcd->calc->lcd.active
+ || (glcd->calc->z80.halted && !glcd->calc->poweronhalt)) {
+ /* screen is turned off */
+ buf->stamp = glcd->calc->z80.lastlcdwrite;
+ buf->contrast = 0;
+ return;
+ }
+
+ buf->contrast = glcd->calc->lcd.contrast;
+
+ /* If LCD remains unchanged throughout the window, set
+ timestamp to the time when the LCD was last changed, so
+ that consecutive frames have the same timestamp. If LCD
+ has changed during the window, values of gray pixels will
+ vary from one frame to another, so use a unique timestamp
+ for each frame */
+ lastwrite = glcd->calc->z80.lastlcdwrite;
+ if (glcd->framestamp[glcd->framenum] == lastwrite)
+ buf->stamp = lastwrite;
+ else
+ buf->stamp = glcd->calc->z80.clock + 0x80000000;
+ glcd->framestamp[glcd->framenum] = lastwrite;
+
+ /* set tbase to the sample number where the window began; this
+ is used to limit the weight of unchanging pixels */
+ tbase = glcd->tframestart[glcd->framenum];
+ glcd->tframestart[glcd->framenum] = glcd->t;
+ tlimit = glcd->t - tbase; /* number of samples per window */
+
+ bp = glcd->newbits;
+ op = buf->data;
+ pix = glcd->curpixels;
+ basepix = glcd->framebasepixels + (glcd->framenum * glcd->height
+ * glcd->bwidth * 8);
+ tchange = glcd->tchange;
+
+ (*glcd->calc->hw.get_lcd)(glcd->calc, bp);
+
+ n = 0;
+
+ for (i = 0; i < glcd->bwidth * glcd->height; i++) {
+ for (j = 0; j < 8; j++) {
+ /* check if pixel is currently set */
+ current = *bp & (0x80 >> j);
+
+ /* compute number of dark and light samples
+ within the window */
+ ndark = pix[n].ndark - basepix[n].ndark;
+ nlight = pix[n].nlight - basepix[n].nlight;
+
+ /* compute number of dark and light segments
+ within the window */
+ ndarkseg = pix[n].ndarkseg - basepix[n].ndarkseg;
+ nlightseg = pix[n].nlightseg - basepix[n].nlightseg;
+
+ /* average light segment in this window is
+ (nlight / nlightseg); average dark segment
+ is (ndark / ndarkseg) */
+
+ /* ensure tchange is later than or equal to tbase */
+ if (tchange[n] - tbase > tlimit) {
+ tchange[n] = tbase;
+ }
+
+ /* if current segment is longer than average,
+ count it as well */
+ delta = glcd->t - tchange[n];
+
+ if (current) {
+ if (delta * ndarkseg >= ndark) {
+ ndark += delta;
+ ndarkseg++;
+ }
+ }
+ else {
+ if (delta * nlightseg >= nlight) {
+ nlight += delta;
+ nlightseg++;
+ }
+ }
+
+ fd = ndark * nlightseg;
+ fl = nlight * ndarkseg;
+
+ if (fd + fl == 0)
+ *op = (ndark ? 128 : 0);
+ else
+ *op = ((fd * 128) / (fd + fl));
+
+ n++;
+ op++;
+ }
+ bp++;
+ }
+
+ memcpy(basepix, pix, (glcd->height * glcd->bwidth * 8
+ * sizeof(TilemGrayLCDPixel)));
+
+ glcd->framenum = (glcd->framenum + 1) % glcd->windowsize;
+}
diff --git a/tool/tilem-src/emu/graylcd.h b/tool/tilem-src/emu/graylcd.h
new file mode 100644
index 0000000..dbbf8da
--- /dev/null
+++ b/tool/tilem-src/emu/graylcd.h
@@ -0,0 +1,57 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2010-2011 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifndef _TILEM_GRAYLCD_H
+#define _TILEM_GRAYLCD_H
+
+typedef struct _TilemGrayLCDPixel {
+ word ndark; /* Sum of lengths of dark intervals */
+ word nlight; /* Sum of lengths of light intervals */
+ word ndarkseg; /* Number of dark intervals */
+ word nlightseg; /* Number of light intervals */
+} TilemGrayLCDPixel;
+
+struct _TilemGrayLCD {
+ TilemCalc *calc; /* Calculator */
+ int timer_id; /* Screen update timer */
+ dword lcdupdatetime; /* CPU time of last known LCD update */
+
+ dword t; /* Time counter */
+ int windowsize; /* Number of frames in the sampling
+ window */
+ int framenum; /* Current frame number */
+ int sampleint; /* Microseconds per sample */
+
+ int bwidth; /* Width of LCD, bytes */
+ int height; /* Height of LCD, pixels */
+ byte *oldbits; /* Original pixel values (current buffer) */
+ byte *newbits; /* Original pixel values (alternate buffer) */
+
+ dword *tchange; /* Time when pixels changed */
+ dword *tframestart; /* Time at start of frame */
+ dword *framestamp; /* LCD update time at start of frame */
+
+ TilemGrayLCDPixel *curpixels; /* Current pixel counters */
+ TilemGrayLCDPixel *framebasepixels; /* Pixel counters as of
+ the start of each
+ frame */
+};
+
+#endif
diff --git a/tool/tilem-src/emu/keypad.c b/tool/tilem-src/emu/keypad.c
new file mode 100644
index 0000000..37953e7
--- /dev/null
+++ b/tool/tilem-src/emu/keypad.c
@@ -0,0 +1,91 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include "tilem.h"
+#include "scancodes.h"
+
+void tilem_keypad_reset(TilemCalc* calc)
+{
+ int i;
+
+ calc->keypad.group = 0xff;
+ calc->keypad.onkeydown = 0;
+ calc->keypad.onkeyint = 0;
+ for (i = 0; i < 8; i++)
+ calc->keypad.keysdown[i] = 0;
+}
+
+void tilem_keypad_set_group(TilemCalc* calc, byte group)
+{
+ calc->keypad.group = group;
+}
+
+byte tilem_keypad_read_keys(TilemCalc* calc)
+{
+ int i;
+ byte keys, old;
+
+ keys = 0;
+ for (i = 0; i < 8; i++) {
+ if (!(calc->keypad.group & (1 << i)))
+ keys |= calc->keypad.keysdown[i];
+ }
+
+ do {
+ old = keys;
+ for (i = 0; i < 8; i++) {
+ if (keys & calc->keypad.keysdown[i])
+ keys |= calc->keypad.keysdown[i];
+ }
+ } while (keys != old);
+
+ return ~keys;
+}
+
+void tilem_keypad_press_key(TilemCalc* calc, int scancode)
+{
+ if (scancode == TILEM_KEY_ON) {
+ if (!calc->keypad.onkeydown && calc->keypad.onkeyint)
+ calc->z80.interrupts |= TILEM_INTERRUPT_ON_KEY;
+ calc->keypad.onkeydown = 1;
+ }
+ else if (scancode > 0 && scancode < 65) {
+ scancode--;
+ calc->keypad.keysdown[scancode / 8] |= (1 << (scancode % 8));
+ }
+}
+
+void tilem_keypad_release_key(TilemCalc* calc, int scancode)
+{
+ if (scancode == TILEM_KEY_ON) {
+ if (calc->keypad.onkeydown && calc->keypad.onkeyint)
+ calc->z80.interrupts |= TILEM_INTERRUPT_ON_KEY;
+ calc->keypad.onkeydown = 0;
+ }
+ else if (scancode > 0 && scancode < 65) {
+ scancode--;
+ calc->keypad.keysdown[scancode / 8] &= ~(1 << (scancode % 8));
+ }
+}
diff --git a/tool/tilem-src/emu/lcd.c b/tool/tilem-src/emu/lcd.c
new file mode 100644
index 0000000..1820805
--- /dev/null
+++ b/tool/tilem-src/emu/lcd.c
@@ -0,0 +1,268 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2001 Solignac Julien
+ * Copyright (C) 2004-2009 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include "tilem.h"
+
+#ifdef DISABLE_LCD_DRIVER_DELAY
+# define BUSY 0
+# define SET_BUSY 0
+#else
+# define BUSY check_delay_timer(calc)
+# define SET_BUSY set_delay_timer(calc)
+
+static inline int check_delay_timer(TilemCalc* calc)
+{
+ int t;
+
+ if (!calc->lcd.busy)
+ return 0;
+
+ t = tilem_z80_get_timer_clocks(calc, TILEM_TIMER_LCD_DELAY);
+ return (t > 0);
+}
+
+static inline void set_delay_timer(TilemCalc* calc)
+{
+ int delay;
+
+ if (!(calc->lcd.emuflags & TILEM_LCD_REQUIRE_DELAY))
+ return;
+
+ if (calc->lcd.emuflags & TILEM_LCD_REQUIRE_LONG_DELAY)
+ delay = 70;
+ else
+ delay = 50;
+
+ calc->lcd.busy = 1;
+
+ tilem_z80_set_timer(calc, TILEM_TIMER_LCD_DELAY, delay, 0, 0);
+}
+#endif
+
+void tilem_lcd_reset(TilemCalc* calc)
+{
+ calc->lcd.active = 0;
+ calc->lcd.contrast = 32;
+ calc->lcd.addr = 0;
+ calc->lcd.mode = 1;
+ calc->lcd.nextbyte = 0;
+ calc->lcd.x = calc->lcd.y = 0;
+ calc->lcd.inc = 7;
+ calc->lcd.rowshift = 0;
+ calc->lcd.busy = 0;
+
+ if (calc->hw.lcdmemsize)
+ calc->lcd.rowstride = (calc->hw.lcdmemsize
+ / calc->hw.lcdheight);
+ else
+ calc->lcd.rowstride = (calc->hw.lcdwidth / 8);
+}
+
+void tilem_lcd_delay_timer(TilemCalc* calc, void* data TILEM_ATTR_UNUSED)
+{
+ calc->lcd.busy = 0;
+}
+
+byte tilem_lcd_t6a04_status(TilemCalc* calc)
+{
+ return (calc->lcd.busy << 7
+ | calc->lcd.mode << 6
+ | calc->lcd.active << 5
+ | (calc->lcd.inc & 3));
+}
+
+void tilem_lcd_t6a04_control(TilemCalc* calc, byte val)
+{
+ if (BUSY) return;
+
+ if (val <= 1) {
+ calc->lcd.mode = val;
+
+ } else if (val == 2) {
+ calc->lcd.active = 0;
+
+ } else if (val == 3) {
+ calc->lcd.active = 1;
+
+ } else if (val <= 7) {
+ calc->lcd.inc = val;
+
+ } else if ((val >= 0x20) && (val <= 0x3F)){
+ calc->lcd.x = val - 0x20;
+
+ } else if ((val >= 0x80) && (val <= 0xBF)) {
+ calc->lcd.y = val - 0x80;
+
+ } else if ((val >= 0x40) && (val <= 0x7F)) {
+ calc->lcd.rowshift = val - 0x40;
+
+ } else if (val >= 0xc0) {
+ calc->lcd.contrast = val - 0xc0;
+
+ }
+
+ calc->z80.lastlcdwrite = calc->z80.clock;
+ SET_BUSY;
+}
+
+
+byte tilem_lcd_t6a04_read(TilemCalc* calc)
+{
+ byte retv = calc->lcd.nextbyte;
+ byte* lcdbuf = calc->lcdmem;
+ int stride = calc->lcd.rowstride;
+ int xlimit;
+
+ if (BUSY) return(0);
+
+ if (calc->lcd.mode)
+ xlimit = stride;
+ else
+ xlimit = (stride * 8 + 5) / 6;
+
+ if (calc->lcd.x >= xlimit)
+ calc->lcd.x = 0;
+ else if (calc->lcd.x < 0)
+ calc->lcd.x = xlimit - 1;
+
+ if (calc->lcd.y >= 0x40)
+ calc->lcd.y = 0;
+ else if (calc->lcd.y < 0)
+ calc->lcd.y = 0x3F;
+
+ if (calc->lcd.mode) {
+ calc->lcd.nextbyte = *(lcdbuf + calc->lcd.x + stride * calc->lcd.y);
+
+ } else {
+ int col = 0x06 * calc->lcd.x;
+ int ofs = calc->lcd.y * stride + (col >> 3);
+ int shift = 0x0A - (col & 0x07);
+
+ calc->lcd.nextbyte = ((*(lcdbuf + ofs) << 8) | *(lcdbuf + ofs + 1)) >> shift;
+ }
+
+ switch (calc->lcd.inc) {
+ case 4: calc->lcd.y--; break;
+ case 5: calc->lcd.y++; break;
+ case 6: calc->lcd.x--; break;
+ case 7: calc->lcd.x++; break;
+ }
+
+ SET_BUSY;
+ return(retv);
+}
+
+
+void tilem_lcd_t6a04_write(TilemCalc* calc, byte sprite)
+{
+ byte* lcdbuf = calc->lcdmem;
+ int stride = calc->lcd.rowstride;
+ int xlimit;
+
+ if (BUSY) return;
+
+ if (calc->lcd.mode)
+ xlimit = stride;
+ else
+ xlimit = (stride * 8 + 5) / 6;
+
+ if (calc->lcd.x >= xlimit)
+ calc->lcd.x = 0;
+ else if (calc->lcd.x < 0)
+ calc->lcd.x = xlimit - 1;
+
+ if (calc->lcd.y >= 0x40)
+ calc->lcd.y = 0;
+ else if (calc->lcd.y < 0)
+ calc->lcd.y = 0x3F;
+
+ if (calc->lcd.mode) {
+ *(lcdbuf + calc->lcd.x + stride * calc->lcd.y) = sprite;
+
+ } else {
+ int col = 0x06 * calc->lcd.x;
+ int ofs = calc->lcd.y * stride + (col >> 3);
+ int shift = col & 0x07;
+ int mask;
+
+ sprite <<= 2;
+ mask = ~(0xFC >> shift);
+ *(lcdbuf + ofs) = (*(lcdbuf + ofs) & mask) | (sprite >> shift);
+ if (shift > 2 && (col >> 3) < (stride - 1)) {
+ ofs++;
+ shift = 8 - shift;
+ mask = ~(0xFC << shift);
+ *(lcdbuf + ofs) = (*(lcdbuf + ofs) & mask) | (sprite << shift);
+ }
+ }
+
+ switch (calc->lcd.inc) {
+ case 4: calc->lcd.y--; break;
+ case 5: calc->lcd.y++; break;
+ case 6: calc->lcd.x--; break;
+ case 7: calc->lcd.x++; break;
+ }
+
+ calc->z80.lastlcdwrite = calc->z80.clock;
+ SET_BUSY;
+ return;
+}
+
+
+void tilem_lcd_t6a04_get_data(TilemCalc* calc, byte* data)
+{
+ int width = calc->hw.lcdwidth / 8;
+ byte* lcdbuf = calc->lcdmem;
+ int stride = calc->lcd.rowstride;
+ int i, j, k;
+
+ for (i = 0; i < calc->hw.lcdheight; i++) {
+ j = (i + calc->lcd.rowshift) % 64;
+ for (k = 0; k < width; k++)
+ data[k] = lcdbuf[j * stride + k];
+ data += width;
+ }
+}
+
+void tilem_lcd_t6a43_get_data(TilemCalc* calc, byte* data)
+{
+ int width = calc->hw.lcdwidth / 8;
+ byte* lcdbuf = calc->ram + calc->lcd.addr;
+ int stride = calc->lcd.rowstride;
+ int i, j;
+
+ for (i = 0; i < calc->hw.lcdheight; i++) {
+ for (j = 0; j < 10; j++)
+ data[j] = lcdbuf[j];
+ for (; j < 10 + width - stride; j++)
+ data[j] = 0;
+ for (; j < width; j++)
+ data[j] = lcdbuf[j + stride - width];
+
+ data += width;
+ lcdbuf += stride;
+ }
+}
diff --git a/tool/tilem-src/emu/link.c b/tool/tilem-src/emu/link.c
new file mode 100644
index 0000000..0bd5ca9
--- /dev/null
+++ b/tool/tilem-src/emu/link.c
@@ -0,0 +1,456 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include "tilem.h"
+
+/* Internal link port control */
+
+static inline void dbus_interrupt(TilemCalc* calc, dword inttype,
+ dword mask)
+{
+ if (!(calc->linkport.mode & mask))
+ return;
+
+ calc->z80.interrupts |= inttype;
+}
+
+static inline void dbus_set_lines(TilemCalc* calc, byte lines)
+{
+ if (lines != calc->linkport.lines) {
+ calc->linkport.lines = lines;
+ if (calc->linkport.linkemu == TILEM_LINK_EMULATOR_BLACK) {
+ tilem_z80_stop(calc, TILEM_STOP_LINK_STATE);
+ }
+ }
+}
+
+static inline void dbus_set_extlines(TilemCalc* calc, byte lines)
+{
+ if ((lines ^ calc->linkport.extlines) & ~calc->linkport.lines) {
+ dbus_interrupt(calc, TILEM_INTERRUPT_LINK_ACTIVE,
+ TILEM_LINK_MODE_INT_ON_ACTIVE);
+ }
+ calc->linkport.extlines = lines;
+}
+
+void tilem_linkport_assist_timer(TilemCalc* calc,
+ void* data TILEM_ATTR_UNUSED)
+{
+ TilemLinkport* lp = &calc->linkport;
+
+ if (lp->assistflags & TILEM_LINK_ASSIST_WRITE_BUSY) {
+ lp->assistflags &= ~TILEM_LINK_ASSIST_WRITE_BUSY;
+ lp->assistflags |= TILEM_LINK_ASSIST_WRITE_ERROR;
+ }
+ else if (lp->assistflags & TILEM_LINK_ASSIST_READ_BUSY) {
+ lp->assistflags &= ~TILEM_LINK_ASSIST_READ_BUSY;
+ lp->assistflags |= TILEM_LINK_ASSIST_READ_ERROR;
+ }
+ else
+ return;
+
+ dbus_interrupt(calc, TILEM_INTERRUPT_LINK_ERROR,
+ TILEM_LINK_MODE_INT_ON_ERROR);
+}
+
+static inline void assist_set_timeout(TilemCalc* calc)
+{
+ if (calc->linkport.mode & TILEM_LINK_MODE_NO_TIMEOUT)
+ return;
+
+ tilem_z80_set_timer(calc, TILEM_TIMER_LINK_ASSIST, 2000000, 0, 1);
+}
+
+static inline void assist_clear_timeout(TilemCalc* calc)
+{
+ tilem_z80_set_timer(calc, TILEM_TIMER_LINK_ASSIST, 0, 0, 0);
+}
+
+static void assist_update_write(TilemCalc* calc)
+{
+ switch (calc->linkport.extlines) {
+ case 0:
+ if (calc->linkport.lines == 0 && calc->linkport.assistoutbits > 0) {
+ /* Ready to send next bit */
+ if (calc->linkport.assistout & 1)
+ dbus_set_lines(calc, 2);
+ else
+ dbus_set_lines(calc, 1);
+ calc->linkport.assistout >>= 1;
+ calc->linkport.assistoutbits--;
+ assist_set_timeout(calc); /* other device must
+ respond within 2
+ seconds */
+ }
+ else if (calc->linkport.lines == 0) {
+ /* Finished sending a byte */
+ calc->linkport.assistflags &= ~TILEM_LINK_ASSIST_WRITE_BUSY;
+ assist_clear_timeout(calc);
+ }
+ break;
+
+ case 1:
+ case 2:
+ if (calc->linkport.extlines == (calc->linkport.lines ^ 3)) {
+ /* Other device acknowledged our bit. Note
+ that the timeout is NOT set at this point.
+ My experiments indicate that the assist
+ will wait, apparently indefinitely, for the
+ other device to bring its lines high. */
+ dbus_set_lines(calc, 0);
+ assist_clear_timeout(calc);
+ }
+ break;
+
+ case 3:
+ /* illegal line state; flag error */
+ calc->linkport.assistflags &= ~TILEM_LINK_ASSIST_WRITE_BUSY;
+ calc->linkport.assistflags |= TILEM_LINK_ASSIST_WRITE_ERROR;
+ dbus_set_lines(calc, 0);
+ assist_clear_timeout(calc);
+ dbus_interrupt(calc, TILEM_INTERRUPT_LINK_ERROR,
+ TILEM_LINK_MODE_INT_ON_ERROR);
+ break;
+ }
+}
+
+static void assist_update_read(TilemCalc* calc)
+{
+ switch (calc->linkport.extlines) {
+ case 0:
+ /* Finished receiving a bit */
+ if (calc->linkport.lines == 1) {
+ calc->linkport.assistin >>= 1;
+ calc->linkport.assistin |= 0x80;
+ calc->linkport.assistinbits++;
+ }
+ else if (calc->linkport.lines == 2) {
+ calc->linkport.assistin >>= 1;
+ calc->linkport.assistinbits++;
+ }
+
+ if (calc->linkport.assistinbits >= 8) {
+ /* finished receiving a byte */
+ calc->linkport.assistlastbyte = calc->linkport.assistin;
+ calc->linkport.assistflags &= ~TILEM_LINK_ASSIST_READ_BUSY;
+ calc->linkport.assistflags |= TILEM_LINK_ASSIST_READ_BYTE;
+ assist_clear_timeout(calc);
+ }
+ else {
+ assist_set_timeout(calc); /* other device must
+ send next bit
+ within 2
+ seconds */
+ }
+
+ dbus_set_lines(calc, 0); /* indicate we're ready to
+ receive */
+ break;
+
+ case 1:
+ /* other device sent a zero; acknowledge it */
+ calc->linkport.assistflags |= TILEM_LINK_ASSIST_READ_BUSY;
+ dbus_set_lines(calc, 2);
+ assist_set_timeout(calc); /* other device must bring
+ both lines high again
+ within 2 seconds */
+ break;
+
+ case 2:
+ /* same as above, but other device sent a one */
+ calc->linkport.assistflags |= TILEM_LINK_ASSIST_READ_BUSY;
+ dbus_set_lines(calc, 1);
+ assist_set_timeout(calc); /* other device must bring
+ both lines high again
+ within 2 seconds */
+ break;
+
+ case 3:
+ /* illegal line state; flag error */
+ calc->linkport.assistflags &= ~TILEM_LINK_ASSIST_READ_BUSY;
+ calc->linkport.assistflags |= TILEM_LINK_ASSIST_READ_ERROR;
+ dbus_set_lines(calc, 0);
+ assist_clear_timeout(calc);
+ dbus_interrupt(calc, TILEM_INTERRUPT_LINK_ERROR,
+ TILEM_LINK_MODE_INT_ON_ERROR);
+ break;
+ }
+}
+
+static void graylink_update_write(TilemCalc* calc)
+{
+ switch (calc->linkport.lines) {
+ case 0:
+ if (calc->linkport.extlines == 0 && calc->linkport.graylinkoutbits > 1) {
+ /* Ready to send next bit */
+ if (calc->linkport.graylinkout & 1)
+ dbus_set_extlines(calc, 2);
+ else
+ dbus_set_extlines(calc, 1);
+ calc->linkport.graylinkout >>= 1;
+ calc->linkport.graylinkoutbits--;
+ }
+ else if (calc->linkport.extlines == 0) {
+ /* Finished sending a byte */
+ calc->linkport.graylinkoutbits = 0;
+ tilem_z80_stop(calc, TILEM_STOP_LINK_WRITE_BYTE);
+ }
+ break;
+
+ case 1:
+ case 2:
+ if (calc->linkport.extlines == (calc->linkport.lines ^ 3))
+ /* Other device acknowledged our bit */
+ dbus_set_extlines(calc, 0);
+ break;
+
+ case 3:
+ /* illegal line state; flag error */
+ dbus_set_extlines(calc, 0);
+ calc->linkport.graylinkoutbits = 0;
+ tilem_z80_stop(calc, TILEM_STOP_LINK_ERROR);
+ break;
+ }
+}
+
+static void graylink_update_read(TilemCalc* calc)
+{
+ switch (calc->linkport.lines) {
+ case 0:
+ /* Finished receiving a bit */
+ if (calc->linkport.extlines == 1) {
+ calc->linkport.graylinkin >>= 1;
+ calc->linkport.graylinkin |= 0x80;
+ calc->linkport.graylinkinbits++;
+ }
+ else if (calc->linkport.extlines == 2) {
+ calc->linkport.graylinkin >>= 1;
+ calc->linkport.graylinkinbits++;
+ }
+
+ if (calc->linkport.graylinkinbits >= 8) {
+ /* finished receiving a byte */
+ tilem_z80_stop(calc, TILEM_STOP_LINK_READ_BYTE);
+ }
+
+ dbus_set_extlines(calc, 0);
+ break;
+
+ case 1:
+ /* other device sent a zero; acknowledge it */
+ dbus_set_extlines(calc, 2);
+ break;
+
+ case 2:
+ /* same as above, but other device sent a one */
+ dbus_set_extlines(calc, 1);
+ break;
+
+ case 3:
+ /* illegal line state; flag error */
+ dbus_set_extlines(calc, 0);
+ calc->linkport.graylinkinbits = 0;
+ tilem_z80_stop(calc, TILEM_STOP_LINK_ERROR);
+ break;
+ }
+}
+
+static void dbus_update(TilemCalc* calc)
+{
+ byte oldlines;
+
+ do {
+ if (calc->linkport.linkemu == TILEM_LINK_EMULATOR_GRAY) {
+ if (calc->linkport.graylinkoutbits) {
+ graylink_update_write(calc);
+ }
+ else if (calc->linkport.graylinkinbits != 8) {
+ graylink_update_read(calc);
+ }
+ }
+
+ oldlines = calc->linkport.lines;
+ if (calc->linkport.assistflags & TILEM_LINK_ASSIST_WRITE_BUSY) {
+ assist_update_write(calc);
+ }
+ else if (calc->linkport.mode & TILEM_LINK_MODE_ASSIST
+ && !(calc->linkport.assistflags & TILEM_LINK_ASSIST_READ_BYTE)) {
+ assist_update_read(calc);
+ }
+ } while (oldlines != calc->linkport.lines);
+
+ if ((calc->linkport.assistflags & TILEM_LINK_ASSIST_READ_BYTE)
+ && (calc->linkport.mode & TILEM_LINK_MODE_INT_ON_READ))
+ calc->z80.interrupts |= TILEM_INTERRUPT_LINK_READ;
+ else
+ calc->z80.interrupts &= ~TILEM_INTERRUPT_LINK_READ;
+
+ if (!(calc->linkport.assistflags & (TILEM_LINK_ASSIST_READ_BUSY
+ | TILEM_LINK_ASSIST_WRITE_BUSY))
+ && (calc->linkport.mode & TILEM_LINK_MODE_INT_ON_IDLE))
+ calc->z80.interrupts |= TILEM_INTERRUPT_LINK_IDLE;
+ else
+ calc->z80.interrupts &= ~TILEM_INTERRUPT_LINK_IDLE;
+}
+
+void tilem_linkport_reset(TilemCalc* calc)
+{
+ dbus_set_lines(calc, 0);
+ assist_clear_timeout(calc);
+ calc->linkport.mode = 0;
+ calc->linkport.assistflags = 0;
+ calc->linkport.assistin = 0;
+ calc->linkport.assistinbits = 0;
+ calc->linkport.assistout = 0;
+ calc->linkport.assistoutbits = 0;
+ calc->linkport.assistlastbyte = 0;
+}
+
+byte tilem_linkport_get_lines(TilemCalc* calc)
+{
+ //dbus_update(calc);
+ return (~calc->linkport.lines & ~calc->linkport.extlines & 3);
+}
+
+void tilem_linkport_set_lines(TilemCalc* calc, byte lines)
+{
+ if (!(calc->linkport.mode & TILEM_LINK_MODE_ASSIST)
+ && !(calc->linkport.assistflags & TILEM_LINK_ASSIST_WRITE_BUSY))
+ dbus_set_lines(calc, lines & 3);
+
+ dbus_update(calc);
+}
+
+byte tilem_linkport_read_byte(TilemCalc* calc)
+{
+ byte value = calc->linkport.assistin;
+ calc->linkport.assistflags &= ~(TILEM_LINK_ASSIST_READ_BYTE
+ | TILEM_LINK_ASSIST_READ_BUSY);
+ calc->linkport.assistinbits = 0;
+ dbus_update(calc);
+ return value;
+}
+
+void tilem_linkport_write_byte(TilemCalc* calc, byte data)
+{
+ if (calc->linkport.assistflags & (TILEM_LINK_ASSIST_READ_BUSY
+ | TILEM_LINK_ASSIST_WRITE_BUSY))
+ return;
+
+ dbus_set_lines(calc, 0);
+ calc->linkport.assistout = data;
+ calc->linkport.assistoutbits = 8;
+ calc->linkport.assistflags |= TILEM_LINK_ASSIST_WRITE_BUSY;
+ dbus_update(calc);
+}
+
+unsigned int tilem_linkport_get_assist_flags(TilemCalc* calc)
+{
+ //dbus_update(calc);
+ return calc->linkport.assistflags;
+}
+
+void tilem_linkport_set_mode(TilemCalc* calc, unsigned int mode)
+{
+ if ((mode ^ calc->linkport.mode) & TILEM_LINK_MODE_ASSIST) {
+ dbus_set_lines(calc, 0);
+ calc->linkport.assistflags &= ~(TILEM_LINK_ASSIST_READ_BUSY
+ | TILEM_LINK_ASSIST_WRITE_BUSY);
+ assist_clear_timeout(calc);
+ }
+
+ if (!(mode & TILEM_LINK_MODE_INT_ON_ACTIVE))
+ calc->z80.interrupts &= ~TILEM_INTERRUPT_LINK_ACTIVE;
+ if (!(mode & TILEM_LINK_MODE_INT_ON_ERROR))
+ calc->z80.interrupts &= ~TILEM_INTERRUPT_LINK_ERROR;
+
+ calc->linkport.mode = mode;
+
+ dbus_update(calc);
+}
+
+
+/* External BlackLink emulation */
+
+void tilem_linkport_blacklink_set_lines(TilemCalc* calc, byte lines)
+{
+ dbus_set_extlines(calc, lines & 3);
+ dbus_update(calc);
+}
+
+byte tilem_linkport_blacklink_get_lines(TilemCalc* calc)
+{
+ dbus_update(calc);
+ return (~calc->linkport.lines & ~calc->linkport.extlines & 3);
+}
+
+
+/* External GrayLink emulation */
+
+void tilem_linkport_graylink_reset(TilemCalc* calc)
+{
+ calc->linkport.graylinkin = 0;
+ calc->linkport.graylinkinbits = 0;
+ calc->linkport.graylinkout = 0;
+ calc->linkport.graylinkoutbits = 0;
+ dbus_set_extlines(calc, 0);
+ dbus_update(calc);
+}
+
+int tilem_linkport_graylink_ready(TilemCalc* calc)
+{
+ if (calc->linkport.graylinkoutbits
+ || calc->linkport.graylinkinbits)
+ return 0;
+ else
+ return 1;
+}
+
+int tilem_linkport_graylink_send_byte(TilemCalc* calc, byte value)
+{
+ if (!tilem_linkport_graylink_ready(calc))
+ return -1;
+
+ dbus_set_extlines(calc, 0);
+
+ /* set to 9 because we want to wait for the calc to bring both
+ link lines low before we send the first bit, and also after
+ we send the last bit */
+ calc->linkport.graylinkoutbits = 9;
+
+ calc->linkport.graylinkout = value;
+ dbus_update(calc);
+ return 0;
+}
+
+int tilem_linkport_graylink_get_byte(TilemCalc* calc)
+{
+ dbus_update(calc);
+ if (calc->linkport.graylinkinbits != 8)
+ return -1;
+
+ calc->linkport.graylinkinbits = 0;
+ return calc->linkport.graylinkin;
+}
diff --git a/tool/tilem-src/emu/md5.c b/tool/tilem-src/emu/md5.c
new file mode 100644
index 0000000..14f8996
--- /dev/null
+++ b/tool/tilem-src/emu/md5.c
@@ -0,0 +1,86 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include "tilem.h"
+
+void tilem_md5_assist_reset(TilemCalc* calc)
+{
+ int i;
+
+ for (i = 0; i < 6; i++)
+ calc->md5assist.regs[i] = 0;
+ calc->md5assist.shift = 0;
+ calc->md5assist.mode = 0;
+}
+
+dword tilem_md5_assist_get_value(TilemCalc* calc)
+{
+ /* Return the result of a complete MD5 operation:
+ b + ((a + f(b,c,d) + X + T) <<< s) */
+ dword a, b, c, d, x, t, result;
+ byte mode, s;
+
+ mode = calc->md5assist.mode;
+ a = calc->md5assist.regs[TILEM_MD5_REG_A];
+ b = calc->md5assist.regs[TILEM_MD5_REG_B];
+ c = calc->md5assist.regs[TILEM_MD5_REG_C];
+ d = calc->md5assist.regs[TILEM_MD5_REG_D];
+ x = calc->md5assist.regs[TILEM_MD5_REG_X];
+ t = calc->md5assist.regs[TILEM_MD5_REG_T];
+ s = calc->md5assist.shift;
+
+ switch (mode) {
+ case TILEM_MD5_FUNC_FF:
+ /* F(X,Y,Z) = XY v not(X) Z */
+ result = (b & c) | ((~b) & d);
+ break;
+
+ case TILEM_MD5_FUNC_GG:
+ /* G(X,Y,Z) = XZ v Y not(Z) */
+ result = (b & d) | (c & (~d));
+ break;
+
+ case TILEM_MD5_FUNC_HH:
+ /* H(X,Y,Z) = X xor Y xor Z */
+ result = b ^ c ^ d;
+ break;
+
+ case TILEM_MD5_FUNC_II:
+ /* I(X,Y,Z) = Y xor (X v not(Z)) */
+ result = c ^ (b | (~d));
+ break;
+
+ default:
+ tilem_internal(calc, "Invalid MD5 mode %d", mode);
+ return 0;
+ }
+
+ result += a + x + t;
+ result &= 0xffffffff;
+ result = (result << s) | (result >> (32 - s));
+ result += b;
+
+ return result;
+}
diff --git a/tool/tilem-src/emu/monolcd.c b/tool/tilem-src/emu/monolcd.c
new file mode 100644
index 0000000..6c6f173
--- /dev/null
+++ b/tool/tilem-src/emu/monolcd.c
@@ -0,0 +1,148 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2011 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+#include "tilem.h"
+
+TilemLCDBuffer* tilem_lcd_buffer_new()
+{
+ return tilem_new0(TilemLCDBuffer, 1);
+}
+
+void tilem_lcd_buffer_free(TilemLCDBuffer *buf)
+{
+ tilem_free(buf->data);
+ tilem_free(buf->tmpbuf);
+ tilem_free(buf);
+}
+
+void tilem_lcd_get_frame(TilemCalc * restrict calc,
+ TilemLCDBuffer * restrict buf)
+{
+ byte * restrict bp;
+ byte * restrict op;
+ int dwidth = calc->hw.lcdwidth;
+ int dheight = calc->hw.lcdheight;
+ unsigned int size;
+ int bwidth = ((calc->hw.lcdwidth + 7) / 8);
+ int i, j;
+
+ if (TILEM_UNLIKELY(buf->height != dheight
+ || buf->rowstride != bwidth * 8)) {
+ /* reallocate data buffer */
+ tilem_free(buf->data);
+ buf->data = tilem_new_atomic(byte, dwidth * bwidth * 8);
+ buf->rowstride = bwidth * 8;
+ buf->height = dheight;
+ }
+
+ size = bwidth * dheight * sizeof(byte);
+ if (TILEM_UNLIKELY(buf->tmpbufsize < size)) {
+ /* reallocate temp buffer */
+ tilem_free(buf->tmpbuf);
+ buf->tmpbuf = tilem_malloc_atomic(size);
+ buf->tmpbufsize = size;
+ }
+
+ buf->width = dwidth;
+
+ buf->stamp = calc->z80.lastlcdwrite;
+
+ if (!calc->lcd.active || (calc->z80.halted && !calc->poweronhalt)) {
+ /* screen is turned off */
+ buf->contrast = 0;
+ return;
+ }
+
+ buf->contrast = calc->lcd.contrast;
+
+ bp = buf->tmpbuf;
+ op = buf->data;
+ (*calc->hw.get_lcd)(calc, bp);
+
+ for (i = 0; i < bwidth * dheight; i++) {
+ for (j = 0; j < 8; j++) {
+ *op = (*bp << j) & 0x80;
+ op++;
+ }
+ bp++;
+ }
+}
+
+/* Do the same thing as tilem_lcd_get_frame, but output is only 0 and 1 */
+void tilem_lcd_get_frame1(TilemCalc * restrict calc,
+ TilemLCDBuffer * restrict buf)
+{
+ byte * restrict bp;
+ byte * restrict op;
+ int dwidth = calc->hw.lcdwidth;
+ int dheight = calc->hw.lcdheight;
+ unsigned int size;
+ int bwidth = ((calc->hw.lcdwidth + 7) / 8);
+ int i, j;
+
+ if (TILEM_UNLIKELY(buf->height != dheight
+ || buf->rowstride != bwidth * 8)) {
+ /* reallocate data buffer */
+ tilem_free(buf->data);
+ buf->data = tilem_new_atomic(byte, dwidth * bwidth * 8);
+ buf->rowstride = bwidth * 8;
+ buf->height = dheight;
+ }
+
+ size = bwidth * dheight * sizeof(byte);
+ if (TILEM_UNLIKELY(buf->tmpbufsize < size)) {
+ /* reallocate temp buffer */
+ tilem_free(buf->tmpbuf);
+ buf->tmpbuf = tilem_malloc_atomic(size);
+ buf->tmpbufsize = size;
+ }
+
+ buf->width = dwidth;
+
+ buf->stamp = calc->z80.lastlcdwrite;
+
+ if (!calc->lcd.active || (calc->z80.halted && !calc->poweronhalt)) {
+ /* screen is turned off */
+ buf->contrast = 0;
+ return;
+ }
+
+ buf->contrast = calc->lcd.contrast;
+
+ bp = buf->tmpbuf;
+ op = buf->data;
+ (*calc->hw.get_lcd)(calc, bp);
+
+ for (i = 0; i < bwidth * dheight; i++) {
+ for (j = 0; j < 8; j++) {
+ *op = (*bp << j) & 0x80;
+ if(*op != 0)
+ *op = 1;
+ op++;
+ }
+ bp++;
+ }
+}
diff --git a/tool/tilem-src/emu/rom.c b/tool/tilem-src/emu/rom.c
new file mode 100644
index 0000000..9cc24c9
--- /dev/null
+++ b/tool/tilem-src/emu/rom.c
@@ -0,0 +1,118 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+#include "tilem.h"
+
+static int find_string(const char *str, FILE *romfile,
+ dword start, dword limit)
+{
+ char buf[256];
+ int pos = 0;
+ int len, i;
+
+ len = strlen(str);
+
+ fseek(romfile, (long int) start, SEEK_SET);
+
+ for (i = 0; i < len-1; i++) {
+ buf[pos] = fgetc(romfile);
+ pos = (pos+1)%256;
+ limit--;
+ }
+
+ while (limit > 0 && !feof(romfile) && !ferror(romfile)) {
+ buf[pos] = fgetc(romfile);
+ pos = (pos+1)%256;
+ limit--;
+
+ for (i = 0; i < len; i++) {
+ if (str[i] != buf[(pos + 256 - len + i)%256])
+ break;
+ }
+ if (i == len)
+ return 1;
+ }
+ return 0;
+}
+
+char tilem_guess_rom_type(FILE* romfile)
+{
+ unsigned long initpos;
+ dword size;
+ char result;
+
+ initpos = ftell(romfile);
+
+ fseek(romfile, 0L, SEEK_END);
+ size = ftell(romfile);
+
+ if (size >= 0x8000 && size < 0x9000) {
+ /* 32k: TI-81 (old or new) */
+ result = TILEM_CALC_TI81;
+ }
+ else if (size >= 0x20000 && size < 0x2C000) {
+ /* 128k: TI-82 or TI-86 */
+ if (find_string("CATALOG", romfile, 0, 0x20000))
+ result = TILEM_CALC_TI85;
+ else
+ result = TILEM_CALC_TI82;
+ }
+ else if (size >= 0x40000 && size < 0x4C000) {
+ /* 256k: TI-83 (or a variant) or TI-86 */
+ if (!find_string("TI82", romfile, 0, 0x40000))
+ result = TILEM_CALC_TI86;
+ else if (find_string("Termin\x96", romfile, 0, 0x40000))
+ result = TILEM_CALC_TI76;
+ else
+ result = TILEM_CALC_TI83;
+ }
+ else if (size >= 0x80000 && size < 0x8C000) {
+ /* 512k: TI-83 Plus or TI-73 */
+ if (find_string("TI-83 Plus", romfile, 0, 8 * 0x4000))
+ result = TILEM_CALC_TI83P;
+ else
+ result = TILEM_CALC_TI73;
+ }
+ else if (size >= 0x100000 && size < 0x124000) {
+ /* 1024k: TI-84 Plus */
+ result = TILEM_CALC_TI84P;
+ }
+ else if (size >= 0x200000 && size < 0x224000) {
+ /* 2048k: TI-83 Plus SE, TI-84 Plus SE */
+ if (find_string("\xed\xef", romfile, 0x1FC000, 0x4000))
+ result = TILEM_CALC_TI84P_NSPIRE;
+ else if (find_string("Operating", romfile, 0x1FC000, 0x4000))
+ result = TILEM_CALC_TI84P_SE;
+ else
+ result = TILEM_CALC_TI83P_SE;
+ }
+ else {
+ result = 0;
+ }
+
+ fseek(romfile, initpos, SEEK_SET);
+ return result;
+}
diff --git a/tool/tilem-src/emu/scancodes.h b/tool/tilem-src/emu/scancodes.h
new file mode 100644
index 0000000..7662a18
--- /dev/null
+++ b/tool/tilem-src/emu/scancodes.h
@@ -0,0 +1,85 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifndef _TILEM_SCANCODES_H
+#define _TILEM_SCANCODES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ TILEM_KEY_DOWN = 0x01,
+ TILEM_KEY_LEFT = 0x02,
+ TILEM_KEY_RIGHT = 0x03,
+ TILEM_KEY_UP = 0x04,
+ TILEM_KEY_ENTER = 0x09,
+ TILEM_KEY_ADD = 0x0A,
+ TILEM_KEY_SUB = 0x0B,
+ TILEM_KEY_MUL = 0x0C,
+ TILEM_KEY_DIV = 0x0D,
+ TILEM_KEY_POWER = 0x0E,
+ TILEM_KEY_CLEAR = 0x0F,
+ TILEM_KEY_CHS = 0x11,
+ TILEM_KEY_3 = 0x12,
+ TILEM_KEY_6 = 0x13,
+ TILEM_KEY_9 = 0x14,
+ TILEM_KEY_RPAREN = 0x15,
+ TILEM_KEY_TAN = 0x16,
+ TILEM_KEY_VARS = 0x17,
+ TILEM_KEY_DECPNT = 0x19,
+ TILEM_KEY_2 = 0x1A,
+ TILEM_KEY_5 = 0x1B,
+ TILEM_KEY_8 = 0x1C,
+ TILEM_KEY_LPAREN = 0x1D,
+ TILEM_KEY_COS = 0x1E,
+ TILEM_KEY_PRGM = 0x1F,
+ TILEM_KEY_STAT = 0x20,
+ TILEM_KEY_0 = 0x21,
+ TILEM_KEY_1 = 0x22,
+ TILEM_KEY_4 = 0x23,
+ TILEM_KEY_7 = 0x24,
+ TILEM_KEY_COMMA = 0x25,
+ TILEM_KEY_SIN = 0x26,
+ TILEM_KEY_MATRIX = 0x27,
+ TILEM_KEY_GRAPHVAR = 0x28,
+ TILEM_KEY_ON = 0x29,
+ TILEM_KEY_STORE = 0x2A,
+ TILEM_KEY_LN = 0x2B,
+ TILEM_KEY_LOG = 0x2C,
+ TILEM_KEY_SQUARE = 0x2D,
+ TILEM_KEY_RECIP = 0x2E,
+ TILEM_KEY_MATH = 0x2F,
+ TILEM_KEY_ALPHA = 0x30,
+ TILEM_KEY_GRAPH = 0x31,
+ TILEM_KEY_TRACE = 0x32,
+ TILEM_KEY_ZOOM = 0x33,
+ TILEM_KEY_WINDOW = 0x34,
+ TILEM_KEY_YEQU = 0x35,
+ TILEM_KEY_2ND = 0x36,
+ TILEM_KEY_MODE = 0x37,
+ TILEM_KEY_DEL = 0x38
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tool/tilem-src/emu/state.c b/tool/tilem-src/emu/state.c
new file mode 100644
index 0000000..2447866
--- /dev/null
+++ b/tool/tilem-src/emu/state.c
@@ -0,0 +1,892 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2009-2012 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+#include
+#include "tilem.h"
+#include "z80.h"
+
+static void set_hw_reg(TilemCalc* calc, const char* name, dword value)
+{
+ int i;
+
+ for (i = 0; i < calc->hw.nhwregs; i++) {
+ if (!strcmp(name, calc->hw.hwregnames[i])) {
+ calc->hwregs[i] = value;
+ return;
+ }
+ }
+
+ tilem_warning(calc, "Unknown hwreg %s", name);
+}
+
+static const char* get_timer_name(TilemCalc* calc, int id)
+{
+ if (id == TILEM_TIMER_LCD_DELAY)
+ return "lcddelay";
+ else if (id == TILEM_TIMER_FLASH_DELAY)
+ return "flashdelay";
+ else if (id == TILEM_TIMER_LINK_ASSIST)
+ return "linkassist";
+ else if (id == TILEM_TIMER_USER1)
+ return "user1";
+ else if (id == TILEM_TIMER_USER2)
+ return "user2";
+ else if (id == TILEM_TIMER_USER3)
+ return "user3";
+ else if (id <= TILEM_NUM_SYS_TIMERS)
+ abort();
+
+ id -= TILEM_NUM_SYS_TIMERS + 1;
+ if (id < calc->hw.nhwtimers)
+ return calc->hw.hwtimernames[id];
+ else
+ return NULL;
+}
+
+static void set_ptimer(TilemCalc* calc, const char* name, dword value,
+ dword period, int rt)
+{
+ int i;
+ const char* tname;
+
+ for (i = 1; i <= calc->z80.ntimers; i++) {
+ tname = get_timer_name(calc, i);
+ if (tname && !strcmp(name, tname)) {
+ tilem_z80_set_timer(calc, i, value, period, rt);
+ return;
+ }
+ }
+
+ tilem_warning(calc, "Unknown timer %s", name);
+}
+
+static int load_old_sav_file(TilemCalc* calc, FILE* savfile)
+{
+ byte b[76];
+ dword regs[19];
+ int i, le, be, c;
+ unsigned int pageA, pageB;
+
+ /* Read memory mapping */
+
+ if (fread(calc->mempagemap, 1, 4, savfile) < 4)
+ return 1;
+
+ /* Read CPU registers */
+
+ if (fread(b, 1, 76, savfile) < 76)
+ return 1;
+
+ be = le = 0;
+
+ /* determine if file is in big-endian or little-endian
+ format */
+
+ for (i = 0; i < 19; i++) {
+ if (b[i * 4] || b[i * 4 + 1])
+ le++;
+ if (b[i * 4 + 2] || b[i * 4 + 3])
+ be++;
+ }
+
+ if (le > be) {
+ for (i = 0; i < 19; i++) {
+ regs[i] = b[i * 4] + (b[i * 4 + 1] << 8);
+ }
+ }
+ else {
+ for (i = 0; i < 19; i++) {
+ regs[i] = b[i * 4 + 3] + (b[i * 4 + 2] << 8);
+ }
+ }
+
+ calc->z80.r.af.d = regs[0];
+ calc->z80.r.bc.d = regs[1];
+ calc->z80.r.de.d = regs[2];
+ calc->z80.r.hl.d = regs[3];
+ calc->z80.r.ix.d = regs[4];
+ calc->z80.r.iy.d = regs[5];
+ calc->z80.r.pc.d = regs[6];
+ calc->z80.r.sp.d = regs[7];
+ calc->z80.r.af2.d = regs[8];
+ calc->z80.r.bc2.d = regs[9];
+ calc->z80.r.de2.d = regs[10];
+ calc->z80.r.hl2.d = regs[11];
+ calc->z80.r.iff1 = regs[12] ? 1 : 0;
+ calc->z80.r.iff2 = regs[13] ? 1 : 0;
+ calc->z80.r.im = regs[15];
+ calc->z80.r.ir.b.h = regs[16];
+ calc->z80.r.ir.b.l = regs[17];
+ calc->z80.r.r7 = regs[18] & 0x80;
+
+ if (calc->hw.model_id == '2' || calc->hw.model_id == '3') {
+ if (fread(b, 1, 5, savfile) < 5)
+ return 1;
+
+ if (calc->hw.model_id == '3')
+ set_hw_reg(calc, "rom_bank", calc->mempagemap[1] & 0x08);
+ calc->hw.z80_out(calc, 0x02, b[4]);
+ }
+
+ /* Read RAM contents: old save files for TI-82/83/85 store RAM
+ pages in logical rather than physical order */
+
+ if (calc->hw.model_id == '2' || calc->hw.model_id == '3'
+ || calc->hw.model_id == '5') {
+ if (fread(calc->mem + calc->hw.romsize + 0x4000, 1,
+ 0x4000, savfile) < 0x4000)
+ return 1;
+ if (fread(calc->mem + calc->hw.romsize, 1,
+ 0x4000, savfile) < 0x4000)
+ return 1;
+ }
+ else {
+ if (fread(calc->mem + calc->hw.romsize, 1,
+ calc->hw.ramsize, savfile) < calc->hw.ramsize)
+ return 1;
+ }
+
+ /* Read LCD contents */
+
+ if (calc->hw.flags & TILEM_CALC_HAS_T6A04) {
+ calc->lcd.rowstride = 12; /* old save files only
+ support the visible
+ portion of the screen */
+ if (fread(calc->lcdmem, 1, 768, savfile) < 768)
+ return 1;
+ }
+
+ /* Read additional HW state */
+
+ switch (calc->hw.model_id) {
+ case '1':
+ break;
+
+ case '2':
+ case '3':
+ if ((c = fgetc(savfile)) != EOF)
+ calc->lcd.mode = c;
+ if ((c = fgetc(savfile)) != EOF)
+ calc->lcd.x = c;
+ if ((c = fgetc(savfile)) != EOF)
+ calc->lcd.y = c;
+ break;
+
+ case '5':
+ pageA = calc->mempagemap[1];
+ if (pageA >= 0x08)
+ pageA += 0x38;
+ calc->hw.z80_out(calc, 0x05, pageA);
+
+ if ((c = fgetc(savfile)) != EOF)
+ calc->hw.z80_out(calc, 0x06, c);
+ break;
+
+ case '6':
+ pageA = calc->mempagemap[1];
+ pageB = calc->mempagemap[2];
+ if (pageA >= 0x10)
+ pageA += 0x30;
+ if (pageB >= 0x10)
+ pageB += 0x30;
+
+ calc->hw.z80_out(calc, 0x05, pageA);
+ calc->hw.z80_out(calc, 0x06, pageB);
+ break;
+
+ default: /* TI-73/83+ series */
+ if ((c = fgetc(savfile)) != EOF)
+ calc->lcd.mode = c;
+ if ((c = fgetc(savfile)) != EOF)
+ calc->lcd.x = c;
+ if ((c = fgetc(savfile)) != EOF)
+ calc->lcd.y = c;
+ if ((c = fgetc(savfile)) != EOF)
+ calc->lcd.inc = c;
+
+ if ((c = fgetc(savfile)) == EOF)
+ c = 0;
+ if (c) {
+ pageA = calc->mempagemap[2];
+ pageB = calc->mempagemap[3];
+ calc->hw.z80_out(calc, 0x04, 0x77);
+ }
+ else {
+ pageA = calc->mempagemap[1];
+ pageB = calc->mempagemap[2];
+ calc->hw.z80_out(calc, 0x04, 0x76);
+ }
+
+ if (pageA >= (calc->hw.romsize >> 14))
+ pageA = ((pageA & 0x1f) | calc->hw.rampagemask);
+ if (pageB >= (calc->hw.romsize >> 14))
+ pageB = ((pageB & 0x1f) | calc->hw.rampagemask);
+
+ calc->hw.z80_out(calc, 0x06, pageA);
+ calc->hw.z80_out(calc, 0x07, pageB);
+
+ if ((c = fgetc(savfile)) != EOF)
+ calc->flash.state = c;
+ if ((c = fgetc(savfile)) != EOF)
+ calc->flash.unlock = c;
+
+ if ((c = fgetc(savfile)) != EOF)
+ calc->hw.z80_out(calc, 0x20, c);
+ if ((c = fgetc(savfile)) != EOF)
+ set_hw_reg(calc, "port21", c);
+ if ((c = fgetc(savfile)) != EOF)
+ set_hw_reg(calc, "port22", c);
+ if ((c = fgetc(savfile)) != EOF)
+ set_hw_reg(calc, "port23", c);
+ if ((c = fgetc(savfile)) != EOF)
+ calc->hw.z80_out(calc, 0x27, c);
+ if ((c = fgetc(savfile)) != EOF)
+ calc->hw.z80_out(calc, 0x28, c);
+ break;
+ }
+
+ calc->poweronhalt = calc->lcd.active = 1;
+
+ return 0;
+}
+
+static int read_sav_line(FILE* savfile, char **buf)
+{
+ int c, n, na;
+
+ tilem_free(*buf);
+
+ na = 100;
+ *buf = tilem_malloc_atomic(na);
+ n = 0;
+
+ while ((c = fgetc(savfile)) != EOF) {
+ if (c == '\r' || c == '\n')
+ break;
+
+ n++;
+ if (n >= na) {
+ na = n * 2;
+ *buf = tilem_realloc(*buf, na);
+ }
+
+ if (c == '#')
+ c = 0;
+ (*buf)[n - 1] = c;
+ }
+
+ if (n == 0 && c == EOF) {
+ tilem_free(*buf);
+ *buf = NULL;
+ return 0;
+ }
+ else {
+ (*buf)[n] = 0;
+ return 1;
+ }
+}
+
+static int parse_sav_definition(char* line, char** value)
+{
+ char *p;
+
+ p = strchr(line, '=');
+ if (!p)
+ return 0;
+
+ while (p != line && p[-1] == ' ')
+ p--;
+ *p = 0;
+ p++;
+ while (*p == ' ' || *p == '=')
+ p++;
+ *value = p;
+ return 1;
+}
+
+static int load_new_sav_file(TilemCalc* calc, FILE* savfile)
+{
+ char *buf = NULL;
+ char *p, *q;
+ dword value, length;
+ byte *data;
+ int ok = 0;
+ byte digit;
+ int firstdigit;
+ dword period;
+ int rt;
+
+ while (read_sav_line(savfile, &buf)) {
+ if (!parse_sav_definition(buf, &p))
+ continue;
+
+ if (*p == '{') {
+ p++;
+ if (!strcmp(buf, "RAM")) {
+ length = calc->hw.ramsize;
+ data = calc->ram;
+ }
+ else if (!strcmp(buf, "LCD")) {
+ length = calc->hw.lcdmemsize;
+ data = calc->lcdmem;
+ }
+ else {
+ length = 0;
+ data = NULL;
+ }
+
+ value = 0;
+ firstdigit = 1;
+
+ while (*p != '}') {
+ if (*p == 0 || *p == '#') {
+ if (!read_sav_line(savfile, &buf))
+ return 1;
+ p = buf;
+ continue;
+ }
+
+ if (*p >= '0' && *p <= '9') {
+ digit = *p - '0';
+ p++;
+ }
+ else if (*p >= 'A' && *p <= 'F') {
+ digit = *p + 10 - 'A';
+ p++;
+ }
+ else if (*p >= 'a' && *p <= 'f') {
+ digit = *p + 10 - 'a';
+ p++;
+ }
+ else {
+ p++;
+ continue;
+ }
+
+ if (firstdigit) {
+ value = digit << 4;
+ firstdigit = 0;
+ }
+ else {
+ value |= digit;
+ if (length != 0) {
+ *data = value;
+ data++;
+ length--;
+ }
+ firstdigit = 1;
+ }
+ }
+
+ continue;
+ }
+
+ if (!strcmp(buf, "MODEL")) {
+ q = p;
+ while (*q >= ' ')
+ q++;
+ *q = 0;
+ if (strcmp(p, calc->hw.name)) {
+ tilem_free(buf);
+ return 1;
+ }
+ ok = 1;
+ continue;
+ }
+
+ value = strtol(p, &q, 16);
+
+ /* Persistent timers */
+ if (!strncmp(buf, "timer:", 6)) {
+ while (*q == ' ')
+ q++;
+ if (*q != ',')
+ continue;
+ q++;
+ while (*q == ' ')
+ q++;
+ period = strtol(q, &q, 16);
+
+ while (*q == ' ')
+ q++;
+ if (*q != ',')
+ continue;
+ q++;
+ while (*q == ' ')
+ q++;
+ rt = strtol(q, &q, 16);
+
+ set_ptimer(calc, buf + 6, value, period, rt);
+ continue;
+ }
+
+ /* Z80 */
+ if (!strcmp(buf, "af")) calc->z80.r.af.d = value;
+ else if (!strcmp(buf, "bc")) calc->z80.r.bc.d = value;
+ else if (!strcmp(buf, "de")) calc->z80.r.de.d = value;
+ else if (!strcmp(buf, "hl")) calc->z80.r.hl.d = value;
+ else if (!strcmp(buf, "af'")) calc->z80.r.af2.d = value;
+ else if (!strcmp(buf, "bc'")) calc->z80.r.bc2.d = value;
+ else if (!strcmp(buf, "de'")) calc->z80.r.de2.d = value;
+ else if (!strcmp(buf, "hl'")) calc->z80.r.hl2.d = value;
+ else if (!strcmp(buf, "ix")) calc->z80.r.ix.d = value;
+ else if (!strcmp(buf, "iy")) calc->z80.r.iy.d = value;
+ else if (!strcmp(buf, "pc")) calc->z80.r.pc.d = value;
+ else if (!strcmp(buf, "sp")) calc->z80.r.sp.d = value;
+ else if (!strcmp(buf, "ir")) {
+ calc->z80.r.ir.d = value;
+ calc->z80.r.r7 = value & 0x80;
+ }
+ else if (!strcmp(buf, "wz")) calc->z80.r.wz.d = value;
+ else if (!strcmp(buf, "wz'")) calc->z80.r.wz2.d = value;
+ else if (!strcmp(buf, "iff1")) calc->z80.r.iff1 = value;
+ else if (!strcmp(buf, "iff2")) calc->z80.r.iff2 = value;
+ else if (!strcmp(buf, "im")) calc->z80.r.im = value;
+ else if (!strcmp(buf, "interrupts"))
+ calc->z80.interrupts = value;
+ else if (!strcmp(buf, "clockspeed"))
+ calc->z80.clockspeed = value;
+ else if (!strcmp(buf, "halted")) calc->z80.halted = value;
+
+ /* LCD */
+ else if (!strcmp(buf, "lcd.active"))
+ calc->lcd.active = value;
+ else if (!strcmp(buf, "lcd.addr"))
+ calc->lcd.addr = value;
+ else if (!strcmp(buf, "lcd.rowshift"))
+ calc->lcd.rowshift = value;
+ else if (!strcmp(buf, "lcd.contrast"))
+ calc->lcd.contrast = value;
+ else if (!strcmp(buf, "lcd.inc"))
+ calc->lcd.inc = value;
+ else if (!strcmp(buf, "lcd.mode"))
+ calc->lcd.mode = value;
+ else if (!strcmp(buf, "lcd.x"))
+ calc->lcd.x = value;
+ else if (!strcmp(buf, "lcd.y"))
+ calc->lcd.y = value;
+ else if (!strcmp(buf, "lcd.nextbyte"))
+ calc->lcd.nextbyte = value;
+ else if (!strcmp(buf, "lcd.rowstride"))
+ calc->lcd.rowstride = value;
+ else if (!strcmp(buf, "lcd.busy"))
+ calc->lcd.busy = value;
+
+ /* Link port */
+ else if (!strcmp(buf, "linkport.lines"))
+ calc->linkport.lines = value;
+ else if (!strcmp(buf, "linkport.mode"))
+ calc->linkport.mode = value;
+ else if (!strcmp(buf, "linkport.assistflags"))
+ calc->linkport.assistflags = value;
+ else if (!strcmp(buf, "linkport.assistin"))
+ calc->linkport.assistin = value;
+ else if (!strcmp(buf, "linkport.assistinbits"))
+ calc->linkport.assistinbits = value;
+ else if (!strcmp(buf, "linkport.assistout"))
+ calc->linkport.assistout = value;
+ else if (!strcmp(buf, "linkport.assistoutbits"))
+ calc->linkport.assistoutbits = value;
+ else if (!strcmp(buf, "linkport.assistlastbyte"))
+ calc->linkport.assistlastbyte = value;
+
+ /* Keypad */
+ else if (!strcmp(buf, "keypad.group"))
+ calc->keypad.group = value;
+ else if (!strcmp(buf, "keypad.onkeyint"))
+ calc->keypad.onkeyint = value;
+
+ /* MD5 assist */
+ else if (!strcmp(buf, "md5assist.a"))
+ calc->md5assist.regs[0] = value;
+ else if (!strcmp(buf, "md5assist.b"))
+ calc->md5assist.regs[1] = value;
+ else if (!strcmp(buf, "md5assist.c"))
+ calc->md5assist.regs[2] = value;
+ else if (!strcmp(buf, "md5assist.d"))
+ calc->md5assist.regs[3] = value;
+ else if (!strcmp(buf, "md5assist.x"))
+ calc->md5assist.regs[4] = value;
+ else if (!strcmp(buf, "md5assist.t"))
+ calc->md5assist.regs[5] = value;
+ else if (!strcmp(buf, "md5assist.shift"))
+ calc->md5assist.shift = value;
+ else if (!strcmp(buf, "md5assist.mode"))
+ calc->md5assist.mode = value;
+
+ /* Programmable timers */
+ else if (!strcmp(buf, "usertimer0.frequency"))
+ calc->usertimers[0].frequency = value;
+ else if (!strcmp(buf, "usertimer0.loopvalue"))
+ calc->usertimers[0].loopvalue = value;
+ else if (!strcmp(buf, "usertimer0.status"))
+ calc->usertimers[0].status = value;
+ else if (!strcmp(buf, "usertimer1.frequency"))
+ calc->usertimers[1].frequency = value;
+ else if (!strcmp(buf, "usertimer1.loopvalue"))
+ calc->usertimers[1].loopvalue = value;
+ else if (!strcmp(buf, "usertimer1.status"))
+ calc->usertimers[1].status = value;
+ else if (!strcmp(buf, "usertimer2.frequency"))
+ calc->usertimers[2].frequency = value;
+ else if (!strcmp(buf, "usertimer2.loopvalue"))
+ calc->usertimers[2].loopvalue = value;
+ else if (!strcmp(buf, "usertimer2.status"))
+ calc->usertimers[2].status = value;
+
+ /* Main power */
+ else if (!strcmp(buf, "poweronhalt"))
+ calc->poweronhalt = value;
+
+ /* Battery */
+ else if (!strcmp(buf, "battery"))
+ calc->battery = value;
+
+ /* Memory */
+ else if (!strcmp(buf, "mempagemap0"))
+ calc->mempagemap[0] = value;
+ else if (!strcmp(buf, "mempagemap1"))
+ calc->mempagemap[1] = value;
+ else if (!strcmp(buf, "mempagemap2"))
+ calc->mempagemap[2] = value;
+ else if (!strcmp(buf, "mempagemap3"))
+ calc->mempagemap[3] = value;
+ else if (!strcmp(buf, "flash.unlock"))
+ calc->flash.unlock = value;
+ else if (!strcmp(buf, "flash.state"))
+ calc->flash.state = value;
+ else if (!strcmp(buf, "flash.busy"))
+ calc->flash.busy = value;
+ else if (!strcmp(buf, "flash.progaddr"))
+ calc->flash.progaddr = value;
+ else if (!strcmp(buf, "flash.progbyte"))
+ calc->flash.progbyte = value;
+ else if (!strcmp(buf, "flash.toggles"))
+ calc->flash.toggles = value;
+ else if (!strcmp(buf, "flash.overridegroup"))
+ calc->flash.overridegroup = value;
+
+ else
+ set_hw_reg(calc, buf, value);
+ }
+
+ tilem_free(buf);
+
+ return !ok;
+}
+
+int tilem_calc_load_state(TilemCalc* calc, FILE* romfile, FILE* savfile)
+{
+ int b;
+ int savtype = 0;
+
+ if (romfile) {
+ if (fread(calc->mem, 1, calc->hw.romsize, romfile)
+ != calc->hw.romsize)
+ return 1;
+ }
+
+ tilem_calc_reset(calc);
+
+ if (savfile) {
+ /* first byte of old save files is always zero */
+ b = fgetc(savfile);
+ fseek(savfile, 0L, SEEK_SET);
+
+ if (b == 0) {
+ if (load_old_sav_file(calc, savfile)) {
+ tilem_calc_reset(calc);
+ return 1;
+ }
+ else
+ savtype = 1;
+ }
+ else {
+ if (load_new_sav_file(calc, savfile)) {
+ tilem_calc_reset(calc);
+ return 1;
+ }
+ else
+ savtype = 2;
+ }
+ }
+
+ if (calc->hw.stateloaded)
+ (*calc->hw.stateloaded)(calc, savtype);
+
+ return 0;
+}
+
+char tilem_get_sav_type(FILE* savfile)
+{
+ int b;
+ char *buf = NULL, *p, *q;
+ const TilemHardware **models;
+ int nmodels, i;
+ char id = 0;
+
+ tilem_get_supported_hardware(&models, &nmodels);
+
+ /* first byte of old save files is always zero */
+ b = fgetc(savfile);
+ fseek(savfile, 0L, SEEK_SET);
+ if (b == 0)
+ return 0; /* old files give no way to detect model */
+
+ while (read_sav_line(savfile, &buf)) {
+ if (parse_sav_definition(buf, &p)
+ && !strcmp(buf, "MODEL")) {
+ q = p;
+ while (*q >= ' ')
+ q++;
+ *q = 0;
+
+ for (i = 0; i < nmodels; i++)
+ if (!strcmp(p, models[i]->name))
+ id = models[i]->model_id;
+
+ break;
+ }
+ }
+
+ fseek(savfile, 0L, SEEK_SET);
+ tilem_free(buf);
+ return id;
+}
+
+int tilem_calc_save_state(TilemCalc* calc, FILE* romfile, FILE* savfile)
+{
+ dword i;
+ dword t;
+ int j;
+ const char* tname;
+ unsigned int rowstride;
+
+ if (romfile) {
+ if (fwrite(calc->mem, 1, calc->hw.romsize, romfile)
+ != calc->hw.romsize)
+ return 1;
+ }
+
+ if (savfile) {
+ fprintf(savfile, "# Tilem II State File\n# Version: %s\n",
+ PACKAGE_VERSION);
+ fprintf(savfile, "MODEL = %s\n", calc->hw.name);
+
+ fprintf(savfile, "\n## CPU ##\n");
+ fprintf(savfile, "af = %04X\n", calc->z80.r.af.w.l);
+ fprintf(savfile, "bc = %04X\n", calc->z80.r.bc.w.l);
+ fprintf(savfile, "de = %04X\n", calc->z80.r.de.w.l);
+ fprintf(savfile, "hl = %04X\n", calc->z80.r.hl.w.l);
+ fprintf(savfile, "af' = %04X\n", calc->z80.r.af2.w.l);
+ fprintf(savfile, "bc' = %04X\n", calc->z80.r.bc2.w.l);
+ fprintf(savfile, "de' = %04X\n", calc->z80.r.de2.w.l);
+ fprintf(savfile, "hl' = %04X\n", calc->z80.r.hl2.w.l);
+ fprintf(savfile, "ix = %04X\n", calc->z80.r.ix.w.l);
+ fprintf(savfile, "iy = %04X\n", calc->z80.r.iy.w.l);
+ fprintf(savfile, "pc = %04X\n", calc->z80.r.pc.w.l);
+ fprintf(savfile, "sp = %04X\n", calc->z80.r.sp.w.l);
+ fprintf(savfile, "ir = %04X\n",
+ ((calc->z80.r.ir.w.l & ~0x80) | calc->z80.r.r7));
+ fprintf(savfile, "wz = %04X\n", calc->z80.r.wz.w.l);
+ fprintf(savfile, "wz' = %04X\n", calc->z80.r.wz2.w.l);
+ fprintf(savfile, "iff1 = %X\n", calc->z80.r.iff1);
+ fprintf(savfile, "iff2 = %X\n", calc->z80.r.iff2);
+ fprintf(savfile, "im = %X\n", calc->z80.r.im);
+ fprintf(savfile, "interrupts = %08X\n", calc->z80.interrupts);
+ fprintf(savfile, "clockspeed = %X\n", calc->z80.clockspeed);
+ fprintf(savfile, "halted = %X\n", calc->z80.halted);
+
+ fprintf(savfile, "\n## LCD Driver ##\n");
+ fprintf(savfile, "lcd.active = %X\n",
+ calc->lcd.active);
+ fprintf(savfile, "lcd.contrast = %X\n",
+ calc->lcd.contrast);
+ fprintf(savfile, "lcd.rowstride = %X\n",
+ calc->lcd.rowstride);
+ if (calc->hw.flags & TILEM_CALC_HAS_T6A04) {
+ fprintf(savfile, "lcd.rowshift = %X\n",
+ calc->lcd.rowshift);
+ fprintf(savfile, "lcd.inc = %X\n",
+ calc->lcd.inc);
+ fprintf(savfile, "lcd.mode = %X\n",
+ calc->lcd.mode);
+ fprintf(savfile, "lcd.x = %02X\n",
+ calc->lcd.x);
+ fprintf(savfile, "lcd.y = %02X\n",
+ calc->lcd.y);
+ fprintf(savfile, "lcd.nextbyte = %02X\n",
+ calc->lcd.nextbyte);
+ fprintf(savfile, "lcd.busy = %X\n",
+ calc->lcd.busy);
+ }
+ fprintf(savfile, "lcd.addr = %X\n", calc->lcd.addr);
+
+ if (calc->hw.flags & TILEM_CALC_HAS_LINK) {
+ fprintf(savfile, "\n## Link Port ##\n");
+ fprintf(savfile, "linkport.lines = %X\n",
+ calc->linkport.lines);
+ fprintf(savfile, "linkport.mode = %08X\n",
+ calc->linkport.mode);
+ }
+ if (calc->hw.flags & TILEM_CALC_HAS_LINK_ASSIST) {
+ fprintf(savfile, "linkport.assistflags = %08X\n",
+ calc->linkport.assistflags);
+ fprintf(savfile, "linkport.assistin = %02X\n",
+ calc->linkport.assistin);
+ fprintf(savfile, "linkport.assistinbits = %X\n",
+ calc->linkport.assistinbits);
+ fprintf(savfile, "linkport.assistout = %02X\n",
+ calc->linkport.assistout);
+ fprintf(savfile, "linkport.assistoutbits = %X\n",
+ calc->linkport.assistoutbits);
+ fprintf(savfile, "linkport.assistlastbyte = %02X\n",
+ calc->linkport.assistlastbyte);
+ }
+
+ fprintf(savfile, "\n## Keypad ##\n");
+ fprintf(savfile, "keypad.group = %X\n", calc->keypad.group);
+ fprintf(savfile, "keypad.onkeyint = %X\n",
+ calc->keypad.onkeyint);
+
+ fprintf(savfile, "\n## Memory mapping ##\n");
+ fprintf(savfile, "mempagemap0 = %X\n", calc->mempagemap[0]);
+ fprintf(savfile, "mempagemap1 = %X\n", calc->mempagemap[1]);
+ fprintf(savfile, "mempagemap2 = %X\n", calc->mempagemap[2]);
+ fprintf(savfile, "mempagemap3 = %X\n", calc->mempagemap[3]);
+
+ fprintf(savfile, "\n## Power ##\n");
+ fprintf(savfile, "poweronhalt = %X\n", calc->poweronhalt);
+ fprintf(savfile, "battery = %X\n", calc->battery);
+
+ if (calc->hw.flags & TILEM_CALC_HAS_FLASH) {
+ fprintf(savfile, "\n## Flash ##\n");
+ fprintf(savfile, "flash.unlock = %X\n",
+ calc->flash.unlock);
+ fprintf(savfile, "flash.state = %X\n",
+ calc->flash.state);
+ fprintf(savfile, "flash.busy = %X\n",
+ calc->flash.busy);
+ fprintf(savfile, "flash.progaddr = %X\n",
+ calc->flash.progaddr);
+ fprintf(savfile, "flash.progbyte = %X\n",
+ calc->flash.progbyte);
+ fprintf(savfile, "flash.toggles = %X\n",
+ calc->flash.toggles);
+ fprintf(savfile, "flash.overridegroup = %X\n",
+ calc->flash.overridegroup);
+ }
+
+ if (calc->hw.flags & TILEM_CALC_HAS_MD5_ASSIST) {
+ fprintf(savfile, "\n## MD5 assist ##\n");
+ fprintf(savfile, "md5assist.a = %X\n",
+ calc->md5assist.regs[0]);
+ fprintf(savfile, "md5assist.b = %X\n",
+ calc->md5assist.regs[1]);
+ fprintf(savfile, "md5assist.c = %X\n",
+ calc->md5assist.regs[2]);
+ fprintf(savfile, "md5assist.d = %X\n",
+ calc->md5assist.regs[3]);
+ fprintf(savfile, "md5assist.x = %X\n",
+ calc->md5assist.regs[4]);
+ fprintf(savfile, "md5assist.t = %X\n",
+ calc->md5assist.regs[5]);
+ fprintf(savfile, "md5assist.shift = %X\n",
+ calc->md5assist.shift);
+ fprintf(savfile, "md5assist.mode = %X\n",
+ calc->md5assist.mode);
+ }
+
+ for (j = 0; j < calc->hw.nusertimers; j++) {
+ fprintf(savfile,
+ "\n## Programmable timer %d ##\n", j);
+ fprintf(savfile, "usertimer%d.frequency = %X\n",
+ j, calc->usertimers[j].frequency);
+ fprintf(savfile, "usertimer%d.loopvalue = %X\n",
+ j, calc->usertimers[j].loopvalue);
+ fprintf(savfile, "usertimer%d.status = %X\n",
+ j, calc->usertimers[j].status);
+ }
+
+ fprintf(savfile, "\n## Model-specific ##\n");
+ for (j = 0; j < calc->hw.nhwregs; j++) {
+ fprintf(savfile, "%s = %X\n", calc->hw.hwregnames[j],
+ calc->hwregs[j]);
+ }
+
+ fprintf(savfile, "\n## Timers ##\n");
+ for (j = calc->z80.timer_cpu; j;
+ j = calc->z80.timers[j].next) {
+ tname = get_timer_name(calc, j);
+ if (tname) {
+ t = tilem_z80_get_timer_clocks(calc, j);
+ fprintf(savfile, "timer:%s = %X, %X, 0\n",
+ tname, t, calc->z80.timers[j].period);
+ }
+ }
+ for (j = calc->z80.timer_rt; j;
+ j = calc->z80.timers[j].next) {
+ tname = get_timer_name(calc, j);
+ if (tname) {
+ t = tilem_z80_get_timer_microseconds(calc, j);
+ fprintf(savfile, "timer:%s = %X, %X, 1\n",
+ tname, t, calc->z80.timers[j].period);
+ }
+ }
+
+ fprintf(savfile, "\n## RAM contents ##\n");
+ fprintf(savfile, "RAM = {\n");
+ for (i = 0; i < calc->hw.ramsize; i++) {
+ if (i % 256 == 0) {
+ fprintf(savfile, "# %02X:%04X\n",
+ (i >> 14), (i & 0x3fff));
+ }
+
+ fprintf(savfile, "%02X",
+ calc->mem[i + calc->hw.romsize]);
+ if (i % 32 == 31)
+ fprintf(savfile, "\n");
+ }
+ fprintf(savfile, "}\n## End of RAM contents ##\n");
+
+ if (calc->hw.lcdmemsize) {
+ fprintf(savfile, "\n## LCD contents ##\n");
+ fprintf(savfile, "LCD = {\n");
+ rowstride = calc->lcd.rowstride;
+ if (rowstride == 0)
+ rowstride = 32;
+
+ for (i = 0; i < calc->hw.lcdmemsize; i++) {
+ fprintf(savfile, "%02X", calc->lcdmem[i]);
+ if (i % rowstride == (rowstride - 1))
+ fprintf(savfile, "\n");
+ }
+ fprintf(savfile, "}\n## End of LCD contents ##\n");
+ }
+ }
+
+ return 0;
+}
diff --git a/tool/tilem-src/emu/tilem.h b/tool/tilem-src/emu/tilem.h
new file mode 100644
index 0000000..01878ad
--- /dev/null
+++ b/tool/tilem-src/emu/tilem.h
@@ -0,0 +1,950 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2009-2012 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifndef _TILEM_H
+#define _TILEM_H
+
+#include "tilemint.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Basic integer types */
+typedef uint8_t byte;
+typedef uint16_t word;
+typedef uint32_t dword;
+typedef uint64_t qword;
+
+/* Structure types */
+typedef struct _TilemHardware TilemHardware;
+typedef struct _TilemCalc TilemCalc;
+
+/* Useful macros */
+#if __GNUC__ >= 3
+# define TILEM_ATTR_PURE __attribute__((__pure__))
+# define TILEM_ATTR_UNUSED __attribute__((__unused__))
+# define TILEM_ATTR_MALLOC __attribute__((__malloc__))
+# define TILEM_ATTR_PRINTF(x,y) __attribute__((__format__(__printf__,x,y)))
+# define TILEM_LIKELY(xxx) (__builtin_expect((xxx), 1))
+# define TILEM_UNLIKELY(xxx) (__builtin_expect((xxx), 0))
+#else
+# define TILEM_ATTR_PURE
+# define TILEM_ATTR_UNUSED
+# define TILEM_ATTR_MALLOC
+# define TILEM_ATTR_PRINTF(x,y)
+# define TILEM_LIKELY(xxx) (xxx)
+# define TILEM_UNLIKELY(xxx) (xxx)
+#endif
+
+#define TILEM_DWORD_TO_PTR(xxx) ((void*)(uintptr_t)(xxx))
+#define TILEM_PTR_TO_DWORD(xxx) ((dword)(uintptr_t)(xxx))
+
+/* Memory allocation */
+void* tilem_malloc(size_t size) TILEM_ATTR_MALLOC;
+void* tilem_malloc0(size_t size) TILEM_ATTR_MALLOC;
+void* tilem_malloc_atomic(size_t size) TILEM_ATTR_MALLOC;
+void* tilem_try_malloc(size_t size) TILEM_ATTR_MALLOC;
+void* tilem_try_malloc0(size_t size) TILEM_ATTR_MALLOC;
+void* tilem_try_malloc_atomic(size_t size) TILEM_ATTR_MALLOC;
+void* tilem_realloc(void* ptr, size_t size) TILEM_ATTR_MALLOC;
+void tilem_free(void* ptr);
+#define tilem_new(ttt, nnn) ((ttt*) tilem_malloc((nnn) * sizeof(ttt)));
+#define tilem_new0(ttt, nnn) ((ttt*) tilem_malloc0((nnn) * sizeof(ttt)));
+#define tilem_new_atomic(ttt, nnn) ((ttt*) tilem_malloc_atomic((nnn) * sizeof(ttt)));
+
+#define tilem_try_new(ttt, nnn) ((ttt*) tilem_try_malloc((nnn) * sizeof(ttt)));
+#define tilem_try_new0(ttt, nnn) ((ttt*) tilem_try_malloc0((nnn) * sizeof(ttt)));
+#define tilem_try_new_atomic(ttt, nnn) ((ttt*) tilem_try_malloc_atomic((nnn) * sizeof(ttt)));
+#define tilem_renew(ttt, ppp, nnn) ((ttt*) tilem_realloc((ppp), (nnn) * sizeof(ttt)))
+
+/* Message/error logging */
+
+/* Write an informative message. This can be used to notify the user
+ of major occurences, such as changes in the Flash protection.
+ These messages can occur regularly in normal operation and are
+ provided chiefly to aid in debugging. */
+void tilem_message(TilemCalc* calc, const char* msg, ...)
+ TILEM_ATTR_PRINTF(2, 3);
+
+/* Write a warning message. These messages occur when the calculator
+ software (either the OS or a user program) performs an invalid
+ operation; these messages often indicate a bug in the calculator
+ software, but are otherwise harmless. */
+void tilem_warning(TilemCalc* calc, const char* msg, ...)
+ TILEM_ATTR_PRINTF(2, 3);
+
+/* Write a warning about an internal error. These messages should
+ never occur and indicate a bug in TilEm. */
+void tilem_internal(TilemCalc* calc, const char* msg, ...)
+ TILEM_ATTR_PRINTF(2, 3);
+
+
+/* Z80 CPU */
+
+/* This union allows us to manipulate register pairs as either byte or
+ word values. It may need to be modified for really unusual host
+ CPUs. */
+typedef union _TilemZ80Reg {
+#ifdef WORDS_BIGENDIAN
+ struct {
+ byte h3, h2, h, l;
+ } b;
+
+ struct {
+ word h, l;
+ } w;
+
+ dword d;
+#else
+ struct {
+ byte l, h, h2, h3;
+ } b;
+
+ struct {
+ word l, h;
+ } w;
+
+ dword d;
+#endif
+} TilemZ80Reg;
+
+typedef struct _TilemZ80Regs {
+ TilemZ80Reg af, bc, de, hl;
+ TilemZ80Reg ix, iy, pc, sp;
+ TilemZ80Reg ir, wz, wz2;
+ TilemZ80Reg af2, bc2, de2, hl2;
+ int iff1, iff2, im;
+ byte r7;
+} TilemZ80Regs;
+
+/* Breakpoint types */
+enum {
+ TILEM_BREAK_MEM_READ = 1, /* Break after reading from memory */
+ TILEM_BREAK_MEM_EXEC, /* Break prior to executing from memory */
+ TILEM_BREAK_MEM_WRITE, /* Break after writing to memory */
+ TILEM_BREAK_PORT_READ, /* Break after reading from port */
+ TILEM_BREAK_PORT_WRITE, /* Break after writing to port */
+ TILEM_BREAK_EXECUTE, /* Break after executing opcode */
+
+ TILEM_BREAK_TYPE_MASK = 0xffff,
+
+ TILEM_BREAK_PHYSICAL = 0x10000, /* Use physical addresses */
+ TILEM_BREAK_DISABLED = 0x20000 /* Disabled breakpoint */
+};
+
+/* Emulation flags */
+enum {
+ TILEM_Z80_BREAK_INVALID = 1, /* Break on invalid
+ instructions */
+ TILEM_Z80_BREAK_UNDOCUMENTED = 2, /* Break on undocumented
+ instructions */
+ TILEM_Z80_SKIP_UNDOCUMENTED = 4, /* Ignore undocumented
+ instructions entirely
+ (act as two NOPs) */
+ TILEM_Z80_RESET_UNDOCUMENTED = 8, /* Reset CPU following
+ undocumented instructions */
+ TILEM_Z80_BREAK_EXCEPTIONS = 16, /* Break on hardware exceptions */
+ TILEM_Z80_IGNORE_EXCEPTIONS = 32 /* Ignore hardware exceptions */
+};
+
+/* Reasons for stopping emulation */
+enum {
+ TILEM_STOP_TIMEOUT = 0, /* stopped due to timeout */
+ TILEM_STOP_BREAKPOINT = 1, /* stopped due to breakpoint */
+ TILEM_STOP_INVALID_INST = 2, /* invalid instruction */
+ TILEM_STOP_UNDOCUMENTED_INST = 4, /* undocumented instruction */
+ TILEM_STOP_EXCEPTION = 8, /* hardware exception */
+ TILEM_STOP_LINK_STATE = 16, /* blacklink state change */
+ TILEM_STOP_LINK_READ_BYTE = 32, /* graylink finished reading byte */
+ TILEM_STOP_LINK_WRITE_BYTE = 64, /* graylink finished writing byte */
+ TILEM_STOP_LINK_ERROR = 128 /* graylink encountered error */
+};
+
+/* Types of interrupt */
+enum {
+ TILEM_INTERRUPT_ON_KEY = 1, /* ON key pressed */
+ TILEM_INTERRUPT_TIMER1 = 2, /* Main interrupt timer */
+ TILEM_INTERRUPT_TIMER2 = 4, /* Alt. interrupt timer (83/83+) */
+ TILEM_INTERRUPT_USER_TIMER1 = 8, /* Programmable timers (83+SE) */
+ TILEM_INTERRUPT_USER_TIMER2 = 16,
+ TILEM_INTERRUPT_USER_TIMER3 = 32,
+ TILEM_INTERRUPT_LINK_ACTIVE = 512, /* Link port state changed */
+ TILEM_INTERRUPT_LINK_READ = 1024, /* Link assist read a byte */
+ TILEM_INTERRUPT_LINK_IDLE = 2048, /* Link assist is idle */
+ TILEM_INTERRUPT_LINK_ERROR = 4096 /* Link assist failed */
+};
+
+/* Types of hardware exception */
+enum {
+ TILEM_EXC_RAM_EXEC = 1, /* Executing at invalid RAM address */
+ TILEM_EXC_FLASH_EXEC = 2, /* Executing at invalid Flash address */
+ TILEM_EXC_FLASH_WRITE = 4, /* Writing to invalid Flash address */
+ TILEM_EXC_INSTRUCTION = 8 /* Invalid instruction */
+};
+
+/* Constant hardware timer IDs */
+enum {
+ TILEM_TIMER_NONE = 0,
+ TILEM_TIMER_LCD_DELAY,
+ TILEM_TIMER_FLASH_DELAY,
+ TILEM_TIMER_LINK_ASSIST,
+ TILEM_TIMER_USER1,
+ TILEM_TIMER_USER2,
+ TILEM_TIMER_USER3,
+ TILEM_TIMER_HW
+};
+
+#define TILEM_NUM_SYS_TIMERS (TILEM_TIMER_HW - 1)
+
+/* Type of a timer callback function. Second arg is the callback data
+ passed to tilem_z80_add_timer(). */
+typedef void (*TilemZ80TimerFunc)(TilemCalc*, void*);
+
+/* Type of a breakpoint test function. Second arg is the memory
+ address (or opcode in the case of TILEM_BREAK_EXECUTE breakpoints.)
+ Third arg is the callback data passed to
+ tilem_z80_add_breakpoint(). */
+typedef int (*TilemZ80BreakpointFunc)(TilemCalc*, dword, void*);
+
+typedef struct _TilemZ80Timer TilemZ80Timer;
+typedef struct _TilemZ80Breakpoint TilemZ80Breakpoint;
+
+typedef struct _TilemZ80 {
+ TilemZ80Regs r;
+ unsigned int interrupts; /* Currently active interrupts */
+ int clockspeed; /* Current CPU speed (kHz) */
+ int halted;
+ unsigned int exception;
+ dword clock;
+ dword lastwrite;
+ dword lastlcdwrite;
+
+ unsigned int emuflags;
+
+ int ntimers;
+ TilemZ80Timer* timers;
+ int timer_cpu; /* Sorted list of timers (CPU-based) */
+ int timer_rt; /* Sorted list of timers (realtime) */
+ int timer_free; /* List of free timer structs */
+
+ int nbreakpoints;
+ TilemZ80Breakpoint* breakpoints;
+ int breakpoint_mr; /* Memory read breakpoints */
+ int breakpoint_mx; /* Memory exec breakpoints */
+ int breakpoint_mw; /* Memory write breakpoints */
+ int breakpoint_pr; /* Port read breakpoints */
+ int breakpoint_pw; /* Port write breakpoints */
+ int breakpoint_op; /* Opcode breakpoints */
+ int breakpoint_mpr; /* Physical mem read breakpoints */
+ int breakpoint_mpx; /* Physical mem exec breakpoints */
+ int breakpoint_mpw; /* Physical mem write breakpoints */
+ int breakpoint_disabled; /* Disabled breakpoints */
+ int breakpoint_free; /* List of free bp structs */
+
+ int stopping;
+ dword stop_reason;
+ dword stop_mask;
+ int stop_breakpoint;
+} TilemZ80;
+
+/* Reset CPU */
+void tilem_z80_reset(TilemCalc* calc);
+
+/* Halt simulation */
+void tilem_z80_stop(TilemCalc* calc, dword reason);
+
+/* Set CPU speed (kHz) */
+void tilem_z80_set_speed(TilemCalc* calc, int speed);
+
+/* Raise a hardware exception */
+void tilem_z80_exception(TilemCalc* calc, unsigned type);
+
+/* Add a timer with the given callback function and data. The
+ callback function will be called after 'count' time units, and
+ every 'period' time units thereafter. If rt = 0, the time units
+ are CPU clock cycles; if rt = 1, time units are microseconds.
+
+ Note that if a timer is set in response to a memory read or write,
+ the length of the delay may be off by as much as 19 clock cycles;
+ the precise timings for these are not (yet) properly emulated.
+ Timers set in response to port I/O events will be accurate to the
+ nearest CPU clock cycle.
+
+ The timer is considered to have "fired" as soon as the specified
+ amount of time has elapsed. The callback function, however, may
+ not be called until after the instruction finishes. If multiple
+ timers fire during the same instruction, the order in which the
+ callback functions will be called is undefined.
+
+ If you create a timer using this function (either repeating or
+ non-repeating), you must call tilem_z80_remove_timer() when the
+ timer is no longer needed.
+*/
+int tilem_z80_add_timer(TilemCalc* calc, dword count, dword period,
+ int rt, TilemZ80TimerFunc func, void* data);
+
+/* Change settings for an existing timer. Arguments are the same as
+ above. If count = 0, the timer is disabled. */
+void tilem_z80_set_timer(TilemCalc* calc, int id, dword count,
+ dword period, int rt);
+
+/* Change period for an existing timer without affecting the current
+ interval. */
+void tilem_z80_set_timer_period(TilemCalc* calc, int id, dword period);
+
+/* Delete a timer. */
+void tilem_z80_remove_timer(TilemCalc* calc, int id);
+
+/* Check whether a timer is currently running. */
+int tilem_z80_timer_running(TilemCalc* calc, int id)
+ TILEM_ATTR_PURE;
+
+/* Get the number of clock ticks from now until the next time the
+ given timer fires. (This may be negative, if the timer has already
+ fired during this instruction.) NOTE: If the timer is disabled,
+ the return value is undefined. */
+int tilem_z80_get_timer_clocks(TilemCalc* calc, int id)
+ TILEM_ATTR_PURE;
+
+/* Get the number of microseconds from now until the next time the
+ given timer fires. */
+int tilem_z80_get_timer_microseconds(TilemCalc* calc, int id)
+ TILEM_ATTR_PURE;
+
+/* Add a breakpoint. The breakpoint will be triggered if the address,
+ ANDed with the given mask, falls between the given start and end
+ inclusive. If a callback function is specified it acts as an
+ additional filter, to determine whether the simulation should be
+ halted. */
+int tilem_z80_add_breakpoint(TilemCalc* calc, int type,
+ dword start, dword end, dword mask,
+ TilemZ80BreakpointFunc func, void* data);
+
+/* Remove the given breakpoint. */
+void tilem_z80_remove_breakpoint(TilemCalc* calc, int id);
+
+/* Enable the given breakpoint. */
+void tilem_z80_enable_breakpoint(TilemCalc* calc, int id);
+
+/* Disable the given breakpoint. */
+void tilem_z80_disable_breakpoint(TilemCalc* calc, int id);
+
+/* Check whether the given breakpoint is currently enabled. */
+int tilem_z80_breakpoint_enabled(TilemCalc* calc, int id);
+
+/* Get the type of the given breakpoint. */
+int tilem_z80_get_breakpoint_type(TilemCalc* calc, int id);
+
+/* Get the start address of the given breakpoint. */
+dword tilem_z80_get_breakpoint_address_start(TilemCalc* calc, int id);
+
+/* Get the start address of the given breakpoint. */
+dword tilem_z80_get_breakpoint_address_end(TilemCalc* calc, int id);
+
+/* Get the start address of the given breakpoint. */
+dword tilem_z80_get_breakpoint_address_mask(TilemCalc* calc, int id);
+
+/* Get the callback/filter function associated to the given breakpoint. */
+TilemZ80BreakpointFunc tilem_z80_get_breakpoint_callback(TilemCalc* calc,
+ int id);
+
+/* Get the data associated to the given breakpoint. */
+void* tilem_z80_get_breakpoint_data(TilemCalc* calc, int id);
+
+/* Set the type of the given breakpoint. */
+void tilem_z80_set_breakpoint_type(TilemCalc* calc, int id, int type);
+
+/* Set the start address of the given breakpoint. */
+void tilem_z80_set_breakpoint_address_start(TilemCalc* calc, int id,
+ dword start);
+
+/* Set the start address of the given breakpoint. */
+void tilem_z80_set_breakpoint_address_end(TilemCalc* calc, int id, dword end);
+
+/* Set the start address of the given breakpoint. */
+void tilem_z80_set_breakpoint_address_mask(TilemCalc* calc, int id, dword mask);
+
+/* Set the callback/filter function associated to the given breakpoint. */
+void tilem_z80_set_breakpoint_callback(TilemCalc* calc, int id,
+ TilemZ80BreakpointFunc func);
+
+/* Set the data associated to the given breakpoint. */
+void tilem_z80_set_breakpoint_data(TilemCalc* calc, int id, void* data);
+
+
+/* Run the simulated CPU for the given number of clock
+ ticks/microseconds, or until a breakpoint is hit or
+ tilem_z80_stop() is called. */
+dword tilem_z80_run(TilemCalc* calc, int clocks, int* remaining);
+dword tilem_z80_run_time(TilemCalc* calc, int microseconds, int* remaining);
+
+
+/* LCD driver */
+
+/* Emulation flags */
+enum {
+ TILEM_LCD_REQUIRE_DELAY = 1, /* Emulate required delay
+ between commands */
+ TILEM_LCD_REQUIRE_LONG_DELAY = 2 /* Require extra-long delay */
+};
+
+typedef struct _TilemLCD {
+ /* Common settings */
+ byte active; /* LCD driver active */
+ byte contrast; /* Contrast value (0-63) */
+ int rowstride; /* Number of bytes per row */
+ unsigned int emuflags;
+
+ /* T6A43 internal driver */
+ word addr; /* Memory address */
+
+ /* T6A04 external driver */
+ byte mode; /* I/O mode (0 = 6bit, 1 = 8bit) */
+ byte inc; /* Increment mode (4-7) */
+ byte nextbyte; /* Output register */
+ int x, y; /* Current position */
+ int rowshift; /* Starting row for display */
+ byte busy;
+} TilemLCD;
+
+/* Reset LCD driver */
+void tilem_lcd_reset(TilemCalc* calc);
+
+/* Get LCD driver status (port 10 input) */
+byte tilem_lcd_t6a04_status(TilemCalc* calc);
+
+/* Send command to LCD driver (port 10 output) */
+void tilem_lcd_t6a04_control(TilemCalc* calc, byte val);
+
+/* Read data from LCD driver (port 11 input) */
+byte tilem_lcd_t6a04_read(TilemCalc* calc);
+
+/* Write data to LCD driver (port 11 output) */
+void tilem_lcd_t6a04_write(TilemCalc* calc, byte val);
+
+/* Get screen image (T6A04 style) */
+void tilem_lcd_t6a04_get_data(TilemCalc* calc, byte* data);
+
+/* Get screen image (T6A43 style) */
+void tilem_lcd_t6a43_get_data(TilemCalc* calc, byte* data);
+
+/* Callback for TILEM_TIMER_LCD_DELAY */
+void tilem_lcd_delay_timer(TilemCalc* calc, void* data);
+
+
+
+/* DBUS link port driver */
+
+/* Link port / assist mode flags */
+enum {
+ TILEM_LINK_MODE_ASSIST = 1, /* Enable link assist */
+ TILEM_LINK_MODE_NO_TIMEOUT = 2, /* Assist doesn't time out (xp) */
+ TILEM_LINK_MODE_INT_ON_ACTIVE = 4, /* Interrupt on state change */
+ TILEM_LINK_MODE_INT_ON_READ = 8, /* Interrupt on asst. read */
+ TILEM_LINK_MODE_INT_ON_IDLE = 16, /* Interrupt when asst. idle */
+ TILEM_LINK_MODE_INT_ON_ERROR = 32 /* Interrupt on asst. error */
+};
+
+/* Link port state flags */
+enum {
+ TILEM_LINK_ASSIST_READ_BYTE = 1, /* Assisted read finished */
+ TILEM_LINK_ASSIST_READ_BUSY = 2, /* Assisted read in progress */
+ TILEM_LINK_ASSIST_READ_ERROR = 4, /* Assisted read failed */
+ TILEM_LINK_ASSIST_WRITE_BUSY = 8, /* Assisted write in progress */
+ TILEM_LINK_ASSIST_WRITE_ERROR = 16 /* Assisted write failed */
+};
+
+/* Link emulation mode */
+enum {
+ TILEM_LINK_EMULATOR_NONE = 0, /* Link port disconnected */
+ TILEM_LINK_EMULATOR_BLACK = 1, /* Connected to virtual BlackLink
+ (exit emulation on state change) */
+ TILEM_LINK_EMULATOR_GRAY = 2 /* Connected to virtual GrayLink
+ (auto send/receive bytes) */
+};
+
+typedef struct _TilemLinkport {
+ byte lines, extlines; /* Link line state for TI/PC
+ 0 = both lines high
+ 1 = red wire low
+ 2 = white wire low
+ 3 = both wires low */
+
+ unsigned int mode; /* Mode flags */
+
+ /* Internal link assist */
+ unsigned int assistflags; /* Assist state */
+ byte assistin; /* Input buffer (recv from PC) */
+ byte assistinbits; /* Input bit count */
+ byte assistout; /* Output buffer (send to PC) */
+ byte assistoutbits; /* Output bit count */
+ byte assistlastbyte; /* Last byte received */
+
+ /* External link emulator */
+ byte linkemu;
+ byte graylinkin; /* Input buffer (recv from TI) */
+ byte graylinkinbits; /* Input bit count */
+ byte graylinkout; /* Output buffer (send to TI) */
+ byte graylinkoutbits; /* Output bit count */
+} TilemLinkport;
+
+/* Reset link port */
+void tilem_linkport_reset(TilemCalc* calc);
+
+/* Read link port lines */
+byte tilem_linkport_get_lines(TilemCalc* calc);
+
+/* Set link port lines */
+void tilem_linkport_set_lines(TilemCalc* calc, byte lines);
+
+/* Read from, and clear, link assist input buffer */
+byte tilem_linkport_read_byte(TilemCalc* calc);
+
+/* Write to link assist output buffer */
+void tilem_linkport_write_byte(TilemCalc* calc, byte data);
+
+/* Get assist state */
+unsigned int tilem_linkport_get_assist_flags(TilemCalc* calc);
+
+/* Set link port mode */
+void tilem_linkport_set_mode(TilemCalc* calc, unsigned int mode);
+
+/* Set line states for virtual BlackLink */
+void tilem_linkport_blacklink_set_lines(TilemCalc* calc, byte lines);
+
+/* Get line states from virtual BlackLink */
+byte tilem_linkport_blacklink_get_lines(TilemCalc* calc);
+
+/* Reset GrayLink */
+void tilem_linkport_graylink_reset(TilemCalc* calc);
+
+/* Check if GrayLink is ready to send data */
+int tilem_linkport_graylink_ready(TilemCalc* calc);
+
+/* Send a byte via virtual GrayLink */
+int tilem_linkport_graylink_send_byte(TilemCalc* calc, byte value);
+
+/* Get byte received by virtual GrayLink (-1 = none available) */
+int tilem_linkport_graylink_get_byte(TilemCalc* calc);
+
+/* Callback for TILEM_TIMER_LINK_ASSIST */
+void tilem_linkport_assist_timer(TilemCalc* calc, void* data);
+
+
+/* Keypad */
+
+typedef struct _TilemKeypad {
+ byte group;
+ byte onkeydown;
+ byte onkeyint;
+ byte keysdown[8];
+} TilemKeypad;
+
+/* Reset keypad */
+void tilem_keypad_reset(TilemCalc* calc);
+
+/* Set current group (port 1 output) */
+void tilem_keypad_set_group(TilemCalc* calc, byte group);
+
+/* Read keys from current group (port 1 input) */
+byte tilem_keypad_read_keys(TilemCalc* calc);
+
+/* Press a key */
+void tilem_keypad_press_key(TilemCalc* calc, int scancode);
+
+/* Release a key */
+void tilem_keypad_release_key(TilemCalc* calc, int scancode);
+
+
+/* Flash */
+
+/* Emulation flags */
+enum {
+ TILEM_FLASH_REQUIRE_DELAY = 1 /* Require delay after
+ program/erase */
+};
+
+typedef struct _TilemFlashSector {
+ dword start;
+ dword size;
+ byte protectgroup;
+} TilemFlashSector;
+
+typedef struct _TilemFlash {
+ byte unlock;
+ byte state;
+ unsigned int emuflags;
+ byte busy;
+ dword progaddr;
+ byte progbyte;
+ byte toggles;
+ byte overridegroup;
+} TilemFlash;
+
+/* Reset Flash */
+void tilem_flash_reset(TilemCalc* calc);
+
+/* Read a byte from the Flash chip */
+byte tilem_flash_read_byte(TilemCalc* calc, dword pa);
+
+/* Erase a Flash sector */
+void tilem_flash_erase_address(TilemCalc* calc, dword pa);
+
+/* Write a byte to the Flash chip */
+void tilem_flash_write_byte(TilemCalc* calc, dword pa, byte v);
+
+/* Callback for TILEM_TIMER_FLASH_DELAY */
+void tilem_flash_delay_timer(TilemCalc* calc, void* data);
+
+
+/* MD5 assist */
+
+enum {
+ TILEM_MD5_REG_A = 0, /* initial 'a' value */
+ TILEM_MD5_REG_B = 1, /* 'b' value */
+ TILEM_MD5_REG_C = 2, /* 'c' value */
+ TILEM_MD5_REG_D = 3, /* 'd' value */
+ TILEM_MD5_REG_X = 4, /* 'X' (or 'T') value */
+ TILEM_MD5_REG_T = 5 /* 'T' (or 'X') value */
+};
+
+enum {
+ TILEM_MD5_FUNC_FF = 0,
+ TILEM_MD5_FUNC_GG = 1,
+ TILEM_MD5_FUNC_HH = 2,
+ TILEM_MD5_FUNC_II = 3
+};
+
+typedef struct _TilemMD5Assist {
+ dword regs[6];
+ byte shift;
+ byte mode;
+} TilemMD5Assist;
+
+/* Reset MD5 assist */
+void tilem_md5_assist_reset(TilemCalc* calc);
+
+/* Get output value */
+dword tilem_md5_assist_get_value(TilemCalc* calc);
+
+
+/* Programmable timers */
+
+#define TILEM_MAX_USER_TIMERS 3
+
+enum {
+ TILEM_USER_TIMER_LOOP = 1, /* loop when counter
+ reaches 0 */
+ TILEM_USER_TIMER_INTERRUPT = 2, /* generate interrupt when
+ finished */
+ TILEM_USER_TIMER_OVERFLOW = 4, /* timer has expired at
+ least twice since last
+ mode setting */
+ TILEM_USER_TIMER_FINISHED = 256, /* timer has expired at
+ least once since last
+ mode setting (port 4
+ status bit) */
+ TILEM_USER_TIMER_NO_HALT_INT = 512 /* suppress interrupt if
+ CPU is halted */
+};
+
+typedef struct _TilemUserTimer {
+ byte frequency;
+ byte loopvalue;
+ unsigned int status;
+} TilemUserTimer;
+
+/* Reset timers */
+void tilem_user_timers_reset(TilemCalc* calc);
+
+/* Set frequency control register */
+void tilem_user_timer_set_frequency(TilemCalc* calc, int n, byte value);
+
+/* Set status flags */
+void tilem_user_timer_set_mode(TilemCalc* calc, int n, byte mode);
+
+/* Start timer */
+void tilem_user_timer_start(TilemCalc* calc, int n, byte value);
+
+/* Get timer value */
+byte tilem_user_timer_get_value(TilemCalc* calc, int n);
+
+/* Callback function */
+void tilem_user_timer_expired(TilemCalc* calc, void* data);
+
+
+/* Calculators */
+
+/* Model IDs */
+enum {
+ TILEM_CALC_TI73 = '7', /* TI-73 / TI-73 Explorer */
+ TILEM_CALC_TI76 = 'f', /* TI-76.fr */
+ TILEM_CALC_TI81 = '1', /* TI-81 */
+ TILEM_CALC_TI82 = '2', /* TI-82 */
+ TILEM_CALC_TI83 = '3', /* TI-83 / TI-82 STATS [.fr] */
+ TILEM_CALC_TI83P = 'p', /* TI-83 Plus */
+ TILEM_CALC_TI83P_SE = 's', /* TI-83 Plus Silver Edition */
+ TILEM_CALC_TI84P = '4', /* TI-84 Plus */
+ TILEM_CALC_TI84P_SE = 'z', /* TI-84 Plus Silver Edition */
+ TILEM_CALC_TI84P_NSPIRE = 'n', /* TI-Nspire 84 Plus emulator */
+ TILEM_CALC_TI85 = '5', /* TI-85 */
+ TILEM_CALC_TI86 = '6' /* TI-86 */
+};
+
+/* Calculator flags */
+enum {
+ TILEM_CALC_HAS_LINK = 1, /* Has link port */
+ TILEM_CALC_HAS_LINK_ASSIST = 2, /* Has hardware link assist */
+ TILEM_CALC_HAS_USB = 4, /* Has USB controller */
+ TILEM_CALC_HAS_FLASH = 8, /* Has (writable) Flash */
+ TILEM_CALC_HAS_T6A04 = 16, /* Has separate LCD driver */
+ TILEM_CALC_HAS_MD5_ASSIST = 32 /* Has hardware MD5 assist */
+};
+
+/* Calculator hardware description */
+struct _TilemHardware {
+ char model_id; /* Single character identifying model */
+ const char* name; /* Short name (e.g. ti83p) */
+ const char* desc; /* Full name (e.g. TI-83 Plus) */
+
+ unsigned int flags;
+
+ int lcdwidth, lcdheight; /* Size of LCD */
+ dword romsize, ramsize; /* Size of ROM and RAM */
+ dword lcdmemsize; /* Size of external LCD memory */
+ byte rampagemask; /* Bit mask used for RAM page */
+
+ int nflashsectors;
+ const TilemFlashSector* flashsectors;
+
+ int nusertimers;
+
+ int nhwregs; /* Number of hardware registers */
+ const char** hwregnames; /* Harware register names */
+
+ int nhwtimers; /* Number of hardware timers */
+ const char** hwtimernames; /* Hardware timer names*/
+
+ const char** keynames;
+
+ /* Reset calculator */
+ void (*reset) (TilemCalc*);
+
+ /* Reinitialize after loading state */
+ void (*stateloaded) (TilemCalc*, int);
+
+ /* Z80 ports and memory */
+ byte (*z80_in) (TilemCalc*, dword);
+ void (*z80_out) (TilemCalc*, dword, byte);
+ void (*z80_wrmem) (TilemCalc*, dword, byte);
+ byte (*z80_rdmem) (TilemCalc*, dword);
+ byte (*z80_rdmem_m1) (TilemCalc*, dword);
+
+ /* Evaluate a non-standard instruction */
+ void (*z80_instr) (TilemCalc*, dword);
+
+ /* Persistent timer callback */
+ void (*z80_ptimer) (TilemCalc*, int);
+
+ /* Retrieve LCD contents */
+ void (*get_lcd) (TilemCalc*, byte*);
+
+ /* Convert physical <-> logical addresses */
+ dword (*mem_ltop) (TilemCalc*, dword);
+ dword (*mem_ptol) (TilemCalc*, dword);
+};
+
+/* Current state of the calculator */
+struct _TilemCalc {
+ TilemHardware hw;
+
+ TilemZ80 z80;
+ byte* mem;
+ byte* ram;
+ byte* lcdmem;
+ byte mempagemap[4];
+
+ TilemLCD lcd;
+ TilemLinkport linkport;
+ TilemKeypad keypad;
+ TilemFlash flash;
+ TilemMD5Assist md5assist;
+ TilemUserTimer usertimers[TILEM_MAX_USER_TIMERS];
+
+ byte poweronhalt; /* System power control. If this is
+ zero, turn off LCD, timers,
+ etc. when CPU halts */
+
+ byte battery; /* Battery level (units of 0.1 V) */
+
+ dword* hwregs;
+};
+
+/* Get a list of supported hardware models */
+void tilem_get_supported_hardware(const TilemHardware*** models,
+ int* nmodels);
+
+/* Create a new calculator. This function returns NULL if
+ insufficient memory is available. */
+TilemCalc* tilem_calc_new(char id);
+
+/* Make an exact copy of an existing calculator (including both
+ internal and external state.) Be careful when using this in
+ conjunction with custom timer/breakpoint callback functions. This
+ function returns NULL if insufficient memory is available. */
+TilemCalc* tilem_calc_copy(TilemCalc* calc);
+
+/* Free a calculator that was previously created by tilem_calc_new()
+ or tilem_calc_copy(). */
+void tilem_calc_free(TilemCalc* calc);
+
+/* Reset calculator (essentially, remove and replace batteries.) */
+void tilem_calc_reset(TilemCalc* calc);
+
+/* Load calculator state from ROM and/or save files. */
+int tilem_calc_load_state(TilemCalc* calc, FILE* romfile, FILE* savfile);
+
+/* Save calculator state to ROM and/or save files. */
+int tilem_calc_save_state(TilemCalc* calc, FILE* romfile, FILE* savfile);
+
+
+/* LCD image conversion/scaling */
+
+/* Scaling algorithms */
+enum {
+ TILEM_SCALE_FAST = 0, /* Fast scaling (nearest neighbor) -
+ looks lousy unless the scaling
+ factor is fairly large */
+ TILEM_SCALE_SMOOTH /* Smooth scaling - slower and looks
+ better at small sizes; note that
+ this falls back to using the "fast"
+ algorithm if we are scaling up by
+ an integer factor */
+};
+
+/* Buffer representing a snapshot of the LCD state */
+typedef struct _TilemLCDBuffer {
+ byte width; /* Width of LCD */
+ byte height; /* Height of LCD */
+ byte rowstride; /* Offset between rows in buffer */
+ byte contrast; /* Contrast value (0-63) */
+ dword stamp; /* Timestamp */
+ dword tmpbufsize; /* Size of temporary buffer */
+ byte *data; /* Image data (rowstride*height bytes) */
+ void *tmpbuf; /* Temporary buffer used for scaling */
+} TilemLCDBuffer;
+
+/* Create new TilemLCDBuffer. */
+TilemLCDBuffer* tilem_lcd_buffer_new(void)
+ TILEM_ATTR_MALLOC;
+
+/* Free a TilemLCDBuffer. */
+void tilem_lcd_buffer_free(TilemLCDBuffer *buf);
+
+/* Convert current LCD memory contents to a TilemLCDBuffer (i.e., a
+ monochrome snapshot.) */
+void tilem_lcd_get_frame(TilemCalc * restrict calc,
+ TilemLCDBuffer * restrict buf);
+
+/* Convert current LCD memory contents to a TilemLCDBuffer (i.e., a
+ monochrome snapshot.)
+ Output is only 0 and 1 */
+void tilem_lcd_get_frame1(TilemCalc * restrict calc,
+ TilemLCDBuffer * restrict buf);
+
+/* Convert and scale image to an 8-bit indexed image buffer. IMGWIDTH
+ and IMGHEIGHT are the width and height of the output image,
+ ROWSTRIDE the number of bytes from the start of one row to the next
+ (often equal to IMGWIDTH), and SCALETYPE the scaling algorithm to
+ use. */
+void tilem_draw_lcd_image_indexed(TilemLCDBuffer * restrict frm,
+ byte * restrict buffer,
+ int imgwidth, int imgheight,
+ int rowstride, int scaletype);
+
+/* Convert and scale image to a 24-bit RGB or 32-bit RGBA image
+ buffer. IMGWIDTH and IMGHEIGHT are the width and height of the
+ output image, ROWSTRIDE the number of bytes from the start of one
+ row to the next (often equal to 3 * IMGWIDTH), PIXBYTES the number
+ of bytes per pixel (3 or 4), and SCALETYPE the scaling algorithm to
+ use. PALETTE is an array of 256 color values. */
+void tilem_draw_lcd_image_rgb(TilemLCDBuffer * restrict frm,
+ byte * restrict buffer,
+ int imgwidth, int imgheight, int rowstride,
+ int pixbytes, const dword * restrict palette,
+ int scaletype);
+
+/* Calculate a color palette for use with the above functions.
+ RLIGHT, GLIGHT, BLIGHT are the RGB components (0 to 255) of the
+ lightest possible color; RDARK, GDARK, BDARK are the RGB components
+ of the darkest possible color. GAMMA is the gamma value for the
+ output device (2.2 for most current computer displays and image
+ file formats.) */
+dword* tilem_color_palette_new(int rlight, int glight, int blight,
+ int rdark, int gdark, int bdark,
+ double gamma);
+
+/* Calculate a color palette, as above, and convert it to a packed
+ array of bytes (R, G, B) */
+byte* tilem_color_palette_new_packed(int rlight, int glight, int blight,
+ int rdark, int gdark, int bdark,
+ double gamma);
+
+
+/* Grayscale LCD simulation */
+
+typedef struct _TilemGrayLCD TilemGrayLCD;
+
+/* Create a new LCD and attach to a calculator. Sampling for
+ grayscale is done across WINDOWSIZE frames, with samples taken
+ every SAMPLEINT microseconds. */
+TilemGrayLCD* tilem_gray_lcd_new(TilemCalc *calc, int windowsize,
+ int sampleint);
+
+/* Detach and free an LCD. */
+void tilem_gray_lcd_free(TilemGrayLCD *glcd);
+
+/* Generate a grayscale image for the next frame, based on current
+ calculator state. This function also updates the frame counter and
+ internal state; for proper grayscale behavior, this function needs
+ to be called at regular intervals. */
+void tilem_gray_lcd_get_frame(TilemGrayLCD * restrict glcd,
+ TilemLCDBuffer * restrict frm);
+
+
+/* Miscellaneous functions */
+
+/* Guess calculator type for a ROM file */
+char tilem_guess_rom_type(FILE* romfile);
+
+/* Get calculator type for a SAV file */
+char tilem_get_sav_type(FILE* savfile);
+
+/* Check validity of calculator certificate; repair if necessary */
+void tilem_calc_fix_certificate(TilemCalc* calc, byte* cert,
+ int app_start, int app_end,
+ unsigned exptab_offset);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tool/tilem-src/emu/tilemint.h b/tool/tilem-src/emu/tilemint.h
new file mode 100644
index 0000000..0e95956
--- /dev/null
+++ b/tool/tilem-src/emu/tilemint.h
@@ -0,0 +1,12 @@
+#ifndef _TILEMINT_H
+#define _TILEMINT_H
+
+#ifdef HAVE_STDINTS1_H
+# include
+#elif defined(HAVE_STDINTS2_H)
+# include
+#else
+# include
+#endif
+
+#endif
diff --git a/tool/tilem-src/emu/timers.c b/tool/tilem-src/emu/timers.c
new file mode 100644
index 0000000..967aa73
--- /dev/null
+++ b/tool/tilem-src/emu/timers.c
@@ -0,0 +1,231 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include "tilem.h"
+
+void tilem_user_timers_reset(TilemCalc* calc)
+{
+ int i;
+
+ for (i = 0; i < TILEM_MAX_USER_TIMERS; i++) {
+ tilem_z80_set_timer(calc, TILEM_TIMER_USER1 + i, 0, 0, 0);
+ calc->usertimers[i].frequency = 0;
+ calc->usertimers[i].loopvalue = 0;
+ calc->usertimers[i].status = 0;
+ }
+}
+
+static inline dword get_duration(int fvalue, int nticks)
+{
+ qword t=0;
+
+ if (fvalue & 0x80) {
+ if (fvalue & 0x20)
+ return 64 * nticks;
+ else if (fvalue & 0x10)
+ return 32 * nticks;
+ else if (fvalue & 0x08)
+ return 16 * nticks;
+ else if (fvalue & 0x04)
+ return 8 * nticks;
+ else if (fvalue & 0x02)
+ return 4 * nticks;
+ else if (fvalue & 0x01)
+ return 2 * nticks;
+ else
+ return nticks;
+ }
+ else if (fvalue & 0x40) {
+ switch (fvalue & 7) {
+ case 0:
+ t = 3000000;
+ break;
+ case 1:
+ t = 33000000;
+ break;
+ case 2:
+ t = 328000000;
+ break;
+ case 3:
+ t = 0xC3530D40; //3277000000;
+ break;
+ case 4:
+ t = 1000000;
+ break;
+ case 5:
+ t = 16000000;
+ break;
+ case 6:
+ t = 256000000;
+ break;
+ case 7:
+ t = 0xF4240000; //4096000000;
+ break;
+ }
+
+ return ((t * nticks + 16384) / 32768);
+ }
+
+ return 0;
+}
+
+static dword get_normal_duration(const TilemUserTimer* tmr)
+{
+ if (tmr->loopvalue)
+ return get_duration(tmr->frequency, tmr->loopvalue);
+ else
+ return get_duration(tmr->frequency, 256);
+}
+
+static dword get_overflow_duration(const TilemUserTimer* tmr)
+{
+ return get_duration(tmr->frequency, 256);
+}
+
+void tilem_user_timer_set_frequency(TilemCalc* calc, int n, byte value)
+{
+ TilemUserTimer* tmr = &calc->usertimers[n];
+
+ /* writing to frequency control port stops timer; set
+ loopvalue to the current value of the counter */
+ tmr->loopvalue = tilem_user_timer_get_value(calc, n);
+ tilem_z80_set_timer(calc, TILEM_TIMER_USER1 + n, 0, 0, 0);
+ tmr->frequency = value;
+}
+
+void tilem_user_timer_set_mode(TilemCalc* calc, int n, byte mode)
+{
+ TilemUserTimer* tmr = &calc->usertimers[n];
+
+ /* setting mode clears "finished" and "overflow" flags */
+ tmr->status = ((tmr->status & TILEM_USER_TIMER_NO_HALT_INT)
+ | (mode & 3));
+
+ calc->z80.interrupts &= ~(TILEM_INTERRUPT_USER_TIMER1 << n);
+
+ /* if timer is currently running, it will not overflow the
+ next time it expires -> set period to normal */
+ if ((mode & TILEM_USER_TIMER_LOOP) || tmr->loopvalue == 0) {
+ tilem_z80_set_timer_period(calc, TILEM_TIMER_USER1 + n,
+ get_normal_duration(tmr));
+ }
+ else {
+ tilem_z80_set_timer_period(calc, TILEM_TIMER_USER1 + n, 0);
+ }
+}
+
+void tilem_user_timer_start(TilemCalc* calc, int n, byte value)
+{
+ TilemUserTimer* tmr = &calc->usertimers[n];
+ dword count, period;
+
+ tmr->loopvalue = value;
+
+ /* if a valid frequency is set, then writing to value port
+ starts timer */
+
+ count = get_normal_duration(tmr);
+ if (!count)
+ return;
+
+ if (!value) {
+ /* input value 0 means loop indefinitely */
+ period = get_overflow_duration(tmr);
+ }
+ else if (tmr->status & TILEM_USER_TIMER_FINISHED) {
+ /* timer has already expired once -> it will overflow
+ the next time it expires (note that this happens
+ even if the loop flag isn't set) */
+ period = get_overflow_duration(tmr);
+ }
+ else if (!(tmr->status & TILEM_USER_TIMER_LOOP)) {
+ /* don't loop */
+ period = 0;
+ }
+ else {
+ /* timer hasn't expired yet; second iteration starts
+ from the same counter value as the first */
+ period = count;
+ }
+
+ tilem_z80_set_timer(calc, TILEM_TIMER_USER1 + n, count, period,
+ (calc->usertimers[n].frequency & 0x80 ? 0 : 1));
+}
+
+byte tilem_user_timer_get_value(TilemCalc* calc, int n)
+{
+ TilemUserTimer* tmr = &calc->usertimers[n];
+ dword period;
+
+ if (!tilem_z80_timer_running(calc, TILEM_TIMER_USER1 + n))
+ return tmr->loopvalue;
+
+ period = get_overflow_duration(tmr);
+
+ if (tmr->frequency & 0x80) {
+ dword t = tilem_z80_get_timer_clocks
+ (calc, TILEM_TIMER_USER1 + n);
+ return ((t * 256) / period) % 256;
+ }
+ else {
+ qword t = tilem_z80_get_timer_microseconds
+ (calc, TILEM_TIMER_USER1 + n);
+ return ((t * 256) / period) % 256;
+ }
+}
+
+void tilem_user_timer_expired(TilemCalc* calc, void* data)
+{
+ int n = TILEM_PTR_TO_DWORD(data);
+ TilemUserTimer* tmr = &calc->usertimers[n];
+
+ /* input value 0 means loop indefinitely (don't set flags) */
+ if (!tmr->loopvalue) {
+ return;
+ }
+
+ /* if timer has already finished, set "overflow" flag */
+ if (tmr->status & TILEM_USER_TIMER_FINISHED) {
+ tmr->status |= TILEM_USER_TIMER_OVERFLOW;
+ }
+
+ /* set "finished" flag */
+ tmr->status |= TILEM_USER_TIMER_FINISHED;
+
+ /* generate interrupt if appropriate */
+ if ((tmr->status & TILEM_USER_TIMER_INTERRUPT)
+ && (!(tmr->status & TILEM_USER_TIMER_NO_HALT_INT)
+ || !calc->z80.halted)) {
+ calc->z80.interrupts |= (TILEM_INTERRUPT_USER_TIMER1 << n);
+ }
+
+ if (tmr->status & TILEM_USER_TIMER_LOOP) {
+ /* timer will overflow the next time it expires
+ (unless user writes to the mode port before
+ then) */
+ tilem_z80_set_timer_period(calc, TILEM_TIMER_USER1 + n,
+ get_overflow_duration(tmr));
+ }
+}
diff --git a/tool/tilem-src/emu/x1/x1.h b/tool/tilem-src/emu/x1/x1.h
new file mode 100644
index 0000000..eecb19e
--- /dev/null
+++ b/tool/tilem-src/emu/x1/x1.h
@@ -0,0 +1,53 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifndef _TILEM_X1_H
+#define _TILEM_X1_H
+
+enum {
+ HW_VERSION, /* HW version: 0 = unknown
+ 1 = original HW (1990-1992)
+ 2 = revised HW (1992-1996) */
+ PORT2, /* memory mapping control (new HW) */
+ PORT3, /* mask of enabled interrupts */
+ PORT4, /* mapping mode, timer control */
+ PORT5, /* memory mapping bank A (old HW) */
+ PORT6, /* memory mapping bank B (old HW) */
+ NUM_HW_REGS
+};
+
+#define HW_REG_NAMES { "hw_version", "port2", "port3", "port4", "port5", "port6" }
+
+#define TIMER_INT (TILEM_NUM_SYS_TIMERS + 1)
+#define NUM_HW_TIMERS 1
+
+#define HW_TIMER_NAMES { "int" }
+
+void x1_reset(TilemCalc* calc);
+byte x1_z80_in(TilemCalc* calc, dword port);
+void x1_z80_out(TilemCalc* calc, dword port, byte value);
+void x1_z80_ptimer(TilemCalc* calc, int id);
+void x1_z80_wrmem(TilemCalc* calc, dword addr, byte value);
+byte x1_z80_rdmem(TilemCalc* calc, dword addr);
+dword x1_mem_ltop(TilemCalc* calc, dword addr);
+dword x1_mem_ptol(TilemCalc* calc, dword addr);
+void x1_get_lcd(TilemCalc* calc, byte* data);
+
+#endif
diff --git a/tool/tilem-src/emu/x1/x1_init.c b/tool/tilem-src/emu/x1/x1_init.c
new file mode 100644
index 0000000..962b4b1
--- /dev/null
+++ b/tool/tilem-src/emu/x1/x1_init.c
@@ -0,0 +1,50 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2001 Solignac Julien
+ * Copyright (C) 2004-2009 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+
+#include "x1.h"
+
+void x1_reset(TilemCalc* calc)
+{
+ calc->hwregs[PORT3] = 0x08;
+ calc->hwregs[PORT2] = 0x00;
+ calc->hwregs[PORT5] = 0x00;
+ calc->hwregs[PORT6] = 0x00;
+
+ calc->mempagemap[0] = 0x00;
+ calc->mempagemap[1] = 0x01;
+ calc->mempagemap[2] = 0x00;
+ calc->mempagemap[3] = 0x02;
+
+ if (calc->hwregs[HW_VERSION] != 2)
+ calc->lcd.rowstride = 12;
+
+ tilem_z80_set_speed(calc, 2000);
+
+ /* FIXME: measure actual frequency */
+ tilem_z80_set_timer(calc, TIMER_INT, 6000, 6000, 1);
+}
diff --git a/tool/tilem-src/emu/x1/x1_io.c b/tool/tilem-src/emu/x1/x1_io.c
new file mode 100644
index 0000000..b46977d
--- /dev/null
+++ b/tool/tilem-src/emu/x1/x1_io.c
@@ -0,0 +1,237 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2001 Solignac Julien
+ * Copyright (C) 2004-2011 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+
+#include "x1.h"
+
+byte x1_z80_in(TilemCalc* calc, dword port)
+{
+ byte v;
+
+ if (calc->hwregs[HW_VERSION] == 1)
+ port &= 7;
+
+ switch(port&0x1f) {
+ case 0x01:
+ return(tilem_keypad_read_keys(calc));
+
+ case 0x02:
+ return(calc->hwregs[PORT2]);
+
+ case 0x03:
+ v = (calc->keypad.onkeydown ? 0x00: 0x08);
+
+ if (calc->z80.interrupts & TILEM_INTERRUPT_ON_KEY)
+ v |= 0x01;
+ if (calc->z80.interrupts & TILEM_INTERRUPT_TIMER1)
+ v |= 0x02;
+
+ return(v);
+
+ case 0x05:
+ return(calc->hwregs[PORT5]);
+
+ case 0x06:
+ return(calc->hwregs[PORT6]);
+
+ case 0x10:
+ return(tilem_lcd_t6a04_status(calc));
+
+ case 0x11:
+ return(tilem_lcd_t6a04_read(calc));
+ }
+
+ tilem_warning(calc, "Input from port %x", port);
+ return(0x00);
+}
+
+
+static void setup_mapping(TilemCalc* calc)
+{
+ int pageA, pageB;
+
+ switch (calc->hwregs[HW_VERSION]) {
+ case 1:
+ if (calc->hwregs[PORT5] & 0x40)
+ pageA = 2;
+ else if (calc->hwregs[PORT5] & 1)
+ pageA = 1;
+ else
+ pageA = 0;
+
+ if (calc->hwregs[PORT6] & 0x40)
+ pageB = 2;
+ else if (calc->hwregs[PORT6] & 1)
+ pageB = 1;
+ else
+ pageB = 0;
+ break;
+
+ case 2:
+ if (calc->hwregs[PORT2] & 0x40)
+ pageA = 2;
+ else if (calc->hwregs[PORT2] & 1)
+ pageA = 1;
+ else
+ pageA = 0;
+
+ if (calc->hwregs[PORT2] & 0x80)
+ pageB = 2;
+ else if (calc->hwregs[PORT2] & 8)
+ pageB = 1;
+ else
+ pageB = 0;
+ break;
+
+ default:
+ /* unknown HW version - ignore all output values and
+ use standard mapping */
+ pageA = 1;
+ pageB = 0;
+ }
+
+ calc->mempagemap[1] = pageA;
+ calc->mempagemap[2] = pageB;
+ calc->mempagemap[3] = 2;
+}
+
+void x1_z80_out(TilemCalc* calc, dword port, byte value)
+{
+ if (!calc->hwregs[HW_VERSION] && calc->z80.r.pc.d < 0x8000) {
+ /* detect version */
+ if (port == 0x05 || port == 0x06) {
+ calc->hwregs[HW_VERSION] = 1;
+ setup_mapping(calc);
+ }
+ else if (port == 0x10 || port == 0x11) {
+ calc->lcd.rowstride = 15;
+ calc->hwregs[HW_VERSION] = 2;
+ setup_mapping(calc);
+ }
+ }
+
+ if (calc->hwregs[HW_VERSION] == 1)
+ port &= 7;
+
+ switch(port&0x1f) {
+ case 0x00:
+ calc->lcd.addr = ((value & 0x1f) << 8);
+ calc->z80.lastlcdwrite = calc->z80.clock;
+ break;
+
+ case 0x01:
+ tilem_keypad_set_group(calc, value);
+ break;
+
+ case 0x02:
+ calc->hwregs[PORT2] = value;
+ if (calc->hwregs[HW_VERSION] != 2)
+ calc->lcd.contrast = 16 + (value & 0x1f);
+ setup_mapping(calc);
+ break;
+
+ case 0x03:
+ if (value & 0x01) {
+ calc->keypad.onkeyint = 1;
+ }
+ else {
+ calc->z80.interrupts &= ~TILEM_INTERRUPT_ON_KEY;
+ calc->keypad.onkeyint = 0;
+ }
+
+ if (!(value & 0x02)) {
+ calc->z80.interrupts &= ~TILEM_INTERRUPT_TIMER1;
+ }
+
+ calc->hwregs[PORT3] = value;
+ calc->lcd.active = calc->poweronhalt = ((value & 8) >> 3);
+ break;
+
+ case 0x04:
+ calc->hwregs[PORT4] = value;
+
+ if (calc->hwregs[HW_VERSION] == 1) {
+ switch (value & 0x18) {
+ case 0x00:
+ calc->lcd.rowstride = 10;
+ break;
+
+ case 0x08:
+ calc->lcd.rowstride = 12;
+ break;
+
+ case 0x10:
+ calc->lcd.rowstride = 16;
+ break;
+
+ case 0x18:
+ calc->lcd.rowstride = 20;
+ break;
+ }
+ calc->z80.lastlcdwrite = calc->z80.clock;
+ }
+ break;
+
+ case 0x05:
+ calc->hwregs[PORT5] = value;
+ setup_mapping(calc);
+ break;
+
+ case 0x06:
+ calc->hwregs[PORT6] = value;
+ setup_mapping(calc);
+ break;
+
+ case 0x10:
+ tilem_lcd_t6a04_control(calc, value);
+ break;
+
+ case 0x11:
+ tilem_lcd_t6a04_write(calc, value);
+ break;
+ }
+
+ return;
+}
+
+void x1_z80_ptimer(TilemCalc* calc, int id)
+{
+ switch (id) {
+ case TIMER_INT:
+ if (calc->hwregs[PORT3] & 0x02)
+ calc->z80.interrupts |= TILEM_INTERRUPT_TIMER1;
+ break;
+ }
+}
+
+void x1_get_lcd(TilemCalc* calc, byte* data)
+{
+ if (calc->hwregs[HW_VERSION] == 2)
+ tilem_lcd_t6a04_get_data(calc, data);
+ else
+ tilem_lcd_t6a43_get_data(calc, data);
+}
diff --git a/tool/tilem-src/emu/x1/x1_memory.c b/tool/tilem-src/emu/x1/x1_memory.c
new file mode 100644
index 0000000..34c860e
--- /dev/null
+++ b/tool/tilem-src/emu/x1/x1_memory.c
@@ -0,0 +1,71 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2001 Solignac Julien
+ * Copyright (C) 2004-2011 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+
+#include "x1.h"
+
+void x1_z80_wrmem(TilemCalc* calc, dword A, byte v)
+{
+ dword pa = 0x4000 * calc->mempagemap[(A)>>14] + (A & 0x3FFF);
+
+ if (pa >= 0x8000) {
+ *(calc->mem + 0x8000 + (pa & 0x1fff)) = v;
+
+ if ((((pa - 0x8000 - calc->lcd.addr) >> 6)
+ < (unsigned) calc->lcd.rowstride)
+ && calc->hwregs[HW_VERSION] < 2)
+ calc->z80.lastlcdwrite = calc->z80.clock;
+ }
+}
+
+byte x1_z80_rdmem(TilemCalc* calc, dword A)
+{
+ dword pa = 0x4000 * calc->mempagemap[(A)>>14] + (A & 0x3FFF);
+
+ if (pa >= 0x8000)
+ return (*(calc->mem + 0x8000 + (pa & 0x1fff)));
+ else
+ return (*(calc->mem + (pa & 0x7fff)));
+}
+
+dword x1_mem_ltop(TilemCalc* calc, dword A)
+{
+ dword pa = 0x4000 * calc->mempagemap[(A)>>14] + (A & 0x3FFF);
+
+ if (pa >= 0x8000)
+ return (0x8000 + (pa & 0x1fff));
+ else
+ return (pa);
+}
+
+dword x1_mem_ptol(TilemCalc* calc TILEM_ATTR_UNUSED, dword A)
+{
+ if (A & 0x8000)
+ return (0xE000 + (A & 0x1fff));
+ else
+ return (A);
+}
diff --git a/tool/tilem-src/emu/x1/x1_subcore.c b/tool/tilem-src/emu/x1/x1_subcore.c
new file mode 100644
index 0000000..2f82856
--- /dev/null
+++ b/tool/tilem-src/emu/x1/x1_subcore.c
@@ -0,0 +1,56 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2001 Solignac Julien
+ * Copyright (C) 2004-2009 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+
+#include "x1.h"
+
+static const char* hwregnames[NUM_HW_REGS] = HW_REG_NAMES;
+
+static const char* hwtimernames[NUM_HW_TIMERS] = HW_TIMER_NAMES;
+
+static const char* keynames[64] = {
+ "Down", "Left", "Right", "Up", 0, 0, 0, 0,
+ "Enter", "Add", "Sub", "Mul", "Div", "Power", "Clear", 0,
+ "Chs", "3", "6", "9", "RParen", "Tan", "Vars", 0,
+ "DecPnt", "2", "5", "8", "LParen", "Cos", "Prgm", "Mode",
+ "0", "1", "4", "7", "EE", "Sin", "Matrix", "Graphvar",
+ "On", "Store", "Ln", "Log", "Square", "Recip", "Math", "Alpha",
+ "Graph", "Trace", "Zoom", "Range", "YEqu", "2nd", "Ins", "Del",
+ 0, 0, 0, 0, 0, 0, 0, 0};
+
+const TilemHardware hardware_ti81 = {
+ '1', "ti81", "TI-81", TILEM_CALC_HAS_T6A04,
+ 96, 64, 0x8000, 0x2000, 15 * 64, 0x40,
+ 0, NULL, 0,
+ NUM_HW_REGS, hwregnames,
+ NUM_HW_TIMERS, hwtimernames,
+ keynames,
+ x1_reset, NULL,
+ x1_z80_in, x1_z80_out,
+ x1_z80_wrmem, x1_z80_rdmem, x1_z80_rdmem, NULL,
+ x1_z80_ptimer, x1_get_lcd,
+ x1_mem_ltop, x1_mem_ptol };
diff --git a/tool/tilem-src/emu/x2/x2.h b/tool/tilem-src/emu/x2/x2.h
new file mode 100644
index 0000000..cfa6093
--- /dev/null
+++ b/tool/tilem-src/emu/x2/x2.h
@@ -0,0 +1,51 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2009 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifndef _TILEM_X2_H
+#define _TILEM_X2_H
+
+enum {
+ HW_VERSION, /* HW version: 0 = unknown
+ 1 = original HW (1993-2000)
+ 2 = revised HW (2001-2003) */
+ PORT0, /* port 0 (link port control) */
+ PORT2, /* port 2 (memory mapping) */
+ PORT3, /* mask of enabled interrupts */
+ PORT4, /* mapping mode + timer speed */
+ NUM_HW_REGS
+};
+
+#define HW_REG_NAMES { "hw_version", "port0", "port2", "port3", "port4" }
+
+#define TIMER_INT (TILEM_NUM_SYS_TIMERS + 1)
+#define NUM_HW_TIMERS 1
+
+#define HW_TIMER_NAMES { "int" }
+
+void x2_reset(TilemCalc* calc);
+byte x2_z80_in(TilemCalc* calc, dword port);
+void x2_z80_out(TilemCalc* calc, dword port, byte value);
+void x2_z80_ptimer(TilemCalc* calc, int id);
+void x2_z80_wrmem(TilemCalc* calc, dword addr, byte value);
+byte x2_z80_rdmem(TilemCalc* calc, dword addr);
+dword x2_mem_ltop(TilemCalc* calc, dword addr);
+dword x2_mem_ptol(TilemCalc* calc, dword addr);
+
+#endif
diff --git a/tool/tilem-src/emu/x2/x2_init.c b/tool/tilem-src/emu/x2/x2_init.c
new file mode 100644
index 0000000..1e83119
--- /dev/null
+++ b/tool/tilem-src/emu/x2/x2_init.c
@@ -0,0 +1,46 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2001 Solignac Julien
+ * Copyright (C) 2004-2009 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+
+#include "x2.h"
+
+void x2_reset(TilemCalc* calc)
+{
+ calc->hwregs[PORT2] = 0xF8;
+ calc->hwregs[PORT3] = 0x0B;
+ calc->hwregs[PORT4] = 0x00;
+
+ calc->mempagemap[0] = 0x00;
+ calc->mempagemap[1] = 0x00;
+ calc->mempagemap[2] = 0x09;
+ calc->mempagemap[3] = 0x08;
+
+ tilem_z80_set_speed(calc, 6000);
+
+ /* FIXME: measure actual frequency */
+ tilem_z80_set_timer(calc, TIMER_INT, 1000, 9259, 1);
+}
diff --git a/tool/tilem-src/emu/x2/x2_io.c b/tool/tilem-src/emu/x2/x2_io.c
new file mode 100644
index 0000000..f8e3121
--- /dev/null
+++ b/tool/tilem-src/emu/x2/x2_io.c
@@ -0,0 +1,207 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2001 Solignac Julien
+ * Copyright (C) 2004-2009 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+
+#include "x2.h"
+
+byte x2_z80_in(TilemCalc* calc, dword port)
+{
+ static const byte battlevel[4] = { 33, 39, 36, 43 };
+ byte v, b;
+
+ switch(port&0xff) {
+ case 0x00:
+ v = tilem_linkport_get_lines(calc);
+
+ if (calc->hwregs[HW_VERSION] == 1) {
+ /* HW version 1 uses separate PCR/PDR, as the
+ TI-85 does. */
+ b = (calc->hwregs[PORT0] >> 4) | 0xf0;
+ return ((calc->hwregs[PORT0] & b) | (v & ~b));
+ }
+ else {
+ /* HW version 2 uses a TI-83-like interface.
+ (Do the same if version is unknown, because
+ most code written for HW version 1 will
+ work fine with these values.) */
+ return (0xc0 | (v * 5));
+ }
+
+ case 0x01:
+ return(tilem_keypad_read_keys(calc));
+
+ case 0x02:
+ return(calc->hwregs[PORT2]);
+
+ case 0x03:
+ v = (calc->keypad.onkeydown ? 0x00: 0x08);
+
+ if (calc->z80.interrupts & TILEM_INTERRUPT_ON_KEY)
+ v |= 0x01;
+ if (calc->z80.interrupts & TILEM_INTERRUPT_TIMER1)
+ v |= 0x02;
+
+ return(v);
+
+ case 0x10:
+ return(tilem_lcd_t6a04_status(calc));
+
+ case 0x11:
+ return(tilem_lcd_t6a04_read(calc));
+
+ case 0x14:
+ /* FIXME: determine value of this port on old
+ hardware, and the values of bits 1-7. (As on
+ TI-83, probably mirrors port 0 in both cases.) */
+ b = battlevel[calc->hwregs[PORT4] >> 6];
+ return(calc->battery >= b ? 1 : 0);
+ }
+
+ tilem_warning(calc, "Input from port %x", port);
+ return(0x00);
+}
+
+
+static void setup_mapping(TilemCalc* calc)
+{
+ unsigned int pageA, pageB;
+
+ /* FIXME: this is all rather hypothetical and untested, but it
+ makes sense based on how the TI-83 works */
+
+ if (calc->hwregs[PORT2] & 0x40) {
+ pageA = (0x08 | (calc->hwregs[PORT2] & 1));
+ }
+ else {
+ pageA = (calc->hwregs[PORT2] & 7);
+ }
+
+ if (calc->hwregs[PORT2] & 0x80) {
+ pageB = (0x08 | ((calc->hwregs[PORT2] >> 3) & 1));
+ }
+ else {
+ pageB = ((calc->hwregs[PORT2] >> 3) & 7);
+ }
+
+ if (calc->hwregs[PORT4] & 1) {
+ calc->mempagemap[1] = (pageA & ~1);
+ calc->mempagemap[2] = (pageA | 1);
+ calc->mempagemap[3] = pageB;
+ }
+ else {
+ calc->mempagemap[1] = pageA;
+ calc->mempagemap[2] = pageB;
+ calc->mempagemap[3] = 0x08;
+ }
+}
+
+void x2_z80_out(TilemCalc* calc, dword port, byte value)
+{
+ switch(port&0xff) {
+ case 0x00:
+ calc->hwregs[PORT0] = value;
+
+ if (calc->hwregs[HW_VERSION] == 1) {
+ /* HW version 1 */
+ value = (((value >> 6) & (value >> 2))
+ | ((value >> 4) & ~value));
+ }
+ else if (calc->hwregs[HW_VERSION] == 0) {
+ /* HW version unknown: auto-detect */
+ if ((value & 0xc3) == 0xc0) {
+ value = ((value >> 2) | (value >> 4));
+ }
+ }
+
+ tilem_linkport_set_lines(calc, value);
+ break;
+
+ case 0x01:
+ tilem_keypad_set_group(calc, value);
+ break;
+
+ case 0x02:
+ calc->hwregs[PORT2] = value;
+ setup_mapping(calc);
+ break;
+
+ case 0x03:
+ if (value & 0x01) {
+ calc->keypad.onkeyint = 1;
+ }
+ else {
+ calc->z80.interrupts &= ~TILEM_INTERRUPT_ON_KEY;
+ calc->keypad.onkeyint = 0;
+ }
+
+ if (!(value & 0x02)) {
+ calc->z80.interrupts &= ~TILEM_INTERRUPT_TIMER1;
+ }
+
+ calc->poweronhalt = ((value & 8) >> 3);
+ calc->hwregs[PORT3] = value;
+ break;
+
+ case 0x04:
+ calc->hwregs[PORT4] = value;
+
+ /* Detect hardware version */
+ if (calc->z80.r.pc.d < 0x4000) {
+ if (value & 0x10)
+ calc->hwregs[HW_VERSION] = 1;
+ else
+ calc->hwregs[HW_VERSION] = 2;
+ }
+
+ /* FIXME: implement changing interrupt frequencies --
+ somebody needs to measure them. Also check if bit
+ 4 works as on 83. */
+
+ setup_mapping(calc);
+ break;
+
+ case 0x10:
+ tilem_lcd_t6a04_control(calc, value);
+ break;
+
+ case 0x11:
+ tilem_lcd_t6a04_write(calc, value);
+ break;
+ }
+
+ return;
+}
+
+void x2_z80_ptimer(TilemCalc* calc, int id)
+{
+ switch (id) {
+ case TIMER_INT:
+ if (calc->hwregs[PORT3] & 0x02)
+ calc->z80.interrupts |= TILEM_INTERRUPT_TIMER1;
+ break;
+ }
+}
diff --git a/tool/tilem-src/emu/x2/x2_memory.c b/tool/tilem-src/emu/x2/x2_memory.c
new file mode 100644
index 0000000..9829f4f
--- /dev/null
+++ b/tool/tilem-src/emu/x2/x2_memory.c
@@ -0,0 +1,70 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2001 Solignac Julien
+ * Copyright (C) 2004-2009 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include
+#include
+
+#include "x2.h"
+
+#include
+
+void x2_z80_wrmem(TilemCalc* calc, dword A, byte v)
+{
+ dword pa = 0x4000 * calc->mempagemap[(A)>>14] + (A & 0x3FFF);
+
+ if (pa >= 0x28000)
+ abort();
+
+ if (pa >= 0x20000) {
+ *(calc->mem + pa) = v;
+ }
+}
+
+
+byte x2_z80_rdmem(TilemCalc* calc, dword A)
+{
+ dword pa = 0x4000 * calc->mempagemap[(A)>>14] + (A & 0x3FFF);
+ return (*(calc->mem + pa));
+}
+
+dword x2_mem_ltop(TilemCalc* calc, dword A)
+{
+ byte page = calc->mempagemap[A >> 14];
+ return ((page << 14) | (A & 0x3fff));
+}
+
+dword x2_mem_ptol(TilemCalc* calc, dword A)
+{
+ byte page = A >> 14;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (calc->mempagemap[i] == page) {
+ return ((i << 14) | (A & 0x3fff));
+ }
+ }
+
+ return (0xffffffff);
+}
diff --git a/tool/tilem-src/emu/x2/x2_subcore.c b/tool/tilem-src/emu/x2/x2_subcore.c
new file mode 100644
index 0000000..bdb19fe
--- /dev/null
+++ b/tool/tilem-src/emu/x2/x2_subcore.c
@@ -0,0 +1,57 @@
+/*
+ * libtilemcore - Graphing calculator emulation library
+ *
+ * Copyright (C) 2001 Solignac Julien
+ * Copyright (C) 2004-2009 Benjamin Moody
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * .
+ */
+
+#ifdef HAVE_CONFIG_H
+# include
+#endif
+
+#include