Fixed assembler problems, added tetris tune example
h3rald h3rald@h3rald.com
Tue, 10 Feb 2026 15:28:39 +0100
3 files changed,
129 insertions(+),
2 deletions(-)
A
examples/korobeiniki.xyw
@@ -0,0 +1,58 @@
+.include "lib/macros.xyw" + +;;; Korobeiniki - Traditional Russian folk song (Tetris theme) +;;; Main melody - Type A theme + +;; Note duration macros +.macro quarter $0060 +.macro eighth $0030 +.macro half $00C0 + +;; Helper to play a note (using literal addresses to avoid nested macro issues) +.macro PLAY $40 STW $42 STW $01 $44 STB + +;; Main theme - Part A +;; E5 B4 C5 D5 | C5 B4 A4 A4 | C5 E5 D5 C5 | B4 B4 C5 D5 | E5 C5 A4 A4 + +quarter note.e5 PLAY +eighth note.b4 PLAY +eighth note.c5 PLAY +quarter note.d5 PLAY +eighth note.c5 PLAY +eighth note.b4 PLAY +quarter note.a4 PLAY +eighth note.a4 PLAY +eighth note.c5 PLAY +quarter note.e5 PLAY +eighth note.d5 PLAY +eighth note.c5 PLAY +quarter note.b4 PLAY +eighth note.b4 PLAY +eighth note.c5 PLAY +quarter note.d5 PLAY +quarter note.e5 PLAY +quarter note.c5 PLAY +quarter note.a4 PLAY +half note.a4 PLAY + +;; Main theme - Part B +;; D5 F5 A5 G5 | F5 E5 C5 C5 | E5 D5 C5 | B4 B4 C5 D5 | E5 C5 A4 A4 + +quarter note.d5 PLAY +eighth note.f5 PLAY +quarter note.a5 PLAY +eighth note.g5 PLAY +eighth note.f5 PLAY +quarter note.e5 PLAY +eighth note.c5 PLAY +quarter note.e5 PLAY +eighth note.d5 PLAY +eighth note.c5 PLAY +quarter note.b4 PLAY +eighth note.b4 PLAY +eighth note.c5 PLAY +quarter note.d5 PLAY +quarter note.e5 PLAY +quarter note.c5 PLAY +quarter note.a4 PLAY +half note.a4 PLAY
M
examples/lib/macros.xyw
→
examples/lib/macros.xyw
@@ -70,3 +70,44 @@ ;;; File types
.macro file.type.unspecified $00 .macro file.type.file $01 .macro file.type.directory $02 + +;;; Beeper notes + +.macro note.c4 $0106 ; 262 Hz +.macro note.cs4 $0115 ; 277 Hz +.macro note.d4 $0126 ; 294 Hz +.macro note.ds4 $0137 ; 311 Hz +.macro note.e4 $014A ; 330 Hz +.macro note.f4 $015D ; 349 Hz +.macro note.fs4 $0172 ; 370 Hz +.macro note.g4 $0188 ; 392 Hz +.macro note.gs4 $019F ; 415 Hz +.macro note.a4 $01B8 ; 440 Hz +.macro note.as4 $01D2 ; 466 Hz +.macro note.b4 $01EE ; 494 Hz + +.macro note.c5 $020B ; 523 Hz +.macro note.cs5 $022A ; 554 Hz +.macro note.d5 $024B ; 587 Hz +.macro note.ds5 $026E ; 622 Hz +.macro note.e5 $0293 ; 659 Hz +.macro note.f5 $02BA ; 698 Hz +.macro note.fs5 $02E4 ; 740 Hz +.macro note.g5 $0310 ; 784 Hz +.macro note.gs5 $033F ; 831 Hz +.macro note.a5 $0370 ; 880 Hz +.macro note.as5 $03A4 ; 932 Hz +.macro note.b5 $03DC ; 988 Hz + +.macro note.c6 $0417 ; 1047 Hz +.macro note.cs6 $0455 ; 1109 Hz +.macro note.d6 $0497 ; 1175 Hz +.macro note.ds6 $04DD ; 1245 Hz +.macro note.e6 $0527 ; 1319 Hz +.macro note.f6 $0575 ; 1397 Hz +.macro note.fs6 $05C8 ; 1480 Hz +.macro note.g6 $0620 ; 1568 Hz +.macro note.gs6 $067D ; 1661 Hz +.macro note.a6 $06E0 ; 1760 Hz +.macro note.as6 $0749 ; 1865 Hz +.macro note.b6 $07B8 ; 1976 Hz
M
xywasm.c
→
xywasm.c
@@ -482,10 +482,12 @@ xyw_dbg("Macro:\t\t%s -> %s\n", token, sym->contents);
// Save context position before macro expansion int saved_line = ctx->line; int saved_column = ctx->column; + int saved_src = ctx->src; + const char *saved_sp = ctx->sp; ctx->sp = sym->contents; assemble_string(ctx); - ctx->src = SRC_FILE; - ctx->sp = NULL; + ctx->src = saved_src; + ctx->sp = saved_sp; // Restore context position after macro expansion ctx->line = saved_line; ctx->column = saved_column;@@ -653,6 +655,27 @@ break;
} if (c == ';') { + // Consume rest of line (comment) + while (1) + { + if (ctx->src == SRC_FILE) + { + if (fread(&c, 1, 1, ctx->fp) != 1) + break; + } + else + { + if (!ctx->sp || *ctx->sp == '\0') + break; + c = *ctx->sp++; + } + if (c == '\n') + { + ctx->line++; + ctx->column = 1; + break; + } + } break; } if (length > DIRECTIVE_CONTENT_MAX_LENGTH)@@ -664,6 +687,11 @@ }
ctx->column++; contents[length++] = c; contents[length] = '\0'; + } + // Trim trailing whitespace from macro contents + while (length > 0 && (contents[length - 1] == ' ' || contents[length - 1] == '\t')) + { + contents[--length] = '\0'; } macro(ctx, token, contents); return 0;