; 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 one bank this touches ---- ; ; Six: 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 0d6 OUTA 0xE3 INIA 0x3B OUTA 0xE2 INIA 0x03 OUTA 0xE8 ; ---- And it does NOT take the screen ---- ; ; osTakeScreen saves what is on the screen and puts it back at exit, and this program ; called it at first. That was wrong in a way worth keeping written down: it saves the ; screen AS IT WAS BEFORE, so the line printed below - the line whose whole job is to still ; be there afterwards - was wiped out by the restore that was meant to be tidy. ; ; It was not needed either. NOTHING THIS TOUCHES IS THE SHELL'S: the only memory it writes ; is the map of the screen nobody is looking at, and the only register it leaves changed is ; which screen that is - which the system puts back itself. ; ; A program that wants a screen saved should ask. A program that damages nothing should ; not, and asking anyway is not free - it costs the screen it was standing on. SETD.0 Message SWI osPrintString INIA 0x0A OUTA 0x00 ; The assembler has no escapes; a newline is a byte. ; Key mode, so a key arrives when it is pressed rather than when Return is. INIA 0x01 OUTA 0x02 ; ---- Every cell of the other screen, in one command ---- ; ; TEN, and the reason is worth the paragraph. Fill writes one byte, and a cell is two, so ; whatever is filled with is BOTH the tile and the attribute - there is no filling a map ; with a tile and a colour that are different numbers. ; ; Ten as a tile is an asterisk, because the font begins at the space and glyph n is ; character n plus thirty two. Ten as an attribute is one of the eight REVERSED schemes, ; whose paper is a colour and whose ink is black. So the screen comes out green, covered in ; black asterisks, without a single tile being redefined. ; ; The high nibble stays at nought, which the manual asks for: it is reserved. That is the ; real constraint on which byte this can be - it has to be under sixteen to leave the ; nibble alone, and eight or over to land on a reversed scheme whose PAPER is the colour. ; ; Which means THIS PROGRAM WRITES NOTHING BUT THE SCREEN NOBODY IS LOOKING AT. It was ; drawn with a tile of its own first, and that tile was one the system copies the font back ; over at every exit - so the screen it had filled turned blank the moment it left, and a ; check that it had been put back could not tell a restored screen from an abandoned one. ; A picture that depends on the atlas does not survive leaving. INIA 0d6 OUTA 0xE3 INIA 0x40 OUTA 0xE4 RSTA OUTA 0xE5 INIA 0x0A OUTA 0xE2 ; Fill takes the byte it writes from SourceLow. 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 ; One line and no newline in it. A string literal is terminated where it ends, so a second ; one after a 0x0A byte would never be reached - printing stops at the first terminator. The ; newline is written to the console directly instead. Message: "A screen is drawn where you cannot see it. A key shows it, another comes back."