Fill the window, let it be resized, and make black black
Three things a person looking at a real screen found in five minutes, none of which the headless tests could have seen. THE PICTURE FILLED A QUARTER OF THE WINDOW. The window opened at the largest screen the device can make, doubled, and then drew a 320 by 200 mode at that same doubling - so three quarters of it was bezel. It now takes the largest whole-number scale that fits: the two modes are exactly a factor of two apart and the window opens at twice the larger, so both fill it exactly, at four and at two. Changing mode changes how sharp the screen is rather than how big it is. Whole numbers on purpose. A 320 by 200 picture stretched by 2.7 has some rows twice as tall as their neighbours, which on eight pixel glyphs is the difference between text and mush. THE WINDOW WOULD NOT RESIZE. It does now, and the picture rescales to whatever it becomes, still in whole pixels and still centred. How big somebody wants a screen is not the machine's business. AND BLACK WAS NOT BLACK. Both the paper and the bezel were tinted towards green, on the theory that a phosphor never was neutral. On a real screen that reads as a fault rather than as character: a background that is nearly black looks like a background that failed to be black. Paper is black now and ink is a neutral grey, because a default should be the unsurprising thing - anything with a point of view about colour is 254 palette entries away and belongs to a program. The bezel is a clearly lighter grey, so what is left over when the window's shape does not match the picture's looks like a bezel rather than like more screen. The two checks that name the waking colours name the new ones. That they had to change is the check working: they say what they depend on rather than assuming it. 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
773b0f8add
commit
6f8ad42277
@@ -38,8 +38,14 @@ int videoRows(void) { return rowsFor(mode); }
|
||||
// Only two, and the rest of the palette left at zero. A program that wants colour sets it,
|
||||
// and a machine that guessed sixteen entries on its behalf would be sixteen entries it had
|
||||
// to overwrite. What it must not do is wake up unable to show text at all.
|
||||
static const uint8_t defaultInk[3] = { 0xDC, 0xE6, 0xDC };
|
||||
static const uint8_t defaultPaper[3] = { 0x10, 0x14, 0x12 };
|
||||
//
|
||||
// BLACK IS BLACK AND GREY IS GREY. These were tinted towards green to begin with, on the
|
||||
// theory that a phosphor never was neutral, and on a real screen it read as a fault rather
|
||||
// than as character - a background that is nearly black looks like a background that failed
|
||||
// to be black. A default should be the unsurprising thing; anything with a point of view
|
||||
// about colour is 254 entries away and belongs to a program.
|
||||
static const uint8_t defaultInk[3] = { 0xD8, 0xD8, 0xD8 };
|
||||
static const uint8_t defaultPaper[3] = { 0x00, 0x00, 0x00 };
|
||||
|
||||
void videoLoadFont(void) {
|
||||
// One bit a pixel becomes one byte a pixel: index 1 where the font has a dot and 0
|
||||
|
||||
+28
-10
@@ -29,9 +29,8 @@
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
|
||||
// The window is the largest screen the video device can produce, scaled up because a 320 by
|
||||
// 200 window is a postage stamp on a modern display. A smaller mode is drawn into the middle
|
||||
// of it rather than resizing the window out from under whoever is looking at it.
|
||||
// The window opens at the largest screen the device can produce, doubled, because a 640 by
|
||||
// 400 window is small on a modern display and a 320 by 200 one is a postage stamp.
|
||||
#define SCREEN_SCALE 2
|
||||
|
||||
// ---- Running without a window ----
|
||||
@@ -79,16 +78,32 @@ static void presentFrame(void) {
|
||||
frame);
|
||||
}
|
||||
BeginDrawing();
|
||||
// Not black. The border around a smaller mode should look like a machine with a screen
|
||||
// on, rather than like a window that failed to open.
|
||||
ClearBackground((Color){ 18, 22, 20, 255 });
|
||||
// Clearly not the screen. What is left over when the window's shape does not match the
|
||||
// picture's is a bezel, and it should look like one rather than like more screen.
|
||||
ClearBackground((Color){ 40, 40, 40, 255 });
|
||||
if (width > 0 && height > 0) {
|
||||
// Centred, so changing mode moves the picture rather than the window.
|
||||
// ---- Filling the window, in whole pixels ----
|
||||
//
|
||||
// The largest whole-number scale that still fits. Whole numbers because a 320 by 200
|
||||
// picture stretched by 2.7 is a picture with some rows twice as tall as their
|
||||
// neighbours, which on eight pixel glyphs is the difference between text and mush.
|
||||
//
|
||||
// The two modes are exactly a factor of two apart and the window opens at twice the
|
||||
// larger, so both fill it exactly: 320 by 200 at four, and 640 by 400 at two.
|
||||
// Changing mode therefore changes how sharp the screen is and not how big it is.
|
||||
const int windowWidth = GetScreenWidth();
|
||||
const int windowHeight = GetScreenHeight();
|
||||
int scale = windowWidth / width;
|
||||
const int fits = windowHeight / height;
|
||||
if (fits < scale) scale = fits;
|
||||
if (scale < 1) scale = 1;
|
||||
const int drawnWidth = width * scale;
|
||||
const int drawnHeight = height * scale;
|
||||
Rectangle from = { 0, 0, (float)width, (float)height };
|
||||
Rectangle to = {
|
||||
(float)((VIDEO_MAX_WIDTH * SCREEN_SCALE - width * SCREEN_SCALE) / 2),
|
||||
(float)((VIDEO_MAX_HEIGHT * SCREEN_SCALE - height * SCREEN_SCALE) / 2),
|
||||
(float)(width * SCREEN_SCALE), (float)(height * SCREEN_SCALE)
|
||||
(float)((windowWidth - drawnWidth) / 2),
|
||||
(float)((windowHeight - drawnHeight) / 2),
|
||||
(float)drawnWidth, (float)drawnHeight
|
||||
};
|
||||
DrawTexturePro(screenTexture, from, to, (Vector2){ 0, 0 }, 0.0f, WHITE);
|
||||
}
|
||||
@@ -156,6 +171,9 @@ int main(int argc, char *argv[]) {
|
||||
machineRunSlice(&machine);
|
||||
}
|
||||
} else {
|
||||
// Resizable, because how big somebody wants a screen is not the machine's business.
|
||||
// The picture is rescaled to whatever the window becomes, in whole pixels.
|
||||
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
|
||||
InitWindow(VIDEO_MAX_WIDTH * SCREEN_SCALE, VIDEO_MAX_HEIGHT * SCREEN_SCALE,
|
||||
"Segan Voyager");
|
||||
SetTargetFPS(60);
|
||||
|
||||
Reference in New Issue
Block a user