Give the screen a bitmap mode
V4. Mode 2 is 320 by 200 with a byte a pixel: no tile to look up and no attribute to add, the byte IS the palette index. Programs/Examples/picture.asm fills a whole one in 127 bytes of program and 47,498 cycles. IT 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 holding whatever the picture put there. Taking the screen means taking it. The palette moves to 0xFC00, the top of video memory, because it is the one thing that has to mean the same in every mode and 64,000 bytes of picture leaves nowhere in the middle for it to hide. That is a documented address, so the example, the tests and the manual move with it. A BITMAP HAS NO COLUMNS AND NO ROWS, and both registers read zero rather than a leftover from the last mode. The console asks: told there is no character screen, it has nowhere to put a glyph and draws nothing, while still saying everything down the serial line. The honest alternative is what a machine with shared video memory really does, which is scribble marks nobody can read across somebody's picture - honest and useless, since a program that has taken the screen has not stopped wanting to print. Six checks in Tests/video.sh, to 55: that the mode is 320 by 200, that a byte is one pixel's colour and only that pixel, that printing leaves a picture alone while the letter still goes out, and that the columns register says nought and then forty again. The example is worth reading for one thing beyond the mode: Fill leaves its destination past what it touched, so two hundred rows are drawn from one address set once. Working out where row n begins would be n times 320, and this machine has no multiply. 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
1174bd9af5
commit
13b20c8834
+32
-2
@@ -28,8 +28,18 @@ static uint8_t pixels[VIDEO_MAX_WIDTH * VIDEO_MAX_HEIGHT * 3];
|
||||
static int renderedWidth = 0;
|
||||
static int renderedHeight = 0;
|
||||
|
||||
static int columnsFor(uint8_t m) { return m == VIDEO_MODE_80x50 ? 80 : 40; }
|
||||
static int rowsFor(uint8_t m) { return m == VIDEO_MODE_80x50 ? 50 : 25; }
|
||||
// Zero in bitmap mode, where there are no characters. Everything that draws one checks, so
|
||||
// this is the single place the answer lives rather than a mode test in each of them.
|
||||
static int columnsFor(uint8_t m) {
|
||||
if (m == VIDEO_MODE_BITMAP) return 0;
|
||||
return m == VIDEO_MODE_80x50 ? 80 : 40;
|
||||
}
|
||||
static int rowsFor(uint8_t m) {
|
||||
if (m == VIDEO_MODE_BITMAP) return 0;
|
||||
return m == VIDEO_MODE_80x50 ? 50 : 25;
|
||||
}
|
||||
|
||||
int videoTextRows(void) { return rowsFor(mode); }
|
||||
|
||||
int videoColumns(void) { return columnsFor(mode); }
|
||||
int videoRows(void) { return rowsFor(mode); }
|
||||
@@ -231,6 +241,26 @@ uint8_t videoRead(uint8_t port) {
|
||||
}
|
||||
|
||||
void videoRender(void) {
|
||||
if (mode == VIDEO_MODE_BITMAP) {
|
||||
// ---- A byte a pixel, and nothing in the way ----
|
||||
//
|
||||
// No tile to look up and no attribute to add: the byte IS the palette index. Which
|
||||
// is the whole difference between the two kinds of screen - a tile mode costs the
|
||||
// CPU the number of cells that changed, and this costs it the number of pixels.
|
||||
const uint8_t *palette = videoRAM + VIDEO_PALETTE_BASE;
|
||||
const uint8_t *from = videoRAM + VIDEO_BITMAP_BASE;
|
||||
uint8_t *out = pixels;
|
||||
for (int at = 0; at < VIDEO_BITMAP_WIDTH * VIDEO_BITMAP_HEIGHT; at++) {
|
||||
const uint8_t *entry = palette + from[at] * VIDEO_PALETTE_BYTES;
|
||||
*out++ = entry[0];
|
||||
*out++ = entry[1];
|
||||
*out++ = entry[2];
|
||||
}
|
||||
renderedWidth = VIDEO_BITMAP_WIDTH;
|
||||
renderedHeight = VIDEO_BITMAP_HEIGHT;
|
||||
return;
|
||||
}
|
||||
|
||||
const int columns = columnsFor(mode);
|
||||
const int rows = rowsFor(mode);
|
||||
const int width = columns * VIDEO_CELL_PIXELS;
|
||||
|
||||
Reference in New Issue
Block a user