; 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+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+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+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+1 jsr print_str rts print_entries_done ; print choose string 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+1 jsr print_str jmp monitor wrong_option_str .byt $0F,$0D,"WRONG OPTION",$0D,$0D fast_loader_end #include "src/rom_content.a65"