Add Type and More, and the file stream they are built on
Two applications that read a file too big for Data Memory: Type prints one, More pages it. Both sit on fileStream.asm, which wraps osFileInfo and osFileBlock into open-and-next so an application walks a file's blocks without repeating the service calls. The disk fixture is deliberately awkward: readable.txt crosses several blocks and carries no zero byte to be mistaken for an end marker, and empty.txt says that zero blocks is a valid file rather than an error. These three files were written by ChatGPT, as their headers record. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
co-authored by
Claude Opus 5
parent
4fd8bf7b3f
commit
dbe58db660
@@ -0,0 +1,151 @@
|
||||
; Read a text file one screen at a time.
|
||||
;
|
||||
; Twenty two lines are shown before a prompt. Space advances another screen, Return one
|
||||
; line, and q gives the machine back to CosmOS. This is forward-only on purpose: the file
|
||||
; stream holds one block and never asks the whole document to fit in memory.
|
||||
;
|
||||
; Written by ChatGPT for Anachronaut's SplitBit
|
||||
|
||||
#Include services.asm
|
||||
#Program
|
||||
#Base 0x2000
|
||||
|
||||
start:
|
||||
SETD.0 Name
|
||||
INIB 0d29
|
||||
SWI osArgument
|
||||
SETD.0 Name
|
||||
LDA.0
|
||||
BRA noName
|
||||
CALL fileStreamOpen
|
||||
BNQ openFailed
|
||||
CALL fullPage
|
||||
|
||||
nextBlock:
|
||||
CALL fileStreamNext
|
||||
BNQ readFailed
|
||||
PSHD.3
|
||||
POPB
|
||||
POPA
|
||||
SETD.2 Remaining
|
||||
STA.2
|
||||
INCD.2
|
||||
STB.2
|
||||
OR
|
||||
BRQ finished
|
||||
SETD.1 FileStreamBlock
|
||||
SETD.2 Remaining
|
||||
|
||||
printLoop:
|
||||
LDA.1
|
||||
OUTA 0x00
|
||||
INIB 0x0A
|
||||
XOR
|
||||
BNQ bytePrinted
|
||||
SETD.3 LinesLeft
|
||||
LDA.3
|
||||
DECA
|
||||
STA.3
|
||||
BNA bytePrinted
|
||||
CALL pause
|
||||
BNQ finished
|
||||
bytePrinted:
|
||||
INCD.1
|
||||
CALL fileStreamTakeRemaining
|
||||
BRQ nextBlock
|
||||
BRI printLoop
|
||||
|
||||
; Ask for one key without asking for Return. The console is put back immediately,
|
||||
; including on q and end of redirected input.
|
||||
pause:
|
||||
SETD.0 MorePrompt
|
||||
SWI osPrintString
|
||||
INIA 0x01
|
||||
OUTA 0x02
|
||||
INA 0x00
|
||||
PSHA ; Keep the key while A is used to restore line mode.
|
||||
RSTA
|
||||
OUTA 0x02
|
||||
POPA
|
||||
SETD.0 ClearPrompt
|
||||
SWI osPrintString
|
||||
|
||||
INIB 0x71 ; q
|
||||
XOR
|
||||
BRQ pauseQuit
|
||||
INIB 0xFF ; end of redirected input
|
||||
XOR
|
||||
BRQ pauseQuit
|
||||
INIB 0x0A ; Return: one more line.
|
||||
XOR
|
||||
BRQ oneLine
|
||||
INIB 0x20 ; Space: one more screen.
|
||||
XOR
|
||||
BNQ pause ; Ignore every other key.
|
||||
CALL fullPage
|
||||
RSTA
|
||||
RSTB
|
||||
OR
|
||||
RET
|
||||
oneLine:
|
||||
SETD.3 LinesLeft
|
||||
INIA 0x01
|
||||
STA.3
|
||||
RSTA
|
||||
RSTB
|
||||
OR
|
||||
RET
|
||||
pauseQuit:
|
||||
RSTA
|
||||
INIB 0x01
|
||||
OR
|
||||
RET
|
||||
fullPage:
|
||||
SETD.3 LinesLeft
|
||||
INIA 0d22
|
||||
STA.3
|
||||
RET
|
||||
|
||||
noName:
|
||||
SETD.0 Usage
|
||||
SWI osPrintString
|
||||
SWI osExit
|
||||
openFailed:
|
||||
SETD.0 OpenError
|
||||
SWI osPrintString
|
||||
BRI printError
|
||||
readFailed:
|
||||
SETD.0 ReadError
|
||||
SWI osPrintString
|
||||
printError:
|
||||
RSTA
|
||||
MVQB
|
||||
SWI osPrintNumber
|
||||
SETD.0 NewLine
|
||||
SWI osPrintString
|
||||
finished:
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
#Base 0x1000
|
||||
Usage:
|
||||
"more: give me a file name
|
||||
"
|
||||
OpenError:
|
||||
"more: cannot find the file, error "
|
||||
ReadError:
|
||||
"more: cannot read the file, error "
|
||||
NewLine:
|
||||
0x0A 0x00
|
||||
MorePrompt:
|
||||
"-- more --"
|
||||
ClearPrompt:
|
||||
0x0A 0x00
|
||||
Name:
|
||||
#Reserve 0d29
|
||||
Remaining:
|
||||
0x00 0x00
|
||||
LinesLeft:
|
||||
0x00
|
||||
|
||||
#Include fileStream.asm
|
||||
@@ -0,0 +1,80 @@
|
||||
; Print a text file without asking it to fit in Data Memory.
|
||||
; fileStream.asm owns finding the file and walking its blocks. Type owns only what makes
|
||||
; it Type: send each byte to the console until the stream says there are no more.
|
||||
;
|
||||
; Written by ChatGPT for Anachronaut's SplitBit
|
||||
|
||||
#Include services.asm
|
||||
#Program
|
||||
#Base 0x2000
|
||||
|
||||
start:
|
||||
SETD.0 Name
|
||||
INIB 0d29
|
||||
SWI osArgument
|
||||
SETD.0 Name
|
||||
LDA.0
|
||||
BRA noName
|
||||
CALL fileStreamOpen
|
||||
BNQ openFailed
|
||||
|
||||
nextBlock:
|
||||
CALL fileStreamNext
|
||||
BNQ readFailed
|
||||
PSHD.3
|
||||
POPB
|
||||
POPA
|
||||
SETD.2 Remaining
|
||||
STA.2
|
||||
INCD.2
|
||||
STB.2
|
||||
OR
|
||||
BRQ finished
|
||||
SETD.1 FileStreamBlock
|
||||
SETD.2 Remaining
|
||||
|
||||
printLoop:
|
||||
LDA.1
|
||||
OUTA 0x00
|
||||
INCD.1
|
||||
CALL fileStreamTakeRemaining
|
||||
BRQ nextBlock
|
||||
BRI printLoop
|
||||
|
||||
noName:
|
||||
SETD.0 Usage
|
||||
SWI osPrintString
|
||||
SWI osExit
|
||||
openFailed:
|
||||
SETD.0 OpenError
|
||||
SWI osPrintString
|
||||
BRI printError
|
||||
readFailed:
|
||||
SETD.0 ReadError
|
||||
SWI osPrintString
|
||||
printError:
|
||||
RSTA
|
||||
MVQB
|
||||
SWI osPrintNumber
|
||||
SETD.0 NewLine
|
||||
SWI osPrintString
|
||||
finished:
|
||||
SWI osExit
|
||||
|
||||
#Data
|
||||
#Base 0x1000
|
||||
Usage:
|
||||
"type: give me a file name
|
||||
"
|
||||
OpenError:
|
||||
"type: cannot find the file, error "
|
||||
ReadError:
|
||||
"type: cannot read the file, error "
|
||||
NewLine:
|
||||
0x0A 0x00
|
||||
Name:
|
||||
#Reserve 0d29
|
||||
Remaining:
|
||||
0x00 0x00
|
||||
|
||||
#Include fileStream.asm
|
||||
@@ -138,6 +138,8 @@ from every assembly file in it. Several are old programs written for the bare ma
|
||||
| Break | Stops itself twice with SWI osBreak, so that the registers can be seen changing between one stop and the next. |
|
||||
| Edit | A line editor. |
|
||||
| Stream | Reads an 84,000 byte file through a buffer of 256, which is what says a file bigger than Data Memory can be read at all. |
|
||||
| Type | Prints a named text file a block at a time, including one too large to fit in Data Memory. |
|
||||
| More | A forward-only pager. Space advances a screen, Return one line, and q stops. |
|
||||
|
||||
### The Monitor:
|
||||
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
; Read a named file from beginning to end, one block at a time.
|
||||
;
|
||||
; DP0 = filename
|
||||
; CALL fileStreamOpen Q = 0, or the osFileInfo error
|
||||
; CALL fileStreamNext Q = 0, or the osFileBlock error
|
||||
; DP3 = bytes in FileStreamBlock; zero means EOF
|
||||
;
|
||||
; This is application-side machinery built on CosmOS services, not a filesystem and not
|
||||
; yet an OS stream. Open remembers the address of the caller's filename, which must remain
|
||||
; valid until the one stream is finished.
|
||||
;
|
||||
; Written by ChatGPT for Anachronaut's SplitBit
|
||||
|
||||
#Program
|
||||
fileStreamOpen:
|
||||
SETD.3 FileStreamName
|
||||
STD.0.3
|
||||
SWI osFileInfo
|
||||
BNQ fileStreamReturn
|
||||
PSHD.3
|
||||
POPB
|
||||
POPA
|
||||
SETD.3 FileStreamBlocks
|
||||
STA.3
|
||||
INCD.3
|
||||
STB.3
|
||||
SETD.3 FileStreamIndex
|
||||
RSTA
|
||||
STA.3
|
||||
INCD.3
|
||||
STA.3
|
||||
fileStreamReturn:
|
||||
RET
|
||||
|
||||
fileStreamNext:
|
||||
SETD.3 FileStreamBlocks
|
||||
LDA.3
|
||||
INCD.3
|
||||
LDB.3
|
||||
OR
|
||||
BRQ fileStreamEnd
|
||||
SETD.3 FileStreamName
|
||||
LDD.0.3
|
||||
SETD.1 FileStreamBlock
|
||||
SETD.3 FileStreamIndex
|
||||
LDA.3
|
||||
INCD.3
|
||||
LDB.3
|
||||
SWI osFileBlock
|
||||
BNQ fileStreamReturn
|
||||
|
||||
; DP3 is the service's return value and also the pointer this routine uses for all of
|
||||
; its bookkeeping. Keep the value before touching the pointer, then restore it at the
|
||||
; one successful return below.
|
||||
PSHD.3
|
||||
POPB
|
||||
POPA
|
||||
SETD.3 FileStreamCount
|
||||
STA.3
|
||||
INCD.3
|
||||
STB.3
|
||||
|
||||
; Index++.
|
||||
SETD.3 FileStreamIndex
|
||||
INCD.3
|
||||
LDA.3
|
||||
INCA
|
||||
STA.3
|
||||
BNC fileStreamTakeBlock
|
||||
DECD.3
|
||||
LDA.3
|
||||
INCA
|
||||
STA.3
|
||||
fileStreamTakeBlock:
|
||||
; Blocks--.
|
||||
SETD.3 FileStreamBlocks
|
||||
INCD.3
|
||||
LDA.3
|
||||
BRA fileStreamBlocksBorrow
|
||||
DECA
|
||||
STA.3
|
||||
BRI fileStreamReadReturn
|
||||
fileStreamBlocksBorrow:
|
||||
INIA 0xFF
|
||||
STA.3
|
||||
DECD.3
|
||||
LDA.3
|
||||
DECA
|
||||
STA.3
|
||||
fileStreamReadReturn:
|
||||
SETD.3 FileStreamCount
|
||||
LDD.3.3
|
||||
RET
|
||||
fileStreamEnd:
|
||||
; There is no reset-pointer instruction. Two zero bytes through the Stack are the
|
||||
; literal construction of a zero Data Pointer.
|
||||
RSTA
|
||||
PSHA
|
||||
PSHA
|
||||
POPD.3
|
||||
RET
|
||||
|
||||
; DP2 names a big-endian sixteen-bit byte count. Decrement it, returning Q = 0 when it
|
||||
; reached zero and nonzero while bytes remain. This is shared because correctly counting
|
||||
; a full 0x0100-byte block is the least interesting part of both applications to duplicate.
|
||||
fileStreamTakeRemaining:
|
||||
INCD.2
|
||||
LDA.2
|
||||
BRA fileStreamRemainingBorrow
|
||||
DECA
|
||||
STA.2
|
||||
DECD.2
|
||||
LDB.2
|
||||
INCD.2
|
||||
LDA.2
|
||||
OR
|
||||
RET
|
||||
fileStreamRemainingBorrow:
|
||||
INIA 0xFF
|
||||
STA.2
|
||||
DECD.2
|
||||
LDA.2
|
||||
DECA
|
||||
STA.2
|
||||
LDB.2
|
||||
INCD.2
|
||||
LDA.2
|
||||
OR
|
||||
RET
|
||||
|
||||
#Data
|
||||
FileStreamName:
|
||||
0x00 0x00
|
||||
FileStreamBlocks:
|
||||
0x00 0x00
|
||||
FileStreamIndex:
|
||||
0x00 0x00
|
||||
FileStreamCount:
|
||||
0x00 0x00
|
||||
FileStreamBlock:
|
||||
#Reserve 0d256
|
||||
Reference in New Issue
Block a user