// Space Taxi -- HUD (score / lives / level / current-fare strip). // // Lives in the bottom 3 tile-rows (y = 176..199) below the playfield. // Renders textual score / lives / level name / current fare via the // font asset (loaded by stRender). No fuel meter: the C64 original // has no fuel mechanic. The strip at $DBA2-$DBCB in the original game // is a per-frame Y-velocity status indicator ($6419), not a fuel bar. #include #include #include "spacetaxi.h" JOEYLIB_SEGMENT("STAXI") void stHudDraw(jlSurfaceT *stage, const StGameT *game) { char buf[32]; char livesBuf[ST_MAX_PADS + 1]; uint8_t i; // Wipe the HUD band with the level's border color (C64 $7D00 -> $D020). // Most canonical levels set both border and bg to 0 (black), so this // looks identical to the previous hardcoded ST_HUD_BG_COLOR for them. jlFillRect(stage, 0, (int16_t)(ST_HUD_ROW * ST_TILE_PIXELS), SURFACE_WIDTH, (int16_t)(ST_HUD_ROW_COUNT * ST_TILE_PIXELS), game->level.borderColor); // 4-digit score with a separator after the thousands digit, matching // the C64 HUD template at $43B1 ('___ . __'). The format puts the // ones digit at position 3 and uses '.' as a thousands marker. Range // is 0..9999; beyond that we wrap (the C64 BCD can't exceed 9999 // either). snprintf(buf, sizeof(buf), "%04lu.", (unsigned long)(game->score % 10000ul)); stRenderDrawText(stage, 0u, (uint8_t)ST_HUD_ROW, buf); // Lives indicator: graphic-ish "cabs remaining" -- one 'O' per life, // up to 9. C64 shows this as filled glyphs in color RAM ($DBDC etc). for (i = 0u; i < 9u && i < game->lives; i++) { livesBuf[i] = 'O'; } livesBuf[i] = '\0'; stRenderDrawText(stage, 7u, (uint8_t)ST_HUD_ROW, livesBuf); // Level name right-aligned in the 40-col HUD row. { uint8_t nameLen = (uint8_t)strlen(game->level.name); uint8_t col = (nameLen < ST_TILEMAP_W) ? (uint8_t)(ST_TILEMAP_W - nameLen) : 0u; stRenderDrawText(stage, col, (uint8_t)ST_HUD_ROW, game->level.name); } // Active fare display: where the current passenger wants to go // (or "PAD x WANTS y" when one is still waiting to be picked up). for (i = 0u; i < ST_MAX_PASSENGERS; i++) { const StPassengerT *p = &game->passengers[i]; if (p->active && p->onboard && p->destPad < game->level.padCount) { char dest = (char)game->level.pads[p->destPad].letter; snprintf(buf, sizeof(buf), "FARE %c", dest); stRenderDrawText(stage, 0u, (uint8_t)(ST_HUD_ROW + 1u), buf); break; } if (p->active && !p->onboard && p->currentPad < game->level.padCount) { char src = (char)game->level.pads[p->currentPad].letter; char dest = (p->destPad < game->level.padCount) ? (char)game->level.pads[p->destPad].letter : '?'; snprintf(buf, sizeof(buf), "PAD %c WANTS %c", src, dest); stRenderDrawText(stage, 0u, (uint8_t)(ST_HUD_ROW + 1u), buf); break; } } }