Fast loader and bugfixes in firmware

This commit is contained in:
flowenol 2021-03-10 10:48:58 +01:00
parent 7a38e133a9
commit 4eed9a3270
3 changed files with 180 additions and 59 deletions

View File

@ -6,25 +6,29 @@ This repository contains firmware files for the "Apple-1 RAM/ROM Cartridge" expa
## Description ## Description
This project aims to provide Apple-1 users with a quick way to expand RAM capacity in their systems up to 52 KB and to simultaneously store some Apple-1 programs in This project aims to equip Apple-1 users with a quick way to expand RAM capacity in their systems up to 52 KB and to simultaneously
~30KB of on-board ROM, which can be banked in and out via software. The on-board ROM also contains a loader program which is capable of loading programs spanning across noncontinuous memory locations. store Apple-1 programs in ~30KB of on-board ROM, which can be banked in and out via software. The on-board ROM also contains a loader
program which is capable of loading programs spanning across noncontinuous memory locations. You can either use a default loader program `4000R`, which displays the list of all available program entries, or the fast loader program `4300R`, which loads the
specific program entry automatically.
The A1C expansion card allows via the physical switch to completely disable the ROM/loader program functionality which takes up to the 2 KB of memory (`$4000-$47FF`) The A1C expansion card allows to completely disable the ROM/loader functionality (via physical switch) which takes up to 2 KB of
and to provide continuous 44KB wide RAM address space instead. memory (`$4000-$47FF`) and to provide continuous 44KB wide RAM address space instead (`$1000-$BFFF`).
## Memory map ## Memory map
Physical switch in ROM mode: With physical switch in ROM mode:
| address | function | | address | function |
| --- | --- | | --- | --- |
| `$0000` | program entry to load via the fast loader program |
| `$1000-$3FFF` | RAM region #1 | | `$1000-$3FFF` | RAM region #1 |
| `$4000` | the start address of the on-board loader program | | `$4000` | the start address of the on-board loader program |
| `$4300` | the start address of the fast loader program |
| `$47F8-$47FF` | write to these memory locations causes ROM to be banked in or out depending on the least significant bit of the address, A0=0 - ROM banked out, A0=1 - ROM banked in | | `$47F8-$47FF` | write to these memory locations causes ROM to be banked in or out depending on the least significant bit of the address, A0=0 - ROM banked out, A0=1 - ROM banked in |
| `$4800-$BFFF` | RAM region #2 when ROM banked out | | `$4800-$BFFF` | RAM region #2 when ROM banked out |
| `$4800-$BFFF` | ROM with program contents when ROM banked in | | `$4800-$BFFF` | ROM with program contents when ROM banked in |
Physical Switch in RAM mode: With physical switch in RAM mode:
| address | function | | address | function |
| --- | --- | | --- | --- |
@ -37,14 +41,15 @@ The contents of this repository are as following:
* inc/ - contains Apple-1 programs in binary format, the package is downloadable [here](https://drive.google.com/file/d/1G0ycKSszlr45RE8Rp6eW-0qxz4MS9qDN/view?usp=sharing) * inc/ - contains Apple-1 programs in binary format, the package is downloadable [here](https://drive.google.com/file/d/1G0ycKSszlr45RE8Rp6eW-0qxz4MS9qDN/view?usp=sharing)
* mapping/ - contains EQN and JED files for GAL22V10 based address decoder * mapping/ - contains EQN and JED files for GAL22V10 based address decoder
* scripts/ - a bunch of useful python scripts which allow conversion from binary to Woz monitor format and vice versa * scripts/ - a bunch of useful python scripts which allow conversion from binary to Woz monitor format and vice versa
* src/ - contains the 6502 assembly sources for the Apple-1 RAM/ROM Cartridge onboard ROM loader program * src/ - contains the 6502 assembly sources for the on-board ROM loader programs
## Requirements ## Requirements
You need the following to successfully build the firmware: You need the following to successfully build and install the firmware:
* [xa](https://www.floodgap.com/retrotech/xa/) cross assembler * [xa](https://www.floodgap.com/retrotech/xa/) cross assembler
* Some software capable of translating the EQN files into JED's. I used for this purpose the DOS based EQN2JED from OPALjr PLD Development Package. This is only required if you wish to make some changes to the GAL based address decoder. The default JED file should be fine for most users. * Some software capable of translating the EQN files into JED's. I used for this purpose the DOS based EQN2JED from OPALjr PLD Development Package. This is only required if you wish to make some changes to the GAL based address decoder. The default JED file should be fine for most users.
* EEPROM programmer. I used [TL866](http://autoelectric.cn/EN/TL866_main.html) programmer for this purpose.
## How to build? ## How to build?
@ -58,7 +63,8 @@ And to clean the build:
# How to customise? # How to customise?
In order to customise your ROM contents you have to edit the `src/rom_content.a65` source file. You can find the entry table structure documentation in the source file. In order to customise your ROM contents you have to edit the `src/rom_content.a65` source file. You can find the entry table structure
documentation in the source file. Maximum of 99 entries is allowed, anything above that will be ignored.
## PCB ## PCB
@ -76,6 +82,6 @@ http://github.com/flowenol/applesoft-lite
## How to install hardware? ## How to install hardware?
Just put the board in right orientation (as marked on the PCB) in the Apple-1 expansion slot. Just put the board in right orientation (as marked on the PCB) in the Apple-1 expansion slot.
Or you can use the port expander if the on board slot is already occupied: Or you can use the port expander if the expansion slot on the Apple-1 board is already occupied:
https://github.com/flowenol/Apple1ExpanderPcb https://github.com/flowenol/Apple1ExpanderPcb

View File

@ -22,17 +22,22 @@
#define str_addr $40 #define str_addr $40
; entries scanning variables ; entries scanning variables
#define entries_counter $42 #define entries_number $42
#define entries_scan_addr $43 #define entries_counter $43
#define entry_segments $45 #define entries_counter_bcd $44
#define entry_to_load $46 #define entries_scan_addr $45
#define entry_segments $47
#define entry_to_load $48
; jmp addr variable ; jmp addr variable
#define jmp_addr $47 #define jmp_addr $49
; option select variables #define key_data $4B
#define option_data $49
#define key_data $50 #define option_data $00
#define entries_per_page $14
#define max_entries $63
* = $4000 * = $4000
@ -44,17 +49,49 @@ start
; enable rom bank ; enable rom bank
sta rom_bank sta rom_bank
; print entries and get option ; 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 jsr print_entries
input
jsr get_option 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 ; option validation
lda option_data lda option_data
beq start ; invalid - user typed "0" or "00"
beq show_entries
cmp rom_content cmp entries_number
; valid - last entry
beq valid_option beq valid_option
bpl start
; invalid out of range
bcs show_entries
valid_option valid_option
lda option_data lda option_data
@ -252,6 +289,7 @@ print_entries
; init entries counter ; init entries counter
lda #$00 lda #$00
sta entries_counter sta entries_counter
sta entries_counter_bcd
; init entries scan addr ; init entries scan addr
lda #<rom_content lda #<rom_content
@ -285,8 +323,13 @@ skip_segment
; print entry number ; print entry number
inc entries_counter inc entries_counter
ldx #entries_counter sed
jsr print_number clc
lda #$01
adc entries_counter_bcd
sta entries_counter_bcd
jsr print_number_bcd
cld
; print dot and space ; print dot and space
lda #'.' lda #'.'
@ -313,14 +356,28 @@ skip_segment
jsr add_to_addr jsr add_to_addr
; skip entry jump address ; skip entry jump address
ldx #entries_scan_addr
lda #$02 lda #$02
jsr add_to_addr jsr add_to_addr
; if not last entry then repeat ; if not last entry then repeat
lda rom_content lda entries_number
cmp entries_counter cmp entries_counter
beq print_entries_done
jsr entries_page_hit
bne print_entry 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_entries_done
; print choose string ; print choose string
lda #<choose_str lda #<choose_str
@ -328,7 +385,6 @@ print_entries_done
lda #>choose_str lda #>choose_str
sta str_addr+1 sta str_addr+1
jsr print_str jsr print_str
rts rts
print_str print_str
@ -349,56 +405,66 @@ print_str_loop
bne print_str_loop bne print_str_loop
rts rts
; prints only numbers in range 0-19 print_number_bcd
print_number pha
lda #$09 clc
cmp $00,X and #$F0
bmi greater_than_nine rol
lda $00,X rol
rol
rol
rol
beq print_next_digit
jsr prhex jsr prhex
jmp print_number_done
greater_than_nine print_next_digit
lda #$01 pla
and #$0F
jsr prhex jsr prhex
; save number in Y
lda $00,X
tay
; decrement 10
lda #$09
sta $00,X
tya
sbc $00,X
jsr prhex
; restore number from Y
tya
sta $00,X
print_number_done print_number_done
rts 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 ;;; printing-end
;;; get-option ;;; get-option
get_option get_option
; init digits counter ; stores option number in option_data, digits count in X
; init digits counter in X
ldx #$00 ldx #$00
get_key get_key
; wait for key ; wait for key
lda kbd_cr lda kbd_cr
bpl get_key bpl get_key
lda kbd_data lda kbd_data
and #$7F
; store key data ; store key data
sta key_data sta key_data
; if CR check if option is satisfied ; if CR check if option is satisfied
cmp #$8D ; CR cmp #$0D ; CR
beq get_key_done beq get_key_done
; check range 0-9 ; check range 0-9
cmp #$B0 ; 0 cmp #$30 ; 0
bmi get_key bmi get_key
cmp #$BA ; 9 cmp #$3A ; 9
bpl get_key bpl get_key
; which digit we are processing? ; which digit we are processing?
@ -416,7 +482,7 @@ one_digit
; ??? ; ???
sec sec
lda key_data lda key_data
sbc #$B0 sbc #$30
sta option_data sta option_data
echo_key echo_key
@ -446,7 +512,7 @@ two_digit_inc_done
; compute int value from second digit ; compute int value from second digit
sec sec
lda key_data lda key_data
sbc #$B0 sbc #$30
; and store in option_data ; and store in option_data
sta option_data sta option_data
@ -461,10 +527,6 @@ two_digit_inc_done
jmp echo_key jmp echo_key
get_key_done get_key_done
; if CR was pressed as the first key, then simply omit
txa
beq get_key
; print CR ; print CR
lda #$8D ; CR lda #$8D ; CR
jsr echo jsr echo
@ -481,6 +543,7 @@ increment_16bit
increment_16bit_done increment_16bit_done
rts rts
;; adds A to ZP address in X
add_to_addr add_to_addr
clc clc
adc $00,X adc $00,X
@ -497,6 +560,57 @@ add_to_addr_done
welcome_str .byt $15,$0D,"AVAILABLE OPTIONS:",$0D,$0D welcome_str .byt $15,$0D,"AVAILABLE OPTIONS:",$0D,$0D
choose_str .byt $0F,$0D,"CHOOSE OPTION:" choose_str .byt $0F,$0D,"CHOOSE OPTION:"
choose_next_str .byt $27,$0D,"CHOOSE OPTION (PRESS RETURN FOR NEXT):"
loader_end 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" #include "src/rom_content.a65"

View File

@ -1,5 +1,5 @@
* = $4800 * = $4800
.dsb (*-loader_end), $FF .dsb (*-fast_loader_end), $FF
; start of loader entry table section ; start of loader entry table section
@ -9,7 +9,7 @@ rom_content = $4800
; define the number of available entries ; define the number of available entries
number_of_entries .byt $08 number_of_entries .byt $08
; entry srtucture ; entry structure
; number of segments - byte ; number of segments - byte
; ;
; repeat for each segment: ; repeat for each segment:
@ -171,6 +171,7 @@ count10_3_cont_start .word count10_fix_cont
count10_str .byt $13,"COUNT TO 10 (ASOFT)" count10_str .byt $13,"COUNT TO 10 (ASOFT)"
count10_jmp_addr .word $7DF4 count10_jmp_addr .word $7DF4
; end of loader entry table section ; end of loader entry table section
; start of binary content section ; start of binary content section