1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-26 07:38:06 +11:00

Compare commits

..

No commits in common. "69daf49920c77821c78b747bb59ea5e3ad0409ac" and "8a696a1e23cc94f4db71489cfb39d0cf9e2747a8" have entirely different histories.

23 changed files with 276 additions and 201 deletions

View File

@ -1,5 +1,5 @@
This file describe tricks and conventions that are used throughout the code and
might need explanation.
This file describe tricks that are used throughout the code and might need
explanation.
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
"unsetZ" routine exists for that, although that in certain circumstances,
"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.

View File

@ -7,43 +7,47 @@ look like:
; The RAM module is selected on A15, so it has the range 0x8000-0xffff
.equ RAMSTART 0x8000
.equ RAMEND 0xffff
.equ ACIA_CTL 0x80 ; Control and status. RS off.
.equ ACIA_IO 0x81 ; Transmit. RS on.
.equ RAMSTART 0x8000
.equ RAMEND 0xffff
.equ ACIA_CTL 0x80 ; Control and status. RS off.
.equ ACIA_IO 0x81 ; Transmit. RS on.
jp init
jr init
; interrupt hook
.fill 0x38-$
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"
jp aciaInt
init:
di
; setup stack
ld hl, RAMEND
ld sp, hl
ld hl, RAMEND
ld sp, hl
im 1
call aciaInit
call shellInit
call aciaInit
xor a
ld de, BLOCKDEV_SEL
call blkSel
call stdioInit
call shellInit
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:

View File

@ -98,17 +98,17 @@ aciaInt:
reti
; *** STDIO ***
; These function below follow the stdio API.
; *** BLOCKDEV ***
; These function below follow the blockdev API.
aciaGetC:
push de
.loop:
ld a, (ACIA_BUFWRIDX)
ld e, a
ld a, (ACIA_BUFRDIDX)
cp e
jr z, .loop ; equal? nothing to read. loop
jr z, .nothingToRead ; equal? nothing to read.
; Alrighty, buffer not empty. let's read.
ld de, ACIA_BUF
@ -120,6 +120,12 @@ aciaGetC:
; And finally, fetch the value.
ld a, (de)
cp a ; ensure Z
jr .end
.nothingToRead:
call unsetZ
.end:
pop de
ret

View File

@ -35,10 +35,6 @@
; number of entries in shellCmdTbl
.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 ***
; Memory address that the shell is currently "pointing at" for peek, load, call
; operations. Set with mptr.
@ -46,12 +42,14 @@
; Places where we store arguments specifiers and where resulting values are
; 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
.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 ***
shellInit:
@ -60,6 +58,7 @@ shellInit:
ld (SHELL_MEM_PTR+1), a
ld hl, noop
ld (SHELL_CMDHOOK), hl
ld (SHELL_LOOPHOOK), hl
; print welcome
ld hl, .welcome
@ -71,8 +70,15 @@ shellInit:
; 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.
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 stdioGetLine
call shellParse
ld hl, .prompt
call printstr
@ -86,7 +92,7 @@ shellParse:
; first thing: is command empty?
ld a, (hl)
or a
ret z ; empty, nothing to do
ret z ; empty, nthing to do
push af
push bc
@ -104,13 +110,6 @@ shellParse:
; 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.
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:
xor a
ld (hl), a

View File

@ -11,9 +11,6 @@
; The space character is the first among special chars.
; * 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 ***
;
.equ PAD_CTLPORT 0x3f
@ -32,18 +29,21 @@
;
; Button status of last padUpdateSel call. Used for debouncing.
.equ PAD_SELSTAT PAD_RAMSTART
; Button status of last padGetC call.
.equ PAD_GETCSTAT PAD_SELSTAT+1
; 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
; LF that is feeded when Start is pressed.
.equ PAD_NEXTCHR @+1
.equ PAD_RAMEND @+1
.equ PAD_NEXTCHR PAD_SELCHR+1
.equ PAD_RAMEND PAD_NEXTCHR+1
; *** Code ***
padInit:
ld a, 0xff
ld (PAD_SELSTAT), a
ld (PAD_GETCSTAT), a
xor a
ld (PAD_NEXTCHR), a
ld a, 'a'
@ -78,14 +78,14 @@ padStatus:
ret
; 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:
call padStatus
push hl ; --> lvl 1
push hl
ld hl, PAD_SELSTAT
cp (hl)
ld (hl), a
pop hl ; <-- lvl 1
pop hl
jr z, .nothing ; nothing changed
bit PAD_UP, a
jr z, .up
@ -156,51 +156,45 @@ padUpdateSel:
ld (PAD_SELCHR), a
jp unsetZ
.nothing:
; Z already set
cp a ; ensure Z
ld a, (PAD_SELCHR)
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:
ld a, (PAD_NEXTCHR)
or a
jr nz, .nextchr
call padUpdateSel
jp z, padGetC ; nothing changed, loop
; pad status was changed, let's see if an action button was pressed
ld a, (PAD_SELSTAT)
call padStatus
push hl
ld hl, PAD_GETCSTAT
cp (hl)
ld (hl), a
pop hl
jp z, unsetZ ; nothing changed
bit PAD_BUTC, a
jr z, .advance
bit PAD_BUTA, a
jr z, .backspace
bit PAD_START, a
jr z, .return
; no action button pressed, but because our pad status changed, update
; VDP before looping.
ld a, (PAD_SELCHR)
call vdpConv
call vdpSpitC
jp padGetC
jp unsetZ
.return:
ld a, ASCII_LF
ld (PAD_NEXTCHR), a
; continue to .advance
.advance:
ld a, (PAD_SELCHR)
; Z was already set from previous BIT instruction
cp a
ret
.backspace:
ld a, ASCII_BS
; Z was already set from previous BIT instruction
cp a
ret
.nextchr:
; We have a "next char", return it and clear it.
cp a ; ensure Z
ex af, af'
push af
xor a
ld (PAD_NEXTCHR), a
ex af, af'
pop af
ret

View File

@ -21,8 +21,11 @@
; Row of cursor
.equ VDP_ROW VDP_RAMSTART
; Line of cursor
.equ VDP_LINE @+1
.equ VDP_RAMEND @+1
.equ VDP_LINE VDP_ROW+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 ***
@ -30,6 +33,9 @@ vdpInit:
xor a
ld (VDP_ROW), a
ld (VDP_LINE), a
ld (VDP_LASTSEL), a
ld hl, noop
ld (VDP_CHRSELHOOK), hl
ld hl, vdpInitData
ld b, vdpInitDataEnd-vdpInitData
@ -115,6 +121,12 @@ vdpSpitC:
ret
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
; 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
@ -255,6 +267,26 @@ vdpConv:
ld a, 0x5e
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:
.db 0x00,0x3f
vdpPaletteDataEnd:

View File

@ -4,26 +4,6 @@
; in", that is, the console through which the user is connected in a decoupled
; 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 ***
; Size of the readline buffer. If a typed line reaches this size, the line is
; flushed immediately (same as pressing return).
@ -32,19 +12,34 @@
; *** Variables ***
; Used to store formatted hex values just before printing it.
.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
; This buffer is null-terminated.
.equ STDIO_BUF @+2
; This buffer is null-terminated and we don't keep an index around: we look
; 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.
.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:
jp STDIO_GETC
ld ix, (STDIO_GETC)
jp (ix)
stdioPutC:
jp STDIO_PUTC
ld ix, (STDIO_PUTC)
jp (ix)
; print null-terminated string pointed to by HL
printstr:
@ -55,7 +50,7 @@ printstr:
ld a, (hl) ; load character to send
or a ; is it zero?
jr z, .end ; if yes, we're finished
call STDIO_PUTC
call stdioPutC
inc hl
jr .loop
@ -70,7 +65,7 @@ printnstr:
push hl
.loop:
ld a, (hl) ; load character to send
call STDIO_PUTC
call stdioPutC
inc hl
djnz .loop
@ -82,9 +77,9 @@ printnstr:
printcrlf:
push af
ld a, ASCII_CR
call STDIO_PUTC
call stdioPutC
ld a, ASCII_LF
call STDIO_PUTC
call stdioPutC
pop af
ret
@ -110,19 +105,21 @@ printHexPair:
pop af
ret
; Repeatedly calls stdioGetC until a whole line was read, that is, when CR or
; LF is read or if the buffer is full. Sets HL to the beginning of the read
; line, which is null-terminated.
; Call stdioGetC and put the result in the buffer. Sets Z according to whether
; the buffer is "complete", that is, whether CR or LF have been pressed or if
; 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.
; It also manages backspaces properly.
stdioReadLine:
push bc
ld hl, STDIO_BUF
ld b, STDIO_BUFSIZE-1
.loop:
;
; This routine doesn't wait after a typed char. If nothing is typed, we return
; immediately with Z flag unset.
;
; Note that this routine doesn't bother returning the typed character.
stdioReadC:
; 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?
cp ASCII_CR
jr z, .complete ; char is CR? buffer complete!
@ -134,37 +131,86 @@ stdioReadLine:
jr z, .delchr
; 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
; 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
; follow up with a null char
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
ld (hl), a
ld hl, STDIO_BUF
pop bc
pop hl ; <-- lvl 1
; 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
.delchr:
; Deleting is a tricky business. We have to decrease HL and increase B
; so that everything stays consistent. We also have to make sure that
; We don't do buffer underflows.
ld a, b
cp STDIO_BUFSIZE-1
jr z, .loop ; beginning of line, nothing to delete
dec hl
inc b
ld a, (STDIO_BUFIDX)
or a
jp z, unsetZ ; buf empty? nothing to do
; buffer not empty, let's go back one char and set a null char there.
dec a
ld (STDIO_BUFIDX), a
push hl ;<|
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
; to clear its previous char
ld a, ASCII_BS
call STDIO_PUTC
call stdioPutC
ld a, ' '
call STDIO_PUTC
call stdioPutC
ld a, ASCII_BS
call STDIO_PUTC
jr .loop
call stdioPutC
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

View File

@ -22,30 +22,16 @@ for.
## 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
minimally get Collapse OS running on it. Then, in the same folder, there are
auxiliary recipes for nice stuff built around that architecture.
Installation procedures are centered around using a modern system to install
Collapse OS. These are the most useful instructions to have under both
pre-collapse and post-collapse conditions because even after the collapse,
we'll interact mostly with modern technology for many years.
The structure of those recipes follow a regular pattern: pre-collapse recipe
and post-collapse recipe. That is, instructions to achieve the desired outcome
from a "modern" system, and then, instructions to achieve the same thing from a
system running Collapse OS.
There are, however, recipes to write to different storage media, thus making
Collapse OS fully reproducible. For example, you can use `rc2014/eeprom` to
write arbitrary data to a `AT28` EEPROM.
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.
Initially, those recipes will only be possible in a "modern" system, but as
tooling improve, we should be able to have recipes that we can consider
complete.

View File

@ -28,9 +28,11 @@ are other recipes related to the RC2014:
* [Assembling binaries](zasm/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
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:
../../tools/zasm.sh ../../kernel < glue.asm > os.bin
Running `make` will also work.
zasm < glue.asm > rom.bin
### 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!
## Post-collapse
TODO
[rc2014]: https://rc2014.co.uk
[romwrite]: https://github.com/hsoft/romwrite
[zasm]: ../../tools/emul

View File

@ -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,
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
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.
I don't think you need a schematic. It's really simple.

View File

@ -27,8 +27,6 @@ jp aciaInt
.dw mmapGetB, mmapPutB
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
.equ STDIO_GETC aciaGetC
.equ STDIO_PUTC aciaPutC
.inc "stdio.asm"
.equ AT28W_RAMSTART STDIO_RAMEND
@ -51,6 +49,9 @@ init:
im 1
call aciaInit
ld hl, aciaGetC
ld de, aciaPutC
call stdioInit
call shellInit
xor a

View File

@ -18,8 +18,6 @@ jp aciaInt
.inc "acia.asm"
.equ STDIO_RAMSTART ACIA_RAMEND
.equ STDIO_GETC aciaGetC
.equ STDIO_PUTC aciaPutC
.inc "stdio.asm"
.equ SHELL_RAMSTART STDIO_RAMEND
@ -34,6 +32,9 @@ init:
im 1
call aciaInit
ld hl, aciaGetC
ld de, aciaPutC
call stdioInit
call shellInit
ei
jp shellLoop

View File

@ -16,8 +16,6 @@ jp init
.inc "kbd.asm"
.equ STDIO_RAMSTART KBD_RAMEND
.equ STDIO_GETC kbdGetC
.equ STDIO_PUTC aciaPutC
.inc "stdio.asm"
.equ SHELL_RAMSTART STDIO_RAMEND
@ -32,6 +30,9 @@ init:
call aciaInit
call kbdInit
ld hl, kbdGetC
ld de, aciaPutC
call stdioInit
call shellInit
jp shellLoop

View File

@ -34,8 +34,6 @@ jp aciaInt
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
.equ STDIO_GETC aciaGetC
.equ STDIO_PUTC aciaPutC
.inc "stdio.asm"
.equ FS_RAMSTART STDIO_RAMEND
@ -68,6 +66,9 @@ init:
ld sp, hl
im 1
call aciaInit
ld hl, aciaGetC
ld de, aciaPutC
call stdioInit
call fsInit
call shellInit
ld hl, pgmShellHook

View File

@ -65,8 +65,6 @@ jp aciaInt
.inc "mmap.asm"
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
.equ STDIO_GETC aciaGetC
.equ STDIO_PUTC aciaPutC
.inc "stdio.asm"
.equ FS_RAMSTART STDIO_RAMEND
@ -101,6 +99,9 @@ init:
ld sp, hl
im 1
call aciaInit
ld hl, aciaGetC
ld de, aciaPutC
call stdioInit
call fsInit
call shellInit
ld hl, pgmShellHook

View File

@ -19,8 +19,6 @@
.inc "sms/vdp.asm"
.equ STDIO_RAMSTART VDP_RAMEND
.equ STDIO_GETC padGetC
.equ STDIO_PUTC vdpPutC
.inc "stdio.asm"
.equ SHELL_RAMSTART STDIO_RAMEND
@ -35,7 +33,15 @@ init:
call padInit
call vdpInit
ld hl, padUpdateSel
ld (VDP_CHRSELHOOK), hl
ld hl, padGetC
ld de, vdpPutC
call stdioInit
call shellInit
ld hl, vdpShellLoopHook
ld (SHELL_LOOPHOOK), hl
jp shellLoop
.fill 0x7ff0-$

View File

@ -21,8 +21,6 @@
.inc "sms/vdp.asm"
.equ STDIO_RAMSTART VDP_RAMEND
.equ STDIO_GETC kbdGetC
.equ STDIO_PUTC vdpPutC
.inc "stdio.asm"
.equ SHELL_RAMSTART STDIO_RAMEND
@ -47,6 +45,10 @@ init:
call kbdInit
call vdpInit
ld hl, kbdGetC
ld de, vdpPutC
call stdioInit
call shellInit
jp shellLoop

View File

@ -52,8 +52,6 @@
.inc "sms/vdp.asm"
.equ STDIO_RAMSTART VDP_RAMEND
.equ STDIO_GETC kbdGetC
.equ STDIO_PUTC vdpPutC
.inc "stdio.asm"
.equ MMAP_START 0xd700
@ -106,6 +104,9 @@ init:
ld a, 'S'
ld (hl), a
ld hl, kbdGetC
ld de, vdpPutC
call stdioInit
call fsInit
xor a
ld de, BLOCKDEV_SEL

View File

@ -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.
# The proper blkdev has to be selected and placed already.

View File

@ -58,8 +58,6 @@
.inc "mmap.asm"
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
.equ STDIO_GETC emulGetC
.equ STDIO_PUTC emulPutC
.inc "stdio.asm"
.equ FS_RAMSTART STDIO_RAMEND
@ -86,6 +84,9 @@ init:
; setup stack
ld hl, KERNEL_RAMEND
ld sp, hl
ld hl, emulGetC
ld de, emulPutC
call stdioInit
call fsInit
ld a, 0 ; select fsdev
ld de, BLOCKDEV_SEL

View File

@ -45,8 +45,6 @@ jp printstr
.dw fsdevGetB, fsdevPutB
.equ STDIO_RAMSTART BLOCKDEV_RAMEND
.equ STDIO_GETC noop
.equ STDIO_PUTC stderrPutC
.inc "stdio.asm"
.equ FS_RAMSTART STDIO_RAMEND
@ -57,6 +55,9 @@ init:
di
ld hl, 0xffff
ld sp, hl
ld hl, unsetZ
ld de, stderrPutC
call stdioInit
ld a, 2 ; select fsdev
ld de, BLOCKDEV_SEL
call blkSel

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/python
# Read specified number of bytes at specified memory address and dump it to
# stdout.

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/python
# Push specified file to specified device and verify that the contents is
# correct by sending a "peek" command afterwards and check the output. Errors