mirror of https://github.com/brouhaha/a1mon68.git
215 lines
7.0 KiB
NASM
215 lines
7.0 KiB
NASM
; a1mon68: a rewrite of the Apple 1 monitor to run on an MC6800
|
|
; microprocessor, rather than the MCS6502 microprocessor that
|
|
; was standard.
|
|
|
|
; Copyright 2011 Eric Smith <spacewar@gmail.com>
|
|
|
|
; This source code will assemble with the AS Macro Assembler:
|
|
; http://john.ccac.rwth-aachen.de:8000/as/
|
|
; With minor changes it should assemble with any MC6800 assembler.
|
|
|
|
; This program is free software; you can redistribute and/or modify it
|
|
; under the terms of the GNU General Public License version 3 as
|
|
; published by the Free Software Foundation.
|
|
;
|
|
; This program is distributed in the hope that it will be useful, but
|
|
; WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
; General Public License for more details.
|
|
;
|
|
; You should have received a copy of the GNU General Public License
|
|
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
cpu 6800
|
|
|
|
xam equ $0024 ; two bytes
|
|
st equ $0026 ; two bytes
|
|
h equ $0028
|
|
l equ $0029
|
|
|
|
mode equ $002b
|
|
ysav equ $002c ; two bytes
|
|
inptr equ $002e ; two bytes
|
|
|
|
in equ $0200
|
|
|
|
kbd equ $d010
|
|
kbd_cr equ $d011
|
|
dsp equ $d012
|
|
dsp_cr equ $d013
|
|
|
|
org $ff00
|
|
|
|
reset: ; cld ; No decimal mode on 6800, so we don't need
|
|
; need to clear it.
|
|
; cli ; Disable interrupts - not actually needed on reset.
|
|
ldab #$7f ; Mask for DSP data direction register.
|
|
stab dsp ; Set it up.
|
|
ldab #$a7 ; KBD and DSP control register mask.
|
|
stab kbd_cr ; Enable interrupts, set CA1, CB1, for
|
|
stab dsp_cr ; positive edge sense/output mode.
|
|
lds #$01ff ; On the 6502, the monitor didn't initialize the
|
|
; stack pointer, which was OK because it was
|
|
; guaranteed to be somewhere in page 1. Not so
|
|
; on the 6800!
|
|
; Ideally, I'd take advantage of the stack
|
|
; starting right before the input buffer to
|
|
; save a few bytes, but I haven't yet figured
|
|
; out how to do it.
|
|
|
|
; Note that B contains $a7 here, which means that the incb below will
|
|
; set the negative flag, causing the bpl to fall through into escape.
|
|
; This saves us a "bra escape" instruction here.
|
|
|
|
; Get a line of input from the keyboard, echoing to display.
|
|
; Normally enter at escape or getline.
|
|
|
|
notcr: cmpa #$df ; "_"? [NB back arrow]
|
|
beq backspace ; Yes.
|
|
cmpa #$9b ; ESC?
|
|
beq escape ; Yes.
|
|
inx ; Advance text index.
|
|
incb
|
|
bpl nextchar ; Auto ESC if > 127.
|
|
|
|
escape: ldaa #$dc ; "\".
|
|
jsr echo ; Output it.
|
|
|
|
getline: ldaa #$8d ; CR.
|
|
jsr echo ; Output it.
|
|
ldx #in+1 ; Initiallize [sic] text index.
|
|
ldab #1
|
|
backspace: dex ; Back up text index.
|
|
decb
|
|
bmi getline ; Beyond start of line, reinitialize.
|
|
|
|
nextchar: ldaa kbd_cr ; Key ready?
|
|
bpl nextchar ; Loop until ready.
|
|
ldaa kbd ; Load character. B7 should be '1'.
|
|
staa ,x ; Add to text buffer.
|
|
bsr echo ; Display character.
|
|
cmpa #$8d ; CR?
|
|
bne notcr ; No.
|
|
|
|
; Process an input line.
|
|
|
|
cr: ldx #in+256-1 ; Reset text index to in-1, +256 so that
|
|
; 'inc inptr+1' will result in $0200.
|
|
stx inptr
|
|
clra ; For XAM mode. 0->B.
|
|
|
|
setblok: asl a ; Leaves $56 if setting BLOCK XAM mode.
|
|
setmode: staa mode ; $00 = XAM, $BA = STOR, $56 = BLOK XAM.
|
|
blskip: inc inptr+1 ; Advance text index.
|
|
nextitem: ldx inptr
|
|
ldaa ,x ; Get character.
|
|
cmpa #$8d ; CR?
|
|
beq getline ; Yes, done this line.
|
|
cmpa #$ae ; "."?
|
|
beq setblok ; Set BLOCK XAM mode.
|
|
bls blskip ; Skip delimiter.
|
|
cmpa #$ba ; ":"?
|
|
beq setmode ; Yes, set STOR mode.
|
|
cmpa #$d2 ; "R"?
|
|
beq run ; Yes, run user program.
|
|
clr l ; $00->L.
|
|
clr h ; and H.
|
|
stx ysav ; Save Y for comparison.
|
|
|
|
nexthex: ldx inptr
|
|
ldaa ,x ; Get character for hex test.
|
|
eora #$b0 ; Map digits to $0-9.
|
|
cmpa #$09 ; Digit?
|
|
bls dig ; Yes.
|
|
adda #$89 ; Map letter "A"-"F" to $FA-FF.
|
|
cmpa #$f9 ; Hex letter?
|
|
bls nothex ; No, character not hex.
|
|
|
|
dig: asla ; Hex digit to MSD of A.
|
|
asla
|
|
asla
|
|
asla
|
|
|
|
ldab #$04 ; Shift count.
|
|
hexshift: asla ; Hex digit left, MSB to carry.
|
|
rol l ; Rotate into LSD.
|
|
rol h ; Rotate into MSD's.
|
|
decb ; Done 4 shifts?
|
|
bne hexshift ; No, loop.
|
|
|
|
inc inptr+1 ; Advance text index.
|
|
bra nexthex ; Always taken. Check next character for hex.
|
|
|
|
nothex: cpx ysav ; Check if L, H empty (no hex digits).
|
|
beq escape ; Yes, generate ESC sequence.
|
|
tst mode ; Test MODE byte.
|
|
bpl notstor ; B6=0 for STOR, 1 for XAM and BLOCK XAM
|
|
|
|
; STOR mode
|
|
ldx st
|
|
ldaa l ; LSD's of hex data.
|
|
staa ,x ; Store at current 'store index'.
|
|
inx
|
|
stx st
|
|
tonextitem: bra nextitem ; Get next command item.
|
|
|
|
prbyte: psh a ; Save A for LSD.
|
|
lsra
|
|
lsra
|
|
lsra ; MSD to LSD position.
|
|
lsra
|
|
bsr prhex ; Output hex digit.
|
|
pul a ; Restore A.
|
|
prhex: anda #$0f ; Mask LSD for hex print.
|
|
oraa #$b0 ; Add "0".
|
|
cmpa #$b9 ; Digit?
|
|
bls echo ; Yes, output it.
|
|
adda #$07 ; Add offset for letter.
|
|
echo: tst dsp ; DA bit (B7) cleared yet?
|
|
bmi echo ; No, wait for display.
|
|
staa dsp ; Output character. Sets DA.
|
|
rts ; Return.
|
|
|
|
run: ldx xam
|
|
jmp ,x ; Run at current XAM index.
|
|
|
|
notstor: bne xamnext ; mode = $00 for XAM, $56 for BLOCK XAM.
|
|
|
|
ldx h ; Copy hex data to
|
|
stx st ; 'store index'.
|
|
stx xam ; And to 'XAM index'.
|
|
clra ; set Z flag to force following branch.
|
|
|
|
nxtprnt: bne prdata ; NE means no address to print.
|
|
ldaa #$8d ; CR.
|
|
bsr echo ; Output it.
|
|
ldaa xam ; 'Examine index' high-order byte.
|
|
bsr prbyte ; Output it in hex format.
|
|
ldaa xam+1 ; Low-order 'Examine index' byte.
|
|
bsr prbyte ; Output it in hex format.
|
|
ldaa #$ba ; ":".
|
|
bsr echo ; Output it.
|
|
|
|
prdata: ldaa #$a0 ; Blank.
|
|
bsr echo ; Output it.
|
|
|
|
ldx xam
|
|
ldaa ,x ; Get data byte at 'examine index'.
|
|
bsr prbyte ; Output it in hex format.
|
|
|
|
xamnext: clr mode ; 0->MODE (XAM mode).
|
|
ldx xam ; Compare 'examine index' to hex data.
|
|
cpx h
|
|
beq tonextitem ; Not less, so more data to output.
|
|
inx
|
|
stx xam
|
|
ldaa xam+1 ; Check low-order 'examine index' byte
|
|
anda #$07 ; For MOD 8 = 0
|
|
bra nxtprnt ; always taken
|
|
|
|
org $fff8 ; vector table
|
|
fdb $0000 ; IRQ
|
|
fdb $0000 ; SWI
|
|
fdb $f000 ; NMI
|
|
fdb $ff00 ; RESET
|