Flash-ready version

Tweaks needed to build a flashable version of the toolbox.
This commit is contained in:
Peter Weingartner 2024-08-11 17:48:00 -04:00
parent 85e6941b5a
commit e45ce4000d
39 changed files with 859 additions and 162 deletions

12
roms/f256k/README.md Normal file
View file

@ -0,0 +1,12 @@
# ROM Files for the F256K
This directory contains BIN files for programming the F256K flash memory with the Foenix Toolbox.
## How to Install
Currently, the toolbox must be installed by bulk programming the flash memory.
Using the FoenixMgr Python script, this can be done with the following command (substitute the device path or name for your F256K's USB debug port):
```
python FoenixMgr.zip --port {debug device name} --flash-bulk toolbox.csv
```

BIN
roms/f256k/toolbox-00.bin Normal file

Binary file not shown.

BIN
roms/f256k/toolbox-01.bin Normal file

Binary file not shown.

BIN
roms/f256k/toolbox-02.bin Normal file

Binary file not shown.

BIN
roms/f256k/toolbox-03.bin Normal file

Binary file not shown.

BIN
roms/f256k/toolbox-04.bin Normal file

Binary file not shown.

BIN
roms/f256k/toolbox-05.bin Normal file

Binary file not shown.

BIN
roms/f256k/toolbox-06.bin Normal file

Binary file not shown.

BIN
roms/f256k/toolbox-07.bin Normal file

Binary file not shown.

BIN
roms/f256k/toolbox-08.bin Normal file

Binary file not shown.

BIN
roms/f256k/toolbox-09.bin Normal file

Binary file not shown.

BIN
roms/f256k/toolbox-0A.bin Normal file

Binary file not shown.

BIN
roms/f256k/toolbox-0B.bin Normal file

Binary file not shown.

BIN
roms/f256k/toolbox-0C.bin Normal file

Binary file not shown.

BIN
roms/f256k/toolbox-0D.bin Normal file

Binary file not shown.

BIN
roms/f256k/toolbox-0E.bin Normal file

Binary file not shown.

BIN
roms/f256k/toolbox-0F.bin Normal file

Binary file not shown.

BIN
roms/f256k/toolbox-3F.bin Normal file

Binary file not shown.

BIN
roms/f256k/toolbox.bin Normal file

Binary file not shown.

17
roms/f256k/toolbox.csv Normal file
View file

@ -0,0 +1,17 @@
"00","toolbox-00.bin"
"01","toolbox-01.bin"
"02","toolbox-02.bin"
"03","toolbox-03.bin"
"04","toolbox-04.bin"
"05","toolbox-05.bin"
"06","toolbox-06.bin"
"07","toolbox-07.bin"
"08","toolbox-08.bin"
"09","toolbox-09.bin"
"0A","toolbox-0A.bin"
"0B","toolbox-0B.bin"
"0C","toolbox-0C.bin"
"0D","toolbox-0D.bin"
"0E","toolbox-0E.bin"
"0F","toolbox-0F.bin"
"3F","toolbox-3F.bin"
1 00 toolbox-00.bin
2 01 toolbox-01.bin
3 02 toolbox-02.bin
4 03 toolbox-03.bin
5 04 toolbox-04.bin
6 05 toolbox-05.bin
7 06 toolbox-06.bin
8 07 toolbox-07.bin
9 08 toolbox-08.bin
10 09 toolbox-09.bin
11 0A toolbox-0A.bin
12 0B toolbox-0B.bin
13 0C toolbox-0C.bin
14 0D toolbox-0D.bin
15 0E toolbox-0E.bin
16 0F toolbox-0F.bin
17 3F toolbox-3F.bin

55
src/C256/addresses.csv Normal file
View file

@ -0,0 +1,55 @@
"sys_proc_exit","FFE000"
"sys_chan_read_b","FFE004"
"sys_chan_read","FFE008"
"sys_chan_readline","FFE00C"
"sys_chan_write_b","FFE010"
"sys_chan_write","FFE014"
"sys_chan_status","FFE018"
"sys_chan_flush","FFE01C"
"sys_chan_seek","FFE020"
"sys_chan_ioctrl","FFE024"
"sys_chan_open","FFE028"
"sys_chan_close","FFE02C"
"sys_chan_swap","FFE030"
"sys_chan_device","FFE034"
"sys_bdev_register","FFE038"
"sys_bdev_read","FFE03C"
"sys_bdev_write","FFE040"
"sys_bdev_status","FFE044"
"sys_bdev_flush","FFE048"
"sys_bdev_ioctrl","FFE04C"
"sys_fsys_open","FFE050"
"sys_fsys_close","FFE054"
"sys_fsys_opendir","FFE058"
"sys_fsys_closedir","FFE05C"
"sys_fsys_readdir","FFE060"
"sys_fsys_findfirst","FFE064"
"sys_fsys_findnext","FFE068"
"sys_fsys_mkdir","FFE06C"
"sys_fsys_delete","FFE070"
"sys_fsys_rename","FFE074"
"sys_fsys_set_cwd","FFE078"
"sys_fsys_get_cwd","FFE07C"
"sys_fsys_load","FFE080"
"sys_fsys_register_loader","FFE084"
"sys_fsys_stat","FFE088"
"sys_mem_get_ramtop","FFE08C"
"sys_mem_reserve","FFE090"
"sys_err_message","FFE094"
"sys_proc_run","FFE098"
"sys_txt_get_capabilities","FFE09C"
"sys_txt_set_mode","FFE0A0"
"sys_txt_setsizes","FFE0A4"
"sys_txt_set_xy","FFE0A8"
"sys_txt_get_xy","FFE0AC"
"sys_txt_get_region","FFE0B0"
"sys_txt_set_region","FFE0B4"
"sys_txt_set_color","FFE0B8"
"sys_txt_get_color","FFE0BC"
"sys_txt_set_cursor_visible","FFE0C0"
"sys_txt_set_font","FFE0C4"
"sys_txt_get_sizes","FFE0C8"
"sys_txt_set_border","FFE0CC"
"sys_txt_set_border_color","FFE0D0"
"sys_txt_put","FFE0D4"
"sys_txt_print","FFE0D8"
1 sys_proc_exit FFE000
2 sys_chan_read_b FFE004
3 sys_chan_read FFE008
4 sys_chan_readline FFE00C
5 sys_chan_write_b FFE010
6 sys_chan_write FFE014
7 sys_chan_status FFE018
8 sys_chan_flush FFE01C
9 sys_chan_seek FFE020
10 sys_chan_ioctrl FFE024
11 sys_chan_open FFE028
12 sys_chan_close FFE02C
13 sys_chan_swap FFE030
14 sys_chan_device FFE034
15 sys_bdev_register FFE038
16 sys_bdev_read FFE03C
17 sys_bdev_write FFE040
18 sys_bdev_status FFE044
19 sys_bdev_flush FFE048
20 sys_bdev_ioctrl FFE04C
21 sys_fsys_open FFE050
22 sys_fsys_close FFE054
23 sys_fsys_opendir FFE058
24 sys_fsys_closedir FFE05C
25 sys_fsys_readdir FFE060
26 sys_fsys_findfirst FFE064
27 sys_fsys_findnext FFE068
28 sys_fsys_mkdir FFE06C
29 sys_fsys_delete FFE070
30 sys_fsys_rename FFE074
31 sys_fsys_set_cwd FFE078
32 sys_fsys_get_cwd FFE07C
33 sys_fsys_load FFE080
34 sys_fsys_register_loader FFE084
35 sys_fsys_stat FFE088
36 sys_mem_get_ramtop FFE08C
37 sys_mem_reserve FFE090
38 sys_err_message FFE094
39 sys_proc_run FFE098
40 sys_txt_get_capabilities FFE09C
41 sys_txt_set_mode FFE0A0
42 sys_txt_setsizes FFE0A4
43 sys_txt_set_xy FFE0A8
44 sys_txt_get_xy FFE0AC
45 sys_txt_get_region FFE0B0
46 sys_txt_set_region FFE0B4
47 sys_txt_set_color FFE0B8
48 sys_txt_get_color FFE0BC
49 sys_txt_set_cursor_visible FFE0C0
50 sys_txt_set_font FFE0C4
51 sys_txt_get_sizes FFE0C8
52 sys_txt_set_border FFE0CC
53 sys_txt_set_border_color FFE0D0
54 sys_txt_put FFE0D4
55 sys_txt_print FFE0D8

View file

@ -9,7 +9,7 @@
#endif
.section stack
.section code
.section farcode
;
; Reset the stack to the initial value.

149
src/C256/f256-cstartup.s Normal file
View file

@ -0,0 +1,149 @@
;;; Startup variant, change attribute value if you make your own
.rtmodel cstartup,"f256"
.rtmodel version, "1"
.rtmodel core, "*"
.section stack
.section cstack
.section heap
.section data_init_table
.extern main, exit
.extern _Dp, _Vfp
.extern _DirectPageStart
#ifndef __CALYPSI_DATA_MODEL_SMALL__
.extern _NearBaseAddress
#endif
#include "macros.h"
;;; ***************************************************************************
;;;
;;; The reset vector. This uses the entry point label __program_root_section
;;; which by default is what the linker will pull in first.
;;;
;;; ***************************************************************************
.section reset
.pubweak __program_root_section
__program_root_section:
.word __program_start
;;; ***************************************************************************
;;;
;;; __program_start - actual start point of the program
;;;
;;; Set up CPU stack, initialize sections and call main().
;;; You can override this with your own routine, or tailor it as needed.
;;; The easiest way to make custom initialization is to provide your own
;;; __low_level_init which gets called after stacks have been initialized.
;;;
;;; ***************************************************************************
#ifdef __CALYPSI_CODE_MODEL_COMPACT__
.section code
#else
.section code, noreorder
#endif
.pubweak __program_start
__program_start:
clc
xce ; native 16-bit mode
rep #0x38 ; 16-bit registers, no decimal mode
ldx ##.sectionEnd stack
txs ; set stack
lda ##_DirectPageStart
tcd ; set direct page
#ifdef __CALYPSI_DATA_MODEL_SMALL__
lda ##0
#else
lda ##.word2 _NearBaseAddress
#endif
stz dp:.tiny(_Vfp+2)
xba ; A upper half = data bank
pha
plb ; pop 8 dummy
plb ; set data bank
#ifdef __CALYPSI_CODE_MODEL_COMPACT__
jmp long:_Trampoline_program_start
.section compactcode, noreorder
_Trampoline_program_start:
#define CODE compactcode
#elif __CALYPSI_CODE_MODEL_LARGE__
jmp long:_Trampoline_program_start
.section farcode, noreorder
_Trampoline_program_start:
#define CODE farcode
#else
#define CODE code
#endif
call __low_level_init
;;; **** Initialize data sections if needed.
.section CODE, noroot, noreorder
.pubweak __data_initialization_needed
.extern __initialize_sections
__data_initialization_needed:
lda ##.word2 (.sectionEnd data_init_table)
sta dp:.tiny(_Dp+6)
lda ##.word0 (.sectionEnd data_init_table)
sta dp:.tiny(_Dp+4)
lda ##.word2 (.sectionStart data_init_table)
sta dp:.tiny(_Dp+2)
lda ##.word0 (.sectionStart data_init_table)
sta dp:.tiny(_Dp+0)
call __initialize_sections
;;; **** Initialize streams if needed.
.section CODE, noroot, noreorder
.pubweak __call_initialize_global_streams
.extern __initialize_global_streams
__call_initialize_global_streams:
call __initialize_global_streams
;;; **** Initialize heap if needed.
.section CODE, noroot, noreorder
.pubweak __call_heap_initialize
.extern __heap_initialize, __default_heap
__call_heap_initialize:
#ifdef __CALYPSI_DATA_MODEL_SMALL__
lda ##.sectionSize heap
sta dp:.tiny(_Dp+2)
lda ##.sectionStart heap
sta dp:.tiny(_Dp+0)
lda ##__default_heap
#else
lda ##.word2 (.sectionStart heap)
sta dp:.tiny(_Dp+6)
lda ##.word0 (.sectionStart heap)
sta dp:.tiny(_Dp+4)
lda ##.word2 __default_heap
sta dp:.tiny(_Dp+2)
lda ##.word0 __default_heap
sta dp:.tiny(_Dp+0)
ldx ##.word2 (.sectionSize heap)
lda ##.word0 (.sectionSize heap)
#endif
call __heap_initialize
.section CODE, root, noreorder
lda ##0 ; argc = 0
call main
jump exit
;;; ***************************************************************************
;;;
;;; __low_level_init - custom low level initialization
;;;
;;; This default routine just returns doing nothing. You can provide your own
;;; routine, either in C or assembly for doing custom low leve initialization.
;;;
;;; ***************************************************************************
.section libcode
.pubweak __low_level_init
__low_level_init:
return

57
src/C256/f256-flash.scm Normal file
View file

@ -0,0 +1,57 @@
(define memories
'(
(memory flash
(address (#xf80000 . #xfdffff))
(type ROM)
(fill #xff)
(section
(jumptable #xf80000)
data_init_table
data
ifar))
(memory flash-shadow
(address (#xffff00 . #xffffff))
(type ROM)
(fill 0)
(section
(LoCodeStorage #xffff00)
(VectorStorage #xffffe0)))
(memory LoCode
(address (#x00ff00 . #x00ffdf))
(type ROM)
(scatter-to LoCodeStorage)
(section code cdata))
(memory Vector
(address (#x00ffe0 . #x00ffff))
(type ROM)
(scatter-to VectorStorage)
(section (reset #xfffc)))
(memory hiram
(address (#x070000 . #x07ffff))
(type RAM)
(section heap))
(memory loram
(address (#x00d000 . #x00dfff))
(type RAM)
(placement-group nobits (section zdata znear))
(placement-group bits (section data near)))
(memory stackram
(address (#x00c000 . #x00cfff))
(type RAM)
(section stack))
(memory DirectPage
(address (#x00bf00 . #x00bfff))
(section (registers ztiny)))
(block stack (size #x1000))
(block heap (size #x1000))
(base-address _DirectPageStart DirectPage 0)
(base-address _NearBaseAddress hiram 0)
))

View file

@ -1,10 +1,15 @@
(define memories
'((memory flash (address (#x040000 . #x07ffff))
(type rom))
(type rom)
)
(memory DirectPage (address (#x00c000 . #x00c0ff))
(section (registers ztiny)))
(memory LoRAM (address (#x00c100 . #x00efff))
(section stack data zdata data heap))
(memory RAM-jumptable
(address (#x00f000 . #x00feff))
(section jumptable))
(memory NearRAM1 (address (#x010000 . #x017fff))
(section znear near))
(memory NearRAM2 (address (#x018000 . #x01ffff))
@ -13,8 +18,8 @@
(section far huge))
(memory FarRAM2 (address (#x030000 . #x03ffff))
(section zfar zhuge ))
(memory LoCODE (address (#x00f000 . #x00ffdf))
(section code cdata (jumptable #x00f000)))
(memory LoCODE (address (#x00ff00 . #x00ffdf))
(section code cdata))
(memory Vector (address (#x00ffe0 . #x00ffff))
(section (reset #xfffc)))
(block stack (size #x1000))

View file

@ -1,5 +1,12 @@
(define memories
'((memory flash (address (#xf80000 . #xffffff))
'(
(memory HiCode1 (address (#xfc0000 . #xfcffff))
(section cfar switch data_init_table idata ifar farcode))
(memory HiCode2 (address (#xfd0000 . #xfdffff))
(section cfar switch data_init_table idata ifar farcode))
(memory HiCode3 (address (#xfe0000 . #xfeffff))
(section cfar switch data_init_table idata ifar farcode))
(memory flash (address (#xff0000 . #xffffff))
(fill 0)
(section
(LoCodeStorage #xffe000)
@ -22,12 +29,6 @@
(memory Vector (address (#x00ffe0 . #x00ffff))
(scatter-to VectorStorage)
(section (reset #xfffc)))
(memory HiCode1 (address (#xf80000 . #xf8ffff))
(section cfar switch data_init_table ifar farcode))
(memory HiCode2 (address (#xf90000 . #xf9ffff))
(section cfar switch data_init_table ifar farcode))
(memory HiCode3 (address (#xfa0000 . #xfaffff))
(section cfar switch data_init_table ifar farcode))
(block stack (size #x1000))
(block heap (size #x1000))
(base-address _DirectPageStart DirectPage 0)

19
src/C256/genaddresses.py Normal file
View file

@ -0,0 +1,19 @@
address = 0xffe000
# Read in the list of system calls ("sys_")
with open("addresses.csv", "w") as addresses:
with open("syscalls.txt", "r") as call_names:
for line in call_names:
# Remove comments
index = line.find("#")
if index == 0:
line = ""
elif index > 0:
line = line[index - 1:]
line = line.strip()
# Process only actual names
if len(line) > 0:
addresses.write("\"sys_{0}\",\"{1:06X}\"\n".format(line, address))
address = address + 4

View file

@ -2,8 +2,8 @@
;;; Low-level support code for the IEC port
;;;
;;; NOTE: routines will be split into private routines and public routines.
;;; Private routines will assume near JSRs, 8-bit accumulator and index registers, and interrupts disabled.
;;; Public routines will assume far JSRs and 16-bit accumulator and index registers.
;;; Private routines will assume near jsls, 8-bit accumulator and index registers, and interrupts disabled.
;;; Public routines will assume far jsls and 16-bit accumulator and index registers.
;;; Public routines will also assume Calypsi calling conventions.
;;;
@ -21,14 +21,14 @@
#include "F256/iec_f256.h"
.section data,data
.section ztiny,bss
eoi_pending: .byte 0
rx_eoi: .byte 0
delayed: .byte 0
queue: .byte 0
eoi_pending: .space 1
rx_eoi: .space 1
delayed: .space 1
queue: .space 1
.section code
.section farcode
;;
;; Macros
@ -40,7 +40,7 @@ assert_bit: .macro pin
and #(\pin ^ 0xff)
sta IEC_OUTPUT_PORT
pla
rts
rtl
.endm
release_bit: .macro pin
@ -49,7 +49,7 @@ release_bit: .macro pin
ora #(\pin)
sta IEC_OUTPUT_PORT
pla
rts
rtl
.endm
read_bit: .macro pin
@ -60,7 +60,7 @@ loop$ lda IEC_INPUT_PORT
and #(\pin)
cmp #1
pla
rts
rtl
.endm
emit: .macro char
@ -106,38 +106,38 @@ sleep_20us: phx
_loop$ dex
bne _loop$
plx
rts
rtl
sleep_100us: phx
ldx #5
_loop$ jsr sleep_20us
_loop$ jsl sleep_20us
dex
bne _loop$
plx
rts
rtl
sleep_300us: jsr sleep_100us
jsr sleep_100us
jsr sleep_100us
rts
sleep_300us: jsl sleep_100us
jsl sleep_100us
jsl sleep_100us
rtl
sleep_1ms: jsr sleep_300us
jsr sleep_300us
jsr sleep_300us
jmp sleep_100us
sleep_1ms: jsl sleep_300us
jsl sleep_300us
jsl sleep_300us
jmp long: sleep_100us
;;
;; Code to handle the IEC port
;;
init: jsr sleep_1ms
jsr release_ATN
jsr release_DATA
jsr release_SREQ
jsr assert_CLOCK ; IDLE state
jsr sleep_1ms
jsr sleep_1ms
jsr sleep_1ms
init: jsl sleep_1ms
jsl release_ATN
jsl release_DATA
jsl release_SREQ
jsl assert_CLOCK ; IDLE state
jsl sleep_1ms
jsl sleep_1ms
jsl sleep_1ms
; Bail if ATN and SRQ fail to float back up.
; We'll have a more thorough test when we send
@ -145,18 +145,18 @@ init: jsr sleep_1ms
nop
nop
nop
jsr read_SREQ
jsl read_SREQ
bcc err$
jsr read_ATN
jsl read_ATN
bcc err$
jsr sleep_1ms
jsl sleep_1ms
clc
rts
rtl
err$ sec
rts
rtl
;
; Send a command byte and release the DATA and CLOCK lines afterwards
@ -164,25 +164,25 @@ err$ sec
; A = the command byte to send
;
atn_release_data
jsr release_DATA
jsr release_CLOCK ; TODO: makes /no/ sense; maybe we can remove...
jsr atn_common ; NOTE: does NOT release ATN! Does NOT release IRQs!
rts
jsl release_DATA
jsl release_CLOCK ; TODO: makes /no/ sense; maybe we can remove...
jsl atn_common ; NOTE: does NOT release ATN! Does NOT release IRQs!
rtl
;
; Send a command byte and release the ATN, DATA, and CLOCK lines
;
; A = the command byte to send
;
atn_release jsr atn_common
atn_release jsl atn_common
jsr release_ATN
jsr sleep_20us
jsr sleep_20us
jsr sleep_20us
jsr release_CLOCK
jsr release_DATA
rts
jsl release_ATN
jsl sleep_20us
jsl sleep_20us
jsl sleep_20us
jsl release_CLOCK
jsl release_DATA
rtl
;
; Send a command byte with ATN asserted
@ -193,41 +193,41 @@ atn_common
; Assert ATN; if we aren't already in sending mode,
; get there:
jsr assert_ATN
jsr assert_CLOCK
jsr release_DATA
jsl assert_ATN
jsl assert_CLOCK
jsl release_DATA
; Now give the devices ~1ms to start listening.
jsr sleep_1ms
jsl sleep_1ms
; If no one is listening, there's nothing on
; the bus, so signal an error.
jsr read_DATA
jsl read_DATA
bcs err$
; ATN bytes are technically never EOI bytes
stz eoi_pending
jmp send
jmp long: send
err$
; Always release the ATN line on error; TODO: add post delay
jmp release_ATN
jmp long: release_ATN
;
; Send a byte over the IEC bus but mark it as the last byte
;
; A = the byte to send
;
send_eoi jsr set_eoi
jmp send
send_eoi jsl set_eoi
jmp long: send
;
; Set that the EOI byte is the next to be sent
;
set_eoi stz eoi_pending
dec eoi_pending
rts
rtl
;
; Sends the queued byte with an EOI
@ -237,9 +237,9 @@ flush bit delayed
pha
lda queue
stz delayed
jsr send_eoi
jsl send_eoi
pla
done$: rts
done$: rtl
;
; Send a byte over the IEC bus
@ -251,26 +251,26 @@ send
; the host is asserting CLOCK and the devices are asserting DATA.
; There must be at least 100us between bytes.
jsr sleep_300us
jsl sleep_300us
; ; Clever cheating (PJW: removed since we disable interrupts for all this code)
; ; Act as an ersatz listener to keep the other listeners busy
; ; until we are ready to receive. This is NOT part of the
; ; IEC protocol -- we are doing this in lieu of an interrupt.
; jsr assert_DATA
; jsl assert_DATA
; Release CLOCK to signal that we are ready to send
; We can do this without disabling interrupts because
; we are also asserting DATA.
jsr release_CLOCK
jsl release_CLOCK
; Now we wait for all of the listeners to acknowledge.
wait$
jsr sleep_20us
jsl sleep_20us
; Check to see if all listeners have acknowledged
jsr read_DATA
jsl read_DATA
bcs ready$
; Other listeners are still busy; go back to sleep.
@ -288,7 +288,7 @@ eoi$
; already had the opportunity to delay before starting the
; ack, so hopefully it will stay in nominal 250us range.
TYE$ jsr read_DATA
TYE$ jsl read_DATA
bcs TYE$
; Now we're basically back to the point where we are waiting
@ -299,13 +299,13 @@ TYE$ jsr read_DATA
; The drive should hold DATA for at least 60us. Give it
; 20us, and then repeat our ersatz listener trick.
jsr sleep_20us
; jsr assert_DATA (PJW: removed trick)
jsl sleep_20us
; jsl assert_DATA (PJW: removed trick)
bra wait$
send$
; Give the listeners time to notice that the've all ack'd
jsr sleep_20us ; NOT on the C64
jsl sleep_20us ; NOT on the C64
; Now start pushing out the bits. Note that the timing
; is not critical, but each clock state must last at
@ -317,32 +317,32 @@ loop$
; TODO: opt test for a frame error
; Clock out the next bit
jsr assert_CLOCK
jsr sleep_20us
jsl assert_CLOCK
jsl sleep_20us
lsr a
bcs one$
zero$ jsr assert_DATA
zero$ jsl assert_DATA
bra clock$
one$ jsr release_DATA
one$ jsl release_DATA
bra clock$
clock$
; Toggle the clock
jsr sleep_20us ; TODO: Maybe extend this.
jsl sleep_20us ; TODO: Maybe extend this.
jsr sleep_20us ; 1541 needs this.
jsr release_CLOCK
jsl sleep_20us ; 1541 needs this.
jsl release_CLOCK
jsr sleep_20us
jsl sleep_20us
dex
bne loop$
plx
; Finish the last bit and wait for the listeners to ack.
jsr release_DATA
jsr assert_CLOCK
jsl release_DATA
jsl assert_CLOCK
; Now wait for listener ack. Of course, if there are
; multiple listeners, we can only know that one ack'd.
@ -352,10 +352,10 @@ clock$
; TODO: ATN release timing appears to be semi-critical; we may need
; to completely change the code below.
ack$ jsr read_DATA
ack$ jsl read_DATA
bcs ack$
clc
rts
rtl
;
; Wait for a byte of data to be read from the IEC port
@ -366,16 +366,16 @@ recv_data
stz rx_eoi
; Wait for the sender to have a byte
wait1$ jsr read_CLOCK
wait1$ jsl read_CLOCK
bcc wait1$
; TODO: start and check a timer
; Signal we are ready to receive
ready$ jsr release_DATA
ready$ jsl release_DATA
; Wait for all other listeners to signal
wait2$ jsr read_DATA
wait2$ jsl read_DATA
bcc wait2$
; Wait for the first bit or an EOI condition
@ -383,7 +383,7 @@ wait2$ jsr read_DATA
lda #0 ; counter
wait3$ inc a
beq eoi$
jsr read_CLOCK
jsl read_CLOCK
bcc recv$
adc #7 ; microseconds per loop
bcc wait3$
@ -392,10 +392,10 @@ eoi$ lda rx_eoi
bmi error$
; Ack the EOI
jsr assert_DATA
jsr sleep_20us
jsr sleep_20us
jsr sleep_20us
jsl assert_DATA
jsl sleep_20us
jsl sleep_20us
jsl sleep_20us
; Set the EOI flag.
dec rx_eoi ; TODO: error on second round
@ -404,42 +404,42 @@ eoi$ lda rx_eoi
bra ready$
error$ sec
rts
rtl
recv$
; Clock in the bits
phx
ldx #8
wait_fall$ jsr read_CLOCK
wait_fall$ jsl read_CLOCK
bcs wait_fall$
wait_rise$ jsr read_CLOCK
wait_rise$ jsl read_CLOCK
bcc wait_rise$
jsr read_DATA
jsl read_DATA
ror a
dex
bne wait_fall$
plx
; Ack
jsr sleep_20us
jsr assert_DATA
jsl sleep_20us
jsl assert_DATA
; Drives /usually/ work with a lot less, but
; I see failures on the SD2IEC on a status check
; after file-not-found when debugging is turned off.
jsr sleep_20us ; Seems to be missing the ack.
jsr sleep_20us ; Seems to be missing the ack.
jsr sleep_20us ; Seems to be missing the ack.
jsr sleep_20us ; Seems to be missing the ack.
jsl sleep_20us ; Seems to be missing the ack.
jsl sleep_20us ; Seems to be missing the ack.
jsl sleep_20us ; Seems to be missing the ack.
jsl sleep_20us ; Seems to be missing the ack.
; Return EOI in NV
clc
bit rx_eoi
ora #0
rts
rtl
;;
;; Public Functions
@ -458,7 +458,7 @@ iecll_ioinit php
stz delayed
jsr init
jsl init
bcs err$
plp
@ -481,8 +481,8 @@ iecll_talk php
sep #0x30
ora #0x40
jsr flush
jsr atn_release_data ; NOTE: does NOT drop ATN!
jsl flush
jsl atn_release_data ; NOTE: does NOT drop ATN!
plp
rtl
@ -498,12 +498,12 @@ iecll_talk_sa php
sei
sep #0x30
jsr atn_common
jsl atn_common
jsr assert_DATA
jsr release_ATN
jsr release_CLOCK
1$ jsr read_CLOCK
jsl assert_DATA
jsl release_ATN
jsl release_CLOCK
1$ jsl read_CLOCK
bcs 1$ ; TODO: should time out.
plp
@ -521,8 +521,8 @@ iecll_listen php
sep #0x30
ora #0x20
jsr flush
jsr atn_release_data ; NOTE: does NOT drop ATN!
jsl flush
jsl atn_release_data ; NOTE: does NOT drop ATN!
plp
rtl
@ -538,8 +538,8 @@ iecll_listen_sa php
sei
sep #0x30
jsr atn_common
jsr release_ATN
jsl atn_common
jsl release_ATN
; TODO: WARNING! No delay here!
; TODO: IMHO, should wait at least 100us to avoid accidental turn-around!
@ -569,8 +569,8 @@ iecll_untalk php
; TODO: track the state and cause calls to IECOUT to fail.
; pre-sets CLOCK IMMEDIATELY before the ATN ... again, TODO: makes no sense
jsr assert_CLOCK
jsr atn_release
jsl assert_CLOCK
jsl atn_release
plp
rtl
@ -587,8 +587,8 @@ iecll_unlisten php
; Detangled from C64 sources; TODO: compare with Stef's
lda #0x3f
jsr flush
jsr atn_release
jsl flush
jsl atn_release
plp
rtl
@ -607,7 +607,7 @@ iecll_in php
sei ; Disable interrupts
sep #0x30 ; Switch to 8-bit registers
jsr recv_data
jsl recv_data
; NOTE: we'll just read from the eoi variable in a separate function
; We might need to return it here folded in with the data somwhow
@ -662,7 +662,7 @@ iecll_out php
; Send the old byte
pha
lda queue
jsr send
jsl send
pla
stz delayed
@ -680,9 +680,9 @@ iecll_reset: php
sei
sep #0x30
jsr assert_RST
jsr sleep_1ms
jsr release_RST
jsl assert_RST
jsl sleep_1ms
jsl release_RST
plp
rtl

144
src/C256/interrupts.s Normal file
View file

@ -0,0 +1,144 @@
;;;
;;; Assembly stubs for the interrupt handlers on the F256
;;;
;;; NOTE: this is necessary since the F256 has only 256 bytes of flash mapped
;;; into bank 0, so we can have only the smallest amount of code there
;;; that we can get away with.
;;;
.extern int_handle_nmi
.extern int_handle_irq
.extern _Dp, _Vfp
.extern _DirectPageStart
.extern _NearBaseAddress
.section `$$interruptVector_0x00ffee`,text
.word hw_handle_irq
.section `$$interruptVector_0x00ffea`,text
.word hw_handle_nmi
.section code,root
hw_handle_irq: rep #48
pha
phx
phy
pei dp:.tiny _Dp
pei dp:.tiny (_Dp+2)
pei dp:.tiny (_Dp+4)
pei dp:.tiny (_Dp+6)
pei dp:.tiny (_Dp+8)
pei dp:.tiny (_Dp+10)
pei dp:.tiny (_Dp+12)
pei dp:.tiny (_Dp+14)
pei dp:.tiny (_Dp+8)
pei dp:.tiny (_Dp+10)
; Save the caller's databank and direct page
; TODO: this might change to being done only in the toolbox IRQ handler
phd
phb
; Set the toolbox's direct page
lda ##_DirectPageStart
tcd
; Set the toolbox's databank
lda ##.word2 _NearBaseAddress
stz dp:.tiny(_Vfp+2)
xba ; A upper half = data bank
pha
plb ; pop 8 dummy
plb ; set data bank
; Call the interrupt handlers
jsl int_handle_irq
plb
pld
ply
sty dp:.tiny (_Dp+10)
ply
sty dp:.tiny (_Dp+8)
ply
sty dp:.tiny (_Dp+14)
ply
sty dp:.tiny (_Dp+12)
ply
sty dp:.tiny (_Dp+10)
ply
sty dp:.tiny (_Dp+8)
ply
sty dp:.tiny (_Dp+6)
ply
sty dp:.tiny (_Dp+4)
ply
sty dp:.tiny (_Dp+2)
ply
sty dp:.tiny _Dp
ply
plx
pla
rti
hw_handle_nmi: rep #48
pha
phx
phy
pei dp:.tiny _Dp
pei dp:.tiny (_Dp+2)
pei dp:.tiny (_Dp+4)
pei dp:.tiny (_Dp+6)
pei dp:.tiny (_Dp+8)
pei dp:.tiny (_Dp+10)
pei dp:.tiny (_Dp+12)
pei dp:.tiny (_Dp+14)
pei dp:.tiny (_Dp+8)
pei dp:.tiny (_Dp+10)
; Save the caller's databank and direct page
; TODO: this might change to being done only in the toolbox IRQ handler
phd
phb
; Set the toolbox's direct page
lda ##_DirectPageStart
tcd
; Set the toolbox's databank
lda ##.word2 _NearBaseAddress
stz dp:.tiny(_Vfp+2)
xba ; A upper half = data bank
pha
plb ; pop 8 dummy
plb ; set data bank
; Call the interrupt handlers
jsl int_handle_nmi
plb
pld
ply
sty dp:.tiny (_Dp+10)
ply
sty dp:.tiny (_Dp+8)
ply
sty dp:.tiny (_Dp+14)
ply
sty dp:.tiny (_Dp+12)
ply
sty dp:.tiny (_Dp+10)
ply
sty dp:.tiny (_Dp+8)
ply
sty dp:.tiny (_Dp+6)
ply
sty dp:.tiny (_Dp+4)
ply
sty dp:.tiny (_Dp+2)
ply
sty dp:.tiny _Dp
ply
plx
pla
rti

86
src/C256/macros.h Normal file
View file

@ -0,0 +1,86 @@
#ifndef __MACROS_H
#define __MACROS_H
#ifdef __CALYPSI_ASSEMBLER__
#ifdef __CALYPSI_CODE_MODEL_SMALL__
#define libcode code
call .macro dest
jsr \dest
.endm
return .macro
rts
.endm
jump .macro dest
jmp \dest
.endm
#elif defined(__CALYPSI_CODE_MODEL_COMPACT__)
#define libcode compactcode
call .macro dest
jsr .kbank \dest
.endm
return .macro
rts
.endm
jump .macro dest
jmp .kbank \dest
.endm
#else
#define libcode farcode
call .macro dest
jsl \dest
.endm
return .macro
rtl
.endm
jump .macro dest
jmp long:\dest
.endm
#endif // __CALYPSI_CODE_MODEL_SMALL__
// ----------------------------------------------------------------------
//
// Define code and data model used. This is to add a bit of safety in
// case the way a file is assembled is combined with the wrong run-time.
//
// ----------------------------------------------------------------------
#if defined(__CALYPSI_DATA_MODEL_SMALL__)
.rtmodel dataModel,"small"
#elif defined (__CALYPSI_DATA_MODEL_MEDIUM__)
.rtmodel dataModel,"medium"
#elif defined(__CALYPSI_DATA_MODEL_LARGE__)
.rtmodel dataModel,"large"
#elif defined(__CALYPSI_DATA_MODEL_HUGE__)
.rtmodel dataModel,"huge"
#else
#pragma GCC error "unexpected data model"
#endif
#if defined(__CALYPSI_CODE_MODEL_SMALL__)
.rtmodel codeModel,"small"
#elif defined(__CALYPSI_CODE_MODEL_COMPACT__)
.rtmodel codeModel,"compact"
#elif defined(__CALYPSI_CODE_MODEL_LARGE__)
.rtmodel codeModel,"large"
#else
#pragma GCC error "unexpected code model"
#endif
#endif // __CALYPSI_ASSEMBLER__
#endif // __MACROS_H

View file

@ -1,8 +1,8 @@
# VPATH=.:../../module/Calypsi-remote-debug/src
DEBUGGER=../module/Calypsi-remote-debug/src
UNIT := F256
MEMORY := RAM
UNIT := F256K
MEMORY := ROM
# Define OS-dependent variables
@ -44,20 +44,20 @@ else ifeq ($(UNIT),F256)
CFLAGS_FOR_UNIT=-DMODEL=2 -DCPU=255 --code-model large --data-model large
ifeq ($(MEMORY),ROM)
LDFLAGS_FOR_UNIT=C256/flash-f256.scm clib-lc-ld.a --rtattr printf=medium
LDFLAGS_FOR_UNIT=C256/f256-flash.scm clib-lc-ld.a --rtattr printf=medium
else
LDFLAGS_FOR_UNIT=C256/ld_lc_f256.scm clib-lc-ld.a --rtattr printf=medium
LDFLAGS_FOR_UNIT=C256/f256-ld_lc.scm clib-lc-ld.a --rtattr printf=medium
endif
else ifeq ($(UNIT),F256K)
CPU=w65816
C_SRCS_DEBUGGER=$(DEBUGGER)/agent.c $(DEBUGGER)/c256-uart.c $(DEBUGGER)/low_level_WDC65816.s
SRCS_FOR_UNIT=C256/jumptable.s C256/io_stubs.c C256/extras.s C256/iecll.s
CFLAGS_FOR_UNIT=-DMODEL=2 -DCPU=255 --code-model large --data-model large
SRCS_FOR_UNIT=C256/jumptable.s C256/io_stubs.c C256/extras.s C256/iecll.s C256/interrupts.s C256/f256-cstartup.s
CFLAGS_FOR_UNIT=-DMODEL=17 -DCPU=255 --code-model large --data-model large
ifeq ($(MEMORY),ROM)
LDFLAGS_FOR_UNIT=C256/flash-f256.scm clib-lc-ld.a --rtattr printf=medium
LDFLAGS_FOR_UNIT=C256/f256-flash.scm clib-lc-ld.a --rtattr printf=medium --cstartup=f256
else
LDFLAGS_FOR_UNIT=C256/ld_lc_f256.scm clib-lc-ld.a --rtattr printf=medium
LDFLAGS_FOR_UNIT=C256/f256-ld_lc.scm clib-lc-ld.a --rtattr printf=medium --cstartup=f256
endif
endif
@ -69,8 +69,8 @@ ifeq ($(CPU),w65816)
endif
INCLUDES=-I. -I./include
CFLAGS=$(INCLUDES) $(CFLAGS_FOR_UNIT) # -l -D_CALYPSI_MCP_DEBUGGER
ASFLAGS=$(INCLUDES)
CFLAGS=$(INCLUDES) $(CFLAGS_FOR_UNIT) -l # -l -D_CALYPSI_MCP_DEBUGGER
ASFLAGS=$(INCLUDES) --data-model large --code-model large
ifeq ($(MEMORY),ROM)
LDFLAGS=--rom-code $(LDFLAGS_FOR_UNIT) --list-file toolbox.map
@ -89,7 +89,7 @@ toolbox.s37: $(OBJS) $(LIBS)
$(LD) $(LDFLAGS) --output-format s37 -o $@ $^
toolbox.raw: $(OBJS) $(LIBS)
$(LD) $(LDFLAGS) --output-format raw -o $@ $^
$(LD) $(LDFLAGS) --raw-multiple-memories --output-format raw -o $@ $^
dev/devices.a:
$(MAKE) --directory=dev

View file

@ -469,8 +469,10 @@ SYSTEMCALL void int_clear(unsigned short n) {
*
* NOTE: this routine might not be fast enough in C and have to be replaced by hand written
* assembly code... but we will try it this way first.
*
* __attribute__((interrupt(0xffee)))
*/
__attribute__((interrupt(0xffee))) void int_handle_irq() {
void int_handle_irq() {
uint8_t mask_bits = 0;
// Process any pending interrupts in group 0
@ -525,6 +527,8 @@ __attribute__((interrupt(0xffee))) void int_handle_irq() {
/**
* @brief Handle incomming NMI signal
*
* __attribute__((interrupt(0xffea)))
*/
__attribute__((interrupt(0xffea))) void int_handle_nmi() {
void int_handle_nmi() {
}

View file

@ -79,13 +79,6 @@ void initialize() {
long target_jiffies;
int i;
short res;
*vky_brdr_ctrl = 0x01;
*vky_brdr_col_red = 0x80;
*vky_brdr_col_green = 0x00;
*vky_brdr_col_blue = 0x00;
*vky_brdr_size_x = 0x08;
*vky_brdr_size_y = 0x08;
/* Setup logging early */
log_init();
@ -186,8 +179,8 @@ void initialize() {
INFO("Timers initialized");
/* Initialize the real time clock */
rtc_init();
INFO("Real time clock initialized");
// rtc_init();
// INFO("Real time clock initialized");
/* Enable all interrupts */
int_enable_all();
@ -487,24 +480,28 @@ int main(int argc, char * argv[]) {
test_sysinfo();
printf("Initializing IEC\n");
result = iec_init();
if (result != 0) {
printf("Error initializing IEC.\n");
}
printf("Foenix Toolbox v%d.%04d.%04d\n", VER_MAJOR, VER_MINOR, VER_BUILD);
test_kbd();
// printf("Initializing IEC\n");
// result = iec_init();
// if (result != 0) {
// printf("Error initializing IEC.\n");
// }
// printf("Attempting to get status for IEC drive #8: ");
// short n = iec_status(8, message, 256);
// printf("\"%s\"\n", message);
printf("Attempting to write to the printer.\n");
iec_print(4, "\e1THIS IS PRINTED FROM AN F256K OVER THE IEC PORT!\r");
printf("Done.\n");
// printf("Attempting to write to the printer.\n");
// iec_print(4, "\e1THIS IS PRINTED FROM AN F256K OVER THE IEC PORT!\r");
// Attempt to start up the user code
// log(LOG_INFO, "Looking for user startup code:");
// boot_launch();
printf("Done.\n");
#ifdef _CALYPSI_MCP_DEBUGGER
extern int CalypsiDebugger(void);
CalypsiDebugger(); // This will not return

17
src/toolbox.csv Normal file
View file

@ -0,0 +1,17 @@
"00","toolbox-00.bin"
"01","toolbox-01.bin"
"02","toolbox-02.bin"
"03","toolbox-03.bin"
"04","toolbox-04.bin"
"05","toolbox-05.bin"
"06","toolbox-06.bin"
"07","toolbox-07.bin"
"08","toolbox-08.bin"
"09","toolbox-09.bin"
"0A","toolbox-0A.bin"
"0B","toolbox-0B.bin"
"0C","toolbox-0C.bin"
"0D","toolbox-0D.bin"
"0E","toolbox-0E.bin"
"0F","toolbox-0F.bin"
"3F","toolbox-3F.bin"
1 00 toolbox-00.bin
2 01 toolbox-01.bin
3 02 toolbox-02.bin
4 03 toolbox-03.bin
5 04 toolbox-04.bin
6 05 toolbox-05.bin
7 06 toolbox-06.bin
8 07 toolbox-07.bin
9 08 toolbox-08.bin
10 09 toolbox-09.bin
11 0A toolbox-0A.bin
12 0B toolbox-0B.bin
13 0C toolbox-0C.bin
14 0D toolbox-0D.bin
15 0E toolbox-0E.bin
16 0F toolbox-0F.bin
17 3F toolbox-3F.bin

View file

@ -7,6 +7,6 @@
#define VER_MAJOR 1
#define VER_MINOR 0
#define VER_BUILD 0
#define VER_BUILD 2
#endif

2
tests/make_test.bat Normal file
View file

@ -0,0 +1,2 @@
@echo off
64tass -x -f -b --list test_boot.lst -o test_boot.bin test_boot.s

1
tests/test.csv Normal file
View file

@ -0,0 +1 @@
"3F","test_boot.bin"
1 3F test_boot.bin

65
tests/test_boot.s Normal file
View file

@ -0,0 +1,65 @@
;;;
;;; Test booting the F256k2e...
;;;
.cpu "65816"
vky_border_ctrl = $f01004
vky_border_blue = $f01005
vky_border_green = $f01006
vky_border_red = $f01007
vky_border_size_x = $f01008
vky_border_size_y = $f01009
led_pwr_blue = $f016a7
led_pwr_green = $f016a8
led_pwr_red = $f016a9
* = $ff00
start: clc
xce
sep #$30
.as
.xs
lda #$01
sta @l vky_border_ctrl
lda #$ff
sta @l vky_border_red
sta @l led_pwr_red
lda #0
sta @l vky_border_blue
sta @l led_pwr_blue
sta @l vky_border_green
sta @l led_pwr_green
lda #16
sta @l vky_border_size_x
sta @l vky_border_size_y
loop: nop
bra loop
not_impl: rti
* = $ffe4
hcop: .word <>not_impl
hbrk: .word <>not_impl
habort: .word <>not_impl
hnmi: .word <>not_impl
.word 0
hirq: .word <>not_impl
* = $fff4
ehcop: .word <>not_impl
.word 0
ehabort: .word <>not_impl
ehnmi: .word <>not_impl
hreset: .word <>start
ehirq: .word <>not_impl

66
utils/srec2bin.py Normal file
View file

@ -0,0 +1,66 @@
#
# Convert Motorola SREC to binary ROM files (both a 512KB main file and 8KB sector files for non-empty sectors)
#
# usage: python srec2bin.py
#
import re
def srec_add_data(rom, address, data):
"""Add a line of data from an SREC file (hex digits) to the binary image at the given address"""
data_bytes = bytearray.fromhex(data)
for i in range(len(data_bytes)):
rom[address + i] = data_bytes[i]
def srec_process(rom, line):
"""Process a line of a Motorola SREC file"""
m = re.match(r'^S(\d)([0-9a-fA-F]{2})([0-9a-fA-F]+)$', line)
if m:
type = int(m.group(1), 10)
size = int(m.group(2), 16)
addr_data_chk = m.group(3)
if type == 3:
m2 = re.match(r'^([0-9a-fA-F]{8})([0-9a-fA-F]+)([0-9a-fA-F]{2})$', addr_data_chk)
if m2:
address = int(m2.group(1),16)
data = m2.group(2)
chksum = m2.group(3)
if address >= rom_base:
srec_add_data(rom, address - rom_base, data)
def bank_has_data(rom, bank):
"""Check to see if a bank is empty (all 0xFF)"""
start = bank * 8192
end = start + 8192
for i in range(start, end):
if rom[i] != 0xff:
# Return True if we find a non-blank entry
return True
return False
rom_size = 512 * 1024
rom_base = 0xf80000
input_file = "toolbox.s37"
output_file = "toolbox.bin"
rom_image = bytearray(rom_size)
for i in range(rom_size):
rom_image[i] = 0xff
with open(input_file, "r") as input:
for line in input:
srec_process(rom_image, line)
with open("toolbox.bin", "wb") as output:
output.write(rom_image)
for bank in range(0, 64):
if bank_has_data(rom_image, bank):
output_name = "toolbox-{:02X}.bin".format(bank)
with open(output_name, "wb") as output:
output.write(rom_image[bank * 8192:bank * 8192 + 8192])