618 lines
10 KiB
Plaintext
618 lines
10 KiB
Plaintext
; apple-1 constants
|
|
#define monitor $FF1F
|
|
#define echo $FFEF
|
|
#define prhex $FFE5
|
|
#define kbd_data $D010
|
|
#define kbd_cr $D011
|
|
|
|
; cartridge bank control constants
|
|
#define rom_bank $47FF
|
|
#define ram_bank $47FE
|
|
|
|
; zero page variables
|
|
|
|
; content copy variables
|
|
#define dest_addr $30
|
|
#define src_addr $32
|
|
#define src_len $34
|
|
#define copy_counter $36
|
|
|
|
; string printing variables
|
|
#define str_len $38
|
|
#define str_addr $40
|
|
|
|
; entries scanning variables
|
|
#define entries_number $42
|
|
#define entries_counter $43
|
|
#define entries_counter_bcd $44
|
|
#define entries_scan_addr $45
|
|
#define entry_segments $47
|
|
#define entry_to_load $48
|
|
|
|
; jmp addr variable
|
|
#define jmp_addr $49
|
|
|
|
#define key_data $4B
|
|
|
|
#define option_data $00
|
|
|
|
#define entries_per_page $14
|
|
#define max_entries $63
|
|
|
|
* = $4000
|
|
|
|
start
|
|
|
|
; clear decimal mode
|
|
cld
|
|
|
|
; enable rom bank
|
|
sta rom_bank
|
|
|
|
; only 99 entries allowed
|
|
lda rom_content
|
|
cmp #max_entries
|
|
bcc store_entries_count
|
|
lda #max_entries
|
|
|
|
store_entries_count
|
|
sta entries_number
|
|
|
|
show_entries
|
|
; print entries and get option - X contains number of digits
|
|
jsr print_entries
|
|
input
|
|
jsr get_option
|
|
|
|
; check number of digits - if not zero then validate option,
|
|
; otherwise print next page or repeat
|
|
txa
|
|
bne validate_option
|
|
|
|
; check if all entries have been printed
|
|
lda entries_counter
|
|
cmp entries_number
|
|
|
|
; if yes - repeat
|
|
beq show_entries
|
|
|
|
; else continue printing pages
|
|
jsr print_entry
|
|
jmp input
|
|
|
|
validate_option
|
|
; option validation
|
|
lda option_data
|
|
; invalid - user typed "0" or "00"
|
|
beq show_entries
|
|
|
|
cmp entries_number
|
|
; valid - last entry
|
|
beq valid_option
|
|
|
|
; invalid out of range
|
|
bcs show_entries
|
|
|
|
valid_option
|
|
lda option_data
|
|
sta entry_to_load
|
|
|
|
;;; load-start
|
|
load_entry
|
|
|
|
; init entries counter
|
|
lda #$01
|
|
sta entries_counter
|
|
|
|
; init entries scan addr
|
|
lda #<rom_content
|
|
sta entries_scan_addr
|
|
|
|
lda #>rom_content
|
|
sta entries_scan_addr+1
|
|
|
|
; skip number of entries byte
|
|
ldx #entries_scan_addr
|
|
jsr increment_16bit
|
|
|
|
check_load
|
|
|
|
; load number of entry segments
|
|
ldy #$00
|
|
lda (entries_scan_addr),Y
|
|
sta entry_segments
|
|
|
|
; skip number of entry segments
|
|
ldx #entries_scan_addr
|
|
jsr increment_16bit
|
|
|
|
lda entry_to_load
|
|
cmp entries_counter
|
|
|
|
bne skip_entry
|
|
|
|
load_segment
|
|
|
|
; load segment length
|
|
ldy #$00
|
|
lda (entries_scan_addr),Y
|
|
sta src_len
|
|
ldx #entries_scan_addr
|
|
jsr increment_16bit
|
|
lda (entries_scan_addr),Y
|
|
sta src_len+1
|
|
|
|
; load dest addr
|
|
ldx #entries_scan_addr
|
|
jsr increment_16bit
|
|
lda (entries_scan_addr),Y
|
|
sta dest_addr
|
|
ldx #entries_scan_addr
|
|
jsr increment_16bit
|
|
lda (entries_scan_addr),Y
|
|
sta dest_addr+1
|
|
|
|
; load source addr
|
|
ldx #entries_scan_addr
|
|
jsr increment_16bit
|
|
lda (entries_scan_addr),Y
|
|
sta src_addr
|
|
ldx #entries_scan_addr
|
|
jsr increment_16bit
|
|
lda (entries_scan_addr),Y
|
|
sta src_addr+1
|
|
|
|
; copy segment from source to destination
|
|
jsr init_copy
|
|
|
|
; proceed to next segment
|
|
ldx #entries_scan_addr
|
|
jsr increment_16bit
|
|
|
|
dec entry_segments
|
|
bne load_segment
|
|
|
|
load_program
|
|
|
|
; skip entry string
|
|
ldy #$00
|
|
lda (entries_scan_addr),Y
|
|
tay
|
|
iny
|
|
tya
|
|
ldx #entries_scan_addr
|
|
jsr add_to_addr
|
|
|
|
; load entry jump address
|
|
lda entries_scan_addr
|
|
sta dest_addr
|
|
lda entries_scan_addr+1
|
|
sta dest_addr+1
|
|
|
|
ldy #$00
|
|
lda (dest_addr),Y
|
|
sta jmp_addr
|
|
|
|
iny
|
|
|
|
lda (dest_addr),Y
|
|
sta jmp_addr+1
|
|
|
|
; enable ram bank to make jmp
|
|
sta ram_bank
|
|
|
|
jmp (jmp_addr)
|
|
|
|
skip_entry
|
|
; skip length, dest addr, content
|
|
ldx #entries_scan_addr
|
|
lda #$06
|
|
jsr add_to_addr
|
|
dec entry_segments
|
|
bne skip_entry
|
|
|
|
; skip entry string
|
|
ldy #$00
|
|
lda (entries_scan_addr),Y
|
|
tay
|
|
iny
|
|
tya
|
|
ldx #entries_scan_addr
|
|
jsr add_to_addr
|
|
|
|
; skip entry jump address
|
|
lda #$02
|
|
ldx #entries_scan_addr
|
|
jsr add_to_addr
|
|
|
|
inc entries_counter
|
|
jmp check_load
|
|
|
|
init_copy
|
|
lda #$01
|
|
sta copy_counter
|
|
lda #$00
|
|
sta copy_counter+1
|
|
copy
|
|
; load byte from rom
|
|
ldy #$00
|
|
lda (src_addr),Y
|
|
|
|
; enable ram bank
|
|
stx ram_bank
|
|
|
|
; store byte to ram
|
|
sta (dest_addr),Y
|
|
|
|
; enable rom bank
|
|
stx rom_bank
|
|
|
|
; increment source address
|
|
ldx #src_addr
|
|
jsr increment_16bit
|
|
|
|
; increment destination address
|
|
ldx #dest_addr
|
|
jsr increment_16bit
|
|
|
|
; compare counter lower byte with source length lower byte
|
|
; if not equal increment counter
|
|
lda src_len
|
|
cmp copy_counter
|
|
bne increment_copy_counter
|
|
|
|
; compare counter upper byte with content length upper byte
|
|
; if not equal increment counter
|
|
lda src_len+1
|
|
cmp copy_counter+1
|
|
bne increment_copy_counter
|
|
|
|
rts
|
|
|
|
increment_copy_counter
|
|
ldx #copy_counter
|
|
jsr increment_16bit
|
|
|
|
jmp copy
|
|
|
|
;;; load-end
|
|
|
|
;;; printing
|
|
|
|
print_entries
|
|
; print welcome string
|
|
lda #<welcome_str
|
|
sta str_addr
|
|
lda #>welcome_str
|
|
sta str_addr+1
|
|
jsr print_str
|
|
|
|
; init entries counter
|
|
lda #$00
|
|
sta entries_counter
|
|
sta entries_counter_bcd
|
|
|
|
; init entries scan addr
|
|
lda #<rom_content
|
|
sta entries_scan_addr
|
|
|
|
lda #>rom_content
|
|
sta entries_scan_addr+1
|
|
|
|
; skip number of entries byte
|
|
ldx #entries_scan_addr
|
|
jsr increment_16bit
|
|
|
|
print_entry
|
|
|
|
; load number of entry segments
|
|
ldy #$00
|
|
lda (entries_scan_addr),Y
|
|
sta entry_segments
|
|
|
|
; skip number of entry segments
|
|
ldx #entries_scan_addr
|
|
jsr increment_16bit
|
|
|
|
skip_segment
|
|
; skip length, dest addr, content
|
|
ldx #entries_scan_addr
|
|
lda #$06
|
|
jsr add_to_addr
|
|
dec entry_segments
|
|
bne skip_segment
|
|
|
|
; print entry number
|
|
inc entries_counter
|
|
sed
|
|
clc
|
|
lda #$01
|
|
adc entries_counter_bcd
|
|
sta entries_counter_bcd
|
|
jsr print_number_bcd
|
|
cld
|
|
|
|
; print dot and space
|
|
lda #'.'
|
|
jsr echo
|
|
lda #' '
|
|
jsr echo
|
|
|
|
; print entry string
|
|
lda entries_scan_addr
|
|
sta str_addr
|
|
lda entries_scan_addr+1
|
|
sta str_addr+1
|
|
jsr print_str
|
|
lda #$0D
|
|
jsr echo
|
|
|
|
; skip entry string
|
|
ldy #$00
|
|
lda (entries_scan_addr),Y
|
|
tay
|
|
iny
|
|
tya
|
|
ldx #entries_scan_addr
|
|
jsr add_to_addr
|
|
|
|
; skip entry jump address
|
|
ldx #entries_scan_addr
|
|
lda #$02
|
|
jsr add_to_addr
|
|
|
|
; if not last entry then repeat
|
|
lda entries_number
|
|
|
|
cmp entries_counter
|
|
beq print_entries_done
|
|
|
|
jsr entries_page_hit
|
|
bne print_entry
|
|
|
|
print_entries_page_done
|
|
; print choose next string
|
|
lda #<choose_next_str
|
|
sta str_addr
|
|
lda #>choose_next_str
|
|
sta str_addr+1
|
|
jsr print_str
|
|
rts
|
|
|
|
print_entries_done
|
|
; print choose string
|
|
lda #<choose_str
|
|
sta str_addr
|
|
lda #>choose_str
|
|
sta str_addr+1
|
|
jsr print_str
|
|
rts
|
|
|
|
print_str
|
|
; store string length
|
|
ldy #$00
|
|
lda (str_addr),Y
|
|
sta str_len
|
|
|
|
; skip length byte from string address
|
|
ldx #str_addr
|
|
jsr increment_16bit
|
|
|
|
print_str_loop
|
|
lda (str_addr),Y
|
|
jsr echo
|
|
iny
|
|
cpy str_len
|
|
bne print_str_loop
|
|
rts
|
|
|
|
print_number_bcd
|
|
pha
|
|
clc
|
|
and #$F0
|
|
rol
|
|
rol
|
|
rol
|
|
rol
|
|
rol
|
|
beq print_next_digit
|
|
jsr prhex
|
|
|
|
print_next_digit
|
|
pla
|
|
and #$0F
|
|
jsr prhex
|
|
|
|
print_number_done
|
|
rts
|
|
|
|
entries_page_hit
|
|
lda entries_counter
|
|
entries_page_loop
|
|
cmp #entries_per_page
|
|
beq entries_page_end
|
|
bcc entries_page_end
|
|
sec
|
|
sbc #entries_per_page
|
|
jmp entries_page_loop
|
|
entries_page_end
|
|
rts
|
|
|
|
|
|
;;; printing-end
|
|
|
|
;;; get-option
|
|
|
|
get_option
|
|
; stores option number in option_data, digits count in X
|
|
; init digits counter in X
|
|
ldx #$00
|
|
get_key
|
|
; wait for key
|
|
lda kbd_cr
|
|
bpl get_key
|
|
lda kbd_data
|
|
and #$7F
|
|
|
|
; store key data
|
|
sta key_data
|
|
|
|
; if CR check if option is satisfied
|
|
cmp #$0D ; CR
|
|
beq get_key_done
|
|
|
|
; check range 0-9
|
|
cmp #$30 ; 0
|
|
bmi get_key
|
|
|
|
cmp #$3A ; 9
|
|
bpl get_key
|
|
|
|
; which digit we are processing?
|
|
txa
|
|
|
|
; second digit
|
|
cmp #$01
|
|
beq two_digit
|
|
|
|
; if we have already processed second digit then only CR is eligible
|
|
cmp #$02
|
|
beq get_key
|
|
|
|
one_digit
|
|
; ???
|
|
sec
|
|
lda key_data
|
|
sbc #$30
|
|
sta option_data
|
|
|
|
echo_key
|
|
; echo digit
|
|
lda key_data
|
|
jsr echo
|
|
|
|
; increment digit counter
|
|
inx
|
|
jmp get_key
|
|
|
|
two_digit
|
|
lda #$00
|
|
ldy option_data
|
|
; if first digit was 0 then simply add second to A
|
|
beq two_digit_inc_done
|
|
clc
|
|
two_digit_inc
|
|
; loop adding 10 to A first digit times
|
|
adc #$0A
|
|
dey
|
|
bne two_digit_inc
|
|
two_digit_inc_done
|
|
; save current option calculation on stack
|
|
pha
|
|
|
|
; compute int value from second digit
|
|
sec
|
|
lda key_data
|
|
sbc #$30
|
|
; and store in option_data
|
|
sta option_data
|
|
|
|
; restore previously calculated first digit part from stack
|
|
pla
|
|
clc
|
|
; and add second digit value
|
|
adc option_data
|
|
; store fully computed option value
|
|
sta option_data
|
|
; and wait for CR
|
|
jmp echo_key
|
|
|
|
get_key_done
|
|
; print CR
|
|
lda #$8D ; CR
|
|
jsr echo
|
|
rts
|
|
|
|
;;; get-option-end
|
|
|
|
;;; tools
|
|
increment_16bit
|
|
inc $00,X
|
|
bne increment_16bit_done
|
|
inx
|
|
inc $00,X
|
|
increment_16bit_done
|
|
rts
|
|
|
|
;; adds A to ZP address in X
|
|
add_to_addr
|
|
clc
|
|
adc $00,X
|
|
sta $00,X
|
|
bcs add_to_addr_carry
|
|
jmp add_to_addr_done
|
|
add_to_addr_carry
|
|
inx
|
|
inc $00,X
|
|
add_to_addr_done
|
|
rts
|
|
|
|
;;; tools-end
|
|
|
|
welcome_str .byt $15,$0D,"AVAILABLE OPTIONS:",$0D,$0D
|
|
choose_str .byt $0F,$0D,"CHOOSE OPTION:"
|
|
choose_next_str .byt $27,$0D,"CHOOSE OPTION (PRESS RETURN FOR NEXT):"
|
|
|
|
loader_end
|
|
|
|
* = $4300
|
|
.dsb (*-loader_end), $FF
|
|
|
|
* = $4300
|
|
fast_loader_start = $4300
|
|
|
|
; clear decimal mode
|
|
cld
|
|
|
|
; enable rom bank
|
|
sta rom_bank
|
|
|
|
; only 99 entries allowed
|
|
lda rom_content
|
|
cmp #max_entries
|
|
bcc store_entries_count_fast
|
|
lda #max_entries
|
|
|
|
store_entries_count_fast
|
|
sta entries_number
|
|
|
|
validate_option_fast
|
|
; option validation
|
|
lda option_data
|
|
beq invalid_option_fast
|
|
cmp entries_number
|
|
beq valid_option_fast
|
|
bcs invalid_option_fast
|
|
|
|
; load entry
|
|
valid_option_fast
|
|
sta entry_to_load
|
|
jmp load_entry
|
|
|
|
invalid_option_fast
|
|
; print choose string
|
|
lda #<wrong_option_str
|
|
sta str_addr
|
|
lda #>wrong_option_str
|
|
sta str_addr+1
|
|
jsr print_str
|
|
|
|
jmp monitor
|
|
|
|
|
|
wrong_option_str .byt $0F,$0D,"WRONG OPTION",$0D,$0D
|
|
|
|
fast_loader_end
|
|
|
|
#include "src/rom_content.a65"
|