mirror of
https://github.com/flowenol/apple1cartridge.git
synced 2024-12-26 13:31:15 +00:00
Fast loader and bugfixes in firmware
This commit is contained in:
parent
7a38e133a9
commit
4eed9a3270
26
README.md
26
README.md
@ -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
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user