A list of files in a makefile goes stale the moment somebody adds a program and forgets to name it, and what they forgot is invisible until they go looking for it on the machine. So SplitDisk gained a mirror command and the disk rule is one line: putting a file where the others live is now the whole of putting it on the disk. EVERY FILE GOES THROUGH put AND EVERY DIRECTORY THROUGH mkdir. That is the point of it - mirror adds a walk and no filesystem code at all, so anything the format refuses here it refuses everywhere, in the same words. What is new is the walk, and the walk is what the six checks in Tests/disk.sh are about: that it goes all the way down, that it leaves dotfiles and named directories behind, and that a name too long stops it. REFUSED RATHER THAN SKIPPED, because a disk quietly missing a file is the exact failure a mirror exists to prevent. Which meant four sources had to be renamed - a directory entry holds 22 characters and they were 23, 23, 24 and 29: 16bitSegmentedSieve.asm -> 16bitSieve.asm 16bitSegmentedSieveModern.asm -> 16bitSieveModern.asm consoleInterruptTest.asm -> consoleInterrupt.asm controllerWriteTest.asm -> controllerWrite.asm The test names in the manifest are unchanged, since those are identifiers and every recorded result is filed under them. Only where the source lives has moved. The entries are sorted before anything is written. readdir hands them back in whatever order the host filesystem feels like, and a disk image that comes out different from one run to the next is an image no test could compare against another. The disk grew from one megabyte to four and from 192 directory entries to 1,024. The sources are 2,850 blocks and the mirror filled the old directory on its first run, which is a thing that should not need thinking about again. The Tests fixture disk is deliberately NOT mirrored. It is a controlled fixture with known contents, and the shipped disk is the one meant to be useful; they want different things. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
146 lines
3.3 KiB
NASM
146 lines
3.3 KiB
NASM
; Exercises the console's status and control ports.
|
|
;
|
|
; The console answers on three ports now: 0x00 for bytes as it always did, 0x01 for what
|
|
; it is doing, and 0x02 to say which mode it should be in. The point of the mode is that
|
|
; the data port never changed, so this checks the old behaviour is still there as much as
|
|
; it checks the new behaviour arrived.
|
|
;
|
|
; What the status bits mean:
|
|
; bit 0 READY reading the data port will not have to wait
|
|
; bit 1 ENDED input has run out for good
|
|
; bit 2 KEYMODE the console is in key mode
|
|
;
|
|
; There is a fourth bit, for whether the console interrupts on input, and nothing here
|
|
; sets it. Polling and interrupting are the two ways to get a byte and this is the one
|
|
; about polling; consoleInterrupt.asm is the other.
|
|
;
|
|
; This runs with input from a file rather than a terminal, so key mode has no terminal to
|
|
; put into another state and the mode bit is the only thing that changes. That is on
|
|
; purpose: the same program has to work either way, and a test that needed a terminal
|
|
; could not run here at all.
|
|
|
|
#Include console.asm
|
|
|
|
#Program
|
|
|
|
start:
|
|
SETD.0 Banner
|
|
CALL printString
|
|
CALL newLine
|
|
|
|
; ---- What mode does it start in ----
|
|
;
|
|
; Nothing has been written to the control port, so this is how the machine comes up, and
|
|
; every program written before these ports existed runs in exactly this.
|
|
SETD.0 AtStartLabel
|
|
CALL printString
|
|
CALL showStatus
|
|
|
|
; ---- Into key mode ----
|
|
INIA 0x01
|
|
OUTA 0x02
|
|
SETD.0 KeyModeLabel
|
|
CALL printString
|
|
CALL showStatus
|
|
|
|
; ---- Read what is waiting ----
|
|
;
|
|
; Reading until ENDED rather than until a count, which is the thing that could not be
|
|
; done before: 0xFF from the data port used to mean both "the byte 0xFF" and "there is
|
|
; no more", and nothing could tell those apart.
|
|
SETD.0 ReadLabel
|
|
CALL printString
|
|
CALL newLine
|
|
readLoop:
|
|
INA 0x01
|
|
INIB 0x02 ; ENDED
|
|
AND
|
|
BNQ readDone
|
|
INA 0x00
|
|
OUTA 0x00 ; Nothing echoes in key mode, so the program does it.
|
|
BRI readLoop
|
|
readDone:
|
|
CALL newLine
|
|
|
|
; ---- The status at the end of input ----
|
|
;
|
|
; ENDED is set and READY is clear, although a read would answer at once here: what it
|
|
; answers is 0xFF standing in for nothing. READY means there is a byte to be had, so the
|
|
; loop above stops on its own rather than taking imaginary bytes forever.
|
|
SETD.0 AtEndLabel
|
|
CALL printString
|
|
CALL showStatus
|
|
|
|
; ---- Back to line mode ----
|
|
RSTA
|
|
OUTA 0x02
|
|
SETD.0 LineModeLabel
|
|
CALL printString
|
|
CALL showStatus
|
|
|
|
HALT
|
|
|
|
; Prints the status byte as hex and then names the bits that are up, so that a change in
|
|
; the output says which bit moved rather than only that the number is different.
|
|
showStatus:
|
|
INA 0x01
|
|
PSHA
|
|
CALL printByteHex
|
|
INIA 0x20
|
|
OUTA 0x00
|
|
POPA
|
|
PSHA
|
|
|
|
INIB 0x01
|
|
AND
|
|
BRQ showNotReady
|
|
SETD.0 ReadyWord
|
|
CALL printString
|
|
showNotReady:
|
|
POPA
|
|
PSHA
|
|
|
|
INIB 0x02
|
|
AND
|
|
BRQ showNotEnded
|
|
SETD.0 EndedWord
|
|
CALL printString
|
|
showNotEnded:
|
|
POPA
|
|
|
|
INIB 0x04
|
|
AND
|
|
BRQ showNotKeys
|
|
SETD.0 KeysWord
|
|
CALL printString
|
|
showNotKeys:
|
|
CALL newLine
|
|
RET
|
|
|
|
#Data
|
|
|
|
Banner:
|
|
"console mode ports"
|
|
|
|
AtStartLabel:
|
|
"at start: "
|
|
KeyModeLabel:
|
|
"key mode: "
|
|
AtEndLabel:
|
|
"at the end: "
|
|
LineModeLabel:
|
|
"line mode: "
|
|
ReadLabel:
|
|
"what came in:"
|
|
|
|
ReadyWord:
|
|
"ready "
|
|
EndedWord:
|
|
"ended "
|
|
KeysWord:
|
|
"keys "
|
|
|
|
#Vectors
|
|
|
|
Boot start
|