;;; -*- TI-Asm -*- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Unity - assembly program loader for the TI-81 ;;; ;;; Copyright (c) 2010 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 ;;; . ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .nolist .include .list .include "kernel.exp" kernel_buffer .equ $E356 ; buffer (part of tempMatrix on new ; OSes; plotSScreen on 1.1K) used to ; store unpacked kernel temporarily kernel_buffer_end .equ kernel_buffer + KERNEL_SIZE + 1 ; the last byte of the unpacked kernel ; will be at buffer + KERNEL_SIZE - 1; ; the checksum will be at ; kernel_buffer + KERNEL_SIZE; after ; unpacking, the output pointer will ; be kernel_buffer + KERNEL_SIZE + 1. .org equMem + 6 - $2000 - 1 .db tQuote unpack_kernel_shift_bits: ;; A = next token read from prgm0 sub tH patch_rld: ;; (HL) = 10h if nothing written there yet -> A = 1 after RLD ;; (HL) = 0Xh if one nibble already written -> A = 0 after RLD ;; RLD = ED 6F .db t0, $6F ; CODEPATCH dec a jr z,unpack_kernel_same_byte inc a ; if A is not 0 or 1, the input token ; was not a recognized character -> ; end of kernel code (or an error) jr nz,unpack_kernel_finished ld a,(hl) inc hl xor c jr unpack_kernel_continue ;; Loader starts at DCDC .if $ != $DCDC .error "code misaligned" .endif ;; set IM 1 (in case we are replacing an existing kernel) ld hl,patch_im_1 ld a,(hl) ; A = $ED cpl ld (hl),a patch_im_1: ;; IM 1 = ED 56 .db $12, $56 ; CODEPATCH ld (patch_rld),a ;; set shift2nd flag so user can abort if something goes ;; seriously wrong ld hl,flags + shiftFlags + $10 res 4,l ld (hl),$18 ;; get start of prgm0 (it may not equal progMem if user has ;; already installed a kernel) sub (hl) add a,$FB - $ED + $18 ; A = $FB ld l,a ld h,(prgm0Start - $2000) / 256 ; HL = prgm0Start - $2000 ld e,(hl) inc hl ld d,(hl) ; DE = start of prgm0 ld hl,kernel_buffer xor a unpack_kernel_continue: ld c,a ld (hl),$10 unpack_kernel_same_byte: ld a,(de) inc de jr unpack_kernel_shift_bits unpack_kernel_finished: ;; C = XOR of all output bytes (should equal 0) ;; DE = address of next char in prgm0 (start of stage2 code) ;; HL = final output address (should equal kernel_buffer_end) ld a,l sub kernel_buffer_end & $ff or c jp nz,unpack_kernel_error push de call swap_kernel ld c,e pop hl ; start of packed data call INIT_EXEC_PROG; - $2000 **** ;; if INIT_EXEC_PROG returns, something went wrong call swap_kernel unpack_kernel_error: ;; kernel checksum failed or stage2 program not valid ld a,LsupE ld hl,patch_rst set 2,(hl) patch_rst: ; RST 20h = E7 .db $E3 ; CODEPATCH wait_loop: halt jp wait_loop swap_kernel: ld hl,kernel_buffer ld de,progMem - $2000 swap_kernel_loop: ld c,(hl) ld a,(de) ld (hl),a ld a,c ld (de),a inc hl inc e ; end of kernel at $D300 / $F300 jp nz,swap_kernel_loop ret .db tQuote, tStore, tY2, tEnter ;; Additional stuff needed for setup .db tQuote, tPtOn, tQuote, tStore, tY3T, tEnter .db tQuote, tLParen, tChs, t1, tRParen, tPower, tPi, tQuote, tStore, tY1, tEnter .db t0, tStore, tX