check in rabbitsign/tilem
2
.gitignore
vendored
|
@ -6,3 +6,5 @@ main.8xk
|
||||||
main.bin
|
main.bin
|
||||||
|
|
||||||
ti83pv116.sav
|
ti83pv116.sav
|
||||||
|
|
||||||
|
tool/rabbitsign
|
||||||
|
|
24
Makefile
|
@ -1,15 +1,19 @@
|
||||||
|
|
||||||
CC=sdcc
|
SDCC=sdcc
|
||||||
CFLAGS=-Ilib83 -c -mz80 --std-sdcc2x --no-std-crt0 --reserve-regs-iy --opt-code-size
|
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 \
|
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 \
|
getchar.rel put_int.rel ctype.rel memcpy.rel memset.rel memmove.rel memcmp.rel \
|
||||||
strcpy.rel strlen.rel strncpy.rel \
|
strcpy.rel strlen.rel strncpy.rel \
|
||||||
main.rel
|
main.rel
|
||||||
|
|
||||||
.PHONY: all clean try
|
.PHONY: all clean try init
|
||||||
all: main.8xk
|
all: main.8xk
|
||||||
|
|
||||||
|
init:
|
||||||
|
@echo "Compiling rabbitsign..."
|
||||||
|
@$(CC) tool/rabbitsign-src/*.c -o tool/rabbitsign -O2 -g -w -DPROTOTYPES
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -f obj/* main.ihx main.bin main.8xk
|
@rm -f obj/* main.ihx main.bin main.8xk
|
||||||
|
|
||||||
|
@ -17,16 +21,16 @@ try: main.8xk
|
||||||
@tilem2 --rom=ti83pv116.bin
|
@tilem2 --rom=ti83pv116.bin
|
||||||
|
|
||||||
%.rel: lib83/%.c
|
%.rel: lib83/%.c
|
||||||
@echo "(lib) CC $<"
|
@echo "(lib) SDCC $<"
|
||||||
@$(CC) $(CFLAGS) $< -o obj/$@
|
@$(SDCC) $(SDCCFLAGS) $< -o obj/$@
|
||||||
|
|
||||||
%.rel: %.c
|
%.rel: %.c
|
||||||
@echo "CC $<"
|
@echo "SDCC $<"
|
||||||
@$(CC) $(CFLAGS) $< -o obj/$@
|
@$(SDCC) $(SDCCFLAGS) $< -o obj/$@
|
||||||
|
|
||||||
obj/main.ihx: $(OBJS)
|
obj/main.ihx: $(OBJS)
|
||||||
@echo "LD $@"
|
@echo "SDCCLD $@"
|
||||||
@cd obj && $(CC) -mz80 --no-std-crt0 --code-loc 0x4000 --code-size 0x4000 --xram-loc 0x9D95 --xram-size 0x6060 $^ -o ../$@ && cd ..
|
@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
|
main.bin: obj/main.ihx
|
||||||
@echo "IHX->BIN $@"
|
@echo "IHX->BIN $@"
|
||||||
|
@ -35,5 +39,5 @@ main.bin: obj/main.ihx
|
||||||
|
|
||||||
main.8xk: main.bin
|
main.8xk: main.bin
|
||||||
@echo "SIGN $@"
|
@echo "SIGN $@"
|
||||||
@rabbitsign -P -p -t 8xk -g $<
|
@tool/rabbitsign -P -p -t 8xk -g $<
|
||||||
|
|
||||||
|
|
22
README.md
|
@ -4,11 +4,25 @@ A C programming SDK for the TI-83 calculator. Includes pre-configured build syst
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- SDCC
|
- A GNU/Linux system.
|
||||||
- GNU Make
|
|
||||||
- TilEm
|
|
||||||
- RabbitSign
|
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
WIP.
|
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
|
||||||
|
```
|
||||||
|
|
445
tool/rabbitsign-src/app8x.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
297
tool/rabbitsign-src/app9x.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
85
tool/rabbitsign-src/apps.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
241
tool/rabbitsign-src/autokey.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
# include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
# 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;
|
||||||
|
}
|
47
tool/rabbitsign-src/autokeys.h
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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 }};
|
112
tool/rabbitsign-src/cmdline.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
# 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;
|
||||||
|
}
|
||||||
|
}
|
131
tool/rabbitsign-src/error.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
# 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);
|
||||||
|
}
|
118
tool/rabbitsign-src/graphlink.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TIME_WITH_SYS_TIME
|
||||||
|
# include <sys/time.h>
|
||||||
|
# include <time.h>
|
||||||
|
#else
|
||||||
|
# ifdef TM_IN_SYS_TIME
|
||||||
|
# include <sys/time.h>
|
||||||
|
# else
|
||||||
|
# include <time.h>
|
||||||
|
# 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;
|
||||||
|
}
|
||||||
|
|
169
tool/rabbitsign-src/header.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
520
tool/rabbitsign-src/input.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
# 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;
|
||||||
|
}
|
||||||
|
|
111
tool/rabbitsign-src/internal.h
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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__ */
|
234
tool/rabbitsign-src/keys.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
# 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;
|
||||||
|
}
|
||||||
|
}
|
419
tool/rabbitsign-src/md5.c
Normal file
|
@ -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 <drepper@gnu.ai.mit.edu>, 1995. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#if STDC_HEADERS || defined _LIBC
|
||||||
|
# include <stdlib.h>
|
||||||
|
# include <string.h>
|
||||||
|
#else
|
||||||
|
# ifndef HAVE_MEMCPY
|
||||||
|
# define memcpy(d, s, n) bcopy ((s), (d), (n))
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "md5.h"
|
||||||
|
|
||||||
|
#ifdef _LIBC
|
||||||
|
# include <endian.h>
|
||||||
|
# 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;
|
||||||
|
}
|
146
tool/rabbitsign-src/md5.h
Normal file
|
@ -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 <stdio.h>
|
||||||
|
|
||||||
|
#if defined HAVE_LIMITS_H || _LIBC
|
||||||
|
# include <limits.h>
|
||||||
|
#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 <sys/types.h>
|
||||||
|
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 <limits.h>) 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
|
73
tool/rabbitsign-src/mem.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
# include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
# 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;
|
||||||
|
}
|
1026
tool/rabbitsign-src/mpz.c
Normal file
123
tool/rabbitsign-src/mpz.h
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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
|
298
tool/rabbitsign-src/os8x.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
# 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;
|
||||||
|
}
|
39
tool/rabbitsign-src/output.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
248
tool/rabbitsign-src/output8x.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
# 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);
|
||||||
|
}
|
||||||
|
|
96
tool/rabbitsign-src/output9x.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
# 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;
|
||||||
|
}
|
||||||
|
|
187
tool/rabbitsign-src/program.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
# 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;
|
||||||
|
}
|
463
tool/rabbitsign-src/rabbitsign.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
# include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
# 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 <name>.app\n",
|
||||||
|
" or <name>.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;
|
||||||
|
}
|
342
tool/rabbitsign-src/rabbitsign.h
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RABBITSIGN_H__
|
||||||
|
#define __RABBITSIGN_H__
|
||||||
|
|
||||||
|
#ifdef HAVE_GMP_H
|
||||||
|
# include <gmp.h>
|
||||||
|
# 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__ */
|
425
tool/rabbitsign-src/rabin.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
137
tool/rabbitsign-src/rsa.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
161
tool/rabbitsign-src/typestr.c
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
# 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";
|
||||||
|
}
|
||||||
|
}
|
316
tool/tilem-src/CHANGELOG
Normal file
|
@ -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.
|
||||||
|
*/
|
||||||
|
|
674
tool/tilem-src/COPYING
Normal file
|
@ -0,0 +1,674 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
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.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
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
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
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
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
53
tool/tilem-src/INSTALL
Normal file
|
@ -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.
|
270
tool/tilem-src/KEYS
Normal file
|
@ -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]
|
91
tool/tilem-src/Makefile.in
Normal file
|
@ -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
|
73
tool/tilem-src/NEWS
Normal file
|
@ -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.
|
92
tool/tilem-src/README
Normal file
|
@ -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 <tilem-devel@lists.sourceforge.net>.
|
||||||
|
Please let us know of any problems you encounter, or ideas for how we
|
||||||
|
could make TilEm better.
|
37
tool/tilem-src/THANKS
Normal file
|
@ -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.
|
7
tool/tilem-src/TODO
Normal file
|
@ -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)
|
||||||
|
|
||||||
|
|
173
tool/tilem-src/aclocal.m4
vendored
Normal file
|
@ -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 <scott@netsplit.com>.
|
||||||
|
#
|
||||||
|
# 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 <http://pkg-config.freedesktop.org/>.])[]dnl
|
||||||
|
])
|
||||||
|
else
|
||||||
|
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
|
||||||
|
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
$3
|
||||||
|
fi[]dnl
|
||||||
|
])# PKG_CHECK_MODULES
|
||||||
|
|
91
tool/tilem-src/config.h.in
Normal file
|
@ -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 <inttypes.h> header file. */
|
||||||
|
#undef HAVE_INTTYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
|
#undef HAVE_MEMORY_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
|
#undef HAVE_STDINT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
|
#undef HAVE_STDLIB_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
|
#undef HAVE_STRINGS_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <string.h> header file. */
|
||||||
|
#undef HAVE_STRING_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
|
#undef HAVE_SYS_STAT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/types.h> 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 <unistd.h> 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
|
6127
tool/tilem-src/configure
vendored
Executable file
172
tool/tilem-src/configure.ac
Normal file
|
@ -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 <http://lpg.ticalc.org/prj_tilp/>.
|
||||||
|
|
||||||
|
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
|
114
tool/tilem-src/data/Makefile.in
Normal file
|
@ -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
|
10
tool/tilem-src/data/desktop/tilem2.desktop
Normal file
|
@ -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;
|
322
tool/tilem-src/data/desktop/tilem2.xml
Normal file
|
@ -0,0 +1,322 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
||||||
|
<mime-type type="application/x-tigroup">
|
||||||
|
<sub-class-of type="application/zip" />
|
||||||
|
<comment>TI calculator group file</comment>
|
||||||
|
<glob pattern="*.tig" />
|
||||||
|
</mime-type>
|
||||||
|
|
||||||
|
<mime-type type="application/x-ti73-variables">
|
||||||
|
<comment>TI-73 variable</comment>
|
||||||
|
<glob pattern="*.73g" />
|
||||||
|
<glob pattern="*.73n" />
|
||||||
|
<glob pattern="*.73l" />
|
||||||
|
<glob pattern="*.73m" />
|
||||||
|
<glob pattern="*.73y" />
|
||||||
|
<glob pattern="*.73e" />
|
||||||
|
<glob pattern="*.73s" />
|
||||||
|
<glob pattern="*.73i" />
|
||||||
|
<glob pattern="*.73d" />
|
||||||
|
<glob pattern="*.73w" />
|
||||||
|
<glob pattern="*.73z" />
|
||||||
|
<glob pattern="*.73t" />
|
||||||
|
<glob pattern="*.73v" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI73**\x1a\x0a\x00">
|
||||||
|
<match type="little16" offset="55" value="0x000b" />
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/x-ti73-program">
|
||||||
|
<sub-class-of type="application/x-ti73-variables" />
|
||||||
|
<comment>TI-73 program</comment>
|
||||||
|
<glob pattern="*.73p" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI73**\x1a\x0a\x00">
|
||||||
|
<match type="little16" offset="55" value="0x000b">
|
||||||
|
<match type="byte" offset="59" value="0x05" />
|
||||||
|
<match type="byte" offset="59" value="0x06" />
|
||||||
|
</match>
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/x-ti73-backup">
|
||||||
|
<comment>TI-73 memory backup</comment>
|
||||||
|
<glob pattern="*.73b" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI73**\x1a\x0a\x00">
|
||||||
|
<match type="little16" offset="55" value="0x0009">
|
||||||
|
<match type="byte" offset="59" value="0x13" />
|
||||||
|
</match>
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/x-ti73-app">
|
||||||
|
<comment>TI-73 Flash application</comment>
|
||||||
|
<glob pattern="*.73k" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TIFL**">
|
||||||
|
<match type="big16" offset="48" value="0x7424" />
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/x-ti73-os">
|
||||||
|
<comment>TI-73 operating system</comment>
|
||||||
|
<glob pattern="*.73u" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TIFL**">
|
||||||
|
<match type="big16" offset="48" value="0x7423" />
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
|
||||||
|
<mime-type type="application/x-ti81-program">
|
||||||
|
<comment>TI-81 program</comment>
|
||||||
|
<glob pattern="*.prg" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI81**\x00\x6e" />
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
|
||||||
|
<mime-type type="application/x-ti82-variables">
|
||||||
|
<comment>TI-82 variable</comment>
|
||||||
|
<glob pattern="*.82g" />
|
||||||
|
<glob pattern="*.82n" />
|
||||||
|
<glob pattern="*.82l" />
|
||||||
|
<glob pattern="*.82y" />
|
||||||
|
<glob pattern="*.82e" />
|
||||||
|
<glob pattern="*.82s" />
|
||||||
|
<glob pattern="*.82i" />
|
||||||
|
<glob pattern="*.82d" />
|
||||||
|
<glob pattern="*.82w" />
|
||||||
|
<glob pattern="*.82z" />
|
||||||
|
<glob pattern="*.82t" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI82**\x1a\x0a\x00">
|
||||||
|
<match type="little16" offset="55" value="0x000b" />
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/x-ti82-program">
|
||||||
|
<sub-class-of type="application/x-ti82-variables" />
|
||||||
|
<comment>TI-82 program</comment>
|
||||||
|
<glob pattern="*.82p" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI82**\x1a\x0a\x00">
|
||||||
|
<match type="little16" offset="55" value="0x000b">
|
||||||
|
<match type="byte" offset="59" value="0x05" />
|
||||||
|
<match type="byte" offset="59" value="0x06" />
|
||||||
|
</match>
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/x-ti82-backup">
|
||||||
|
<comment>TI-82 memory backup</comment>
|
||||||
|
<glob pattern="*.82b" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI82**\x1a\x0a\x00">
|
||||||
|
<match type="little16" offset="55" value="0x0009">
|
||||||
|
<match type="byte" offset="59" value="0x0f" />
|
||||||
|
</match>
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
|
||||||
|
<mime-type type="application/x-ti83-variables">
|
||||||
|
<comment>TI-83 variable</comment>
|
||||||
|
<glob pattern="*.83g" />
|
||||||
|
<glob pattern="*.83n" />
|
||||||
|
<glob pattern="*.83l" />
|
||||||
|
<glob pattern="*.83m" />
|
||||||
|
<glob pattern="*.83y" />
|
||||||
|
<glob pattern="*.83e" />
|
||||||
|
<glob pattern="*.83s" />
|
||||||
|
<glob pattern="*.83i" />
|
||||||
|
<glob pattern="*.83d" />
|
||||||
|
<glob pattern="*.83c" />
|
||||||
|
<glob pattern="*.83w" />
|
||||||
|
<glob pattern="*.83z" />
|
||||||
|
<glob pattern="*.83t" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI83**\x1a\x0a\x00">
|
||||||
|
<match type="little16" offset="55" value="0x000b" />
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/x-ti83-program">
|
||||||
|
<sub-class-of type="application/x-ti83-variables" />
|
||||||
|
<comment>TI-83 program</comment>
|
||||||
|
<glob pattern="*.83p" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI83**\x1a\x0a\x00">
|
||||||
|
<match type="little16" offset="55" value="0x000b">
|
||||||
|
<match type="byte" offset="59" value="0x05" />
|
||||||
|
<match type="byte" offset="59" value="0x06" />
|
||||||
|
</match>
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/x-ti83-backup">
|
||||||
|
<comment>TI-83 memory backup</comment>
|
||||||
|
<glob pattern="*.83b" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI83**\x1a\x0a\x00">
|
||||||
|
<match type="little16" offset="55" value="0x0009">
|
||||||
|
<match type="byte" offset="59" value="0x13" />
|
||||||
|
</match>
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
|
||||||
|
<mime-type type="application/x-ti83plus-variables">
|
||||||
|
<comment>TI-83/84 Plus variable</comment>
|
||||||
|
<glob pattern="*.8xg" />
|
||||||
|
<glob pattern="*.8xn" />
|
||||||
|
<glob pattern="*.8xl" />
|
||||||
|
<glob pattern="*.8xm" />
|
||||||
|
<glob pattern="*.8xy" />
|
||||||
|
<glob pattern="*.8xe" />
|
||||||
|
<glob pattern="*.8xs" />
|
||||||
|
<glob pattern="*.8xi" />
|
||||||
|
<glob pattern="*.8xd" />
|
||||||
|
<glob pattern="*.8xc" />
|
||||||
|
<glob pattern="*.8xw" />
|
||||||
|
<glob pattern="*.8xz" />
|
||||||
|
<glob pattern="*.8xt" />
|
||||||
|
<glob pattern="*.8xv" />
|
||||||
|
<glob pattern="*.8xo" />
|
||||||
|
<glob pattern="*.8xgrp" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI83F*\x1a\x0a\x00">
|
||||||
|
<match type="little16" offset="55" value="0x000d" />
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/x-ti83plus-program">
|
||||||
|
<sub-class-of type="application/x-ti83plus-variables" />
|
||||||
|
<comment>TI-83/84 Plus program</comment>
|
||||||
|
<glob pattern="*.8xp" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI83F*\x1a\x0a\x00">
|
||||||
|
<match type="little16" offset="55" value="0x000d">
|
||||||
|
<match type="byte" offset="59" value="0x05" />
|
||||||
|
<match type="byte" offset="59" value="0x06" />
|
||||||
|
</match>
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/x-ti83plus-app">
|
||||||
|
<comment>TI-83/84 Plus Flash application</comment>
|
||||||
|
<glob pattern="*.8xk" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TIFL**">
|
||||||
|
<match type="big16" offset="48" value="0x7324" />
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/x-ti83plus-os">
|
||||||
|
<comment>TI-83/84 Plus operating system</comment>
|
||||||
|
<glob pattern="*.8xu" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TIFL**">
|
||||||
|
<match type="big16" offset="48" value="0x7323" />
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
|
||||||
|
<mime-type type="application/x-ti85-variables">
|
||||||
|
<comment>TI-85 variable</comment>
|
||||||
|
<glob pattern="*.85g" />
|
||||||
|
<glob pattern="*.85n" />
|
||||||
|
<glob pattern="*.85v" />
|
||||||
|
<glob pattern="*.85l" />
|
||||||
|
<glob pattern="*.85m" />
|
||||||
|
<glob pattern="*.85k" />
|
||||||
|
<glob pattern="*.85c" />
|
||||||
|
<glob pattern="*.85y" />
|
||||||
|
<glob pattern="*.85s" />
|
||||||
|
<glob pattern="*.85d" />
|
||||||
|
<glob pattern="*.85i" />
|
||||||
|
<glob pattern="*.85r" />
|
||||||
|
<glob pattern="*.85w" />
|
||||||
|
<glob pattern="*.85z" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI85**\x1a\x0c\x00">
|
||||||
|
<match type="little16" offset="55" value="0x0004" mask="0xfffc" />
|
||||||
|
<match type="little16" offset="55" value="0x0008" mask="0xfff8" />
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/x-ti85-program">
|
||||||
|
<sub-class-of type="application/x-ti85-variables" />
|
||||||
|
<comment>TI-85 program</comment>
|
||||||
|
<glob pattern="*.85p" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI85**\x1a\x0c\x00">
|
||||||
|
<match type="byte" offset="59" value="0x12">
|
||||||
|
<match type="little16" offset="55" value="0x0004" mask="0xfffc" />
|
||||||
|
<match type="little16" offset="55" value="0x0008" mask="0xfff8" />
|
||||||
|
</match>
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/x-ti85-backup">
|
||||||
|
<comment>TI-85 memory backup</comment>
|
||||||
|
<glob pattern="*.85b" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI85**\x1a\x0c\x00">
|
||||||
|
<match type="little16" offset="55" value="0x0009">
|
||||||
|
<match type="byte" offset="59" value="0x1d" />
|
||||||
|
</match>
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
|
||||||
|
<mime-type type="application/x-ti86-variables">
|
||||||
|
<comment>TI-86 variable</comment>
|
||||||
|
<glob pattern="*.86g" />
|
||||||
|
<glob pattern="*.86n" />
|
||||||
|
<glob pattern="*.86v" />
|
||||||
|
<glob pattern="*.86l" />
|
||||||
|
<glob pattern="*.86m" />
|
||||||
|
<glob pattern="*.86k" />
|
||||||
|
<glob pattern="*.86c" />
|
||||||
|
<glob pattern="*.86y" />
|
||||||
|
<glob pattern="*.86s" />
|
||||||
|
<glob pattern="*.86d" />
|
||||||
|
<glob pattern="*.86i" />
|
||||||
|
<glob pattern="*.86r" />
|
||||||
|
<glob pattern="*.86w" />
|
||||||
|
<glob pattern="*.86z" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI86**\x1a\x0c\x00">
|
||||||
|
<match type="little16" offset="55" value="0x0004" mask="0xfffc" />
|
||||||
|
<match type="little16" offset="55" value="0x0008" mask="0xfff8" />
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/x-ti86-program">
|
||||||
|
<sub-class-of type="application/x-ti86-variables" />
|
||||||
|
<comment>TI-86 program</comment>
|
||||||
|
<glob pattern="*.86p" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI86**\x1a\x0c\x00">
|
||||||
|
<match type="byte" offset="59" value="0x12">
|
||||||
|
<match type="little16" offset="55" value="0x0004" mask="0xfffc" />
|
||||||
|
<match type="little16" offset="55" value="0x0008" mask="0xfff8" />
|
||||||
|
</match>
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
<mime-type type="application/x-ti86-backup">
|
||||||
|
<comment>TI-86 memory backup</comment>
|
||||||
|
<glob pattern="*.86b" />
|
||||||
|
<magic>
|
||||||
|
<match type="string" offset="0" value="**TI86**\x1a\x0c\x00">
|
||||||
|
<match type="little16" offset="55" value="0x0009">
|
||||||
|
<match type="byte" offset="59" value="0x1d" />
|
||||||
|
</match>
|
||||||
|
</match>
|
||||||
|
</magic>
|
||||||
|
</mime-type>
|
||||||
|
</mime-info>
|
123
tool/tilem-src/data/icons-svg/breakpoint.svg
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="16px"
|
||||||
|
height="16px"
|
||||||
|
id="svg4802"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.47 r22583"
|
||||||
|
sodipodi:docname="breakpoint.svg">
|
||||||
|
<defs
|
||||||
|
id="defs4804">
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient5326">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ef2929;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop5328" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#a40000;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop5330" />
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient5326"
|
||||||
|
id="radialGradient5352"
|
||||||
|
cx="5.0625"
|
||||||
|
cy="4.0624986"
|
||||||
|
fx="5.0625"
|
||||||
|
fy="4.0624986"
|
||||||
|
r="7"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1.4693072e-8,1.2857142,-1.2857143,1.4693073e-8,11.223212,-2.508928)" />
|
||||||
|
<radialGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient5326"
|
||||||
|
id="radialGradient6163"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1.4693072e-8,1.2857142,-1.2857143,1.4693073e-8,11.723212,-3.008928)"
|
||||||
|
cx="5.0625"
|
||||||
|
cy="4.0624986"
|
||||||
|
fx="5.0625"
|
||||||
|
fy="4.0624986"
|
||||||
|
r="7" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="22.627417"
|
||||||
|
inkscape:cx="9.0315411"
|
||||||
|
inkscape:cy="7.1603107"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="888"
|
||||||
|
inkscape:window-height="993"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="0">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid4812"
|
||||||
|
empspacing="2"
|
||||||
|
visible="true"
|
||||||
|
enabled="true"
|
||||||
|
snapvisiblegridlinesonly="true"
|
||||||
|
spacingx="0.5px"
|
||||||
|
spacingy="0.5px" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata4807">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer">
|
||||||
|
<g
|
||||||
|
id="g6159"
|
||||||
|
transform="translate(-0.5,0.5)">
|
||||||
|
<path
|
||||||
|
d="M 14,8 A 6,6 0 1 1 2,8 6,6 0 1 1 14,8 z"
|
||||||
|
sodipodi:ry="6"
|
||||||
|
sodipodi:rx="6"
|
||||||
|
sodipodi:cy="8"
|
||||||
|
sodipodi:cx="8"
|
||||||
|
id="path4814"
|
||||||
|
style="fill:url(#radialGradient6163);fill-opacity:1;fill-rule:evenodd;stroke:#800000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
sodipodi:type="arc" />
|
||||||
|
<path
|
||||||
|
d="M 13,8 A 5,5 0 1 1 3,8 5,5 0 1 1 13,8 z"
|
||||||
|
sodipodi:ry="5"
|
||||||
|
sodipodi:rx="5"
|
||||||
|
sodipodi:cy="8"
|
||||||
|
sodipodi:cx="8"
|
||||||
|
id="path5336"
|
||||||
|
style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:0.24705882;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
sodipodi:type="arc" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.8 KiB |
159
tool/tilem-src/data/icons-svg/pc-arrow.svg
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="16px"
|
||||||
|
height="16px"
|
||||||
|
id="svg5540"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.47 r22583"
|
||||||
|
sodipodi:docname="pc-arrow.svg">
|
||||||
|
<defs
|
||||||
|
id="defs5542">
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient6064">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#fce94f;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop6066" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#c4a000;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop6068" />
|
||||||
|
</linearGradient>
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 8 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="16 : 8 : 1"
|
||||||
|
inkscape:persp3d-origin="8 : 5.3333333 : 1"
|
||||||
|
id="perspective5548" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient6064"
|
||||||
|
id="linearGradient6070"
|
||||||
|
x1="9"
|
||||||
|
y1="6"
|
||||||
|
x2="8"
|
||||||
|
y2="11"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<inkscape:perspective
|
||||||
|
id="perspective6082"
|
||||||
|
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||||
|
inkscape:vp_z="1 : 0.5 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_x="0 : 0.5 : 1"
|
||||||
|
sodipodi:type="inkscape:persp3d" />
|
||||||
|
<radialGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient5326"
|
||||||
|
id="radialGradient5352"
|
||||||
|
cx="5.0625"
|
||||||
|
cy="4.0624986"
|
||||||
|
fx="5.0625"
|
||||||
|
fy="4.0624986"
|
||||||
|
r="7"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1.4693072e-8,1.2857142,-1.2857143,1.4693073e-8,11.223212,-2.508928)" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient5326">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ef2929;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop5328" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#a40000;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop5330" />
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient
|
||||||
|
r="7"
|
||||||
|
fy="4.0624986"
|
||||||
|
fx="5.0625"
|
||||||
|
cy="4.0624986"
|
||||||
|
cx="5.0625"
|
||||||
|
gradientTransform="matrix(1.4693072e-8,1.2857142,-1.2857143,1.4693073e-8,10.723212,-3.0089279)"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
id="radialGradient6092"
|
||||||
|
xlink:href="#linearGradient5326"
|
||||||
|
inkscape:collect="always" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient6064"
|
||||||
|
id="linearGradient6188"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="8"
|
||||||
|
y1="6"
|
||||||
|
x2="7"
|
||||||
|
y2="11"
|
||||||
|
gradientTransform="translate(1,0)" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="32"
|
||||||
|
inkscape:cx="8.1146157"
|
||||||
|
inkscape:cy="8.0354484"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="888"
|
||||||
|
inkscape:window-height="993"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="0">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid5550"
|
||||||
|
empspacing="2"
|
||||||
|
visible="true"
|
||||||
|
enabled="true"
|
||||||
|
snapvisiblegridlinesonly="true"
|
||||||
|
spacingx="0.5px"
|
||||||
|
spacingy="0.5px" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5545">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer">
|
||||||
|
<g
|
||||||
|
id="g6184"
|
||||||
|
transform="translate(-1,0)">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccccccc"
|
||||||
|
id="path5552"
|
||||||
|
d="m 13.5,8.5 -4,4 0,-2 -5,0 0,-4 5,0 0,-2 4,4 z"
|
||||||
|
style="fill:url(#linearGradient6188);fill-opacity:1;fill-rule:evenodd;stroke:#c4a000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccccccc"
|
||||||
|
id="path6072"
|
||||||
|
d="m 12,8.5 -1.5,1.5 0,-0.5 -5,0 0,-2 5,0 0,-0.5 1.5,1.5 z"
|
||||||
|
style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:0.36138617;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.8 KiB |
217
tool/tilem-src/data/icons-svg/stepicons-16.svg
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="16px"
|
||||||
|
height="16px"
|
||||||
|
id="svg17687"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.47 r22583"
|
||||||
|
sodipodi:docname="stepicons-16.svg">
|
||||||
|
<defs
|
||||||
|
id="defs17689">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 8 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="16 : 8 : 1"
|
||||||
|
inkscape:persp3d-origin="8 : 5.3333333 : 1"
|
||||||
|
id="perspective7144" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3743-1">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#d3d7cf;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3745-9" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#555753;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3747-6" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient14417-2">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#8ae234;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop14419-0" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4e9a06;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop14421-6" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient14417-2-6-4">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#729fcf;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop14419-0-1-9" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#204a87;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop14421-6-1-9" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient14417-2-6">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ad7fa8;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop14419-0-1" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#5c3566;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop14421-6-1" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient14417-2"
|
||||||
|
id="linearGradient4839"
|
||||||
|
x1="5.5"
|
||||||
|
y1="4.53125"
|
||||||
|
x2="3.3125"
|
||||||
|
y2="9.84375"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3743-1"
|
||||||
|
id="linearGradient4880"
|
||||||
|
x1="11"
|
||||||
|
y1="5"
|
||||||
|
x2="13"
|
||||||
|
y2="13"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient14417-2-6-4"
|
||||||
|
id="linearGradient4890"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="3.3910849"
|
||||||
|
y1="8.5"
|
||||||
|
x2="9"
|
||||||
|
y2="7.2027574" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient14417-2-6"
|
||||||
|
id="linearGradient4900"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="3.6299806"
|
||||||
|
y1="11.140816"
|
||||||
|
x2="11.09375"
|
||||||
|
y2="12.219177" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="16"
|
||||||
|
inkscape:cx="10.91886"
|
||||||
|
inkscape:cy="6.6259422"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="1278"
|
||||||
|
inkscape:window-height="993"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid17697"
|
||||||
|
empspacing="2"
|
||||||
|
visible="true"
|
||||||
|
enabled="true"
|
||||||
|
snapvisiblegridlinesonly="true"
|
||||||
|
spacingx="0.5px"
|
||||||
|
spacingy="0.5px" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata17692">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer">
|
||||||
|
<g
|
||||||
|
id="boxes">
|
||||||
|
<rect
|
||||||
|
ry="1.5"
|
||||||
|
rx="1.5"
|
||||||
|
y="4.5"
|
||||||
|
x="8.5"
|
||||||
|
height="6"
|
||||||
|
width="7"
|
||||||
|
id="rect2895-6"
|
||||||
|
style="opacity:1;fill:url(#linearGradient4880);fill-opacity:1;stroke:#555753;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
<rect
|
||||||
|
ry="0.5"
|
||||||
|
rx="0.5"
|
||||||
|
y="5.5"
|
||||||
|
x="9.5"
|
||||||
|
height="4"
|
||||||
|
width="5"
|
||||||
|
id="rect3713-8"
|
||||||
|
style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-opacity:0.23529412" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="exit-arrow">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccccccccccc"
|
||||||
|
id="path13783-3"
|
||||||
|
d="m 9.5,5.5 0,4 -3,0 0,2 2,0 -4,4 -4,-4 2,0 0,-2 c 0,-2.5 1.5,-4 4,-4 l 3,0 z"
|
||||||
|
style="fill:url(#linearGradient4900);fill-opacity:1;fill-rule:evenodd;stroke:#5c3566;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccccccccccc"
|
||||||
|
id="path13783-5-7"
|
||||||
|
d="m 8.5,6.5 0,2 -2,0 c -0.5,0 -1,0.5 -1,1 l 0,3 0.5,0 L 4.5,14 3,12.5 l 0.5,0 0,-3 c 0,-2 1,-3 3,-3 l 2,0 z"
|
||||||
|
style="fill:none;stroke:#ffffff;stroke-opacity:0.18823529" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="skip-arrow">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccccccc"
|
||||||
|
id="path13783-3-8"
|
||||||
|
d="m 2.5,1.5 4,0 0,10 2,0 -4,4 -4,-4 2,0 0,-10 z"
|
||||||
|
style="fill:url(#linearGradient4890);fill-opacity:1;fill-rule:evenodd;stroke:#204a87;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccccccc"
|
||||||
|
id="path13783-5-7-3"
|
||||||
|
d="m 3.5,2.5 2,0 0,10 0.5,0 L 4.5,14 3,12.5 l 0.5,0 0,-10 z"
|
||||||
|
style="fill:none;stroke:#ffffff;stroke-opacity:0.15686275" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="enter-arrow">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccccccccccc"
|
||||||
|
id="path13783"
|
||||||
|
d="m 0.5,0.5 4,0 0,5 2,0 0,-2 4,4 -4,4 0,-2 -2,0 C 2,9.5 0.5,8 0.5,5.5 l 0,-5 z"
|
||||||
|
style="opacity:1;fill:url(#linearGradient4839);fill-opacity:1;fill-rule:evenodd;stroke:#4e9a06;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccccccccccc"
|
||||||
|
id="path13783-5"
|
||||||
|
d="m 1.5,1.5 2,0 0,4 c 0,0.5 0.5,1 1,1 l 3,0 L 7.5,6 9,7.5 7.5,9 l 0,-0.5 -3,0 c -2,0 -3,-1 -3,-3 l 0,-4 z"
|
||||||
|
style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-opacity:0.23529412000000000" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 7.0 KiB |
389
tool/tilem-src/data/icons-svg/stepicons-24.svg
Normal file
|
@ -0,0 +1,389 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
id="svg16550"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.47 r22583"
|
||||||
|
sodipodi:docname="stepicons-24.svg"
|
||||||
|
inkscape:export-filename="/home/benjamin/programs/tilem2/misc/step-over-24.png"
|
||||||
|
inkscape:export-xdpi="90"
|
||||||
|
inkscape:export-ydpi="90">
|
||||||
|
<defs
|
||||||
|
id="defs16552">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 12 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="24 : 12 : 1"
|
||||||
|
inkscape:persp3d-origin="12 : 8 : 1"
|
||||||
|
id="perspective60" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient19570">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop19572" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop19574" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient5777">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0;"
|
||||||
|
offset="0"
|
||||||
|
id="stop5779" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0.49803922;"
|
||||||
|
offset="1"
|
||||||
|
id="stop5781" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient14417-2-6-4">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#729fcf;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop14419-0-1-9" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#204a87;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop14421-6-1-9" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient14417-2-6">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ad7fa8;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop14419-0-1" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#5c3566;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop14421-6-1" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient14417-2">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#73d216;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop14419-0" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4e9a06;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop14421-6" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3743-1-3-0">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#d3d7cf;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3745-9-8-3" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#555753;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3747-6-73-03" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3743-1-3-0"
|
||||||
|
id="linearGradient6950"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="translate(0,-8)"
|
||||||
|
x1="17"
|
||||||
|
y1="2"
|
||||||
|
x2="19"
|
||||||
|
y2="10" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3743-1-3-0"
|
||||||
|
id="linearGradient6969"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="translate(0,-8)"
|
||||||
|
x1="17"
|
||||||
|
y1="17"
|
||||||
|
x2="19"
|
||||||
|
y2="25" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient14417-2-6"
|
||||||
|
id="linearGradient4301"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="8.5"
|
||||||
|
y1="4.3125"
|
||||||
|
x2="16"
|
||||||
|
y2="11.0625" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient14417-2"
|
||||||
|
id="linearGradient5798"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="9"
|
||||||
|
y1="-2.375"
|
||||||
|
x2="3.625"
|
||||||
|
y2="8.5" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3743-1-3-0"
|
||||||
|
id="linearGradient19598"
|
||||||
|
x1="17"
|
||||||
|
y1="0"
|
||||||
|
x2="19"
|
||||||
|
y2="11"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3743-1-3-0"
|
||||||
|
id="linearGradient19608"
|
||||||
|
x1="18"
|
||||||
|
y1="13"
|
||||||
|
x2="18"
|
||||||
|
y2="10.5"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient14417-2-6-4"
|
||||||
|
id="linearGradient19628"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="5.125"
|
||||||
|
y1="5"
|
||||||
|
x2="12.5"
|
||||||
|
y2="6.3125" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient19570"
|
||||||
|
id="linearGradient19636"
|
||||||
|
x1="-1.5"
|
||||||
|
y1="4"
|
||||||
|
x2="9"
|
||||||
|
y2="4"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient19570"
|
||||||
|
id="linearGradient19638"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="-0.83650517"
|
||||||
|
y1="8.1351967"
|
||||||
|
x2="5.7805586"
|
||||||
|
y2="8.1351967" />
|
||||||
|
<radialGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient5777"
|
||||||
|
id="radialGradient22298"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(-0.85844211,-0.88068425,1.5254682,-1.4869414,-4.0810409,47.152195)"
|
||||||
|
cx="10.991496"
|
||||||
|
cy="15.354539"
|
||||||
|
fx="10.991496"
|
||||||
|
fy="15.354539"
|
||||||
|
r="5.25" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient19570"
|
||||||
|
id="linearGradient22300"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="9.5"
|
||||||
|
y1="5.5"
|
||||||
|
x2="9.5"
|
||||||
|
y2="14" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="16"
|
||||||
|
inkscape:cx="6.6424946"
|
||||||
|
inkscape:cy="9.8308889"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:snap-global="true"
|
||||||
|
inkscape:window-width="1278"
|
||||||
|
inkscape:window-height="993"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid16560"
|
||||||
|
empspacing="2"
|
||||||
|
visible="true"
|
||||||
|
enabled="true"
|
||||||
|
snapvisiblegridlinesonly="true"
|
||||||
|
spacingx="0.5px"
|
||||||
|
spacingy="0.5px" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata16555">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
transform="translate(0,8)">
|
||||||
|
<g
|
||||||
|
id="enter-arrow">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccccccccccc"
|
||||||
|
id="path13783"
|
||||||
|
d="m 1.5,-5.5 6,0 0,7 3,0 0,-3 6,6 -6,6 0,-3 -4.5,0 C 3.5,7.5 1.5,5.5 1.5,3 l 0,-8.5 z"
|
||||||
|
style="fill:url(#linearGradient5798);fill-opacity:1;fill-rule:evenodd;stroke:#4e9a06;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccccccccccc"
|
||||||
|
id="path13783-5"
|
||||||
|
d="m 2.5,-4.5 4,0 0,6 c 0,0.5 0.5,1 1,1 l 4,0 L 11.5,1 15,4.5 11.5,8 11.5,6.5 6,6.5 C 4,6.5 2.5,5 2.5,3 l 0,-7.5 z"
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:0.25098039000000000" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccssssc"
|
||||||
|
transform="translate(0,-8)"
|
||||||
|
id="path19548"
|
||||||
|
d="M 2,11.5 C 1.9441214,10.997093 2.014329,4.7642029 2,4.5 2,4 2.3052366,3.5236342 2.7400388,3.427612 3.4340805,3.274339 3.9146482,3.7586271 4.1100582,4.0463305 5.1289687,5.5464784 4.7496137,9.1495023 4.5740968,10.741748 4.4778765,11.614635 4.2844847,12.982713 3.7786017,13.636466 3.0393768,14.591768 2.0558786,12.002907 2,11.5 z"
|
||||||
|
style="fill:url(#linearGradient19638);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccccc"
|
||||||
|
transform="translate(0,-8)"
|
||||||
|
id="path19568"
|
||||||
|
d="m 7.5,10 c -4.9264746,2.756282 2.955806,3.522097 7.5,2 l -4,-4 0,2 -3.5,0 z"
|
||||||
|
style="fill:url(#linearGradient22300);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="skip-arrow">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccccccc"
|
||||||
|
id="path13783-3-8"
|
||||||
|
d="m 4.5,-4.5 6,0 0,13 3,0 -6,6 -6,-6 3,0 0,-13 z"
|
||||||
|
style="fill:url(#linearGradient19628);fill-opacity:1;fill-rule:evenodd;stroke:#204a87;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccccccc"
|
||||||
|
id="path13783-5-7-3"
|
||||||
|
d="m 5.5,-3.5 4,0 0,13 1.5,0 L 7.5,13 4,9.5 l 1.5,0 0,-13 z"
|
||||||
|
style="fill:none;stroke:#ffffff;stroke-opacity:0.18823529" />
|
||||||
|
<path
|
||||||
|
style="fill:url(#linearGradient19636);fill-opacity:1;stroke:none"
|
||||||
|
d="M 5,-2.5 C 5,-3 5.2936905,-3.5149404 5.8232233,-3.4611676 6.9640388,-3.3453204 7.8692177,1.7617947 7.8696383,7.081299 7.8698453,9.6989932 7.6325825,10.823223 7,13 L 3,9 5,9 5,-2.5 z"
|
||||||
|
id="path19615"
|
||||||
|
sodipodi:nodetypes="csscccc" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="boxes">
|
||||||
|
<g
|
||||||
|
id="g6971">
|
||||||
|
<rect
|
||||||
|
style="fill:url(#linearGradient6969);fill-opacity:1;stroke:#555753;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
id="rect2895-6-1-8"
|
||||||
|
width="9"
|
||||||
|
height="6"
|
||||||
|
x="13.5"
|
||||||
|
y="8.5"
|
||||||
|
rx="2"
|
||||||
|
ry="2" />
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke:#ffffff;stroke-opacity:0.23529412"
|
||||||
|
id="rect3713-8-0-0"
|
||||||
|
width="7"
|
||||||
|
height="4"
|
||||||
|
x="14.5"
|
||||||
|
y="9.5"
|
||||||
|
rx="1"
|
||||||
|
ry="1" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g19610">
|
||||||
|
<rect
|
||||||
|
style="fill:url(#linearGradient19598);stroke:#555753;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;fill-opacity:1"
|
||||||
|
id="rect2895-6-1-5"
|
||||||
|
width="9"
|
||||||
|
height="9"
|
||||||
|
x="13.5"
|
||||||
|
y="-0.5"
|
||||||
|
rx="2"
|
||||||
|
ry="2" />
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke:#ffffff;stroke-opacity:0.23529412"
|
||||||
|
id="rect3713-8-0-9"
|
||||||
|
width="7"
|
||||||
|
height="7"
|
||||||
|
x="14.5"
|
||||||
|
y="0.5"
|
||||||
|
rx="1"
|
||||||
|
ry="1" />
|
||||||
|
<rect
|
||||||
|
style="fill:url(#linearGradient19608);fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||||
|
id="rect19600"
|
||||||
|
width="5"
|
||||||
|
height="2"
|
||||||
|
x="15.5"
|
||||||
|
y="11"
|
||||||
|
transform="translate(0,-8)"
|
||||||
|
rx="1"
|
||||||
|
ry="0.984375" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g6986">
|
||||||
|
<rect
|
||||||
|
style="fill:url(#linearGradient6950);fill-opacity:1;stroke:#555753;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||||
|
id="rect2895-6-1"
|
||||||
|
width="9"
|
||||||
|
height="6"
|
||||||
|
x="13.5"
|
||||||
|
y="-6.5"
|
||||||
|
rx="2"
|
||||||
|
ry="2" />
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke:#ffffff;stroke-opacity:0.23529412"
|
||||||
|
id="rect3713-8-0"
|
||||||
|
width="7"
|
||||||
|
height="4"
|
||||||
|
x="14.5"
|
||||||
|
y="-5.5"
|
||||||
|
rx="1"
|
||||||
|
ry="1" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="exit-arrow">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccccccccccc"
|
||||||
|
id="path13783-3"
|
||||||
|
d="m 15.5,0.5 0,6 -5,0 0,2 3,0 -6,6 -6,-6 3,0 0,-3.5 C 4.5,2.5 6.5,0.5 9,0.5 l 6.5,0 z"
|
||||||
|
style="fill:url(#linearGradient4301);fill-opacity:1;fill-rule:evenodd;stroke:#5c3566;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccccccccccc"
|
||||||
|
id="path13783-5-7"
|
||||||
|
d="m 14.5,1.5 0,4 -4,0 c -0.5,0 -1,0.5 -1,1 l 0,3 1.5,0 L 7.5,13 4,9.5 5.5,9.5 5.5,5 C 5.5,3 7,1.5 9,1.5 l 5.5,0 z"
|
||||||
|
style="fill:none;stroke:#ffffff;stroke-opacity:0.19607843000000000;fill-opacity:1" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccssssssscscc"
|
||||||
|
transform="translate(0,-8)"
|
||||||
|
id="path5775"
|
||||||
|
d="m 3,17 4,4 C 7.522097,19.367417 7.7711374,18.480908 7.7046955,17.621939 7.6368873,16.745307 7.4622004,15.840071 7.4033784,15.188039 7.292893,13.963314 7.2859183,13.413837 7.5138635,12.69064 7.7252404,12.02001 8.4401649,11.452716 9.2209703,11.226601 10.029108,10.992571 11.281114,11.028841 12.265164,10.850951 13.243067,10.674173 14.2513,10.314991 14.229203,9.9254757 14.200884,9.4262783 13.287262,9.0441942 12.817591,9.0441942 11.817593,9.0441942 10,9 9,9 7,9 5,10.5 5,13 c 0,1 0,4 0,4 l -2,0 z"
|
||||||
|
style="fill:url(#radialGradient22298);stroke:none;fill-opacity:1" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 472 B |
After Width: | Height: | Size: 490 B |
After Width: | Height: | Size: 498 B |
BIN
tool/tilem-src/data/icons/hicolor/16x16/apps/tilem.png
Normal file
After Width: | Height: | Size: 679 B |
After Width: | Height: | Size: 592 B |
After Width: | Height: | Size: 534 B |
After Width: | Height: | Size: 269 B |
BIN
tool/tilem-src/data/icons/hicolor/22x22/apps/tilem.png
Normal file
After Width: | Height: | Size: 1001 B |
After Width: | Height: | Size: 978 B |
After Width: | Height: | Size: 959 B |
After Width: | Height: | Size: 1.0 KiB |
BIN
tool/tilem-src/data/icons/hicolor/24x24/apps/tilem.png
Normal file
After Width: | Height: | Size: 1004 B |
BIN
tool/tilem-src/data/icons/hicolor/32x32/apps/tilem.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
tool/tilem-src/data/icons/hicolor/48x48/apps/tilem.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
44
tool/tilem-src/data/icons/hicolor/index.theme
Normal file
|
@ -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
|
555
tool/tilem-src/data/keybindings.ini
Normal file
|
@ -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
|
45
tool/tilem-src/data/skins/README
Normal file
|
@ -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)
|
BIN
tool/tilem-src/data/skins/ti76.skn
Normal file
BIN
tool/tilem-src/data/skins/ti81.skn
Normal file
BIN
tool/tilem-src/data/skins/ti82.skn
Normal file
BIN
tool/tilem-src/data/skins/ti82stats.skn
Normal file
BIN
tool/tilem-src/data/skins/ti83.skn
Normal file
BIN
tool/tilem-src/data/skins/ti83p.skn
Normal file
BIN
tool/tilem-src/data/skins/ti83pfr.skn
Normal file
BIN
tool/tilem-src/data/skins/ti84p.skn
Normal file
BIN
tool/tilem-src/data/skins/ti84p2.skn
Normal file
BIN
tool/tilem-src/data/skins/ti86.skn
Normal file
939
tool/tilem-src/data/symbols/ti82.sym
Normal file
|
@ -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
|
1307
tool/tilem-src/data/symbols/ti83.sym
Normal file
2327
tool/tilem-src/data/symbols/ti83p.sym
Normal file
254
tool/tilem-src/data/symbols/ti85.sym
Normal file
|
@ -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
|
1112
tool/tilem-src/data/symbols/ti86.sym
Normal file
59
tool/tilem-src/db/Makefile.in
Normal file
|
@ -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
|
1084
tool/tilem-src/db/disasm.c
Normal file
379
tool/tilem-src/db/listing.c
Normal file
|
@ -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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
384
tool/tilem-src/db/lstfile.c
Normal file
|
@ -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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#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.
|
||||||
|
%<pad><width>d, %<pad><width>x match decimal and hex integers;
|
||||||
|
%<width>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;
|
||||||
|
}
|
||||||
|
|
149
tool/tilem-src/db/tilemdb.h
Normal file
|
@ -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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TILEMDB_H
|
||||||
|
#define _TILEMDB_H
|
||||||
|
|
||||||
|
#include <tilem.h>
|
||||||
|
|
||||||
|
#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
|
218
tool/tilem-src/emu/Makefile.in
Normal file
|
@ -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
|
186
tool/tilem-src/emu/calcs.c
Normal file
|
@ -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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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);
|
||||||
|
}
|
136
tool/tilem-src/emu/cert.c
Normal file
|
@ -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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
326
tool/tilem-src/emu/flash.c
Normal file
|
@ -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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
90
tool/tilem-src/emu/graycolor.c
Normal file
|
@ -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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#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;
|
||||||
|
}
|
324
tool/tilem-src/emu/grayimage.c
Normal file
|
@ -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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
263
tool/tilem-src/emu/graylcd.c
Normal file
|
@ -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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
57
tool/tilem-src/emu/graylcd.h
Normal file
|
@ -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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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
|
91
tool/tilem-src/emu/keypad.c
Normal file
|
@ -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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#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));
|
||||||
|
}
|
||||||
|
}
|
268
tool/tilem-src/emu/lcd.c
Normal file
|
@ -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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
456
tool/tilem-src/emu/link.c
Normal file
|
@ -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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#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;
|
||||||
|
}
|
86
tool/tilem-src/emu/md5.c
Normal file
|
@ -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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#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;
|
||||||
|
}
|
148
tool/tilem-src/emu/monolcd.c
Normal file
|
@ -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
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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++;
|
||||||
|
}
|
||||||
|
}
|