mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-26 09:28:05 +11:00
Compare commits
No commits in common. "69daf49920c77821c78b747bb59ea5e3ad0409ac" and "8a696a1e23cc94f4db71489cfb39d0cf9e2747a8" have entirely different histories.
69daf49920
...
8a696a1e23
16
TRICKS.txt
16
TRICKS.txt
@ -1,5 +1,5 @@
|
|||||||
This file describe tricks and conventions that are used throughout the code and
|
This file describe tricks that are used throughout the code and might need
|
||||||
might need explanation.
|
explanation.
|
||||||
|
|
||||||
or a: Equivalent to "cp 0", but results in a shorter opcode.
|
or a: Equivalent to "cp 0", but results in a shorter opcode.
|
||||||
|
|
||||||
@ -13,15 +13,3 @@ Reset for failure. "xor a" (destroys A) and "cp a" (preserves A) are used to
|
|||||||
ensure Z is set. To ensure that it is reset, it's a bit more complicated and
|
ensure Z is set. To ensure that it is reset, it's a bit more complicated and
|
||||||
"unsetZ" routine exists for that, although that in certain circumstances,
|
"unsetZ" routine exists for that, although that in certain circumstances,
|
||||||
"inc a \ dec a" or "or a" can work.
|
"inc a \ dec a" or "or a" can work.
|
||||||
|
|
||||||
z80 is little endian in its 16-bit loading operations. For example, "ld hl, (0)"
|
|
||||||
will load the contents of memory address 0 in L and memory address 1 in H. This
|
|
||||||
little-endianess is followed by Collapse OS in most situations. When it's not,
|
|
||||||
it's specified in comments.
|
|
||||||
|
|
||||||
This get a bit awkward with regards to 32-bit. There are no "native" z80 32-bit
|
|
||||||
operations, so z80 doesn't mandate an alignment. In Collapse OS, 32-bit numbers
|
|
||||||
are stored as "big endian pair of little endian 16-bit numbers". For example,
|
|
||||||
if "ld dehl, (0)" existed and if the first 4 bytes of memory were 0x01, 0x02,
|
|
||||||
0x03 and 0x04, then DE (being the "high" word) would be 0x0201 and HL would be
|
|
||||||
0x0403.
|
|
||||||
|
@ -7,43 +7,47 @@ look like:
|
|||||||
|
|
||||||
|
|
||||||
; The RAM module is selected on A15, so it has the range 0x8000-0xffff
|
; The RAM module is selected on A15, so it has the range 0x8000-0xffff
|
||||||
.equ RAMSTART 0x8000
|
.equ RAMSTART 0x8000
|
||||||
.equ RAMEND 0xffff
|
.equ RAMEND 0xffff
|
||||||
.equ ACIA_CTL 0x80 ; Control and status. RS off.
|
.equ ACIA_CTL 0x80 ; Control and status. RS off.
|
||||||
.equ ACIA_IO 0x81 ; Transmit. RS on.
|
.equ ACIA_IO 0x81 ; Transmit. RS on.
|
||||||
|
|
||||||
jp init
|
jr init
|
||||||
|
|
||||||
; interrupt hook
|
; interrupt hook
|
||||||
.fill 0x38-$
|
.fill 0x38-$
|
||||||
jp aciaInt
|
jp aciaInt
|
||||||
|
|
||||||
.inc "err.h"
|
|
||||||
.inc "core.asm"
|
|
||||||
.inc "parse.asm"
|
|
||||||
.equ ACIA_RAMSTART RAMSTART
|
|
||||||
.inc "acia.asm"
|
|
||||||
|
|
||||||
.equ STDIO_RAMSTART ACIA_RAMEND
|
|
||||||
.equ STDIO_GETC aciaGetC
|
|
||||||
.equ STDIO_PUTC aciaPutC
|
|
||||||
.inc "stdio.asm"
|
|
||||||
|
|
||||||
.equ SHELL_RAMSTART STDIO_RAMEND
|
|
||||||
.equ SHELL_EXTRA_CMD_COUNT 0
|
|
||||||
.inc "shell.asm"
|
|
||||||
|
|
||||||
init:
|
init:
|
||||||
di
|
di
|
||||||
; setup stack
|
; setup stack
|
||||||
ld hl, RAMEND
|
ld hl, RAMEND
|
||||||
ld sp, hl
|
ld sp, hl
|
||||||
im 1
|
im 1
|
||||||
|
call aciaInit
|
||||||
call aciaInit
|
xor a
|
||||||
call shellInit
|
ld de, BLOCKDEV_SEL
|
||||||
|
call blkSel
|
||||||
|
call stdioInit
|
||||||
|
call shellInit
|
||||||
ei
|
ei
|
||||||
jp shellLoop
|
jp shellLoop
|
||||||
|
|
||||||
|
#include "core.asm"
|
||||||
|
.equ ACIA_RAMSTART RAMSTART
|
||||||
|
#include "acia.asm"
|
||||||
|
.equ BLOCKDEV_RAMSTART ACIA_RAMEND
|
||||||
|
.equ BLOCKDEV_COUNT 1
|
||||||
|
#include "blockdev.asm"
|
||||||
|
; List of devices
|
||||||
|
.dw aciaGetC, aciaPutC, 0, 0
|
||||||
|
|
||||||
|
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
||||||
|
#include "stdio.asm"
|
||||||
|
|
||||||
|
.equ SHELL_RAMSTART STDIO_RAMEND
|
||||||
|
.equ SHELL_EXTRA_CMD_COUNT 0
|
||||||
|
#include "shell.asm"
|
||||||
|
|
||||||
Once this is written, building it is easy:
|
Once this is written, building it is easy:
|
||||||
|
|
||||||
|
@ -98,17 +98,17 @@ aciaInt:
|
|||||||
reti
|
reti
|
||||||
|
|
||||||
|
|
||||||
; *** STDIO ***
|
; *** BLOCKDEV ***
|
||||||
; These function below follow the stdio API.
|
; These function below follow the blockdev API.
|
||||||
|
|
||||||
aciaGetC:
|
aciaGetC:
|
||||||
push de
|
push de
|
||||||
.loop:
|
|
||||||
ld a, (ACIA_BUFWRIDX)
|
ld a, (ACIA_BUFWRIDX)
|
||||||
ld e, a
|
ld e, a
|
||||||
ld a, (ACIA_BUFRDIDX)
|
ld a, (ACIA_BUFRDIDX)
|
||||||
cp e
|
cp e
|
||||||
jr z, .loop ; equal? nothing to read. loop
|
jr z, .nothingToRead ; equal? nothing to read.
|
||||||
|
|
||||||
; Alrighty, buffer not empty. let's read.
|
; Alrighty, buffer not empty. let's read.
|
||||||
ld de, ACIA_BUF
|
ld de, ACIA_BUF
|
||||||
@ -120,6 +120,12 @@ aciaGetC:
|
|||||||
|
|
||||||
; And finally, fetch the value.
|
; And finally, fetch the value.
|
||||||
ld a, (de)
|
ld a, (de)
|
||||||
|
cp a ; ensure Z
|
||||||
|
jr .end
|
||||||
|
|
||||||
|
.nothingToRead:
|
||||||
|
call unsetZ
|
||||||
|
.end:
|
||||||
pop de
|
pop de
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
@ -35,10 +35,6 @@
|
|||||||
; number of entries in shellCmdTbl
|
; number of entries in shellCmdTbl
|
||||||
.equ SHELL_CMD_COUNT 6+SHELL_EXTRA_CMD_COUNT
|
.equ SHELL_CMD_COUNT 6+SHELL_EXTRA_CMD_COUNT
|
||||||
|
|
||||||
; maximum length for shell commands. Should be confortably below stdio's
|
|
||||||
; readline buffer length.
|
|
||||||
.equ SHELL_MAX_CMD_LEN 0x10
|
|
||||||
|
|
||||||
; *** VARIABLES ***
|
; *** VARIABLES ***
|
||||||
; Memory address that the shell is currently "pointing at" for peek, load, call
|
; Memory address that the shell is currently "pointing at" for peek, load, call
|
||||||
; operations. Set with mptr.
|
; operations. Set with mptr.
|
||||||
@ -46,12 +42,14 @@
|
|||||||
|
|
||||||
; Places where we store arguments specifiers and where resulting values are
|
; Places where we store arguments specifiers and where resulting values are
|
||||||
; written to after parsing.
|
; written to after parsing.
|
||||||
.equ SHELL_CMD_ARGS @+2
|
.equ SHELL_CMD_ARGS SHELL_MEM_PTR+2
|
||||||
|
|
||||||
; Pointer to a hook to call when a cmd name isn't found
|
; Pointer to a hook to call when a cmd name isn't found
|
||||||
.equ SHELL_CMDHOOK @+PARSE_ARG_MAXCOUNT
|
.equ SHELL_CMDHOOK SHELL_CMD_ARGS+PARSE_ARG_MAXCOUNT
|
||||||
|
|
||||||
.equ SHELL_RAMEND @+2
|
; Pointer to a routine to call at each shell loop iteration
|
||||||
|
.equ SHELL_LOOPHOOK SHELL_CMDHOOK+2
|
||||||
|
.equ SHELL_RAMEND SHELL_LOOPHOOK+2
|
||||||
|
|
||||||
; *** CODE ***
|
; *** CODE ***
|
||||||
shellInit:
|
shellInit:
|
||||||
@ -60,6 +58,7 @@ shellInit:
|
|||||||
ld (SHELL_MEM_PTR+1), a
|
ld (SHELL_MEM_PTR+1), a
|
||||||
ld hl, noop
|
ld hl, noop
|
||||||
ld (SHELL_CMDHOOK), hl
|
ld (SHELL_CMDHOOK), hl
|
||||||
|
ld (SHELL_LOOPHOOK), hl
|
||||||
|
|
||||||
; print welcome
|
; print welcome
|
||||||
ld hl, .welcome
|
ld hl, .welcome
|
||||||
@ -71,8 +70,15 @@ shellInit:
|
|||||||
; Inifite loop that processes input. Because it's infinite, you should jump
|
; Inifite loop that processes input. Because it's infinite, you should jump
|
||||||
; to it rather than call it. Saves two precious bytes in the stack.
|
; to it rather than call it. Saves two precious bytes in the stack.
|
||||||
shellLoop:
|
shellLoop:
|
||||||
call stdioReadLine
|
; First, call the loop hook
|
||||||
|
ld ix, (SHELL_LOOPHOOK)
|
||||||
|
call callIX
|
||||||
|
; Then, let's wait until something is typed.
|
||||||
|
call stdioReadC
|
||||||
|
jr nz, shellLoop ; not done? loop
|
||||||
|
; We're done. Process line.
|
||||||
call printcrlf
|
call printcrlf
|
||||||
|
call stdioGetLine
|
||||||
call shellParse
|
call shellParse
|
||||||
ld hl, .prompt
|
ld hl, .prompt
|
||||||
call printstr
|
call printstr
|
||||||
@ -86,7 +92,7 @@ shellParse:
|
|||||||
; first thing: is command empty?
|
; first thing: is command empty?
|
||||||
ld a, (hl)
|
ld a, (hl)
|
||||||
or a
|
or a
|
||||||
ret z ; empty, nothing to do
|
ret z ; empty, nthing to do
|
||||||
|
|
||||||
push af
|
push af
|
||||||
push bc
|
push bc
|
||||||
@ -104,13 +110,6 @@ shellParse:
|
|||||||
; no arg, (HL) is zero to facilitate processing later, add a second
|
; no arg, (HL) is zero to facilitate processing later, add a second
|
||||||
; null next to that one to indicate unambiguously that we have no args.
|
; null next to that one to indicate unambiguously that we have no args.
|
||||||
inc hl
|
inc hl
|
||||||
; Oh wait, before we proceed, is our cmd length within limits? cmd len
|
|
||||||
; is currently in A from findchar
|
|
||||||
cp SHELL_MAX_CMD_LEN
|
|
||||||
jr c, .hasArgs ; within limits
|
|
||||||
; outside limits
|
|
||||||
ld a, SHELL_ERR_UNKNOWN_CMD
|
|
||||||
jr .error
|
|
||||||
.hasArgs:
|
.hasArgs:
|
||||||
xor a
|
xor a
|
||||||
ld (hl), a
|
ld (hl), a
|
||||||
|
@ -11,9 +11,6 @@
|
|||||||
; The space character is the first among special chars.
|
; The space character is the first among special chars.
|
||||||
; * C confirms letter selection
|
; * C confirms letter selection
|
||||||
;
|
;
|
||||||
; This module is currently hard-wired to sms/vdp, that is, it calls vdp's
|
|
||||||
; routines during padGetC to update character selection.
|
|
||||||
;
|
|
||||||
; *** Consts ***
|
; *** Consts ***
|
||||||
;
|
;
|
||||||
.equ PAD_CTLPORT 0x3f
|
.equ PAD_CTLPORT 0x3f
|
||||||
@ -32,18 +29,21 @@
|
|||||||
;
|
;
|
||||||
; Button status of last padUpdateSel call. Used for debouncing.
|
; Button status of last padUpdateSel call. Used for debouncing.
|
||||||
.equ PAD_SELSTAT PAD_RAMSTART
|
.equ PAD_SELSTAT PAD_RAMSTART
|
||||||
|
; Button status of last padGetC call.
|
||||||
|
.equ PAD_GETCSTAT PAD_SELSTAT+1
|
||||||
; Current selected character
|
; Current selected character
|
||||||
.equ PAD_SELCHR @+1
|
.equ PAD_SELCHR PAD_GETCSTAT+1
|
||||||
; When non-zero, will be the next char returned in GetC. So far, only used for
|
; When non-zero, will be the next char returned in GetC. So far, only used for
|
||||||
; LF that is feeded when Start is pressed.
|
; LF that is feeded when Start is pressed.
|
||||||
.equ PAD_NEXTCHR @+1
|
.equ PAD_NEXTCHR PAD_SELCHR+1
|
||||||
.equ PAD_RAMEND @+1
|
.equ PAD_RAMEND PAD_NEXTCHR+1
|
||||||
|
|
||||||
; *** Code ***
|
; *** Code ***
|
||||||
|
|
||||||
padInit:
|
padInit:
|
||||||
ld a, 0xff
|
ld a, 0xff
|
||||||
ld (PAD_SELSTAT), a
|
ld (PAD_SELSTAT), a
|
||||||
|
ld (PAD_GETCSTAT), a
|
||||||
xor a
|
xor a
|
||||||
ld (PAD_NEXTCHR), a
|
ld (PAD_NEXTCHR), a
|
||||||
ld a, 'a'
|
ld a, 'a'
|
||||||
@ -78,14 +78,14 @@ padStatus:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
; From a pad status in A, update current char selection and return it.
|
; From a pad status in A, update current char selection and return it.
|
||||||
; Sets Z if current selection was unchanged, unset if changed.
|
; Returns the same Z as padStatus: set if unchanged, unset if changed
|
||||||
padUpdateSel:
|
padUpdateSel:
|
||||||
call padStatus
|
call padStatus
|
||||||
push hl ; --> lvl 1
|
push hl
|
||||||
ld hl, PAD_SELSTAT
|
ld hl, PAD_SELSTAT
|
||||||
cp (hl)
|
cp (hl)
|
||||||
ld (hl), a
|
ld (hl), a
|
||||||
pop hl ; <-- lvl 1
|
pop hl
|
||||||
jr z, .nothing ; nothing changed
|
jr z, .nothing ; nothing changed
|
||||||
bit PAD_UP, a
|
bit PAD_UP, a
|
||||||
jr z, .up
|
jr z, .up
|
||||||
@ -156,51 +156,45 @@ padUpdateSel:
|
|||||||
ld (PAD_SELCHR), a
|
ld (PAD_SELCHR), a
|
||||||
jp unsetZ
|
jp unsetZ
|
||||||
.nothing:
|
.nothing:
|
||||||
; Z already set
|
cp a ; ensure Z
|
||||||
ld a, (PAD_SELCHR)
|
ld a, (PAD_SELCHR)
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Repeatedly poll the pad for input and returns the resulting "input char".
|
|
||||||
; This routine takes a long time to return because it waits until C, B or Start
|
|
||||||
; was pressed. Until this is done, this routine takes care of updating the
|
|
||||||
; "current selection" directly in the VDP.
|
|
||||||
padGetC:
|
padGetC:
|
||||||
ld a, (PAD_NEXTCHR)
|
ld a, (PAD_NEXTCHR)
|
||||||
or a
|
or a
|
||||||
jr nz, .nextchr
|
jr nz, .nextchr
|
||||||
call padUpdateSel
|
call padStatus
|
||||||
jp z, padGetC ; nothing changed, loop
|
push hl
|
||||||
; pad status was changed, let's see if an action button was pressed
|
ld hl, PAD_GETCSTAT
|
||||||
ld a, (PAD_SELSTAT)
|
cp (hl)
|
||||||
|
ld (hl), a
|
||||||
|
pop hl
|
||||||
|
jp z, unsetZ ; nothing changed
|
||||||
bit PAD_BUTC, a
|
bit PAD_BUTC, a
|
||||||
jr z, .advance
|
jr z, .advance
|
||||||
bit PAD_BUTA, a
|
bit PAD_BUTA, a
|
||||||
jr z, .backspace
|
jr z, .backspace
|
||||||
bit PAD_START, a
|
bit PAD_START, a
|
||||||
jr z, .return
|
jr z, .return
|
||||||
; no action button pressed, but because our pad status changed, update
|
jp unsetZ
|
||||||
; VDP before looping.
|
|
||||||
ld a, (PAD_SELCHR)
|
|
||||||
call vdpConv
|
|
||||||
call vdpSpitC
|
|
||||||
jp padGetC
|
|
||||||
.return:
|
.return:
|
||||||
ld a, ASCII_LF
|
ld a, ASCII_LF
|
||||||
ld (PAD_NEXTCHR), a
|
ld (PAD_NEXTCHR), a
|
||||||
; continue to .advance
|
; continue to .advance
|
||||||
.advance:
|
.advance:
|
||||||
ld a, (PAD_SELCHR)
|
ld a, (PAD_SELCHR)
|
||||||
; Z was already set from previous BIT instruction
|
cp a
|
||||||
ret
|
ret
|
||||||
.backspace:
|
.backspace:
|
||||||
ld a, ASCII_BS
|
ld a, ASCII_BS
|
||||||
; Z was already set from previous BIT instruction
|
cp a
|
||||||
ret
|
ret
|
||||||
.nextchr:
|
.nextchr:
|
||||||
; We have a "next char", return it and clear it.
|
; We have a "next char", return it and clear it.
|
||||||
cp a ; ensure Z
|
cp a ; ensure Z
|
||||||
ex af, af'
|
push af
|
||||||
xor a
|
xor a
|
||||||
ld (PAD_NEXTCHR), a
|
ld (PAD_NEXTCHR), a
|
||||||
ex af, af'
|
pop af
|
||||||
ret
|
ret
|
||||||
|
@ -21,8 +21,11 @@
|
|||||||
; Row of cursor
|
; Row of cursor
|
||||||
.equ VDP_ROW VDP_RAMSTART
|
.equ VDP_ROW VDP_RAMSTART
|
||||||
; Line of cursor
|
; Line of cursor
|
||||||
.equ VDP_LINE @+1
|
.equ VDP_LINE VDP_ROW+1
|
||||||
.equ VDP_RAMEND @+1
|
; Returns, in A, the currently selected char in a "pad char selection" scheme.
|
||||||
|
.equ VDP_CHRSELHOOK VDP_LINE+1
|
||||||
|
.equ VDP_LASTSEL VDP_CHRSELHOOK+2
|
||||||
|
.equ VDP_RAMEND VDP_LASTSEL+1
|
||||||
|
|
||||||
; *** Code ***
|
; *** Code ***
|
||||||
|
|
||||||
@ -30,6 +33,9 @@ vdpInit:
|
|||||||
xor a
|
xor a
|
||||||
ld (VDP_ROW), a
|
ld (VDP_ROW), a
|
||||||
ld (VDP_LINE), a
|
ld (VDP_LINE), a
|
||||||
|
ld (VDP_LASTSEL), a
|
||||||
|
ld hl, noop
|
||||||
|
ld (VDP_CHRSELHOOK), hl
|
||||||
|
|
||||||
ld hl, vdpInitData
|
ld hl, vdpInitData
|
||||||
ld b, vdpInitDataEnd-vdpInitData
|
ld b, vdpInitDataEnd-vdpInitData
|
||||||
@ -115,6 +121,12 @@ vdpSpitC:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
vdpPutC:
|
vdpPutC:
|
||||||
|
; First, let's invalidate last sel
|
||||||
|
ex af, af'
|
||||||
|
xor a
|
||||||
|
ld (VDP_LASTSEL), a
|
||||||
|
ex af, af'
|
||||||
|
|
||||||
; Then, let's place our cursor. We need to first send our LSB, whose
|
; Then, let's place our cursor. We need to first send our LSB, whose
|
||||||
; 6 low bits contain our row*2 (each tile is 2 bytes wide) and high
|
; 6 low bits contain our row*2 (each tile is 2 bytes wide) and high
|
||||||
; 2 bits are the two low bits of our line
|
; 2 bits are the two low bits of our line
|
||||||
@ -255,6 +267,26 @@ vdpConv:
|
|||||||
ld a, 0x5e
|
ld a, 0x5e
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
; During the shell loop, updates the currently selected char, if appropriate
|
||||||
|
vdpShellLoopHook:
|
||||||
|
push af
|
||||||
|
push ix
|
||||||
|
push hl
|
||||||
|
xor a
|
||||||
|
ld ix, (VDP_CHRSELHOOK)
|
||||||
|
call callIX
|
||||||
|
ld hl, VDP_LASTSEL
|
||||||
|
cp (hl)
|
||||||
|
jr z, .noChange
|
||||||
|
; selection changed
|
||||||
|
call vdpConv
|
||||||
|
call vdpSpitC
|
||||||
|
.noChange:
|
||||||
|
pop hl
|
||||||
|
pop ix
|
||||||
|
pop af
|
||||||
|
ret
|
||||||
|
|
||||||
vdpPaletteData:
|
vdpPaletteData:
|
||||||
.db 0x00,0x3f
|
.db 0x00,0x3f
|
||||||
vdpPaletteDataEnd:
|
vdpPaletteDataEnd:
|
||||||
|
164
kernel/stdio.asm
164
kernel/stdio.asm
@ -4,26 +4,6 @@
|
|||||||
; in", that is, the console through which the user is connected in a decoupled
|
; in", that is, the console through which the user is connected in a decoupled
|
||||||
; manner.
|
; manner.
|
||||||
;
|
;
|
||||||
; Those GetC/PutC routines are hooked through defines and have this API:
|
|
||||||
;
|
|
||||||
; GetC: Blocks until a character is read from the device and return that
|
|
||||||
; character in A.
|
|
||||||
;
|
|
||||||
; PutC: Write character specified in A onto the device.
|
|
||||||
;
|
|
||||||
; *** Accepted characters ***
|
|
||||||
;
|
|
||||||
; For now, we're in muddy waters in this regard. We try to stay close to ASCII.
|
|
||||||
; Anything over 0x7f is undefined. Both CR and LF are interpreted as "line end".
|
|
||||||
; Both BS and DEL mean "delete previous character".
|
|
||||||
;
|
|
||||||
; When outputting, newlines are marked by CR and LF. Outputting a character
|
|
||||||
; deletion is made through BS then space then BS.
|
|
||||||
;
|
|
||||||
; *** Defines ***
|
|
||||||
; STDIO_GETC: address of a GetC routine
|
|
||||||
; STDIO_PUTC: address of a PutC routine
|
|
||||||
;
|
|
||||||
; *** Consts ***
|
; *** Consts ***
|
||||||
; Size of the readline buffer. If a typed line reaches this size, the line is
|
; Size of the readline buffer. If a typed line reaches this size, the line is
|
||||||
; flushed immediately (same as pressing return).
|
; flushed immediately (same as pressing return).
|
||||||
@ -32,19 +12,34 @@
|
|||||||
; *** Variables ***
|
; *** Variables ***
|
||||||
; Used to store formatted hex values just before printing it.
|
; Used to store formatted hex values just before printing it.
|
||||||
.equ STDIO_HEX_FMT STDIO_RAMSTART
|
.equ STDIO_HEX_FMT STDIO_RAMSTART
|
||||||
|
.equ STDIO_GETC STDIO_HEX_FMT+2
|
||||||
|
.equ STDIO_PUTC STDIO_GETC+2
|
||||||
|
|
||||||
; Line buffer. We read types chars into this buffer until return is pressed
|
; Line buffer. We read types chars into this buffer until return is pressed
|
||||||
; This buffer is null-terminated.
|
; This buffer is null-terminated and we don't keep an index around: we look
|
||||||
.equ STDIO_BUF @+2
|
; for the null-termination every time we write to it. Simpler that way.
|
||||||
|
.equ STDIO_BUF STDIO_PUTC+2
|
||||||
|
|
||||||
; Index where the next char will go in stdioGetC.
|
; Index where the next char will go in stdioGetC.
|
||||||
.equ STDIO_RAMEND @+STDIO_BUFSIZE
|
.equ STDIO_BUFIDX STDIO_BUF+STDIO_BUFSIZE
|
||||||
|
.equ STDIO_RAMEND STDIO_BUFIDX+1
|
||||||
|
|
||||||
|
; Sets GetC to the routine where HL points to and PutC to DE.
|
||||||
|
stdioInit:
|
||||||
|
ld (STDIO_GETC), hl
|
||||||
|
ld (STDIO_PUTC), de
|
||||||
|
xor a
|
||||||
|
ld (STDIO_BUF), a
|
||||||
|
ld (STDIO_BUFIDX), a
|
||||||
|
ret
|
||||||
|
|
||||||
stdioGetC:
|
stdioGetC:
|
||||||
jp STDIO_GETC
|
ld ix, (STDIO_GETC)
|
||||||
|
jp (ix)
|
||||||
|
|
||||||
stdioPutC:
|
stdioPutC:
|
||||||
jp STDIO_PUTC
|
ld ix, (STDIO_PUTC)
|
||||||
|
jp (ix)
|
||||||
|
|
||||||
; print null-terminated string pointed to by HL
|
; print null-terminated string pointed to by HL
|
||||||
printstr:
|
printstr:
|
||||||
@ -55,7 +50,7 @@ printstr:
|
|||||||
ld a, (hl) ; load character to send
|
ld a, (hl) ; load character to send
|
||||||
or a ; is it zero?
|
or a ; is it zero?
|
||||||
jr z, .end ; if yes, we're finished
|
jr z, .end ; if yes, we're finished
|
||||||
call STDIO_PUTC
|
call stdioPutC
|
||||||
inc hl
|
inc hl
|
||||||
jr .loop
|
jr .loop
|
||||||
|
|
||||||
@ -70,7 +65,7 @@ printnstr:
|
|||||||
push hl
|
push hl
|
||||||
.loop:
|
.loop:
|
||||||
ld a, (hl) ; load character to send
|
ld a, (hl) ; load character to send
|
||||||
call STDIO_PUTC
|
call stdioPutC
|
||||||
inc hl
|
inc hl
|
||||||
djnz .loop
|
djnz .loop
|
||||||
|
|
||||||
@ -82,9 +77,9 @@ printnstr:
|
|||||||
printcrlf:
|
printcrlf:
|
||||||
push af
|
push af
|
||||||
ld a, ASCII_CR
|
ld a, ASCII_CR
|
||||||
call STDIO_PUTC
|
call stdioPutC
|
||||||
ld a, ASCII_LF
|
ld a, ASCII_LF
|
||||||
call STDIO_PUTC
|
call stdioPutC
|
||||||
pop af
|
pop af
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@ -110,19 +105,21 @@ printHexPair:
|
|||||||
pop af
|
pop af
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Repeatedly calls stdioGetC until a whole line was read, that is, when CR or
|
; Call stdioGetC and put the result in the buffer. Sets Z according to whether
|
||||||
; LF is read or if the buffer is full. Sets HL to the beginning of the read
|
; the buffer is "complete", that is, whether CR or LF have been pressed or if
|
||||||
; line, which is null-terminated.
|
; the the buffer is full. Z is set if the line is "complete", unset if not.
|
||||||
|
; The next call to stdioReadC after a completed line will start a new line.
|
||||||
;
|
;
|
||||||
; This routine also takes care of echoing received characters back to the TTY.
|
; This routine also takes care of echoing received characters back to the TTY.
|
||||||
; It also manages backspaces properly.
|
;
|
||||||
stdioReadLine:
|
; This routine doesn't wait after a typed char. If nothing is typed, we return
|
||||||
push bc
|
; immediately with Z flag unset.
|
||||||
ld hl, STDIO_BUF
|
;
|
||||||
ld b, STDIO_BUFSIZE-1
|
; Note that this routine doesn't bother returning the typed character.
|
||||||
.loop:
|
stdioReadC:
|
||||||
; Let's wait until something is typed.
|
; Let's wait until something is typed.
|
||||||
call STDIO_GETC
|
call stdioGetC
|
||||||
|
ret nz ; nothing typed? nothing to do
|
||||||
; got it. Now, is it a CR or LF?
|
; got it. Now, is it a CR or LF?
|
||||||
cp ASCII_CR
|
cp ASCII_CR
|
||||||
jr z, .complete ; char is CR? buffer complete!
|
jr z, .complete ; char is CR? buffer complete!
|
||||||
@ -134,37 +131,86 @@ stdioReadLine:
|
|||||||
jr z, .delchr
|
jr z, .delchr
|
||||||
|
|
||||||
; Echo the received character right away so that we see what we type
|
; Echo the received character right away so that we see what we type
|
||||||
call STDIO_PUTC
|
call stdioPutC
|
||||||
|
|
||||||
; Ok, gotta add it do the buffer
|
; Ok, gotta add it do the buffer
|
||||||
|
; save char for later
|
||||||
|
ex af, af'
|
||||||
|
ld a, (STDIO_BUFIDX)
|
||||||
|
push hl ; --> lvl 1
|
||||||
|
ld hl, STDIO_BUF
|
||||||
|
; make HL point to dest spot
|
||||||
|
call addHL
|
||||||
|
; Write our char down
|
||||||
|
ex af, af'
|
||||||
ld (hl), a
|
ld (hl), a
|
||||||
|
; follow up with a null char
|
||||||
inc hl
|
inc hl
|
||||||
djnz .loop
|
|
||||||
; buffer overflow, complete line
|
|
||||||
.complete:
|
|
||||||
; The line in our buffer is complete.
|
|
||||||
; Let's null-terminate it and return.
|
|
||||||
xor a
|
xor a
|
||||||
ld (hl), a
|
ld (hl), a
|
||||||
ld hl, STDIO_BUF
|
pop hl ; <-- lvl 1
|
||||||
pop bc
|
; inc idx, which still is in AF'
|
||||||
|
ex af, af'
|
||||||
|
inc a
|
||||||
|
cp STDIO_BUFSIZE-1 ; -1 is because we always want to keep our
|
||||||
|
; last char at zero.
|
||||||
|
jr z, .complete ; end of buffer reached? buffer is full.
|
||||||
|
|
||||||
|
; not complete. save idx back
|
||||||
|
ld (STDIO_BUFIDX), a
|
||||||
|
; Z already unset
|
||||||
|
ret
|
||||||
|
|
||||||
|
.complete:
|
||||||
|
; The line in our buffer is complete.
|
||||||
|
; But before we do that, let's take care of a special case: the empty
|
||||||
|
; line. If we didn't add any character since the last "complete", then
|
||||||
|
; our buffer's content is the content from the last time. Let's set this
|
||||||
|
; to an empty string.
|
||||||
|
ld a, (STDIO_BUFIDX)
|
||||||
|
or a
|
||||||
|
jr nz, .completeSkip
|
||||||
|
ld (STDIO_BUF), a
|
||||||
|
.completeSkip:
|
||||||
|
xor a ; sets Z
|
||||||
|
ld (STDIO_BUFIDX), a
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.delchr:
|
.delchr:
|
||||||
; Deleting is a tricky business. We have to decrease HL and increase B
|
ld a, (STDIO_BUFIDX)
|
||||||
; so that everything stays consistent. We also have to make sure that
|
or a
|
||||||
; We don't do buffer underflows.
|
jp z, unsetZ ; buf empty? nothing to do
|
||||||
ld a, b
|
; buffer not empty, let's go back one char and set a null char there.
|
||||||
cp STDIO_BUFSIZE-1
|
dec a
|
||||||
jr z, .loop ; beginning of line, nothing to delete
|
ld (STDIO_BUFIDX), a
|
||||||
dec hl
|
push hl ;<|
|
||||||
inc b
|
ld hl, STDIO_BUF ; |
|
||||||
|
; make HL point to dest spot |
|
||||||
|
call addHL ; |
|
||||||
|
xor a ; |
|
||||||
|
ld (hl), a ; |
|
||||||
|
pop hl ;<|
|
||||||
; Char deleted in buffer, now send BS + space + BS for the terminal
|
; Char deleted in buffer, now send BS + space + BS for the terminal
|
||||||
; to clear its previous char
|
; to clear its previous char
|
||||||
ld a, ASCII_BS
|
ld a, ASCII_BS
|
||||||
call STDIO_PUTC
|
call stdioPutC
|
||||||
ld a, ' '
|
ld a, ' '
|
||||||
call STDIO_PUTC
|
call stdioPutC
|
||||||
ld a, ASCII_BS
|
ld a, ASCII_BS
|
||||||
call STDIO_PUTC
|
call stdioPutC
|
||||||
jr .loop
|
jp unsetZ
|
||||||
|
|
||||||
|
|
||||||
|
; Make HL point to the line buffer. It is always null terminated.
|
||||||
|
stdioGetLine:
|
||||||
|
ld hl, STDIO_BUF
|
||||||
|
ret
|
||||||
|
|
||||||
|
; Repeatedly call stdioReadC until Z is set, then make HL point to the read
|
||||||
|
; buffer.
|
||||||
|
stdioReadLine:
|
||||||
|
call stdioReadC
|
||||||
|
jr nz, stdioReadLine
|
||||||
|
ld hl, STDIO_BUF
|
||||||
|
ret
|
||||||
|
|
||||||
|
@ -22,30 +22,16 @@ for.
|
|||||||
|
|
||||||
## Structure
|
## Structure
|
||||||
|
|
||||||
Each top folder represents an architecture. In that top folder, there's a
|
Each top folder represent an architecture. In that top folder, there's a
|
||||||
`README.md` file presenting the architecture as well as instructions to
|
`README.md` file presenting the architecture as well as instructions to
|
||||||
minimally get Collapse OS running on it. Then, in the same folder, there are
|
minimally get Collapse OS running on it. Then, in the same folder, there are
|
||||||
auxiliary recipes for nice stuff built around that architecture.
|
auxiliary recipes for nice stuff built around that architecture.
|
||||||
|
|
||||||
Installation procedures are centered around using a modern system to install
|
The structure of those recipes follow a regular pattern: pre-collapse recipe
|
||||||
Collapse OS. These are the most useful instructions to have under both
|
and post-collapse recipe. That is, instructions to achieve the desired outcome
|
||||||
pre-collapse and post-collapse conditions because even after the collapse,
|
from a "modern" system, and then, instructions to achieve the same thing from a
|
||||||
we'll interact mostly with modern technology for many years.
|
system running Collapse OS.
|
||||||
|
|
||||||
There are, however, recipes to write to different storage media, thus making
|
Initially, those recipes will only be possible in a "modern" system, but as
|
||||||
Collapse OS fully reproducible. For example, you can use `rc2014/eeprom` to
|
tooling improve, we should be able to have recipes that we can consider
|
||||||
write arbitrary data to a `AT28` EEPROM.
|
complete.
|
||||||
|
|
||||||
The `rc2014` architecture is considered the "canonical" one. That means that
|
|
||||||
if a recipe is considered architecture independent, it's the `rc2014` recipe
|
|
||||||
folder that's going to contain it.
|
|
||||||
|
|
||||||
For example, `rc2014/eeprom` can be considered architecture independent because
|
|
||||||
it's much more about the `AT28` than about a specific z80 architecture. You can
|
|
||||||
adapt it to any supported architecture with minimal hassle. Therefore, it's
|
|
||||||
not going to be copied in every architecture recipe folder.
|
|
||||||
|
|
||||||
`rc2014` installation recipe also contains more "newbie-friendly" instructions
|
|
||||||
than other installation recipes, which take this knowledge for granted. It is
|
|
||||||
therefore recommended to have a look at it even if you're not planning on using
|
|
||||||
a RC2014.
|
|
||||||
|
@ -28,9 +28,11 @@ are other recipes related to the RC2014:
|
|||||||
* [Assembling binaries](zasm/README.md)
|
* [Assembling binaries](zasm/README.md)
|
||||||
* [Interfacing a PS/2 keyboard](ps2/README.md)
|
* [Interfacing a PS/2 keyboard](ps2/README.md)
|
||||||
|
|
||||||
## Recipe
|
## Goal
|
||||||
|
|
||||||
The goal is to have the shell running and accessible through the Serial I/O.
|
Have the shell running and accessible through the Serial I/O.
|
||||||
|
|
||||||
|
## Pre-collapse
|
||||||
|
|
||||||
You'll need specialized tools to write data to the AT28 EEPROM. There seems to
|
You'll need specialized tools to write data to the AT28 EEPROM. There seems to
|
||||||
be many devices around made to write in flash and EEPROM modules, but being in
|
be many devices around made to write in flash and EEPROM modules, but being in
|
||||||
@ -75,9 +77,7 @@ is decoupled from the ACIA and can get its IO from anything. See
|
|||||||
|
|
||||||
We only have the shell to build, so it's rather straightforward:
|
We only have the shell to build, so it's rather straightforward:
|
||||||
|
|
||||||
../../tools/zasm.sh ../../kernel < glue.asm > os.bin
|
zasm < glue.asm > rom.bin
|
||||||
|
|
||||||
Running `make` will also work.
|
|
||||||
|
|
||||||
### Write to the ROM
|
### Write to the ROM
|
||||||
|
|
||||||
@ -100,6 +100,10 @@ identify the tty bound to it (in my case, `/dev/ttyUSB0`). Then:
|
|||||||
|
|
||||||
Press the reset button on the RC2014 and you should see the Collapse OS prompt!
|
Press the reset button on the RC2014 and you should see the Collapse OS prompt!
|
||||||
|
|
||||||
|
## Post-collapse
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
[rc2014]: https://rc2014.co.uk
|
[rc2014]: https://rc2014.co.uk
|
||||||
[romwrite]: https://github.com/hsoft/romwrite
|
[romwrite]: https://github.com/hsoft/romwrite
|
||||||
[zasm]: ../../tools/emul
|
[zasm]: ../../tools/emul
|
||||||
|
@ -27,7 +27,7 @@ If you're tempted by the idea of hacking your existing RC2014 ROM module by
|
|||||||
wiring `WR` and write directly to the range `0x0000-0x1fff` while running it,
|
wiring `WR` and write directly to the range `0x0000-0x1fff` while running it,
|
||||||
be aware that it's not that easy. I was also tempted by this idea, tried it,
|
be aware that it's not that easy. I was also tempted by this idea, tried it,
|
||||||
but on bootup, it seems that some random `WR` triggers happen and it corrupts
|
but on bootup, it seems that some random `WR` triggers happen and it corrupts
|
||||||
the EEPROM contents. Theoretically, we could go around that by putting the AT28
|
the EEPROM contents. Theoretically, we could go around that my putting the AT28
|
||||||
in write protection mode, but I preferred building my own module.
|
in write protection mode, but I preferred building my own module.
|
||||||
|
|
||||||
I don't think you need a schematic. It's really simple.
|
I don't think you need a schematic. It's really simple.
|
||||||
|
@ -27,8 +27,6 @@ jp aciaInt
|
|||||||
.dw mmapGetB, mmapPutB
|
.dw mmapGetB, mmapPutB
|
||||||
|
|
||||||
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
||||||
.equ STDIO_GETC aciaGetC
|
|
||||||
.equ STDIO_PUTC aciaPutC
|
|
||||||
.inc "stdio.asm"
|
.inc "stdio.asm"
|
||||||
|
|
||||||
.equ AT28W_RAMSTART STDIO_RAMEND
|
.equ AT28W_RAMSTART STDIO_RAMEND
|
||||||
@ -51,6 +49,9 @@ init:
|
|||||||
im 1
|
im 1
|
||||||
|
|
||||||
call aciaInit
|
call aciaInit
|
||||||
|
ld hl, aciaGetC
|
||||||
|
ld de, aciaPutC
|
||||||
|
call stdioInit
|
||||||
call shellInit
|
call shellInit
|
||||||
|
|
||||||
xor a
|
xor a
|
||||||
|
@ -18,8 +18,6 @@ jp aciaInt
|
|||||||
.inc "acia.asm"
|
.inc "acia.asm"
|
||||||
|
|
||||||
.equ STDIO_RAMSTART ACIA_RAMEND
|
.equ STDIO_RAMSTART ACIA_RAMEND
|
||||||
.equ STDIO_GETC aciaGetC
|
|
||||||
.equ STDIO_PUTC aciaPutC
|
|
||||||
.inc "stdio.asm"
|
.inc "stdio.asm"
|
||||||
|
|
||||||
.equ SHELL_RAMSTART STDIO_RAMEND
|
.equ SHELL_RAMSTART STDIO_RAMEND
|
||||||
@ -34,6 +32,9 @@ init:
|
|||||||
im 1
|
im 1
|
||||||
|
|
||||||
call aciaInit
|
call aciaInit
|
||||||
|
ld hl, aciaGetC
|
||||||
|
ld de, aciaPutC
|
||||||
|
call stdioInit
|
||||||
call shellInit
|
call shellInit
|
||||||
ei
|
ei
|
||||||
jp shellLoop
|
jp shellLoop
|
||||||
|
@ -16,8 +16,6 @@ jp init
|
|||||||
.inc "kbd.asm"
|
.inc "kbd.asm"
|
||||||
|
|
||||||
.equ STDIO_RAMSTART KBD_RAMEND
|
.equ STDIO_RAMSTART KBD_RAMEND
|
||||||
.equ STDIO_GETC kbdGetC
|
|
||||||
.equ STDIO_PUTC aciaPutC
|
|
||||||
.inc "stdio.asm"
|
.inc "stdio.asm"
|
||||||
|
|
||||||
.equ SHELL_RAMSTART STDIO_RAMEND
|
.equ SHELL_RAMSTART STDIO_RAMEND
|
||||||
@ -32,6 +30,9 @@ init:
|
|||||||
|
|
||||||
call aciaInit
|
call aciaInit
|
||||||
call kbdInit
|
call kbdInit
|
||||||
|
ld hl, kbdGetC
|
||||||
|
ld de, aciaPutC
|
||||||
|
call stdioInit
|
||||||
call shellInit
|
call shellInit
|
||||||
jp shellLoop
|
jp shellLoop
|
||||||
|
|
||||||
|
@ -34,8 +34,6 @@ jp aciaInt
|
|||||||
|
|
||||||
|
|
||||||
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
||||||
.equ STDIO_GETC aciaGetC
|
|
||||||
.equ STDIO_PUTC aciaPutC
|
|
||||||
.inc "stdio.asm"
|
.inc "stdio.asm"
|
||||||
|
|
||||||
.equ FS_RAMSTART STDIO_RAMEND
|
.equ FS_RAMSTART STDIO_RAMEND
|
||||||
@ -68,6 +66,9 @@ init:
|
|||||||
ld sp, hl
|
ld sp, hl
|
||||||
im 1
|
im 1
|
||||||
call aciaInit
|
call aciaInit
|
||||||
|
ld hl, aciaGetC
|
||||||
|
ld de, aciaPutC
|
||||||
|
call stdioInit
|
||||||
call fsInit
|
call fsInit
|
||||||
call shellInit
|
call shellInit
|
||||||
ld hl, pgmShellHook
|
ld hl, pgmShellHook
|
||||||
|
@ -65,8 +65,6 @@ jp aciaInt
|
|||||||
.inc "mmap.asm"
|
.inc "mmap.asm"
|
||||||
|
|
||||||
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
||||||
.equ STDIO_GETC aciaGetC
|
|
||||||
.equ STDIO_PUTC aciaPutC
|
|
||||||
.inc "stdio.asm"
|
.inc "stdio.asm"
|
||||||
|
|
||||||
.equ FS_RAMSTART STDIO_RAMEND
|
.equ FS_RAMSTART STDIO_RAMEND
|
||||||
@ -101,6 +99,9 @@ init:
|
|||||||
ld sp, hl
|
ld sp, hl
|
||||||
im 1
|
im 1
|
||||||
call aciaInit
|
call aciaInit
|
||||||
|
ld hl, aciaGetC
|
||||||
|
ld de, aciaPutC
|
||||||
|
call stdioInit
|
||||||
call fsInit
|
call fsInit
|
||||||
call shellInit
|
call shellInit
|
||||||
ld hl, pgmShellHook
|
ld hl, pgmShellHook
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
.inc "sms/vdp.asm"
|
.inc "sms/vdp.asm"
|
||||||
|
|
||||||
.equ STDIO_RAMSTART VDP_RAMEND
|
.equ STDIO_RAMSTART VDP_RAMEND
|
||||||
.equ STDIO_GETC padGetC
|
|
||||||
.equ STDIO_PUTC vdpPutC
|
|
||||||
.inc "stdio.asm"
|
.inc "stdio.asm"
|
||||||
|
|
||||||
.equ SHELL_RAMSTART STDIO_RAMEND
|
.equ SHELL_RAMSTART STDIO_RAMEND
|
||||||
@ -35,7 +33,15 @@ init:
|
|||||||
|
|
||||||
call padInit
|
call padInit
|
||||||
call vdpInit
|
call vdpInit
|
||||||
|
ld hl, padUpdateSel
|
||||||
|
ld (VDP_CHRSELHOOK), hl
|
||||||
|
|
||||||
|
ld hl, padGetC
|
||||||
|
ld de, vdpPutC
|
||||||
|
call stdioInit
|
||||||
call shellInit
|
call shellInit
|
||||||
|
ld hl, vdpShellLoopHook
|
||||||
|
ld (SHELL_LOOPHOOK), hl
|
||||||
jp shellLoop
|
jp shellLoop
|
||||||
|
|
||||||
.fill 0x7ff0-$
|
.fill 0x7ff0-$
|
||||||
|
@ -21,8 +21,6 @@
|
|||||||
.inc "sms/vdp.asm"
|
.inc "sms/vdp.asm"
|
||||||
|
|
||||||
.equ STDIO_RAMSTART VDP_RAMEND
|
.equ STDIO_RAMSTART VDP_RAMEND
|
||||||
.equ STDIO_GETC kbdGetC
|
|
||||||
.equ STDIO_PUTC vdpPutC
|
|
||||||
.inc "stdio.asm"
|
.inc "stdio.asm"
|
||||||
|
|
||||||
.equ SHELL_RAMSTART STDIO_RAMEND
|
.equ SHELL_RAMSTART STDIO_RAMEND
|
||||||
@ -47,6 +45,10 @@ init:
|
|||||||
|
|
||||||
call kbdInit
|
call kbdInit
|
||||||
call vdpInit
|
call vdpInit
|
||||||
|
|
||||||
|
ld hl, kbdGetC
|
||||||
|
ld de, vdpPutC
|
||||||
|
call stdioInit
|
||||||
call shellInit
|
call shellInit
|
||||||
jp shellLoop
|
jp shellLoop
|
||||||
|
|
||||||
|
@ -52,8 +52,6 @@
|
|||||||
.inc "sms/vdp.asm"
|
.inc "sms/vdp.asm"
|
||||||
|
|
||||||
.equ STDIO_RAMSTART VDP_RAMEND
|
.equ STDIO_RAMSTART VDP_RAMEND
|
||||||
.equ STDIO_GETC kbdGetC
|
|
||||||
.equ STDIO_PUTC vdpPutC
|
|
||||||
.inc "stdio.asm"
|
.inc "stdio.asm"
|
||||||
|
|
||||||
.equ MMAP_START 0xd700
|
.equ MMAP_START 0xd700
|
||||||
@ -106,6 +104,9 @@ init:
|
|||||||
ld a, 'S'
|
ld a, 'S'
|
||||||
ld (hl), a
|
ld (hl), a
|
||||||
|
|
||||||
|
ld hl, kbdGetC
|
||||||
|
ld de, vdpPutC
|
||||||
|
call stdioInit
|
||||||
call fsInit
|
call fsInit
|
||||||
xor a
|
xor a
|
||||||
ld de, BLOCKDEV_SEL
|
ld de, BLOCKDEV_SEL
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/python
|
||||||
|
|
||||||
# Read specified number of bytes in specified blkdev ID and spit it to stdout.
|
# Read specified number of bytes in specified blkdev ID and spit it to stdout.
|
||||||
# The proper blkdev has to be selected and placed already.
|
# The proper blkdev has to be selected and placed already.
|
||||||
|
@ -58,8 +58,6 @@
|
|||||||
.inc "mmap.asm"
|
.inc "mmap.asm"
|
||||||
|
|
||||||
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
||||||
.equ STDIO_GETC emulGetC
|
|
||||||
.equ STDIO_PUTC emulPutC
|
|
||||||
.inc "stdio.asm"
|
.inc "stdio.asm"
|
||||||
|
|
||||||
.equ FS_RAMSTART STDIO_RAMEND
|
.equ FS_RAMSTART STDIO_RAMEND
|
||||||
@ -86,6 +84,9 @@ init:
|
|||||||
; setup stack
|
; setup stack
|
||||||
ld hl, KERNEL_RAMEND
|
ld hl, KERNEL_RAMEND
|
||||||
ld sp, hl
|
ld sp, hl
|
||||||
|
ld hl, emulGetC
|
||||||
|
ld de, emulPutC
|
||||||
|
call stdioInit
|
||||||
call fsInit
|
call fsInit
|
||||||
ld a, 0 ; select fsdev
|
ld a, 0 ; select fsdev
|
||||||
ld de, BLOCKDEV_SEL
|
ld de, BLOCKDEV_SEL
|
||||||
|
@ -45,8 +45,6 @@ jp printstr
|
|||||||
.dw fsdevGetB, fsdevPutB
|
.dw fsdevGetB, fsdevPutB
|
||||||
|
|
||||||
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
|
||||||
.equ STDIO_GETC noop
|
|
||||||
.equ STDIO_PUTC stderrPutC
|
|
||||||
.inc "stdio.asm"
|
.inc "stdio.asm"
|
||||||
|
|
||||||
.equ FS_RAMSTART STDIO_RAMEND
|
.equ FS_RAMSTART STDIO_RAMEND
|
||||||
@ -57,6 +55,9 @@ init:
|
|||||||
di
|
di
|
||||||
ld hl, 0xffff
|
ld hl, 0xffff
|
||||||
ld sp, hl
|
ld sp, hl
|
||||||
|
ld hl, unsetZ
|
||||||
|
ld de, stderrPutC
|
||||||
|
call stdioInit
|
||||||
ld a, 2 ; select fsdev
|
ld a, 2 ; select fsdev
|
||||||
ld de, BLOCKDEV_SEL
|
ld de, BLOCKDEV_SEL
|
||||||
call blkSel
|
call blkSel
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/python
|
||||||
|
|
||||||
# Read specified number of bytes at specified memory address and dump it to
|
# Read specified number of bytes at specified memory address and dump it to
|
||||||
# stdout.
|
# stdout.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/python
|
||||||
|
|
||||||
# Push specified file to specified device and verify that the contents is
|
# Push specified file to specified device and verify that the contents is
|
||||||
# correct by sending a "peek" command afterwards and check the output. Errors
|
# correct by sending a "peek" command afterwards and check the output. Errors
|
||||||
|
Loading…
Reference in New Issue
Block a user