commit e43c0ba9a8c944f2d62ec4358a198f8be363efd5
parent 82c47766dfd4fd7d1a2490220735a7e38ee58777
Author: Gerd Beuster <gerd@frombelow.net>
Date: Sun, 27 Dec 2020 13:22:01 +0100
Changed bus logic to support up to 4 I/O devices
Diffstat:
38 files changed, 1504 insertions(+), 1560 deletions(-)
diff --git a/doc/Documentation.txt b/doc/Documentation.txt
@@ -1,4 +1,4 @@
-* GATE 2010 - An 8-Bit Computer
+* Eris 2010 - An 8-Bit Computer
** Main Components
@@ -6,7 +6,7 @@ The computer is based on a 65C02 running at 1 Mhz with 32K RAM
(AS6C62256-55PCN) and 8 K EEPROM (AT28C64B-15PU). A W65C51N ACAI
provides a serial communication interface. Bus logic is provided by a
ATF16V8B EEPLD. The reset logic is based on a NE555 in a monostable
-configuration (with a little help (an inverter of the AFT16V8B).
+configuration with a little help (an inverter on the AFT16V8B).
See hw/bom.ods for details of the components. (This list also contains
components not used in the current design.)
@@ -138,7 +138,7 @@ for examples.
*** gfs.py
Program for formatting, listing, and writing SD card in a format
-readable by GATE 2010.
+readable by Eris 2010.
*** boot.py
@@ -178,9 +178,21 @@ replaced by a NE555 configured as a monostable multivibrator.
** TODOs
+*** Wire interrupt lines
+
+- To VIA(s) and ACIA(s)
+- Add reset button
+
+*** Reset Logic
+
+- Add switch or jumper to enable/disable connection between DTR and reset
+- Change indicator LED to off-on-reset
+- Reduce delay in NE555 reset circuit
+
*** Write library functions
- Multiplication and division
- CRC generator
*** Design PCB
+
diff --git a/hw/bus_logic/BUS_LOGIC.PLD b/hw/bus_logic/BUS_LOGIC.PLD
@@ -22,10 +22,10 @@ pin 8 = reset_in; /* Reset logic output */
pin 9 = phi; /* cpu_PHI2 */
pin 12 = o0; /* eeprom_#ce */
pin 13 = o1; /* ram_#oe */
-pin 14 = o2; /* acai_#cs0 */
+pin 14 = o2; /* I/O Devices */
pin 15 = o3; /* ram_#ce */
-pin 16 = o4; /* ce (not assigned) */
-pin 17 = o5; /* ce (not assigned) */
+pin 16 = o4; /* I/O Devices */
+pin 17 = o5; /* I/O Devices */
pin 18 = o6; /* #we */
pin 19 = o7; /* cpu_RESB */
@@ -39,30 +39,43 @@ o0 = (!i0 # !i1 # !i2);
/* RAM (32k)
Address range: 0x0000 - 0x7fff
Bit pattern: 0b0...............
- */
-
-/* See below */
-
-/* ACIA (1k)
- Address range: 0xdc00 - 0xdfff
- Bit pattern: 0b110111..........
-*/
-
-o2 = (!i0 # !i1 # i2 # !i3 # !i4 # !i5);
-/* VIA (1k)
- Address range: 0xd800 - 0xdbff
- Bit pattern: 0b110110..........
-*/
+ RAM access must happen only in secon half of cycle, therefore
+ oe#, ce#, and we# are qualified by !phi.
+ */
-o4 = (!i0 # !i1 # i2 # !i3 # !i4 # i5);
+o1 = !phi # !rwb; /* ram_oe# */
+o3 = !phi # i0; /* ram_ce# */
+o6 = !phi # rwb; /* ram_we# */
+
+/* In order to drive up to 4 I/O devices from 3 output lines, we
+ exploit that both the 6522 and the 6551 have two ce lines, of which
+ one must be logic 1 and the other logic 0. In the table below,
+ columns ce and #ce indicate which lines should be connected to ce
+ and #ce of the I/O device given in the row. The third column ensure
+ that all selections are distinct. Column four and five assign
+ the I/O devices to input addresses.
+
+ ce #ce i3 i4
+ acia0 : o2 & !o4 & !o5 0 0
+ via0 : o4 & !o2 & o5 0 1
+ acia1 : o5 & !o4 & !o2 1 0
+ via1 : o4 & !o5 & o2 1 1
+
+ We place the I/O devices right below the ROM,
+ i.e. i0 i1 i2 == 0b110, resulting in the
+ following address mapping:
+
+ acia0 : 0b11000........... = 0xc000 .. 0xc7ff
+ via0 : 0b11001........... = 0xc800 .. 0xcfff
+ acia1 : 0b11010........... = 0xd000 .. 0xd7ff
+ via1 : 0b11011........... = 0xd800 .. 0xdfff
-/* TBA (1k)
- Address range: 0xd400 - 0xd7ff
- Bit pattern: 0b110101..........
*/
-o5 = (!i0 # !i1 # i2 # !i3 # i4 # !i5);
+o2 = ((!i3 & !i4) # (i3 & i4)) & i0 & i1 & !i2;
+o4 = ((!i3 & i4) # (i3 & i4)) & i0 & i1 & !i2;
+o5 = ((!i3 & i4) # (i3 & !i4)) & i0 & i1 & !i2;
/* Inverter
This is not part of the bus logic.
@@ -71,19 +84,3 @@ o5 = (!i0 # !i1 # i2 # !i3 # i4 # !i5);
*/
o7 = !reset_in;
-
-/*
-oe# we#, and ce# for the memory chips must be
-qualified by phi - No memory access
-in the first part of the cycle, while phi
-is low.
-*/
-
-/* ram_oe# */
-o1 = !phi # !rwb;
-
-/* ram_ce# */
-o3 = !phi # i0;
-
-/* ram_we# */
-o6 = !phi # rwb;
diff --git a/misc/write_default_files.sh b/misc/write_default_files.sh
@@ -1,7 +1,17 @@
-#!/bin/sh
+#!/bin/bash
GFS_CMD="sudo ../tools/gfs.py"
SW=../sw
+for i in 10print ansi_test serial_line_echo stack_test ttt via_test
+do
+ pushd ../sw/$i
+ make clean all
+ popd
+done
+pushd ../sw/ttt
+make test
+popd
+
${GFS_CMD} format
${GFS_CMD} store 0 "10print" ${SW}/10print/10print.bin
${GFS_CMD} store 1 "Tic Tac Toe" ${SW}/ttt/ttt.bin
diff --git a/roms/Makefile.common b/roms/Makefile.common
@@ -1,12 +1,29 @@
-CFLAGS=-C --line-numbers --tab-size=1 -Wall -c -b --labels-root=export
+CFLAGS=-C --line-numbers --tab-size=1 -Wall -c -b
+
+LABELS=--labels-root=export -l $(TARGET).l \
+ --labels-root=io -l io.l \
+ --labels-root=ds -l ds.l \
+ --labels-root=sd -l sd.l \
+ --labels-root=lfsr -l lfsr.l \
+ --labels-root=spi -l spi.l \
+ --labels-root=term -l term.l
+
+LABELS_SYMON=--labels-root=export -l $(TARGET)_symon.l \
+ --labels-root=io -l io_symon.l \
+ --labels-root=ds -l ds_symon.l \
+ --labels-root=sd -l sd_symon.l \
+ --labels-root=lfsr -l lfsr_symon.l \
+ --labels-root=spi -l spi_symon.l \
+ --labels-root=term -l term_symon.l
+
all: $(TARGET).bin $(TARGET)_symon.bin
%.bin: %.asm
- 64tass $(CFLAGS) -DSYMON=false -l $(TARGET).l -L $(TARGET).lst "$<" -o "$@"
+ 64tass $(CFLAGS) -DSYMON=false $(LABELS) -L $(TARGET).lst "$<" -o "$@"
%_symon.bin: %.asm
- 64tass $(CFLAGS) -DSYMON=true -l $(TARGET)_symon.l -L $(TARGET)_symon.lst "$<" -o "$@"
+ 64tass $(CFLAGS) -DSYMON=true $(LABELS_SYMON) -L $(TARGET)_symon.lst "$<" -o "$@"
flash: $(TARGET).bin
sudo ~/opt/minipro-0.3/minipro -p AT28C64B -w $<
diff --git a/roms/boot/ansi.asm b/roms/boot/ansi.asm
@@ -1,281 +0,0 @@
-;;;
-;;; Special commands for ANSI terminals
-;;;
-
-.namespace export
-;;; ANSI text attributes
-plain = 0
-bold = 1
-blink = 5
-reverse = 7
-
-;;; ANSI colors
-black = 0
-red = 1
-green = 2
-yellow = 3
-blue = 4
-magenta = 5
-cyan = 6
-white = 7
-bright_black = 8
-bright_red = 9
-bright_green = 10
-bright_yellow = 11
-bright_blue = 12
-bright_magenta = 13
-bright_cyan = 14
-bright_white = 15
-.endn
-
-;;; get_screen_size
-;;; Returns screen size in X, A.
-;;; If not supported by terminal, C is set
-;;; Input:
-;;; -
-;;; Output:
-;;; X: Screen width
-;;; A: Screen height
-;;; Changes:
-;;; a, x, y, c
-.namespace export
-get_screen_size:
-.endn
- .block
- jsr export.create_stack_frame
- PUSH $02
- cursor_save_x = 0 ; Local variable
- cursor_save_y = 1 ; Local variable
- ;; Local variables 0 & 1: Saved cursor position
- jsr export.get_cursor ; Save cursor position
- bcs terminal_does_not_answer
- sta_LOCAL cursor_save_y
- txa
- sta_LOCAL cursor_save_x
- #SET_CURSOR #$FF, #$FF ; Try to move cursor to max. position
- jsr export.get_cursor ; Get cursor position (= screen size)
- pha ; Save it temporary
- txa ; on the
- pha ; hardware stack.
- lda_LOCAL cursor_save_x ; Restore
- tax ; old
- lda_LOCAL cursor_save_y ; cursor
- jsr export.set_cursor ; position
- jsr export.delete_stack_frame
- pla
- tax
- pla
- rts
-terminal_does_not_answer:
- jsr export.delete_stack_frame
- ldx #80
- lda #25
- rts
- .bend
-
-.namespace export
-clear_screen:
-.endn
- PRINTS x"1b" .. "[2J"
- rts
-
-.namespace export
-set_color:
-.endn
- pha
- PRINTS x"1b" .. "[38;5;"
- pla
- jsr export.putd
- lda #"m"
- jmp export.putc
-
-.namespace export
-set_background_color:
-.endn
- pha
- PRINTS x"1b" .. "[48;5;"
- pla
- jsr export.putd
- lda #"m"
- jmp export.putc
-
-.namespace export
-set_text:
-.endn
- tax
- lda #"m"
- jmp send_CSI
-
-.namespace export
-cursor_up:
-.endn
- tax
- lda #"A"
- jmp send_CSI
-
-.namespace export
-cursor_down:
-.endn
- tax
- lda #"B"
- jmp send_CSI
-
-.namespace export
-cursor_forward:
-.endn
- tax
- lda #"C"
- jmp send_CSI
-
-.namespace export
-cursor_back:
-.endn
- tax
- lda #"D"
- jmp send_CSI
-
-.namespace export
-scroll_up:
-.endn
- tax
- lda #"S"
- jmp send_CSI
-
-.namespace export
-scroll_down:
-.endn
- tax
- lda #"T"
- jmp send_CSI
-
-;;; Send ANSI escape sequence to terminal.
-;;; A contains command, X value
-send_CSI:
- pha
- phx
- lda #$1b
- jsr export.putc
- lda #"["
- jsr export.putc
- pla
- jsr export.putd
- pla
- jmp export.putc
-
-;;; set_cursor
-;;; Sets cursor to position x, a.
-;;; Position starts at 1, not 0!
-;;; Input:
-;;; x: x position
-;;; a: y position
-;;; Output:
-;;; -
-;;; Changes:
-;;; a, x, y, c
-;;; Set Cursor; x position in X, y position in A
-.namespace export
-set_cursor:
-.endn
- phx
- pha
- lda #$1b
- jsr export.putc
- lda #"["
- jsr export.putc
- pla
- jsr export.putd
- lda #";"
- jsr export.putc
- pla
- jsr export.putd
- lda #"H"
- jmp export.putc
-
-;;; get_cursor
-;;; Store cursor position in x, a.
-;;; Position starts at 1, not 0!
-;;; Input:
-;;; -
-;;; Output:
-;;; x: x position
-;;; a: y position
-;;; Changes:
-;;; a, x, y, c
-.namespace export
-get_cursor:
-.endn
- .block
- jsr export.create_stack_frame
- PUSH $08 ; Position as string
- ;; We store the position string as local variables.
- ;; By initializing the local variables with #$00,
- ;; the strings terminate automatically when no
- ;; more digits are written.
- lda #$00
- .for i = 0, i < 8, i += 1
- sta_LOCAL i
- .next
- ;; Request cursor position
- PRINTS x"1b" .. "[6n"
- ;; Read answer
- ldx #$08 ; Number of tries
- ldy #$ff ; to get an answer.
-wait_for_answer:
- phx
- phy
- jsr export.getc_nonblocking ; $1b
- ply
- plx
- bcc terminal_answers
- dey
- cpy #$00
- bne wait_for_answer
- dex
- cpx #$00
- bne wait_for_answer
- ;; Terminal does not answer.
- jsr export.delete_stack_frame
- lda #$00
- ldx #$00
- sec
- rts
-terminal_answers:
- jsr export.getc ; "["
- jsr export.getc ; First digit y
- sta_LOCAL 0
- jsr export.getc ; Second digit y
- cmp #";"
- beq got_y_position
- sta_LOCAL 1
- jsr export.getc ; Third digit y
- cmp #";"
- beq got_y_position
- sta_LOCAL 2
-got_y_position:
- jsr export.getc ; First digit x
- sta_LOCAL 4
- jsr export.getc ; Second digit x
- cmp #"R"
- beq got_x_position
- sta_LOCAL 5
- jsr export.getc ; Third digit x
- cmp #"R"
- beq got_x_position
- sta_LOCAL 6
-got_x_position:
- ;; x position is in local variable(s) 4...
- ;; y position is in local variable(s) 0...
- ;; Convert them to ints
- CALL export.str2byte, [0, 1, 2, 3], lda_LOCAL
- lda_PARAM 0
- pha
- CALL export.str2byte, [4, 5, 6, 7], lda_LOCAL
- lda_PARAM 0
- pha
- jsr export.delete_stack_frame
- plx
- pla
- clc
- rts
- .bend
-
diff --git a/roms/boot/ansi.inc b/roms/boot/ansi.inc
@@ -1,59 +0,0 @@
-;;; -*- asm -*-
-
-;;; -----------------------------------
-;;;
-;;; ANSI Terminal
-;;;
-;;; -----------------------------------
-
-SET_COLOR .macro color
- lda #color
- jsr set_color
- .endm
-
-SET_BACKGROUND_COLOR .macro color
- lda #color
- jsr set_background_color
- .endm
-
-SET_TEXT .macro attribute
- lda #\attribute
- jsr set_text
- .endm
-
-CURSOR_UP .macro steps
- lda #\steps
- jsr cursor_up
- .endm
-
-CURSOR_DOWN .macro steps
- lda #\steps
- jsr cursor_down
- .endm
-
-CURSOR_FORWARD .macro steps
- lda #\steps
- jsr cursor_forward
- .endm
-
-CURSOR_BACK .macro steps
- lda #\steps
- jsr cursor_back
- .endm
-
-SCROLL_UP .macro steps
- lda #\steps
- jsr scroll_up
- .endm
-
-SCROLL_DOWN .macro steps
- lda #\steps
- jsr scroll_DOWN
- .endm
-
-SET_CURSOR .macro x, y
- lda \y
- ldx \x
- jsr export.set_cursor
- .endm
-
diff --git a/roms/boot/boot.asm b/roms/boot/boot.asm
@@ -1,4 +1,3 @@
-
DEBUG = false
;; DEBUG = true
@@ -19,31 +18,7 @@
.dsection rom
.cerror * > $ffff, "ROM exhausted"
-export .namespace
-.section zero_page
- ;; LFSR
-lfsr_state: .word ?
- ;; Stack
-ds_pointer: .word ?
-ds_frame: .word ?
- ;; Temporary zero page variables;
- ;; only used in subroutine
-puts_str: .word ?
-gets_len: .byte ?
-gets_str: .word ?
- ;; Used by VIA for (de-)serialization
-via_buffer: .byte ?
-sd_data: .word ?
- ;; sd_type does not need to be on the zero page.
- ;; We may want to move it to $200-$2ff.
-sd_type: .byte ? ; $05 = SD; $c1 = SDHC
- ;; Everything beyond these reserved variables available to
- ;; programs in RAM.
-rom_zero_page_end:
-.send zero_page
-.endn
-
-.namespace export
+export .namespace
ram_end = $7fff
.endn
@@ -67,13 +42,13 @@ irq_vector = export.ram_end - $1
boot: .block
sei
- #STORE_WORD export.default_irq_handler, export.irq_vector
- #STORE_WORD export.default_nmi_handler, export.nmi_vector
+ #mem.STORE_WORD export.default_irq_handler, export.irq_vector
+ #mem.STORE_WORD export.default_nmi_handler, export.nmi_vector
cld
cli
- jsr export.init_acia
- INIT_STACK export.ram_end-$206+$1 ;Minimal stack size to access SD card
- jsr export.init_via
+ jsr io.init_acia
+ #ds.INIT_STACK export.ram_end-$206+$1 ;Minimal stack size to access SD card
+ jsr spi.init_via
jsr check_for_program_download
bcs no_program_download
jmp download_program
@@ -88,18 +63,18 @@ no_program_download:
;;; The value of the byte is the number of $100 byte
;;; blocks to receive.
check_for_program_download: .block
- #PRINTSNL "READY!"
+ #io.PRINTSNL "READY!"
ldy #$20 ; Outer loop counter
ldx #$00 ; Inner counter
loop:
;; Try to get number of 0x100 byte blocks to be read
- jsr export.getc_nonblocking
+ jsr io.getc_nonblocking
bcc got_byte
dex
bne loop
dey
bne loop
- #PRINTSNL "Nothing to download."
+ #io.PRINTSNL "Nothing to download."
sec
got_byte:
rts
@@ -133,7 +108,7 @@ download_program: .block
sta add_checksum
sta xor_checksum
transmit_block:
- jsr export.getc
+ jsr io.getc
;; Store data
ldy #$00
sta (addr_pointer), y
@@ -159,21 +134,27 @@ transmit_block:
;; Transmission completed.
;; Transmit result of checksum calculation
lda add_checksum
- jsr export.putc
+ jsr io.putc
lda xor_checksum
- jsr export.putc
+ jsr io.putc
;; Start program
jmp $0200
.bend
.include "io.asm"
-.include "stack.asm"
+.include "ds.asm"
.include "lfsr.asm"
.include "spi.asm"
-.include "sd_card.asm"
-.include "ansi.asm"
+.include "sd.asm"
+.include "term.asm"
+.namespace export
+.section zero_page
+rom_zero_page_end:
+.send zero_page
+.endn
+
;;; Default IRQ handler. Unless the user program changes
;;; the irq_vector, IRQs are handled here.
.namespace export
diff --git a/roms/boot/boot.inc b/roms/boot/boot.inc
@@ -12,33 +12,48 @@
CLOCK_SPEED = 0
.endweak
.if CLOCK_SPEED == 0
+ .if SYMON
+ filename_addition = "_symon"
+ start_address = $0300
+ .else
+ filename_addition = ""
+ start_address = $0200
+ .endif
export .namespace
- puts = puts
- puth = puth
- puts_str = puts_str
- gets_str = gets_str
- gets_len = gets_len
- gets = gets
- putc = putc
- putd = putd
- create_stack_frame = create_stack_frame
- delete_stack_frame = delete_stack_frame
- push_a = push_a
- pull_a = pull_a
- ds_pointer = ds_pointer
- ds_frame = ds_frame
- ram_end = ram_end
- set_cursor = set_cursor
+ .include "boot" .. filename_addition .. ".l"
+ .endn
+ io .namespace
+ .include "io" .. filename_addition .. ".l"
+ .endn
+ ds .namespace
+ .include "ds" .. filename_addition .. ".l"
+ .endn
+ sd .namespace
+ .include "sd" .. filename_addition .. ".l"
+ .endn
+ lfsr .namespace
+ .include "lfsr" .. filename_addition .. ".l"
+ .endn
+ spi .namespace
+ .include "spi" .. filename_addition .. ".l"
+ .endn
+ term .namespace
+ .include "term" .. filename_addition .. ".l"
.endn
BOOT_EMBEDDED = false
+ ;; Set start addresses for program and
+ ;; zero page variables
+ * = export.rom_zero_page_end
+ .dsection zero_page
+ * = start_address
.else
BOOT_EMBEDDED = true
.endif
-
+
.include "io.inc"
-.include "stack.inc"
-.include "sd_card.inc"
-.include "ansi.inc"
+.include "ds.inc"
+.include "sd.inc"
+.include "term.inc"
;;; -----------------------------------
;;;
@@ -46,6 +61,8 @@
;;;
;;; -----------------------------------
+mem .namespace
+
SET_BITS .macro
lda \1
ora \2
@@ -115,3 +132,5 @@ ADD_WORD: .macro
adc #>\2
sta \1+1
.endm
+
+.endn
diff --git a/roms/boot/ds.asm b/roms/boot/ds.asm
@@ -0,0 +1,76 @@
+;;; ----------------------------------------------------------
+;;;
+;;; STACK
+;;;
+;;; ----------------------------------------------------------
+
+;;; Software implementation of data stack. In difference to typical
+;;; stack implementations, this stack grows from bottom to top, because
+;;; we want to access eleements using indirected indexed access with
+;;; the stack frame pointer as base. Therefore the stack should
+;;; be initialized with the first unoccupied RAM address after the
+;;; program code.
+;;;
+;;; PULL and PUSH do not move actual stack data, they just shift
+;;; the stack pointer.
+;;;
+;;; Local variables on the data stack are supported by macro
+;;; VAR. VAR i refers to the ith byte on the stack. PARAM allows
+;;; to pass variables to a callee. PARAM i of the caller becomes
+;;; VAR i of the callee. The callee should reserve stack space
+;;; for both its parameters and local variables.
+;;;
+;;; Stack frames used for these calls are created/destroyed by
+;;; subroutines create_stack_frame and delete_stack_frame.
+;;;
+;;; CALL is like jsr with parameter passing. There addressing
+;;; modes are supported: immediate, zero-page, and local variables.
+;;; For immediate and zero page, the third parameter must be lda.
+;;; For local variables, the third parameter must be lda_LOCAL.
+;;; See sw/stack_test/stack_test.asm for examles.
+
+ds .namespace
+
+.section zero_page
+ ;; Stack
+ptr: .word ?
+frame_ptr: .word ?
+.send zero_page
+
+.section rom
+
+create_stack_frame:
+ .block
+ ;; Store old frame pointer on stack.
+ ;; Since our stack grows bottom to top, we write
+ ;; the data before increasing the stack pointer
+ #mem.COPY_WORD_ABSOLUTE_INDIRECT ds.frame_ptr, (ds.ptr)
+ #ds.PUSH $02 ; Store old frame pointer
+ #mem.COPY_WORD_ABSOLUTE_INDIRECT ds.ptr, ds.frame_ptr ; Set new frame pointer
+ rts
+ .bend
+
+delete_stack_frame:
+ .block
+ #mem.COPY_WORD_ABSOLUTE_INDIRECT ds.frame_ptr, ds.ptr ; Reset stack pointer to begin of frame.
+ #ds.PULL $02 ; Move stack pointer to frame reference
+ #mem.COPY_WORD_ABSOLUTE_INDIRECT (ds.ptr), ds.frame_ptr ; Restore old frame pointer.
+ rts
+ .bend
+
+push_a:
+ .block
+ sta (ds.ptr)
+ #ds.PUSH $01
+ rts
+ .bend
+
+pull_a:
+ .block
+ #ds.PULL $01
+ lda (ds.ptr)
+ rts
+ .bend
+
+.send rom
+.endn
diff --git a/roms/boot/ds.inc b/roms/boot/ds.inc
@@ -0,0 +1,79 @@
+;;; -*- asm -*-
+
+;;; Macros for accessing the data stack
+;;; and managing local variables and
+;;; call parameters. Check ds.asm for
+;;; documentation.
+
+.namespace ds
+
+INIT_STACK: .macro
+ #mem.STORE_WORD \1, ds.ptr
+ .endm
+
+PUSH: .macro ; Reserve bytes on stack (no actual push operation)
+ #mem.ADD_WORD ds.ptr, \1
+ .endm
+
+PULL: .macro ; Remove bytes from stack (no return value)
+ #mem.SUB_WORD ds.ptr, \1
+ .endm
+
+PUSH_WORD: .macro ; Push a word on the stack
+ lda #<\1
+ sta (ds.ptr)
+ lda #>\1
+ ldy #$01
+ sta (ds.ptr),y
+ #ds.PUSH $02
+ .endm
+
+LOCAL: .macro
+ ldy #\1
+ \2 (ds.frame_ptr),y
+ .endm
+lda_LOCAL: .macro
+ #ds.LOCAL \1, lda
+ .endm
+sta_LOCAL: .macro
+ #ds.LOCAL \1, sta
+ .endm
+adc_LOCAL: .macro
+ #ds.LOCAL \1, adc
+ .endm
+PARAM: .macro
+ ldy #\1
+ \2 (ds.ptr),y
+ .endm
+sta_PARAM: .macro
+ #ds.PARAM \1+2, sta
+ .endm
+lda_PARAM: .macro
+ #ds.PARAM \1+2, lda
+ .endm
+
+CALL: .macro subroutine, param=[], param_lda=""
+ .block
+ .if len(\param) != 0
+ .for CALL_param := 0, CALL_param < len(\param), CALL_param += $1
+ \param_lda \param[CALL_param]
+ #ds.sta_PARAM CALL_param
+ .next
+ .endif
+ jsr \subroutine
+ .bend
+ .endm
+
+;; Push sequence of bytes to stack. Parameters: From, Length
+PUSH_RANGE: .macro
+ ldy #$00
+loop_PUSH_RANGE:
+ lda \1,y
+ sta (ds_pointer),y
+ iny
+ cpy \2
+ bne loop_PUSH_RANGE
+ #PUSH \2
+ .endm
+
+.endn
diff --git a/roms/boot/io.asm b/roms/boot/io.asm
@@ -1,45 +1,18 @@
;;; Serial IO and string manipulation
-
-.namespace export
+
+io .namespace
+
.if SYMON
- acia_base = $8800 ; Symon
+ acia_base = $8800
+ via_start = $8000
.else
- acia_base = $dc00
+ acia_base = $c000
+ via_start = $c800
.endif
acia_data_reg = acia_base
acia_status_reg = acia_base + $1
acia_cmd_reg = acia_base + $2
acia_ctrl_reg = acia_base + $3
-.endn
-
-;;; init_acia
-;;; Initialize acai for communication
-;;; Input:
-;;; -
-;;; Output:
-;;; -
-;;; Changes:
-;;; a, acai registers
-.namespace export
-init_acia:
-.endn
- .block
- ;; Reset acai
- sta export.acia_status_reg
- lda #%00011111 ; 19200 bps, 8 data bits, 1 stop bit
- sta export.acia_ctrl_reg
- ;; No parity, no echo, no interrupts, DTR ready
- lda #%11001011
- sta export.acia_cmd_reg
- rts
- .bend
-
-.namespace export
-.if SYMON
- via_start = $8000
-.else
- via_start = $d800
-.endif
via_irb = via_start
via_orb = via_start
via_ira = via_start+$1
@@ -59,7 +32,37 @@ init_acia:
via_ier = via_start+$14
via_ira2 = via_start+$15
via_ora2 = via_start+$15
-.endn
+
+
+.section zero_page
+ ;; Temporary zero page variables;
+ ;; only used in subroutine
+puts_str: .word ?
+gets_len: .byte ?
+gets_str: .word ?
+.send zero_page
+
+.section rom
+
+;;; init_acia
+;;; Initialize acai for communication
+;;; Input:
+;;; -
+;;; Output:
+;;; -
+;;; Changes:
+;;; a, acai registers
+init_acia:
+ .block
+ ;; Reset acai
+ sta io.acia_status_reg
+ lda #%00011111 ; 19200 bps, 8 data bits, 1 stop bit
+ sta io.acia_ctrl_reg
+ ;; No parity, no echo, no interrupts, DTR ready
+ lda #%11001011
+ sta io.acia_cmd_reg
+ rts
+ .bend
;;; ----------------------------------------------------------
;;; STANDARD LIBRARY FUNCTIONS
@@ -79,17 +82,15 @@ init_acia:
;;; -
;;; Changes:
;;; a, x, y, puts_str, put_str+1
-.namespace export
puts:
-.endn
.block
;; Send string terminated by '\0'
ldy #$00
_puts_loop:
- lda (export.puts_str),y
+ lda (io.puts_str),y
beq _puts_end
phy
- jsr export.putc
+ jsr io.putc
ply
iny
jmp _puts_loop
@@ -106,15 +107,13 @@ _puts_end:
;;; -
;;; Changes:
;;; x, acai registers
-.namespace export
putc:
-.endn
.block
;; Send character.
;; Due to bugs in the register and interrupt
;; handling of the WDC 65C02, we have to use
;; a manual delay.
- sta export.acia_data_reg
+ sta io.acia_data_reg
.switch CLOCK_SPEED
.case 4 ; 4 Mhz Clock
SERIAL_SEND_DELAY_X = $c3
@@ -146,9 +145,7 @@ inner_loop:
;;; -
;;; Changes:
;;; a, x, acai registers, c-flag
-.namespace export
puth:
-.endn
.block
;; Send byte a as hex number
pha
@@ -156,9 +153,9 @@ puth:
lsr a
lsr a
lsr a
- jsr export.puth_nibble
+ jsr io.puth_nibble
pla
- jsr export.puth_nibble
+ jsr io.puth_nibble
rts
.bend
@@ -171,9 +168,7 @@ puth:
;;; -
;;; Changes:
;;; a, x, acai registers, c-flag
-.namespace export
puth_nibble:
-.endn
.block
;; Print hex digit
clc
@@ -183,7 +178,7 @@ puth_nibble:
bmi _puth_putc
adc #$26
_puth_putc:
- jsr export.putc
+ jsr io.putc
rts
.bend
@@ -196,9 +191,7 @@ _puth_putc:
;;; -
;;; Changes:
;;; a, x, y, acai registers, c-flag
-.namespace export
putd:
-.endn
.block
ldy #$00
first_digit:
@@ -213,7 +206,7 @@ first_digit_set:
pha
tya
beq skip_first_leading_zero
- jsr export.puth_nibble
+ jsr io.puth_nibble
ldx #$01 ; Force printing of zeros in rest of term
skip_first_leading_zero:
pla
@@ -232,10 +225,10 @@ second_digit_set:
cmp #$00
beq skip_second_leading_zero
do_not_skip_potential_second_leading_zero:
- jsr export.puth_nibble
+ jsr io.puth_nibble
skip_second_leading_zero:
pla
- jmp export.puth_nibble
+ jmp io.puth_nibble
.bend
@@ -247,14 +240,12 @@ skip_second_leading_zero:
;;; -
;;; Changes:
;;; a
-.namespace export
putnl:
-.endn
.block
lda #$0d
- jsr export.putc
+ jsr io.putc
lda #$0a
- jsr export.putc
+ jsr io.putc
rts
.bend
@@ -267,15 +258,13 @@ putnl:
;;; Character read
;;; Changes:
;;; a, acai registers
-.namespace export
getc:
-.endn
.block
;; Read character from acia
- lda export.acia_status_reg
+ lda io.acia_status_reg
and #%00001000
- beq export.getc
- lda export.acia_data_reg
+ beq io.getc
+ lda io.acia_data_reg
rts
.bend
@@ -291,24 +280,20 @@ getc:
;;; Character read
;;; Changes:
;;; a, acai registers, lsfr_state
-.namespace export
getc_seed_rng:
-.endn
.block
;; Read character from acia
;; We also use the time between keystrokes
;; as entropy source for the RNG
- jsr export.lfsr_step
- lda export.acia_status_reg
+ jsr lfsr.step
+ lda io.acia_status_reg
and #%00001000
- beq export.getc_seed_rng
- lda export.acia_data_reg
+ beq io.getc_seed_rng
+ lda io.acia_data_reg
rts
.bend
-.namespace export
getc_nonblocking:
-.endn
.block
;; Non-blocking read: If
;; character has been read,
@@ -316,11 +301,11 @@ getc_nonblocking:
;; C is cleared. If not,
;; C is set
sec
- lda export.acia_status_reg
+ lda io.acia_status_reg
and #%00001000
beq nothing_read
clc
- lda export.acia_data_reg
+ lda io.acia_data_reg
nothing_read:
rts
.bend
@@ -341,26 +326,24 @@ nothing_read:
;;; Zero terminated string at gets_str, gets_str+1
;;; Changes:
;;; a, y, ACAI registers
-.namespace export
gets:
-.endn
.block
;; Read string terminated by CR
ldy #$00
loop:
phy
- jsr export.getc
- jsr export.putc
+ jsr io.getc
+ jsr io.putc
ply
cmp #$0d ; GOT CR?
beq terminate_string ; if not
- sta (export.gets_str), y ; store character
+ sta (io.gets_str), y ; store character
iny ; if max length
- cpy export.gets_len ; not reached,
+ cpy io.gets_len ; not reached,
bne loop ; continue loop.
terminate_string:
lda #$00
- sta (export.gets_str), y
+ sta (io.gets_str), y
rts
.bend
@@ -374,32 +357,30 @@ terminate_string:
;;; Byte value
;;; Changes:
;;; a, x, y
-.namespace export
str2byte:
-.endn
.block
- jsr export.create_stack_frame
- PUSH $04 ; Local variable (string of length four)
+ jsr ds.create_stack_frame
+ #ds.PUSH $04 ; Local variable (string of length four)
lda #$00
pha
ldy #$00
add_digit:
- lda (export.ds_frame),y
+ lda (ds.frame_ptr),y
beq done
sec ; Convert next digit
sbc #'0' ; from ascii to
- sta (export.ds_frame),y ; number.
+ sta (ds.frame_ptr),y ; number.
pla ; Multiply current
- jsr export.multiply_by_ten ; accumulator by 10.
+ jsr io.multiply_by_ten ; accumulator by 10.
clc ; Add new
- adc (export.ds_frame),y ; digit.
+ adc (ds.frame_ptr),y ; digit.
pha
iny ; Advance to next digit
jmp add_digit
done:
pla
- sta_LOCAL 0
- jsr export.delete_stack_frame
+ #ds.sta_LOCAL 0
+ jsr ds.delete_stack_frame
.bend
;;; multiply_by_ten
@@ -410,15 +391,16 @@ done:
;;; a: Number * 10
;;; Changes:
;;; a, c
-.namespace export
multiply_by_ten:
-.endn
.block
- sta (export.ds_pointer)
+ sta (ds.ptr)
lda #$00
clc
.for i = 0, i < 10, i += 1
- adc (export.ds_pointer)
+ adc (ds.ptr)
.next
rts
.bend
+
+.send rom
+.endn
diff --git a/roms/boot/io.inc b/roms/boot/io.inc
@@ -1,5 +1,7 @@
;;; -*- asm -*-
+.namespace io
+
;;; PRINT(addr)
;;; Send zero terminated string at addr via acia.
;;; Input:
@@ -12,10 +14,10 @@
PRINT .macro
lda #<\1
- sta export.puts_str
+ sta io.puts_str
lda #>\1
- sta export.puts_str+1
- jsr export.puts
+ sta io.puts_str+1
+ jsr io.puts
.endm
;;; PRINTS(string) (<= 255 characters)
@@ -29,7 +31,7 @@ PRINT .macro
;;; a, x, y, puts_str, put_str+1
PRINTS .macro
- PRINT(saddr)
+ #io.PRINT saddr
jmp cont_PRINTS
saddr:
.null \1
@@ -47,7 +49,7 @@ cont_PRINTS:
;;; a, x, y, puts_str, put_str+1
PRINTSNL .macro
- PRINT(saddr)
+ #io.PRINT saddr
jmp cont_PRINTSNL
saddr:
.null \1, $0d, $0a
@@ -74,12 +76,12 @@ cont_PRINTSNL:
INPUTS .macro
lda #<\1
- sta export.gets_str
+ sta io.gets_str
lda #>\1
- sta export.gets_str+1
+ sta io.gets_str+1
lda \2
- sta export.gets_len
- jsr export.gets
+ sta io.gets_len
+ jsr io.gets
.endm
;;; PRINTNL
@@ -93,8 +95,9 @@ INPUTS .macro
PRINTNL .macro
lda #$0d
- jsr export.putc
+ jsr io.putc
lda #$0a
- jsr export.putc
+ jsr io.putc
.endm
+.endn
diff --git a/roms/boot/lfsr.asm b/roms/boot/lfsr.asm
@@ -4,7 +4,7 @@
;;; bit from the state yields random numbers with reasonable
;;; statistical properties.
-;;; lfsr_init
+;;; init
;;; Initialize lfsr
;;; Input:
;;; -
@@ -12,14 +12,21 @@
;;; -
;;; Changes:
;;; lfsr
-.namespace export
-lfsr_init:
-.endn
+lfsr .namespace
+
+.section zero_page
+ ;; LFSR
+state: .word ?
+.send zero_page
+
+.section rom
+
+init:
.block
- #STORE_WORD $beef, export.lfsr_state
+ #mem.STORE_WORD $beef, lfsr.state
.bend
-;;; lfsr_step
+;;; step
;;; update lfsr
;;; Input:
;;; -
@@ -27,20 +34,18 @@ lfsr_init:
;;; -
;;; Changes:
;;; lfsr
-.namespace export
-lfsr_step:
-.endn
+step:
.block
- asl export.lfsr_state
- lda export.lfsr_state+1
+ asl lfsr.state
+ lda lfsr.state+1
rol a
bcc cont
eor #$0b
cont:
- sta export.lfsr_state+1
- lda export.lfsr_state
+ sta lfsr.state+1
+ lda lfsr.state
adc #$00
- sta export.lfsr_state
+ sta lfsr.state
rts
.bend
@@ -48,14 +53,16 @@ cont:
;;; Test function for LFSR
test_lfsr: .block
loop:
- jsr export.lfsr_step
- lda export.lfsr_state+1
+ jsr lfsr.step
+ lda lfsr.state+1
jsr puth
- lda export.lfsr_state
- jsr export.puth
+ lda lfsr.state
+ jsr io.puth
PRINTSNL("")
- jsr export.getc
+ jsr io.getc
jmp loop
.bend
.endif ; false
+.send rom
+.endn
diff --git a/roms/boot/sd.asm b/roms/boot/sd.asm
@@ -0,0 +1,269 @@
+;; -----------------------------------
+;;;
+;;; SD card communication interface
+;;;
+;;; -----------------------------------
+
+
+sd .namespace
+
+.section zero_page
+data: .word ?
+ ;; type does not need to be on the zero page.
+type: .byte ? ; $05 = SD; $c1 = SDHC
+ ;; Everything beyond these reserved variables available to
+ ;; programs in RAM.
+.send zero_page
+
+.section rom
+
+send_cmd:
+ .block
+ ldy #$00
+cmd_bytes_loop:
+ lda (sd.data),y
+ jsr spi.set
+ iny
+ cpy #$06
+ bne cmd_bytes_loop
+ lda #$ff ; Finalize transmission
+ jsr spi.set ; with dummy byte
+ rts
+ .bend
+
+
+print_block:
+ .block
+ ldx #$02
+ ldy #$00
+loop:
+ phx
+ phy
+ lda (sd.data),y
+ jsr io.puth
+ #io.PRINTS " "
+ ply
+ plx
+ iny
+ bne loop
+ #mem.ADD_WORD sd.data, $0100
+ dex
+ bne loop
+ #io.PRINTNL
+ #mem.SUB_WORD sd.data, $0200
+ rts
+ .bend
+
+read_block:
+ ;; Read a block of data
+ ;; Block number is passed via stack.
+ .block
+ jsr ds.create_stack_frame
+ #ds.PUSH $04 ; Local variable (32 bit block number)
+.if DEBUG
+ io.PRINTSNL "Sending CMD17"
+.endif
+ lda #$51 ; CMD17 (READ_SINGLE_BLOCK)
+ jsr spi.set
+ jsr send_block_number
+ lda #$01 ; Dummy CRC
+ jsr spi.set
+ jsr spi.get
+ cmp #$00
+ beq wait_for_start_token
+ jmp read_failed
+wait_for_start_token:
+ jsr spi.get_nonblocking
+ cmp #$ff
+ beq wait_for_start_token
+ cmp #$fe
+ bne read_failed
+ ldx #$02
+ ldy #$00
+loop:
+ phx
+ phy
+ jsr spi.get_nonblocking
+ ply
+ plx
+ sta (sd.data),y
+ iny
+ bne loop
+ #mem.ADD_WORD sd.data, $0100 ; Second half of block
+ dex
+ bne loop
+ #mem.SUB_WORD sd.data, $0200 ; Restore pointer
+ clc
+ #sd.RECEIVE $2 ; Get CRC
+ jsr ds.delete_stack_frame
+ rts
+read_failed:
+ #io.PRINTSNL "Error reading SD card!"
+ sec
+ jsr ds.delete_stack_frame
+ rts
+ .bend
+
+send_block_number:
+ .block
+ lda sd.type ; Old cards expect the position
+ cmp #$05 ; as bytes, not blocks
+ beq old_card
+ #ds.lda_LOCAL 0 ; Block number
+ jsr spi.set
+ #ds.lda_LOCAL 1
+ jsr spi.set
+ #ds.lda_LOCAL 2
+ jsr spi.set
+ #ds.lda_LOCAL 3
+ jsr spi.set
+ rts
+old_card:
+ #ds.lda_LOCAL 3
+ asl a
+ #ds.sta_LOCAL 3
+ #ds.lda_LOCAL 2
+ rol a
+ #ds.sta_LOCAL 2
+ #ds.lda_LOCAL 1
+ rol a
+ jsr spi.set
+ #ds.lda_LOCAL 2
+ jsr spi.set
+ #ds.lda_LOCAL 3
+ jsr spi.set
+ lda #$00
+ jsr spi.set
+ rts
+ .bend
+
+write_block:
+ ;; Write block at data to card.
+ ;; Block number is passed via stack.
+ .block
+ jsr ds.create_stack_frame
+ #ds.PUSH $04 ; Local variable (32 bit block number)
+.if DEBUG
+ io.PRINTSNL "Sending CMD24"
+.endif
+ lda #$58 ; CMD24 (WRITE_BLOCK)
+ jsr spi.set
+ jsr send_block_number
+ lda #$01 ; Dummy CRC
+ jsr spi.set
+ lda #$ff
+ jsr spi.set ; Dummy byte
+ #sd.RECEIVE $1
+ ;; Send start token
+ lda #$fe
+ jsr spi.set
+ ;; Send data
+ ldx #$02
+ ldy #$00
+write_loop:
+ phx
+ phy
+ lda (sd.data),y
+ jsr spi.set
+ ply
+ plx
+ iny
+ cpy #$00
+ bne write_loop
+ #mem.ADD_WORD sd.data, $0100 ; Second half of block
+ dex
+ cpx #$00
+ bne write_loop
+ #mem.SUB_WORD sd.data, $0200 ; Restore pointer
+ ;; Wait for write operation to complete
+ #sd.RECEIVE $1
+ cmp #$e5
+ bne error_writing
+wait_loop:
+ #sd.RECEIVE $1
+ beq wait_loop
+ jsr ds.delete_stack_frame
+ clc
+ rts
+error_writing:
+ #io.PRINTSNL "Error writing to SD card!"
+ jsr ds.delete_stack_frame
+ sec
+ rts
+ .bend
+
+close:
+ #mem.SET_BITS io.via_ora, #spi.CS
+ rts
+
+open:
+ .block
+.if DEBUG
+ #io.PRINTSNL "Initializing SD Card"
+.endif
+ ;; Configure ports for in- and output
+ #mem.SET_BITS io.via_ddra, #(spi.CS | spi.SCK | spi.MOSI)
+ #mem.CLEAR_BITS io.via_ddra, #spi.MISO
+ ldy #$10 ; Error counter
+ phy
+start_init:
+ ;; Card power on sequence:
+ ;; Keep CS high, toggle clock for at least 74 cycles.
+ #mem.SET_BITS io.via_ora, #(spi.CS | spi.MOSI)
+ ;; Wait for 80 clock pulses
+ ldx #160
+boot_wait_loop:
+ #mem.TOGGLE_BITS io.via_ora, #spi.SCK
+ dex
+ bne boot_wait_loop
+ #mem.CLEAR_BITS io.via_ora, #(spi.CS|spi.MOSI|spi.SCK)
+ #sd.SEND_CMD [$40, $00, $00, $00, $00, $95] ; CMD0
+ #sd.RECEIVE $1
+ cmp #$01 ; Should be $01 (In idle state).
+ beq cont
+ ply
+ dey
+ phy
+ beq failed_init
+ jmp start_init ; If not, start over.
+failed_init:
+ ply
+ #io.PRINTSNL "Error initializing SD card!"
+ sec
+ rts
+cont:
+ ;; Card is in SPI mode
+ ply
+ #sd.SEND_CMD [$48, $00, $00, $01, $aa, $87] ; CMD8
+ #sd.RECEIVE $1
+ #sd.SEND_CMD [$45, $00, $00, $00, $00, $5b] ; CMD5
+ #sd.RECEIVE $1 ; $05 = SD; $c1 = SDHC
+ sta sd.type
+ #sd.SEND_CMD [$7b, $00, $00, $00, $00, $83] ; CMD59
+ #sd.RECEIVE $1 ; should be $01
+ ;; Send ACMD41 until card is initialized
+ ldy #$10 ; Fail counter
+ phy
+wait_for_card_initialized:
+ #sd.SEND_CMD [$77, $00, $00, $00, $00, $65] ; CMD55
+ #sd.RECEIVE $1 ; should be $01
+ #sd.SEND_CMD [$69, $40, $00, $00, $00, $95] ; ACMD41 (v1 & v2 card)
+ #sd.RECEIVE $1 ; $01 if busy, $00 if ready (initialized)
+ cmp #$00
+ beq initialized
+ ply
+ dey
+ phy
+ bne cont2 ; More tries?
+cont2:
+ jmp wait_for_card_initialized
+initialized:
+ ply
+ #sd.SEND_CMD [$50, $00, $00, $02, $00, $15] ; CMD16
+ #sd.RECEIVE $1
+ clc
+ rts
+ .bend
+
+.send rom
+.endn
diff --git a/roms/boot/sd.inc b/roms/boot/sd.inc
@@ -0,0 +1,51 @@
+;;; -*- asm -*-
+
+;;; Macros for accessing SD cards
+
+.namespace sd
+
+SEND_CMD .macro
+.if DEBUG
+ PRINTS "Sending CMD$"
+ lda cmd
+ sec
+ sbc #$40
+ jsr io.puth
+ PRINTNL
+.endif
+ lda #<cmd
+ sta sd.data
+ lda #>cmd
+ sta sd.data+1
+ jsr sd.send_cmd
+ jmp cont_SEND_CMD
+cmd: .byte \1
+cont_SEND_CMD:
+ .endm
+
+
+
+RECEIVE .macro
+ ldx #\1
+loop_RECEIVE:
+ phx
+ jsr spi.get
+.if DEBUG
+ pha
+ jsr io.puth
+ PRINTS " "
+ pla
+.endif
+ plx
+ dex
+ bne loop_RECEIVE
+ pha
+.if DEBUG
+ PRINTNL
+.endif
+ ;; Read non-existing dummy byte for snychronization
+ jsr spi.get_nonblocking
+ pla
+ .endm
+
+.endn
diff --git a/roms/boot/sd_card.asm b/roms/boot/sd_card.asm
@@ -1,266 +0,0 @@
-;;; -----------------------------------
-;;;
-;;; SD card communication interface
-;;;
-;;; -----------------------------------
-
-
-;;; Send command
-.namespace export
-sd_send_cmd:
-.endn
- .block
- ldy #$00
-cmd_bytes_loop:
- lda (export.sd_data),y
- jsr export.spi_set
- iny
- cpy #$06
- bne cmd_bytes_loop
- lda #$ff ; Finalize transmission
- jsr export.spi_set ; with dummy byte
- rts
- .bend
-
-
-.namespace export
-print_block:
-.endn
- .block
- ldx #$02
- ldy #$00
-loop:
- phx
- phy
- lda (export.sd_data),y
- jsr export.puth
- PRINTS " "
- ply
- plx
- iny
- bne loop
- ADD_WORD export.sd_data, $0100
- dex
- bne loop
- PRINTNL
- SUB_WORD export.sd_data, $0200
- rts
- .bend
-
-.namespace export
-sd_read_block:
-.endn
- ;; Read a block of data
- ;; Block number is passed via stack.
- .block
- jsr export.create_stack_frame
- PUSH $04 ; Local variable (32 bit block number)
-.if DEBUG
- PRINTSNL "Sending CMD17"
-.endif
- lda #$51 ; CMD17 (READ_SINGLE_BLOCK)
- jsr export.spi_set
- jsr sd_send_block_number
- lda #$01 ; Dummy CRC
- jsr export.spi_set
- jsr export.spi_get
- cmp #$00
- beq wait_for_start_token
- jmp read_failed
-wait_for_start_token:
- jsr export.spi_get_nonblocking
- cmp #$ff
- beq wait_for_start_token
- cmp #$fe
- bne read_failed
- ldx #$02
- ldy #$00
-loop:
- phx
- phy
- jsr export.spi_get_nonblocking
- ply
- plx
- sta (export.sd_data),y
- iny
- bne loop
- ADD_WORD export.sd_data, $0100 ; Second half of block
- dex
- bne loop
- SUB_WORD export.sd_data, $0200 ; Restore pointer
- clc
- SD_RECEIVE $2 ; Get CRC
- jsr export.delete_stack_frame
- rts
-read_failed:
- PRINTSNL("Error reading SD card!")
- sec
- jsr export.delete_stack_frame
- rts
- .bend
-
-sd_send_block_number:
- .block
- lda export.sd_type ; Old cards expect the position
- cmp #$05 ; as bytes, not blocks
- beq old_card
- lda_LOCAL 0 ; Block number
- jsr export.spi_set
- lda_LOCAL 1
- jsr export.spi_set
- lda_LOCAL 2
- jsr export.spi_set
- lda_LOCAL 3
- jsr export.spi_set
- rts
-old_card:
- lda_LOCAL 3
- asl a
- sta_LOCAL 3
- lda_LOCAL 2
- rol a
- sta_LOCAL 2
- lda_LOCAL 1
- rol a
- jsr export.spi_set
- lda_LOCAL 2
- jsr export.spi_set
- lda_LOCAL 3
- jsr export.spi_set
- lda #$00
- jsr export.spi_set
- rts
- .bend
-
-.namespace export
-sd_write_block:
-.endn
- ;; Write block at sd_data to card.
- ;; Block number is passed via stack.
- .block
- jsr export.create_stack_frame
- PUSH $04 ; Local variable (32 bit block number)
-.if DEBUG
- PRINTSNL "Sending CMD24"
-.endif
- lda #$58 ; CMD24 (WRITE_BLOCK)
- jsr export.spi_set
- jsr sd_send_block_number
- lda #$01 ; Dummy CRC
- jsr export.spi_set
- lda #$ff
- jsr export.spi_set ; Dummy byte
- SD_RECEIVE $1
- ;; Send start token
- lda #$fe
- jsr export.spi_set
- ;; Send data
- ldx #$02
- ldy #$00
-write_loop:
- phx
- phy
- lda (export.sd_data),y
- jsr export.spi_set
- ply
- plx
- iny
- cpy #$00
- bne write_loop
- ADD_WORD export.sd_data, $0100 ; Second half of block
- dex
- cpx #$00
- bne write_loop
- SUB_WORD export.sd_data, $0200 ; Restore pointer
- ;; Wait for write operation to complete
- SD_RECEIVE $1
- cmp #$e5
- bne error_writing
-wait_loop:
- SD_RECEIVE $1
- beq wait_loop
- jsr export.delete_stack_frame
- clc
- rts
-error_writing:
- PRINTSNL("Error writing to SD card!")
- jsr export.delete_stack_frame
- sec
- rts
- .bend
-
-sd_close:
- #SET_BITS export.via_ora, #CS
- rts
-
-.namespace export
-sd_open:
-.endn
- .block
-.if DEBUG
- PRINTSNL "Initializing SD Card"
-.endif
- ;; Configure ports for in- and output
- SET_BITS export.via_ddra, #(CS | SCK | MOSI)
- CLEAR_BITS export.via_ddra, #MISO
- ldy #$10 ; Error counter
- phy
-start_init:
- ;; Card power on sequence:
- ;; Keep CS high, toggle clock for at least 74 cycles.
- SET_BITS export.via_ora, #(CS | MOSI)
- ;; Wait for 80 clock pulses
- ldx #160
-boot_wait_loop:
- TOGGLE_BITS export.via_ora, #SCK
- dex
- bne boot_wait_loop
- CLEAR_BITS export.via_ora, #(CS|MOSI|SCK)
- SD_SEND_CMD [$40, $00, $00, $00, $00, $95] ; CMD0
- SD_RECEIVE $1
- cmp #$01 ; Should be $01 (In idle state).
- beq cont
- ply
- dey
- phy
- beq failed_init
- jmp start_init ; If not, start over.
-failed_init:
- ply
- PRINTSNL("Error initializing SD card!")
- sec
- rts
-cont:
- ;; Card is in SPI mode
- ply
- SD_SEND_CMD [$48, $00, $00, $01, $aa, $87] ; CMD8
- SD_RECEIVE $1
- SD_SEND_CMD [$45, $00, $00, $00, $00, $5b] ; CMD5
- SD_RECEIVE $1 ; $05 = SD; $c1 = SDHC
- sta export.sd_type
- SD_SEND_CMD [$7b, $00, $00, $00, $00, $83] ; CMD59
- SD_RECEIVE $1 ; should be $01
- ;; Send ACMD41 until card is initialized
- ldy #$10 ; Fail counter
- phy
-wait_for_card_initialized:
- SD_SEND_CMD [$77, $00, $00, $00, $00, $65] ; CMD55
- SD_RECEIVE $1 ; should be $01
- SD_SEND_CMD [$69, $40, $00, $00, $00, $95] ; ACMD41 (v1 & v2 card)
- SD_RECEIVE $1 ; $01 if busy, $00 if ready (initialized)
- cmp #$00
- beq initialized
- ply
- dey
- phy
- bne cont2 ; More tries?
-cont2:
- jmp wait_for_card_initialized
-initialized:
- ply
- SD_SEND_CMD [$50, $00, $00, $02, $00, $15] ; CMD16
- SD_RECEIVE $1
- clc
- rts
- .bend
-
diff --git a/roms/boot/sd_card.inc b/roms/boot/sd_card.inc
@@ -1,48 +0,0 @@
-;;; -*- asm -*-
-
-;;; Macros for accessing SD cards
-
-SD_SEND_CMD .macro
-.if DEBUG
- PRINTS "Sending CMD$"
- lda cmd
- sec
- sbc #$40
- jsr export.puth
- PRINTNL
-.endif
- lda #<cmd
- sta export.sd_data
- lda #>cmd
- sta export.sd_data+1
- jsr export.sd_send_cmd
- jmp cont_SD_SEND_CMD
-cmd: .byte \1
-cont_SD_SEND_CMD:
- .endm
-
-
-
-SD_RECEIVE .macro
- ldx #\1
-loop_SD_RECEIVE:
- phx
- jsr export.spi_get
-.if DEBUG
- pha
- jsr export.puth
- PRINTS " "
- pla
-.endif
- plx
- dex
- bne loop_SD_RECEIVE
- pha
-.if DEBUG
- PRINTNL
-.endif
- ;; Read non-existing dummy byte for snychronization
- jsr export.spi_get_nonblocking
- pla
- .endm
-
diff --git a/roms/boot/spi.asm b/roms/boot/spi.asm
@@ -3,7 +3,14 @@
;;; SPI read and write operations
;;;
;;; -----------------------------------
+
+spi .namespace
+.section zero_page
+ ;; Used by VIA for (de-)serialization
+via_buffer: .byte ?
+.send zero_page
+
;; Wiring:
;; PA0: CS
CS = %00000001
@@ -15,29 +22,28 @@
MISO = %00001000
+
+.section rom
+
;;; Initialize VIA: Switch all ports to output
;;; and all pins to low
-.namespace export
init_via:
lda #$ff
- sta export.via_ddra
- sta export.via_ddrb
+ sta io.via_ddra
+ sta io.via_ddrb
lda #$00
- sta export.via_ora
- sta export.via_orb
+ sta io.via_ora
+ sta io.via_orb
rts
-.endn
;;; Blocking read - read until
;;; byte != $ff is read or retry counter
;;; expires.
-.namespace export
-spi_get:
-.endn
+get:
.block
ldy #$00 ; Try up to $ff times
retry_loop:
- jsr export.spi_get_nonblocking
+ jsr spi.get_nonblocking
;; If we read $ff, we did not receive
;; a byte.
cmp #$ff
@@ -45,58 +51,57 @@ retry_loop:
dey ; Try again unless retry
bne retry_loop ; counter expired.
done:
- CLEAR_BITS export.via_ora, #(MOSI|SCK) ; Set MOSI and SCK low on completion.
- lda export.via_buffer
+ #mem.CLEAR_BITS io.via_ora, #(MOSI|SCK) ; Set MOSI and SCK low on completion.
+ lda spi.via_buffer
rts
.bend
;;; Return next byte; may be $ff in case of no transmission
-.namespace export
-spi_get_nonblocking:
-.endn
- SET_BITS export.via_ora, #MOSI ; Keep MOSI high during read
+get_nonblocking:
+ #mem.SET_BITS io.via_ora, #MOSI ; Keep MOSI high during read
lda #$00 ; Clear
- sta export.via_buffer ; receive buffer.
+ sta spi.via_buffer ; receive buffer.
ldx #$08 ; 8 bit to read.
read_bits_loop:
.block
- asl export.via_buffer ; Make room for next bit
- CLEAR_BITS export.via_ora, #SCK ; Generate clock impulse
- SET_BITS export.via_ora, #SCK
- lda export.via_ira ; Get next bit.
+ asl spi.via_buffer ; Make room for next bit
+ #mem.CLEAR_BITS io.via_ora, #SCK ; Generate clock impulse
+ #mem.SET_BITS io.via_ora, #SCK
+ lda io.via_ira ; Get next bit.
and #MISO
cmp #MISO
bne cont ; Nothing to do if we got a zero bit.
- inc export.via_buffer ; Set lowest bit in via_buffer
+ inc spi.via_buffer ; Set lowest bit in via_buffer
cont:
dex
bne read_bits_loop
- CLEAR_BITS export.via_ora, #(MOSI|SCK) ; Set MOSI and SCK low on completion.
- lda export.via_buffer
+ #mem.CLEAR_BITS io.via_ora, #(MOSI|SCK) ; Set MOSI and SCK low on completion.
+ lda spi.via_buffer
rts
.bend
;;; Write byte via SPI
-.namespace export
-spi_set:
-.endn
+set:
.block
- sta export.via_buffer ; We send from via_buffer
+ sta spi.via_buffer ; We send from via_buffer
ldx #$08 ; 8 bit to write
write_bits_loop:
- CLEAR_BITS export.via_ora, #SCK ; Set bits on low clock
- CLEAR_BITS export.via_ora,#MOSI
- lda export.via_buffer ; Get next bit to send
+ #mem.CLEAR_BITS io.via_ora, #SCK ; Set bits on low clock
+ #mem.CLEAR_BITS io.via_ora,#MOSI
+ lda spi.via_buffer ; Get next bit to send
and #%10000000 ; Isolate bit to send.
beq cont ; Set MOSI accordingly.
- SET_BITS export.via_ora,#MOSI
+ #mem.SET_BITS io.via_ora,#MOSI
jmp cont
cont:
- SET_BITS export.via_ora, #SCK ; Send bits on high clock
- asl export.via_buffer ; Advance to next bit
+ #mem.SET_BITS io.via_ora, #SCK ; Send bits on high clock
+ asl spi.via_buffer ; Advance to next bit
dex
bne write_bits_loop
- CLEAR_BITS export.via_ora,#SCK
+ #mem.CLEAR_BITS io.via_ora,#SCK
rts
.bend
+.send rom
+
+.endn
diff --git a/roms/boot/stack.asm b/roms/boot/stack.asm
@@ -1,72 +0,0 @@
-;;; ----------------------------------------------------------
-;;;
-;;; STACK
-;;;
-;;; ----------------------------------------------------------
-
-;;; Software implementation of data stack. In difference to typical
-;;; stack implementations, this stack grows from bottom to top, because
-;;; we want to access eleements using indirected indexed access with
-;;; the stack frame pointer as base. Therefore the stack should
-;;; be initialized with the first unoccupied RAM address after the
-;;; program code.
-;;;
-;;; PULL and PUSH do not move actual stack data, they just shift
-;;; the stack pointer.
-;;;
-;;; Local variables on the data stack are supported by macro
-;;; VAR. VAR i refers to the ith byte on the stack. PARAM allows
-;;; to pass variables to a callee. PARAM i of the caller becomes
-;;; VAR i of the callee. The callee should reserve stack space
-;;; for both its parameters and local variables.
-;;;
-;;; Stack frames used for these calls are created/destroyed by
-;;; subroutines create_stack_frame and delete_stack_frame.
-;;;
-;;; CALL is like jsr with parameter passing. There addressing
-;;; modes are supported: immediate, zero-page, and local variables.
-;;; For immediate and zero page, the third parameter must be lda.
-;;; For local variables, the third parameter must be lda_LOCAL.
-;;; See sw/stack_test/stack_test.asm for examles.
-
-
-.namespace export
-create_stack_frame:
-.endn
- .block
- ;; Store old frame pointer on stack.
- ;; Since our stack grows bottom to top, we write
- ;; the data before increasing the stack pointer
- #COPY_WORD_ABSOLUTE_INDIRECT export.ds_frame, (export.ds_pointer)
- #PUSH $02 ; Store old frame pointer
- #COPY_WORD_ABSOLUTE_INDIRECT export.ds_pointer, export.ds_frame ; Set new frame pointer
- rts
- .bend
-
-.namespace export
-delete_stack_frame:
-.endn
- .block
- #COPY_WORD_ABSOLUTE_INDIRECT export.ds_frame, export.ds_pointer ; Reset stack pointer to begin of frame.
- #PULL $02 ; Move stack pointer to frame reference
- #COPY_WORD_ABSOLUTE_INDIRECT (export.ds_pointer), export.ds_frame ; Restore old frame pointer.
- rts
- .bend
-
-.namespace export
-push_a:
-.endn
- .block
- sta (export.ds_pointer)
- #PUSH $01
- rts
- .bend
-
-.namespace export
-pull_a:
-.endn
- .block
- #PULL $01
- lda (export.ds_pointer)
- rts
- .bend
diff --git a/roms/boot/stack.inc b/roms/boot/stack.inc
@@ -1,77 +0,0 @@
-;;; -*- asm -*-
-
-;;; Macros for accessing the data stack
-;;; and managing local variables and
-;;; call parameters. Check stack.asm for
-;;; documentation.
-
-;;; Stack related macros
-
-INIT_STACK: .macro
- #STORE_WORD \1, export.ds_pointer
- .endm
-
-PUSH: .macro ; Reserve bytes on stack (no actual push operation)
- #ADD_WORD export.ds_pointer, \1
- .endm
-
-PULL: .macro ; Remove bytes from stack (no return value)
- #SUB_WORD export.ds_pointer, \1
- .endm
-
-PUSH_WORD: .macro ; Push a word on the stack
- lda #<\1
- sta (export.ds_pointer)
- lda #>\1
- ldy #$01
- sta (export.ds_pointer),y
- #PUSH $02
- .endm
-
-LOCAL: .macro
- ldy #\1
- \2 (export.ds_frame),y
- .endm
-lda_LOCAL: .macro
- LOCAL \1, lda
- .endm
-sta_LOCAL: .macro
- LOCAL \1, sta
- .endm
-adc_LOCAL: .macro
- LOCAL \1, adc
- .endm
-PARAM: .macro
- ldy #\1
- \2 (export.ds_pointer),y
- .endm
-sta_PARAM: .macro
- PARAM \1+2, sta
- .endm
-lda_PARAM: .macro
- PARAM \1+2, lda
- .endm
-
-CALL: .macro subroutine, param=[], param_lda=""
- .block
- .if len(\param) != 0
- .for CALL_param := 0, CALL_param < len(\param), CALL_param += $1
- \param_lda \param[CALL_param]
- sta_PARAM CALL_param
- .next
- .endif
- jsr \subroutine
- .bend
- .endm
-
-;; Push sequence of bytes to stack. Parameters: From, Length
-PUSH_RANGE: .macro
- ldy #$00
-loop_PUSH_RANGE:
- lda \1,y
- sta (ds_pointer),y
- iny
- cpy \2
- bne loop_PUSH_RANGE
- #PUSH \2
- .endm
diff --git a/roms/boot/term.asm b/roms/boot/term.asm
@@ -0,0 +1,260 @@
+;;;
+;;; Special commands for ANSI terminals
+;;;
+
+term .namespace
+.section rom
+
+;;; ANSI text attributes
+plain = 0
+bold = 1
+blink = 5
+reverse = 7
+
+;;; ANSI colors
+black = 0
+red = 1
+green = 2
+yellow = 3
+blue = 4
+magenta = 5
+cyan = 6
+white = 7
+bright_black = 8
+bright_red = 9
+bright_green = 10
+bright_yellow = 11
+bright_blue = 12
+bright_magenta = 13
+bright_cyan = 14
+bright_white = 15
+
+;;; get_screen_size
+;;; Returns screen size in X, A.
+;;; If not supported by terminal, C is set
+;;; Input:
+;;; -
+;;; Output:
+;;; X: Screen width
+;;; A: Screen height
+;;; Changes:
+;;; a, x, y, c
+get_screen_size:
+ .block
+ jsr ds.create_stack_frame
+ #ds.PUSH $02
+ cursor_save_x = 0 ; Local variable
+ cursor_save_y = 1 ; Local variable
+ ;; Local variables 0 & 1: Saved cursor position
+ jsr term.get_cursor ; Save cursor position
+ bcs terminal_does_not_answer
+ #ds.sta_LOCAL cursor_save_y
+ txa
+ #ds.sta_LOCAL cursor_save_x
+ #SET_CURSOR #$FF, #$FF ; Try to move cursor to max. position
+ jsr term.get_cursor ; Get cursor position (= screen size)
+ pha ; Save it temporary
+ txa ; on the
+ pha ; hardware stack.
+ #ds.lda_LOCAL cursor_save_x ; Restore
+ tax ; old
+ #ds.lda_LOCAL cursor_save_y ; cursor
+ jsr term.set_cursor ; position
+ jsr ds.delete_stack_frame
+ pla
+ tax
+ pla
+ rts
+terminal_does_not_answer:
+ jsr ds.delete_stack_frame
+ ldx #80
+ lda #25
+ rts
+ .bend
+
+clear_screen:
+ #io.PRINTS x"1b" .. "[2J"
+ rts
+
+set_color:
+ pha
+ #io.PRINTS x"1b" .. "[38;5;"
+ pla
+ jsr io.putd
+ lda #"m"
+ jmp io.putc
+
+set_background_color:
+ pha
+ #io.PRINTS x"1b" .. "[48;5;"
+ pla
+ jsr io.putd
+ lda #"m"
+ jmp io.putc
+
+set_text:
+ tax
+ lda #"m"
+ jmp send_CSI
+
+cursor_up:
+ tax
+ lda #"A"
+ jmp send_CSI
+
+cursor_down:
+ tax
+ lda #"B"
+ jmp send_CSI
+
+cursor_forward:
+ tax
+ lda #"C"
+ jmp send_CSI
+
+cursor_back:
+ tax
+ lda #"D"
+ jmp send_CSI
+
+scroll_up:
+ tax
+ lda #"S"
+ jmp send_CSI
+
+scroll_down:
+ tax
+ lda #"T"
+ jmp send_CSI
+
+;;; Send ANSI escape sequence to terminal.
+;;; A contains command, X value
+send_CSI:
+ pha
+ phx
+ lda #$1b
+ jsr io.putc
+ lda #"["
+ jsr io.putc
+ pla
+ jsr io.putd
+ pla
+ jmp io.putc
+
+;;; set_cursor
+;;; Sets cursor to position x, a.
+;;; Position starts at 1, not 0!
+;;; Input:
+;;; x: x position
+;;; a: y position
+;;; Output:
+;;; -
+;;; Changes:
+;;; a, x, y, c
+;;; Set Cursor; x position in X, y position in A
+set_cursor:
+ phx
+ pha
+ lda #$1b
+ jsr io.putc
+ lda #"["
+ jsr io.putc
+ pla
+ jsr io.putd
+ lda #";"
+ jsr io.putc
+ pla
+ jsr io.putd
+ lda #"H"
+ jmp io.putc
+
+;;; get_cursor
+;;; Store cursor position in x, a.
+;;; Position starts at 1, not 0!
+;;; Input:
+;;; -
+;;; Output:
+;;; x: x position
+;;; a: y position
+;;; Changes:
+;;; a, x, y, c
+get_cursor:
+ .block
+ jsr ds.create_stack_frame
+ #ds.PUSH $08 ; Position as string
+ ;; We store the position string as local variables.
+ ;; By initializing the local variables with #$00,
+ ;; the strings terminate automatically when no
+ ;; more digits are written.
+ lda #$00
+ .for i = 0, i < 8, i += 1
+ #ds.sta_LOCAL i
+ .next
+ ;; Request cursor position
+ #io.PRINTS x"1b" .. "[6n"
+ ;; Read answer
+ ldx #$08 ; Number of tries
+ ldy #$ff ; to get an answer.
+wait_for_answer:
+ phx
+ phy
+ jsr io.getc_nonblocking ; $1b
+ ply
+ plx
+ bcc terminal_answers
+ dey
+ cpy #$00
+ bne wait_for_answer
+ dex
+ cpx #$00
+ bne wait_for_answer
+ ;; Terminal does not answer.
+ jsr ds.delete_stack_frame
+ lda #$00
+ ldx #$00
+ sec
+ rts
+terminal_answers:
+ jsr io.getc ; "["
+ jsr io.getc ; First digit y
+ #ds.sta_LOCAL 0
+ jsr io.getc ; Second digit y
+ cmp #";"
+ beq got_y_position
+ #ds.sta_LOCAL 1
+ jsr io.getc ; Third digit y
+ cmp #";"
+ beq got_y_position
+ #ds.sta_LOCAL 2
+ jsr io.getc ; Read and ignore terminating ';'
+got_y_position:
+ jsr io.getc ; First digit x
+ #ds.sta_LOCAL 4
+ jsr io.getc ; Second digit x
+ cmp #"R"
+ beq got_x_position
+ #ds.sta_LOCAL 5
+ jsr io.getc ; Third digit x
+ cmp #"R"
+ beq got_x_position
+ #ds.sta_LOCAL 6
+ jsr io.getc ; Read and ignore terminating 'R'
+got_x_position:
+ ;; x position is in local variable(s) 4...
+ ;; y position is in local variable(s) 0...
+ ;; Convert them to ints
+ #ds.CALL io.str2byte, [0, 1, 2, 3], #ds.lda_LOCAL
+ #ds.lda_PARAM 0
+ pha
+ #ds.CALL io.str2byte, [4, 5, 6, 7], #ds.lda_LOCAL
+ #ds.lda_PARAM 0
+ pha
+ jsr ds.delete_stack_frame
+ plx
+ pla
+ clc
+ rts
+ .bend
+
+.send rom
+.endn
diff --git a/roms/boot/term.inc b/roms/boot/term.inc
@@ -0,0 +1,62 @@
+;;; -*- asm -*-
+
+;;; -----------------------------------
+;;;
+;;; ANSI Terminal
+;;;
+;;; -----------------------------------
+
+.namespace term
+
+SET_COLOR .macro color
+ lda #color
+ jsr term.set_color
+ .endm
+
+SET_BACKGROUND_COLOR .macro color
+ lda #color
+ jsr term.set_background_color
+ .endm
+
+SET_TEXT .macro attribute
+ lda #\attribute
+ jsr term.set_text
+ .endm
+
+CURSOR_UP .macro steps
+ lda #\steps
+ jsr term.cursor_up
+ .endm
+
+CURSOR_DOWN .macro steps
+ lda #\steps
+ jsr term.cursor_down
+ .endm
+
+CURSOR_FORWARD .macro steps
+ lda #\steps
+ jsr term.cursor_forward
+ .endm
+
+CURSOR_BACK .macro steps
+ lda #\steps
+ jsr term.cursor_back
+ .endm
+
+SCROLL_UP .macro steps
+ lda #\steps
+ jsr term.scroll_up
+ .endm
+
+SCROLL_DOWN .macro steps
+ lda #\steps
+ jsr term.scroll_DOWN
+ .endm
+
+SET_CURSOR .macro x, y
+ lda \y
+ ldx \x
+ jsr term.set_cursor
+ .endm
+
+.endn
diff --git a/sw/10print/10print.asm b/sw/10print/10print.asm
@@ -3,25 +3,13 @@
.weak
BOOT_EMBEDDED = false
.endweak
-.if BOOT_EMBEDDED
- init_acia = export.init_acia
- lfsr_init = export.lfsr_init
- lfsr_step = export.lfsr_step
- putc = export.putc
-.else
- .if SYMON
- .include "boot_symon.l"
- * = $0300
- .else
- .include "boot.l"
- * = $0200
- .endif
+.if !BOOT_EMBEDDED
.include "boot.inc"
.endif
init:
cld
- jsr init_acia
- jsr lfsr_init
+ jsr io.init_acia
+ jsr lfsr.init
jmp ten_print
ten_print:
@@ -34,24 +22,24 @@ l0:
bne l0
dex
bne l1
- jsr lfsr_step
+ jsr lfsr.step
and #$01
bne slash
.if SYMON
lda #'\'
- jsr putc
+ jsr io.putc
.else
- PRINTS('╲')
+ #io.PRINTS '╲'
.endif
- jsr putc
+ jsr io.putc
jmp ten_print
slash:
.if SYMON
lda #'/'
- jsr putc
+ jsr io.putc
.else
- PRINTS('╱')
+ #io.PRINTS '╱'
.endif
- jsr putc
+ jsr io.putc
jmp ten_print
.bend
diff --git a/sw/ansi_test/ansi_test.asm b/sw/ansi_test/ansi_test.asm
@@ -1,25 +1,14 @@
-.if SYMON
- .include "boot_symon.l"
- start_address = $0300
-.else
- .include "boot.l"
- start_address = $0200
-.endif
.include "boot.inc"
- * = rom_zero_page_end
- .dsection zero_page
- * = start_address
- .dsection code
- .cerror * > $8000, "RAM exhausted"
+.dsection code
.section code
start_of_stack = end_of_code ; Stack starts right after code
init:
cld
- jsr init_acia
- INIT_STACK start_of_stack
+ jsr io.init_acia
+ #ds.INIT_STACK start_of_stack
;; Termin program on PC needs some time to start up
- ldy #$80
+ ldy #$ff
ldx #$ff
delay:
dex
@@ -27,115 +16,120 @@ delay:
dey
bne delay
jsr ansi_test
- jsr getc
+ jsr io.getc
jsr print_all_colors
-.if false
-.endif
-end:
- jmp end
+ jsr io.getc
+ jmp init
ansi_test:
.block
- jsr create_stack_frame
- jsr clear_screen
- #SET_CURSOR #$01, #$01
- #PRINTSNL "ANSI Terminal"
- #SET_CURSOR #$03, #$02
- PRINTS "Text starting at position 3, 2"
- #SET_CURSOR #$02, #$03
- PRINTSNL "Text starting at position 2, 3"
- PRINTS "Cursor position: "
- jsr get_cursor
+ jsr ds.create_stack_frame
+ jsr term.clear_screen
+ #term.SET_CURSOR #$01, #$01
+ #io.PRINTSNL "ANSI Terminal"
+ #term.SET_CURSOR #$03, #$02
+ #io.PRINTS "Text starting at position 3, 2"
+ #term.SET_CURSOR #$02, #$03
+ #io.PRINTSNL "Text starting at position 2, 3"
+ #io.PRINTS "Cursor position: "
+ jsr term.get_cursor
pha
txa
- jsr putd
- PRINTS ", "
+ jsr io.putd
+ #io.PRINTS ", "
pla
- jsr putd
- #SET_CURSOR #$01, #$05
- PRINTS "Screen size: "
- jsr get_screen_size
+ jsr io.putd
+ #term.SET_CURSOR #$01, #$05
+ #io.PRINTS "Screen size: "
+ jsr term.get_screen_size
pha
txa
- jsr putd
- PRINTS ", "
+ jsr io.putd
+ #io.PRINTS ", "
pla
- jsr putd
- PRINTNL
- #SET_TEXT bold
- PRINTSNL "Bold text"
- #SET_TEXT plain
- #SET_TEXT blink
- PRINTSNL "Blinking text"
- #SET_TEXT plain
- #SET_TEXT reverse
- PRINTSNL "Reverse text"
- #SET_TEXT plain
+ jsr io.putd
+ jsr io.putnl
+ #term.SET_TEXT term.bold
+ #io.PRINTSNL "Bold text"
+ #term.SET_TEXT term.plain
+ #term.SET_TEXT term.blink
+ #io.PRINTSNL "Blinking text"
+ #term.SET_TEXT term.plain
+ #term.SET_TEXT term.reverse
+ #io.PRINTSNL "Reverse text"
+ #term.SET_TEXT term.plain
lda #"*"
- jsr putc
- #CURSOR_DOWN 1
- #CURSOR_BACK 1
+ jsr io.putc
+ #term.CURSOR_DOWN 1
+ #term.CURSOR_BACK 1
lda #"*"
- jsr putc
- #CURSOR_DOWN 1
- #CURSOR_BACK 1
+ jsr io.putc
+ #term.CURSOR_DOWN 1
+ #term.CURSOR_BACK 1
lda #"*"
- jsr putc
- #CURSOR_FORWARD 1
+ jsr io.putc
+ #term.CURSOR_FORWARD 1
lda #"*"
- jsr putc
- #CURSOR_BACK 1
- #CURSOR_UP 1
+ jsr io.putc
+ #term.CURSOR_BACK 1
+ #term.CURSOR_UP 1
lda #"*"
- jsr putc
- #CURSOR_BACK 1
- #CURSOR_UP 1
+ jsr io.putc
+ #term.CURSOR_BACK 1
+ #term.CURSOR_UP 1
lda #"*"
- jsr putc
+ jsr io.putc
lda #$03
- jsr cursor_down
+ jsr term.cursor_down
lda #$03
- jsr cursor_back
- PRINTSNL "ANSI test completed."
+ jsr term.cursor_back
+ #io.PRINTSNL "ANSI test completed."
+ jsr ds.delete_stack_frame
rts
.bend
print_all_colors:
.block
- jsr clear_screen
- .for color in black, red, green, yellow, blue, magenta, cyan, white
- #SET_COLOR color
- PRINTSNL "Foreground color"
+ jsr ds.create_stack_frame
+ jsr term.clear_screen
+ #term.SET_CURSOR #$01, #$01
+ .for color in (term.black, term.red, term.green, term.yellow,
+ term.blue, term.magenta, term.cyan, term.white)
+ #term.SET_COLOR color
+ #io.PRINTSNL "Foreground color"
.next
- #SET_TEXT plain
- .for color in black, red, green, yellow, blue, magenta, cyan, white
- #SET_BACKGROUND_COLOR color
- PRINTS "Background color"
- #SET_TEXT plain
- PRINTNL
+ #term.SET_TEXT term.plain
+ .for color in (term.black, term.red, term.green, term.yellow,
+ term.blue, term.magenta, term.cyan, term.white)
+ #term.SET_BACKGROUND_COLOR color
+ #io.PRINTS "Background color"
+ #term.SET_TEXT term.plain
+ jsr io.putnl
.next
- .for color in (bright_black, bright_red, bright_green, bright_yellow,
- bright_blue, bright_magenta, bright_cyan, bright_white)
- #SET_COLOR color
- PRINTSNL "Foreground color"
+ .for color in (term.bright_black, term.bright_red,
+ term.bright_green, term.bright_yellow,
+ term.bright_blue, term.bright_magenta,
+ term.bright_cyan, term.bright_white)
+ #term.SET_COLOR color
+ #io.PRINTSNL "Foreground color"
.next
lda #$00
loop:
pha
- jsr set_color
+ jsr term.set_color
pla
pha
- jsr putd
+ jsr io.putd
lda #" "
- jsr putc
+ jsr io.putc
pla
- pha
inc a
cmp #$00
bne loop
- PRINTNL
- jsr delete_stack_frame
- #SET_TEXT plain
+ jsr io.putnl
+ jsr ds.delete_stack_frame
+ #term.SET_TEXT term.plain
+ #io.PRINTSNL "Color test completed."
rts
.bend
diff --git a/sw/interrupts/interrupts.asm b/sw/interrupts/interrupts.asm
@@ -77,7 +77,7 @@ loop:
jsr getc
lda flag
jsr puth
- PRINTNL
+ #PRINTNL
jmp loop
.bend
diff --git a/sw/load_from_card/load_from_card.asm b/sw/load_from_card/load_from_card.asm
@@ -4,32 +4,11 @@
.weak
BOOT_EMBEDDED = false
.endweak
-.if BOOT_EMBEDDED
- init_acia = export.init_acia
- init_via = export.init_via
- getc = export.getc
- putc = export.putc
- create_stack_frame = export.create_stack_frame
- ds_pointer = export.ds_pointer
- sd_data = export.sd_data
- sd_read_block = export.sd_read_block
- sd_open = export.sd_open
- puts_str = export.puts_str
- puts = export.puts
- puth = export.puth
-.else
- .if SYMON
- .include "boot_symon.l"
- start_address = $0300
- .else
- .include "boot.l"
- start_address = $0200
- .endif
+.if !BOOT_EMBEDDED
.include "boot.inc"
- * = rom_zero_page_end
- .dsection zero_page
- * = start_address
.endif
+
+
.dsection code
.section code
@@ -44,15 +23,17 @@ init:
.block
.if SYMON
cld
- jsr init_acia
- jsr init_via
+ jsr io.init_acia
+ jsr spi.init_via
.endif
.if !BOOT_EMBEDDED
;; Wait for key to start
- jsr getc
+ jsr io.getc
.endif
- INIT_STACK $7fff-$0400
+ #ds.INIT_STACK $7fff-$0400
loop:
+ #io.PRINTSNL "***** Eris 2010 8-Bit System *****"
+ #io.PRINTNL
jsr ls
jsr choose_program
bcs loop
@@ -63,8 +44,8 @@ loop:
load_address = $0200
choose_program:
- PRINTSNL("Choose program (0-9). Any other key reloads card.")
- jsr getc
+ #io.PRINTSNL "Choose program (0-9). Any other key reloads card."
+ jsr io.getc
sec
sbc #'0'
cmp #$0a ; Sets carry if not a digit
@@ -74,44 +55,45 @@ choose_program:
execute:
.block
pha
- jsr create_stack_frame
- PUSH 4 ; Local variables
+ jsr ds.create_stack_frame
+ #ds.PUSH 4 ; Local variables
pla
;; Each app has 2**16 blocks, app number is in A, therefore
;; the address of the app is [#$00, A, #$00, #$01]
- sta_LOCAL 1
- PRINTS "Executing program "
- lda_LOCAL 1
+ #ds.sta_LOCAL 1
+ #io.PRINTS "Loading and executing program "
+ #ds.lda_LOCAL 1
clc
adc #'0'
- jsr putc
- PRINTSNL "."
+ jsr io.putc
+ #io.PRINTSNL "."
lda #$00
- sta_LOCAL 0
- sta_LOCAL 2
+ #ds.sta_LOCAL 0
+ #ds.sta_LOCAL 2
lda #$01
- sta_LOCAL 3
- COPY_WORD_ABSOLUTE_INDIRECT ds_pointer, sd_data ; Read block
- PUSH $0200 ; to stack
- CALL sd_read_block, [0, 1, 2, 3], lda_LOCAL
- PULL $0200 ; Reset stack pointer to block read
- COPY_WORD_IMMEDIATE load_address, sd_data ; Set Target address
- lda (ds_pointer) ; Number of blocks
+ #ds.sta_LOCAL 3
+ #mem.COPY_WORD_ABSOLUTE_INDIRECT ds.ptr, sd.data ; Read block
+ #ds.PUSH $0200 ; to stack
+ #ds.CALL sd.read_block, [0, 1, 2, 3], #ds.lda_LOCAL
+ #ds.PULL $0200 ; Reset stack pointer to block read
+ #mem.COPY_WORD_IMMEDIATE load_address, sd.data ; Set Target address
+ lda (ds.ptr) ; Number of blocks
read_next_block:
pha
;; Advance to next block on card
clc
- lda_LOCAL 3
+ #ds.lda_LOCAL 3
adc #$01
- sta_LOCAL 3
- lda_LOCAL 2
+ #ds.sta_LOCAL 3
+ #ds.lda_LOCAL 2
adc #$00
- sta_LOCAL 2
- CALL sd_read_block, [0, 1, 2, 3], lda_LOCAL ; Read block
- ADD_WORD sd_data, $0200 ; Advance to next block
+ #ds.sta_LOCAL 2
+ #ds.CALL sd.read_block, [0, 1, 2, 3], #ds.lda_LOCAL ; Read block
+ #mem.ADD_WORD sd.data, $0200 ; Advance to next block
pla
dec a
bne read_next_block
+ jsr ds.delete_stack_frame
;; Done. Execute program
jmp load_address
.bend
@@ -120,14 +102,14 @@ read_next_block:
;; List programs on card
ls:
.block
- jsr create_stack_frame
- jsr sd_open
+ jsr ds.create_stack_frame
+ jsr sd.open
;; List files on card
- COPY_WORD_ABSOLUTE_INDIRECT ds_pointer, sd_data ; Read block
- PUSH $0200 ; to stack
- CALL sd_read_block, [#$00, #$00, #$00, #$00], lda
- PULL $0200 ; Reset stack pointer to point to block read
- lda (ds_pointer)
+ #mem.COPY_WORD_ABSOLUTE_INDIRECT ds.ptr, sd.data ; Read block
+ #ds.PUSH $0200 ; to stack
+ #ds.CALL sd.read_block, [#$00, #$00, #$00, #$00], lda
+ #ds.PULL $0200 ; Reset stack pointer to point to block read
+ lda (ds.ptr)
cmp #$00 ; Check FS version
beq cont
jmp not_supported
@@ -137,43 +119,43 @@ dir_entry_loop:
pha
clc
adc #'0'
- jsr putc
- PRINTS ": "
+ jsr io.putc
+ #io.PRINTS ": "
;; Each app has 2**16 blocks, therefore
;; the address of app i is [#$00, #i, #$00, #$01]
lda #$00
- sta_LOCAL 0
- sta_LOCAL 2
+ #ds.sta_LOCAL 0
+ #ds.sta_LOCAL 2
lda #$01
- sta_LOCAL 3
+ #ds.sta_LOCAL 3
pla
pha
- sta_LOCAL 1
- PUSH 4
- COPY_WORD_ABSOLUTE_INDIRECT ds_pointer, sd_data ; Read block
- PUSH $0200 ; to stack
- CALL sd_read_block, [0, 1, 2, 3], lda_LOCAL
- PULL $0200 ; Reset stack pointer to block read
- lda (ds_pointer) ; Number of blocks
+ #ds.sta_LOCAL 1
+ #ds.PUSH 4
+ #mem.COPY_WORD_ABSOLUTE_INDIRECT ds.ptr, sd.data ; Read block
+ #ds.PUSH $0200 ; to stack
+ #ds.CALL sd.read_block, [0, 1, 2, 3], #ds.lda_LOCAL
+ #ds.PULL $0200 ; Reset stack pointer to block read
+ lda (ds.ptr) ; Number of blocks
beq filename_printed ; This spot is not occupied
pha
- COPY_WORD_ABSOLUTE_INDIRECT ds_pointer, puts_str
- ADD_WORD puts_str, $01 ; Start of filename
- jsr puts
- PRINTS " ($"
+ #mem.COPY_WORD_ABSOLUTE_INDIRECT ds.ptr, io.puts_str
+ #mem.ADD_WORD io.puts_str, $01 ; Start of filename
+ jsr io.puts
+ #io.PRINTS " ("
pla
pha
- jsr puth
+ jsr io.putd
pla
cmp #$01
beq one_block
- PRINTS " blocks)"
+ #io.PRINTS " blocks)"
jmp filename_printed
one_block:
- PRINTS " block)"
+ #io.PRINTS " block)"
filename_printed:
- PRINTNL
- PULL 4
+ jsr io.putnl
+ #ds.PULL 4
pla
inc a
cmp #$0a
@@ -181,12 +163,12 @@ filename_printed:
jmp dir_entry_loop
done:
clc
- jsr export.delete_stack_frame
+ jsr ds.delete_stack_frame
rts
not_supported:
- PRINTSNL "This filesystem is not supported."
+ #io.PRINTSNL "This filesystem is not supported."
sec
- jsr export.delete_stack_frame
+ jsr ds.delete_stack_frame
rts
.bend
diff --git a/sw/serial_line_echo/serial_line_echo.asm b/sw/serial_line_echo/serial_line_echo.asm
@@ -1,17 +1,11 @@
-.if SYMON
- .include "boot_symon.l"
-.else
- .include "boot.l"
-.endif
.include "boot.inc"
- * = $0200
init:
- jsr init_acia
+ jsr io.init_acia
loop:
- #PRINTSNL "Serial line echo"
- #INPUTS $1000, #$10
- #PRINTNL
- #PRINT $1000
- #PRINTNL
+ #io.PRINTSNL "Serial line echo"
+ #io.INPUTS $1000, #$10
+ jsr io.putnl
+ #io.PRINT $1000
+ jsr io.putnl
jmp loop
diff --git a/sw/stack_test/stack_test.asm b/sw/stack_test/stack_test.asm
@@ -1,17 +1,7 @@
;;; A data stack
-.if SYMON
- .include "boot_symon.l"
- start_address = $0300
-.else
- .include "boot.l"
- start_address = $0200
-.endif
.include "boot.inc"
- * = start_address
.dsection code
- .cerror * > $8000, "RAM exhausted"
-
.section code
;; start_of_stack = $7fff-$206+$1 ; Minimal stack as defined in ROM
@@ -19,11 +9,11 @@
init:
.block
cld
- INIT_STACK start_of_stack
- jsr init_acia
+ #ds.INIT_STACK start_of_stack
+ jsr io.init_acia
.if SYMON
.else
- jsr getc
+ jsr io.getc
.endif
jsr stack_test
jsr test_local_variables
@@ -37,85 +27,85 @@ loop:
stack_test:
.block
;; Testing empty stack
- jsr create_stack_frame
- jsr delete_stack_frame
- lda ds_pointer
+ jsr ds.create_stack_frame
+ jsr ds.delete_stack_frame
+ lda ds.ptr
cmp #<start_of_stack
#CHECK_ERROR
- lda ds_pointer+1
+ lda ds.ptr+1
cmp #>start_of_stack
#CHECK_ERROR
;; Push and pull
- jsr create_stack_frame
+ jsr ds.create_stack_frame
lda #$a0
- sta (ds_pointer)
- PUSH $01
+ sta (ds.ptr)
+ #ds.PUSH $01
lda #$b0
- sta (ds_pointer)
- PUSH $01
+ sta (ds.ptr)
+ #ds.PUSH $01
lda #$c0
- sta (ds_pointer)
- PUSH $01
- PULL $01
- lda (ds_pointer)
+ sta (ds.ptr)
+ #ds.PUSH $01
+ #ds.PULL $01
+ lda (ds.ptr)
cmp #$c0
#CHECK_ERROR
- PULL $01
- lda (ds_pointer)
+ #ds.PULL $01
+ lda (ds.ptr)
cmp #$b0
#CHECK_ERROR
- PULL $01
- lda (ds_pointer)
+ #ds.PULL $01
+ lda (ds.ptr)
cmp #$a0
#CHECK_ERROR
- PUSH $01
+ #ds.PUSH $01
;; Push and pull with new frame
lda #$a1
- sta (ds_pointer)
- PUSH $01
- lda ds_pointer ; Save ds_pointer
+ sta (ds.ptr)
+ #ds.PUSH $01
+ lda ds.ptr ; Save stack pointer
pha ; for later comparison
- jsr create_stack_frame
+ jsr ds.create_stack_frame
ldy #$00
lda #$b1
- sta (ds_pointer),y
+ sta (ds.ptr),y
inc y
- sta (ds_pointer),y
+ sta (ds.ptr),y
inc y
- sta (ds_pointer),y
+ sta (ds.ptr),y
inc y
- PUSH $03
- PULL $01
- lda (ds_pointer)
+ #ds.PUSH $03
+ #ds.PULL $01
+ lda (ds.ptr)
cmp #$b1
#CHECK_ERROR
- jsr delete_stack_frame
- pla ; Still same ds_pointer
- cmp ds_pointer ; as before creating and
+ jsr ds.delete_stack_frame
+ pla ; Still same stack pointer
+ cmp ds.ptr ; as before creating and
#CHECK_ERROR ; deleting frame?
- PULL $01
- lda (ds_pointer)
+ #ds.PULL $01
+ lda (ds.ptr)
cmp #$a1
#CHECK_ERROR
- PULL $01
- lda (ds_pointer)
+ #ds.PULL $01
+ lda (ds.ptr)
cmp #$a0
#CHECK_ERROR
- jsr delete_stack_frame
- lda ds_pointer ; Stack should be
+ jsr ds.delete_stack_frame
+ lda ds.ptr ; Stack should be
cmp #<start_of_stack ; empty again.
#CHECK_ERROR
- lda ds_pointer+1
+ lda ds.ptr+1
cmp #>start_of_stack
#CHECK_ERROR
- #PUSH_WORD $abcd
- jsr pull_a
+ #ds.PUSH_WORD $abcd
+ jsr ds.pull_a
cmp #$ab
#CHECK_ERROR
- jsr pull_a
+ jsr ds.pull_a
cmp #$cd
#CHECK_ERROR
- PRINTSNL("Stack test completed!")
+ #io.PRINTSNL "Stack test completed!"
rts
.bend
@@ -123,7 +113,7 @@ CHECK_ERROR: .macro
.block
beq error_cont
error:
- PRINTSNL("Error!")
+ #io.PRINTSNL "Error!"
error_loop:
jmp error_loop
error_cont:
@@ -132,86 +122,86 @@ error_cont:
test_local_variables:
.block
- jsr create_stack_frame
+ jsr ds.create_stack_frame
;; Working with local variables
- PUSH $02 ; Create local variables
+ #ds.PUSH $02 ; Create local variables
lda #$ab
- sta_LOCAL 0
+ #ds.sta_LOCAL 0
lda #$00
- lda_LOCAL 0
+ #ds.lda_LOCAL 0
inc a
- sta_LOCAL 1
+ #ds.sta_LOCAL 1
lda #$00
- lda_LOCAL 1
+ #ds.lda_LOCAL 1
cmp #$ac
#CHECK_ERROR
;; Passing paramters
lda #$01
- sta_PARAM 0
+ #ds.sta_PARAM 0
lda #$02
- sta_PARAM 1
+ #ds.sta_PARAM 1
jsr test_param
- lda_PARAM 0
+ #ds.lda_PARAM 0
cmp #$03
#CHECK_ERROR
- jsr delete_stack_frame
- PRINTSNL("Local variable test completed!")
+ jsr ds.delete_stack_frame
+ #io.PRINTSNL "Local variable test completed!"
rts
.bend
test_param:
.block
- jsr create_stack_frame
- PUSH $02 ; Local variables (here: parameters)
- lda_LOCAL 0
+ jsr ds.create_stack_frame
+ #ds.PUSH $02 ; Local variables (here: parameters)
+ #ds.lda_LOCAL 0
clc
- adc_LOCAL 1
- sta_LOCAL 0
- jsr delete_stack_frame
+ #ds.adc_LOCAL 1
+ #ds.sta_LOCAL 0
+ jsr ds.delete_stack_frame
rts
.bend
test_recursion:
.block
- jsr create_stack_frame
- PUSH $02 ; Create local variables
+ jsr ds.create_stack_frame
+ #ds.PUSH $02 ; Create local variables
lda #$04 ; Recursion counter
- sta_LOCAL 0
+ #ds.sta_LOCAL 0
lda #$01 ; Initial value
- sta_LOCAL 1
- CALL recursion, [0, 1], lda_LOCAL
- lda_PARAM 1 ; Check for
+ #ds.sta_LOCAL 1
+ #ds.CALL recursion, [0, 1], #ds.lda_LOCAL
+ #ds.lda_PARAM 1 ; Check for
cmp #$09 ; expected result
#CHECK_ERROR
- jsr delete_stack_frame
+ jsr ds.delete_stack_frame
;; Check if stack is empty again
- lda ds_pointer
+ lda ds.ptr
cmp #<start_of_stack
#CHECK_ERROR
- lda ds_pointer+1
+ lda ds.ptr+1
cmp #>start_of_stack
#CHECK_ERROR
- PRINTSNL("Recursion test completed!")
+ #io.PRINTSNL "Recursion test completed!"
rts
.bend
recursion:
.block
- jsr create_stack_frame
- PUSH $02 ; Local variables
- lda_LOCAL 0
+ jsr ds.create_stack_frame
+ #ds.PUSH $02 ; Local variables
+ #ds.lda_LOCAL 0
beq done
dec a
- sta_LOCAL 0
- lda_LOCAL 1
+ #ds.sta_LOCAL 0
+ #ds.lda_LOCAL 1
inc a
inc a
- sta_LOCAL 1
- CALL recursion, [0, 1], lda_LOCAL
- lda_PARAM 1
- sta_LOCAL 1
+ #ds.sta_LOCAL 1
+ #ds.CALL recursion, [0, 1], #ds.lda_LOCAL
+ #ds.lda_PARAM 1
+ #ds.sta_LOCAL 1
done:
- jsr delete_stack_frame
+ jsr ds.delete_stack_frame
rts
.bend
diff --git a/sw/ttt/README.txt b/sw/ttt/README.txt
@@ -1,13 +1,11 @@
* Targets
ttt.bin
- is the binary to be uploaded to address $300 on the GATE 2010
+ is the binary to be uploaded to address $200 on the Eris 2010
ttt_symon.bin
is the binary for Symon (ROM & ACIA at different memory addresses)
-*_boot.bin
- are binaries to be included into the boot ROM of GATE 2010 and Symon
*_test.bin
- are binaries running self-tests on GATE 2010 and Symon
+ are binaries running self-tests on Eris 2010 and Symon
* Source Code
diff --git a/sw/ttt/board.asm b/sw/ttt/board.asm
@@ -33,7 +33,7 @@ game_finished:
jsr print_board
pla
jsr print_game_state
- PRINTNL
+ jsr io.putnl
rts
next_ply:
cmp #piece_x
@@ -291,7 +291,7 @@ SET_FIELD .macro
.endm
GET_FIELD .macro
- #STORE_WORD \1, board_ptr
+ #mem.STORE_WORD \1, board_ptr
ldx #\2
jsr get_field
.endm
@@ -305,23 +305,23 @@ print_board:
.block
ldx #$ff
phx
- #PRINTSNL '+---+---+---+'
+ #io.PRINTSNL '+---+---+---+'
print_field:
lda #$03
sta tmp ; Print each line 3 times
print_line:
lda #'|'
- jsr putc
+ jsr io.putc
plx
inx
phx
jsr get_field
jsr piece_to_ascii
- jsr putc
+ jsr io.putc
plx
phx
jsr put_field_number_if_empty_and_middle
- jsr putc
+ jsr io.putc
plx
phx
cpx #$02
@@ -338,7 +338,7 @@ check_if_all_rows_printed:
plx ; Clean-up stack
rts
print_row_seperator:
- #PRINTSNL '|'
+ #io.PRINTSNL '|'
dec tmp ; Check if each line has been printed 3 times
lda tmp
beq print_seperator
@@ -348,7 +348,7 @@ print_row_seperator:
pha
jmp print_line ;again.
print_seperator:
- #PRINTSNL '+---+---+---+'
+ #io.PRINTSNL '+---+---+---+'
lda #$03
sta tmp
jmp check_if_all_rows_printed
@@ -366,12 +366,12 @@ put_field_number_if_empty_and_middle:
txa
clc
adc #'1'
- jsr putc
+ jsr io.putc
pla
rts
print_verbatim:
pla
- jmp putc
+ jmp io.putc
.bend
@@ -575,18 +575,18 @@ print_game_state:
beq somebody_won
cmp #piece_none
bne no_draw
- #PRINTSNL "Draw!"
+ #io.PRINTSNL "Draw!"
rts
no_draw:
- #PRINTSNL "Let the game continue!"
+ #io.PRINTSNL "Let the game continue!"
rts
somebody_won:
pha
- #PRINTS "Player "
+ #io.PRINTS "Player "
pla
clc
adc #'0'
- jsr putc
- #PRINTSNL " wins!"
+ jsr io.putc
+ #io.PRINTSNL " wins!"
rts
.bend
diff --git a/sw/ttt/board_test.asm b/sw/ttt/board_test.asm
@@ -3,7 +3,7 @@
CHECK_ERROR .macro
cmp #\1
beq no_error
- #PRINTSNL "Error"
+ #io.PRINTSNL "Error"
stop_loop
jmp stop_loop
no_error
@@ -137,6 +137,6 @@ game_board_test:
#PLAYER_WIN_FIRST_DIAGONAL piece_x
#PLAYER_WIN_SECOND_DIAGONAL piece_o
#PLAYER_WIN_FIRST_DIAGONAL piece_o
- #PRINTSNL "Board tests completed. No errors found!"
+ #io.PRINTSNL "Board tests completed. No errors found!"
rts
.bend
diff --git a/sw/ttt/computer_player.asm b/sw/ttt/computer_player.asm
@@ -15,8 +15,8 @@ computer_random_ply:
;; nibble until it is <= 8.
;; BUG: Looks like we never get 0.
get_random:
- jsr lfsr_step
- lda lfsr_state
+ jsr lfsr.step
+ lda lfsr.state
and #$0f
cmp #$09
bcs get_random
@@ -127,7 +127,7 @@ computer_perfect_ply:
pla
bcc execute_ply
;; No rule left; this should not happen.
- #PRINTSNL 'Error'
+ #io.PRINTSNL 'Error'
error:
jmp error
execute_ply:
@@ -232,12 +232,12 @@ win_column:
;; We mirror the board in order to use
;; win_column to check for a winning
;; position.
- #STORE_WORD board_mirrored,other_board_ptr
+ #mem.STORE_WORD board_mirrored,other_board_ptr
jsr mirror_board
- #STORE_WORD board_mirrored,board_ptr
+ #mem.STORE_WORD board_mirrored,board_ptr
lda tmp ; Who am I?
jsr win_row
- #STORE_WORD main_board,board_ptr
+ #mem.STORE_WORD main_board,board_ptr
bcs no_win
;; We found a winning position
;; since we found the winning
@@ -360,7 +360,7 @@ fork:
;; an empty field after pairing, then this is the
;; fork field.
pha ; Remember who I am
- #STORE_WORD fork_board_rows, other_board_ptr
+ #mem.STORE_WORD fork_board_rows, other_board_ptr
pla ; Store my piece
pha ; in A
jsr find_rows_for_fork
@@ -369,25 +369,25 @@ fork:
;; find_rows_for_fork again.
;; We use board_mirrored as an auxillary variable
;; here.
- #STORE_WORD main_board, board_ptr
- #STORE_WORD fork_board_columns, other_board_ptr
+ #mem.STORE_WORD main_board, board_ptr
+ #mem.STORE_WORD fork_board_columns, other_board_ptr
jsr mirror_board
;; Check for fork points on mirrored
;; board and store the result in
;; fork_board_columns
- #STORE_WORD fork_board_columns, board_ptr
- #STORE_WORD board_mirrored, other_board_ptr
+ #mem.STORE_WORD fork_board_columns, board_ptr
+ #mem.STORE_WORD board_mirrored, other_board_ptr
pla ; Store my piece
pha ; in A
jsr find_rows_for_fork
;; Reverse mirroring
- #STORE_WORD board_mirrored, board_ptr
- #STORE_WORD fork_board_columns, other_board_ptr
+ #mem.STORE_WORD board_mirrored, board_ptr
+ #mem.STORE_WORD fork_board_columns, other_board_ptr
jsr mirror_board
pla
pha
- #STORE_WORD fork_board_rows, board_ptr
- #STORE_WORD fork_board_columns, other_board_ptr
+ #mem.STORE_WORD fork_board_rows, board_ptr
+ #mem.STORE_WORD fork_board_columns, other_board_ptr
jsr check_fork
bcs cont
jmp done
@@ -410,8 +410,8 @@ cont:
sta fork_board_diagonals
sta fork_board_diagonals+1
sta fork_board_diagonals+2
- #STORE_WORD main_board, board_ptr
- #STORE_WORD fork_board_diagonals, other_board_ptr
+ #mem.STORE_WORD main_board, board_ptr
+ #mem.STORE_WORD fork_board_diagonals, other_board_ptr
#COPY_FIELD 0, 0
#COPY_FIELD 4, 1
#COPY_FIELD 8, 2
@@ -419,8 +419,8 @@ cont:
#COPY_FIELD 2, 3
#COPY_FIELD 4, 4
#COPY_FIELD 6, 5
- #STORE_WORD fork_board_diagonals, board_ptr
- #STORE_WORD board_mirrored, other_board_ptr
+ #mem.STORE_WORD fork_board_diagonals, board_ptr
+ #mem.STORE_WORD board_mirrored, other_board_ptr
pla ; Store my piece
pha ; in A
jsr find_rows_for_fork
@@ -432,8 +432,8 @@ cont:
lda #%00110011
sta fork_board_diagonals+1
;; First diagonal
- #STORE_WORD board_mirrored, board_ptr
- #STORE_WORD fork_board_diagonals, other_board_ptr
+ #mem.STORE_WORD board_mirrored, board_ptr
+ #mem.STORE_WORD fork_board_diagonals, other_board_ptr
#COPY_FIELD 0, 0
#COPY_FIELD 1, 4
#COPY_FIELD 2, 8
@@ -445,21 +445,21 @@ cont:
#GET_FIELD board_mirrored, 4
cmp #$00
bne middle_field_not_part_of_potential_fork
- #STORE_WORD fork_board_diagonals, board_ptr
+ #mem.STORE_WORD fork_board_diagonals, board_ptr
#SET_FIELD $00, 4
middle_field_not_part_of_potential_fork:
;; No check if there is a fork between
;; rows and diagonals ...
- #STORE_WORD fork_board_diagonals, board_ptr
- #STORE_WORD fork_board_rows, other_board_ptr
+ #mem.STORE_WORD fork_board_diagonals, board_ptr
+ #mem.STORE_WORD fork_board_rows, other_board_ptr
jsr check_fork
bcc done
;; ... and columns and diagonals.
- #STORE_WORD fork_board_columns, other_board_ptr
+ #mem.STORE_WORD fork_board_columns, other_board_ptr
jsr check_fork
done:
;; Some restore operatons
- #STORE_WORD main_board, board_ptr
+ #mem.STORE_WORD main_board, board_ptr
pla
rts
.bend
diff --git a/sw/ttt/computer_player_test.asm b/sw/ttt/computer_player_test.asm
@@ -42,7 +42,7 @@ check_board_cont:
mirror_board_test:
.block
jsr init_board
- #STORE_WORD board_mirrored,other_board_ptr
+ #mem.STORE_WORD board_mirrored,other_board_ptr
;; Test rotation of board
;; One piece on field 0.
;; Rotation should change nothing
@@ -66,10 +66,10 @@ mirror_board_test:
jsr mirror_board
#CHECK_BOARD %011100,%100001,%011110
no_error:
- #PRINTSNL "OK"
+ #io.PRINTSNL "OK"
rts
error:
- #PRINTSNL "ERROR"
+ #io.PRINTSNL "ERROR"
rts
.bend
@@ -127,7 +127,7 @@ win_by_column:
rts
play_win_by_column:
jsr print_board
- PRINTNL
+ jsr io.putnl
lda #piece_x
jsr computer_perfect_ply
pha
@@ -136,10 +136,10 @@ play_win_by_column:
jsr get_game_state
cmp #piece_x
bne win_by_column_error
- #PRINTSNL "OK"
+ #io.PRINTSNL "OK"
rts
win_by_column_error:
- #PRINTSNL "ERROR"
+ #io.PRINTSNL "ERROR"
rts
win_by_diagonal:
@@ -188,7 +188,7 @@ win_by_diagonal:
rts
play_win_by_diagonal:
jsr print_board
- #PRINTNL
+ jsr io.putnl
lda #piece_x
jsr computer_perfect_ply
pha
@@ -197,10 +197,10 @@ play_win_by_diagonal:
jsr get_game_state
cmp #piece_x
bne win_by_diagonal_error
- #PRINTSNL "OK"
+ #io.PRINTSNL "OK"
rts
win_by_diagonal_error:
- #PRINTSNL "ERROR"
+ #io.PRINTSNL "ERROR"
rts
block_by_column:
@@ -255,13 +255,13 @@ block_by_column:
rts
play_block_by_column:
jsr print_board
- #PRINTNL
+ jsr io.putnl
lda #piece_o
jsr computer_perfect_ply
pha
jsr print_board
pla
- jsr getc
+ jsr io.getc
rts
fork_row_column:
@@ -277,7 +277,7 @@ fork_row_column:
pha
jsr print_board
pla
- #PRINTNL
+ jsr io.putnl
lda #piece_o
jsr computer_perfect_ply
pha
@@ -286,30 +286,30 @@ fork_row_column:
;; Check for correct ply
#GET_FIELD main_board,5
#CHECK_ERROR piece_o
- jsr getc
+ jsr io.getc
;; Row/diagonal fork
jsr init_board
;; lda #$ac ; Test runs perfectly with this initialization of the lfsr
- ;; sta lfsr_state
- ;; sta lfsr_state+1
+ ;; sta lfsr.state
+ ;; sta lfsr.state+1
jsr computer_perfect_init
#SET_FIELD piece_x, 0
#SET_FIELD piece_o, 3
#SET_FIELD piece_x, 6
- #PRINTNL
+ jsr io.putnl
pha
jsr print_board
pla
lda #piece_x
jsr computer_perfect_ply
pha
- #PRINTNL
+ jsr io.putnl
jsr print_board
pla
;; Check for correct ply
#GET_FIELD main_board,2
#CHECK_ERROR piece_x
- jsr getc
+ jsr io.getc
;; Another Row/diagonal fork
jsr init_board
jsr computer_perfect_init
@@ -321,7 +321,7 @@ fork_row_column:
pha
jsr print_board
pla
- #PRINTNL
+ jsr io.putnl
lda #piece_o
jsr computer_perfect_ply
pha
@@ -330,32 +330,32 @@ fork_row_column:
;; Check for correct ply
#GET_FIELD main_board,4
#CHECK_ERROR piece_o
- jsr getc
+ jsr io.getc
rts
.bend
test_block_fork:
.block
jsr computer_perfect_init
- #STORE_WORD main_board,board_ptr
+ #mem.STORE_WORD main_board,board_ptr
#SET_FIELD piece_x, 0
#SET_FIELD piece_o, 3
#SET_FIELD piece_x, 4
#SET_FIELD piece_o, 8
- #PRINTNL
+ jsr io.putnl
pha
jsr print_board
pla
lda #piece_o
jsr computer_perfect_ply
pha
- #PRINTNL
+ jsr io.putnl
jsr print_board
pla
;; Check for correct ply
#GET_FIELD main_board,1
#CHECK_ERROR piece_o
- jsr getc
+ jsr io.getc
;; Check if computer creates
;; two-in-a-row/column/diagonal
;; when when a fork by the opponet is
@@ -366,48 +366,48 @@ test_block_fork:
;; O -> 1
;; X -> 9
jsr computer_perfect_init
- #STORE_WORD main_board,board_ptr
+ #mem.STORE_WORD main_board,board_ptr
#SET_FIELD piece_o, 0
#SET_FIELD piece_x, 4
#SET_FIELD piece_x, 8
- #PRINTNL
+ jsr io.putnl
pha
jsr print_board
pla
lda #piece_o
jsr computer_perfect_ply
pha
- #PRINTNL
+ jsr io.putnl
jsr print_board
pla
;; Check for correct ply
#GET_FIELD main_board,1
#CHECK_ERROR piece_o
- jsr getc
+ jsr io.getc
;; The following scenario
;; can be created by the plys
;; X -> 1
;; O -> 5
;; X -> 9
jsr computer_perfect_init
- #STORE_WORD main_board,board_ptr
+ #mem.STORE_WORD main_board,board_ptr
#SET_FIELD piece_x, 0
#SET_FIELD piece_o, 4
#SET_FIELD piece_x, 8
- #PRINTNL
+ jsr io.putnl
pha
jsr print_board
pla
lda #piece_o
jsr computer_perfect_ply
pha
- #PRINTNL
+ jsr io.putnl
jsr print_board
pla
;; Check for correct ply
#GET_FIELD main_board,3
#CHECK_ERROR piece_o
- jsr getc
+ jsr io.getc
rts
;; The following scenario
;; can be created by the plys
@@ -415,70 +415,70 @@ test_block_fork:
;; O -> 1
;; X -> 9
jsr computer_perfect_init
- #STORE_WORD main_board,board_ptr
+ #mem.STORE_WORD main_board,board_ptr
#SET_FIELD piece_x, 4
#SET_FIELD piece_o, 0
#SET_FIELD piece_x, 8
- #PRINTNL
+ jsr io.putnl
pha
jsr print_board
pla
lda #piece_o
jsr computer_perfect_ply
pha
- #PRINTNL
+ jsr io.putnl
jsr print_board
pla
;; Check for correct ply
#GET_FIELD main_board,2
#CHECK_ERROR piece_o
- jsr getc
+ jsr io.getc
rts
.bend
test_play_opposite_corner:
.block
jsr computer_perfect_init
- #STORE_WORD main_board,board_ptr
+ #mem.STORE_WORD main_board,board_ptr
#SET_FIELD piece_x, 0
#SET_FIELD piece_o, 4
- #PRINTNL
+ jsr io.putnl
pha
jsr print_board
pla
lda #piece_o
jsr computer_perfect_ply
pha
- #PRINTNL
+ jsr io.putnl
jsr print_board
pla
;; Check for correct ply
#GET_FIELD main_board,8
#CHECK_ERROR piece_o
- jsr getc
+ jsr io.getc
rts
.bend
test_play_empty_corner:
.block
jsr computer_perfect_init
- #STORE_WORD main_board,board_ptr
+ #mem.STORE_WORD main_board,board_ptr
#SET_FIELD piece_x, 4
#SET_FIELD piece_o, 0
- #PRINTNL
+ jsr io.putnl
pha
jsr print_board
pla
lda #piece_o
jsr computer_perfect_ply
pha
- #PRINTNL
+ jsr io.putnl
jsr print_board
pla
;; Check for correct ply
#GET_FIELD main_board,2
#CHECK_ERROR piece_o
- jsr getc
+ jsr io.getc
rts
.bend
@@ -486,16 +486,16 @@ test_perfect_vs_random_computer_player:
.block
game_loop:
;; Set player X
- #STORE_WORD computer_perfect_init, player_x_init_ptr
- #STORE_WORD computer_perfect_ply, player_x_ply_ptr
+ #mem.STORE_WORD computer_perfect_init, player_x_init_ptr
+ #mem.STORE_WORD computer_perfect_ply, player_x_ply_ptr
;; Set player O
- #STORE_WORD computer_random_init, player_o_init_ptr
- #STORE_WORD computer_random_ply, player_o_ply_ptr
+ #mem.STORE_WORD computer_random_init, player_o_init_ptr
+ #mem.STORE_WORD computer_random_ply, player_o_ply_ptr
jsr play_game
jsr get_game_state
cmp #piece_o ; Random player
bne game_loop ; Should never win
- #PRINTSNL 'Error'
+ #io.PRINTSNL 'Error'
error:
jmp error
.bend
@@ -503,16 +503,16 @@ test_random_vs_perfect_computer_player:
.block
game_loop:
;; Set player X
- #STORE_WORD computer_random_init, player_x_init_ptr
- #STORE_WORD computer_random_ply, player_x_ply_ptr
+ #mem.STORE_WORD computer_random_init, player_x_init_ptr
+ #mem.STORE_WORD computer_random_ply, player_x_ply_ptr
;; Set player O
- #STORE_WORD computer_perfect_init, player_o_init_ptr
- #STORE_WORD computer_perfect_ply, player_o_ply_ptr
+ #mem.STORE_WORD computer_perfect_init, player_o_init_ptr
+ #mem.STORE_WORD computer_perfect_ply, player_o_ply_ptr
jsr play_game
jsr get_game_state
cmp #piece_x ; Random player
bne game_loop ; Should never win
- #PRINTSNL 'Error'
+ #io.PRINTSNL 'Error'
error:
jmp error
.bend
@@ -520,16 +520,16 @@ test_perfect_vs_perfect_computer_player:
.block
game_loop:
;; Set player X
- #STORE_WORD computer_perfect_init, player_x_init_ptr
- #STORE_WORD computer_perfect_ply, player_x_ply_ptr
+ #mem.STORE_WORD computer_perfect_init, player_x_init_ptr
+ #mem.STORE_WORD computer_perfect_ply, player_x_ply_ptr
;; Set player O
- #STORE_WORD computer_perfect_init, player_o_init_ptr
- #STORE_WORD computer_perfect_ply, player_o_ply_ptr
+ #mem.STORE_WORD computer_perfect_init, player_o_init_ptr
+ #mem.STORE_WORD computer_perfect_ply, player_o_ply_ptr
jsr play_game
jsr get_game_state
cmp #piece_none ; All games should end in
beq game_loop ; a draw.
- #PRINTSNL 'Error'
+ #io.PRINTSNL 'Error'
error:
jmp error
.bend
@@ -541,13 +541,13 @@ print_random_ply:
phx
clc
adc #'0'
- jsr putc
- #PRINTS ' plays '
+ jsr io.putc
+ #io.PRINTS ' plays '
pla
pha
adc #'0'
- jsr putc
- #PRINTNL
+ jsr io.putc
+ jsr io.putnl
plx
pla
rts
@@ -561,21 +561,21 @@ print_ply:
phx
clc
adc #'0'
- jsr putc
- #PRINTS ' plays '
+ jsr io.putc
+ #io.PRINTS ' plays '
pla
pha
adc #'0'
- jsr putc
+ jsr io.putc
lda #'/'
- jsr putc
+ jsr io.putc
plx
pla
pha
phx
adc #'0'
- jsr putc
- #PRINTNL
+ jsr io.putc
+ jsr io.putnl
plx
ply
pla
diff --git a/sw/ttt/human_player.asm b/sw/ttt/human_player.asm
@@ -12,17 +12,17 @@ human_player_ply:
pha
jsr print_board
;; Print question for move
- #PRINTS "Player "
+ #io.PRINTS "Player "
pla
pha
clc
adc #'0'
- jsr putc
- #PRINTS ": "
+ jsr io.putc
+ #io.PRINTS ": "
;; Get move and check
;; if move is valid.
- jsr getc
- jsr putc
+ jsr io.getc
+ jsr io.putc
;; Check if user input
;; is in range [1..9]
cmp #"1"
@@ -38,16 +38,16 @@ human_player_ply:
jsr get_field
cmp #piece_none
bne invalid
- #PRINTNL
- #PRINTNL
+ jsr io.putnl
+ jsr io.putnl
;; Set the piece
ldx tmp ; Field number
pla ; Piece
jsr set_field
rts
invalid:
- #PRINTNL
- #PRINTSNL "Not a valid move."
+ jsr io.putnl
+ #io.PRINTSNL "Not a valid move."
pla
jmp human_player_ply
.bend
diff --git a/sw/ttt/ttt.asm b/sw/ttt/ttt.asm
@@ -1,30 +1,9 @@
;;; If we are included in boot.asm, we
;;; should not set the start address
-.weak
- BOOT_EMBEDDED = false
-.endweak
-.if BOOT_EMBEDDED
- init_acia = export.init_acia
- lfsr_init = export.lfsr_init
- lfsr_step = export.lfsr_step
- lfsr_state = export.lfsr_state
- getc = export.getc
- getc_seed_rng = export.getc_seed_rng
- putc = export.putc
-.else
- .if SYMON
- .include "boot_symon.l"
- start_address = $0300
- .else
- .include "boot.l"
- start_address = $0200
- .endif
+
.include "boot.inc"
- * = rom_zero_page_end
- .dsection zero_page
- * = start_address
-.endif
-.dsection ttt_game
+
+ .dsection ttt_game
.section zero_page
;; This temporary variable is used all over the place
@@ -67,14 +46,14 @@ board_ascii: .byte ?, ?, ?, ?, ?, ?, ?, ?, ?
start_ttt:
.block
cld
- jsr init_acia
- jsr lfsr_init
+ jsr io.init_acia
+ jsr lfsr.init
.if RUN_TESTS
jsr run_tests
.endif
game_loop:
- #PRINTSNL '** Tic-Tac-Toe **'
- #PRINTNL
+ #io.PRINTSNL '** Tic-Tac-Toe **'
+ jsr io.putnl
lda #piece_x
jsr choose_player
lda #piece_o
@@ -87,17 +66,17 @@ game_loop:
choose_player:
.block
pha
- #PRINTS "Choose player "
+ #io.PRINTS "Choose player "
pla
pha
clc
adc #'0'
- jsr putc
- #PRINTSNL ':'
- #PRINTSNL '1 - Human'
- #PRINTSNL '2 - Computer (perfect)'
- #PRINTSNL '3 - Computer (random)'
- jsr getc_seed_rng
+ jsr io.putc
+ #io.PRINTSNL ':'
+ #io.PRINTSNL '1 - Human'
+ #io.PRINTSNL '2 - Computer (perfect)'
+ #io.PRINTSNL '3 - Computer (random)'
+ jsr io.getc_seed_rng
cmp #'1'
beq set_human_player
cmp #'2'
@@ -111,16 +90,16 @@ choose_player:
;; board_ptr to store a temporary
;; variable.
set_human_player:
- #STORE_WORD human_player_init, tmp
- #STORE_WORD human_player_ply, board_ptr
+ #mem.STORE_WORD human_player_init, tmp
+ #mem.STORE_WORD human_player_ply, board_ptr
jmp set_player
set_computer_perfect_player:
- #STORE_WORD computer_perfect_init, tmp
- #STORE_WORD computer_perfect_ply, board_ptr
+ #mem.STORE_WORD computer_perfect_init, tmp
+ #mem.STORE_WORD computer_perfect_ply, board_ptr
jmp set_player
set_computer_random_player:
- #STORE_WORD computer_random_init, tmp
- #STORE_WORD computer_random_ply, board_ptr
+ #mem.STORE_WORD computer_random_init, tmp
+ #mem.STORE_WORD computer_random_ply, board_ptr
set_player:
pla
cmp #piece_x
@@ -158,12 +137,12 @@ set_second_player:
.include "computer_player_test.asm"
run_tests:
;; jsr game_board_test
- ;; #PRINTNL
+ ;; jsr io.putnl
;; jsr getc
;; jsr mirror_board_test
jsr computer_player_test
- #PRINTNL
- jsr getc
+ jsr io.putnl
+ jsr io.getc
jmp run_tests
.endif
diff --git a/sw/via_test/via_test.asm b/sw/via_test/via_test.asm
@@ -1,44 +1,36 @@
;;; Connect LEDs to the 65C22 and enjoy some blinkenlights
-.if SYMON
- .include "boot_symon.l"
-.else
- .include "boot.l"
-.endif
.include "boot.inc"
- * = $200
.dsection code
- .cerror * > $8000, "RAM exhausted"
-
.section code
init:
.block
cld
- jsr init_acia
- jsr getc
- PRINTSNL "VIA Test"
+ jsr io.init_acia
+ jsr io.getc
+ #io.PRINTSNL "VIA Test"
;; Configure all ports of A as input
lda #$00
- sta via_ddra
+ sta io.via_ddra
;; Configure all ports of B as output
lda #$ff
- sta via_ddrb
+ sta io.via_ddrb
loop: jsr read_and_write_via
jmp loop
.bend
read_and_write_via:
.block
- inc via_orb
- PRINTS "IRA: "
- lda via_ira
- jsr puth
+ inc io.via_orb
+ #io.PRINTS "IRA: "
+ lda io.via_ira
+ jsr io.puth
lda #" "
- jsr putc
- PRINTS "IRB: "
- lda via_irb
- jsr puth
- PRINTNL
+ jsr io.putc
+ #io.PRINTS "IRB: "
+ lda io.via_irb
+ jsr io.puth
+ jsr io.putnl
ldx #$00
ldy #$00
delay:
diff --git a/tools/boot.py b/tools/boot.py
@@ -11,7 +11,7 @@ import os
SERIAL_PORT = '/dev/ttyUSB0'
SERIAL_SPEED = 19200
-# File upload does not work if GATE is run 100 kHz clock frequency
+# File upload does not work if Eris 2010 is run 100 kHz clock frequency
# unless SLOW_CPU is set.
SLOW_CPU = False
# SLOW_CPU = True
diff --git a/tools/gfs.py b/tools/gfs.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-"""Access GATE2010 filesystem"""
+"""Access Eris 2010 filesystem"""
import os
import argparse
@@ -66,7 +66,7 @@ class GFS:
if number_of_blocks > 0:
end = b[1:].find(b'\x00')
filename = b[1:end+1]
- print("{filenumber}: {filename} (0x{blocks:X} blocks)".
+ print("{filenumber}: {filename} ({blocks} blocks)".
format(filenumber=a, filename=filename.decode('utf-8'),
blocks=number_of_blocks))