Compare commits

...

30 Commits

Author SHA1 Message Date
f68fa4c0a6 docs(buzbee): update docs to represent feature completion state 2025-10-12 17:57:11 -05:00
d92b8f6ba4 fix(buzbee): respecting new portable command token format 2025-10-12 17:42:25 -05:00
96a5804467 feat(buzbee): add tokenizing routines, buzbee feature complete 2025-10-12 17:38:07 -05:00
9ab92eb8a5 style(buzbee): fixed hex style to be more conventional 2025-10-12 17:19:57 -05:00
a6a93e656a fix(reset): removed POST as it is to be an inbuilt EF, and style fixes 2025-10-12 17:16:20 -05:00
b5cfd501c5 fix(buzbee): formatting, typos, unrolling, and stack fixes 2025-10-12 17:15:05 -05:00
8f615e1bd8 feat(docs): update manual 2025-10-11 18:32:28 -05:00
31cf42167f feat(buzbee): hexadecimal to byte conversion routine and skip-whitespace routine for tokenizer 2025-10-11 17:30:30 -05:00
a616d47e76 feat(buzbee): Implemented CALL, PEEK, POKE IFs 2025-10-10 23:29:30 -05:00
1cd6720bf6 feat(docs): expanded Typst doc 2025-10-07 14:23:56 -05:00
88fcc86e72 feat(buzbee): using BSS sections for variables 2025-10-07 14:21:12 -05:00
6cbb038b42 feat(doc/buzbee): Added IF tables, added doc building system and updated stylesheet, removed pdf for now 2025-10-07 00:36:12 -05:00
aed8ca28f9 doc(buzbee): added docs folder 2025-10-06 20:53:59 -05:00
3441aea9c1 fix(buzbee): removed EXEC command as it was causing a duplicate sum 2025-10-05 14:11:52 -05:00
893753561c feat(buzbee): add command token parsing interface, and help message, added newlines to messages 2025-10-03 22:38:13 -05:00
eda7b3ac1f fix(buzbee): cleaned up hashtable generation 2025-10-03 14:40:07 -05:00
eafc0ce98e feat(buzbee): BUZBEE command tables now generated with bbmkcmds.c 2025-10-01 17:24:32 -05:00
d7d8532021 feat(buzbee): add command hashes 2025-10-01 13:55:34 -05:00
6544321450 feat(buzbee): add command hashing mode 2025-09-29 19:46:33 -05:00
98ed74f10d fix(reset): using clra instead of lda #0 2025-09-29 19:45:29 -05:00
15872f93b9 fix(version): now using CR LF sequence 2025-09-29 19:44:54 -05:00
8c12c2106f fix(memtest): memtest now no longer overwrites stack, more complete memory testing should be loaded with BUZBEE 2025-09-28 15:37:34 -05:00
35a2f12cce feat(buzbee): implement terminal echo and backspace handling 2025-09-28 15:28:16 -05:00
dce0719796 merge gitea with local 2025-09-27 10:43:28 -05:00
abeecf4e93 style(buzbee): sort includes 2025-09-27 10:40:22 -05:00
180fc932c9 feat(buzbee): implement buzbee input processing 2025-09-27 10:39:36 -05:00
f0104c74c2 feat(buzbee): initial setup for loading into BUZBEE 2025-09-27 10:39:35 -05:00
2988fb9059 Merge branch 'buzbee' of https://gitea.ambersplace.net/gfaraday/chibi-firmware into buzbee 2025-09-26 13:53:49 -05:00
2b23634bb8 feat(buzbee): initial setup for loading into BUZBEE 2025-09-26 13:53:09 -05:00
853efd9bac feat(buzbee): initial setup for loading into BUZBEE 2025-09-25 17:21:08 -05:00
13 changed files with 919 additions and 17 deletions

View File

@@ -12,7 +12,7 @@ insert_final_newline = true
indent_style = space
indent_size = 2
[*.md]
[*.{md,typ}]
indent_style = space
indent_size = 2
max_line_length = 80

3
.gitignore vendored
View File

@@ -6,6 +6,9 @@
*.s19
build/
map.txt
bbmkhash
*.pdf
# Build system generated files
src/version.s
src/bbhash.s

67
bbmkhash.c Normal file
View File

@@ -0,0 +1,67 @@
/* Generates BUZBEE command hash data table asm file */
#include <stdint.h>
#include <stdio.h>
/* Length of commands in printable-char count (excluding NUL terminator). */
const int s_cchCmd = 4;
/* Add your commands here to be hashed. Imprtant that they all be CCH_CMD
* chars long EXCLUDING the NUL terminator. Order is important here. */
const char *s_ppszCmds[] = {
"CALL",
"HELP",
"PEEK",
"POKE",
"SREC",
/* "BOOT", */
};
int mkHash(const char pszCmd[]);
int main(void) {
/* Emit file header */
puts("; CHIBI PC-09 -- BUZBEE -- Command Hash Table\n\
; Copyright (c) 2025 Gale Faraday\n\
; Licensed under MIT\n\
\n\
; This file generated by bbmkcmds.c\n\
\n\
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\
;;\n\
;; BUZBEE Command Hash Table\n\
;;\n\
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\
\n\
SECTION BBHASHES\n\
\n\
EXPORT BBCHTC\n\
EXPORT BBCHT\n");
/* Command count.
* NOTE: This is a u16 because it gets emitted into the output assembly. */
uint16_t cCmds = sizeof(s_ppszCmds) / sizeof(char *);
/* Emit command count */
printf("BBCHTC\n fdb $%.4X\n", cCmds);
/* Emit table data */
puts("\nBBCHT");
for (int iCmd = 0; iCmd < cCmds; iCmd++) {
uint8_t uHash = mkHash(s_ppszCmds[iCmd]);
printf(" fcb $%.2X\n", uHash);
}
return 0;
}
int mkHash(const char pszCmd[]) {
uint8_t nhash = 0;
/* NOTE: Very important that condition is the length of the string MINUS the
* NUL terminator, in this case iChar < 4 */
for (int iChar = 0; iChar < s_cchCmd; iChar++)
nhash = nhash - pszCmd[iChar];
return nhash;
}

293
docs/buzbee.typ Normal file
View File

@@ -0,0 +1,293 @@
#set document(
title: "BUZBEE Manual",
author: "Gale Faraday",
description: "CHIBI PC-09 machine language monitor BUZBEE technical and user manual",
)
#import "style.typ": conf
#show: conf.with(
title: [BUZBEE User Manual and Technical Reference],
subtitle: [A CHIBI PC-09 Machine Language Monitor],
author: [Gale Faraday],
)
= Introduction <intro>
BUZBEE is a "machine language monitor" styled after Steve Wozniak's WOZMON for
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
MIT license.
#pagebreak()
= BUZBEE Functions <bbfunc>
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" 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()
== Internal Functions (IFs) <if-top>
Internal Functions are the textual commands that BUZBEE interprets from the
command line to execute the user's wish. Internal Functions are canonically
listed in alphabetical order. Below in @if-table is a list of available IFs.
#figure(
table(
columns: (auto, auto, 1fr),
inset: 10pt,
align: center,
fill: (_, y) =>
if calc.odd(y) { luma(250) }
else { white },
table.header(
[*Name* (pg. no.)], [*Command Token*], [*Description*]
),
[`CALL` (#ref(<if-call>, form: "page"))],
[`$00`],
[Call a resident routine in the MPU's address space.],
[`HELP` (#ref(<if-help>, form: "page"))],
[`$01`],
[Display a summary of known commands.],
[`PEEK` (#ref(<if-peek>, form: "page"))],
[`$02`],
[Dumps memory from the MPU's address space to the terminal.],
[`POKE` (#ref(<if-poke>, form: "page"))],
[`$03`],
[Overwrites memory in the MPU's address space.],
[`SREC` (#ref(<if-srec>, form: "page"))],
[`$04`],
[Switches into Motorola S-Record receive mode.],
),
caption: [Table of IFs],
) <if-table>
In the following pages these IFs are described in specific.
IFs are tokenized from their textual form into a binary "bytecode" form. This
bytecode is described in @internals.
First the text command name (eg. `CALL`) is hashed in some way into a token.
Then conditional processing on the remainder of the line occurs. Values given in
hex are encoded as their corresponding bytes directly. The token buffer
mechanics are described more in @internals. Subcommands are also hashed into
tokens.
#pagebreak()
// Function for creating IF page headers
#let _ifpagehead(
desc: none,
syntax: none,
params: (),
) = {
smallcaps[#desc]
parbreak()
[Syntax: #syntax]
parbreak()
[Parameters: ]
if params.len() > 0 {
for (param, desc) in params [
- #raw("<" + upper(param) + ">"): #desc
]
} else {
text(style: "italic")[N/A]
}
}
=== IF: `CALL` <if-call>
#_ifpagehead(
desc: "Calls a resident routine in the MPU's address space.",
syntax: [`CALL <PTR>`],
params: (
ptr: "An absolute pointer to a position in the 6309 MPU's memory map.",
),
)
Call takes an absolute pointer into the MPU's address space to call as if it
were a subroutine using `JSR`.
// TODO: For when CHIBI PC-09 Prototype #2 comes out or whenever we get banking
// add it here "Special care must be taken to properly bank in the correct
// memory banks before executing this command." yadda yadda
#pagebreak()
=== IF: `HELP` <if-help>
#_ifpagehead(
desc: "Displays a summary of available IFs.",
syntax: [`HELP`],
params: ()
)
`HELP` does what it says on the tin. It should be noted that between Git tags of
the firmware the message displayed by this may be incomplete or innaccurate.
Internally all this does is print a string with the UART using the `POUTZSTR`
BIOS routine.
#pagebreak()
=== IF: `PEEK` <if-peek>
#_ifpagehead(
desc: "Dumps memory from the MPU's address space to the terminal.",
syntax: [`PEEK <BASE> [<HIGH>]`],
params: (
base: [
The address (two bytes) of the byte to dump or the base (lower bound)
address of the byte to start dumping from if `<HIGH>` is specified.
],
high: [
An optional operand given as the upper bound of the range to dump. Forms
a range together with `<BASE>`. (two bytes)
],
)
)
Peeking memory causes the MPU to read the requested bytes and dump them to the
screen.
#pagebreak()
=== IF: `POKE` <if-poke>
#_ifpagehead(
desc: "Writes values to the MPU's address space.",
syntax: [`POKE <ADDR> <BYTES>`],
params: (
addr: "The base (low) address (two bytes) to start writing bytes from.",
bytes: "The bytes to write into memory separated by whitespace.",
)
)
Poking memory causes the MPU to overwrite the bytes at `<ADDR>` with the bytes
given in `<BYTES>`.
#pagebreak()
=== IF: `SREC` <if-srec>
#_ifpagehead(
desc: "Switches into Motorola S-Record receive mode.",
syntax: [`SREC`],
params: (),
)
Motorola S-Record mode is currently a stub.
#pagebreak()
== External Functions (EFs) <ef-top>
External functions are any native user code that can be called with `CALL` (see
@if-call). This mechanism is usable to run any code or routine in memory as
though interactively using the MPU's `JSR` instruction.
=== EFs in ROM <ef-rom>
Some common EFs to call include the using call to reset the CHIBI PC-09 with
`CALL 8000`.
// TODO: Talk about memory test and BIOS interface
#pagebreak()
= BUZBEE Reserved Memory Regions <res-mem>
BUZBEE uses memory in the 0200-02FF page. A table of the layout of this memory
is provided. The memory is laid out in a packed structure starting at 0200.
#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()
= Building CHIBI PC-09 Firmware from Source <building>
Building the CHIBI PC-09 firmware from source requires LWTOOLS
#link("http://lwtools.ca"), a functioning C compiler (`cc`), and a POSIX Shell
implementation (`sh`). The firmware was developed using LWTOOLS version 4.24 on
Linux, though later versions may work as well. A GNU Make "makefile" is provided for
building on Linux. GNU binutils' `objcopy` is also used to build the compiled
Motorola S-Record into a raw binary. Development is tracked using Git.
Using the makefile is simple. It provides facilities for easy building, and
development.
To build an S-Record of the ROM run:
```sh
make generate && make boot.s19
```
To build a ROM image with `objcopy` run:
```sh
make generate && make
```
In order to rebuild, first the generated files and existing objects must be
cleaned. To do this a `make clean` pseudo-target is defined.
Building the documentation can also be accomplished using `make docs`, provided
`typst` is installed.
#pagebreak()
= BUZBEE Internals and Modding <internals>
BUZBEE's interpreter works by "compiling" textual user commands into bytecode
for more simply passing parameters to IFs (see @if-top). The way that works is
the implementation dependent, but each hash is one byte (1B) in size, and
corresponds to an IF token, which is the index of the hash.
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.

62
docs/style.typ Normal file
View File

@@ -0,0 +1,62 @@
// Style conf function for CHIBI PC-09 projects
#let conf(
title: none,
subtitle: none,
author: none,
doc,
) = {
// Global page format
set page(
paper: "us-letter",
header: align(right, text(10pt, weight: "light")[#title]),
numbering: "1",
)
// Font settings
set text(
font: "New Computer Modern",
size: 12pt,
)
// Default paragraph settings
set par(
justify: true,
first-line-indent: 1cm,
)
// Heading numbering
set heading(numbering: "1.1")
// Show table captions above tables
show figure.where(kind: table): set figure.caption(position: top)
// Title page and TOC
page(header: none, footer: none)[
// Emit title and subtitle page
#block(height: 60%)[
#align(center + horizon,
block(text(22pt)[#title]) +
block(above: 2em)[#smallcaps[#subtitle]] +
block[Written by #author],
)
]
// Emit TOC
#pagebreak()
#outline()
#pagebreak()
]
// Heading formatting for doc, must come after title page and TOC
show heading: it => [
CHAPTER
#counter(heading).display()
#it.body
]
// Emit doc
counter(page).update(1) // Reset counter for first real page
set align(left)
doc
}

View File

@@ -28,6 +28,6 @@ sed -e "s/<TAG>/$TAG/g" -e "s/<DATE>/$DATE/g" <<EOF > "$OUTFILE"
VERMSG
fcc "CHIBI PC-09 BOOT ROM <TAG>"
fcb \$0A
fcb \$0D,\$0A
fcn "BUILT <DATE>"
EOF

View File

@@ -2,5 +2,8 @@ section RESET load 8000
section SERIAL
section MEMTEST
section BUZBEE
section BBHASHES
section VECTORS high 100000
section VERSION high

View File

@@ -1,6 +1,6 @@
# Makefile for CHIBI PC-09 Firmware
.PHONY: generate all clean
.PHONY: generate all clean docs
.IGNORE: clean
.DEFAULT_GOAL := all
@@ -13,7 +13,7 @@ TARGREC := $(TARGET).s19
TARGROM := $(TARGET).bin
SRCDIR := src/
BUILDDIR := build/
GENS := $(SRCDIR)version.s
GENS := $(SRCDIR)version.s $(SRCDIR)bbhash.s
SRCS := $(wildcard $(SRCDIR)*.s)
OBJS := $(patsubst $(SRCDIR)%.s,$(BUILDDIR)%.o,$(SRCS))
INCS := $(wildcard $(SRCDIR)*.inc)
@@ -33,6 +33,9 @@ LDFLAGS := -f srec -m map.txt -s linkscript
# Rules and Phony Targets
# ------------------------------------------------------------------------------
docs: docs/*.typ
typst compile docs/buzbee.typ
all: $(TARGROM)
# Fix srec into flashable bin file
@@ -48,11 +51,18 @@ $(OBJS): $(BUILDDIR)%.o : $(SRCDIR)%.s
-@mkdir -p $(BUILDDIR)
$(AS) $(ASFLAGS) -o $@ $<
# Pseudo target for generation step
generate: $(GENS)
$(GENS):
# Run generation scripts
$(GENS): bbmkhash
./bbmkhash > src/bbhash.s
./genver.sh
# Build bbmkcmds, used to generate src/cmds.s
bbmkhash: bbmkhash.c
cc -o $@ $<
clean:
@echo 'Cleaning up intermediary files...'
@rm -rv $(TARGROM) $(TARGREC) map.txt $(BUILDDIR)

8
src/bbhash.inc Normal file
View File

@@ -0,0 +1,8 @@
; CHIBI PC-09 Machine Language Monitor -- BUZBEE Command Hash Table Symbols
; Copyright (c) 2025 Gale Faraday
; Licensed under MIT
; vim: ft=asm
BBCHTC IMPORT
BBCHT IMPORT

7
src/buzbee.inc Normal file
View File

@@ -0,0 +1,7 @@
; CHIBI PC-09 Machine Language Monitor -- BUZBEE Header
; Copyright (c) 2025 Gale Faraday
; Licensed under MIT
; vim: ft=asm
BUZBEE IMPORT

442
src/buzbee.s Normal file
View File

@@ -0,0 +1,442 @@
; CHIBI PC-09 Machine Language Monitor -- BUZBEE
; Copyright (c) 2025 Gale Faraday
; Licensed under MIT
INCLUDE "bbhash.inc"
INCLUDE "buzbee.inc"
INCLUDE "hardware.inc"
INCLUDE "serial.inc"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; BUZBEE Variables
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
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 rmd 1 ; Token buffer byte count
scratch rmd 1 ; Scratch word
ENDSTRUCT
ORG $0200
BBVAR tagbbvar
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; BUZBEE Main Loop
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SECTION BUZBEE
EXPORT BUZBEE
BUZBEE
lbsr NEWLINE ; Setup the new input line and handle display.
bsr INPLOOP ; Fill input buffer.
cmpy #0 ; No data?
beq BUZBEE ; Try again...
lbsr TOKENIZE ; Try to tokenize the input buffer
lbsr RUNIF ; Execute token buffer, handling any errors
bra BUZBEE ; Repeat
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; BUZBEE Input Buffering and Handling Routines
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Fills input buffer with characters from the serial console. Sets Y to the
; offset in the input buffer of the last char read.
INPLOOP
jsr PINCHAR ; Try to read a char
cmpd #0 ; If no char keep waitin'
beq INPLOOP
bitb #UARTF_LSR_DR ; Is there a char in A?
beq NOCHAR@
cmpa #$1B ; ESC?
beq HESC@ ; Handle ESC
cmpa #$08 ; BS?
beq HBACKSPC@ ; Backup a char
cmpa #$0D ; CR?
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)
beq INPLOOP
bitb #UARTF_LSR_OE ; Check for overrun error
beq NOOVER@
PZSTR EM_OVERRUN
NOOVER@
bitb #UARTF_LSR_PE ; Check for parity error
beq NOPARITY@
PZSTR EM_PARITY
NOPARITY@
bitb #UARTF_LSR_FE ; Check for framing error
beq NOFRAM@
PZSTR EM_FRAMING
NOFRAM@
bitb #UARTF_LSR_FIFO ; Check for FIFO error
beq INPLOOP ; Loop over
PZSTR EM_FIFO
bra INPLOOP ; Loop over
HCR@
sty BBVAR.cchinput ; Store buffer length
rts
HESC@
lda #'^ ; Print a char that signifies that ESC was pressed
jsr POUTCHAR
ldy #0 ; On return we cmpy #0 and if eq then newline
rts
HBACKSPC@
clrb ; Clear last char
leay -1,y
stb BBVAR.input
bra ECHO@ ; Echo the char in A
FULLBUF@
lda #$07 ; ASCII BEL
jsr POUTCHAR
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 #0
NEXT@
sta BBVAR.input,x ; Clear input buffer
leax 1,x
cmpx #BBIN_DEPTH
blo NEXT@
ldy #0 ; Reset buffer fill pointer
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Hex Conversion and Printing Routines
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Prints a byte in A
; @param A: byte to print
PBYTE
pshs b
tfr a,b ; Transfer lower nybble into B
andd #$F00F ; Mask and adjsut
asra
asra
asra
asra
anda #$0F
ora #'0 ; Add '0' to offset to digits
cmpa #$3A ; Hex? ':' '9'+1
blo SKIPA@
adca #6 ; Hex offset
SKIPA@
jsr POUTCHAR ; Print char in A
andb #$0F
orb #'0 ; Add '0' to offset to digits
cmpb #$3A ; Hex? ':' '9'+1
blo SKIPB@
adcb #6 ; Hex offset
SKIPB@
tfr b,a ; Print char in B
jsr POUTCHAR
puls b ; Restore B
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
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Attempts to parse the input buffer into tokens depending on the command
TOKENIZE
ldd BBVAR.cchinput ; Do we have input to work with?
cmpd #4 ; Do we have even enough space for a string command
blo TOKFAIL@ ; No? GTFO
ldy #0 ; Initialize Y; used to track current position in BBVAR.input
ldx #0 ; Initialize X; used to track position in BBVAR.tokens
bsr SKIPTONEXTC ; Get the next non-whitespace char
bsr MKCMDSUM ; Hash the first four non-whitespace chars
bsr HASH2TOKEN ; Try to turn that hash into a proper token
bcs TOKFAIL@
bra STTOK@ ; Store token
NEXTHEX@ ; Next hex token
bsr SKIPTONEXTC ; Skip to next whitespace
ldd BBVAR.input,y ; Get hex value (two digits)
bsr HEX2BYT ; Convert hex value to byte value
STTOK@
sta BBVAR.tokens,x ; Store curent token
leax 1,x ; Advance to next token
cmpx #BBTOKENS_DEPTH ; Is this next token in bounds?
beq FULLBUF@ ; No? handle a full buffer
bra NEXTHEX@ ; Try to turn the next character into a hex value
FULLBUF@
PZSTR EM_FULLTOKBUF ; Print an error message
clrd ; Say we wrote no tokens
std BBVAR.cbtokens
rts
TOKFAIL@
PZSTR EM_TOKFAIL ; Print tokenization fail
clrd ; Say we wrote no tokens
std BBVAR.cbtokens
rts
; Converts a runtime command hash into a portable token. Command tokens are
; indexes into BBCHT, which is generated at compile-time
; @param A: runtime hash
; @return A: output token
; @return CC.C: set if error state, cleared otherwise
HASH2TOKEN
pshs x ; Preserve & init X; other routines in this group use it
ldx #0
NEXTHASH@
cmpa BBCHT,x ; Is this hash our hash?
beq THISHASH@ ; Yes? turn it into a token
leax 1,x ; Begin considering next hash
cmpx BBCHTC ; Is the next hash even in the table?
blo NEXTHASH@ ; Yes? try this next hash, No? fall through
PZSTR EM_BADHASH CALL; Print an error message to the user
puls x
orcc #1 ; Set CC.C to indicate error
rts
THISHASH@
puls x
andcc #$FE ; Clear CC.C to indicate success
rts
; Makes a hash of four chars in BBIN starting at offset X
; @param Y: offset in BBIN to read the four chars from
; @return A: resulting hash
; @return Y: offset after hash processing
MKCMDSUM
pshs b
ldb #4 ; Loop over four chars
clra ; Initialize accumulator
NEXTC@
suba BBVAR.input,y ; Subtract current char from accumulator
leax 1,y ; Next char
decb ; Reduce count
cmpb #0 ; Are we at the end?
bne NEXTC@ ; No? loop
puls b
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
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Executes a command based on the initial token
; @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
tfr a,b ; Get the index in D
asld ; Cheaply << to get *2, pointer size
tfr d,x ; Move to X so we can use indexed mode with the offset
jmp [IFPTRTBL,x] ; Select IF
NOTOK@
rts
; IF pointer table
IFPTRTBL
fdb IFCALL
fdb IFHELP
fdb IFPEEK
fdb IFPOKE
fdb IFSREC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; BUZBEE Internal Command Functions
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Call a pointer
IFCALL
ldd BBVAR.cbtokens ; Only jump if three tokens given
cmpd #3
lbne INVALIDARG
jsr [BBVAR.tokens+1] ; Make our jump (doesn't implicitly return)
rts
; Print out a help message
IFHELP
PZSTR HELP_MSG
rts
; Peek memory
IFPEEK
ldd BBVAR.cbtokens ; One 16-bit token given, single peek
cmpd #3
lblo INVALIDARG ; Not enough args given
bhi SELTYPE@ ; Select forward or backward peek
SINGLE@
lda [BBVAR.tokens+1] ; Get byte
lbsr PBYTE ; Print peek byte
rts
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
bhi INVALIDARG ; Malformed if BASE > HIGH
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
; Poke bytes into memory
; NOTE: Blocks could also use 6309 TFM instruction
IFPOKE
ldx BBVAR.cbtokens ; Make sure we have enough tokens
cmpx #4
lblo INVALIDARG
leax -3,x ; Get count of bytes to write into X
ldy #0 ; Setup Y for indexing
NEXTB@
lda BBVAR.tokens+3,y ; Get source byte to copy
sta [BBVAR.tokens+1,y] ; Copy byte
leay +1,y ; Increment memory indexer
leax -1,x ; Decement byte count
cmpx #0 ; Are we at our last byte?
bhi NEXTB@ ; No? loop
rts
; Placeholder function labels to make assembler happy before git commit
IFSREC
rts
; Invalid argument IF tail
INVALIDARG
PZSTR EM_BADARG
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; BUZBEE Strings and Fixed Data
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
HELP_MSG
fcc "-- BUZBEE HELP --"
fcb $0D,$0A
fcc "Available Commands:"
fcb $0D,$0A
fcc "CALL <PTR> - Call the pointer given in <PTR> as a subroutine."
fcb $0D,$0A
fcc "HELP [CMD] - Display help, command optional."
fcb $0D,$0A
fcc "PEEK <BASE> [<HIGH>] - Read memory at <BASE> to <HIGH>."
fcb $0D,$0A
fcc "POKE <ADDR> <BYTES> - Overwrite memory with <BYTES> starting at <BASE>."
fcb $0D,$0A
fcc "SREC - Enter Motorola S-Record entry mode."
fcb $0D,$0A
fcb $00
PROMPTLINE
fcb $0D,$0A,$25,$00 ; CR LF '%' NUL
EM_OVERRUN
fcc "!!! UART Overrun Error !!!"
fcb $0D,$0A,$00
EM_PARITY
fcc "!!! UART Parity Error !!!"
fcb $0D,$0A,$00
EM_FRAMING
fcc "!!! UART Framing Error !!!"
fcb $0D,$0A,$00
EM_FIFO
fcc "!!! UART FIFO Error !!!"
fcb $0D,$0A,$00
EM_BADHASH
fcc "!!! Bad Command Hash !!!"
fcb $0D,$0A,$00
EM_BADARG
fcc "!!! Malformed Arguments !!!"
fcb $0D,$0A,$00
EM_TOKFAIL
fcc "!!! Tokenization Failure !!!"
fcb $0D,$0A,$00
EM_BADHEX
fcc "!!! Malformed Hex Value !!!"
fcb $0D,$0A,$00
EM_FULLTOKBUF
fcc "!!! Token Buffer Overrun !!!"
fcb $0D,$0A,$00

View File

@@ -18,7 +18,7 @@
; RAM testing routine. Ported to 6809 from 6800, based on source for ROBIT-2 for
; MIKBUG.
RAMTEST
ldx #SRAM_BASE
ldx #STACK_TOP+1 ; bottom of testable SRAM, $0200
AGAIN@ ; Store 1 in memory
lda #1 ; Set [X] to 1
sta 0,x

View File

@@ -2,9 +2,10 @@
; Copyright (c) 2024-2025 Amber Zeller, Gale Faraday
; Licensed under MIT
INCLUDE "buzbee.inc"
INCLUDE "hardware.inc"
INCLUDE "serial.inc"
INCLUDE "memtest.inc"
INCLUDE "serial.inc"
INCLUDE "version.inc"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -22,8 +23,8 @@ RESET
CLRSTACK
; Initialize the system stack
lda #$00 ; Initialize A & X to zero out the stack
ldx #$0000
clra ; Init A & X to zero out the stack
ldx #0
NEXT@
sta STACK_BOTTOM,x ; Write a zero and progress to the next byte
leax 1,x
@@ -35,13 +36,19 @@ BOOTSCR
lda #13 ; 9600 baud
ldb #%11 ; 8N1
jsr INITUART ; Initialize serial console
ldx #VERMSG ; Print version information
jsr POUTZSTR
PZSTR VERMSG ; Print version information
; Progress to POST
POST
jsr RAMTEST
; Hand off control to the BUZBEE monitor and print notification of leaving the
; firmware
ENTERMON
PZSTR TXTRUN
jmp BUZBEE
HALT
sync ; Halt and wait for interrupts
bra HALT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Text/Resources for Reset Handler
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TXTRUN
fcn "<3RUN<3"