diff --git a/Source/Emulator/io.c b/Source/Emulator/io.c index 7160acc..19e0d7f 100644 --- a/Source/Emulator/io.c +++ b/Source/Emulator/io.c @@ -1071,7 +1071,23 @@ uint8_t OutputHandler(uint8_t DataByte, uint8_t Address) { case CONSOLE_COMMAND: if (DataByte == CONSOLE_COMMAND_CLEAR) { consoleClearScreen(0); - consoleTellTerminal("\033[2J"); + // ---- And the cursor goes home ---- + // + // A screen with nothing on it and a cursor half way down it is not a cleared + // screen: the next thing written lands where the last thing happened to + // leave off, which is a position that no longer means anything because + // whatever gave it meaning has just been erased. + // + // The attribute is deliberately NOT reset. Clearing is about what is on the + // screen and not about how the next thing will be drawn - a program that + // chose a colour and then cleared still wants that colour, the same as on a + // terminal, where 2J does not touch the graphics state either. + cursorRow = 0; + cursorColumn = 0; + consoleCursorMoved(); + // 2J empties it and H is what puts the cursor at the top. A terminal given + // only the first does exactly what this device did before this comment. + consoleTellTerminal("\033[2J\033[H"); } // Anything else does nothing. A command block reserved for later should be // quiet rather than fatal, the same as the screen's spare registers. diff --git a/SplitBit Programming Manual.md b/SplitBit Programming Manual.md index 9d27b81..b6f4733 100644 --- a/SplitBit Programming Manual.md +++ b/SplitBit Programming Manual.md @@ -694,7 +694,7 @@ Three more registers, because that is how this machine talks to everything else. | --- | --- | | 0x03 | Cursor row. Read and write. | | 0x04 | Cursor column. Read and write. | -| 0x05 | Command. Write 1 to clear the screen. | +| 0x05 | Command. Write 1 to clear the screen, which also puts the cursor at the top left. | | 0x06 | Attribute. Read and write. | **A cursor is shown only when it is asked for**, with bit 2 of the Control port, and status bit 4 says whether one is being shown. Off is the right default for a machine: a program painting its own screen does not want something blinking in the middle of it, and a system that reads lines from a person turns it on. diff --git a/Tests/expected/16x16Life.out b/Tests/expected/16x16Life.out index 53b44fe..32aca3c 100644 --- a/Tests/expected/16x16Life.out +++ b/Tests/expected/16x16Life.out @@ -1,4 +1,4 @@ - # + # # ### diff --git a/Tests/expected/16x16LifeModern.out b/Tests/expected/16x16LifeModern.out index b35b407..033e3fd 100644 --- a/Tests/expected/16x16LifeModern.out +++ b/Tests/expected/16x16LifeModern.out @@ -1,4 +1,4 @@ - # + # # ### diff --git a/Tests/expected/cosmosLife.out b/Tests/expected/cosmosLife.out index 5518d4e..bfd2203 100644 --- a/Tests/expected/cosmosLife.out +++ b/Tests/expected/cosmosLife.out @@ -1,6 +1,6 @@ CosmOS > loaded, starting at 4000 ->  # +>  # # ### diff --git a/Tests/expected/cosmosLifeKey.out b/Tests/expected/cosmosLifeKey.out index 34aebcb..8206a60 100644 --- a/Tests/expected/cosmosLifeKey.out +++ b/Tests/expected/cosmosLifeKey.out @@ -1,6 +1,6 @@ CosmOS > loaded, starting at 4000 ->  # +>  # # ### diff --git a/Tests/expected/cosmosSnake.out b/Tests/expected/cosmosSnake.out index 732a945..20c1cd8 100644 --- a/Tests/expected/cosmosSnake.out +++ b/Tests/expected/cosmosSnake.out @@ -1,6 +1,6 @@ CosmOS > loaded, starting at 4000 -> +----------------+ +> +----------------+ | | | | | | diff --git a/Tests/expected/cosmosStartup.out b/Tests/expected/cosmosStartup.out index d811bee..8240048 100644 --- a/Tests/expected/cosmosStartup.out +++ b/Tests/expected/cosmosStartup.out @@ -4,7 +4,7 @@ CosmOS ready. > echo and loud again and loud again and quiet again at the end -> > typed by hand +> > typed by hand > halted Execution halted. [exit 0] diff --git a/Tests/expected/cosmosStartupBad.out b/Tests/expected/cosmosStartupBad.out index 0823e92..65f6819 100644 --- a/Tests/expected/cosmosStartupBad.out +++ b/Tests/expected/cosmosStartupBad.out @@ -1,6 +1,6 @@ CosmOS startup.sh is there but does not begin with #!, so it was not run -> > typed by hand +> > typed by hand > halted Execution halted. [exit 0] diff --git a/Tests/video.sh b/Tests/video.sh index e2ebe7d..67c8384 100755 --- a/Tests/video.sh +++ b/Tests/video.sh @@ -718,6 +718,32 @@ TOTAL="$(grep -oE 'after [0-9]+' "$BUILD/poller.out" | grep -oE '[0-9]+')" && result ok "and the flag comes down when looked at" "$TOTAL cycles, so three frames passed" \ || result no "and the flag comes down when looked at" "$TOTAL cycles, too few to be three frames" +# ---- 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 +# writes three lines, clears, and writes one letter: it has to land in the very first cell. +# Before the cursor was homed it landed on the fourth row, on a screen that no longer had +# anything on the first three to justify it. +{ printf '#Program\nstart:\n' + say "AAA"; emit 10 + say "AAA"; emit 10 + say "AAA"; emit 10 + port 0x05 0x01 + say "X" + epilogue +} | run clearhome || exit 1 +inked clearhome 2 1 \ + && result ok "clearing puts the cursor home" "the next letter landed in the first cell" \ + || result no "clearing puts the cursor home" "nothing at 2,1" +# And the three lines really are gone, so the check above is about the cursor rather than +# about a clear that did nothing. +# The SECOND row, which nothing writes to either way - so this fails when the clear did not +# clear and passes whether or not the cursor was homed. Pointed at the fourth row it failed +# for the same reason as the check above, which is a second check that says nothing. +papered clearhome 2 9 \ + && result ok "and the screen really was cleared" "the second row is empty" \ + || result no "and the screen really was cleared" "there is still ink on the second row" + # And what scrolled off the top is still in the map, which is scrollback nothing had to keep. { printf '#Program\nstart:\n' say "A"