Make the screen come back on the machine people actually run
Found by running it: Grid exits and the shell prints its prompt into the grid, with the view up to seven pixels out of alignment. Three faults, and the first is the one that made the other two visible. MAKE RUN-VOYAGER HAD NO SCRATCH DRIVE. It gives drive 1 to Disks/personal.img, which is a file and not volatile, so there was nowhere to keep a screen - osTakeScreen answered no and the whole feature silently did not happen. It was tested with --ram-disk and shipped without one, which is as good a description of testing the wrong machine as I can write. There is now a RAM disk in drive 2, after the personal disk so that drive 1 stays the one that is yours. A PROGRAM TOLD NO MUST COPE. A refusal is not a fault, it means doing what the program did before there was anywhere to save a screen. Grid deleted its own tidying up when it started asking, so being refused left the grid on screen with a prompt written into it. It clears up again when refused, and only then. AND THE SYSTEM ALWAYS LEAVES THE SCREEN USABLE. The fine scroll registers go back to zero at every program exit, whether or not the picture could be saved: the console draws in whole cells, so a view three pixels into one puts every character three pixels out for ever. That is not part of saving a screen and should never have depended on it. Both paths are checked now. With a scratch drive the screen comes back cell for cell; without one, no grid is left behind. Breaking either fails one of them and not the other. 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
ab72443b99
commit
2a29cebc6b
@@ -51,6 +51,9 @@ start:
|
|||||||
; at exit - and if it says it cannot, this carries on anyway, because it did before there
|
; at exit - and if it says it cannot, this carries on anyway, because it did before there
|
||||||
; was anywhere to put it.
|
; was anywhere to put it.
|
||||||
SWI osTakeScreen
|
SWI osTakeScreen
|
||||||
|
MVQA
|
||||||
|
SETD.0 ScreenKept
|
||||||
|
STA.0 ; Nought means the system will put it back.
|
||||||
|
|
||||||
CALL putTile
|
CALL putTile
|
||||||
CALL putPalette
|
CALL putPalette
|
||||||
@@ -135,6 +138,58 @@ finished:
|
|||||||
;
|
;
|
||||||
; All of it is osTakeScreen's now, and it gives back what was actually there rather than
|
; All of it is osTakeScreen's now, and it gives back what was actually there rather than
|
||||||
; what a clean machine looks like.
|
; what a clean machine looks like.
|
||||||
|
;
|
||||||
|
; ---- Unless it said no ----
|
||||||
|
;
|
||||||
|
; A machine with no volatile drive has nowhere to keep a screen, and answers so. Being told
|
||||||
|
; no is not a fault and not a reason to stop: it means doing what this program did before
|
||||||
|
; there was anywhere to put one, which is leaving a blank screen rather than a grid with
|
||||||
|
; somebody's prompt printed into it.
|
||||||
|
SETD.0 ScreenKept
|
||||||
|
LDA.0
|
||||||
|
BRA gridScreenKept
|
||||||
|
|
||||||
|
RSTA
|
||||||
|
OUTA 0x34
|
||||||
|
OUTA 0x36 ; The origins, or the shell looks at a corner of the map.
|
||||||
|
|
||||||
|
INIA 0d4
|
||||||
|
OUTA 0xE3
|
||||||
|
INIA 0x40
|
||||||
|
OUTA 0xE4
|
||||||
|
RSTA
|
||||||
|
OUTA 0xE5
|
||||||
|
OUTA 0xE2 ; Tile nought is the space and attribute nought is plain.
|
||||||
|
INIA 0x80
|
||||||
|
OUTA 0xE6
|
||||||
|
RSTA
|
||||||
|
OUTA 0xE7
|
||||||
|
INIA 0x02
|
||||||
|
OUTA 0xE8 ; Fill the whole map with it.
|
||||||
|
|
||||||
|
; And the colours the machine wakes up in, which is as near as this can get to the ones it
|
||||||
|
; took: grey on black is what plain text has always been here.
|
||||||
|
INIA 0d4
|
||||||
|
OUTA 0xE3
|
||||||
|
INIA 0xFC
|
||||||
|
OUTA 0xE4
|
||||||
|
RSTA
|
||||||
|
OUTA 0xE5
|
||||||
|
OUTA 0xE9
|
||||||
|
OUTA 0xE9
|
||||||
|
OUTA 0xE9
|
||||||
|
OUTA 0xE9
|
||||||
|
INIA 0xD8
|
||||||
|
OUTA 0xE9
|
||||||
|
OUTA 0xE9
|
||||||
|
OUTA 0xE9
|
||||||
|
RSTA
|
||||||
|
OUTA 0xE9
|
||||||
|
|
||||||
|
INIA 0x01
|
||||||
|
OUTA 0x05 ; Cleared, which also puts the cursor home.
|
||||||
|
|
||||||
|
gridScreenKept:
|
||||||
RSTA
|
RSTA
|
||||||
OUTA 0x02 ; Line mode, the way it was found.
|
OUTA 0x02 ; Line mode, the way it was found.
|
||||||
RSTA ; splitlint[redundant-assignment]: an exit status, not a mode
|
RSTA ; splitlint[redundant-assignment]: an exit status, not a mode
|
||||||
@@ -358,6 +413,8 @@ everyCell:
|
|||||||
|
|
||||||
#Base 0x2000
|
#Base 0x2000
|
||||||
|
|
||||||
|
ScreenKept:
|
||||||
|
0x00
|
||||||
FineDown:
|
FineDown:
|
||||||
0x00
|
0x00
|
||||||
FineAcross:
|
FineAcross:
|
||||||
|
|||||||
@@ -843,7 +843,9 @@ walks back and forth without `Copy` itself knowing there is more than one disk.
|
|||||||
|
|
||||||
### A Disk Of Your Own:
|
### A Disk Of Your Own:
|
||||||
|
|
||||||
`make run-voyager` puts a second disk in **drive 1**, at `Disks/personal.img`. It is made the
|
`make run-voyager` puts a second disk in **drive 1**, at `Disks/personal.img`, and a scratch
|
||||||
|
drive made of memory in **drive 2**. The scratch drive is what `osTakeScreen` writes to; drive
|
||||||
|
1 is yours and comes after nothing, so adding the scratch drive later did not renumber it. It is made the
|
||||||
first time it is needed and then left alone: never rebuilt, never cleaned, never committed.
|
first time it is needed and then left alone: never rebuilt, never cleaned, never committed.
|
||||||
|
|
||||||
That last part is the point. Everything else in this repository is made from source and can be
|
That last part is the point. Everything else in this repository is made from source and can be
|
||||||
@@ -884,6 +886,16 @@ and console mode it already puts back. Q is zero if that was arranged; a machine
|
|||||||
volatile drive says no, and **a program told no should carry on regardless**, because it was
|
volatile drive says no, and **a program told no should carry on regardless**, because it was
|
||||||
going to before this existed.
|
going to before this existed.
|
||||||
|
|
||||||
|
**A program told no must cope.** There is no volatile drive on every machine, and a refusal is
|
||||||
|
not a fault - it means doing what the program would have done before there was anywhere to
|
||||||
|
save a screen. `Grid` clears up after itself when refused, which is the difference between a
|
||||||
|
clean prompt and a prompt printed into somebody's grid.
|
||||||
|
|
||||||
|
**The system always leaves the screen usable, refusal or not.** The fine scroll registers go
|
||||||
|
back to zero at every program exit, because the console draws in whole cells and a view three
|
||||||
|
pixels into one puts every character three pixels out for ever. That is true whether or not
|
||||||
|
the picture could be saved, so it is not part of the saving.
|
||||||
|
|
||||||
**It is not automatic, and that is the point.** Saving on every program start would be cheap
|
**It is not automatic, and that is the point.** Saving on every program start would be cheap
|
||||||
enough, but restoring on every exit would be wrong: `dir`, `Files` and `Say` print and stop,
|
enough, but restoring on every exit would be wrong: `dir`, `Files` and `Say` print and stop,
|
||||||
and their output is the reason you ran them. A program that says nothing behaves exactly as
|
and their output is the reason you ran them. A program that says nothing behaves exactly as
|
||||||
|
|||||||
@@ -2090,6 +2090,14 @@ screenGiveDone:
|
|||||||
screenGiveNone:
|
screenGiveNone:
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
; The registers a console cannot work without, put back. Not the picture - that is
|
||||||
|
; screenGive's, and only happens for a program that asked.
|
||||||
|
screenSane:
|
||||||
|
RSTA
|
||||||
|
OUTA 0x37
|
||||||
|
OUTA 0x38 ; No fraction of a cell in either direction.
|
||||||
|
RET
|
||||||
|
|
||||||
; Video memory as bank 4, which is what makes it reachable at all. Bank 3 is the disk's; see
|
; Video memory as bank 4, which is what makes it reachable at all. Bank 3 is the disk's; see
|
||||||
; the table in the CosmOS README, which exists because a program once took 3.
|
; the table in the CosmOS README, which exists because a program once took 3.
|
||||||
screenBank:
|
screenBank:
|
||||||
@@ -3072,6 +3080,16 @@ handleExit:
|
|||||||
SETD.1 LastStatus
|
SETD.1 LastStatus
|
||||||
STA.1
|
STA.1
|
||||||
|
|
||||||
|
; ---- The screen made usable, whether or not the picture can be given back ----
|
||||||
|
;
|
||||||
|
; A fraction of a cell is never what anybody wants left behind: the console draws in whole
|
||||||
|
; cells, so a view three pixels into one puts every character three pixels out for ever.
|
||||||
|
; That is true whether or not there was anywhere to save the picture, so it is not part of
|
||||||
|
; the saving - a program refused by osTakeScreen still must not leave the shell squinting.
|
||||||
|
;
|
||||||
|
; Before screenGive, so that a restored screen's own registers win.
|
||||||
|
CALL screenSane
|
||||||
|
|
||||||
; What was on the screen before this program had it, if it asked for that.
|
; What was on the screen before this program had it, if it asked for that.
|
||||||
CALL screenGive
|
CALL screenGive
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ Snake.sbx 2164
|
|||||||
Keys.sbx 664
|
Keys.sbx 664
|
||||||
Say.sbx 156
|
Say.sbx 156
|
||||||
Break.sbx 149
|
Break.sbx 149
|
||||||
Grid.sbx 479
|
Grid.sbx 559
|
||||||
notes.txt 21
|
notes.txt 21
|
||||||
Apps <dir>
|
Apps <dir>
|
||||||
hi.script 121
|
hi.script 121
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Snake.sbx 2164
|
|||||||
Keys.sbx 664
|
Keys.sbx 664
|
||||||
Say.sbx 156
|
Say.sbx 156
|
||||||
Break.sbx 149
|
Break.sbx 149
|
||||||
Grid.sbx 479
|
Grid.sbx 559
|
||||||
notes.txt 21
|
notes.txt 21
|
||||||
Apps <dir>
|
Apps <dir>
|
||||||
hi.script 121
|
hi.script 121
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
CosmOS
|
CosmOS
|
||||||
> it says: before Grid
|
> it says: before Grid
|
||||||
finished
|
finished
|
||||||
> finished
|
> [2J[Hfinished
|
||||||
> > it says: after Grid
|
> > it says: after Grid
|
||||||
finished
|
finished
|
||||||
> greet.sbx 211
|
> greet.sbx 211
|
||||||
@@ -11,7 +11,7 @@ Snake.sbx 2164
|
|||||||
Keys.sbx 664
|
Keys.sbx 664
|
||||||
Say.sbx 156
|
Say.sbx 156
|
||||||
Break.sbx 149
|
Break.sbx 149
|
||||||
Grid.sbx 479
|
Grid.sbx 559
|
||||||
notes.txt 21
|
notes.txt 21
|
||||||
Apps <dir>
|
Apps <dir>
|
||||||
hi.script 121
|
hi.script 121
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Snake.sbx 2164
|
|||||||
Keys.sbx 664
|
Keys.sbx 664
|
||||||
Say.sbx 156
|
Say.sbx 156
|
||||||
Break.sbx 149
|
Break.sbx 149
|
||||||
Grid.sbx 479
|
Grid.sbx 559
|
||||||
notes.txt 21
|
notes.txt 21
|
||||||
Apps <dir>
|
Apps <dir>
|
||||||
hi.script 121
|
hi.script 121
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ Snake.sbx 2164
|
|||||||
Keys.sbx 664
|
Keys.sbx 664
|
||||||
Say.sbx 156
|
Say.sbx 156
|
||||||
Break.sbx 149
|
Break.sbx 149
|
||||||
Grid.sbx 479
|
Grid.sbx 559
|
||||||
notes.txt 21
|
notes.txt 21
|
||||||
Apps <dir>
|
Apps <dir>
|
||||||
hi.script 121
|
hi.script 121
|
||||||
|
|||||||
@@ -860,6 +860,20 @@ SAME="$(python3 "$ROOT/Tests/samescreen.py" "$BUILD/before.ppm" "$BUILD/after.pp
|
|||||||
&& result ok "a program gives the screen back" "every row it did not write on is as it was" \
|
&& result ok "a program gives the screen back" "every row it did not write on is as it was" \
|
||||||
|| result no "a program gives the screen back" "$SAME"
|
|| result no "a program gives the screen back" "$SAME"
|
||||||
|
|
||||||
|
# ---- And when there is nowhere to put it ----
|
||||||
|
#
|
||||||
|
# The same program on a machine with no volatile drive. osTakeScreen answers no, and a program
|
||||||
|
# told no does what it did before there was anywhere to save a screen: it clears up after
|
||||||
|
# itself. What must NOT happen is the shell printing its prompt into somebody's grid, which is
|
||||||
|
# what happened the day the run targets had no scratch drive and this check did not exist.
|
||||||
|
timeout 30 "$EMU" --fast --cycles 200000000 --keyboard "$BUILD/after.keys" \
|
||||||
|
--screen "$BUILD/noscratch.ppm" --disk "$ROOT/Tests/build/disks/cosmos.img" \
|
||||||
|
"$BUILD/cosmos.bin" > "$BUILD/noscratch.out" 2>&1 || true
|
||||||
|
LEFT="$(python3 "$ROOT/Tests/periodic.py" "$BUILD/noscratch.ppm" grid)"
|
||||||
|
[ "$LEFT" != "yes" ] \
|
||||||
|
&& result ok "and clears up when it cannot be kept" "no grid left on the screen" \
|
||||||
|
|| result no "and clears up when it cannot be kept" "the grid is still there"
|
||||||
|
|
||||||
# ---- Clearing puts the cursor back at the top ----
|
# ---- Clearing puts the cursor back at the top ----
|
||||||
#
|
#
|
||||||
# A screen with nothing on it and a cursor half way down it is not a cleared screen. This
|
# A screen with nothing on it and a cursor half way down it is not a cleared screen. This
|
||||||
|
|||||||
@@ -172,6 +172,17 @@ COSMOS_DISK = $(PROG_BUILD)/cosmos.img
|
|||||||
# once it exists make never looks at it again.
|
# once it exists make never looks at it again.
|
||||||
PERSONAL_DISK = Disks/personal.img
|
PERSONAL_DISK = Disks/personal.img
|
||||||
|
|
||||||
|
# ---- And a drive made of memory, as drive 2 ----
|
||||||
|
#
|
||||||
|
# 2,048 blocks, half a megabyte, gone when the machine stops. The system keeps there whatever
|
||||||
|
# it wants back later and cannot hold - the screen a program took, and whatever comes after
|
||||||
|
# that. A machine without one does without: osTakeScreen answers no and a program told no
|
||||||
|
# carries on.
|
||||||
|
#
|
||||||
|
# AFTER the personal disk, so drive 1 stays the one that is yours. A scratch drive that took
|
||||||
|
# drive 1 would renumber somebody's disk the day it was added.
|
||||||
|
SCRATCH_BLOCKS = 2048
|
||||||
|
|
||||||
|
|
||||||
# VOYAGER IS NOT IN THE HARD LIST. Everything below it - the assembler, the disk tool, the
|
# VOYAGER IS NOT IN THE HARD LIST. Everything below it - the assembler, the disk tool, the
|
||||||
# linter, the whole test suite - has to build on a machine with no graphics library at all,
|
# linter, the whole test suite - has to build on a machine with no graphics library at all,
|
||||||
@@ -608,13 +619,13 @@ $(PERSONAL_DISK):
|
|||||||
@echo " again - not clean, not a rebuild. Delete it by hand if you want a new one."
|
@echo " again - not clean, not a rebuild. Delete it by hand if you want a new one."
|
||||||
|
|
||||||
run-cosmos: $(COSMOS_DISK) $(PERSONAL_DISK)
|
run-cosmos: $(COSMOS_DISK) $(PERSONAL_DISK)
|
||||||
$(EMU_RUN) --disk $(COSMOS_DISK) --disk $(PERSONAL_DISK)
|
$(EMU_RUN) --disk $(COSMOS_DISK) --disk $(PERSONAL_DISK) --ram-disk $(SCRATCH_BLOCKS)
|
||||||
|
|
||||||
# The same disk with the system handed over directly instead, which is what a debugger does:
|
# The same disk with the system handed over directly instead, which is what a debugger does:
|
||||||
# memory is placed from outside and nothing on the disk is consulted about it. Useful when the
|
# memory is placed from outside and nothing on the disk is consulted about it. Useful when the
|
||||||
# thing being debugged is the boot chain itself, since it skips the boot chain.
|
# thing being debugged is the boot chain itself, since it skips the boot chain.
|
||||||
run-cosmos-direct: $(COSMOS) $(COSMOS_DISK) $(PERSONAL_DISK)
|
run-cosmos-direct: $(COSMOS) $(COSMOS_DISK) $(PERSONAL_DISK)
|
||||||
$(EMU_RUN) --disk $(COSMOS_DISK) --disk $(PERSONAL_DISK) $(COSMOS)
|
$(EMU_RUN) --disk $(COSMOS_DISK) --disk $(PERSONAL_DISK) --ram-disk $(SCRATCH_BLOCKS) $(COSMOS)
|
||||||
|
|
||||||
# ---- The same disk, on the machine with a screen ----
|
# ---- The same disk, on the machine with a screen ----
|
||||||
#
|
#
|
||||||
@@ -626,10 +637,10 @@ run-cosmos-direct: $(COSMOS) $(COSMOS_DISK) $(PERSONAL_DISK)
|
|||||||
# an image full of programs written for the old one - and they will draw whatever the old way
|
# an image full of programs written for the old one - and they will draw whatever the old way
|
||||||
# now means. Making the disk a dependency of running it is what stops that being a puzzle.
|
# now means. Making the disk a dependency of running it is what stops that being a puzzle.
|
||||||
run-voyager: $(COSMOS_DISK) $(PERSONAL_DISK)
|
run-voyager: $(COSMOS_DISK) $(PERSONAL_DISK)
|
||||||
$(VOY_RUN) --disk $(COSMOS_DISK) --disk $(PERSONAL_DISK)
|
$(VOY_RUN) --disk $(COSMOS_DISK) --disk $(PERSONAL_DISK) --ram-disk $(SCRATCH_BLOCKS)
|
||||||
|
|
||||||
run-voyager-direct: $(COSMOS) $(COSMOS_DISK) $(PERSONAL_DISK)
|
run-voyager-direct: $(COSMOS) $(COSMOS_DISK) $(PERSONAL_DISK)
|
||||||
$(VOY_RUN) --disk $(COSMOS_DISK) --disk $(PERSONAL_DISK) $(COSMOS)
|
$(VOY_RUN) --disk $(COSMOS_DISK) --disk $(PERSONAL_DISK) --ram-disk $(SCRATCH_BLOCKS) $(COSMOS)
|
||||||
|
|
||||||
# Pull in the dependency rules the assembler wrote with -M, so that touching a library
|
# Pull in the dependency rules the assembler wrote with -M, so that touching a library
|
||||||
# reassembles every program that includes it.
|
# reassembles every program that includes it.
|
||||||
|
|||||||
Reference in New Issue
Block a user