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
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
~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.
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
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`)
and to provide continuous 44KB wide RAM address space instead.
The A1C expansion card allows to completely disable the ROM/loader functionality (via physical switch) which takes up to 2 KB of
memory (`$4000-$47FF`) and to provide continuous 44KB wide RAM address space instead (`$1000-$BFFF`).
## Memory map
Physical switch in ROM mode:
With physical switch in ROM mode:
| address | function |
| --- | --- |
| `$0000` | program entry to load via the fast loader program |
| `$1000-$3FFF` | RAM region #1 |
| `$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 |
| `$4800-$BFFF` | RAM region #2 when ROM banked out |
| `$4800-$BFFF` | ROM with program contents when ROM banked in |
Physical Switch in RAM mode:
With physical switch in RAM mode:
| 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)
* 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
* 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
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
* 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?
@ -58,7 +63,8 @@ And to clean the build:
# 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
@ -76,6 +82,6 @@ http://github.com/flowenol/applesoft-lite
## How to install hardware?
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

View File

@ -22,17 +22,22 @@
#define str_addr $40
; entries scanning variables
#define entries_counter $42
#define entries_scan_addr $43
#define entry_segments $45
#define entry_to_load $46
#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 $47
#define jmp_addr $49
; option select variables
#define option_data $49
#define key_data $50
#define key_data $4B
#define option_data $00
#define entries_per_page $14
#define max_entries $63
* = $4000
@ -44,17 +49,49 @@ start
; enable 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
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
beq start
; invalid - user typed "0" or "00"
beq show_entries
cmp rom_content
cmp entries_number
; valid - last entry
beq valid_option
bpl start
; invalid out of range
bcs show_entries
valid_option
lda option_data
@ -252,6 +289,7 @@ print_entries
; init entries counter
lda #$00
sta entries_counter
sta entries_counter_bcd
; init entries scan addr
lda #<rom_content
@ -285,8 +323,13 @@ skip_segment
; print entry number
inc entries_counter
ldx #entries_counter
jsr print_number
sed
clc
lda #$01
adc entries_counter_bcd
sta entries_counter_bcd
jsr print_number_bcd
cld
; print dot and space
lda #'.'
@ -313,14 +356,28 @@ skip_segment
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 rom_content
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
@ -328,7 +385,6 @@ print_entries_done
lda #>choose_str
sta str_addr+1
jsr print_str
rts
print_str
@ -349,56 +405,66 @@ print_str_loop
bne print_str_loop
rts
; prints only numbers in range 0-19
print_number
lda #$09
cmp $00,X
bmi greater_than_nine
lda $00,X
print_number_bcd
pha
clc
and #$F0
rol
rol
rol
rol
rol
beq print_next_digit
jsr prhex
jmp print_number_done
greater_than_nine
lda #$01
print_next_digit
pla
and #$0F
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
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
; init digits counter
; 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 #$8D ; CR
cmp #$0D ; CR
beq get_key_done
; check range 0-9
cmp #$B0 ; 0
cmp #$30 ; 0
bmi get_key
cmp #$BA ; 9
cmp #$3A ; 9
bpl get_key
; which digit we are processing?
@ -416,7 +482,7 @@ one_digit
; ???
sec
lda key_data
sbc #$B0
sbc #$30
sta option_data
echo_key
@ -446,7 +512,7 @@ two_digit_inc_done
; compute int value from second digit
sec
lda key_data
sbc #$B0
sbc #$30
; and store in option_data
sta option_data
@ -461,10 +527,6 @@ two_digit_inc_done
jmp echo_key
get_key_done
; if CR was pressed as the first key, then simply omit
txa
beq get_key
; print CR
lda #$8D ; CR
jsr echo
@ -481,6 +543,7 @@ increment_16bit
increment_16bit_done
rts
;; adds A to ZP address in X
add_to_addr
clc
adc $00,X
@ -497,6 +560,57 @@ add_to_addr_done
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"

View File

@ -1,5 +1,5 @@
* = $4800
.dsb (*-loader_end), $FF
.dsb (*-fast_loader_end), $FF
; start of loader entry table section
@ -9,7 +9,7 @@ rom_content = $4800
; define the number of available entries
number_of_entries .byt $08
; entry srtucture
; entry structure
; number of segments - byte
;
; 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_jmp_addr .word $7DF4
; end of loader entry table section
; start of binary content section