Files
SplitBit-Emulator/Programs/CosmOS/Apps/Flip.asm
T
AnachronautandClaude Opus 5 023362b05a A second screen, and one port to say which is shown
A screen drawn where it can be seen is seen half drawn. A program that
moves forty things and rewrites the map underneath them is wrong for as
long as it takes to put them all right, and at a megahertz that is long
enough to look at.

So the device brings a second screen bank, on port 0x3B, and port 0x3C
says which of the two is displayed. Everything a program draws into the
other one is invisible until one byte shows the whole of it at once.

ONE REGISTER IS ENOUGH, where the hardware this imitates needed two. The
other said which screen the CPU's window pointed at; there is no window
here, because a program reaches a bank through the memory controller by
its number. Writing to the screen that is not shown is a matter of naming
its bank, and the device never has to be told.

And a flip cannot tear: a frame is drawn from one bank in one go, so a
flip either happened before that frame or happens before the next. There
is nothing to race, where the real machines had to catch the few lines
between frames to swap in.

The console draws into whichever screen is displayed rather than one of
its own, so a fault message lands where somebody can read it even if a
game had flipped. And CosmOS puts the displayed screen back at exit, the
way it already puts back the cursor and the ink: a program that faulted
while flipped could not have, and a shell that only came out right for
programs which remembered would come out wrong the day one crashed.

Flip.asm is the worked example. It deliberately does NOT restore the
display itself - that is the point of the paragraph above, and it is what
makes the system's guarantee the thing under test rather than the
program's good manners. Written the other way round first, where it
passed with the guarantee deleted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
2026-09-02 10:31:29 -04:00

146 lines
4.8 KiB
NASM

; The screen nobody is looking at.
;
; The screen brings two map banks and shows one of them. Everything this program draws goes
; into the other, so the picture does not change at all while it is being built - and then
; one byte out of one port shows the whole of it at once.
;
; ---- Why that is worth a port ----
;
; A screen drawn where it can be seen is seen half drawn. A game that moves forty things and
; rewrites the map underneath them is WRONG for as long as it takes to put them all right,
; and at a megahertz that is long enough to look at. The machines this one is pretending to
; be had the same problem and solved it the same way, except that they had to catch the few
; lines between one frame and the next to do the swap in. Here a frame is drawn from one bank
; in one go, so a flip cannot land halfway through one and there is nothing to race.
;
; ---- What it costs ----
;
; A whole bank, which is 64K of somebody's memory - and nothing, which is the point. The
; second screen is memory the device brought, the same as the first, so a program that wants
; it registers it and a program that does not never pays for it.
;
; Written by Anachronaut
#Include services.asm
#Program
#Base 0x5000
start:
; ---- The two banks this touches ----
;
; Four is the atlas, where the tiles are. Six is the other screen: three is the disk's and
; four and five are the ones the system registers to save a screen with, so six is the
; first number free. Nothing hands these out - see the table in the CosmOS README.
INIA 0d4
OUTA 0xE3
INIA 0x30
OUTA 0xE2
INIA 0x03
OUTA 0xE8
INIA 0d6
OUTA 0xE3
INIA 0x3B
OUTA 0xE2
INIA 0x03
OUTA 0xE8
; The screen back afterwards, because the tile overwritten below is one the shell spells
; with. Refused is survivable and is not checked: there is nothing this could do about it,
; and the system puts the font back at exit whether or not it saved anything.
SWI osTakeScreen
SETD.0 Message
SWI osPrintString
; Key mode, so a key arrives when it is pressed rather than when Return is.
INIA 0x01
OUTA 0x02
; ---- Tile one, made solid ----
;
; Sixty four pixels of index one, FILLED rather than blitted, which is why this program
; carries no picture of its own.
INIA 0d4
OUTA 0xE3
RSTA
OUTA 0xE4
INIA 0x40
OUTA 0xE5 ; Tile one begins at sixty four.
INIA 0x01
OUTA 0xE2 ; Fill takes the byte it writes from SourceLow.
RSTA
OUTA 0xE6
INIA 0x40
OUTA 0xE7 ; Sixty four bytes of it.
INIA 0x02
OUTA 0xE8
; ---- And every cell of the other screen ----
;
; One byte fills both halves of a cell, so this is tile one and attribute one everywhere:
; the tile is index one at every pixel and the attribute adds sixteen to all of them, which
; comes out as a screen solidly in scheme one's ink.
INIA 0d6
OUTA 0xE3
INIA 0x40
OUTA 0xE4
RSTA
OUTA 0xE5
INIA 0x01
OUTA 0xE2
INIA 0x80
OUTA 0xE6
RSTA
OUTA 0xE7 ; The whole map, which is 0x8000 bytes.
INIA 0x02
OUTA 0xE8
; NOTHING HAS CHANGED ON THE SCREEN. Every byte of that went where nobody can see it, and
; the line printed above is still sitting there to prove it - which is the reason this
; waits here rather than flipping straight away. What a back buffer is for is not visible
; in the flip; it is visible in the time before one.
CALL waitKey
; And this is the whole of showing it.
INIA 0x01
OUTA 0x3C
CALL waitKey
; ---- Which screen is showing is NOT put back here ----
;
; On purpose, and it is the one thing in this program worth arguing about. The system
; restores it at exit, the same way it restores the cursor and the ink, and for the same
; reason: a program that FAULTED while flipped could not have put it back, and a shell that
; only came out right for programs which remembered would be a shell that came out wrong
; the day one crashed. What the person is looking at belongs to the system.
;
; The console mode below IS put back, because that is this program's own borrowing rather
; than something the system hands out.
RSTA
OUTA 0x02 ; Line mode again.
SWI osExit
; ---- A key, asked for rather than waited on ----
;
; The console holds one until somebody wants it, so nothing pressed while the map was being
; filled is lost - it is sitting there and this returns immediately, which is right. A key
; pressed is a key meant for this program.
waitKey:
INA 0x01
INIB 0x01 ; READY
AND
BRQ waitKey
INA 0x00 ; Taken, so the shell is not handed a key meant for this.
RET
#Data
#Base 0x3000
Message:
"A whole screen is about to be drawn where you cannot see it - this line will still\nbe here when it is done. Press a key to show it, and another to come back.\n"