nascom basic compiles and works
This commit is contained in:
@@ -25,6 +25,8 @@ TINYBASIC_SRC := apps/tinybasic/tinybasic.asm
|
|||||||
TINYBASIC_BUILD := $(BUILDDIR)/tinybasic
|
TINYBASIC_BUILD := $(BUILDDIR)/tinybasic
|
||||||
TAPE_LOADER_SRC := apps/casette/tape_loader.asm
|
TAPE_LOADER_SRC := apps/casette/tape_loader.asm
|
||||||
TAPE_LOADER_BUILD := $(BUILDDIR)/casette
|
TAPE_LOADER_BUILD := $(BUILDDIR)/casette
|
||||||
|
NASCOM_BASIC_SRC := apps/nascom_basic/basic.asm
|
||||||
|
NASCOM_BASIC_BUILD := $(BUILDDIR)/nascom_basic
|
||||||
|
|
||||||
.DEFAULT_GOAL := metal
|
.DEFAULT_GOAL := metal
|
||||||
|
|
||||||
@@ -48,6 +50,9 @@ metal: $(BUILDDIR)/metal/$(TARGET).ihx $(BUILDDIR)/metal/$(TARGET).bin $(BUILDDI
|
|||||||
@printf " Tape loader: %5u ROM bytes at %04X\n" \
|
@printf " Tape loader: %5u ROM bytes at %04X\n" \
|
||||||
$$(wc -c < $(TAPE_LOADER_BUILD)/tape_loader.bin) \
|
$$(wc -c < $(TAPE_LOADER_BUILD)/tape_loader.bin) \
|
||||||
$$(( $(TAPE_LOADER_ROM_ADDRESS) ))
|
$$(( $(TAPE_LOADER_ROM_ADDRESS) ))
|
||||||
|
@printf " NASCOM BASIC: %5u ROM bytes at %04X\n" \
|
||||||
|
$$(wc -c < $(NASCOM_BASIC_BUILD)/nascom_basic.bin) \
|
||||||
|
$$(( $(NASCOM_BASIC_ROM_ADDRESS) ))
|
||||||
|
|
||||||
$(BUILDDIR)/metal/$(TARGET).ihx: $(METAL_RELFILES)
|
$(BUILDDIR)/metal/$(TARGET).ihx: $(METAL_RELFILES)
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
@@ -56,13 +61,14 @@ $(BUILDDIR)/metal/$(TARGET).ihx: $(METAL_RELFILES)
|
|||||||
$(BUILDDIR)/metal/$(TARGET).flat.bin: $(BUILDDIR)/metal/$(TARGET).ihx
|
$(BUILDDIR)/metal/$(TARGET).flat.bin: $(BUILDDIR)/metal/$(TARGET).ihx
|
||||||
$(METAL_MAKEBIN) -s $(METAL_IMAGE_SIZE) $< $@
|
$(METAL_MAKEBIN) -s $(METAL_IMAGE_SIZE) $< $@
|
||||||
|
|
||||||
$(BUILDDIR)/metal/$(TARGET).prog.bin: $(BUILDDIR)/metal/$(TARGET).flat.bin $(TINYBASIC_BUILD)/tinybasic.bin $(TAPE_LOADER_BUILD)/tape_loader.bin
|
$(BUILDDIR)/metal/$(TARGET).prog.bin: $(BUILDDIR)/metal/$(TARGET).flat.bin $(TINYBASIC_BUILD)/tinybasic.bin $(TAPE_LOADER_BUILD)/tape_loader.bin $(NASCOM_BASIC_BUILD)/nascom_basic.bin
|
||||||
@set -e; \
|
@set -e; \
|
||||||
payload_end=$$(awk '$$1 == "DEF" && $$2 == "resident_image_end" { print $$3 }' $(BUILDDIR)/metal/$(TARGET).noi); \
|
payload_end=$$(awk '$$1 == "DEF" && $$2 == "resident_image_end" { print $$3 }' $(BUILDDIR)/metal/$(TARGET).noi); \
|
||||||
payload_size=$$((payload_end - $(RESIDENT_RAM_BASE))); \
|
payload_size=$$((payload_end - $(RESIDENT_RAM_BASE))); \
|
||||||
payload_rom_end=$$(( $(RESIDENT_ROM_OFFSET) + payload_size )); \
|
payload_rom_end=$$(( $(RESIDENT_ROM_OFFSET) + payload_size )); \
|
||||||
tiny_size=$$(wc -c < $(TINYBASIC_BUILD)/tinybasic.bin); \
|
tiny_size=$$(wc -c < $(TINYBASIC_BUILD)/tinybasic.bin); \
|
||||||
tape_size=$$(wc -c < $(TAPE_LOADER_BUILD)/tape_loader.bin); \
|
tape_size=$$(wc -c < $(TAPE_LOADER_BUILD)/tape_loader.bin); \
|
||||||
|
nascom_size=$$(wc -c < $(NASCOM_BASIC_BUILD)/nascom_basic.bin); \
|
||||||
if test $$payload_size -le 0; then \
|
if test $$payload_size -le 0; then \
|
||||||
echo "error: resident image is empty or has an invalid end symbol" >&2; exit 1; \
|
echo "error: resident image is empty or has an invalid end symbol" >&2; exit 1; \
|
||||||
fi; \
|
fi; \
|
||||||
@@ -74,14 +80,19 @@ $(BUILDDIR)/metal/$(TARGET).prog.bin: $(BUILDDIR)/metal/$(TARGET).flat.bin $(TIN
|
|||||||
printf "error: Tiny BASIC ends at %04X, beyond tape-loader origin %04X\n" \
|
printf "error: Tiny BASIC ends at %04X, beyond tape-loader origin %04X\n" \
|
||||||
$$(( $(TINYBASIC_ROM_ADDRESS) + tiny_size )) $$(( $(TAPE_LOADER_ROM_ADDRESS) )) >&2; exit 1; \
|
$$(( $(TINYBASIC_ROM_ADDRESS) + tiny_size )) $$(( $(TAPE_LOADER_ROM_ADDRESS) )) >&2; exit 1; \
|
||||||
fi; \
|
fi; \
|
||||||
if test $$(( $(TAPE_LOADER_ROM_ADDRESS) + tape_size )) -gt $$(( $(ROM_SIZE) )); then \
|
if test $$(( $(TAPE_LOADER_ROM_ADDRESS) + tape_size )) -gt $$(( $(NASCOM_BASIC_ROM_ADDRESS) )); then \
|
||||||
printf "error: tape loader ends at %04X, beyond ROM size %04X\n" \
|
printf "error: tape loader ends at %04X, beyond NASCOM BASIC origin %04X\n" \
|
||||||
$$(( $(TAPE_LOADER_ROM_ADDRESS) + tape_size )) $$(( $(ROM_SIZE) )) >&2; exit 1; \
|
$$(( $(TAPE_LOADER_ROM_ADDRESS) + tape_size )) $$(( $(NASCOM_BASIC_ROM_ADDRESS) )) >&2; exit 1; \
|
||||||
fi; \
|
fi; \
|
||||||
dd if=$< of=$@ bs=1 count=$$(( $(TAPE_LOADER_ROM_ADDRESS) )) status=none; \
|
if test $$(( $(NASCOM_BASIC_ROM_ADDRESS) + nascom_size )) -gt $$(( $(ROM_SIZE) )); then \
|
||||||
|
printf "error: NASCOM BASIC ends at %04X, beyond ROM size %04X\n" \
|
||||||
|
$$(( $(NASCOM_BASIC_ROM_ADDRESS) + nascom_size )) $$(( $(ROM_SIZE) )) >&2; exit 1; \
|
||||||
|
fi; \
|
||||||
|
dd if=$< of=$@ bs=1 count=$$(( $(NASCOM_BASIC_ROM_ADDRESS) )) status=none; \
|
||||||
dd if=$< of=$@ bs=1 skip=$$(( $(RESIDENT_RAM_BASE) )) seek=$$(( $(RESIDENT_ROM_OFFSET) )) count=$$payload_size conv=notrunc status=none; \
|
dd if=$< of=$@ bs=1 skip=$$(( $(RESIDENT_RAM_BASE) )) seek=$$(( $(RESIDENT_ROM_OFFSET) )) count=$$payload_size conv=notrunc status=none; \
|
||||||
dd if=$(TINYBASIC_BUILD)/tinybasic.bin of=$@ bs=1 seek=$$(( $(TINYBASIC_ROM_ADDRESS) )) conv=notrunc status=none; \
|
dd if=$(TINYBASIC_BUILD)/tinybasic.bin of=$@ bs=1 seek=$$(( $(TINYBASIC_ROM_ADDRESS) )) conv=notrunc status=none; \
|
||||||
dd if=$(TAPE_LOADER_BUILD)/tape_loader.bin of=$@ bs=1 seek=$$(( $(TAPE_LOADER_ROM_ADDRESS) )) conv=notrunc status=none
|
dd if=$(TAPE_LOADER_BUILD)/tape_loader.bin of=$@ bs=1 seek=$$(( $(TAPE_LOADER_ROM_ADDRESS) )) conv=notrunc status=none; \
|
||||||
|
dd if=$(NASCOM_BASIC_BUILD)/nascom_basic.bin of=$@ bs=1 seek=$$(( $(NASCOM_BASIC_ROM_ADDRESS) )) conv=notrunc status=none
|
||||||
|
|
||||||
$(BUILDDIR)/metal/$(TARGET).bin: $(BUILDDIR)/metal/$(TARGET).flat.bin $(BUILDDIR)/metal/$(TARGET).prog.bin
|
$(BUILDDIR)/metal/$(TARGET).bin: $(BUILDDIR)/metal/$(TARGET).flat.bin $(BUILDDIR)/metal/$(TARGET).prog.bin
|
||||||
dd if=$< of=$@ bs=$(METAL_BIN_SIZE) count=1 status=none
|
dd if=$< of=$@ bs=$(METAL_BIN_SIZE) count=1 status=none
|
||||||
@@ -125,6 +136,10 @@ $(TAPE_LOADER_BUILD)/tape_loader.bin: $(TAPE_LOADER_BUILD)/tape_loader.flat.bin
|
|||||||
test $$loader_size -gt 0; \
|
test $$loader_size -gt 0; \
|
||||||
dd if=$< of=$@ bs=1 skip=$$(( $(TAPE_LOADER_ROM_ADDRESS) )) count=$$loader_size status=none
|
dd if=$< of=$@ bs=1 skip=$$(( $(TAPE_LOADER_ROM_ADDRESS) )) count=$$loader_size status=none
|
||||||
|
|
||||||
|
$(NASCOM_BASIC_BUILD)/nascom_basic.bin: $(NASCOM_BASIC_SRC)
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
zasm --z80 $< -o $@ -l0
|
||||||
|
|
||||||
$(LAYOUT_HEADER): $(LAYOUT_CONFIG)
|
$(LAYOUT_HEADER): $(LAYOUT_CONFIG)
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
@awk 'BEGIN { print "#ifndef ROM_LAYOUT_H"; print "#define ROM_LAYOUT_H"; print "" } \
|
@awk 'BEGIN { print "#ifndef ROM_LAYOUT_H"; print "#define ROM_LAYOUT_H"; print "" } \
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
*.bin
|
||||||
|
*.lst
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,202 @@
|
|||||||
|
;==================================================================================
|
||||||
|
; Contents of this file are copyright Grant Searle
|
||||||
|
;
|
||||||
|
; You have permission to use this for NON COMMERCIAL USE ONLY
|
||||||
|
; If you wish to use it elsewhere, please include an acknowledgement to myself.
|
||||||
|
;
|
||||||
|
; http://searle.hostei.com/grant/index.html
|
||||||
|
;
|
||||||
|
; eMail: home.micros01@btinternet.com
|
||||||
|
;
|
||||||
|
; If the above don't work, please perform an Internet search to see if I have
|
||||||
|
; updated the web page hosting service.
|
||||||
|
;
|
||||||
|
;==================================================================================
|
||||||
|
|
||||||
|
; Minimum 6850 ACIA interrupt driven serial I/O to run modified NASCOM Basic 4.7
|
||||||
|
; Full input buffering with incoming data hardware handshaking
|
||||||
|
; Handshake shows full before the buffer is totally filled to allow run-on from the sender
|
||||||
|
|
||||||
|
SER_BUFSIZE .EQU 3FH
|
||||||
|
SER_FULLSIZE .EQU 30H
|
||||||
|
SER_EMPTYSIZE .EQU 5
|
||||||
|
|
||||||
|
RTS_HIGH .EQU 0D6H
|
||||||
|
RTS_LOW .EQU 096H
|
||||||
|
|
||||||
|
serBuf .EQU $2000
|
||||||
|
serInPtr .EQU serBuf+SER_BUFSIZE
|
||||||
|
serRdPtr .EQU serInPtr+2
|
||||||
|
serBufUsed .EQU serRdPtr+2
|
||||||
|
basicStarted .EQU serBufUsed+1
|
||||||
|
TEMPSTACK .EQU $20ED ; Top of BASIC line input buffer so is "free ram" when BASIC resets
|
||||||
|
|
||||||
|
CR .EQU 0DH
|
||||||
|
LF .EQU 0AH
|
||||||
|
CS .EQU 0CH ; Clear screen
|
||||||
|
|
||||||
|
.ORG $0000
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
; Reset
|
||||||
|
|
||||||
|
RST00 DI ;Disable interrupts
|
||||||
|
JP INIT ;Initialize Hardware and go
|
||||||
|
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
; TX a character over RS232
|
||||||
|
|
||||||
|
.ORG 0008H
|
||||||
|
RST08 JP TXA
|
||||||
|
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
; RX a character over RS232 Channel A [Console], hold here until char ready.
|
||||||
|
|
||||||
|
.ORG 0010H
|
||||||
|
RST10 JP RXA
|
||||||
|
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
; Check serial status
|
||||||
|
|
||||||
|
.ORG 0018H
|
||||||
|
RST18 JP CKINCHAR
|
||||||
|
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
; RST 38 - INTERRUPT VECTOR [ for IM 1 ]
|
||||||
|
|
||||||
|
.ORG 0038H
|
||||||
|
RST38 JR serialInt
|
||||||
|
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
serialInt: PUSH AF
|
||||||
|
PUSH HL
|
||||||
|
|
||||||
|
IN A,($80)
|
||||||
|
AND $01 ; Check if interupt due to read buffer full
|
||||||
|
JR Z,rts0 ; if not, ignore
|
||||||
|
|
||||||
|
IN A,($81)
|
||||||
|
PUSH AF
|
||||||
|
LD A,(serBufUsed)
|
||||||
|
CP SER_BUFSIZE ; If full then ignore
|
||||||
|
JR NZ,notFull
|
||||||
|
POP AF
|
||||||
|
JR rts0
|
||||||
|
|
||||||
|
notFull: LD HL,(serInPtr)
|
||||||
|
INC HL
|
||||||
|
LD A,L ; Only need to check low byte becasuse buffer<256 bytes
|
||||||
|
CP (serBuf+SER_BUFSIZE) & $FF
|
||||||
|
JR NZ, notWrap
|
||||||
|
LD HL,serBuf
|
||||||
|
notWrap: LD (serInPtr),HL
|
||||||
|
POP AF
|
||||||
|
LD (HL),A
|
||||||
|
LD A,(serBufUsed)
|
||||||
|
INC A
|
||||||
|
LD (serBufUsed),A
|
||||||
|
CP SER_FULLSIZE
|
||||||
|
JR C,rts0
|
||||||
|
LD A,RTS_HIGH
|
||||||
|
OUT ($80),A
|
||||||
|
rts0: POP HL
|
||||||
|
POP AF
|
||||||
|
EI
|
||||||
|
RETI
|
||||||
|
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
RXA:
|
||||||
|
waitForChar: LD A,(serBufUsed)
|
||||||
|
CP $00
|
||||||
|
JR Z, waitForChar
|
||||||
|
PUSH HL
|
||||||
|
LD HL,(serRdPtr)
|
||||||
|
INC HL
|
||||||
|
LD A,L ; Only need to check low byte becasuse buffer<256 bytes
|
||||||
|
CP (serBuf+SER_BUFSIZE) & $FF
|
||||||
|
JR NZ, notRdWrap
|
||||||
|
LD HL,serBuf
|
||||||
|
notRdWrap: DI
|
||||||
|
LD (serRdPtr),HL
|
||||||
|
LD A,(serBufUsed)
|
||||||
|
DEC A
|
||||||
|
LD (serBufUsed),A
|
||||||
|
CP SER_EMPTYSIZE
|
||||||
|
JR NC,rts1
|
||||||
|
LD A,RTS_LOW
|
||||||
|
OUT ($80),A
|
||||||
|
rts1:
|
||||||
|
LD A,(HL)
|
||||||
|
EI
|
||||||
|
POP HL
|
||||||
|
RET ; Char ready in A
|
||||||
|
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
TXA: PUSH AF ; Store character
|
||||||
|
conout1: IN A,($80) ; Status byte
|
||||||
|
BIT 1,A ; Set Zero flag if still transmitting character
|
||||||
|
JR Z,conout1 ; Loop until flag signals ready
|
||||||
|
POP AF ; Retrieve character
|
||||||
|
OUT ($81),A ; Output the character
|
||||||
|
RET
|
||||||
|
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
CKINCHAR LD A,(serBufUsed)
|
||||||
|
CP $0
|
||||||
|
RET
|
||||||
|
|
||||||
|
PRINT: LD A,(HL) ; Get character
|
||||||
|
OR A ; Is it $00 ?
|
||||||
|
RET Z ; Then RETurn on terminator
|
||||||
|
RST 08H ; Print it
|
||||||
|
INC HL ; Next Character
|
||||||
|
JR PRINT ; Continue until $00
|
||||||
|
RET
|
||||||
|
;------------------------------------------------------------------------------
|
||||||
|
INIT:
|
||||||
|
LD HL,TEMPSTACK ; Temp stack
|
||||||
|
LD SP,HL ; Set up a temporary stack
|
||||||
|
LD HL,serBuf
|
||||||
|
LD (serInPtr),HL
|
||||||
|
LD (serRdPtr),HL
|
||||||
|
XOR A ;0 to accumulator
|
||||||
|
LD (serBufUsed),A
|
||||||
|
LD A,RTS_LOW
|
||||||
|
OUT ($80),A ; Initialise ACIA
|
||||||
|
IM 1
|
||||||
|
EI
|
||||||
|
LD HL,SIGNON1 ; Sign-on message
|
||||||
|
CALL PRINT ; Output string
|
||||||
|
LD A,(basicStarted); Check the BASIC STARTED flag
|
||||||
|
CP 'Y' ; to see if this is power-up
|
||||||
|
JR NZ,COLDSTART ; If not BASIC started then always do cold start
|
||||||
|
LD HL,SIGNON2 ; Cold/warm message
|
||||||
|
CALL PRINT ; Output string
|
||||||
|
CORW:
|
||||||
|
CALL RXA
|
||||||
|
AND %11011111 ; lower to uppercase
|
||||||
|
CP 'C'
|
||||||
|
JR NZ, CHECKWARM
|
||||||
|
RST 08H
|
||||||
|
LD A,$0D
|
||||||
|
RST 08H
|
||||||
|
LD A,$0A
|
||||||
|
RST 08H
|
||||||
|
COLDSTART: LD A,'Y' ; Set the BASIC STARTED flag
|
||||||
|
LD (basicStarted),A
|
||||||
|
JP $0150 ; Start BASIC COLD
|
||||||
|
CHECKWARM:
|
||||||
|
CP 'W'
|
||||||
|
JR NZ, CORW
|
||||||
|
RST 08H
|
||||||
|
LD A,$0D
|
||||||
|
RST 08H
|
||||||
|
LD A,$0A
|
||||||
|
RST 08H
|
||||||
|
JP $0153 ; Start BASIC WARM
|
||||||
|
|
||||||
|
SIGNON1: .BYTE CS
|
||||||
|
.BYTE "Z80 SBC By Grant Searle",CR,LF,0
|
||||||
|
SIGNON2: .BYTE CR,LF
|
||||||
|
.BYTE "Cold or warm start (C or W)? ",0
|
||||||
|
|
||||||
|
.END
|
||||||
@@ -13,3 +13,4 @@ RESIDENT_DATA_BASE := 0xF000
|
|||||||
|
|
||||||
TINYBASIC_ROM_ADDRESS := 0x1400
|
TINYBASIC_ROM_ADDRESS := 0x1400
|
||||||
TAPE_LOADER_ROM_ADDRESS := 0x3000
|
TAPE_LOADER_ROM_ADDRESS := 0x3000
|
||||||
|
NASCOM_BASIC_ROM_ADDRESS := 0x4000
|
||||||
|
|||||||
Reference in New Issue
Block a user