S2: the assembler writes the file as it makes it
The output image is gone. It was eighteen kilobytes and it is now one block of window, because the file was always produced in order and only ever needed to be written that way. Everything works in FILE OFFSETS now. A cursor is a two byte number counting from the front of the file, and since a block is two hundred and fifty six bytes, the block it lands in is the offset's high byte and the place within that block is its low one - so there is no division anywhere, and ImgWalk, ProgPut and DataPut needed no change but where they start. ONE WINDOW RATHER THAN THREE. The plan said three: one per segment, and a third for the block where the program ends and the data begins, which belongs to both. Fetching a block back instead makes all of that one case. The header is patched after every byte is out, the boundary block is written by both cursors, and both are simply revisits - a revisit is what fetching handles. osFileFetch is the service that allows it, and is the read side of the write. A run of bytes in one segment costs nothing extra; a switch between segments costs two block operations, and a source file has a few dozen switches and several thousand bytes. Two bugs, both a pointer meaning two things: putAt took the cursor to advance in DP2 and then wanted DP2 for the window's address. A call puts DP2 back the way it was AT THE CALL, so the step at the end moved whatever the last call had left there - the window walked off across memory while the cursor stood still. It goes in memory now, like the block did in S1, and for the same reason. The size the file is created at could not be right. How many vectors are actually installed is not known until the second pass has resolved their handlers, and by then the file must already exist to be written into - so Keys, which brings one vector, came out four bytes short. Teaching the first pass to count them meant teaching it about devices, and about a Boot line in a loadable program not being installed at all, which is two ways to disagree with the second pass about what a file contains. So osFileDone is told the size instead. A writer asks for as much as the file could possibly come to - the whole of it plus four bytes for every vector DECLARED, which no file can exceed - and says what it really came to at the end. The blocks it did not use go back to the free count. Asking for too much costs a moment; asking for too little writes off the end of a file. That is a better service for it, not a workaround. A writer that cannot know its size until the last byte is the ordinary case, and it is exactly the case this whole rung exists for. 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
9f7dffdeca
commit
fb7b224bbb
@@ -102,7 +102,13 @@
|
||||
; registers and cannot write more than 65,535.
|
||||
osFileStart 0d29 ; DP0 names it, DP3 is whole blocks, A is bytes in the tail.
|
||||
osFileWrite 0d30 ; DP1 is the block, A and B together are which one, from zero.
|
||||
osFileDone 0d31 ; No arguments. The temporary takes the name.
|
||||
osFileDone 0d31 ; DP3 is whole blocks and A the tail: how big it turned out to be.
|
||||
osFileFetch 0d32 ; DP1 is where it goes, A and B are which block. Reads one back.
|
||||
|
||||
; osFileFetch is what lets a program keep only ONE block of a file in hand while writing
|
||||
; it. Anything producing two parts of a file at once - an assembler, whose source says
|
||||
; #Program and #Data in whatever order it likes - has to be able to put a block down, go
|
||||
; and write somewhere else, and pick it up again where it left off.
|
||||
; Q is zero if it read, DP3 is how many of its bytes are the file's:
|
||||
; a whole 0d256 except in a last block that is short. That count is
|
||||
; why DP3 answers and not a register - 0d256 does not fit in a byte,
|
||||
|
||||
Reference in New Issue
Block a user