The screen is two banks: an atlas and a screen
Tiles and colours are written when a program loads; the map is written whenever anything moves. Sharing one 64K bank made them compete for room neither needed all of, and had a worse consequence than being cramped: a bitmap covers the whole bank, so entering bitmap mode destroyed the font. A program could not draw a picture and then say anything about it. Split, each gets a whole bank. The atlas holds the tiles and the palette, the screen holds the map or a bitmap, and a picture now costs the map and nothing else. It also leaves 48K free in the atlas, which is where the sprite table and a second page of tiles are going. No new mechanism was needed. A bank is registered by naming the port that owns it, so a device with two banks needs two ports that own memory: the base port keeps the atlas, since tiles have been at 0x0000 since there was a screen at all, and 0x3A owns the screen. The registry now answers honestly about which ports in the block bring memory, where it used to say all sixteen did. CosmOS never addresses video memory except in one place - the screen save, which walks 196 pages of it. The page number already says which bank a page is in, so screenBankFor works it out rather than keeping a second list beside screenPageFor. Grid and picture.asm register both banks; colours.asm only touches the palette and needed none of it. Tests/video.sh names the memory every write is for, because an address cannot: tile 5 and bitmap pixel 5 are both 0x0005, and a helper that guessed would be right for the tiles and silently wrong for a picture. And picture.asm gained a check, because this change broke it and nothing noticed - registering the second bank leaves DestBank pointing at it, so the palette went into the wrong one and the picture came out black. It was the only thing here found by looking rather than by a test. 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
2abc8281df
commit
66e7b84272
@@ -615,18 +615,41 @@ It follows that colour depth is free. The map is the same size whatever is behin
|
||||
|
||||
### Video Memory:
|
||||
|
||||
One bank, brought by the device and reached only through the memory controller, like the disk's buffer. It keeps what is in it between frames, so a program writes the part that changed and the rest stays as it was.
|
||||
**Two banks**, brought by the device and reached only through the memory controller, like the disk's buffer. They keep what is in them between frames, so a program writes the part that changed and the rest stays as it was.
|
||||
|
||||
| Address | Holds |
|
||||
Two rather than one because the two halves of a screen are written at completely different rates. The **atlas** is tiles and colours: put there when a program loads and then left alone. The **screen** is the map: rewritten as often as anything moves.
|
||||
|
||||
| Bank | Address | Holds |
|
||||
| --- | --- | --- |
|
||||
| Atlas | 0x0000 - 0x3FFF | Tile memory. 256 tiles of 8 by 8, one byte a pixel, so tile n begins at n times 64. |
|
||||
| Atlas | 0x4000 - 0xFBFF | Free. |
|
||||
| Atlas | 0xFC00 - 0xFFFF | The palette. 256 entries of four bytes: red, green, blue, and one unused. |
|
||||
| Screen | 0x0000 - 0x3FFF | Free in a tile mode. |
|
||||
| Screen | 0x4000 - 0xBFFF | The map. 128 rows of 256 bytes. |
|
||||
| Screen | 0x0000 - 0xF9FF | In bitmap mode, the picture instead: 64,000 bytes, one to a pixel. |
|
||||
|
||||
**The bitmap is the same memory as the map**, which is what shared video memory has always been. Going to bitmap mode does not clear the text screen - it stops calling it one, and coming back finds the map holding whatever the picture put there.
|
||||
|
||||
**What a picture no longer costs is the font.** The tiles and the palette are in the other bank, where a bitmap cannot reach them, so a program can draw a picture and then put readable text back on the screen without asking the character generator for its glyphs again. While the two shared a bank, drawing anything destroyed them.
|
||||
|
||||
The palette is in the atlas, at the top and out of the way, because it is written when a program loads rather than per frame - and because being out of the screen bank is what leaves a bitmap the whole of one.
|
||||
|
||||
Which bank is which is a property of the **address**, never of the mode: tiles and the palette are always in the atlas, the map and a bitmap always in the screen.
|
||||
|
||||
### Naming Them:
|
||||
|
||||
A bank is registered by naming the port that owns it, so a device with two banks needs two ports that own memory. The screen has them:
|
||||
|
||||
| Port | Owns |
|
||||
| --- | --- |
|
||||
| 0x0000 - 0x3FFF | Tile memory. 256 tiles of 8 by 8, one byte a pixel, so tile n begins at n times 64. |
|
||||
| 0x4000 - 0xBFFF | The map. 128 rows of 256 bytes. |
|
||||
| 0x0000 - 0xF9FF | In bitmap mode, the picture instead: 64,000 bytes, one to a pixel. |
|
||||
| 0xFC00 - 0xFFFF | The palette. 256 entries of four bytes: red, green, blue, and one unused. |
|
||||
| 0x30 | The atlas. |
|
||||
| 0x3A | The screen. |
|
||||
|
||||
**The bitmap is the same memory as the tiles and the map**, which is what shared video memory has always been, and there is nowhere else it could be: 64,000 bytes of picture in a 65,536 byte bank leaves room for nothing beside it. Going to bitmap mode does not clear the text screen - it stops calling it one, and coming back finds the tiles and the map holding whatever the picture put there.
|
||||
Nothing is read or written at 0x3A - it is a name for a bank, and the bus registry is where a program finds out it brings one. Asking the registry about the block gives an honest answer: those two ports say they bring memory and the other fourteen say they do not.
|
||||
|
||||
The palette is at the top, out of the way of both, because it is the one thing that means the same in every mode.
|
||||
The base port owns the atlas because tiles have been at 0x0000 since there was a screen at all. `Programs/Examples/picture.asm` registers both, and is the shortest thing to read that does.
|
||||
|
||||
**Registering the second one moves DestBank**, which is worth saying because it is easy to be caught by: RegisterBank takes the number being handed out in DestBank, so a program that registers two banks and then writes without setting DestBank again writes into the second one.
|
||||
|
||||
**A map row is a page whether the mode fills it or not**, and that is arithmetic rather than waste. This machine has no multiply, so on a 40 column screen every cursor move would otherwise cost a `row times 40` in software - a tax on the most common operation in the system. At a page a row there is no arithmetic at all: the row number is the high byte of the address and the doubled column is the low byte.
|
||||
|
||||
@@ -653,6 +676,8 @@ The high nibble is reserved and should be left at zero, so that a meaning can be
|
||||
| 0x36 | Scroll column. Which of the map's 128 columns is drawn at the left. |
|
||||
| 0x37 | Fine X. How many pixels into that column the screen begins, 0 to 7. |
|
||||
| 0x38 | Fine Y. How many pixels into that row the screen begins, 0 to 7. |
|
||||
| 0x39 | Command. Bit 0 copies the font back, bit 1 the sixteen colour schemes. |
|
||||
| 0x3A | Owns the screen bank. Not read or written. |
|
||||
|
||||
| Mode | Screen | Cells |
|
||||
| --- | --- | --- |
|
||||
|
||||
Reference in New Issue
Block a user