Compare commits

...
4 Commits
Author SHA1 Message Date
jurjen.ladeniusandClaude Opus 4.8 d2f9b35356 Inset the logo's lower-right stroke from the bars' right edge
The leg sat flush against the middle bar's right end, looking tacked on.
Move it left so both bars overhang it on the right and it crosses the
middle bar like a real glyph stroke. The leg/mid-bar crossing gets its
own palette entry (pal8), lit during both the mid bar's and the leg's
fade so neither shows a gap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 00:02:33 +02:00
jurjen.ladeniusandClaude Opus 4.8 9b554187af Restore Japanese-glyph logo shape with evened bars
The uniform-thickness pass had dropped the bars' left overhangs, turning
the logo into a pinwheel (swastika-like). Restore the original
firehawk.sc5 layout — a vertical spine crossed by two bars that overhang
it on both sides, plus a hanging lower-right stroke — but even out the
weights: both bars and the leg are a uniform 6px, with the spine slightly
thicker (8px) to keep the original glyph's character.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 23:56:22 +02:00
jurjen.ladeniusandClaude Opus 4.8 961aa89196 Make FH logo stroke thickness uniform
Give every stroke a 6px thickness (stem and right leg width 6, both
crossbars height 6) instead of the previous mix (stem 10, leg 4,
bars 4-5), and recenter the logo. The F+H now reads evenly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 23:44:35 +02:00
jurjen.ladeniusandClaude Opus 4.8 cdc7bc545d Fix MSX2+ horizontal scroll and rework FH logo animation
- Enable single-page horizontal scrolling (R#25 SP2=1) so the scroll
  offset wraps within the 256px page. Without it the V9958 default
  (two-page) scroll revealed the wrong VRAM page, making new tiles
  appear on the opposite edge during horizontal moves.
- Replace the rectangle-approximated FH logo with strokes matching the
  original firehawk.sc5 artwork. The F+H is drawn as partitioned fills
  (crossbar arms, stem, right leg) with dedicated palette entries for
  the two stem/crossbar crossings, so each horizontal then each
  vertical shimmers in and out gap-free before the whole logo holds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 23:40:09 +02:00
2 changed files with 71 additions and 29 deletions
Binary file not shown.
+71 -29
View File
@@ -726,25 +726,35 @@ static const u16 g_DefaultPal[16] = {
0x0171, 0x0373, 0x0661, 0x0664, 0x0411, 0x0265, 0x0555, 0x0777 0x0171, 0x0373, 0x0661, 0x0664, 0x0411, 0x0265, 0x0555, 0x0777
}; };
// Fade palette entry [idx] through brightness sequence 1..7..7..6..0 // Fade a set of palette entries up (black->white) and back down to black
// (mirrors BASIC GOSUBs 100/300/500/700: FOR I=1 TO 30: NEXT I ≈ 5 VBlanks) // together, so a stroke made of several palette entries shimmers as one shape.
static void LogoFade(u8 idx, u8 delay_halts) static void LogoFadeSet(const u8* idx, u8 n, u8 delay_halts)
{ {
static const u8 seq[15] = {1,2,3,4,5,6,7,7,6,5,4,3,2,1,0}; static const u8 seq[15] = {1,2,3,4,5,6,7,7,6,5,4,3,2,1,0};
for (u8 s = 0; s < 15; s++) { for (u8 s = 0; s < 15; s++) {
u8 lvl = seq[s]; u16 c = ((u16)seq[s] << 8) | ((u16)seq[s] << 4) | seq[s];
u16 c = ((u16)lvl << 8) | ((u16)lvl << 4) | lvl; for (u8 k = 0; k < n; k++) VDP_SetPaletteEntry(idx[k], c);
VDP_SetPaletteEntry(idx, c);
for (u8 h = 0; h < delay_halts; h++) Halt(); for (u8 h = 0; h < delay_halts; h++) Halt();
} }
} }
// GOSUB 1000 inner body: set all 4 palette entries to the same grey level, 5 Halts each. // The logo is a Japanese-letter-like glyph (from the original firehawk.sc5): a
static void LogoFadeAllColors(u8 lvl) // vertical spine with two crossing bars that overhang it on BOTH sides, plus a
{ // short hanging stroke on the lower right. Each stroke shimmers in and out on
u16 c = ((u16)lvl << 8) | ((u16)lvl << 4) | lvl; // its own before the whole logo lights up. Because the spine and bars overlap,
for (u8 idx = 2; idx <= 5; idx++) { VDP_SetPaletteEntry(idx, c); Halt(); Halt(); Halt(); Halt(); Halt(); } // the two crossing points get their OWN palette entries (6, 7) that are lit
} // during BOTH the bar's turn and the spine's turn — so neither the horizontals
// nor the verticals ever show a gap. Strokes are partitioned (no shared pixels):
// pal2 = top bar (overhangs) pal3 = spine (excl. crossings) pal6 = top/spine crossing
// pal4 = mid bar (overhangs) pal5 = lower-right stroke pal7 = mid/spine crossing
// pal8 = mid-bar/leg crossing (lit during both the mid bar's and the leg's turn)
// The spine is a touch thicker than the (evened) bars/leg, keeping the original
// glyph's weight. Origin X and all widths are even so the byte-aligned HMMV
// fills land on pixel boundaries.
#define LOGO_OX 108 // logo origin X (even: keeps HMMV fills pixel-aligned)
#define LOGO_OY 73 // logo origin Y
#define LOGO_SW 8 // spine width
#define LOGO_BT 6 // bar height / leg width (evened)
static void ShowLogoAnimation(void) static void ShowLogoAnimation(void)
{ {
@@ -756,30 +766,54 @@ static void ShowLogoAnimation(void)
VDP_ClearVRAM(); VDP_ClearVRAM();
VDP_DisableSprite(); VDP_DisableSprite();
// Blank all 16 palette entries before enabling display // Blank all 16 palette entries so the strokes stay invisible until faded in.
for (u8 i = 0; i < 16; i++) for (u8 i = 0; i < 16; i++)
VDP_SetPaletteEntry(i, 0); VDP_SetPaletteEntry(i, 0);
// Draw FH logo using HMMV fills. // Draw the strokes. They are partitioned so no two share a pixel; the two
// pal2=f-crossbar, pal3=spine, pal4=h-crossbar, pal5=h-right-leg. // spine/bar crossings are separate fills (pal6, pal7). The spine sits at local
// Draw crossbars first, then spine overwrites their centre, then right leg. // x12 (width LOGO_SW); each bar overhangs it on the left (x8) and right.
VDP_CommandHMMV(118, 75, 28, 5, 0x22); VDP_CommandWait(); // f-crossbar // Spine: three segments not covered by a bar, so the crossings light separately.
VDP_CommandHMMV(118, 90, 28, 4, 0x44); VDP_CommandWait(); // h-crossbar VDP_CommandHMMV(LOGO_OX + 12, LOGO_OY + 0, LOGO_SW, 2, 0x33); VDP_CommandWait(); // spine: above top bar
VDP_CommandHMMV(122, 73, 10, 34, 0x33); VDP_CommandWait(); // spine VDP_CommandHMMV(LOGO_OX + 12, LOGO_OY + 8, LOGO_SW, 8, 0x33); VDP_CommandWait(); // spine: between bars
VDP_CommandHMMV(140, 88, 6, 19, 0x55); VDP_CommandWait(); // h right leg VDP_CommandHMMV(LOGO_OX + 12, LOGO_OY + 22, LOGO_SW, 12, 0x33); VDP_CommandWait(); // spine: below mid bar
// Top bar (height LOGO_BT): left overhang + spine crossing + right arm.
VDP_CommandHMMV(LOGO_OX + 8, LOGO_OY + 2, 4, LOGO_BT, 0x22); VDP_CommandWait(); // top bar: left overhang
VDP_CommandHMMV(LOGO_OX + 12, LOGO_OY + 2, LOGO_SW, LOGO_BT, 0x66); VDP_CommandWait(); // top crossing
VDP_CommandHMMV(LOGO_OX + 20, LOGO_OY + 2, 14, LOGO_BT, 0x22); VDP_CommandWait(); // top bar: right arm
// Middle bar (height LOGO_BT): left overhang + spine crossing + two right-arm
// pieces straddling the leg, with the leg/bar crossing (pal8) between them.
VDP_CommandHMMV(LOGO_OX + 8, LOGO_OY + 16, 4, LOGO_BT, 0x44); VDP_CommandWait(); // mid bar: left overhang
VDP_CommandHMMV(LOGO_OX + 12, LOGO_OY + 16, LOGO_SW, LOGO_BT, 0x77); VDP_CommandWait(); // mid/spine crossing
VDP_CommandHMMV(LOGO_OX + 20, LOGO_OY + 16, 4, LOGO_BT, 0x44); VDP_CommandWait(); // mid bar: arm before leg
VDP_CommandHMMV(LOGO_OX + 24, LOGO_OY + 16, LOGO_BT, LOGO_BT, 0x88); VDP_CommandWait(); // mid/leg crossing
VDP_CommandHMMV(LOGO_OX + 30, LOGO_OY + 16, 4, LOGO_BT, 0x44); VDP_CommandWait(); // mid bar: arm past leg
// Lower-right stroke (vertical, width LOGO_BT), inset from the right and crossing
// the middle bar. Drawn as the parts above and below that crossing.
VDP_CommandHMMV(LOGO_OX + 24, LOGO_OY + 14, LOGO_BT, 2, 0x55); VDP_CommandWait(); // leg: above mid bar
VDP_CommandHMMV(LOGO_OX + 24, LOGO_OY + 22, LOGO_BT, 12, 0x55); VDP_CommandWait(); // leg: below mid bar
VDP_EnableDisplay(TRUE); VDP_EnableDisplay(TRUE);
// Phase 1: verticals spine then right leg, each fades in and out // Reveal order: each horizontal shimmers, then each vertical, then the total.
LogoFade(3, 5); // Each crossbar lights its arms + its crossing; the stem lights its body +
LogoFade(5, 5); // both crossings — so every stroke appears as a complete shape.
static const u8 fadeTop[2] = {2, 6}; // top bar: arms + spine crossing
static const u8 fadeMid[3] = {4, 7, 8}; // mid bar: arms + spine crossing + leg crossing
static const u8 fadeStem[3] = {3, 6, 7}; // spine: body + both spine crossings
static const u8 fadeLeg[2] = {5, 8}; // leg: body + leg/mid-bar crossing
static const u8 fadeAll[7] = {2, 3, 4, 5, 6, 7, 8};
LogoFadeSet(fadeTop, 2, 5);
LogoFadeSet(fadeMid, 3, 5);
LogoFadeSet(fadeStem, 3, 5);
LogoFadeSet(fadeLeg, 2, 5);
// Phase 2: horizontals f-crossbar then h-crossbar, each fades in and out // The total: all strokes fade up together and hold.
LogoFade(2, 5); for (u8 lvl = 1; lvl <= 7; lvl++) {
LogoFade(4, 5); u16 c = ((u16)lvl << 8) | ((u16)lvl << 4) | lvl;
for (u8 k = 0; k < 7; k++) VDP_SetPaletteEntry(fadeAll[k], c);
// Phase 3: complete FH all four colors fade in together and hold for (u8 h = 0; h < 5; h++) Halt();
for (u8 lvl = 1; lvl <= 7; lvl++) LogoFadeAllColors(lvl); }
for (u8 h = 0; h < 150; h++) Halt(); for (u8 h = 0; h < 150; h++) Halt();
// Restore MSX2 default palette so SCREEN 0 text mode remains visible. // Restore MSX2 default palette so SCREEN 0 text mode remains visible.
@@ -961,6 +995,14 @@ void main(void)
VDP_ClearVRAM(); VDP_ClearVRAM();
VDP_DisableSprite(); // Software-only sprites: disable VDP hardware sprite layer VDP_DisableSprite(); // Software-only sprites: disable VDP hardware sprite layer
// Single-page horizontal scrolling (R#25 SP2=1). The default SP2=0 scrolls
// across TWO pages (512px), so a non-zero R#26/R#27 offset wraps the *next*
// VRAM page into the entering edge instead of column 0..63 of this page —
// which made the entering strip appear on the wrong side during horizontal
// scroll. SP2=1 makes the offset wrap within one 256px page, which is the
// behaviour the horizontal path in ScrollDraw() relies on.
VDP_SetHorizontalMode(R25_SP2);
// Software sprite: initialize direction and frame for this game. // Software sprite: initialize direction and frame for this game.
g_SprDir = SPR_SOUTH; // face south (toward exit) at game start g_SprDir = SPR_SOUTH; // face south (toward exit) at game start
g_SprFrame = 0; g_SprFrame = 0;