diff --git a/STATUS.md b/STATUS.md index b685197..4e6952d 100644 --- a/STATUS.md +++ b/STATUS.md @@ -51,7 +51,7 @@ and speed on the 8 MHz machines. |------|--------------| | `tests/hostPort.c`, `tests/agiHost.c` | The whole interpreter on the build machine (JoeyLib's BLANK port): virtual 60 Hz time, a scripted keyboard, every frame resolved through the palette and hashed (FNV-1a) or saved as PPM. Fully reproducible. | | `tests/agiGame.py`, `tests/probes.py` | Builds AGI games from scratch (LOGIC assembler from the spec's command table, PICTURE byte lists, VIEW from text art, SOUND, WORDS.TOK, OBJECT). Each probe records what the interpreter did cycle by cycle into variables and prints them, so its frames do not depend on timing. | -| `scripts/oracle.sh` | Runs a probe (or a KQ3 session) on Sierra's interpreter in DOSBox under a private Xvfb, driven by xdotool, and on JoeyAGI, then compares every shot with `tests/tools/compareFrames.py` (EGA colours, text read with each interpreter's own font -- JoeyAGI's font is its own -- and Sierra's 40-column text mode compared cell by cell). A probe whose script says `record` is recorded instead: DOSBox's video capture (every 70 Hz frame) on Sierra's side, every frame on JoeyAGI's, compared by `tests/tools/shakeMeasure.py`. | +| `scripts/oracle.sh` | Runs a probe (or a KQ3 session) on Sierra's interpreter in DOSBox under a private Xvfb, driven by xdotool, and on JoeyAGI, then compares every shot with `tests/tools/compareFrames.py` (EGA colors, text read with each interpreter's own font -- JoeyAGI's font is its own -- and Sierra's 40-column text mode compared cell by cell). A probe whose script says `record` is recorded instead: DOSBox's video capture (every 70 Hz frame) on Sierra's side, every frame on JoeyAGI's, compared by `tests/tools/shakeMeasure.py`. | | `scripts/test-agi.sh` | The host gate: resources, probes and KQ3 sessions against `tests/expected/`. | A caution learned on the way: DOSBox's screenshot key (Ctrl+F5) reaches the @@ -63,7 +63,7 @@ checkpoints below were each taken with a single screenshot. The interpreter at the start (commit 96c72ca) was a VM/host split with many pieces stubbed: `sound` set its flag at once; `save.game`, `restore.game`, `status`, `show.obj`, `menu.input`, `obj.status.v` did nothing; -`restart.game` quit; object collisions and `block` were not modelled; +`restart.game` quit; object collisions and `block` were not modeled; `posn` tests were approximations; ego stepped a fixed 2 pixels; and an argv "starting room" let you skip "a title screen the VM can't yet advance through". The IIgs disk gate passed, but on the IIgs the old engine was the @@ -71,7 +71,7 @@ one drawing. Nearly every module was rewritten (agi.c, agiRes, agiPic, agiView, agiObj, agiText, agiVm) or written new (agiGfx, agiFont, agiInput, agiSound, -agiSave), each behaviour settled against the specifications and then against +agiSave), each behavior settled against the specifications and then against Sierra's interpreter. ## Subsystems @@ -97,7 +97,7 @@ Sierra's interpreter. | have.key | Works: a key this cycle that nothing else took; a logic that asks again in the same cycle (KQ3's help screen spins on it) waits a frame per ask and takes any key | `pictures`, `priority`, `textscreen`, `ego` probes; `screenshots/kq3-help-f1.png` | | Save / restore / restart | Work: restore rebuilds the picture from the script and ends the cycle so logic 0 sees f12 next (KQ3 relies on it); restart keeps menus and set.key mappings (KQ3 builds them only once) | `kq3-saverestore` session; restart + menu matches Sierra | | Memory | Logics other than 0 are freed at new.room and so are the views no object shows, as Sierra frees a room's resources | ASan run of every session clean | -| Picture output | Every machine pushes a picture rectangle with one jlSurfacePasteIndexed call, each AGI pixel doubled (colour runs through jlFillRect on the planar machines before, two jlDrawPixel calls per AGI pixel before that) | IIgs frame outside a moving object byte-identical to the old code; JoeyLib's UBER indexed checks on every port | +| Picture output | Every machine pushes a picture rectangle with one jlSurfacePasteIndexed call, each AGI pixel doubled (color runs through jlFillRect on the planar machines before, two jlDrawPixel calls per AGI pixel before that) | IIgs frame outside a moving object byte-identical to the old code; JoeyLib's UBER indexed checks on every port | ## Bugs found and fixed in this dive, with causes @@ -110,7 +110,7 @@ Sierra's interpreter. moved into the jlAlloc'd state). 2. **ST, Amiga, X68000: picture output.** Planar stages have no chunky bytes, and the fallback drew two jlDrawPixel calls per AGI pixel. Then runs of - one colour per row through jlFillRect. (An 8x8 tile path was tried first + one color per row through jlFillRect. (An 8x8 tile path was tried first and came out striped: jlTileT's bytes are in each port's own layout.) Since 2026-10-17 every machine pastes the rectangle with jlSurfacePasteIndexed (doubleWide), widened to whole 2-pixel pairs: IIgs @@ -118,8 +118,8 @@ Sierra's interpreter. drawn. 3. **Text attributes.** set.text.attribute in picture mode stores a background of white (or black); text.screen clears to that; on the text screen the - colours are used as given; clear.lines and clear.text.rect on the text - screen take the colour as a PC attribute byte (so 0..15 clear to black). + colors are used as given; clear.lines and clear.text.rect on the text + screen take the color as a PC attribute byte (so 0..15 clear to black). The old rule (background | 8) was wrong. 4. **Sound on at start.** Sierra's interpreter sets f9 itself (its status line reads "Sound:on" in a game that never touches f9). @@ -236,14 +236,14 @@ KQ3's own version, shown by the game). At startup `detectVersion` (agiRes.c) reads the version from AGIDATA.OVL, else from the AGI file, else takes 2.435, the version measured, into `game.interpreterVersion`; `agiQuirk()` answers from one table of version ranges (`kQuirkVersions`), -the one place per-version behaviour is decided. The IIgs disk now carries +the one place per-version behavior is decided. The IIgs disk now carries AGIDATA.OVL, and `resources-kq3` checks KQ3 reads as 2435. Only one Sierra interpreter, 2.435, was at hand, so whether the quirks differ between versions could not be measured: all three are on for 2.000 to 2.999 (every version JoeyAGI plays), and narrowing a range is a one-line change once another interpreter is measured. Off, each falls back to the -plain behaviour (a clipped window, an echo from the end of the typed text, +plain behavior (a clipped window, an echo from the end of the typed text, an exact line). - **AGI_QUIRK_WINDOW_BYTE_X -- print.at at column 0 or 1.** A window's box @@ -261,7 +261,7 @@ an exact line). the box and its top, bottom and left lines are drawn a row down, 91 in, and the right side and the text stay in place. Columns 2 and on are not affected. `winedge` probe: nine windows at columns 0 to 3, one to three - lines, on a coloured picture, open and closed: 18/18 frames identical. + lines, on a colored picture, open and closed: 18/18 frames identical. - **AGI_QUIRK_ECHO_STEPS_BACK -- set.cursor.char mid-line.** The input line echo keeps its own position: a redraw (Enter, accept.input) leaves it after the prompt, the text and the cursor; with a cursor set, a typed @@ -309,7 +309,7 @@ an exact line). Every AGI v2 command is implemented. "KQ3 uses" counts the command in KQ3's logics; "Probe" marks commands the probe games exercise against Sierra's interpreter (everything KQ3 uses is also exercised by the KQ3 sessions or -checkpoints). FIXED marks behaviour corrected in this dive's later half; +checkpoints). FIXED marks behavior corrected in this dive's later half; the earlier rewrite touched nearly every command. | # | Command | KQ3 uses | Probe | Status | @@ -419,7 +419,7 @@ the earlier rewrite touched nearly every command. | 0x66 | print.v | 27 | | works | | 0x67 | display | 70 | yes | works | | 0x68 | display.v | 5 | | works | -| 0x69 | clear.lines | 17 | yes | works; FIXED (text-screen colour is an attribute byte) | +| 0x69 | clear.lines | 17 | yes | works; FIXED (text-screen color is an attribute byte) | | 0x6A | text.screen | 3 | yes | works; FIXED (clears to the attribute background) | | 0x6B | graphics | 3 | yes | works | | 0x6C | set.cursor.char | 1 | yes | works (no cursor before it: FIXED; changed mid-line moves the echo as Sierra's: FIXED) | diff --git a/agi.c b/agi.c index cd4d475..49d00eb 100644 --- a/agi.c +++ b/agi.c @@ -43,7 +43,7 @@ #define STATUS_TEXT_MAX 160u -// The AGI palette: EGA's sixteen colours in JoeyLib's $0RGB. +// The AGI palette: EGA's sixteen colors in JoeyLib's $0RGB. static const uint16_t kAgiPalette[AGI_COLOR_COUNT] = { 0x000u, 0x00Au, 0x0A0u, 0x0AAu, 0xA00u, 0xA0Au, 0xA50u, 0xAAAu, @@ -82,16 +82,16 @@ static void changeRoom(void) { vmDiscardLogics(); agiViewDiscardUnused(); saveScriptClear(); - gAgi->playerControl = true; - gAgi->blockActive = false; - gAgi->horizon = AGI_DEFAULT_HORIZON; + gAgi->playerControl = true; + gAgi->blockActive = false; + gAgi->horizon = AGI_DEFAULT_HORIZON; gAgi->vars[VAR_PREV_ROOM] = gAgi->vars[VAR_ROOM]; gAgi->vars[VAR_ROOM] = gAgi->newRoomNumber; gAgi->vars[VAR_OBJ_EDGE_OBJ] = 0u; gAgi->vars[VAR_OBJ_EDGE] = 0u; gAgi->vars[VAR_BAD_WORD] = 0u; - ego = &gAgi->objects[AGI_EGO]; - gAgi->vars[VAR_EGO_VIEW] = ego->viewId; + ego = &gAgi->objects[AGI_EGO]; + gAgi->vars[VAR_EGO_VIEW] = ego->viewId; switch (gAgi->vars[VAR_EGO_EDGE]) { case AGI_EDGE_TOP: ego->y = AGI_MAX_Y; @@ -111,7 +111,7 @@ static void changeRoom(void) { gAgi->vars[VAR_EGO_EDGE] = AGI_EDGE_NONE; (void)vmLoadLogic(gAgi->vars[VAR_ROOM]); gAgi->logicLoaded[gAgi->vars[VAR_ROOM]] = true; - gAgi->flags[FLAG_ENTERED] = 0u; + gAgi->flags[FLAG_ENTERED] = 0u; gAgi->flags[FLAG_NEW_ROOM] = 1u; inputReset(); } @@ -127,7 +127,7 @@ static void cycle(void) { gAgi->vars[VAR_BAD_WORD] = 0u; if (gAgi->menuRequested) { gAgi->menuRequested = false; - chosen = textMenuInput(); + chosen = textMenuInput(); if (chosen != AGI_NO_CONTROLLER) { gAgi->controllers[chosen] = 1u; } @@ -157,11 +157,11 @@ static void cycle(void) { } steerEgo(ego); textUpdateStatus(); - gAgi->vars[VAR_OBJ_EDGE_OBJ] = 0u; - gAgi->vars[VAR_OBJ_EDGE] = 0u; - gAgi->flags[FLAG_NEW_ROOM] = 0u; - gAgi->flags[FLAG_RESTART] = 0u; - gAgi->flags[FLAG_RESTORED] = 0u; + gAgi->vars[VAR_OBJ_EDGE_OBJ] = 0u; + gAgi->vars[VAR_OBJ_EDGE] = 0u; + gAgi->flags[FLAG_NEW_ROOM] = 0u; + gAgi->flags[FLAG_RESTART] = 0u; + gAgi->flags[FLAG_RESTORED] = 0u; gAgi->flags[FLAG_FIRST_LOGIC0] = 0u; if (!gAgi->textMode) { objUpdateAll(); @@ -276,32 +276,32 @@ void agiResetState(void) { for (i = 0u; i < AGI_MAX_ITEMS; i++) { gAgi->itemRoom[i] = agiItemStartRoom(&gAgi->game, (uint8_t)i); } - gAgi->menuRequested = false; - gAgi->horizon = AGI_DEFAULT_HORIZON; - gAgi->blockActive = false; - gAgi->playerControl = true; - gAgi->picRow = DEFAULT_PIC_ROW; - gAgi->inputRow = DEFAULT_INPUT_ROW; - gAgi->statusRow = DEFAULT_STATUS_ROW; - gAgi->statusOn = false; - gAgi->inputOn = false; - gAgi->textMode = false; - gAgi->textFg = AGI_COLOR_WHITE; - gAgi->textBg = AGI_COLOR_BLACK; - gAgi->cursorChar = AGI_NO_CURSOR; - gAgi->windowOpen = false; - gAgi->inputLine[0] = '\0'; - gAgi->inputLen = 0u; - gAgi->lastLine[0] = '\0'; - gAgi->wordCount = 0u; - gAgi->newRoomPending = false; - gAgi->abortLogic = false; - gAgi->vars[VAR_CYCLE_DELAY] = DEFAULT_CYCLE_DELAY; - gAgi->vars[VAR_INPUT_MAX] = DEFAULT_INPUT_MAX; - gAgi->vars[VAR_FREE_PAGES] = DEFAULT_FREE_PAGES; - gAgi->vars[VAR_COMPUTER] = COMPUTER_IBM_PC; - gAgi->vars[VAR_SOUND_TYPE] = SOUND_PC; - gAgi->vars[VAR_MONITOR] = MONITOR_EGA; + gAgi->menuRequested = false; + gAgi->horizon = AGI_DEFAULT_HORIZON; + gAgi->blockActive = false; + gAgi->playerControl = true; + gAgi->picRow = DEFAULT_PIC_ROW; + gAgi->inputRow = DEFAULT_INPUT_ROW; + gAgi->statusRow = DEFAULT_STATUS_ROW; + gAgi->statusOn = false; + gAgi->inputOn = false; + gAgi->textMode = false; + gAgi->textFg = AGI_COLOR_WHITE; + gAgi->textBg = AGI_COLOR_BLACK; + gAgi->cursorChar = AGI_NO_CURSOR; + gAgi->windowOpen = false; + gAgi->inputLine[0] = '\0'; + gAgi->inputLen = 0u; + gAgi->lastLine[0] = '\0'; + gAgi->wordCount = 0u; + gAgi->newRoomPending = false; + gAgi->abortLogic = false; + gAgi->vars[VAR_CYCLE_DELAY] = DEFAULT_CYCLE_DELAY; + gAgi->vars[VAR_INPUT_MAX] = DEFAULT_INPUT_MAX; + gAgi->vars[VAR_FREE_PAGES] = DEFAULT_FREE_PAGES; + gAgi->vars[VAR_COMPUTER] = COMPUTER_IBM_PC; + gAgi->vars[VAR_SOUND_TYPE] = SOUND_PC; + gAgi->vars[VAR_MONITOR] = MONITOR_EGA; gAgi->flags[FLAG_FIRST_LOGIC0] = 1u; gAgi->flags[FLAG_SOUND] = 1u; saveScriptClear(); diff --git a/agi.h b/agi.h index 32d2d4a..3cd0e64 100644 --- a/agi.h +++ b/agi.h @@ -45,7 +45,7 @@ #define AGI_TEXT_ROWS 25u #define AGI_CELL_PX 8 -// Colours. The picture starts white with priority 4 (red) everywhere. +// Colors. The picture starts white with priority 4 (red) everywhere. #define AGI_COLOR_BLACK 0u #define AGI_COLOR_RED 4u #define AGI_COLOR_WHITE 15u @@ -184,7 +184,7 @@ extern const uint8_t kAgiFont[AGI_FONT_GLYPHS][AGI_FONT_ROWS]; // folder has one; otherwise the version the quirks were measured on. #define AGI_VERSION_MEASURED 2435u -// Behaviour of particular Sierra interpreter versions that games may lean +// Behavior of particular Sierra interpreter versions that games may lean // on; agiQuirk says whether the game's version has one (the version ranges // are agiRes.c's kQuirkVersions). typedef enum { diff --git a/agiGfx.c b/agiGfx.c index 1c5432d..7382061 100644 --- a/agiGfx.c +++ b/agiGfx.c @@ -1,10 +1,10 @@ // The picture buffers and the screen objects drawn into them. // // Like Sierra's interpreter, JoeyAGI keeps one 160x168 picture buffer pair -// -- a colour and a priority byte per AGI pixel -- that holds the picture +// -- a color and a priority byte per AGI pixel -- that holds the picture // with the visible objects blitted into it. An object's blit saves the // bytes under its cel, then draws the cel's pixels whose priority is at -// least the buffer's, writing the object's priority with the colour, so a +// least the buffer's, writing the object's priority with the color, so a // lower object drawn later stays hidden behind it. Erasing puts the saved // bytes back, so blits stack: the buffer is always erased in the reverse // order it was drawn. Objects that are not updated (stop.update) are drawn @@ -34,7 +34,7 @@ // Areas waiting to be copied to the stage; more are merged into one. #define DIRTY_MAX 24u #define NIBBLE_SHIFT 4u -// A cel run byte: the colour in the high nibble, the length in the low. +// A cel run byte: the color in the high nibble, the length in the low. #define RLE_COUNT_MASK 0x0Fu // add.to.pic's margin box: margins 0..3 are control values; 4 and above // mean no box. @@ -136,8 +136,8 @@ static void blitObject(uint8_t n) { } o->saveUnder = &gSaveArena[gSaveTop]; saveRect(o->saveUnder, left, o->blitY, o->blitW, o->blitH); - gSaveTop = (uint16_t)(gSaveTop + need); - o->blitted = true; + gSaveTop = (uint16_t)(gSaveTop + need); + o->blitted = true; gBlitStack[gBlitCount] = n; gBlitCount++; if ((o->flags & OBJ_FIX_PRIORITY) == 0u) { @@ -150,7 +150,7 @@ static void blitObject(uint8_t n) { // The screen as a shake beat shows it: moved SHAKE_DX right and SHAKE_DY // down over black. Chunky surfaces move their bytes; planar ones draw the -// screen as one big sprite (colour 0 is transparent, and the surface is +// screen as one big sprite (color 0 is transparent, and the surface is // black beneath). static void buildShifted(jlSurfaceT *shifted, const jlSurfaceT *normal) { jlSpriteT *sprite; @@ -349,7 +349,7 @@ static void restoreRect(const uint8_t *save, int16_t x, int16_t y, uint8_t w, ui } -// Keep a rectangle of both buffers, a row of colours then a row of +// Keep a rectangle of both buffers, a row of colors then a row of // priorities at a time (2 * w * h bytes). static void saveRect(uint8_t *save, int16_t x, int16_t y, uint8_t w, uint8_t h) { uint8_t row; @@ -642,13 +642,13 @@ void gfxShowObjectCel(uint8_t viewId) { void gfxShowPic(void) { - gPicShown = true; + gPicShown = true; gDirtyCount = 0u; gfxRestorePicture(); } -// show.pri.screen: the priority buffer as colours until a key. +// show.pri.screen: the priority buffer as colors until a key. void gfxShowPriority(void) { uint8_t *saved; diff --git a/agiInput.c b/agiInput.c index b3ff46a..fa801fe 100644 --- a/agiInput.c +++ b/agiInput.c @@ -140,7 +140,7 @@ static void handleKey(uint16_t key) { if (dir != AGI_DIR_NONE) { // A second press of the direction ego is walking stops it. if (gAgi->playerControl) { - gAgi->vars[VAR_EGO_DIR] = (gAgi->vars[VAR_EGO_DIR] == dir) ? AGI_DIR_NONE : dir; + gAgi->vars[VAR_EGO_DIR] = (gAgi->vars[VAR_EGO_DIR] == dir) ? AGI_DIR_NONE : dir; gAgi->objects[AGI_EGO].direction = gAgi->vars[VAR_EGO_DIR]; } return; @@ -319,7 +319,7 @@ void inputParse(const char *line) { while (n > 0u && text[n - 1u] == ' ') { n--; } - text[n] = '\0'; + text[n] = '\0'; gAgi->wordCount = 0u; gAgi->vars[VAR_BAD_WORD] = 0u; if (n == 0u) { @@ -430,8 +430,8 @@ void inputPoll(void) { void inputProcess(void) { uint16_t key; - gKeyUnused = false; - gHaveKeyAsked = false; + gKeyUnused = false; + gHaveKeyAsked = false; gAgi->vars[VAR_KEY] = 0u; while ((key = dequeue()) != AGI_KEY_NONE) { handleKey(key); diff --git a/agiObj.c b/agiObj.c index 8b4e57c..637c518 100644 --- a/agiObj.c +++ b/agiObj.c @@ -107,8 +107,8 @@ static void advanceCel(uint8_t n) { } if ((o->cycleMode == AGI_CYCLE_END_LOOP) ? (o->cel >= last) : (o->cel == 0u)) { gAgi->flags[o->loopFlag] = 1u; - o->flags = (uint16_t)(o->flags & (uint16_t)~OBJ_CYCLING); - o->cycleMode = AGI_CYCLE_NORMAL; + o->flags = (uint16_t)(o->flags & (uint16_t)~OBJ_CYCLING); + o->cycleMode = AGI_CYCLE_NORMAL; } break; default: @@ -186,7 +186,7 @@ static bool legalPosition(uint8_t n, int16_t x, int16_t y) { bool insideNow; bool insideNew; - o = &gAgi->objects[n]; + o = &gAgi->objects[n]; anyWater = false; allWater = true; signal = false; @@ -314,8 +314,8 @@ static void stopSpecialMotion(uint8_t n) { } } gAgi->flags[o->motionFlag] = 1u; - o->motion = AGI_MOTION_NORMAL; - o->direction = AGI_DIR_NONE; + o->motion = AGI_MOTION_NORMAL; + o->direction = AGI_DIR_NONE; if (n == AGI_EGO) { gAgi->vars[VAR_EGO_DIR] = AGI_DIR_NONE; } @@ -417,7 +417,7 @@ void objFixPosition(uint8_t n) { void objMoveTo(uint8_t n, uint8_t x, uint8_t y, uint8_t step, uint8_t flag) { AgiObjectT *o; - o = &gAgi->objects[n]; + o = &gAgi->objects[n]; o->motion = AGI_MOTION_MOVE; o->targetX = x; o->targetY = y; @@ -551,7 +551,7 @@ void objUnanimateAll(void) { gfxEraseAll(); for (i = 0u; i < AGI_MAX_OBJECTS; i++) { - o = &gAgi->objects[i]; + o = &gAgi->objects[i]; o->flags = OBJ_SKIP_STEP; o->motion = AGI_MOTION_NORMAL; o->cycleMode = AGI_CYCLE_NORMAL; diff --git a/agiPic.c b/agiPic.c index 5f23a99..bcdcd46 100644 --- a/agiPic.c +++ b/agiPic.c @@ -200,7 +200,7 @@ static void fill(const PicDrawT *d, int16_t x, int16_t y) { if (x < 0 || x > AGI_MAX_X || y < 0 || y > AGI_MAX_Y) { return; } - // Filling with the colour being searched for would never end. + // Filling with the color being searched for would never end. if (d->visualOn) { if (d->color == AGI_PIC_BG_COLOR) { return; @@ -393,7 +393,7 @@ static void plot(const PicDrawT *d, int16_t x, int16_t y) { } -// Plot the current pen centred on (x, y): a rectangle or circle size+1 +// Plot the current pen centered on (x, y): a rectangle or circle size+1 // wide and 2*size+1 tall, solid or masked by a texture's bits. static void plotPen(const PicDrawT *d, int16_t x, int16_t y, uint8_t texture) { uint8_t size; @@ -453,7 +453,7 @@ bool agiPicDecode(uint8_t *visual, uint8_t *priority, const uint8_t *data, uint1 d.color = 0u; d.priorityColor = 0u; d.pen = 0u; - pos = 0u; + pos = 0u; while (pos < length) { op = data[pos++]; switch (op) { diff --git a/agiRes.c b/agiRes.c index 848cc44..25dac9a 100644 --- a/agiRes.c +++ b/agiRes.c @@ -96,7 +96,7 @@ static const QuirkRangeT kQuirkVersions[AGI_QUIRK_COUNT] = { static void buildVolName(char *out, uint8_t volNum) { uint8_t n; - n = 0u; + n = 0u; out[n++] = 'V'; out[n++] = 'O'; out[n++] = 'L'; diff --git a/agiSound.c b/agiSound.c index f6a08d4..a8c8bc5 100644 --- a/agiSound.c +++ b/agiSound.c @@ -103,7 +103,7 @@ static void playNote(uint8_t voice, const uint8_t *note) { jlAudioNoise(gNoisePitch, gNoiseAtten); return; } - divisor = (uint16_t)(((uint16_t)(note[2] & DIVISOR_HIGH_MASK) << DIVISOR_HIGH_SHIFT) | (note[3] & DIVISOR_LOW_MASK)); + divisor = (uint16_t)(((uint16_t)(note[2] & DIVISOR_HIGH_MASK) << DIVISOR_HIGH_SHIFT) | (note[3] & DIVISOR_LOW_MASK)); gToneDivisor[voice] = divisor; gToneHz[voice] = (divisor == 0u) ? 0u : (uint16_t)(PSG_CLOCK_HZ / divisor); gToneAtten[voice] = atten; @@ -230,7 +230,7 @@ void soundStart(uint8_t soundId, uint8_t flag) { soundStop(); gFlag = flag; - gAgi->flags[flag] = 0u; + gAgi->flags[flag] = 0u; if (gAgi->flags[FLAG_SOUND] == 0u) { gAgi->flags[flag] = 1u; return; @@ -238,7 +238,7 @@ void soundStart(uint8_t soundId, uint8_t flag) { gData = agiResLoad(&gAgi->game, AGI_RES_SOUND, soundId, &gLength); if (gData == NULL || gLength < SOUND_HEADER_BYTES) { jlFree(gData); - gData = NULL; + gData = NULL; gAgi->flags[flag] = 1u; return; } diff --git a/agiText.c b/agiText.c index 8d30587..1cee624 100644 --- a/agiText.c +++ b/agiText.c @@ -6,7 +6,7 @@ // stage. In graphics mode Sierra's interpreter draws only white-on-black // style text: a set.text.attribute background other than black shows as // black on white. A message window is the wrapped text (30 columns at -// most) on white, inside a red frame, centred over the picture unless +// most) on white, inside a red frame, centered over the picture unless // print.at places it; the screen under it is saved and put back when it // closes. Geometry measured from Sierra's interpreter. @@ -129,7 +129,7 @@ static bool gShownSound; // ----- Internal helpers (alphabetical) ----- -// The text attribute's colours. On the text screen they are used as they +// The text attribute's colors. On the text screen they are used as they // are; on the picture a background makes the text black on white. static void attrColors(uint8_t *fg, uint8_t *bg) { if (gAgi->textMode) { @@ -147,7 +147,7 @@ static void attrColors(uint8_t *fg, uint8_t *bg) { } -// The column that centres a line of text on the screen. +// The column that centers a line of text on the screen. static uint8_t centerCol(const char *text) { size_t len; @@ -156,8 +156,8 @@ static uint8_t centerCol(const char *text) { } -// clear.lines and clear.text.rect: on the picture any colour but black -// clears to white; on the text screen the colour is a PC text attribute +// clear.lines and clear.text.rect: on the picture any color but black +// clears to white; on the text screen the color is a PC text attribute // whose high nibble is the background. static uint8_t clearColor(uint8_t color) { if (gAgi->textMode) { @@ -853,8 +853,8 @@ void textMenuAdd(const char *name) { m = &gAgi->menus[gAgi->menuCount]; strncpy(m->name, name, AGI_MENU_NAME_MAX); m->name[AGI_MENU_NAME_MAX] = '\0'; - m->firstItem = gAgi->menuItemCount; - m->itemCount = 0u; + m->firstItem = gAgi->menuItemCount; + m->itemCount = 0u; gAgi->menuCount++; } @@ -868,8 +868,8 @@ void textMenuAddItem(const char *name, uint8_t controller) { it = &gAgi->menuItems[gAgi->menuItemCount]; strncpy(it->text, name, AGI_MENU_ITEM_MAX); it->text[AGI_MENU_ITEM_MAX] = '\0'; - it->controller = controller; - it->enabled = true; + it->controller = controller; + it->enabled = true; gAgi->menuItemCount++; gAgi->menus[gAgi->menuCount - 1u].itemCount++; } @@ -878,10 +878,10 @@ void textMenuAddItem(const char *name, uint8_t controller) { // menu.input: let the player pick from the menus; a chosen, enabled // item's controller fires. Returns the controller, or 0xFF for none. uint8_t textMenuInput(void) { - uint8_t menu; - uint8_t item; - uint16_t key; - uint8_t result; + uint8_t menu; + uint8_t item; + uint16_t key; + uint8_t result; jlSurfaceT *stage; if (gAgi->menuCount == 0u) { @@ -945,7 +945,7 @@ void textMessageBox(const char *text) { } -// Open a message window: centred over the picture when row and col are +// Open a message window: centered over the picture when row and col are // negative (print), else with its text at (row, col) of the picture area // (print.at). width 0 means the default 30 columns. void textPrint(const char *text, int16_t row, int16_t col, uint8_t width) { @@ -980,7 +980,7 @@ void textPrint(const char *text, int16_t row, int16_t col, uint8_t width) { // set.text.attribute. Set on the picture, a background only says "white" // (the text screen then clears to white and shows the foreground on it); -// set on the text screen the colours are taken as they are. +// set on the text screen the colors are taken as they are. void textSetAttribute(uint8_t fg, uint8_t bg) { gAgi->textFg = (uint8_t)(fg & AGI_COLOR_MASK); gAgi->textBg = (uint8_t)(bg & AGI_COLOR_MASK); diff --git a/agiView.c b/agiView.c index 7e4f075..82d314b 100644 --- a/agiView.c +++ b/agiView.c @@ -2,9 +2,9 @@ // // A view is a header (loop count, description offset, a loop offset per // loop), each loop a cel count and cel offsets relative to the loop, each -// cel a width, height and a byte holding the transparent colour (low +// cel a width, height and a byte holding the transparent color (low // nibble) and the mirroring bits (high nibble), then run-length rows: a -// byte of colour (high nibble) and run length (low nibble), 0 ending a +// byte of color (high nibble) and run length (low nibble), 0 ending a // row. Loops that mirror each other share their cels; a cel whose // mirroring bit is set is drawn flipped in every loop except the one its // loop field names. @@ -114,7 +114,7 @@ static AgiViewT *load(const AgiGameT *game, uint8_t viewId) { view->loopCount = loopCount; view->loops = (AgiLoopT *)(view + 1); view->description = NULL; - descOffset = readLe16(&raw[VIEW_DESC_OFFSET_BYTE]); + descOffset = readLe16(&raw[VIEW_DESC_OFFSET_BYTE]); if (descOffset != 0u && descOffset < length) { view->description = (const char *)&raw[descOffset]; } diff --git a/agiVm.c b/agiVm.c index 0327927..0e33d47 100644 --- a/agiVm.c +++ b/agiVm.c @@ -338,7 +338,7 @@ static void cmdMisc(VmFrameT *f, uint8_t op, const uint8_t *a) { gAgi->playerControl = false; break; case CMD_PLAYER_CONTROL: - gAgi->playerControl = true; + gAgi->playerControl = true; gAgi->objects[AGI_EGO].motion = AGI_MOTION_NORMAL; break; case CMD_OBJ_STATUS_V: @@ -1379,12 +1379,12 @@ void vmCallLogic(uint8_t logicId) { jlLogF("call: no logic %u", (unsigned)logicId); return; } - raw = gAgi->logicRaw[logicId]; - frame.code = raw + LOGIC_HEADER_BYTES; - frame.length = codeLength(raw); - frame.pc = gAgi->logicScanStart[logicId]; - frame.logic = logicId; - frame.done = false; + raw = gAgi->logicRaw[logicId]; + frame.code = raw + LOGIC_HEADER_BYTES; + frame.length = codeLength(raw); + frame.pc = gAgi->logicScanStart[logicId]; + frame.logic = logicId; + frame.done = false; caller = gAgi->currentLogic; gAgi->currentLogic = logicId; gCallDepth++; diff --git a/tests/agiGame.py b/tests/agiGame.py index 3dc9be0..fe62507 100644 --- a/tests/agiGame.py +++ b/tests/agiGame.py @@ -362,7 +362,7 @@ def _rle(row, transparent): def cel(art, transparent=0): - # A cel from rows of hex digits; '.' is the transparent colour. + # A cel from rows of hex digits; '.' is the transparent color. rows = [[transparent if ch == "." else int(ch, 16) for ch in line] for line in art] return (rows, transparent) diff --git a/tests/expected/probes/textscreen.txt b/tests/expected/probes/textscreen.txt index 91f0739..4e39d01 100644 --- a/tests/expected/probes/textscreen.txt +++ b/tests/expected/probes/textscreen.txt @@ -1,3 +1,3 @@ g1 0222bfaa -t1 a3bbcf30 +t1 08874fc5 g2 0222bfaa diff --git a/tests/hostPort.c b/tests/hostPort.c index ac8f29d..2bfefa7 100644 --- a/tests/hostPort.c +++ b/tests/hostPort.c @@ -397,7 +397,7 @@ static void hostGoto(const char *label) { rewind(gScript); while (fgets(line, sizeof(line), gScript) != NULL) { line[strcspn(line, "#\r\n")] = '\0'; - p = line + strspn(line, " \t"); + p = line + strspn(line, " \t"); if (strncmp(p, "label", 5) != 0 || (p[5] != ' ' && p[5] != '\t')) { continue; } @@ -673,11 +673,11 @@ static void hostStep(void) { gSay = (op[0] == 's') ? HOST_SAY_TYPING : HOST_SAY_NONE; strncpy(gTypeBuf, op + ((op[0] == 's') ? 4 : 5), sizeof(gTypeBuf) - 1u); gTypeBuf[sizeof(gTypeBuf) - 1u] = '\0'; - gTypePos = 0u; + gTypePos = 0u; continue; } op[strcspn(op, "#")] = '\0'; - arg = op + strcspn(op, " \t"); + arg = op + strcspn(op, " \t"); if (*arg != '\0') { *arg = '\0'; arg++; @@ -904,7 +904,7 @@ static bool hostWaitStep(void) { } -// Steer ego one frame towards the walk's target with the arrow keys, +// Steer ego one frame toward the walk's target with the arrow keys, // pressing ego's own arrow again to stop it there. A walk to a place // keeps to the straight line from where it started, within // HOST_WALK_BAND pixels: it stays on one axis until it strays that far, @@ -1103,9 +1103,9 @@ void jlpPresent(const jlSurfaceT *src) { for (y = 0u; y < JL_SURFACE_HEIGHT; y++) { pal = src->palette[src->scb[y]]; for (x = 0u; x < JL_SURFACE_WIDTH; x++) { - byte = src->pixels[(uint32_t)y * JL_SURFACE_BYTES_PER_ROW + x / HOST_PIXELS_PER_BYTE]; - nib = (uint8_t)((x & 1u) ? (byte & 0x0Fu) : (byte >> 4)); - rgb = pal[nib]; + byte = src->pixels[(uint32_t)y * JL_SURFACE_BYTES_PER_ROW + x / HOST_PIXELS_PER_BYTE]; + nib = (uint8_t)((x & 1u) ? (byte & 0x0Fu) : (byte >> 4)); + rgb = pal[nib]; gDisplay[y][x][0] = (uint8_t)(((rgb >> 8) & 0x0Fu) * HOST_NIBBLE_SCALE); gDisplay[y][x][1] = (uint8_t)(((rgb >> 4) & 0x0Fu) * HOST_NIBBLE_SCALE); gDisplay[y][x][2] = (uint8_t)((rgb & 0x0Fu) * HOST_NIBBLE_SCALE); diff --git a/tests/probes.py b/tests/probes.py index ca4172a..fbbca4c 100755 --- a/tests/probes.py +++ b/tests/probes.py @@ -143,7 +143,7 @@ def recordFlag(L, flag, var): # ----- Probes ----- def probePictures(): - # Every picture command: colours on and off, corners, absolute and + # Every picture command: colors on and off, corners, absolute and # relative lines, nested fills (visual, priority-only and both) and # every pen: solid and splatter, circle and rectangle, all sizes. p = bytearray() @@ -493,7 +493,7 @@ def probeSetView(): def controlPicture(): - # Control lines on the priority screen, drawn in matching colours. + # Control lines on the priority screen, drawn in matching colors. p = bytearray() def vline(pri, x, y0, y1, vis): @@ -1086,7 +1086,7 @@ def probeTextScreen(): L.increment(V_CYCLE) with L.If(("equaln", V_CYCLE, 1)): L.text_screen() - L.display(2, 2, L.m("Text screen, default colours")) + L.display(2, 2, L.m("Text screen, default colors")) L.set_text_attribute(14, 1) L.display(4, 2, L.m("Yellow on blue")) L.set_text_attribute(0, 15) @@ -1144,7 +1144,7 @@ def probeShake(): def probeWindowEdge(): - # print.at windows at columns 0, 1 and 2 on a coloured picture. Sierra's + # print.at windows at columns 0, 1 and 2 on a colored picture. Sierra's # interpreter keeps a window's x in a byte and walks the screen as one # line of 160-pixel rows, so a box left of the screen (column 0 or 1) # is saved, filled and put back 256 pixels on -- a row down, 96 in -- diff --git a/tests/tools/compareFrames.py b/tests/tools/compareFrames.py index c347313..e63ccd6 100755 --- a/tests/tools/compareFrames.py +++ b/tests/tools/compareFrames.py @@ -1,15 +1,15 @@ #!/usr/bin/env python3 # compareFrames.py - compare a frame from Sierra's interpreter with one -# from JoeyAGI. Both are mapped to the 16 EGA colours, then compared one +# from JoeyAGI. Both are mapped to the 16 EGA colors, then compared one # 8x8 text cell at a time. JoeyAGI draws text in its own font, so a cell # where both frames hold a character -- read with each interpreter's font, # captured from the "font" probe -- counts as equal when the characters -# and colours match. Every other differing pixel is a real difference. +# and colors match. Every other differing pixel is a real difference. # # Sierra shows its text screen (text.screen, the inventory) in the PC's # 40-column text mode, which DOSBox captures at 360x400 (9x16 cells). # JoeyAGI draws the same screen on the bitmap, so those frames are -# compared cell by cell: blank or not, and the colours. +# compared cell by cell: blank or not, and the colors. # # compareFrames.py ORACLE JOEY [DIFF.png] [--fonts ORACLEFONT JOEYFONT] # prints "real=N text=M" and the cells that differ; exit 1 if any do. @@ -58,7 +58,7 @@ def egaGrid(im): def load(path): - # A frame as rows of EGA colour numbers, scaled to 320x200 if need be. + # A frame as rows of EGA color numbers, scaled to 320x200 if need be. im = Image.open(path).convert("RGB") if im.size != (WIDTH, HEIGHT): im = im.resize((WIDTH, HEIGHT), Image.NEAREST) @@ -67,13 +67,13 @@ def load(path): def textCells(grid, cellW, cellH): # Each cell as (blank?, foreground, background): the background is - # the cell's commonest colour. + # the cell's commonest color. cells = [] for cy in range(ROWS): row = [] for cx in range(COLS): - colours = Counter(grid[cy * cellH + y][cx * cellW + x] for y in range(cellH) for x in range(cellW)) - common = colours.most_common() + colors = Counter(grid[cy * cellH + y][cx * cellW + x] for y in range(cellH) for x in range(cellW)) + common = colors.most_common() if len(common) == 1: row.append((True, None, common[0][0])) else: @@ -93,7 +93,7 @@ def cellBits(g, cx, cy, bg): return tuple(tuple(1 if g[cy * CELL + y][cx * CELL + x] != bg else 0 for x in range(CELL)) for y in range(CELL)) -def cellColours(g, cx, cy): +def cellColors(g, cx, cy): return Counter(g[cy * CELL + y][cx * CELL + x] for y in range(CELL) for x in range(CELL)) @@ -108,12 +108,12 @@ def fontTemplates(path): def readCell(g, cx, cy, templates): # (character, foreground, background) or None when it is not text. - colours = cellColours(g, cx, cy) - if len(colours) > 2: + colors = cellColors(g, cx, cy) + if len(colors) > 2: return None - if len(colours) == 1: - return (" ", None, next(iter(colours))) - (a, na), (b, nb) = colours.most_common() + if len(colors) == 1: + return (" ", None, next(iter(colors))) + (a, na), (b, nb) = colors.most_common() for bg, fg in ((a, b), (b, a)): ch = templates.get(cellBits(g, cx, cy, bg)) if ch is not None: