;;; -*- 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