Compare commits
2 Commits
a616d47e76
...
8f615e1bd8
Author | SHA1 | Date | |
---|---|---|---|
8f615e1bd8
|
|||
31cf42167f
|
@@ -18,6 +18,10 @@ the CHIBI PC-09 hobby computer platform. It is the stock bootloader and
|
||||
interface for the PC-09. This manual goes over the usage of BUZBEE, and some of
|
||||
the technical internals of how it works and how to hack on it.
|
||||
|
||||
BUZBEE was created primarily to debug prototype versions of the CHIBI PC-09.
|
||||
BUZBEE will grow alongside the CHIBI PC-09 project. It also functions as a
|
||||
reference implementation of an OS using the CHIBI PC-09 BIOS.
|
||||
|
||||
The CHIBI PC-09 name and platform is copyright 2024-2025 Amber Zeller. The CHIBI
|
||||
PC-09 BIOS is copyright 2024-2025 Gale Faraday and Amber Zeller. BUZBEE is
|
||||
copyright 2025 Gale Faraday. All CHIBI PC-09 components are licensed under the
|
||||
@@ -29,10 +33,11 @@ MIT license.
|
||||
|
||||
BUZBEE is at its core a chain loader or bootloader. This means that most of the
|
||||
functionality of the CHIBI starts with using BUZBEE. BUZBEE functions are broken
|
||||
into two categories: _Internal Functions_ or "IFs," and _External Functions_ or
|
||||
"EFs." IFs are native routines mapped to textual commands entered at the BUZBEE
|
||||
prompt. EFs are native routines called through IFs. EFs can either be any user
|
||||
supplied code, or one of a set of routines in the BIOS/BUZBEE ROM or "firmware".
|
||||
into two categories: _Internal Functions_ or "IFs" defined in @if-top, and
|
||||
_External Functions_ or "EFs" in @ef-top. IFs are native routines mapped to
|
||||
textual commands entered at the BUZBEE prompt. EFs are native routines called
|
||||
through IFs. EFs can either be any user supplied code, or one of a set of
|
||||
routines in the BIOS/BUZBEE ROM or "firmware".
|
||||
|
||||
#pagebreak()
|
||||
|
||||
@@ -47,6 +52,9 @@ listed in alphabetical order. Below in @if-table is a list of available IFs.
|
||||
columns: (1fr, auto),
|
||||
inset: 10pt,
|
||||
align: center,
|
||||
fill: (_, y) =>
|
||||
if calc.odd(y) { luma(250) }
|
||||
else { white },
|
||||
table.header(
|
||||
[*Name* (pg. no.)], [*Description*]
|
||||
),
|
||||
@@ -149,6 +157,9 @@ BIOS routine.
|
||||
)
|
||||
)
|
||||
|
||||
Peeking memory causes the MPU to read the requested bytes and dump them to the
|
||||
screen.
|
||||
|
||||
#lorem(120)
|
||||
|
||||
#pagebreak()
|
||||
@@ -198,9 +209,34 @@ Some common EFs to call include the using call to reset the CHIBI PC-09 with
|
||||
= BUZBEE Reserved Memory Regions <res-mem>
|
||||
|
||||
BUZBEE uses memory in the 0200-02FF page. A table of the layout of this memory
|
||||
is provided.
|
||||
is provided. The memory is laid out in a packed structure starting at 0200.
|
||||
|
||||
// TODO: Provide a table of the BUZBEE memory layout.
|
||||
#table(
|
||||
columns: (auto, 1fr, auto),
|
||||
inset: 10pt,
|
||||
align: center,
|
||||
fill: (_, y) =>
|
||||
if calc.odd(y) { luma(250) }
|
||||
else { white },
|
||||
table.header(
|
||||
[*Internal Name*], [*Size (Bytes)*], [*Description*]
|
||||
),
|
||||
[`input`],
|
||||
[128],
|
||||
[Text input buffer],
|
||||
[`cchinput`],
|
||||
[2],
|
||||
[Text input buffer character count],
|
||||
[`tokens`],
|
||||
[64],
|
||||
[BUZBEE token buffer],
|
||||
[`cbtokens`],
|
||||
[2],
|
||||
[Count of bytes in `tokens`],
|
||||
[`scratch`],
|
||||
[2],
|
||||
[Internal scratch word used for some operations],
|
||||
)
|
||||
|
||||
#pagebreak()
|
||||
|
||||
@@ -236,4 +272,17 @@ Building the documentation can also be accomplished using `make docs`, provided
|
||||
|
||||
= BUZBEE Internals and Modding <internals>
|
||||
|
||||
#lorem(120)
|
||||
BUZBEE's interpreter works by "compiling" textual user commands into bytecode
|
||||
for more simply passing parameters to IFs (see @if-top).
|
||||
|
||||
BUZBEE's source, and the surrounding BIOS source is well commented, but a
|
||||
general summary of the control flow is provided here.
|
||||
|
||||
+ BUZBEE sets up the prompt and input buffer with `NEWLINE`
|
||||
+ BUZBEE enters an input processing loop that works with the CHIBI PC-09's
|
||||
serial driver.
|
||||
+ If no input is provided, restart.
|
||||
+ BUZBEE makes a tokenizing pass over the input buffer.
|
||||
+ BUZBEE attempts to execute the tokens, which may involve leaving the BUZBEE
|
||||
loop, or in the event the IF returns, loops around and re-enters the BUZBEE
|
||||
loop.
|
||||
|
170
src/buzbee.s
170
src/buzbee.s
@@ -13,15 +13,17 @@
|
||||
;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
BBIN_DEPTH EQU $7F
|
||||
BBTOKENS_DEPTH EQU $3F
|
||||
BBIN_DEPTH EQU $80 ; Input buffer depth
|
||||
BBTOKENS_DEPTH EQU $40 ; Token buffer depth
|
||||
|
||||
SECTION BBVARS,bss
|
||||
|
||||
tagbbvar STRUCT
|
||||
input rmb BBIN_DEPTH ; Input buffer
|
||||
cchinput rmd 1 ; Input buffer char count
|
||||
tokens rmb BBTOKENS_DEPTH ; Token buffer
|
||||
cbtokens rmb 2
|
||||
cbtokens rmd 1 ; Token buffer byte count
|
||||
scratch rmd 1 ; Scratch word
|
||||
ENDSTRUCT
|
||||
|
||||
ORG $0200
|
||||
@@ -38,10 +40,10 @@ BBVAR tagbbvar
|
||||
EXPORT BUZBEE
|
||||
|
||||
BUZBEE
|
||||
bsr NEWLINE ; Setup the new input line and handle display.
|
||||
bsr INPLOOP ; Fill input buffer.
|
||||
cmpy #$0000 ; No data?
|
||||
beq BUZBEE ; Try again...
|
||||
lbsr NEWLINE ; Setup the new input line and handle display.
|
||||
bsr INPLOOP ; Fill input buffer.
|
||||
cmpy #$0000 ; No data?
|
||||
beq BUZBEE ; Try again...
|
||||
; TODO: Parse the input buffer into tokens
|
||||
lbsr RUNIF
|
||||
bra BUZBEE
|
||||
@@ -52,20 +54,6 @@ BUZBEE
|
||||
;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Handle new lines; prints a new prompt and then clears the input buffer
|
||||
NEWLINE
|
||||
PZSTR PROMPTLINE ; Print prompt line
|
||||
CLRIN ; Label to just clear input buffer without newline
|
||||
clra ; Init A and X
|
||||
ldx #$0000
|
||||
NEXT@
|
||||
sta BBVAR.input,x ; Clear input buffer
|
||||
leax 1,x
|
||||
cmpx #BBIN_DEPTH
|
||||
blo NEXT@
|
||||
ldy #$0000 ; Reset buffer fill pointer
|
||||
rts
|
||||
|
||||
; Fills input buffer with characters from the serial console. Sets Y to the
|
||||
; offset in the input buffer of the last char read.
|
||||
INPLOOP
|
||||
@@ -79,13 +67,14 @@ INPLOOP
|
||||
cmpa #$08 ; BS?
|
||||
beq HBACKSPC@ ; Backup a char
|
||||
cmpa #$0D ; CR?
|
||||
beq EXIT@ ; Then parse input buffer
|
||||
beq HCR@ ; Then terminate and parse input buffer
|
||||
cmpy #BBIN_DEPTH ; Are we at the end of the input buffer?
|
||||
beq FULLBUF@ ; Handle the buffer being full
|
||||
ECHO@
|
||||
jsr POUTCHAR ; Echo char back, this includes BS chars
|
||||
sta BBVAR.input,y ; Add it to the input buffer
|
||||
leay 1,y
|
||||
; Fall through
|
||||
NOCHAR@
|
||||
; Check for error condition, work based on The Serial Port release 19
|
||||
bitb #(UARTF_LSR_FIFO|UARTF_LSR_BI|UARTF_LSR_FE|UARTF_LSR_PE|UARTF_LSR_OE)
|
||||
@@ -103,10 +92,11 @@ NOPARITY@
|
||||
PZSTR EM_FRAMING
|
||||
NOFRAM@
|
||||
bitb #UARTF_LSR_FIFO ; Check for FIFO error
|
||||
beq INPLOOP
|
||||
beq INPLOOP ; Loop over
|
||||
PZSTR EM_FIFO
|
||||
bra INPLOOP
|
||||
EXIT@
|
||||
bra INPLOOP ; Loop over
|
||||
HCR@
|
||||
sty BBVAR.cchinput ; Store buffer length
|
||||
rts
|
||||
HESC@
|
||||
lda #'^ ; Print a char that signifies that ESC was pressed
|
||||
@@ -121,7 +111,21 @@ HBACKSPC@
|
||||
FULLBUF@
|
||||
lda #$07 ; ASCII BEL
|
||||
jsr POUTCHAR
|
||||
bra INPLOOP
|
||||
lbra INPLOOP
|
||||
|
||||
; Handle new lines; prints a new prompt and then clears the input buffer
|
||||
NEWLINE
|
||||
PZSTR PROMPTLINE ; Print prompt line
|
||||
CLRIN ; Label to just clear input buffer without newline
|
||||
clra ; Init A and X
|
||||
ldx #$0000
|
||||
NEXT@
|
||||
sta BBVAR.input,x ; Clear input buffer
|
||||
leax 1,x
|
||||
cmpx #BBIN_DEPTH
|
||||
blo NEXT@
|
||||
ldy #$0000 ; Reset buffer fill pointer
|
||||
rts
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
@@ -130,7 +134,7 @@ FULLBUF@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Prints a byte in A
|
||||
; @param a: byte to print
|
||||
; @param A: byte to print
|
||||
PBYTE
|
||||
pshs b
|
||||
tfr a,b ; Transfer lower nybble into B
|
||||
@@ -148,24 +152,58 @@ PBYTE
|
||||
rts
|
||||
|
||||
; Converts a nybble into a valid hex digit
|
||||
; @param a: nybble to convert to a char
|
||||
; @return a: resulting char
|
||||
; @param A: nybble to convert to a char
|
||||
; @return A: resulting char
|
||||
NYB2HEX
|
||||
anda #$0F
|
||||
ora #'0 ; Add "0"
|
||||
cmpa #$3A ; ":" "9"+1
|
||||
bcc SKIP@
|
||||
blo SKIP@
|
||||
adca #6 ; Add offset to "A" in ascii
|
||||
SKIP@
|
||||
rts
|
||||
|
||||
; Converts a hexadecimal sequence into a byte value
|
||||
; @param D: hex representation of a byte with A: MSD B: LSD
|
||||
; @return A: returned byte value
|
||||
; NOTE: Conversion logic credit to Wozniak. This code unrolled for speed.
|
||||
HEX2BYT
|
||||
eora #$B0 ; Map digits to 0-9
|
||||
cmpa #9+1 ; Is it a decimal?
|
||||
blo AISDEC@ ; Yes? skip hex adjust
|
||||
adca #$88 ; Map 'A'-'F' to $FA-$FF
|
||||
cmpa #$FA ; Hex char?
|
||||
blo BADHEX@ ; No? Print error
|
||||
AISDEC@
|
||||
asla ; Shift MSD into upper nybble of A
|
||||
asla
|
||||
asla
|
||||
asla
|
||||
; Do B part
|
||||
eorb #$B0 ; Map digits to 0-9
|
||||
cmpa #9+1 ; Is it a decimal?
|
||||
blo BISDEC@ ; Yes? skip hex adjust
|
||||
adcb #$88 ; Map 'A'-'F' to $FA-$FF
|
||||
andb #$0F ; Mask high nybble
|
||||
cmpb #$0A ; Hex char?
|
||||
blo BADHEX@ ; No? Print error
|
||||
BISDEC@
|
||||
stb BBVAR.scratch ; Store low nybble in scratch buffer
|
||||
ora BBVAR.scratch ; Combine the nybbles
|
||||
rts
|
||||
BADHEX@
|
||||
PZSTR EM_BADHEX ; Print an error message
|
||||
clrd ; Prevent RUNIF from executing
|
||||
std BBVAR.cbtokens
|
||||
rts
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; BUZBEE Tokenizing Routines
|
||||
;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Makes a hash of four chars in BBIN starting at offset X.
|
||||
; Makes a hash of four chars in BBIN starting at offset X
|
||||
; @param X: offset in BBIN to read the four chars from
|
||||
; @return A: resulting hash
|
||||
MKCMDSUM
|
||||
@@ -180,6 +218,18 @@ NEXTC@
|
||||
bne NEXTC@ ; No? loop
|
||||
rts
|
||||
|
||||
; Skips "whitespace" to the next semantic char
|
||||
; @param Y: current index in text buffer
|
||||
; @return Y: resulting index in text buffer
|
||||
SKIPTONEXTC
|
||||
lda BBVAR.input,y ; Get our char?
|
||||
cmpa #$20 ; SPACE or control char?
|
||||
bhi EXIT@ ; Yes? End
|
||||
leay 1,y ; Iterate next char
|
||||
bra SKIPTONEXTC
|
||||
EXIT@
|
||||
rts
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; BUZBEE IF Handling Functions
|
||||
@@ -190,6 +240,9 @@ NEXTC@
|
||||
; @corrupts B
|
||||
; @return X: command data table index
|
||||
RUNIF
|
||||
clrd ; Do we have any tokens?
|
||||
cmpd BBVAR.cbtokens
|
||||
beq NOTOK@
|
||||
ldx #0 ; Counting up from zero
|
||||
lda BBVAR.tokens ; Load token
|
||||
NEXTHASH@
|
||||
@@ -198,13 +251,15 @@ NEXTHASH@
|
||||
leax 1,x ; Begin considering next hash
|
||||
cmpx BBCHTC ; Is this the last byte?
|
||||
blo NEXTHASH@ ; No? try next hash, Yes? fall through
|
||||
PZSTR EM_BADCMD ; Print an error message
|
||||
PZSTR EM_BADHASH ; Print an error message
|
||||
lbra IFHELP ; Proceed to call "HELP"
|
||||
CALCPTR@
|
||||
tfr x,d ; Swap into d to do a cheap multiply
|
||||
asld ; Cheaply << to get *2, pointer size
|
||||
tfr d,x ; Restore x from d and jump to function at index
|
||||
jmp [BBCMDPTRTBL,x]
|
||||
NOTOK@
|
||||
rts
|
||||
|
||||
; IF pointer table
|
||||
BBCMDPTRTBL
|
||||
@@ -238,40 +293,25 @@ IFPEEK
|
||||
ldd BBVAR.cbtokens ; One 16-bit token given, single peek
|
||||
cmpd #3
|
||||
lblo INVALIDARG ; Not enough args given
|
||||
bhi SELFORBAC@ ; Select forward or backward peek
|
||||
bhi SELTYPE@ ; Select forward or backward peek
|
||||
SINGLE@
|
||||
lda [BBVAR.tokens+1] ; Get byte
|
||||
lbsr PBYTE ; Print peek byte
|
||||
rts
|
||||
SELFORBAC@
|
||||
SELTYPE@
|
||||
ldd BBVAR.cbtokens ; Have enough tokens?
|
||||
cmpd #5
|
||||
lbne INVALIDARG ; No? bounce out
|
||||
ldd BBVAR.tokens+1 ; Are we forwards (BASE < HIGH)?
|
||||
cmpd BBVAR.tokens+3
|
||||
beq SINGLE@ ; Gracefully handle BASE == HIGH
|
||||
blo PEEKFWD
|
||||
bhi PEEKBACK
|
||||
|
||||
; Peek forward
|
||||
PEEKFWD
|
||||
ldx BBVAR.tokens+1 ; Get BASE
|
||||
NEXT@
|
||||
lda ,x+ ; Get the next byte
|
||||
lbsr PBYTE ; Print our byte
|
||||
cmpx BBVAR.tokens+3 ; Are we at <HIGH> yet?
|
||||
bne NEXT@ ; No? loop
|
||||
rts
|
||||
|
||||
; Peek backwards
|
||||
PEEKBACK
|
||||
bhi INVALIDARG ; Malformed if BASE > HIGH
|
||||
ldx BBVAR.tokens+1 ; Get BASE
|
||||
PREV@
|
||||
lda 0,x ; Get current byte
|
||||
leax -1,x ; Prep for next byte
|
||||
NEXT@
|
||||
lda ,x+ ; Get the next byte
|
||||
lbsr PBYTE ; Print our byte
|
||||
cmpx BBVAR.tokens+3 ; Are we at <HIGH> yet?
|
||||
bne PREV@ ; No? loop
|
||||
bne NEXT@ ; No? loop
|
||||
rts
|
||||
|
||||
; Poke bytes into memory
|
||||
@@ -297,12 +337,12 @@ IFSREC
|
||||
|
||||
; Invalid argument IF tail
|
||||
INVALIDARG
|
||||
PZSTR EM_MISSINGARG
|
||||
PZSTR EM_BADARG
|
||||
rts
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; BUZBEE Strings and Tables
|
||||
;; BUZBEE Strings and Fixed Data
|
||||
;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@@ -327,20 +367,26 @@ PROMPTLINE
|
||||
fcb $0D,$0A,$25,$00 ; CR LF '%' NUL
|
||||
|
||||
EM_OVERRUN
|
||||
fcc "!!! Overrun Error !!!"
|
||||
fcc "!!! UART Overrun Error !!!"
|
||||
fcb $0D,$0A,$00
|
||||
EM_PARITY
|
||||
fcc "!!! Parity Error !!!"
|
||||
fcc "!!! UART Parity Error !!!"
|
||||
fcb $0D,$0A,$00
|
||||
EM_FRAMING
|
||||
fcc "!!! Framing Error !!!"
|
||||
fcc "!!! UART Framing Error !!!"
|
||||
fcb $0D,$0A,$00
|
||||
EM_FIFO
|
||||
fcc "!!! FIFO Error !!!"
|
||||
fcc "!!! UART FIFO Error !!!"
|
||||
fcb $0D,$0A,$00
|
||||
EM_BADCMD
|
||||
EM_BADHASH
|
||||
fcc "!!! Bad Command Hash !!!"
|
||||
fcb $0D,$0A,$00
|
||||
EM_MISSINGARG
|
||||
fcc "!!! Missing Arguments !!!"
|
||||
EM_BADARG
|
||||
fcc "!!! Malformed Arguments !!!"
|
||||
fcb $0D,$0A,$00
|
||||
EM_TOKFAIL
|
||||
fcc "!!! Tokenization Failure !!!"
|
||||
fcb $0D,$0A,$00
|
||||
EM_BADHEX
|
||||
fcc "!!! Maleformed Hex Value !!!"
|
||||
fcb $0D,$0A,$00
|
||||
|
Reference in New Issue
Block a user