;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
;
; Auto-generated by Regenerator 2000 v0.9.17
; https://github.com/ricardoquesada/regenerator2000
;
; Exported from: c64_moving_tubes_lxt.regen2000proj
;
; Assemble with 64tass:
; 64tass -o c64_moving_tubes_lxt.prg c64_moving_tubes_lxt.asm
;
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; EXTERNAL LABELS
; zpa_ = Zero Page Absolute Address
; f_ = Field
; a_ = Absolute Address
; p_ = Pointer
; e_ = External Jump
; L_ = Other / User-defined
CPU_PORT = $01 ; x-ref: $21F5, $2EF1
KEY_BUF_COUNT = $c6 ; x-ref: $2EC1
music_ptr_lo = $fb ; x-ref: $10DE, $1113, $1120, $1131, $1137, $1141, $1268, $127D, ...
music_ptr_hi = $fc ; x-ref: $10E1, $1118, $113C, $1287, $1622
CHAR_COLOR = $0286 ; x-ref: $2E0E
IRQ_VECTOR_LO = $0314 ; IRQ ; x-ref: $2E9D
IRQ_VECTOR_HI = $0315 ; IRQ ; x-ref: $2E9A
NMI_VECTOR_LO = $0318 ; NMI ; x-ref: $2E16
exit_stub_buffer = $0340 ; x-ref: $2EF6, $2EFC
exit_stub_source_hi = $0344 ; x-ref: $21EE
exit_stub_dest_hi = $0347 ; x-ref: $21EB
SCREEN_RAM = $0400 ; x-ref: $0E1A
SCREEN_RAM_R1C0 = $0428 ; x-ref: $0E1F
SCREEN_RAM_R2C0 = $0450 ; x-ref: $2E36
SCREEN_RAM_R2C39 = $0477 ; x-ref: $2E1E
SCREEN_RAM_R6C39 = $0517 ; x-ref: $2E24
SCREEN_RAM_R11C0 = $05b8 ; x-ref: $2E39
SCREEN_RAM_R12C0 = $05e0 ; x-ref: $0E3A, $2EE9
SCREEN_RAM_R13C0 = $0608 ; x-ref: $0E3F
SCREEN_RAM_R13C23 = $061f ; x-ref: $0E90
SCREEN_RAM_R13C24 = $0620 ; x-ref: $0E8D
SCREEN_RAM_R13C39 = $062f ; x-ref: $2E29
SCREEN_RAM_R14C0 = $0630 ; x-ref: $2E3E
SCREEN_RAM_R15C0 = $0658 ; x-ref: $2E4E
SCREEN_RAM_R16C39 = $06a7 ; x-ref: $0ED5
SCREEN_RAM_R17C39 = $06cf ; x-ref: $0EDB, $2E2C
SCREEN_RAM_R18C39 = $06f7 ; x-ref: $0EE1
SCREEN_RAM_R19C39 = $071f ; x-ref: $0EE7
SCREEN_RAM_R20C0 = $0720 ; x-ref: $2E51
SCREEN_RAM_R21C0 = $0748 ; x-ref: $2E41
SCREEN_RAM_R22C0 = $0770 ; x-ref: $0E5A
SCREEN_RAM_R23C0 = $0798 ; x-ref: $0E5F
exit_backup_basic_area = $3200 ; x-ref: $21E2
COLOR_RAM_R12C0 = $d9e0 ; x-ref: $2EE3
COLOR_RAM_R14C0 = $da30 ; x-ref: $2E46
COLOR_RAM_R15C0 = $da58 ; x-ref: $2E56
COLOR_RAM_R20C0 = $db20 ; x-ref: $2E59
COLOR_RAM_R21C0 = $db48 ; x-ref: $2E49
e_E544 = $e544 ; x-ref: $2E11, $2ECB
e_E5AA = $e5aa ; x-ref: $2ED8
KERNAL_IRQ_HANDLER = $ea31 ; x-ref: $2ECE, $2ED1
e_EA7E = $ea7e ; x-ref: $23D1
KERNAL_RESET_VECTOR = $fce2 ; x-ref: $21F8
KERNAL_IOINITj = $fda3 ; $FDA3 (jmp) - initialize CIA & IRQ ; x-ref: $2EDB
KERNAL_NMI_HANDLER = $fec1 ; x-ref: $2E14
; ENUMS
; Enum: VicIIColors
VicIIColors = {
BLACK: $00,
WHITE: $01,
RED: $02,
CYAN: $03,
PURPLE: $04,
GREEN: $05,
BLUE: $06,
YELLOW: $07,
ORANGE: $08,
BROWN: $09,
LIGHT_RED: $0a,
DARK_GREY: $0b,
GREY: $0c,
LIGHT_GREEN: $0d,
LIGHT_BLUE: $0e,
LIGHT_GREY: $0f
}
; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; Charset: $0800 - $0E07 for Laxity logo
; Code: $0E08 - $0FEF
; Charset: $0FF0 - $0FFF : 2 characters that get "rol"ed to create star effects
; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
$0800charset_data.byte$ff
$0801BASIC_START.byte$ff, $ff, $ff, $ff, $ff, $ff, $ff, $d5; x-ref: $21E5
$0809.byte$5a, $69, $65, $69, $69, $69, $89, $55
$0811.byte$66, $9a, $75, $d5, $75, $55, $75, $5f
$0819.byte$97, $77, $d7, $f7, $fb, $77, $fb, $ff
$0821.byte$ff, $ff, $ff, $fd, $fd, $f5, $f6, $ff
$0829.byte$f5, $d6, $5a, $69, $95, $a5, $b5, $55
$0831.byte$6a, $a2, $95, $55, $99, $56, $99, $66
$0839.byte$88, $22, $9a, $6a, $aa, $6a, $aa, $57
$0841.byte$a5, $9f, $95, $65, $a9, $66, $a9, $ff
$0849.byte$7f, $5f, $d7, $75, $5d, $5d, $57, $ff
$0851.byte$ff, $ff, $ff, $ff, $ff, $7f, $7f, $d5
$0859.byte$5a, $6a, $89, $69, $89, $62, $8a, $55
$0861.byte$a9, $aa, $55, $65, $95, $65, $95, $5f
$0869.byte$97, $77, $d7, $f7, $f7, $f7, $f7, $d5
$0871.byte$5a, $69, $65, $69, $89, $69, $89, $5f
$0879.byte$97, $77, $d7, $f7, $7b, $77, $7b, $55
$0881.byte$6a, $a2, $55, $55, $99, $56, $99, $66
$0889.byte$80, $02, $9a, $6a, $aa, $62, $aa, $65
$0891.byte$8a, $22, $99, $65, $a9, $66, $aa, $55
$0899.byte$29, $aa, $55, $65, $95, $65, $95, $5f
$08A1.byte$97, $77, $d7, $f7, $f7, $77, $f7, $69
$08A9.byte$89, $61, $89, $62, $89, $a2, $89, $55
$08B1.byte$59, $56, $99, $56, $9a, $66, $5a, $77
$08B9.byte$db, $77, $db, $77, $5b, $77, $5b, $d4
$08C1.byte$da, $e2, $4a, $62, $89, $82, $89, $95
$08C9.byte$59, $56, $99, $56, $9a, $66, $5a, $6a
$08D1.byte$99, $65, $95, $96, $56, $59, $5b, $a2
$08D9.byte$59, $66, $88, $76, $fe, $fd, $ff, $aa
$08E1.byte$a9, $2a, $2a, $0a, $0a, $02, $80, $67
$08E9.byte$99, $65, $99, $65, $a9, $a6, $a9, $5f
$08F1.byte$df, $5f, $d7, $57, $db, $77, $db, $62
$08F9.byte$8a, $82, $8a, $82, $82, $02, $80, $65
$0901.byte$99, $65, $95, $66, $a9, $a6, $a9, $f7
$0909.byte$f7, $77, $f7, $77, $db, $77, $db, $61
$0911.byte$89, $67, $d9, $ff, $d9, $62, $88, $55
$0919.byte$f5, $75, $99, $ff, $9a, $22, $80, $db
$0921.byte$77, $e7, $9f, $ff, $9f, $27, $ab, $61
$0929.byte$89, $67, $d9, $ff, $ff, $ff, $ff, $55
$0931.byte$fd, $77, $99, $ff, $ff, $ff, $ff, $6a
$0939.byte$da, $62, $a0, $82, $80, $82, $80, $a2
$0941.byte$8a, $a2, $88, $22, $80, $02, $80, $aa
$0949.byte$55, $55, $9a, $5b, $9b, $63, $9b, $65
$0951.byte$dd, $77, $99, $ff, $ff, $ff, $ff, $77
$0959.byte$db, $57, $9f, $ff, $ff, $ff, $ff, $a2
$0961.byte$8a, $82, $8a, $82, $82, $02, $80, $82
$0969.byte$8a, $02, $82, $02, $80, $02, $80, $6a
$0971.byte$98, $6a, $a8, $a2, $a8, $a2, $88, $5b
$0979.byte$9b, $5b, $9b, $63, $9b, $63, $9b, $82
$0981.byte$82, $02, $82, $02, $80, $02, $80, $02
$0989.byte$80, $02, $80, $02, $80, $02, $00, $a6
$0991.byte$a9, $2a, $a9, $2a, $8a, $2a, $08, $77
$0999.byte$5b, $77, $5b, $5b, $9b, $5b, $9b, $82
$09A1.byte$8a, $02, $82, $42, $60, $e0, $d0, $5b
$09A9.byte$9b, $5b, $9b, $63, $9b, $63, $99, $ff
$09B1.byte$ff, $ff, $ff, $ff, $ff, $ff, $fd, $2a
$09B9.byte$89, $2a, $aa, $22, $8a, $22, $0a, $77
$09C1.byte$5b, $77, $5b, $97, $57, $9f, $5f, $a2
$09C9.byte$82, $02, $82, $02, $80, $02, $80, $63
$09D1.byte$a3, $63, $9b, $63, $9b, $63, $9b, $02
$09D9.byte$80, $02, $80, $02, $80, $00, $80, $00
$09E1.byte$80, $00, $00, $00, $00, $00, $00, $63
$09E9.byte$9b, $a3, $9b, $a3, $a3, $a3, $a3, $2a
$09F1.byte$8a, $2a, $aa, $22, $88, $02, $08, $02
$09F9.byte$80, $02, $00, $02, $00, $00, $aa, $22
$0A01.byte$80, $20, $80, $20, $80, $00, $6a, $a3
$0A09.byte$9b, $a3, $a3, $a3, $a3, $a3, $5b, $a3
$0A11.byte$9b, $a0, $80, $00, $00, $00, $aa, $ff
$0A19.byte$ff, $00, $00, $00, $00, $00, $aa, $02
$0A21.byte$00, $02, $00, $00, $00, $00, $aa, $02
$0A29.byte$08, $02, $00, $02, $00, $00, $aa, $63
$0A31.byte$9b, $63, $9b, $a3, $9b, $a3, $5b, $d8
$0A39.byte$f8, $f6, $fe, $fd, $ff, $ff, $ff, $22
$0A41.byte$80, $20, $00, $80, $60, $d8, $f5, $22
$0A49.byte$28, $0a, $02, $00, $00, $00, $aa, $fe
$0A51.byte$74, $20, $80, $00, $00, $00, $aa, $02
$0A59.byte$08, $00, $00, $00, $02, $0a, $96, $29
$0A61.byte$0a, $29, $29, $a5, $97, $5f, $7f, $9f
$0A69.byte$7f, $7f, $ff, $ff, $ff, $ff, $ff, $00
$0A71.byte$00, $00, $00, $00, $00, $00, $aa, $a3
$0A79.byte$a3, $a3, $a3, $a3, $a3, $a3, $5b, $82
$0A81.byte$40, $60, $e0, $d0, $d8, $f8, $f6, $2a
$0A89.byte$28, $0a, $02, $00, $00, $00, $aa, $ff
$0A91.byte$7f, $00, $80, $00, $00, $00, $aa, $02
$0A99.byte$00, $02, $00, $02, $00, $00, $aa, $57
$0AA1.byte$67, $55, $67, $5b, $67, $59, $65, $ff
$0AA9.byte$ff, $fd, $ff, $fd, $7f, $fd, $77
$0AB0.fill8, $f7
$0AB8.byte$dd, $f7, $d5, $ff, $ff, $f5, $f7, $f7
$0AC0.byte$d6, $55, $56, $f7, $fd, $66, $ff, $ff
$0AC8.byte$55, $55, $55, $75, $d9, $a5, $69, $89
$0AD0.byte$df, $7f, $dd, $77, $df, $57, $5d, $57
$0AD8.byte$ff, $ff, $fd, $fd, $f7, $f5, $d6, $da
$0AE0.byte$dd, $75, $d7, $5f, $5f, $7f, $5d, $7f
$0AE8.byte$5d, $f7, $d5, $75, $d7, $5f, $dd, $7d
$0AF0.byte$d6, $55, $56, $f5, $d6, $5a, $76, $fd
$0AF8.byte$5f, $57, $55, $97, $55, $95, $a5, $a5
$0B00.byte$5f, $d7, $f5, $7d, $dd, $7f, $5f, $77
$0B08.byte$ff, $ff, $ff, $ff, $7f, $7f, $5f, $df
$0B10.byte$59, $67, $59, $67, $69, $67, $69, $69
$0B18.byte$d5, $59, $56, $59, $56, $59, $66, $5a
$0B20.byte$f7, $fd, $ff, $ff, $ff, $ff, $ff, $ff
$0B28.byte$5f, $d7, $76, $dd, $f5, $ff, $ff, $ff
$0B30.byte$dd, $f7, $55, $9f, $77, $55, $ff, $ff
$0B38.byte$d6, $55, $56, $f7, $fd, $59, $ff, $ff
$0B40.byte$69, $65, $69, $69, $69, $89, $69, $89
$0B48.byte$dd, $75, $dd, $75, $d5, $75, $55, $75
$0B50.byte$d5, $5a, $6a, $89, $61, $8a, $82, $8a
$0B58.byte$69, $65, $69, $69, $69, $69, $69, $89
$0B60.byte$f7, $f7, $f7, $f7, $77, $f7, $77, $db
$0B68.byte$6a, $89, $62, $89, $62, $8a, $82, $8a
$0B70.byte$55, $97, $55, $97, $65, $95, $65, $95
$0B78.byte$d9, $56, $59, $65, $69, $69, $69, $89
$0B80.byte$75, $f7, $77, $f7, $77, $f7, $77, $db
$0B88.byte$fd, $ff, $ff, $ff, $ff, $ff, $ff, $ff
$0B90.byte$5f, $97, $55, $97, $65, $95, $65, $95
$0B98.byte$df, $d7, $f7, $f7, $f7, $f7, $f7, $f7
$0BA0.byte$69, $89, $6a, $89, $62, $89, $62, $89
$0BA8.byte$66, $5a, $6a, $9a, $6a, $aa, $62, $a8
$0BB0.byte$77, $5b, $77, $5b, $5b, $5b, $5b, $9b
$0BB8.byte$d5, $5a, $69, $69, $69, $89, $69, $89
$0BC0.byte$5f, $97, $77, $f7, $77, $db, $77, $db
$0BC8.byte$5d, $57, $65, $97, $65, $95, $65, $95
$0BD0.byte$62, $89, $a2, $49, $62, $ea, $d2, $da
$0BD8.byte$55, $59, $56, $99, $56, $9a, $66, $9a
$0BE0.byte$77, $59, $75, $96, $a5, $8a, $a2, $88
$0BE8.byte$ff, $fd, $fd, $76, $a8, $00, $20, $08
$0BF0.byte$82, $82, $02, $0a, $2a, $89, $2a, $8a
$0BF8.byte$65, $99, $65, $95, $67, $99, $a7, $95
$0C00.byte$77, $fb, $77, $db, $67, $df, $6f, $9f
$0C08.byte$69, $89, $61, $89, $62, $89, $82, $89
$0C10.byte$77, $db, $77, $5b, $77, $5b, $5b, $9b
$0C18.byte$82, $82, $82, $82, $82, $80, $02, $80
$0C20.byte$65, $99, $a5, $99, $aa, $a9, $2a, $a9
$0C28.byte$77, $f7, $77, $db, $77, $db, $77, $5b
$0C30.byte$82, $89, $82, $82, $82, $80, $82, $80
$0C38.byte$a2, $a8, $a2, $88, $a2, $80, $22, $80
$0C40.byte$5b, $9b, $63, $9b, $63, $9b, $a3, $9b
$0C48.byte$f8, $f6, $fe, $fd, $ff, $ff, $ff, $ff
$0C50.byte$aa, $28, $0a, $80, $60, $d8, $f6, $ff
$0C58.byte$a2, $80, $22, $80, $00, $0a, $2a, $5a
$0C60.byte$02, $08, $00, $00, $00, $aa, $aa, $02
$0C68.byte$2a, $08, $22, $80, $0a, $99, $a2, $97
$0C70.byte$a5, $96, $26, $99, $67, $9f, $7f, $ff
$0C78.byte$7f, $7f, $ff, $ff, $ff, $ff, $ff, $ff
$0C80.byte$82, $8a, $02, $82, $02, $8a, $69, $d8
$0C88.byte$6a, $98, $6a, $a8, $a2, $59, $66, $88
$0C90.byte$5b, $9b, $63, $9b, $63, $5b, $67, $9f
$0C98.byte$02, $80, $02, $80, $02, $8a, $69, $d8
$0CA0.byte$2a, $aa, $22, $8a, $22, $59, $66, $08
$0CA8.byte$77, $5b, $5b, $9b, $63, $5b, $67, $9f
$0CB0.byte$82, $80, $00, $00, $00, $82, $4a, $d8
$0CB8.byte$00, $80, $00, $80, $00, $aa, $aa, $00
$0CC0.byte$a3, $ab, $a3, $a3, $a3, $ab, $87
$0CC7logo_rows_0_3.byte$9f, $00, $01, $02, $03, $00, $00, $00; x-ref: $2E1B
$0CCF.byte$00, $04, $05, $06, $07, $08, $09, $0a
$0CD7.byte$01, $02, $03, $00, $0b, $0c, $0d, $0e
$0CDF.byte$02, $0f, $0e, $02, $10, $11, $12, $13
$0CE7.byte$14, $01, $02, $03, $00, $0b, $0c, $0d
$0CEF.byte$00, $00, $15, $16, $17, $00, $00, $00
$0CF7.byte$00, $18, $19, $1a, $1b, $1c, $1d, $1e
$0CFF.byte$15, $16, $17, $00, $1f, $20, $21, $22
$0D07.byte$23, $24, $25, $26, $27, $28, $29, $2a
$0D0F.byte$2b, $15, $16, $17, $00, $2c, $20, $21
$0D17.byte$00, $00, $2d, $2e, $2f, $00, $00, $00
$0D1F.byte$00, $30, $2e, $2f, $00, $31, $32, $33
$0D27.byte$34, $2e, $35, $36, $31, $37, $38, $39
$0D2F.byte$2e, $3a, $00, $00, $3b, $3c, $3d, $00
$0D37.byte$00, $2d, $2e, $35, $00, $31, $3e, $33
$0D3F.byte$00, $00, $3f, $40, $41, $00, $00, $00
$0D47.byte$00, $3f, $40, $42, $43, $44, $45, $46
$0D4F.byte$47, $48, $49, $4a, $4b, $4c, $4d, $3f
$0D57.byte$40, $41, $00, $00, $4e, $4e, $4f, $00
$0D5F.byte$00, $50, $40, $51, $52, $44, $53, $46
$0D67logo_rows_4_7.byte$00, $00, $54, $55, $56, $00, $00, $00; x-ref: $2E21
$0D6F.byte$00, $54, $55, $57, $58, $59, $5a, $56
$0D77.byte$5b, $5c, $5d, $5e, $5f, $60, $61, $54
$0D7F.byte$55, $56, $00, $00, $62, $63, $21, $00
$0D87.byte$00, $64, $65, $66, $67, $59, $5a, $56
$0D8F.byte$00, $00, $68, $69, $21, $00, $6a, $0c
$0D97.byte$0d, $6b, $69, $6c, $00, $6d, $6e, $56
$0D9F.byte$6f, $69, $70, $71, $6d, $72, $73, $6b
$0DA7.byte$69, $6c, $00, $00, $74, $75, $76, $00
$0DAF.byte$00, $77, $02, $78, $00, $6d, $79, $56
$0DB7.byte$00, $00, $7a, $7b, $7c, $7d, $7e, $7f
$0DBF.byte$80, $81, $16, $82, $00, $83, $84, $85
$0DC7.byte$81, $16, $82, $00, $83, $84, $85, $81
$0DCF.byte$16, $82, $00, $00, $86, $87, $88, $00
$0DD7.byte$00, $7a, $7b, $7c, $7d, $7e, $7f, $80
$0DDF.byte$00, $00, $89, $8a, $8b, $8c, $8d, $8e
$0DE7.byte$8f, $90, $91, $92, $00, $93, $94, $95
$0DEF.byte$90, $91, $92, $00, $93, $94, $95, $90
$0DF7.byte$91, $92, $00, $00, $96, $97, $98, $00
$0DFF.byte$00, $89, $8a, $8b, $8c, $8d, $8e, $8f
$0E07.byte$00
top_tube_sine_phase =*+$01 ; x-ref: $0E0D
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Updates three sine-wave-scrolled "tube" bands on screen and advances the
; horizontal text scroller. Called every frame from the main loop.
;
; 1) For each of three tube bands (top/mid/bot), advances a sine phase index,
; calls sine_scroller_update to get fine-scroll + coarse offset, patches
; the VIC $D016 scroll value into the corresponding IRQ handler via
; self-modifying code, and fills two adjacent screen rows with a 4-char
; repeating tile pattern offset by the coarse sine value.
;
; 2) Rotates two 8-byte shift register arrays (tube_shift_reg_0/1) that
; drive animated bitmap patterns within the tube bands.
;
; 3) Smooth-scrolls a proportional-width text message across 4 screen rows.
; Decrements a pixel counter by 3 each frame; on underflow, shifts the
; screen left by one char and renders the next font column from a
; character mapping table and 4 font bitmap row tables.
;
; Inputs: Self-modified sine phases at $0E09/$0E29/$0E49,
; scroller pointer at $0EA6/$0EA7, scroll counter at $2334
; Outputs: Screen RAM updated, VIC $D016 values patched in IRQ handlers
; Side Effects: Modifies screen RAM $0400-$0798 and $061F-$071F,
; self-modifies code at multiple locations
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
update_scroller_and_tubes
$0E08a2 00ldx#$00; Sine phase for top tube (self-mod at $0E09) ; x-ref: $2E78, $2E94
$0E0A20 00 22jsrsine_scroller_update; Returns A=fine scroll, Y=coarse offset
$0E0D8e 09 0estxtop_tube_sine_phase; Save updated sine phase (self-mod)
$0E108d 2e 22stapatch_irq_fb_scroll; Patch $D016 scroll in irq_handler_fb
$0E13a2 00ldx#$00
$0E1598fill_top_tube_looptya; x-ref: $0E26
$0E1629 03and#$03; 4-char repeating tile pattern
$0E1809 e0ora#$e0
$0E1A9d 00 04staSCREEN_RAM,x; Top row of tube band (screen row 0)
$0E1D09 04ora#$04
$0E1F9d 28 04staSCREEN_RAM_R1C0,x; Bottom row of tube band (screen row 1)
$0E22c8iny
$0E23e8inx
$0E24e0 27cpx#$27; 39 columns
$0E26d0 edbnefill_top_tube_loop
mid_tube_sine_phase =*+$01 ; x-ref: $0E2D
$0E28a2 18ldx#$18; Sine phase for middle tube (self-mod)
$0E2A20 00 22jsrsine_scroller_update
$0E2D8e 29 0estxmid_tube_sine_phase
$0E308d f4 22stapatch_irq_96_scroll; Patch $D016 scroll in irq_handler_96
$0E33a2 00ldx#$00
$0E3598fill_mid_tube_looptya; x-ref: $0E46
$0E3629 03and#$03
$0E3809 e0ora#$e0
$0E3A9d e0 05staSCREEN_RAM_R12C0,x; Screen row 12
$0E3D09 04ora#$04
$0E3F9d 08 06staSCREEN_RAM_R13C0,x; Screen row 13
$0E42c8iny
$0E43e8inx
$0E44e0 27cpx#$27
$0E46d0 edbnefill_mid_tube_loop
bot_tube_sine_phase =*+$01 ; x-ref: $0E4D
$0E48a2 30ldx#$30; Sine phase for bottom tube (self-mod)
$0E4A20 00 22jsrsine_scroller_update
$0E4D8e 49 0estxbot_tube_sine_phase
$0E508d 93 23stapatch_irq_e6_scroll; Patch $D016 scroll in irq_handler_e6
$0E53a2 00ldx#$00
$0E5598fill_bot_tube_looptya; x-ref: $0E66
$0E5629 03and#$03
$0E5809 e0ora#$e0
$0E5A9d 70 07staSCREEN_RAM_R22C0,x; Screen row 23
$0E5D09 04ora#$04
$0E5F9d 98 07staSCREEN_RAM_R23C0,x; Screen row 24
$0E62c8iny
$0E63e8inx
$0E64e0 27cpx#$27
$0E66d0 edbnefill_bot_tube_loop
$0E68a2 07ldx#$07
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; 1-bit circular left rotation of scroller_star_char_0 ($0FF0-$0FF7).
; scroller_star_char_0 is charset character 254 in the $0800 charset (last-2).
; Rotating it in-place animates every on-screen instance of that character
; simultaneously — the classic C64 "animating star" demo technique.
; Called once per scroll tick; produces a 1-pixel/frame leftward drift.
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
rotate_scroller_star_0
$0E6A18clc; clear carry (default: bit 7 = 0) ; x-ref: $0E76
$0E6Bbd f0 0fldascroller_star_char_0,x; load byte from charset char 254 bitmap
$0E6E10 01bplb_0E71; bit 7 = 0: carry stays clear; skip sec
$0E7038sec; bit 7 = 1: set carry (mirrors bit shifting out)
$0E712ab_0E71rola; circular ROL: bits 6..0 → 7..1; old bit 7 (carry) → bit 0 ; x-ref: $0E6E
$0E729d f0 0fstascroller_star_char_0,x; write rotated byte back to charset
$0E75cadex
$0E7610 f2bplrotate_scroller_star_0; loop until all 8 bytes done
$0E7820 eb 0ejsrrotate_scroller_star_1_x2
; Advance text scroller
$0E7Bad 34 23ldasmooth_scroll_phase
$0E7E38sec
$0E7Fe9 03sbc#$03; Subtract 3 pixels per frame
$0E818d 34 23stasmooth_scroll_phase
$0E8410 64bplr_0EEA; No underflow = skip char fetch
$0E8629 07and#$07; Wrap to 0-7 range
$0E888d 34 23stasmooth_scroll_phase
$0E8Ba2 61ldx#97; 256-97 = 159 ~ 4 * 40
$0E8Dbd 20 06scroll_text_leftldaSCREEN_RAM_R13C24,x; Shift screen row left by 1 char ; x-ref: $0E94
$0E909d 1f 06staSCREEN_RAM_R13C23,x
$0E93e8inx
$0E94d0 f7bnescroll_text_left
$0E96ce 9a 0edecscroller_char_width_ctr
scroller_char_width_ctr =*+$01 ; x-ref: $0E96, $0EC4
$0E99a9 01lda#$01
$0E9Bf0 08beqfetch_next_char
$0E9Dee a1 0eincscroller_font_idx
scroller_font_idx =*+$01 ; x-ref: $0E9D, $0ECA
$0EA0a2 00ldx#$00
$0EA24c d2 0ejmprender_char_column
scroller_text_ptr_lo =*+$01 ; x-ref: $0EAC, $0EB9
scroller_text_ptr_hi =*+$02 ; x-ref: $0EB1, $0EBE
$0EA5ad 00 2ffetch_next_charldascroller_txt; Read next char from scroller_txt ; x-ref: $0E9B, $0EB4, $0ECF
$0EA8d0 0cbnedecode_char; Zero = end of message
$0EAAa9 00lda#<scroller_txt; Reset pointer to start of message
$0EAC8d a6 0estascroller_text_ptr_lo
$0EAFa9 2flda#>scroller_txt
$0EB18d a7 0estascroller_text_ptr_hi
$0EB4d0 efbnefetch_next_char
$0EB629 3fdecode_charand#$3f; Mask to 6-bit screen code index ; x-ref: $0EA8
$0EB8aatax
$0EB9ee a6 0eincscroller_text_ptr_lo
$0EBCd0 03bneb_0EC1
$0EBEee a7 0eincscroller_text_ptr_hi
$0EC1bd c0 27b_0EC1ldachar_col_width,x; Look up column width for this char ; x-ref: $0EBC
$0EC48d 9a 0estascroller_char_width_ctr
$0EC7bd 80 27ldachar_to_font_idx,x; Look up font bitmap start index
$0ECA8d a1 0estascroller_font_idx
$0ECDc9 ffcmp#$ff; $FF = end-of-string marker
$0ECFf0 d4beqfetch_next_char
$0ED1aatax
; Render 4 font rows to screen
$0ED2bd 00 24render_char_columnldafont_row_0,x; x-ref: $0EA2
$0ED58d a7 06staSCREEN_RAM_R16C39
$0ED8bd ca 24ldafont_row_1,x; Font row 1 → screen $06CF
$0EDB8d cf 06staSCREEN_RAM_R17C39
$0EDEbd 94 25ldafont_row_2,x; Font row 2 → screen $06F7
$0EE18d f7 06staSCREEN_RAM_R18C39
$0EE4bd 5e 26ldafont_row_3,x; Font row 3 → screen $071F
$0EE78d 1f 07staSCREEN_RAM_R19C39
$0EEA60r_0EEArts; x-ref: $0E84
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; 2-bit circular left rotation of scroller_star_char_1 ($0FF8-$0FFF).
; scroller_star_char_1 is charset character 255 in the $0800 charset (last).
; Rotating it in-place animates every on-screen instance of that character
; simultaneously — the classic C64 "animating star" demo technique.
; Runs at 2 bits/frame (vs 1 bit/frame for scroller_star_char_0), giving
; the two star rows slightly different animation speeds for visual variety.
;
; Uses the JSR fall-through trick to call rotate_scroller_star_1 twice:
; - JSR at $0EEB pushes return address $0EED onto stack, jumps to $0EEE.
; - rotate_scroller_star_1 executes (1-bit rotate), RTS pops $0EED.
; - rotate_scroller_star_1 executes again (1-bit rotate), RTS returns to caller.
; Net effect: 2-bit circular left rotation with zero extra overhead.
;
; Called once per scroll tick from the text scroller advance at $0E78.
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
rotate_scroller_star_1_x2
$0EEB20 ee 0ejsrrotate_scroller_star_1; JSR fall-through: $0EED pushed as return → re-enters rotate_scroller_star_1 below ; x-ref: $0E78
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; 1-bit circular left rotation of each of the 8 bytes in scroller_star_char_1.
; For each byte (X = 7..0):
; clc / bpl / sec → copy bit 7 into carry
; rol → shift bits 6..0 left; old bit 7 (carry) → bit 0
; Since the carry fed into ROL equals the bit shifted out, the rotation is
; truly circular: bit 7 wraps to bit 0 every 8 calls (= every 4 frames when
; invoked via rotate_scroller_star_1_x2 which doubles each call).
; Inputs/Outputs: scroller_star_char_1[0..7] each rotated left by 1
; Clobbers: A, X
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
rotate_scroller_star_1
$0EEEa2 07ldx#$07; process 8 bytes, X = 7..0 ; x-ref: $0EEB
$0EF018b_0EF0clc; carry = 0 by default ; x-ref: $0EFC
$0EF1bd f8 0fldascroller_star_char_1,x; load byte from charset char 255 bitmap
$0EF410 01bplb_0EF7; bit 7 = 0: carry stays clear; skip sec
$0EF638sec; bit 7 = 1: carry = 1 (mirrors bit about to shift out)
$0EF72ab_0EF7rola; circular ROL: bits 6..0 → 7..1; old bit 7 (carry) → bit 0 ; x-ref: $0EF4
$0EF89d f8 0fstascroller_star_char_1,x; write rotated byte back to charset
$0EFBcadex
$0EFC10 f2bplb_0EF0; loop until all 8 bytes done
$0EFE60rts
$0EFF.byte$dd, $ff, $aa, $00, $00, $22, $aa, $99
$0F07.byte$55, $ff, $a5, $0a, $0a, $29, $a5, $97
$0F0F.byte$5f, $aa, $00, $00, $88, $22, $aa, $99
$0F17.byte$66, $ff, $f5, $5a, $5a, $79, $f5, $f7
$0F1F.byte$ff, $77, $ff, $dd, $55, $66, $aa, $55
$0F27.byte$ff, $7f, $ff, $df, $5f, $6d, $a5, $5f
$0F2F.byte$ff, $55, $dd, $77, $55, $99, $66, $aa
$0F37.byte$55, $ff, $ff, $ff, $ff, $fd, $f5, $ff
$0F3F.byte$ff
$0F40sine_table.byte$80, $85, $8a, $8e, $93, $98, $9d, $a2; x-ref: $2207
$0F48.byte$a7, $ac, $b0, $b5, $b9, $be, $c2, $c6
$0F50.byte$ca, $ce, $d2, $d6, $da, $dd, $e0, $e4
$0F58.byte$e7, $ea, $ec, $ef, $f1, $f3, $f5, $f7
$0F60.byte$f9, $fa, $fb, $fd, $fd, $fe, $ff, $ff
$0F68.byte$ff, $ff, $ff, $fe, $fd, $fd, $fb, $fa
$0F70.byte$f9, $f7, $f5, $f3, $f1, $ef, $ec, $ea
$0F78.byte$e7, $e4, $e0, $dd, $da, $d6, $d2, $ce
$0F80.byte$ca, $c6, $c2, $be, $b9, $b5, $b0, $ac
$0F88.byte$a7, $a2, $9d, $98, $93, $8e, $8a, $85
$0F90.byte$7f, $7a, $75, $71, $6c, $67, $62, $5d
$0F98.byte$58, $53, $4f, $4a, $46, $41, $3d, $39
$0FA0.byte$35, $31, $2d, $29, $25, $22, $1f, $1b
$0FA8.byte$18, $15, $13, $10, $0e, $0c, $0a, $08
$0FB0.byte$06, $05, $04, $02, $02, $01, $00, $00
$0FB8.byte$00, $00, $00, $01, $02, $02, $04, $05
$0FC0.byte$06, $08, $0a, $0c, $0e, $10, $13, $15
$0FC8.byte$18, $1b, $1f, $22, $25, $29, $2d, $31
$0FD0.byte$35, $39, $3d, $41, $46, $4a, $4f, $53
$0FD8.byte$58, $5d, $62, $67, $6c, $71, $75, $7a
$0FE0.fill16, $00
; Charset character 254 bitmap (last-2 char of $0800 charset, 8 bytes).
; Sparse pixel "star" pattern; rotated 1 bit/frame by rotate_scroller_star_0
; to animate all on-screen star rows above/below the scroller text.
$0FF0scroller_star_char_0.byte$00, $08, $00, $80, $00, $00, $02, $00; x-ref: $0E6B, $0E72
; Charset character 255 bitmap (last char of $0800 charset, 8 bytes).
; Same initial pattern as scroller_star_char_0; rotated 2 bits/frame by
; rotate_scroller_star_1_x2 for a slightly faster animation on the second star row.
$0FF8scroller_star_char_1.byte$00, $08, $00, $80, $00, $00, $02, $00; x-ref: $0EF1, $0EF8
; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; SID Music Player - Architecture Overview
;
; +---------------------+
; | Entry: LDX #$02 |
; | (voice 2, 1, 0) |
; +---------------------+
; |
; +---------------------+
; | Save $FB/$FC |
; +---------------------+
; |
; +---------------------+
; | Voice active? |
; | voice_active,x != 0 |
; +-----+---------------+
; Yes | No \
; | +---> next_voice
; +-----v---------------+ (DEX, loop
; | Speed counter | or RTS)
; | voice_speed_ctr != 0|
; +-----+--------+------+
; == 0 | | != 0
; | +---> Sustain: dec ctr,
; | check release tick
; +-----v---------------+
; | Fetch next command |
; | from pattern data |
; +-----+---------------+
; |
; +-------------+-------------+
; | | |
; +----v----+ +----v----+ +----v--------+
; | Note | | Rest | | Control |
; | $01-$7D | | $00 | | $80+ |
; | gate on | | gate off| +------+------+
; +----+----+ +----+----+ |
; | | +---------+---------+
; | | | | |
; +------+------+ +--v---+ +---v---+ +---v------+
; | |Speed | |Instr. | |Effects |
; | |$80 | |$A0 | |$C0+ |
; | +------+ +-------+ +---+------+
; | |
; | +------+------+----+----+
; | | | | |
; | +---v--+ +-v---+ +v------+ +v-------+
; | |Vibr. | |Porta| |Release| |Arpeggio|
; | +------+ +-----+ +-------+ +--------+
; |
; +-----v--------------+
; | Calc frequency |
; | from freq table |
; | + apply effects |
; +-----+--------------+
; |
; +-----v--------------+
; | Write SID regs |
; | $D400-$D418 |
; | Freq, PW, Filter, |
; | Control, ADSR |
; +-----+--------------+
; |
; +-----v--------------+
; | next_voice: DEX |
; | loop or RTS |
; +--------------------+
; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
$10004c 40 10sid_initjmpsid_init_voices; x-ref: $2E75
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; SID Music Player - Play Tick Wrapper
; Called once per frame (from the raster IRQ) to advance the music player.
; Simply jumps to the main player routine.
; Inputs: None
; Outputs: None
; Side Effects: Advances music sequencing, updates SID registers via sid_player_main
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
$10034c dc 10sid_playjmpsid_player_main; x-ref: $2237
$1006voice_active.byte$01, $02, $04; x-ref: $1093, $10E4, $12A1
$1009sid_volume.byte$0f; x-ref: $10D5, $1328
$100Asid_filter_route.byte$f1; x-ref: $132F, $133D, $1346
$100Btemp_byte.byte$00; x-ref: $1061, $106D, $107B, $108D, $1099, $124C, $1256, $1316, ...
$100Cvoice_freq_lo.byte$a9, $b5, $00; x-ref: $14C4, $14FE, $154D, $1554, $15D4, $15DB, $1606
$100Fvoice_freq_hi.byte$03, $1c, $00, $fc, $3e; x-ref: $14BF, $1506, $1557, $155D, $15DE, $15E4, $160C
$1014voice_note.byte$15, $30, $0c; x-ref: $10BF, $114B, $14E9, $1568
$1017voice_transpose.byte$00, $0c, $18; x-ref: $1125, $14EE
$101Avoice_gate_mask.byte$ff, $fe, $fe; x-ref: $1166, $116F, $1178, $1615
$101Dvoice_instr_idx.byte$08, $60, $58; x-ref: $117B, $11B4, $12E0, $130D, $134D, $136B, $1377, $14A3
.encode
.enc"screen"
$1020txt_sid_credits.text"-walawonga to my pet box - deek-"; x-ref: $1083
.endencode
$10400asid_init_voicesasla; x-ref: $1000
$10410aasla
$10420aasla
$1043a8tay
$1044a2 00ldx#$00
$1046b9 7b 17b_1046ldasong_pattern_ptr_table,y; x-ref: $105D
$10499d e9 16stavoice_pat_ptr_lo,x
$104C9d ef 16stavoice_loop_ptr_lo,x
$104Fb9 7c 17ldasong_pattern_ptr_table_hi,y
$10529d ec 16stavoice_pat_ptr_hi,x
$10559d f2 16stavoice_loop_ptr_hi,x
$1058c8iny
$1059c8iny
$105Ae8inx
$105Be0 03cpx#$03
$105Dd0 e7bneb_1046
$105Fa2 00ldx#$00
$10618e 0b 10stxtemp_byte
$1064b9 7b 17ldasong_pattern_ptr_table,y
$10678d e8 16statemp_interval
$106A9d 65 17b_106Astaspeed_lookup,x; x-ref: $1081
$106Dee 0b 10inctemp_byte
$1070ad e8 16ldatemp_interval
$107318clc
$107479 7b 17adcsong_pattern_ptr_table,y
$10778d e8 16statemp_interval
$107A18clc
$107B6d 0b 10adctemp_byte
$107Ee8inx
$107Fe0 10cpx#$10
$1081d0 e7bneb_106A
$1083ad 20 10ldatxt_sid_credits
$1086f0 2bbeqb_10B3
$1088a2 02ldx#$02
$108Ab9 7c 17b_108Aldasong_pattern_ptr_table_hi,y; x-ref: $1097
$108D8d 0b 10statemp_byte
$10903d f5 16andvoice_filter_bit,x
$10939d 06 10stavoice_active,x
$1096cadex
$109710 f1bplb_108A
$10992c 0b 10bittemp_byte
$109C10 15bplb_10B3
$109Ea2 00ldx#$00
$10A0b9 7d 17b_10A0ldasong_loop_ptr_table_lo,y; x-ref: $10B1
$10A39d ef 16stavoice_loop_ptr_lo,x
$10A6b9 7e 17ldasong_loop_ptr_table_hi,y
$10A99d f2 16stavoice_loop_ptr_hi,x
$10ACc8iny
$10ADc8iny
$10AEe8inx
$10AFe0 03cpx#$03
$10B1d0 edbneb_10A0
$10B3a0 00b_10B3ldy#$00; x-ref: $1086, $109C
$10B598tya
$10B699 00 d4b_10B6sta$d400,y; x-ref: $10BC Voice 1: Frequency Control - Low-Byte
$10B9c8iny
$10BAc0 1bcpy#$1b
$10BCd0 f8bneb_10B6
$10BEa8tay
$10BF99 14 10b_10BFstavoice_note,y; x-ref: $10C8
$10C299 0d 17stavoice_pat_pos,y
$10C5c8iny
$10C6c0 0ccpy#$0c
$10C8d0 f5bneb_10BF
$10CAa9 02lda#$02
$10CC8d 16 17stavoice_speed_ctr
$10CF8d 17 17stasid_unused_1717
$10D28d 18 17stasid_unused_1718
$10D5ad 09 10ldasid_volume
$10D88d 18 d4sta$d418; Select Filter Mode and Volume
$10DB60rts
; SID Music Player - Main Entry
; Processes all 3 voices (X=2,1,0) per call.
; Handles sequencing, effects, and SID register output.
$10DCa2 02sid_player_mainldx#$02; start with voice 2, count down to 0 ; x-ref: $1003
$10DEa5 fbldamusic_ptr_lo; save ZP pointers used for pattern data
$10E048pha
$10E1a5 fcldamusic_ptr_hi
$10E348pha
; --- Voice Processing Loop ---
$10E4bd 06 10voice_loopldavoice_active,x; check if voice X is active ; x-ref: $161E
$10E7d0 03bnecheck_tempo
$10E94c 1b 16jmpnext_voice; voice inactive, skip
; --- Tempo / Speed Counter ---
$10ECbd 16 17check_tempoldavoice_speed_ctr,x; speed countdown still running? ; x-ref: $10E7
$10EFf0 19beqadvance_pattern
$10F1dd 07 17cmpvoice_release_tick,x; zero = time for next pattern row
$10F4d0 0ebnedec_speed_ctr
$10F6a9 00lda#$00; not yet, just dec counter
$10F89d 07 17stavoice_release_tick,x; clear release tick marker
$10FBbd 10 17ldavoice_rel_adsr,x
$10FEbc fb 16ldyvoice_sid_offset,x
$110199 06 d4sta$d406,y; Voice 1: Sustain / Release Cycle Control
$1104de 16 17dec_speed_ctrdecvoice_speed_ctr,x; x-ref: $10F4
$11074c 8b 13jmpprocess_effects
; --- Fetch Next Pattern Command ---
$110Abd 13 17advance_patternldavoice_speed_val,x; reload speed into countdown ; x-ref: $10EF
$110D9d 16 17stavoice_speed_ctr,x
$1110bd e9 16ldavoice_pat_ptr_lo,x; load pattern ptr into $FB/$FC
$111385 fbstamusic_ptr_lo
$1115bd ec 16ldavoice_pat_ptr_hi,x
$111885 fcstamusic_ptr_hi
$111Aa0 00ldy#$00
$111C98tya; clear tie flag
$111D9d fe 16stavoice_tie_flag,x
$1120b1 fblda(music_ptr_lo),y; read pattern byte
$112210 0fbpllookup_pattern_ptr; bit7 clear = note index
$11240aasla; bit7 set = transpose value
$11259d 17 10stavoice_transpose,x
$1128fe e9 16incvoice_pat_ptr_lo,x
$112Bd0 03bneb_1130
$112Dfe ec 16incvoice_pat_ptr_hi,x
$1130c8b_1130iny; x-ref: $112B
$1131b1 fblda(music_ptr_lo),y
; --- Lookup Pattern Pointer ---
$1133a8lookup_pattern_ptrtay; use as index into song ptr table ; x-ref: $1122
$1134b9 16 1aldasong_ptr_lo,y; pattern addr lo
$113785 fbstamusic_ptr_lo
$1139b9 3a 1aldasong_ptr_hi,y; pattern addr hi
$113C85 fcstamusic_ptr_hi
; --- Parse Pattern Byte ---
; Dispatches: $01-$7D=note, $7E=tie, $00=rest, $80+=control
$113Ebc 0d 17parse_pattern_loopldyvoice_pat_pos,x; x-ref: $11AA, $11BA
$1141b1 fblda(music_ptr_lo),y
$114330 47bmicmd_control; bit7 set = control cmd
$1145f0 25beqcmd_rest; zero = rest
$1147c9 7ecmp#$7e; $7E = tie (sustain)
$1149f0 16beqcmd_tie
$114B9d 14 10stavoice_note,x; store note number
$114Ebd 01 17ldavoice_porta_mode,x
$1151f0 03beqb_1156
$1153de 01 17decvoice_porta_mode,x
$1156bd 04 17b_1156ldavoice_vibrato_en,x; x-ref: $1151
$1159f0 09beqset_gate_on
$115Bde 04 17decvoice_vibrato_en,x
$115E4c 64 11jmpset_gate_on
$1161fe fe 16cmd_tieincvoice_tie_flag,x; inc tie flag, don't retrigger ; x-ref: $1149
$1164a9 ffset_gate_onlda#$ff; gate mask = $FF (all bits on) ; x-ref: $1159, $115E
$11669d 1a 10stavoice_gate_mask,x
$11694c 62 12jmpadvance_pat_pos
; --- Rest Command ---
$116Cfe fe 16cmd_restincvoice_tie_flag,x; inc tie flag (marks rest) ; x-ref: $1145
$116Fbd 1a 10ldavoice_gate_mask,x
$1172c9 fecmp#$fe; gate mask = $FE (gate off)
$1174f0 13beqadvance_and_done
$1176a9 felda#$fe
$11789d 1a 10stavoice_gate_mask,x
$117Bbc 1d 10ldyvoice_instr_idx,x
$117Eb9 a0 18ldainstr_arp_restart_pos,y
$1181d9 9f 18cmpinstr_arp_loop_pos,y
$1184f0 03beqadvance_and_done
$11869d 50 17stavoice_arp_pos,x
$11894c 62 12advance_and_donejmpadvance_pat_pos; x-ref: $1174, $1184
; --- Control Commands ($80+) ---
; Bits 7-5 determine subtype:
; $80=speed, $A0=instrument, $C0-$FF=effects
$118C48cmd_controlpha; x-ref: $1143
$118D29 e0and#$e0
$118Fc9 80cmp#$80; check bits 7-5
$1191d0 19bnectrl_instrument; $80 = speed command
$119368pla
$119448pha
$119529 10and#$10
$11979d fe 16stavoice_tie_flag,x
$119A68pla
$119B29 0fand#$0f; bits 0-3 = speed value
$119Da8tay; set speed + repeat counter
$119Eb9 65 17ldaspeed_lookup,y
$11A19d 16 17stavoice_speed_ctr,x
$11A49d 13 17stavoice_speed_val,x
$11A7fe 0d 17incvoice_pat_pos,x
$11AAd0 92bneparse_pattern_loop
; --- Select Instrument ---
$11ACc9 a0ctrl_instrumentcmp#$a0; $A0 = instrument select ; x-ref: $1191
$11AEd0 0cbnectrl_effect
$11B068pla
$11B10aasla; extract instrument idx (bits 0-4) * 8
$11B20aasla
$11B30aasla
$11B49d 1d 10stavoice_instr_idx,x
$11B7fe 0d 17next_pattern_byteincvoice_pat_pos,x; x-ref: $11ED, $11F2, $1233, $1246, $125F
$11BAd0 82bneparse_pattern_loop
; --- Effect Commands ---
; Bits 7-6 of param byte 1 determine type:
; %00=vibrato, %01=portamento, %10=release, %11=arpeggio
$11BC68ctrl_effectpla; x-ref: $11AE
$11BD29 3fand#$3f
$11BF0aasla
$11C0a8tay
$11C1b9 41 19ldaeffect_cmd_1,y
$11C448pha
$11C529 c0and#$c0
$11C7d0 2bbneeffect_portamento
$11C968pla
$11CA48pha
$11CB29 0fand#$0f
$11CD9d 56 17stavoice_vib_delta_hi,x
$11D068pla
$11D148pha
$11D229 20and#$20
$11D49d 59 17stavoice_vib_sub_dir,x
$11D7b9 42 19ldaeffect_cmd_2,y
$11DA9d 53 17stavoice_vib_delta_lo,x
$11DDa9 01lda#$01
$11DF9d 04 17stavoice_vibrato_en,x
$11E2a9 00lda#$00
$11E49d 5c 17stavoice_vib_sub_lo,x
$11E79d 5f 17stavoice_vib_sub_hi,x
$11EA68pla
$11EB29 10and#$10
$11EDd0 c8bnenext_pattern_byte
$11EFfe 04 17incvoice_vibrato_en,x
$11F2d0 c3bnenext_pattern_byte
; --- Effect: Portamento ---
$11F4c9 40effect_portamentocmp#$40; x-ref: $11C7
$11F6d0 3ebneeffect_release
$11F8a9 02lda#$02; porta mode = 2 (slide)
$11FA9d 01 17stavoice_porta_mode,x
$11FD68pla
$11FE48pha
$11FF29 60and#$60
$1201c9 60cmp#$60
$1203d0 03bneb_1208
$1205de 01 17decvoice_porta_mode,x
$120868b_1208pla; x-ref: $1203
$120929 0fand#$0f
$120B9d 1f 17stavoice_vib_depth_inc,x
$120Eb9 42 19ldaeffect_cmd_2,y
$121148pha
$12124alsra
$12134alsra
$12144alsra
$12154alsra
$12169d 1c 17stavoice_vib_period,x
$121938sec
$121Ae9 01sbc#$01
$121C9d 19 17stavoice_vib_period_ctr,x
$121Fa9 00lda#$00
$12219d 25 17stavoice_vib_dir,x
$12249d 22 17stavoice_vib_accum,x
$12279d 28 17stavoice_vib_offset_lo,x
$122A9d 2b 17stavoice_vib_offset_hi,x
$122D68pla
$122E29 0fand#$0f
$12309d 2e 17stavoice_vib_rate_div,x
$12334c b7 11jmpnext_pattern_byte
; --- Effect: Release Timing ---
$1236c9 80effect_releasecmp#$80; x-ref: $11F6
$1238d0 0fbneeffect_arpeggio
$123A68pla; bits 0-3 = release tick
$123B29 0fand#$0f
$123D9d 07 17stavoice_release_tick,x
$1240b9 42 19ldaeffect_cmd_2,y; param 2 = sustain/release ADSR
$12439d 10 17stavoice_rel_adsr,x
$12464c b7 11jmpnext_pattern_byte
; --- Effect: Arpeggio Setup ---
$1249b9 42 19effect_arpeggioldaeffect_cmd_2,y; x-ref: $1238
$124C8d 0b 10statemp_byte
$124F68pla
$125029 1fand#$1f
$12520aasla
$12530aasla
$12540aasla
$1255a8tay
$1256ad 0b 10ldatemp_byte
$125999 9f 18stainstr_arp_loop_pos,y
$125C99 a0 18stainstr_arp_restart_pos,y
$125F4c b7 11jmpnext_pattern_byte
; --- Pattern Position Advance ---
$1262fe 0d 17advance_pat_posincvoice_pat_pos,x; x-ref: $1169, $1189
$1265bc 0d 17ldyvoice_pat_pos,x
$1268b1 fblda(music_ptr_lo),y
$126Ac9 7fcmp#$7f; $7F = end of pattern
$126Cd0 2dbnecheck_pat_marker
$126Ea9 00lda#$00
$12709d 0d 17stavoice_pat_pos,x
$1273a8tay
$1274bd e9 16ldavoice_pat_ptr_lo,x
$127718clc
$127869 01adc#$01
$127A9d e9 16stavoice_pat_ptr_lo,x
$127D85 fbstamusic_ptr_lo
$127Fbd ec 16ldavoice_pat_ptr_hi,x
$128269 00adc#$00
$12849d ec 16stavoice_pat_ptr_hi,x
$128785 fcstamusic_ptr_hi
$1289b1 fblda(music_ptr_lo),y
$128Bc9 ffcmp#$ff; $FF = end of song, loop
$128Dd0 0cbnecheck_pat_marker
$128Fbd ef 16ldavoice_loop_ptr_lo,x
$12929d e9 16stavoice_pat_ptr_lo,x
$1295bd f2 16ldavoice_loop_ptr_hi,x
$12989d ec 16stavoice_pat_ptr_hi,x
$129Bc9 fecheck_pat_markercmp#$fe; $FE = stop voice ; x-ref: $126C, $128D
$129Dd0 0ebnecheck_tie_flag
$129Fa9 00lda#$00
$12A19d 06 10stavoice_active,x
$12A4bc fb 16ldyvoice_sid_offset,x
$12A799 04 d4sta$d404,y; Voice 1: Control Register
$12AA4c 1b 16jmpnext_voice
$12ADbd fe 16check_tie_flagldavoice_tie_flag,x; x-ref: $129D
$12B0f0 1cbeqtrigger_note
$12B2bd 53 18ldainstr_filter_minmax,x
$12B5f0 0cbeqb_12C3
$12B7c9 01cmp#$01
$12B9d0 05bneb_12C0
$12BBbd 01 17ldavoice_porta_mode,x
$12BEf0 03beqb_12C3
$12C04c 1b 16b_12C0jmpnext_voice; x-ref: $12B9
$12C34c 8b 13b_12C3jmpprocess_effects; x-ref: $12B5, $12BE
$12C6a9 00lda#$00
$12C89d 01 17stavoice_porta_mode,x
$12CB4c e0 12jmpload_instrument
; --- Trigger New Note ---
; Gate off, set ADSR for quick silence, then load instrument.
$12CEbc fb 16trigger_noteldyvoice_sid_offset,x; x-ref: $12B0
$12D1a9 00lda#$00; ADSR = $00/$0F (instant release)
$12D399 05 d4sta$d405,y; Voice 1: Attack / Decay Cycle Control
$12D6a9 0flda#$0f
$12D899 06 d4sta$d406,y; Voice 1: Sustain / Release Cycle Control
$12DBa9 08lda#$08
$12DD99 04 d4sta$d404,y; control = $08 (noise, gate off); Voice 1: Control Register
; --- Load Instrument Data ---
$12E0bc 1d 10load_instrumentldyvoice_instr_idx,x; x-ref: $12CB
$12E3b9 9f 18ldainstr_arp_loop_pos,y
$12E69d 50 17stavoice_arp_pos,x
$12E9b9 9e 18ldainstr_pwm_tbl_start,y
$12EC9d 3d 17stavoice_pwm_tbl_idx,x
$12EFa8tay
$12F0a9 00lda#$00
$12F29d 40 17stavoice_pwm_delay,x
$12F5b9 78 18ldainstr_pwm_ctrl,y
$12F829 80and#$80
$12FAc9 80cmp#$80
$12FCd0 0fbnesetup_filter_route
$12FEb9 79 18ldainstr_pwm_pulse_init,y
$130148pha
$130229 f0and#$f0
$13049d 43 17stavoice_pulse_lo,x
$130768pla
$130829 0fand#$0f
$130A9d 46 17stavoice_pulse_hi,x
; --- Setup Filter Routing ---
$130Dbc 1d 10setup_filter_routeldyvoice_instr_idx,x; x-ref: $12FC
$1310b9 9c 18ldainstr_filter_route,y
$131348pha
$131429 f0and#$f0
$13168d 0b 10statemp_byte
$131968pla
$131Aa0 00ldy#$00
$131C29 0fand#$0f
$131Ef0 1dbeqb_133D
$1320c9 08cmp#$08
$1322f0 18beqb_133C
$13240aasla
$13250aasla
$13260aasla
$13270aasla
$13280d 09 10orasid_volume
$132B8d 18 d4sta$d418; Select Filter Mode and Volume
$132Ec8iny
$132Fad 0a 10ldasid_filter_route
$133229 0fand#$0f
$13341d f5 16oravoice_filter_bit,x
$13370d 0b 10oratemp_byte
$133Ad0 07bneb_1343
$133Cc8b_133Ciny; x-ref: $1322
$133Dad 0a 10b_133Dldasid_filter_route; x-ref: $131E
$13403d f8 16andvoice_filter_mask,x
$13438d 17 d4b_1343sta$d417; x-ref: $133A Filter Resonance Control / Voice Input Control
$13468d 0a 10stasid_filter_route
$1349c0 01cpy#$01
$134Bd0 1ebnewrite_adsr_gate
$134Dbc 1d 10ldyvoice_instr_idx,x
$1350b9 9d 18ldainstr_filter_tbl_start,y
$13538d 4d 17stafilter_tbl_idx
$1356a8tay
$1357b9 55 18ldainstr_filter_ctrl,y
$135A29 80and#$80
$135Cc9 80cmp#$80
$135Ed0 06bneb_1366
$1360b9 56 18ldainstr_filter_cutoff,y
$13638d 4f 17stafilter_cutoff
$1366a9 00b_1366lda#$00; x-ref: $135E
$13688d 4e 17stafilter_delay
; --- Write ADSR & Gate On ---
$136Bbc 1d 10write_adsr_gateldyvoice_instr_idx,x; x-ref: $134B
$136Eb9 99 18ldainstr_adsr_atk_dec,y
$1371bc fb 16ldyvoice_sid_offset,x
$137499 05 d4sta$d405,y; Voice 1: Attack / Decay Cycle Control
$1377bc 1d 10ldyvoice_instr_idx,x
$137Ab9 9a 18ldainstr_adsr_sus_rel,y
$137Dbc fb 16ldyvoice_sid_offset,x
$138099 06 d4sta$d406,y; Voice 1: Sustain / Release Cycle Control
$1383a9 09lda#$09
$138599 04 d4sta$d404,y; control = $09 (gate on); Voice 1: Control Register
$13884c 1b 16jmpnext_voice
; --- Process Effects (PWM, Filter, Arpeggio, Vibrato) ---
$138Bbd 40 17process_effectsldavoice_pwm_delay,x; PWM delay counter ; x-ref: $1107, $12C3
$138Ef0 06bequpdate_pwm_params
$1390de 40 17decvoice_pwm_delay,x
$13934c e0 13jmpapply_pwm
; --- Update PWM Parameters ---
$1396bc 3d 17update_pwm_paramsldyvoice_pwm_tbl_idx,x; x-ref: $138E
$1399b9 76 18ldainstr_pwm_minmax,y
$139C48pha
$139D4alsra
$139E4alsra
$139F4alsra
$13A04alsra
$13A19d 31 17stavoice_pwm_min_hi,x
$13A468pla
$13A529 0fand#$0f
$13A79d 34 17stavoice_pwm_max_hi,x
$13AAb9 77 18ldainstr_pwm_step,y
$13AD9d 37 17stavoice_pwm_step,x
$13B0b9 78 18ldainstr_pwm_ctrl,y
$13B38d 0b 10statemp_byte
$13B629 3fand#$3f
$13B89d 40 17stavoice_pwm_delay,x
$13BB2c 0b 10bittemp_byte
$13BE10 14bplb_13D4
$13C0b9 79 18ldainstr_pwm_pulse_init,y
$13C348pha
$13C429 f0and#$f0
$13C69d 43 17stavoice_pulse_lo,x
$13C968pla
$13CA29 0fand#$0f
$13CC9d 46 17stavoice_pulse_hi,x
$13CFa9 00lda#$00
$13D19d 3a 17stavoice_pwm_dir,x
$13D42c 0b 10b_13D4bittemp_byte; x-ref: $13BE
$13D770 07bvsapply_pwm
$13D998tya
$13DA18clc
$13DB69 04adc#$04
$13DD9d 3d 17stavoice_pwm_tbl_idx,x
; --- Apply PWM (Triangle Wave Oscillator) ---
$13E0bd 3a 17apply_pwmldavoice_pwm_dir,x; x-ref: $1393, $13D7
$13E3d0 19bnepwm_subtract
$13E5bd 43 17ldavoice_pulse_lo,x
$13E818clc
$13E97d 37 17adcvoice_pwm_step,x
$13EC9d 43 17stavoice_pulse_lo,x
$13EFbd 46 17ldavoice_pulse_hi,x
$13F269 00adc#$00
$13F49d 46 17stavoice_pulse_hi,x
$13F7dd 34 17cmpvoice_pwm_max_hi,x
$13FAd0 21bneb_141D
$13FCf0 17beqpwm_flip_dir
$13FEbd 43 17pwm_subtractldavoice_pulse_lo,x; x-ref: $13E3
$140138sec
$1402fd 37 17sbcvoice_pwm_step,x
$14059d 43 17stavoice_pulse_lo,x
$1408bd 46 17ldavoice_pulse_hi,x
$140Be9 00sbc#$00
$140D9d 46 17stavoice_pulse_hi,x
$1410dd 31 17cmpvoice_pwm_min_hi,x
$1413d0 08bneb_141D
$1415bd 3a 17pwm_flip_dirldavoice_pwm_dir,x; flip PWM direction at bounds ; x-ref: $13FC
$141849 01eor#$01
$141A9d 3a 17stavoice_pwm_dir,x
$141Da0 00b_141Dldy#$00; x-ref: $13FA, $1413
$141F8atxa
$1420d9 56 18cmpinstr_filter_cutoff,y
$1423f0 03bequpdate_filter
$14254c a3 14jmpprocess_arpeggio
; --- Update Filter Sweep ---
$1428ad 4e 17update_filterldafilter_delay; x-ref: $1423
$142Bf0 06beqb_1433
$142Dce 4e 17decfilter_delay
$14304c 76 14jmpapply_filter
$1433ac 4d 17b_1433ldyfilter_tbl_idx; x-ref: $142B
$1436b9 53 18ldainstr_filter_minmax,y
$143948pha
$143A29 f0and#$f0
$143C8d 49 17stafilter_min
$143F68pla
$14400aasla
$14410aasla
$14420aasla
$14430aasla
$14448d 4a 17stafilter_max
$1447b9 54 18ldainstr_filter_step,y
$144A8d 4b 17stafilter_step
$144Db9 55 18ldainstr_filter_ctrl,y
$14508d 0b 10statemp_byte
$145329 3fand#$3f
$14558d 4e 17stafilter_delay
$14582c 0b 10bittemp_byte
$145B10 0bbplb_1468
$145Db9 56 18ldainstr_filter_cutoff,y
$14608d 4f 17stafilter_cutoff
$1463a9 00lda#$00
$14658d 4c 17stafilter_dir
$14682c 0b 10b_1468bittemp_byte; x-ref: $145B
$146B70 09bvsapply_filter
$146Dad 4d 17ldafilter_tbl_idx
$147018clc
$147169 04adc#$04
$14738d 4d 17stafilter_tbl_idx
; --- Apply Filter (Triangle Wave) ---
$1476ad 4c 17apply_filterldafilter_dir; x-ref: $1430, $146B
$1479d0 11bnefilter_subtract
$147Bad 4f 17ldafilter_cutoff
$147E18clc
$147F6d 4b 17adcfilter_step
$14828d 4f 17stafilter_cutoff
$1485cd 4a 17cmpfilter_max
$148890 19bccprocess_arpeggio
$148Ab0 0fbcsfilter_flip_dir
$148Cad 4f 17filter_subtractldafilter_cutoff; x-ref: $1479
$148F38sec
$1490ed 4b 17sbcfilter_step
$14938d 4f 17stafilter_cutoff
$1496cd 49 17cmpfilter_min
$1499b0 08bcsprocess_arpeggio
$149Bad 4c 17filter_flip_dirldafilter_dir; flip filter direction at bounds ; x-ref: $148A
$149E49 01eor#$01
$14A08d 4c 17stafilter_dir
; --- Process Arpeggio & Frequency ---
$14A3bc 1d 10process_arpeggioldyvoice_instr_idx,x; arpeggio enabled for this instr? ; x-ref: $1425, $1488, $1499
$14A6b9 9b 18ldainstr_arp_enable,y
$14A9f0 1fbeqarpeggio_relative
$14ABbc 50 17ldyvoice_arp_pos,x
$14AEb9 8b 17ldaarp_sequence,y
$14B1c9 7fcmp#$7f
$14B3d0 0abneb_14BF
$14B5b9 ef 17ldawaveform_data,y
$14B89d 50 17stavoice_arp_pos,x
$14BBa8tay
$14BCb9 8b 17ldaarp_sequence,y
$14BF9d 0f 10b_14BFstavoice_freq_hi,x; x-ref: $14B3
$14C2a9 00lda#$00
$14C49d 0c 10stavoice_freq_lo,x
$14C74c 09 15jmpprocess_vibrato
; --- Arpeggio: Relative Mode ---
$14CAbc 50 17arpeggio_relativeldyvoice_arp_pos,x; x-ref: $14A9
$14CDb9 8b 17ldaarp_sequence,y
$14D030 10bmib_14E2
$14D2c9 7fcmp#$7f
$14D4d0 12bnecalc_note_freq
$14D6b9 ef 17ldawaveform_data,y
$14D99d 50 17stavoice_arp_pos,x
$14DCa8tay
$14DDb9 8b 17ldaarp_sequence,y
$14E010 06bplcalc_note_freq
$14E20ab_14E2asla; x-ref: $14D0
$14E3a0 01ldy#$01
$14E54c f3 14jmplookup_freq
; --- Calculate Note Frequency ---
; note_idx = (arp_val + base_note) * 2 + transpose
$14E818calc_note_freqclc; add base note number ; x-ref: $14D4, $14E0
$14E97d 14 10adcvoice_note,x
$14EC0aasla; * 2 (word index)
$14ED18clc
$14EE7d 17 10adcvoice_transpose,x; add transpose offset
$14F1a0 00ldy#$00
; --- Lookup Frequency from Table ---
$14F38c 0b 10lookup_freqstytemp_byte; x-ref: $14E5
$14F6a8tay
$14F7b9 28 16ldasid_freq_table,y; freq lo from table; C-0 (ref for slide calc)
$14FA18clc; add finetune offset
$14FB7d 62 17adcvoice_finetune,x
$14FE9d 0c 10stavoice_freq_lo,x
$1501b9 29 16ldasid_freq_table_hi,y
$150469 00adc#$00
$15069d 0f 10stavoice_freq_hi,x
; --- Process Vibrato / Portamento ---
$1509bc 50 17process_vibratoldyvoice_arp_pos,x; read waveform ctrl byte from table ; x-ref: $14C7
$150Cb9 ef 17ldawaveform_data,y
$150F9d 0a 17stavoice_waveform_1,x
$1512fe 50 17incvoice_arp_pos,x
$1515bd 04 17ldavoice_vibrato_en,x
$1518f0 49beqcalc_portamento
$151Abd 59 17ldavoice_vib_sub_dir,x
$151Dd0 16bnevib_subtract
$151Fbd 5c 17ldavoice_vib_sub_lo,x
$152218clc
$15237d 53 17adcvoice_vib_delta_lo,x
$15269d 5c 17stavoice_vib_sub_lo,x
$1529bd 5f 17ldavoice_vib_sub_hi,x
$152C7d 56 17adcvoice_vib_delta_hi,x
$152F9d 5f 17stavoice_vib_sub_hi,x
$15324c 48 15jmpapply_vib_to_freq
$1535bd 5c 17vib_subtractldavoice_vib_sub_lo,x; x-ref: $151D
$153838sec
$1539fd 53 17sbcvoice_vib_delta_lo,x
$153C9d 5c 17stavoice_vib_sub_lo,x
$153Fbd 5f 17ldavoice_vib_sub_hi,x
$1542fd 56 17sbcvoice_vib_delta_hi,x
$15459d 5f 17stavoice_vib_sub_hi,x
$1548ad 0b 10apply_vib_to_freqldatemp_byte; x-ref: $1532
$154Bd0 13bneb_1560
$154Dbd 0c 10ldavoice_freq_lo,x
$155018clc
$15517d 5c 17adcvoice_vib_sub_lo,x
$15549d 0c 10stavoice_freq_lo,x
$1557bd 0f 10ldavoice_freq_hi,x
$155A7d 5f 17adcvoice_vib_sub_hi,x
$155D9d 0f 10stavoice_freq_hi,x
$15604c f1 15b_1560jmpwrite_sid_regs; x-ref: $154B, $1566
; --- Calculate Portamento ---
; Compute semitone interval from freq table, divide by rate
$1563bd 01 17calc_portamentoldavoice_porta_mode,x; portamento mode active? ; x-ref: $1518
$1566f0 f8beqb_1560
$1568bd 14 10ldavoice_note,x; note * 2 = word offset
$156B0aasla
$156Ca8tay
$156Db9 2a 16ldasid_freq_table_hi_plus_1,y; freq[note+1] - freq[note]; C#0 - start of indexed table (note*2)
$157038sec
$1571f9 28 16sbcsid_freq_table,y; C-0 (ref for slide calc)
$15748d e8 16statemp_interval
$1577b9 2b 16ldasid_freq_table_hi_plus_2,y
$157Af9 29 16sbcsid_freq_table_hi,y
$157D18clc
$157E7d 22 17adcvoice_vib_accum,x
$15818d 0b 10statemp_byte
$1584bc 2e 17ldyvoice_vib_rate_div,x
; --- Divide Interval by Rate ---
$158788divide_intervaldey; right-shift loop (divide by 2^rate) ; x-ref: $1590
$158830 09bmiupdate_vib_period
$158A4e 0b 10lsrtemp_byte
$158D6e e8 16rortemp_interval
$15904c 87 15jmpdivide_interval
; --- Update Vibrato Period ---
$1593de 19 17update_vib_perioddecvoice_vib_period_ctr,x; dec period counter ; x-ref: $1588
$159610 0ebplapply_vibrato
$1598bd 25 17ldavoice_vib_dir,x
$159B49 01eor#$01
$159D9d 25 17stavoice_vib_dir,x
$15A0bd 1c 17ldavoice_vib_period,x
$15A39d 19 17stavoice_vib_period_ctr,x
; --- Apply Vibrato Offset ---
$15A6bd 25 17apply_vibratoldavoice_vib_dir,x; direction flag: 0=add, 1=sub ; x-ref: $1596
$15A9d0 16bnevibrato_sub
$15ABbd 28 17ldavoice_vib_offset_lo,x
$15AE18clc
$15AF6d e8 16adctemp_interval
$15B29d 28 17stavoice_vib_offset_lo,x
$15B5bd 2b 17ldavoice_vib_offset_hi,x
$15B86d 0b 10adctemp_byte
$15BB9d 2b 17stavoice_vib_offset_hi,x
$15BE4c d4 15jmpadd_vib_to_freq
$15C1bd 28 17vibrato_subldavoice_vib_offset_lo,x; x-ref: $15A9
$15C438sec
$15C5ed e8 16sbctemp_interval
$15C89d 28 17stavoice_vib_offset_lo,x
$15CBbd 2b 17ldavoice_vib_offset_hi,x
$15CEed 0b 10sbctemp_byte
$15D19d 2b 17stavoice_vib_offset_hi,x
; --- Add Vibrato to Base Frequency ---
$15D4bd 0c 10add_vib_to_freqldavoice_freq_lo,x; freq += vibrato offset ; x-ref: $15BE
$15D718clc
$15D87d 28 17adcvoice_vib_offset_lo,x
$15DB9d 0c 10stavoice_freq_lo,x
$15DEbd 0f 10ldavoice_freq_hi,x
$15E17d 2b 17adcvoice_vib_offset_hi,x
$15E49d 0f 10stavoice_freq_hi,x
$15E7bd 22 17ldavoice_vib_accum,x
$15EA18clc
$15EB7d 1f 17adcvoice_vib_depth_inc,x
$15EE9d 22 17stavoice_vib_accum,x
; --- Write SID Registers ---
; Output pulse width, filter cutoff, frequency, and control.
$15F1bc fb 16write_sid_regsldyvoice_sid_offset,x; x-ref: $1560
$15F4bd 43 17ldavoice_pulse_lo,x
$15F799 02 d4sta$d402,y; Voice 1: Pulse Waveform Width - Low-Byte
$15FAbd 46 17ldavoice_pulse_hi,x
$15FD99 03 d4sta$d403,y; Voice 1: Pulse Waveform Width - High-Nybble
$1600ad 4f 17ldafilter_cutoff
$16038d 16 d4sta$d416; Filter Cutoff Frequency: High-Byte
$1606bd 0c 10ldavoice_freq_lo,x
$160999 00 d4sta$d400,y; Voice 1: Frequency Control - Low-Byte
$160Cbd 0f 10ldavoice_freq_hi,x
$160F99 01 d4sta$d401,y; Voice 1: Frequency Control - High-Byte
$1612bd 0a 17ldavoice_waveform_1,x
$16153d 1a 10andvoice_gate_mask,x
$161899 04 d4sta$d404,y; Voice 1: Control Register
; --- Next Voice / Exit ---
$161Bcanext_voicedex; next voice (2->1->0) ; x-ref: $10E9, $12AA, $12C0, $1388
$161C30 03bmiplayer_exit; all done when X < 0
$161E4c e4 10jmpvoice_loop
$162168player_exitpla; restore ZP pointers and return ; x-ref: $161C
$162285 fcstamusic_ptr_hi
$162468pla
$162585 fbstamusic_ptr_lo
$162760rts
sid_freq_table_hi =*+$01 ; x-ref: $1501, $157A
; SID frequency table for PAL system.
; 96 entries (8 octaves x 12 notes), 16-bit little-endian.
; Note index 0 = C-0 ($0116 = 278), up to B-7 ($FD2E = 64814).
; First entry is used as a reference for portamento/slide calculations.
; Accessed via note index * 2 as word offset.
$1628sid_freq_table.word$0116; C-0 (ref for slide calc) ; x-ref: $14F7, $1571
sid_freq_table_hi_plus_2 =*+$01 ; x-ref: $1577
sid_freq_table_hi_plus_1
$162A.word$0127, $0138, $014b, $015f, $0173; C#0 - start of indexed table (note*2) ; x-ref: $156D
$1634.word$018a, $01a1, $01ba, $01d4, $01f0
$163E.word$020e
$1640.word$022d, $024e, $0271, $0296, $02bd; Octave 1: C-1 to B-1
$164A.word$02e7, $0313, $0342, $0374, $03a9
$1654.word$03e0, $041b
$1658.word$045a, $049b, $04e2, $052c, $057b; Octave 2: C-2 to B-2
$1662.word$05ce, $0627, $0685, $06e8, $0751
$166C.word$07c1, $0837
$1670.word$08b4, $0937, $09c4, $0a57, $0af5; Octave 3: C-3 to B-3
$167A.word$0b9c, $0c4e, $0d09, $0dd0, $0ea3
$1684.word$0f82, $106e
$1688.word$1168, $126e, $1388, $14af, $15eb; Octave 4: C-4 to B-4
$1692.word$1739, $189c, $1a13, $1ba1, $1d46
$169C.word$1f04, $20dc
$16A0.word$22d0, $24dc, $2710, $295e, $2bd6; Octave 5: C-5 to B-5
$16AA.word$2e72, $3138, $3426, $3742, $3a8c
$16B4.word$3e08, $41b8
$16B8.word$45a0, $49b8, $4e20, $52bc, $57ac; Octave 6: C-6 to B-6
$16C2.word$5ce4, $6270, $684c, $6e84, $7518
$16CC.word$7c10, $8370
$16D0.word$8b40, $9370, $9c40, $a578, $af58; Octave 7: C-7 to B-7
$16DA.word$b9c8, $c4e0, $d098, $dd08, $ea30
$16E4.word$f820, $fd2e
$16E8temp_interval.byte$22; x-ref: $1067, $1070, $1077, $1574, $158D, $15AF, $15C5
$16E9voice_pat_ptr_lo.byte<song_order_v0, <song_order_v1, <song_order_v2; x-ref: $1049, $1110, $1128, $1274, $127A, $1292
$16ECvoice_pat_ptr_hi.byte>song_order_v0, >song_order_v1, >song_order_v2; x-ref: $1052, $1115, $112D, $127F, $1284, $1298
$16EFvoice_loop_ptr_lo.byte<song_order_loop_v0, <song_order_loop_v1, <song_order_loop_v2; x-ref: $104C, $10A3, $128F
$16F2voice_loop_ptr_hi.byte>song_order_loop_v0, >song_order_loop_v1, >song_order_loop_v2; x-ref: $1055, $10A9, $1295
$16F5voice_filter_bit.byte$01, $02, $04; x-ref: $1090, $1334
$16F8voice_filter_mask.byte$fe, $fd, $fb; x-ref: $1340
$16FBvoice_sid_offset.byte$00, $07, $0e; x-ref: $10FE, $12A4, $12CE, $1371, $137D, $15F1
$16FEvoice_tie_flag.byte$00, $01, $01; x-ref: $111D, $1161, $116C, $1197, $12AD
$1701voice_porta_mode.byte$00, $00, $00; x-ref: $114E, $1153, $11FA, $1205, $12BB, $12C8, $1563
$1704voice_vibrato_en.byte$00, $01, $00; x-ref: $1156, $115B, $11DF, $11EF, $1515
$1707voice_release_tick.byte$00, $00, $00; x-ref: $10F1, $10F8, $123D
$170Avoice_waveform_1.byte$41; x-ref: $150F, $1612, $223A
$170Bvoice_waveform_2.byte$17; x-ref: $2241
$170Cvoice_waveform_3.byte$00; x-ref: $2248
$170Dvoice_pat_pos.byte$03, $06, $05; x-ref: $10C2, $113E, $11A7, $11B7, $1262, $1265, $1270
$1710voice_rel_adsr.byte$00, $00, $00; x-ref: $10FB, $1243
$1713voice_speed_val.byte$2f, $2f, $2f; x-ref: $110A, $11A4
$1716voice_speed_ctr.byte$08; x-ref: $10CC, $10EC, $1104, $110D, $11A1
$1717sid_unused_1717.byte$0b; x-ref: $10CF
$1718sid_unused_1718.byte$0b; x-ref: $10D2
$1719voice_vib_period_ctr.byte$03, $04, $01; x-ref: $121C, $1593, $15A3
$171Cvoice_vib_period.byte$03, $04, $03; x-ref: $1216, $15A0
$171Fvoice_vib_depth_inc.byte$01, $00, $00; x-ref: $120B, $15EB
$1722voice_vib_accum.byte$0f, $00, $00; x-ref: $1224, $157E, $15E7, $15EE
$1725voice_vib_dir.byte$00, $00, $00; x-ref: $1221, $1598, $159D, $15A6
$1728voice_vib_offset_lo.byte$87, $ad, $49; x-ref: $1227, $15AB, $15B2, $15C1, $15C8, $15D8
$172Bvoice_vib_offset_hi.byte$ff, $ff, $00; x-ref: $122A, $15B5, $15BB, $15CB, $15D1, $15E1
$172Evoice_vib_rate_div.byte$05, $02, $01; x-ref: $1230, $1584
$1731voice_pwm_min_hi.byte$05, $00, $00; x-ref: $13A1, $1410
$1734voice_pwm_max_hi.byte$07, $00, $00; x-ref: $13A7, $13F7
$1737voice_pwm_step.byte$18, $00, $00; x-ref: $13AD, $13E9, $1402
$173Avoice_pwm_dir.byte$00, $00, $00; x-ref: $13D1, $13E0, $1415, $141A
$173Dvoice_pwm_tbl_idx.byte$04, $18, $18; x-ref: $12EC, $1396, $13DD
$1740voice_pwm_delay.byte$0b, $19, $19; x-ref: $12F2, $138B, $1390, $13B8
$1743voice_pulse_lo.byte$d8, $00, $00; x-ref: $1304, $13C6, $13E5, $13EC, $13FE, $1405, $15F4
$1746voice_pulse_hi.byte$06, $08, $08; x-ref: $130A, $13CC, $13EF, $13F4, $1408, $140D, $15FA
$1749filter_min.byte$10; x-ref: $143C, $1496
$174Afilter_max.byte$a0; x-ref: $1444, $1485
$174Bfilter_step.byte$01; x-ref: $144A, $147F, $1490
$174Cfilter_dir.byte$01; x-ref: $1465, $1476, $149B, $14A0
$174Dfilter_tbl_idx.byte$08; x-ref: $1353, $1433, $146D, $1473
$174Efilter_delay.byte$0b; x-ref: $1368, $1428, $142D, $1455
$174Ffilter_cutoff.byte$6b; x-ref: $1363, $1460, $147B, $1482, $148C, $1493, $1600
$1750voice_arp_pos.byte$02, $42, $1d; x-ref: $1186, $12E6, $14AB, $14B8, $14CA, $14D9, $1509, $1512
$1753voice_vib_delta_lo.byte$18, $10, $60; x-ref: $11DA, $1523, $1539
$1756voice_vib_delta_hi.byte$00, $00, $00; x-ref: $11CD, $152C, $1542
$1759voice_vib_sub_dir.byte$00, $20, $20; x-ref: $11D4, $151A
$175Cvoice_vib_sub_lo.byte$b8, $b0, $20; x-ref: $11E4, $151F, $1526, $1535, $153C, $1551
$175Fvoice_vib_sub_hi.byte$08, $fd, $dd; x-ref: $11E7, $1529, $152F, $153F, $1545, $155A
$1762voice_finetune.byte$00, $01, $02; x-ref: $14FB
$1765speed_lookup.byte$02, $05, $08, $0b, $0e, $11, $14, $17; x-ref: $106A, $119E
$176D.byte$1a, $1d, $20, $23, $26, $29, $2c, $2f
$1775.byte$00, $00, $00, $fc, $3c, $01
song_pattern_ptr_table
$177B.byte$51; x-ref: $1046, $1064, $1074
song_pattern_ptr_table_hi
$177C.byte$19; x-ref: $104F, $108A
song_loop_ptr_table_lo
$177D.byte$9e; x-ref: $10A0
song_loop_ptr_table_hi
$177E.byte$19, $d7, $19, $02, $07, $51, $19, $9e; x-ref: $10A6
$1786.byte$19, $d7, $19, $ff, $ff
$178Barp_sequence.byte$ca, $00, $7f, $00, $00, $00, $7f, $ca; x-ref: $14AE, $14BC, $14CD, $14DD
$1793.byte$0d, $0c, $0a, $07, $00, $7f, $30, $11
$179B.byte$0d, $e0, $0c, $7f, $ca, $0e, $0b, $09
$17A3.byte$06, $00, $00, $00, $00, $00, $00, $7f
$17AB.byte$e0, $00, $03, $07, $7f, $e0, $00, $03
$17B3.byte$08, $7f, $e0, $00, $05, $08, $7f, $e0
$17BB.byte$00, $05, $09, $7f, $e0, $00, $04, $07
$17C3.byte$7f, $00, $bc, $01, $bd, $02, $be, $03
$17CB.byte$bf, $04, $c0, $7f, $ca, $01, $00, $7f
$17D3.byte$ca, $00, $05, $0a, $7f
$17D8.fill20, $00
$17EC.byte$7f, $ca, $7f
$17EFwaveform_data.byte$81, $41, $01, $11, $21, $41, $05, $81; x-ref: $14B5, $14D6, $150C
$17F7.byte$41, $41, $41, $41, $00, $0c, $81, $41
$17FF.byte$41, $80, $11, $11, $81, $11, $11, $11
$1807.byte$11, $00, $00, $00, $00, $00, $00, $15
$180F.byte$81, $21, $21, $21, $21, $81, $21, $21
$1817.byte$21, $26, $81, $21, $21, $21, $2b, $81
$181F.byte$21, $21, $21, $30, $81, $21, $21, $21
$1827.byte$35, $13, $13, $53, $53, $23, $23, $15
$182F.byte$15, $17, $17, $39, $81, $11, $11, $46
$1837.byte$81, $21, $21, $21, $49, $41, $41, $41
$183F.byte$41
$1840.fill16, $01
$1850.byte$4d, $81, $62
$1853instr_filter_minmax.byte$00; x-ref: $12B2, $1436
$1854instr_filter_step.byte$00; x-ref: $1447
$1855instr_filter_ctrl.byte$00; x-ref: $1357, $144D
$1856instr_filter_cutoff.byte$00, $19, $01, $81, $90, $1a, $01, $4f; x-ref: $1360, $1420, $145D
$185E.byte$f0, $32, $12, $85, $9e, $14, $01, $8a
$1866.byte$20, $14, $01, $4f, $20, $1a, $05, $83
$186E.byte$a0, $00, $00, $4f, $00, $00, $00, $00
$1876instr_pwm_minmax.byte$35; x-ref: $1399
$1877instr_pwm_step.byte$30; x-ref: $13AA
$1878instr_pwm_ctrl.byte$81; x-ref: $12F5, $13B0
$1879instr_pwm_pulse_init.byte$03, $57, $18, $4f, $05, $36, $a0, $81; x-ref: $12FE, $13C0
$1881.byte$06, $3d, $20, $4f, $30, $48, $30, $85
$1889.byte$08, $4d, $80, $4f, $04, $00, $00, $ff
$1891.byte$08, $1f, $10, $4f, $00, $00, $00, $00
$1899instr_adsr_atk_dec.byte$00; x-ref: $136E
$189Ainstr_adsr_sus_rel.byte$00; x-ref: $137A
$189Binstr_arp_enable.byte$00; x-ref: $14A6
$189Cinstr_filter_route.byte$00; x-ref: $1310
instr_filter_tbl_start
$189D.byte$00; x-ref: $1350
$189Einstr_pwm_tbl_start.byte$00; x-ref: $12E9
$189Finstr_arp_loop_pos.byte$00; x-ref: $1181, $1259, $12E3
instr_arp_restart_pos
$18A0.byte$00, $00, $89, $00, $f1, $04, $00, $00; x-ref: $117E, $125C
$18A8.byte$00, $00, $d9, $00, $f1, $0c, $08, $00
$18B0.byte$00, $00, $71, $00, $00, $00, $10, $03
$18B8.byte$03, $00, $c8, $10, $00, $00, $18, $07
$18C0.byte$07, $09, $08, $10, $00, $00, $18, $0e
$18C8.byte$0e, $08, $09, $00, $00, $00, $00, $20
$18D0.byte$20, $08, $09, $00, $00, $00, $00, $25
$18D8.byte$25, $08, $09, $00, $00, $00, $00, $2a
$18E0.byte$2a, $08, $09, $00, $00, $00, $00, $2f
$18E8.byte$2f, $08, $09, $00, $00, $00, $00, $34
$18F0.byte$34, $00, $d9, $10, $00, $00, $18, $14
$18F8.byte$14, $00, $8d, $00, $00, $00, $18, $39
$1900.byte$39, $40, $88, $00, $00, $00, $00, $44
$1908.byte$44, $08, $09, $00, $00, $00, $00, $48
$1910.byte$48, $00, $9b, $00, $00, $00, $1c, $4d
$1918.byte$4d, $00, $41, $00, $00, $00, $00, $62
$1920.byte$62, $00, $c8, $10, $f1, $0c, $18, $07
$1928.byte$07, $09, $08, $10, $f1, $18, $18, $0e
$1930.byte$0e, $00, $9b, $00, $00, $00, $1c, $4d
$1938.byte$4d
$1939.fill8, $00
$1941effect_cmd_1.byte$82; x-ref: $11C1
$1942effect_cmd_2.byte$00, $10, $d0, $60, $31, $60, $42, $61; x-ref: $11D7, $120E, $1240, $1249
$194A.byte$35, $30, $10, $10, $80, $00, $00
$1951song_order_loop_v0.byte$80, $0a, $80; x-ref: $16EF
$1954song_order_v0.byte$0a, $02, $05, $02, $05, $02, $05, $02; x-ref: $16E9
$195C.byte$05, $02, $05, $02, $05, $02, $05, $02
$1964.byte$05, $11, $10, $11, $0f, $02, $05, $02
$196C.byte$05, $14, $15, $02, $05, $02, $05, $1a
$1974.byte$1c, $1a, $1c, $1f, $82, $1f, $83, $1f
$197C.byte$82, $1f, $80, $1f, $82, $1f, $83, $1f
$1984.byte$87, $1f, $80, $1f, $82, $1f, $83, $1f
$198C.byte$82, $1f, $80, $1f, $82, $1f, $83, $1f
$1994.byte$87, $1f, $80, $02, $05, $02, $05, $14
$199C.byte$15, $ff
$199Esong_order_loop_v1.byte$8c, $0b, $86; x-ref: $16F0
$19A1song_order_v1.byte$0b, $8c, $0b, $0b, $0b, $0b, $80, $01; x-ref: $16EA
$19A9.byte$04, $08, $07, $0c, $0d, $0c, $0e, $8c
$19B1.byte$0b, $0b, $0b, $0b, $0b, $0b, $0b, $86
$19B9.byte$12, $80, $01, $04, $08, $07, $18, $19
$19C1.byte$8c, $0b, $0b, $0b, $86, $0b, $80, $1b
$19C9.byte$1d, $1b, $1d, $1a, $1c, $1a, $1c, $20
$19D1.byte$21, $20, $23, $18, $19, $ff
$19D7song_order_loop_v2.byte$8c, $09, $8c; x-ref: $16F1
$19DAsong_order_v2.byte$09, $03, $06, $03, $06, $03, $06, $03; x-ref: $16EB
$19E2.byte$06, $03, $06, $03, $06, $03, $06, $03
$19EA.byte$06, $03, $06, $03, $13, $03, $06, $03
$19F2.byte$06, $16, $17, $03, $06, $03, $06
$19F9.fill16, $1e
$1A09.byte$80, $1b, $1d, $1b, $1d, $8c, $03, $06
$1A11.byte$03, $06, $16, $17, $ff
$1A16song_ptr_lo.byte<pat_00, <pat_01, <pat_02, <pat_03, <pat_04; x-ref: $1134
$1A1B.byte<pat_05, <pat_06, <pat_07, <pat_08, <pat_09
$1A20.byte<pat_10, <pat_11, <pat_12, <pat_13, <pat_14
$1A25.byte<pat_15, <pat_16, <pat_17, <pat_18, <pat_19
$1A2A.byte<pat_20, <pat_21, <pat_22, <pat_23, <pat_24
$1A2F.byte<pat_25, <pat_26, <pat_27, <pat_28, <pat_29
$1A34.byte<pat_30, <pat_31, <pat_32, <pat_33, <pat_34
$1A39.byte<pat_35
$1A3Asong_ptr_hi.byte>pat_00, >pat_01, >pat_02, >pat_03, >pat_04; x-ref: $1139
$1A3F.byte>pat_05, >pat_06, >pat_07, >pat_08, >pat_09
$1A44.byte>pat_10, >pat_11, >pat_12, >pat_13, >pat_14
$1A49.byte>pat_15, >pat_16, >pat_17, >pat_18, >pat_19
$1A4E.byte>pat_20, >pat_21, >pat_22, >pat_23, >pat_24
$1A53.byte>pat_25, >pat_26, >pat_27, >pat_28, >pat_29
$1A58.byte>pat_30, >pat_31, >pat_32, >pat_33, >pat_34
$1A5D.byte>pat_35
$1A5Epat_00.byte$8f, $00, $00, $00, $00, $7f; x-ref: $1A16
$1A64pat_01.byte$a3, $85, $39, $c3, $84, $7e, $c0, $80; x-ref: $1A17
$1A6C.byte$7e, $82, $3b, $c0, $80, $7e, $82, $3c
$1A74.byte$c0, $80, $7e, $3e, $c1, $7e, $90, $40
$1A7C.byte$c0, $84, $00, $85, $3e, $c3, $84, $7e
$1A84.byte$c0, $80, $7e, $84, $37, $c3, $81, $7e
$1A8C.byte$c0, $80, $7e, $41, $c1, $7e, $90, $43
$1A94.byte$81, $7e, $c3, $7e, $c0, $80, $7e, $84
$1A9C.byte$41, $c3, $81, $7e, $c0, $80, $7e, $7f
$1AA4pat_02.byte$a2, $82, $15, $c0, $80, $7e, $15, $c0; x-ref: $1A18
$1AAC.byte$7e, $82, $15, $c0, $80, $7e, $15, $c0
$1AB4.byte$7e, $82, $15, $c0, $80, $7e, $82, $15
$1ABC.byte$c0, $80, $7e, $82, $17, $c0, $80, $7e
$1AC4.byte$82, $18, $c0, $80, $7e, $82, $19, $c0
$1ACC.byte$80, $7e, $82, $1a, $c0, $80, $7e, $1a
$1AD4.byte$c0, $7e, $82, $1a, $c0, $80, $7e, $1a
$1ADC.byte$c0, $7e, $82, $1a, $c0, $80, $7e, $82
$1AE4.byte$1a, $c0, $80, $7e, $82, $18, $c0, $80
$1AEC.byte$7e, $81, $17, $90, $18, $c0, $80, $7e
$1AF4.byte$82, $15, $c0, $80, $7e, $7f
$1AFApat_03.byte$a4, $80, $0c, $82, $00, $a6, $81, $2d; x-ref: $1A19
$1B02.byte$2d, $a5, $80, $0c, $82, $00, $a6, $81
$1B0A.byte$2d, $2d, $a4, $80, $0c, $82, $00, $a6
$1B12.byte$81, $2d, $2d, $a5, $80, $0c, $82, $00
$1B1A.byte$a6, $81, $2d, $2d, $a4, $80, $0c, $82
$1B22.byte$00, $a8, $81, $2d, $2d, $a5, $80, $0c
$1B2A.byte$82, $00, $a8, $81, $2d, $2d, $a4, $80
$1B32.byte$0c, $82, $00, $a8, $81, $2d, $2d, $a5
$1B3A.byte$80, $0c, $82, $00, $a8, $81, $2d, $2d
$1B42.byte$7f
$1B43pat_04.byte$a3, $85, $40, $c3, $88, $7e, $c0, $80; x-ref: $1A1A
$1B4B.byte$7e, $84, $3b, $c0, $80, $7e, $84, $3c
$1B53.byte$c0, $80, $7e, $3e, $c1, $7e, $90, $40
$1B5B.byte$83, $7e, $c0, $80, $7e, $82, $3e, $c0
$1B63.byte$80, $7e, $83, $00, $82, $3e, $c3, $83
$1B6B.byte$7e, $c0, $80, $7e, $82, $3c, $c0, $80
$1B73.byte$7e, $39, $c1, $7e, $90, $3b, $83, $7e
$1B7B.byte$c0, $80, $7e, $7f
$1B7Fpat_05.byte$a2, $82, $13, $c0, $80, $7e, $13, $c0; x-ref: $1A1B
$1B87.byte$7e, $82, $13, $c0, $80, $7e, $13, $c0
$1B8F.byte$7e, $82, $13, $c0, $80, $7e, $82, $13
$1B97.byte$c0, $80, $7e, $82, $14, $c0, $80, $7e
$1B9F.byte$82, $15, $c0, $80, $7e, $82, $17, $c0
$1BA7.byte$80, $7e, $82, $18, $c0, $80, $7e, $18
$1BAF.byte$c0, $7e, $82, $18, $c0, $80, $7e, $18
$1BB7.byte$c0, $7e, $82, $18, $c0, $80, $7e, $82
$1BBF.byte$17, $c0, $80, $7e, $82, $17, $c0, $80
$1BC7.byte$7e, $82, $17, $c0, $80, $7e, $82, $13
$1BCF.byte$c0, $80, $7e, $7f
$1BD3pat_06.byte$a4, $80, $0c, $82, $00, $a7, $81, $2f; x-ref: $1A1C
$1BDB.byte$2f, $a5, $80, $0c, $82, $00, $a7, $81
$1BE3.byte$2f, $2f, $a4, $80, $0c, $82, $00, $a7
$1BEB.byte$81, $2f, $2f, $a5, $80, $0c, $82, $00
$1BF3.byte$a7, $81, $2f, $2f, $a4, $80, $0c, $82
$1BFB.byte$00, $a9, $81, $2b, $2b, $a5, $80, $0c
$1C03.byte$82, $00, $a9, $81, $2b, $2b, $a4, $80
$1C0B.byte$0c, $82, $00, $aa, $81, $2b, $2b, $a5
$1C13.byte$80, $0c, $82, $00, $aa, $81, $2b, $2b
$1C1B.byte$7f
$1C1Cpat_07.byte$a3, $85, $3b, $c3, $88, $7e, $c0, $80; x-ref: $1A1D
$1C24.byte$7e, $82, $32, $c0, $80, $7e, $82, $34
$1C2C.byte$c0, $80, $7e, $34, $c6, $7e, $90, $35
$1C34.byte$c0, $80, $7e, $85, $34, $c3, $88, $7e
$1C3C.byte$c0, $80, $7e, $32, $c0, $7e, $30, $c0
$1C44.byte$7e, $84, $32, $c0, $80, $7e, $81, $30
$1C4C.byte$c3, $82, $7e, $c0, $80, $7e, $2d, $c6
$1C54.byte$7e, $90, $2f, $c0, $80, $7e, $7f
$1C5Bpat_08.byte$a3, $85, $39, $c3, $84, $7e, $c0, $80; x-ref: $1A1E
$1C63.byte$7e, $82, $3b, $c0, $80, $7e, $82, $3c
$1C6B.byte$c0, $80, $7e, $3e, $c1, $7e, $90, $40
$1C73.byte$c0, $84, $00, $85, $3e, $c3, $84, $7e
$1C7B.byte$c0, $80, $7e, $84, $37, $c3, $81, $7e
$1C83.byte$c0, $80, $7e, $3c, $c1, $7e, $90, $3e
$1C8B.byte$82, $7e, $90, $40, $90, $3e, $90, $3c
$1C93.byte$83, $7e, $c3, $81, $7e, $c0, $80, $7e
$1C9B.byte$7f
$1C9Cpat_09.byte$ab, $80, $0c, $8f, $00, $89, $00, $c0; x-ref: $1A1F
$1CA4.byte$80, $00, $0c, $81, $00, $c0, $80, $00
$1CAC.byte$0c, $8f, $00, $8d, $00, $c0, $80, $00
$1CB4.byte$7f
$1CB5pat_10.byte$a1, $8f, $15, $7e, $7e, $8e, $7e, $c0; x-ref: $1A20
$1CBD.byte$80, $7e, $7f
$1CC0pat_11.byte$ac, $80, $30, $c5, $8f, $00, $00, $00; x-ref: $1A21
$1CC8.byte$8d, $00, $c0, $80, $00, $7f
$1CCEpat_12.byte$a3, $82, $2d, $c0, $80, $7e, $ad, $82; x-ref: $1A22
$1CD6.byte$45, $c0, $80, $7e, $82, $47, $c0, $80
$1CDE.byte$7e, $82, $48, $c0, $80, $7e, $48, $90
$1CE6.byte$49, $90, $4a, $c0, $80, $7e, $82, $48
$1CEE.byte$c0, $80, $7e, $82, $47, $c0, $80, $7e
$1CF6.byte$82, $45, $c0, $80, $7e, $a3, $37, $c1
$1CFE.byte$7e, $90, $39, $83, $7e, $c0, $80, $7e
$1D06.byte$34, $90, $32, $80, $7e, $c0, $7e, $82
$1D0E.byte$30, $c0, $80, $7e, $82, $32, $c4, $83
$1D16.byte$7e, $c0, $80, $7e, $85, $30, $c6, $80
$1D1E.byte$7e, $c0, $7e, $7f
$1D22pat_13.byte$a3, $82, $2d, $c0, $80, $7e, $ad, $82; x-ref: $1A23
$1D2A.byte$45, $c0, $80, $7e, $43, $c0, $7e, $82
$1D32.byte$45, $c0, $80, $7e, $82, $3e, $c0, $80
$1D3A.byte$7e, $3c, $c0, $7e, $82, $3e, $c0, $80
$1D42.byte$7e, $3e, $90, $3f, $90, $40, $c0, $80
$1D4A.byte$7e, $82, $43, $c0, $80, $7e, $a3, $37
$1D52.byte$c1, $7e, $90, $39, $83, $7e, $c0, $80
$1D5A.byte$7e, $82, $3c, $c0, $80, $7e, $82, $3b
$1D62.byte$c4, $83, $7e, $c0, $80, $7e, $82, $3c
$1D6A.byte$c0, $80, $7e, $85, $30, $c6, $80, $7e
$1D72.byte$c0, $7e, $7f
$1D75pat_14.byte$a3, $82, $2d, $c0, $80, $7e, $ad, $82; x-ref: $1A24
$1D7D.byte$45, $c0, $80, $7e, $82, $47, $c0, $80
$1D85.byte$7e, $82, $48, $c0, $80, $7e, $4a, $90
$1D8D.byte$4b, $90, $4c, $c0, $80, $7e, $82, $4f
$1D95.byte$c0, $80, $7e, $82, $4d, $c0, $80, $7e
$1D9D.byte$82, $4c, $c0, $80, $7e, $a3, $3e, $c1
$1DA5.byte$7e, $90, $40, $81, $7e, $c0, $80, $7e
$1DAD.byte$84, $3e, $c0, $80, $7e, $82, $3c, $c0
$1DB5.byte$80, $7e, $3e, $c1, $7e, $90, $40, $c4
$1DBD.byte$87, $7e, $c0, $80, $7e, $a5, $30, $00
$1DC5.byte$30, $00, $7f
$1DC8pat_15.byte$a1, $8f, $15, $8e, $7e, $c0, $80, $7e; x-ref: $1A25
$1DD0.byte$a2, $84, $18, $c0, $80, $7e, $84, $1a
$1DD8.byte$c0, $80, $7e, $82, $1b, $c0, $80, $7e
$1DE0.byte$1c, $c0, $7e, $21, $c0, $7e, $1f, $c0
$1DE8.byte$7e, $1c, $c0, $7e, $1a, $90, $1c, $90
$1DF0.byte$1a, $90, $18, $90, $13, $81, $7e, $c0
$1DF8.byte$80, $7e, $7f
$1DFBpat_16.byte$a1, $8f, $15, $7e, $8e, $7e, $c0, $80; x-ref: $1A26
$1E03.byte$7e, $86, $15, $c0, $80, $7e, $81, $13
$1E0B.byte$c3, $84, $7e, $c0, $80, $7e, $7f
$1E12pat_17.byte$a1, $8f, $15, $7e, $8e, $7e, $c0, $80; x-ref: $1A27
$1E1A.byte$7e, $82, $15, $c0, $80, $7e, $82, $17
$1E22.byte$c0, $80, $7e, $81, $18, $c3, $84, $7e
$1E2A.byte$c0, $80, $7e, $7f
$1E2Epat_18.byte$ac, $80, $30, $c5, $8f, $00, $00, $8d; x-ref: $1A28
$1E36.byte$00, $c0, $80, $00, $a5, $0c, $00, $a4
$1E3E.byte$0c, $00, $0c, $00, $a5, $0c, $00, $a4
$1E46.byte$0c, $00, $0c, $00, $a5, $0c, $00, $0c
$1E4E.byte$00, $7f
$1E50pat_19.byte$a4, $80, $0c, $82, $00, $a7, $81, $2f; x-ref: $1A29
$1E58.byte$2f, $a5, $80, $0c, $82, $00, $a7, $81
$1E60.byte$2f, $2f, $a4, $80, $0c, $82, $00, $a7
$1E68.byte$81, $2f, $2f, $a5, $80, $0c, $82, $00
$1E70.byte$a7, $81, $2f, $2f, $a4, $80, $0c, $82
$1E78.byte$00, $a9, $81, $2b, $2b, $a5, $80, $0c
$1E80.byte$82, $00, $a9, $81, $2b, $2b, $85, $2b
$1E88.byte$aa, $83, $2b, $81, $2b, $2b, $2b, $7f
$1E90pat_20.byte$a2, $82, $1c, $c0, $80, $7e, $1c, $c0; x-ref: $1A2A
$1E98.byte$7e, $82, $1c, $c0, $80, $7e, $1c, $c0
$1EA0.byte$7e, $82, $1c, $c0, $80, $7e, $1a, $90
$1EA8.byte$1b, $90, $1c, $c0, $80, $7e, $82, $1c
$1EB0.byte$c0, $80, $7e, $82, $1a, $c0, $80, $7e
$1EB8.byte$82, $18, $c0, $80, $7e, $82, $1a, $c0
$1EC0.byte$80, $7e, $1a, $c0, $7e, $82, $1a, $c0
$1EC8.byte$80, $7e, $1a, $c0, $7e, $82, $1a, $c0
$1ED0.byte$80, $7e, $82, $1a, $c0, $80, $7e, $82
$1ED8.byte$1c, $c0, $80, $7e, $82, $1d, $c0, $80
$1EE0.byte$7e, $82, $1f, $c0, $80, $7e, $7f
$1EE7pat_21.byte$a2, $82, $1d, $c0, $80, $7e, $1d, $c0; x-ref: $1A2B
$1EEF.byte$7e, $82, $1d, $c0, $80, $7e, $1d, $c0
$1EF7.byte$7e, $82, $1d, $c0, $80, $7e, $82, $1d
$1EFF.byte$c0, $80, $7e, $82, $1c, $c0, $80, $7e
$1F07.byte$82, $1a, $c0, $80, $7e, $82, $18, $c0
$1F0F.byte$80, $7e, $82, $17, $c0, $80, $7e, $17
$1F17.byte$c0, $7e, $82, $17, $c0, $80, $7e, $17
$1F1F.byte$c0, $7e, $17, $90, $18, $90, $1a, $c0
$1F27.byte$80, $7e, $82, $17, $c4, $83, $7e, $c0
$1F2F.byte$80, $7e, $90, $13, $90, $14, $90, $15
$1F37.byte$c0, $80, $7e, $82, $1f, $c0, $80, $7e
$1F3F.byte$7f
$1F40pat_22.byte$a4, $80, $0c, $82, $00, $a8, $81, $2f; x-ref: $1A2C
$1F48.byte$2f, $a5, $80, $0c, $82, $00, $a8, $81
$1F50.byte$2f, $2f, $a4, $80, $0c, $82, $00, $a8
$1F58.byte$81, $2f, $2f, $a5, $80, $0c, $82, $00
$1F60.byte$a8, $81, $2f, $2f, $a4, $80, $0c, $82
$1F68.byte$00, $a7, $81, $2f, $2f, $a5, $80, $0c
$1F70.byte$82, $00, $a7, $81, $2f, $2f, $a4, $80
$1F78.byte$0c, $82, $00, $a7, $81, $2f, $2f, $a5
$1F80.byte$80, $0c, $82, $00, $a7, $81, $2f, $2f
$1F88.byte$7f
$1F89pat_23.byte$a4, $80, $0c, $82, $00, $a8, $81, $2d; x-ref: $1A2D
$1F91.byte$2d, $a5, $80, $0c, $82, $00, $a8, $81
$1F99.byte$2d, $2d, $a4, $80, $0c, $82, $00, $a8
$1FA1.byte$81, $2d, $2d, $a5, $80, $0c, $82, $00
$1FA9.byte$a8, $81, $2d, $2d, $ae, $2f, $2f, $2f
$1FB1.byte$83, $2f, $81, $2f, $83, $2f, $a9, $2f
$1FB9.byte$2f, $a6, $2d, $2d, $7f
$1FBEpat_24.byte$a3, $85, $2f, $c3, $84, $7e, $c0, $80; x-ref: $1A2E
$1FC6.byte$7e, $82, $2f, $c0, $80, $7e, $82, $30
$1FCE.byte$c0, $80, $7e, $82, $32, $c0, $80, $7e
$1FD6.byte$82, $34, $c0, $80, $7e, $32, $c1, $7e
$1FDE.byte$90, $34, $82, $7e, $c3, $8c, $7e, $c0
$1FE6.byte$80, $7e, $86, $35, $c0, $80, $7e, $86
$1FEE.byte$32, $c0, $80, $7e, $7f
$1FF3pat_25.byte$a3, $85, $35, $c3, $7e, $80, $37, $c0; x-ref: $1A2F
$1FFB.byte$7e, $35, $c0, $7e, $34, $90, $35, $90
$2003.byte$34, $90, $32, $90, $30, $c0, $80, $7e
$200B.byte$32, $c0, $7e, $34, $c0, $7e, $35, $c0
$2013.byte$7e, $34, $c0, $7e, $32, $c0, $7e, $85
$201B.byte$34, $c3, $82, $7e, $c5, $86, $7e, $a5
$2023.byte$80, $24, $00, $a4, $24, $00, $24, $00
$202B.byte$a5, $24, $00, $a4, $24, $00, $24, $00
$2033.byte$a5, $24, $00, $24, $00, $7f
$2039pat_26.byte$af, $80, $39, $86, $00, $80, $3b, $86; x-ref: $1A30
$2041.byte$00, $80, $39, $86, $00, $80, $3b, $86
$2049.byte$00, $80, $35, $86, $00, $80, $3b, $86
$2051.byte$00, $80, $37, $86, $00, $80, $3c, $86
$2059.byte$00, $7f
$205Bpat_27.byte$af, $83, $00, $80, $3c, $86, $00, $80; x-ref: $1A31
$2063.byte$37, $86, $00, $80, $3c, $86, $00, $80
$206B.byte$37, $86, $00, $80, $3c, $86, $00, $80
$2073.byte$35, $86, $00, $80, $3e, $86, $00, $80
$207B.byte$3b, $82, $00, $7f
$207Fpat_28.byte$af, $80, $39, $86, $00, $80, $3b, $86; x-ref: $1A32
$2087.byte$00, $80, $39, $86, $00, $80, $3b, $86
$208F.byte$00, $80, $40, $86, $00, $80, $3c, $86
$2097.byte$00, $80, $38, $86, $00, $80, $3c, $86
$209F.byte$00, $7f
$20A1pat_29.byte$af, $83, $00, $80, $3c, $86, $00, $80; x-ref: $1A33
$20A9.byte$37, $86, $00, $80, $3c, $86, $00, $80
$20B1.byte$37, $86, $00, $80, $3e, $86, $00, $80
$20B9.byte$3b, $86, $00, $80, $3b, $86, $00, $80
$20C1.byte$3b, $82, $00, $7f
$20C5pat_30.byte$a4, $80, $30, $82, $00, $b0, $80, $30; x-ref: $1A34
$20CD.byte$00, $30, $00, $a5, $30, $82, $00, $b0
$20D5.byte$80, $30, $00, $30, $00, $7f
$20DBpat_31.byte$b1, $80, $30, $c0, $00, $b0, $09, $c0; x-ref: $1A35
$20E3.byte$7e, $a2, $82, $15, $c0, $80, $7e, $b2
$20EB.byte$0c, $81, $00, $c0, $80, $00, $a2, $82
$20F3.byte$15, $c0, $80, $7e, $7f
$20F8pat_32.byte$a3, $85, $2d, $c3, $8f, $7e, $80, $7e; x-ref: $1A36
$2100.byte$c0, $7e, $32, $c1, $7e, $90, $34, $83
$2108.byte$7e, $c0, $80, $7e, $85, $32, $c3, $89
$2110.byte$7e, $ad, $82, $40, $c0, $80, $7e, $82
$2118.byte$3e, $c0, $80, $7e, $3a, $90, $3b, $90
$2120.byte$3c, $c0, $80, $7e, $83, $3b, $7f
$2127pat_33.byte$81, $7e, $c4, $8c, $7e, $c0, $80, $7e; x-ref: $1A37
$212F.byte$86, $3c, $c0, $80, $7e, $86, $3e, $c0
$2137.byte$80, $7e, $3f, $90, $40, $90, $41, $c0
$213F.byte$80, $7e, $82, $40, $c0, $80, $7e, $82
$2147.byte$3e, $c0, $80, $7e, $82, $40, $c4, $83
$214F.byte$7e, $c0, $80, $7e, $af, $3c, $00, $b3
$2157.byte$30, $00, $af, $3b, $00, $b3, $2f, $00
$215F.byte$af, $3c, $00, $b3, $3b, $00, $7f
$2166pat_34.byte$8f, $00, $00, $00, $00, $7f; x-ref: $1A38
$216Cpat_35.byte$86, $7e, $c0, $80, $7e, $82, $40, $c0; x-ref: $1A39
$2174.byte$80, $7e, $82, $3e, $c0, $80, $7e, $86
$217C.byte$40, $c0, $80, $7e, $82, $40, $c0, $80
$2184.byte$7e, $82, $3e, $c0, $80, $7e, $3f, $90
$218C.byte$40, $90, $41, $c0, $80, $7e, $3e, $c0
$2194.byte$7e, $3e, $90, $3f, $90, $40, $82, $7e
$219C.byte$c4, $86, $7e, $c0, $80, $7e, $82, $45
$21A4.byte$c0, $80, $7e, $82, $47, $c0, $80, $7e
$21AC.byte$82, $48, $c0, $80, $7e, $7f, $00, $00
$21B4.byte$00, $00, $00, $00
.encode
.enc"screen"
$21B8txt_credits_exit.text"CODE:DIDI LOGO:AGD 4X4:DMD MUSIC:DEEK"; x-ref: $2EE6
.endencode
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; Demo exit/cleanup stub — must execute from $0340 (tape buffer), NOT from
; its link address here. Its self-modifying INC targets ($0344, $0347) are
; only correct when the code runs from $0340.
;
; Called by the shutdown sequence at $2EF3, which:
; 1. ldx #$34 / stx $01 — disable BASIC+KERNAL ROMs, expose all RAM
; 2. Copies 53 bytes of this stub to $0340 (tape buffer, always safe RAM)
; 3. jmp $0340 — execute the copy from its correct location
;
; From $0340 the SMC is correct:
; lda $3200,x at $0342 → hi-byte operand at $0344 (inc a0344 = next source page)
; sta $0801,x at $0345 → hi-byte operand at $0347 (inc a0347 = next dest page)
;
; Inner loop copies 256 bytes/iteration; inc a0344/a0347 step both pointers
; to the next page. Loop terminates when the source hi byte wraps $FF→$00,
; having bulk-copied the demo's data from $3200+ back into $0801+ (BASIC
; program area), restoring the machine's memory state after the demo.
;
; Finally: lda #$37/sta $01 restores standard banking (BASIC+KERNAL+I/O),
; cli re-enables interrupts, jmp RESET_VECTOR cold-starts back to BASIC.
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
$21E0a2 00cleanup_reloc_0340ldx#$00; inner loop: copy 256 bytes from current source page to dest page ; x-ref: $2EF3
$21E2bd 00 32b_21E2ldaexit_backup_basic_area,x; SMC target: hi byte of source address (initially $32 for $3200) ; x-ref: $21E9, $21F1
$21E59d 01 08staBASIC_START,x; SMC target: hi byte of dest address (initially $08 for $0801)
$21E8e8inx; 256-byte block done; advance source page
$21E9d0 f7bneb_21E2
$21EBee 47 03incexit_stub_dest_hi; advance dest page
$21EEee 44 03incexit_stub_source_hi
$21F1d0 efbneb_21E2; copy next page; loop until source hi wraps $FF→$00
$21F3a9 37lda#$37; restore standard C64 banking: BASIC+KERNAL+I/O visible
$21F585 01staCPU_PORT
$21F758cli; re-enable interrupts
$21F84c e2 fcjmpKERNAL_RESET_VECTOR; cold-start back to BASIC
$21FB.byte$00, $00, $00, $00, $00
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Advances a sine wave phase index and splits the corresponding table value
; into a fine scroll value (for VIC-II $D016) and a coarse character offset
; (for screen tile positioning). Used by all three tube bands.
;
; Inputs: X = current sine phase index (0-159, maintained via self-mod by caller)
; Outputs: A = $D016 value (fine scroll 0-7 inverted | multicolor bit),
; Y = coarse character offset (0-31),
; X = updated phase index
; Side Effects: None (pure computation)
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
$2200e8sine_scroller_updateinx; Advance sine phase ; x-ref: $0E0A, $0E2A, $0E4A
$2201e0 a0cpx#$a0; Table has 160 entries
$2203d0 02bneb_2207
$2205a2 00ldx#$00; Wrap to 0 at end of table
$2207bd 40 0fb_2207ldasine_table,x; Read 8-bit sine value (0-255) ; x-ref: $2203
$220A48pha; Save full value for fine scroll extraction
$220B29 f8and#$f8; Keep bits 7-3 (coarse part)
$220D4alsra
$220E4alsra
$220F4alsra
$2210a8tay; Y = coarse character offset
$221168pla; Restore full sine value
$221229 07and#$07; Keep bits 2-0 (fine scroll 0-7)
$221449 07eor#$07; Invert: VIC scrolls opposite direction
$221609 10ora#$10; Set bit 4 = multicolor mode for $D016
$221860rts
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; First raster IRQ handler to fire each frame. Fires at raster line $FB
; (below visible screen, in the bottom border), triggered by irq_hanlder_f8.
;
; This handler has two roles beyond the standard raster split mechanics:
;
; 1. DISPLAY SETUP: Restores $D018 to the tube layout (charset $0800, screen
; $0400), applies the orange/brown tube palette, enables multicolor+38-col
; via $D016 (self-modified for scroll), and writes $D011=$17 to set the
; raster compare register upper bit and enable the display. This is the
; setup that takes effect at the very top of the next frame.
;
; 2. SID TICK + LOGO ANIMATION SYNC: Calls sid_play to advance the music
; driver for this frame, then reads the waveform bytes of all three SID
; voices (voice_waveform/$170A, a170B, a170C). If any voice has bit 7 set
; ($80 = rest/gate-off in the music driver), the logo color animation index
; (a226F) is reset to $02, pausing the color shimmer at its starting step.
; This couples the visual animation to musical phrasing.
;
; Finally, arms raster_irq_upper_tube at raster $40 to start the visible
; portion of the raster chain on the next frame.
;
; Inputs: voice_waveform ($170A), a170B, a170C — SID voice waveform states
; Outputs: None
; Side Effects: $D018 set to tube layout; $D016 set to multicolor+38-col;
; $D011 written to enable display + set raster bit 8;
; sid_play called (advances music driver one frame);
; a226F reset to $02 if any voice is in rest state;
; next IRQ armed at raster $40 -> raster_irq_upper_tube
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
raster_irq_frame_start
$2219a9 13lda#%00010011; restore tube charset ($0800) and screen ($0400) for top of next frame ; x-ref: $23C7, $23C9
$221B8d 18 d0sta$d018; VIC Memory Control Register
$221Ea9 0alda#VicIIColors.LIGHT_RED; orange/brown tube palette for the top of the next frame
$2220a2 09ldx#VicIIColors.BROWN
$2222a0 08ldy#VicIIColors.ORANGE
$22248d 21 d0sta$d021; Background Color 0
$22278e 22 d0stx$d022; Background Color 1, Multi-Color Register 0
$222A8c 23 d0sty$d023; Background Color 2, Multi-Color Register 1
patch_irq_fb_scroll =*+$01 ; x-ref: $0E10
$222Da9 d0lda#%11010000; self-modified operand: multicolor+38-col; bits 0-2 may carry scroll offset
$222F8d 16 d0sta$d016; VIC Control Register 2
$2232a9 17lda#$17; enable display + clear raster bit 8 (lines 0-255 visible)
$22348d 11 d0sta$d011; VIC Control Register 1
$223720 03 10jsrsid_play; advance SID music driver one frame tick
; SID-SYNC TRICK: Immediately after sid_play advances the music driver, we
; peer into the driver's internal waveform state for all 3 voices. The driver
; stores the raw SID voice control byte (the value it will write to $D404,
; $D40B, $D412) in voice_waveform_1/voice_waveform_2/voice_waveform_3.
; In this driver, $80 (noise waveform + gate off) is the sentinel for
; "note release / rest".
;
; If ANY voice has just released its note, the logo color animation index
; (a226F, the self-modified operand of LDX #$xx in irq_handler_top_tube)
; is snapped back to step $02. This resets the shimmer cycle so every new
; note attack launches a fresh color flash on the Laxity logo.
;
; The animation table is designed to fade: bright (step 5) → dark → black
; (step 0). By resetting on note boundaries, the logo visually pulses in
; perfect sync with the music phrasing. This is deliberate — not a coincidence.
$223Aad 0a 17ldavoice_waveform_1; driver-internal SID ctrl byte for voice 0; written to $D404 by sid_play
$223Dc9 80cmp#$80; $80 = noise waveform + gate-off; this driver uses it as the note-release sentinel
$223Ff0 0ebeqb_224F
$2241ad 0b 17ldavoice_waveform_2; driver-internal SID ctrl byte for voice 1; written to $D40B by sid_play
$2244c9 80cmp#$80; same sentinel check
$2246f0 07beqb_224F
$2248ad 0c 17ldavoice_waveform_3; driver-internal SID ctrl byte for voice 2; written to $D412 by sid_play
$224Bc9 80cmp#$80; same sentinel check; if none triggered, animation continues its countdown
$224Dd0 05bneb_2254
$224Fa9 02b_224Flda#$02; at least one voice is releasing: snap shimmer back to step $02 (mid-fade, not full-bright) ; x-ref: $223F, $2246
$22518d 6f 22stalogo_shimmer_index; self-modifies the LDX #$xx operand at $226E — resets the per-frame countdown for next frame
$2254a9 40b_2254lda#$40; x-ref: $224D
$2256a2 5dldx#<raster_irq_top_tube
$2258a0 22ldy#>raster_irq_top_tube
$225A4c cb 23jmpj_23CB
; Raster IRQ chain — drives all per-scanline VIC-II splits for the full-screen
; effect. The chain fires ~11 times per frame, one handler per screen region.
; Each handler sets the appropriate background/multicolor palette and switches
; chart/screen bank as needed, then calls set_next_irq_state (A=next raster
; line, X/Y=lo/hi of next handler), acknowledges the VIC IRQ via LSR $D019,
; and exits through the KERNAL IRQ return at $EA7E.
;
; Region map (top to bottom):
; $40 raster_irq_top_tube — upper decorative tube bar
; $46 rater_irq_upper_logo — upper Laxity logo (blue palette)
; $6E rater_irq_lower_logo — lower Laxity logo (red palette)
; $96 raster_irq_mid_tube — middle tube bar
; $A0 raster_irq_mid_tube_ext — transition (same tube palette)
; $A6 raster_irq_tube_scroller_gap — delay + black bg, switches to hi-res
; $B6 raster_irq_upper_scroller — upper scroller (blue, charset at $2800)
; $C6 raster_irq_lower_scroller — lower scroller (red)
; $D6 raster_irq_scroller_tube_gap — delay + hi-res, charset back to $0800
; $E6 raster_irq_bottom_tube — bottom tube bar; bumps frame-sync counter
; $F0 raster_irq_frame_end — wraps back to $40 (top of frame)
;
; Inputs: a226F (color animation index), a2272 (self-mod enable byte)
; Outputs: None
; Side Effects: $D016/$D018/$D021–$D023 updated per split; $D012+$0314/$0315
; reprogrammed for next handler; a2EA5 incremented each frame
$225Dearaster_irq_top_tubenop; x-ref: $2256, $2258
$225Eeanop
$225Fa9 09lda#VicIIColors.BROWN
$2261a2 08ldx#VicIIColors.ORANGE
$2263a0 0cldy#VicIIColors.GREY
$22658d 21 d0sta$d021; Background Color 0
$22688e 22 d0stx$d022; Background Color 1, Multi-Color Register 0
$226B8c 23 d0sty$d023; Background Color 2, Multi-Color Register 1
logo_shimmer_index =*+$01 ; x-ref: $2251, $2276
; Logo color animation: index counts 5→4→3→2→1→0 at 50Hz, cycling the shimmer
; tables. raster_irq_frame_start resets it to $02 on any SID note-off, so
; every new note attack restarts a fresh shimmer flash on the Laxity logo.
; The operand of this LDX is self-modified by the STX at $2276 each frame
; and force-reset by the STA at $2251 on note-off events.
$226Ea2 05ldx#$05; color animation index (0..5); counts down each active frame
$2270f0 2bbeqb_229D; skips color table update until self-modified to JMP
logo_shimmer_enable_gate
$22724c 79 22jmpj_2279; self-modified: file contains $4C (JMP, skips DEX -> frozen). Init writes $2C (BIT, falls through -> active). ; x-ref: $2E86
$2275cadex; advance shimmer: step 5→4→3→2→1→0, one per frame (~50Hz)
$22768e 6f 22stxlogo_shimmer_index; persist: self-modifies the LDX #$xx operand at $226E for the next frame
$2279bd d4 23j_2279ldatbl_background_color_46_0,x; upper logo bg0 color for current animation step ; x-ref: $2272 ;
$227C8d a9 22stalogo_bg0_color_upper
$227Fbd da 23ldatbl_background_color_46_1,x; upper logo bg1 color for current animation step; ;
$22828d ab 22stalogo_bg1_color_upper
$2285bd e0 23ldatbl_background_color_46_2,x; upper logo bg2 color for current animation step; ;
$22888d ad 22stalogo_bg2_color_upper
$228Bbd e6 23ldatbl_background_color_6e_0,x; lower logo bg0 color for current animation step; ;
$228E8d c8 22stalogo_bg0_color_lower
$2291bd ec 23ldatbl_background_color_6e_1,x; lower logo bg1 color for current animation step; ;
$22948d ca 22stalogo_bg1_color_lower
$2297bd f2 23ldatbl_background_color_6e_2,x; lower logo bg2 color for current animation step; ;
$229A8d cc 22stalogo_bg2_color_lower
$229Da9 46b_229Dlda#$46; x-ref: $2270
$229Fa2 a6ldx#<raster_irq_upper_logo
$22A1a0 22ldy#>raster_irq_upper_logo
$22A34c cb 23jmpj_23CB
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Raster IRQ handler for the upper half of the Laxity logo (blue/cyan band).
; Fires at raster line $46. Sets VIC-II multicolor background registers and
; enables multicolor + 38-column mode, then chains to raster_irq_lower_logo.
;
; The three background color immediates (LDA/LDX/LDY #imm) are NOT fixed —
; their operand bytes at a22A9/a22AB/a22AD are overwritten every frame by
; raster_irq_upper_tube using values from tbl_background_color_46_0/1/2,
; cycling through 6 palette steps to produce the color-shimmer animation
; visible on the logo.
;
; Inputs: a22A9 (bg0 immediate), a22AB (bg1 immediate), a22AD (bg2 immediate)
; — all self-modified by raster_irq_upper_tube each frame
; Outputs: None
; Side Effects: $D021-$D023 updated to current animation color step;
; $D016 set to multicolor + 38-col mode;
; next IRQ armed at raster $6E → raster_irq_lower_logo
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
raster_irq_upper_logo
$22A6eanop; NOP padding for stable raster timing (consistent cycle offset after IRQ) ; x-ref: $229F, $22A1
$22A7eanop
logo_bg0_color_upper =*+$01 ; x-ref: $227C
$22A8a9 03lda#VicIIColors.CYAN; self-modified operand (a22A9): bg0 color written by raster_irq_upper_tube from tbl_background_color_46_0
logo_bg1_color_upper =*+$01 ; x-ref: $2282
$22AAa2 06ldx#VicIIColors.BLUE; self-modified operand (a22AB): bg1 color written by raster_irq_upper_tube from tbl_background_color_46_1
logo_bg2_color_upper =*+$01 ; x-ref: $2288
$22ACa0 0eldy#VicIIColors.LIGHT_BLUE; self-modified operand (a22AD): bg2 color written by raster_irq_upper_tube from tbl_background_color_46_2
$22AE8d 21 d0sta$d021; Background Color 0
$22B18e 22 d0stx$d022; Background Color 1, Multi-Color Register 0
$22B48c 23 d0sty$d023; Background Color 2, Multi-Color Register 1
$22B7a9 d0lda#%11010000; multicolor mode on, 38-column (hides left/right border artifacts during color switch)
$22B98d 16 d0sta$d016; VIC Control Register 2
$22BCa9 6elda#$6e
$22BEa2 c5ldx#<raster_irq_lower_logo
$22C0a0 22ldy#>raster_irq_lower_logo
$22C24c cb 23jmpj_23CB
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Raster IRQ handler for the lower half of the Laxity logo (red/warm band).
; Fires at raster line $6E. Sets VIC-II multicolor background registers only
; (no $D016 write — inherits multicolor + 38-col from raster_irq_upper_logo),
; then chains to irq_handler_96 (middle tube).
;
; The three background color immediates (LDA/LDX/LDY #imm) are NOT fixed —
; their operand bytes at a22C8/a22CA/a22CC are overwritten every frame by
; raster_irq_upper_tube using values from tbl_background_color_6e_0/1/2,
; cycling through 6 warm palette steps (grays, reds, light reds) in sync
; with the cool palette cycling on the upper logo, producing the two-tone
; color-shimmer animation across the full Laxity logo.
;
; Inputs: a22C8 (bg0 immediate), a22CA (bg1 immediate), a22CC (bg2 immediate)
; — all self-modified by raster_irq_upper_tube each frame
; Outputs: None
; Side Effects: $D021-$D023 updated to current animation color step;
; next IRQ armed at raster $96 → irq_handler_96 (middle tube)
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
raster_irq_lower_logo
$22C5eanop; NOP padding for stable raster timing (consistent cycle offset after IRQ) ; x-ref: $22BE, $22C0
$22C6eanop
logo_bg0_color_lower =*+$01 ; x-ref: $228E
$22C7a9 0flda#VicIIColors.LIGHT_GREY; self-modified operand (a22C8): bg0 color written by raster_irq_upper_tube from tbl_background_color_6e_0
logo_bg1_color_lower =*+$01 ; x-ref: $2294
$22C9a2 02ldx#VicIIColors.RED; self-modified operand (a22CA): bg1 color written by raster_irq_upper_tube from tbl_background_color_6e_1
logo_bg2_color_lower =*+$01 ; x-ref: $229A
$22CBa0 0aldy#VicIIColors.LIGHT_RED; self-modified operand (a22CC): bg2 color written by raster_irq_upper_tube from tbl_background_color_6e_2
$22CD8d 21 d0sta$d021; no $D016 write here — inherits multicolor+38-col mode from raster_irq_upper_logo; Background Color 0
$22D08e 22 d0stx$d022; Background Color 1, Multi-Color Register 0
$22D38c 23 d0sty$d023; Background Color 2, Multi-Color Register 1
$22D6a9 96lda#$96
$22D8a2 dfldx#<raster_irq_mid_tube
$22DAa0 22ldy#>raster_irq_mid_tube
$22DC4c cb 23jmpj_23CB
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Raster IRQ handler for the middle decorative tube bar.
; Fires at raster line $96. Key transition point: switches $D018 back to the
; tube charset ($0800) and screen ($0400), which were set to the logo charset
; ($2800) by raster_irq_upper_logo for the Laxity logo region above.
;
; The $D016 operand (a22F4) is self-modified every frame by update_scroller_and_tubes
; (via sine_scroller_update, phase pointer at a0E29) to update the pixel-level
; horizontal scroll offset (bits 0-2 of $D016), producing the animated side-scrolling
; movement of the tube tiles. Palette is fixed (orange/brown), matching the upper
; and lower tube handlers.
;
; Inputs: a22F4 ($D016 scroll value) — self-modified by update_scroller_and_tubes
; Outputs: None
; Side Effects: $D018 switched to tube layout (charset=$0800, screen=$0400);
; $D021-$D023 set to orange/brown tube palette;
; $D016 written with current horizontal scroll offset;
; next IRQ armed at raster $A0 → irq_handler_a0
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
$22DFa9 13raster_irq_mid_tubelda#%00010011; restore tube charset/screen layout (was $2800 logo charset during logo region) ; x-ref: $22D8, $22DA
$22E18d 18 d0sta$d018; VIC Memory Control Register
$22E4a9 0alda#VicIIColors.LIGHT_RED; fixed orange/brown tube palette (not animated, unlike logo region)
$22E6a2 09ldx#VicIIColors.BROWN
$22E8a0 08ldy#VicIIColors.ORANGE
$22EA8d 21 d0sta$d021; Background Color 0
$22ED8e 22 d0stx$d022; Background Color 1, Multi-Color Register 0
$22F08c 23 d0sty$d023; Background Color 2, Multi-Color Register 1
patch_irq_96_scroll =*+$01 ; x-ref: $0E30
$22F3a9 d0lda#%11010000; self-modified operand (a22F4): scroll offset written by update_scroller_and_tubes via sine_scroller_update (phase at a0E29)
$22F58d 16 d0sta$d016; VIC Control Register 2
$22F8a9 a0lda#$a0
$22FAa2 01ldx#<raster_irq_mid_tube_ext
$22FCa0 23ldy#>raster_irq_mid_tube_ext
$22FE4c cb 23jmpj_23CB
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Lower extension of the middle tube raster region.
; Fires at raster line $A0, immediately after raster_irq_mid_tube ($96).
; Reapplies the identical orange/brown palette to maintain stable color across
; the full height of the tube bar. No $D016 or $D018 writes — both are
; inherited unchanged from raster_irq_mid_tube (correct charset and scroll
; offset already in effect).
;
; The split into two handlers exists because raster_irq_mid_tube only fires
; once at the top of the tube ($96); this handler covers the lower rows
; ($A0-$A6) with the same palette before handing off to the gap transition.
;
; Inputs: None
; Outputs: None
; Side Effects: $D021-$D023 reapplied with orange/brown tube palette;
; next IRQ armed at raster $A6 -> raster_irq_tube_scroller_gap
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
raster_irq_mid_tube_ext
$2301eanop; NOP padding for stable raster timing (consistent cycle offset after IRQ) ; x-ref: $22FA, $22FC
$2302eanop
$2303a9 09lda#VicIIColors.BROWN; same orange/brown palette as raster_irq_mid_tube — no $D016/$D018 change needed
$2305a2 08ldx#VicIIColors.ORANGE
$2307a0 0cldy#VicIIColors.GREY
$23098d 21 d0sta$d021; Background Color 0
$230C8e 22 d0stx$d022; Background Color 1, Multi-Color Register 0
$230F8c 23 d0sty$d023; Background Color 2, Multi-Color Register 1
$2312a9 a6lda#$a6
$2314a2 1bldx#<raster_irq_tube_scroller_gap
$2316a0 23ldy#>raster_irq_tube_scroller_gap
$23184c cb 23jmpj_23CB
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Transition buffer between the middle tube and the upper scroller regions.
; Fires at raster line $A6. Inserts a thin black separator row between the
; tube and scroller by zeroing $D021, and switches $D016 to hi-res 38-col
; (clearing the multicolor bit set by raster_irq_mid_tube), before handing
; off to raster_irq_upper_scroller at raster line $B6.
;
; The busy-loop delay (DEX/BNE, 2 iterations) provides cycle-accurate
; timing so the VIC register writes land on the correct scanline.
;
; Inputs: None
; Outputs: None
; Side Effects: $D021 set to black (separator line between tube and scroller);
; $D016 switched to hi-res 38-col (clears multicolor bit);
; next IRQ armed at raster $B6 -> raster_irq_upper_scroller
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
raster_irq_tube_scroller_gap
$231Ba2 02ldx#$02; x-ref: $2314, $2316
$231Dcab_231Ddex; cycle-accurate delay: ensures VIC writes land on the correct scanline ; x-ref: $231E
$231Ed0 fdbneb_231D
$23208e 21 d0stx$d021; black bg0 = thin separator line between tube and scroller; Background Color 0
$2323a9 c0lda#%11000000; clear multicolor bit, stay in 38-col mode for the gap row
$23258d 16 d0sta$d016; VIC Control Register 2
$2328a9 b6lda#$b6
$232Aa2 31ldx#<raster_irq_upper_scroller
$232Ca0 23ldy#>raster_irq_upper_scroller
$232E4c cb 23jmpj_23CB
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Raster IRQ handler for the upper text scroller (blue "OLDSCHOOL" band).
; Fires at raster line $B6. Applies pixel-level horizontal smooth scroll via
; $D016 and switches to the scroller charset at $2800, then chains to
; raster_irq_lower_scroller at raster $C6.
;
; Smooth scroll mechanism:
; smooth_scroll_phase ($2334) is a dual-purpose byte: it is both the
; self-modifying immediate operand of LDA #imm at $2333 AND the canonical
; scroll phase variable. Each frame, update_scroller_and_tubes:
; - Reads smooth_scroll_phase, subtracts 3 (scrolls 3px left per frame)
; - Writes it back (patching the LDA operand for this IRQ)
; - On underflow: wraps to 0-7, shifts screen row left by 1 char,
; fetches the next char from scroller_txt and renders it rightmost
; When this IRQ fires, LDA smooth_scroll_phase loads the pre-patched
; pixel offset; ORA #$10 forces multicolor on; result -> $D016 bits 0-2.
;
; Inputs: smooth_scroll_phase ($2334) — self-modified by update_scroller_and_tubes
; Outputs: None
; Side Effects: $D016 set with pixel scroll offset + multicolor + 38-col;
; $D018 switched to scroller charset ($2800), screen ($0400);
; $D021-$D023 set to blue/cyan palette;
; next IRQ armed at raster $C6 -> raster_irq_lower_scroller
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
raster_irq_upper_scroller
$2331eanop; NOP padding for stable raster timing (consistent cycle offset after IRQ) ; x-ref: $232A, $232C
$2332eanop
smooth_scroll_phase =*+$01 ; x-ref: $0E7B, $0E81, $0E88
$2333a9 00lda#$00; dual-purpose: self-mod operand AND scroll phase storage; patched by update_scroller_and_tubes (-3px/frame)
$233509 10ora#$10; force multicolor bit on; bits 0-2 carry pixel scroll offset from smooth_scroll_phase
$23378d 16 d0sta$d016; VIC Control Register 2
$233Aa9 1blda#%00011011; switch to scroller/logo charset at $2800; reused for both logo and scroller text
$233C8d 18 d0sta$d018; VIC Memory Control Register
$233Fa9 03lda#VicIIColors.CYAN; fixed blue/cyan palette matching upper Laxity logo for visual continuity
$2341a2 06ldx#VicIIColors.BLUE
$2343a0 0eldy#VicIIColors.LIGHT_BLUE
$23458d 21 d0sta$d021; Background Color 0
$23488e 22 d0stx$d022; Background Color 1, Multi-Color Register 0
$234B8c 23 d0sty$d023; Background Color 2, Multi-Color Register 1
$234Ea9 c6lda#$c6
$2350a2 57ldx#<raster_irq_lower_scroller
$2352a0 23ldy#>raster_irq_lower_scroller
$23544c cb 23jmpj_23CB
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Raster IRQ handler for the lower half of the scroller band (red/warm palette).
; Fires at raster line $C6. Splits the scroller region into two color bands,
; miroring the two-tone palette split of the Laxity logo above:
; Upper scroller ($B6): blue/cyan (matching the upper logo)
; Lower scroller ($C6): yellow/red (matching the lower logo)
;
; This handler writes NO $D016 or $D018 — both are inherited
; unchanged from raster_irq_upper_scroller. This ensures the two scroller
; bands share the exact same charset ($2800), smooth scroll phase, and
; pixel scroll offset, so the text rows move in perfect lockstep.
;
; The 3-iteration busy-loop provides cycle-accurate delay for the raster
; split to land cleanly on the correct scanline between the two color bands.
;
; Inputs: Inherits $D016 (scroll+multicolor) and $D018 (charset $2800)
; from raster_irq_upper_scroller — NOT independently set
; Outputs: None
; Side Effects: $D021-$D023 updated to warm yellow/red palette;
; next IRQ armed at raster $D6 -> raster_irq_scroller_tube_gap
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
raster_irq_lower_scroller
$2357a2 03ldx#$03; 3-iteration busy-loop for cycle-accurate raster split timing ; x-ref: $2350, $2352
$2359cab_2359dex; busy-loop delay: 3 iterations to align scroller raster split ; x-ref: $235A
$235Ad0 fdbneb_2359
$235Ca9 07lda#VicIIColors.YELLOW; warm yellow/red palette — mirrors lower Laxity logo colors for visual symmetry
$235Ea2 02ldx#VicIIColors.RED
$2360a0 0aldy#VicIIColors.LIGHT_RED
$23628d 21 d0sta$d021; no $D016/$D018 write — inherits charset ($2800) and scroll phase from raster_irq_upper_scroller; text rows move in lockstep; Background Color 0
$23658e 22 d0stx$d022; Background Color 1, Multi-Color Register 0
$23688c 23 d0sty$d023; Background Color 2, Multi-Color Register 1
$236Ba9 d6lda#$d6
$236Da2 74ldx#<raster_irq_scroller_tube_gap
$236Fa0 23ldy#>raster_irq_scroller_tube_gap
$23714c cb 23jmpj_23CB
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Scroller-to-tube transition gap handler. Fires at raster line $D6.
; Mirror of raster_irq_tube_scroller_gap ($A6) but in the reverse direction:
; reverts VIC display mode and charset from scroller layout back to the
; decorative tube configuration, before handing off to irq_handler_e6 (bottom tube).
;
; Reverts $D016 to hi-res 38-col (clears multicolor set by scrollers above),
; and switches $D018 back to tube charset at $0800 / screen $0400 (away from
; scroller charset at $2800). Sets $D021 black for a clean one-line gap.
;
; The delay is a 2-iteration busy-loop plus an extra NOP (vs. just the loop
; in raster_irq_tube_scroller_gap), adding 2 extra cycles to account for the
; different scanline position and ensure VIC writes land correctly.
;
; Inputs: None
; Outputs: None
; Side Effects: $D016 reverted to hi-res 38-col (multicolor cleared);
; $D018 restored to tube charset ($0800) / screen ($0400);
; $D021 set black (thin separator line between scroller and tube);
; next IRQ armed at raster $E6 -> irq_handler_e6 (bottom tube)
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
raster_irq_scroller_tube_gap
$2374a2 02ldx#$02; 2-iteration busy-loop for cycle-accurate raster split timing ; x-ref: $236D, $236F
$2376cab_2376dex; x-ref: $2377
$2377d0 fdbneb_2376
$2379eanop; extra 2-cycle NOP pad (vs. raster_irq_tube_scroller_gap) for scanline alignment at $D6
$237Aa9 c0lda#%11000000; clear multicolor bit, revert to hi-res 38-col for bottom tube region
$237C8d 16 d0sta$d016; VIC Control Register 2
$237Fa9 13lda#%00010011; restore tube charset at $0800 and screen at $0400 (away from scroller charset $2800)
$23818d 18 d0sta$d018; VIC Memory Control Register
$2384a9 00lda#VicIIColors.BLACK; black bg0 = thin separator line between scroller and bottom tube
$23868d 21 d0sta$d021; Background Color 0
$2389a9 e6lda#$e6
$238Ba2 92ldx#<raster_irq_bottom_tube
$238Da0 23ldy#>raster_irq_bottom_tube
$238F4c cb 23jmpj_23CB
patch_irq_e6_scroll =*+$01 ; x-ref: $0E50
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Raster IRQ handler for the bottom decorative tube bar.
; Fires at raster line $E6. Structurally mirrors raster_irq_mid_tube but with
; an independent sine scroll phase (a0E49, offset $30 vs. mid tube's $18),
; giving the two tube bars a staggered wave motion rather than moving in sync.
;
; The $D016 operand (a2393) is self-modified every frame by update_scroller_and_tubes
; (via sine_scroller_update, phase pointer at a0E49) for the horizontal scroll.
; Two leading NOPs fine-tune cycle timing at scanline $E6.
;
; Also serves as the frame-sync tick source: INC a2EA5 is the only place this
; counter is written, and it gates all per-frame updates in wait_frame_or_exit
; (tube fill, scroller advance, sine phase increments).
;
; Inputs: a2393 ($D016 scroll value) — self-modified by update_scroller_and_tubes
; via sine_scroller_update (phase at a0E49, sine offset $30)
; Outputs: None
; Side Effects: $D016 set with current horizontal scroll + multicolor + 38-col;
; $D021-$D023 set to warm orange/red tube palette;
; a2EA5 incremented (main loop frame-sync tick);
; next IRQ armed at raster $F0 -> raster_irq_frame_end
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
raster_irq_bottom_tube
$2392a9 d0lda#%11010000; self-modified operand (a2393): scroll offset written by update_scroller_and_tubes via sine_scroller_update (phase at a0E49) ; x-ref: $238B, $238D
$23948d 16 d0sta$d016; VIC Control Register 2
$2397eanop; 2-cycle NOP padding to fine-tune palette write timing at scanline $E6
$2398eanop
$2399a9 0alda#VicIIColors.LIGHT_RED; warm orange/red tube palette (independent phase gives staggered motion vs. mid tube)
$239Ba2 09ldx#VicIIColors.BROWN
$239Da0 08ldy#VicIIColors.ORANGE
$239F8d 21 d0sta$d021; Background Color 0
$23A28e 22 d0stx$d022; Background Color 1, Multi-Color Register 0
$23A58c 23 d0sty$d023; Background Color 2, Multi-Color Register 1
$23A8ee a5 2eincframe_sync_tick_ctr; sole writer of frame-sync counter; gates all per-frame updates in wait_frame_or_exit
$23ABa9 f0lda#$f0; bump frame-sync counter; polled by wait_frame_or_exit in main loop
$23ADa2 b4ldx#<raster_irq_frame_end
$23AFa0 23ldy#>raster_irq_frame_end
$23B14c cb 23jmpj_23CB
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; End-of-frame raster handler. Fires at raster line $F0 (near bottom of screen).
; Applies the same orange/brown palette as raster_irq_upper_tube to maintain
; visual continuity as the raster beam wraps back to the top.
;
; Does NOT end with JMP j23CB. Instead it falls through into irq_hanlder_f8
; at $23C5, a shared epilogue also called by the init code at $2E6C. This tail-
; fall avoids an extra JMP and arms irq_handler_fb ($FB) as the final link,
; which re-arms raster_irq_upper_tube to restart the full 11-handler chain
; on the next frame.
;
; Inputs: None
; Outputs: None
; Side Effects: $D021-$D023 set to upper-tube orange/brown palette;
; falls into irq_hanlder_f8 which arms raster $FB -> irq_handler_fb
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
$23B4earaster_irq_frame_endnop; NOP padding for stable raster timing (consistent cycle offset after IRQ) ; x-ref: $23AD, $23AF
$23B5eanop
$23B6a9 09lda#VicIIColors.BROWN; same palette as raster_irq_upper_tube for visual continuity at frame wrap
$23B8a2 08ldx#VicIIColors.ORANGE
$23BAa0 0cldy#VicIIColors.GREY
$23BC8d 21 d0sta$d021; Background Color 0
$23BF8e 22 d0stx$d022; Background Color 1, Multi-Color Register 0
$23C28c 23 d0sty$d023; Background Color 2, Multi-Color Register 1
$23C5a9 fbirq_hanlder_f8lda#$fb; shared epilogue entry point (also called directly by init at $2E6C); no JMP above — fall-through from raster_irq_frame_end ; x-ref: $2E6C, $2E6E
$23C7a2 19ldx#<raster_irq_frame_start
$23C9a0 22ldy#>raster_irq_frame_start
$23CB20 9a 2ej_23CBjsrset_next_irq_state; x-ref: $225A, $22A3, $22C2, $22DC, $22FE, $2318, $232E, $2354, ...
$23CE4e 19 d0lsr$d019; acknowledge VIC IRQ and exit via KERNAL return ($EA7E: pop A/X/Y, RTI); VIC Interrupt Request Register (IRR)
$23D14c 7e eajmpe_EA7E; clear intr flags, pop y, pop x, pop a, rti
tbl_background_color_46_0
$23D4.byteVicIIColors.CYAN; ; ; x-ref: $2279
$23D5.byteVicIIColors.WHITE; ;
$23D6.byteVicIIColors.CYAN; ;
$23D7.byteVicIIColors.LIGHT_BLUE; ;
$23D8.byteVicIIColors.BLUE; ;
$23D9.byteVicIIColors.BLACK; ;
tbl_background_color_46_1
$23DA.byteVicIIColors.BLUE; ; ; x-ref: $227F
$23DB.byteVicIIColors.LIGHT_BLUE; ;
$23DC.byteVicIIColors.BLUE; ;
$23DD.byteVicIIColors.BLACK; ;
$23DE.byteVicIIColors.BLACK; ;
$23DF.byteVicIIColors.BLACK; ;
tbl_background_color_46_2
$23E0.byteVicIIColors.LIGHT_BLUE; ; ; x-ref: $2285
$23E1.byteVicIIColors.CYAN; ;
$23E2.byteVicIIColors.LIGHT_BLUE; ;
$23E3.byteVicIIColors.BLUE; ;
$23E4.byteVicIIColors.BLACK; ;
$23E5.byteVicIIColors.BLACK; ;
tbl_background_color_6e_0
$23E6.byteVicIIColors.LIGHT_GREY; ; ; x-ref: $228B
$23E7.byteVicIIColors.WHITE; ;
$23E8.byteVicIIColors.LIGHT_GREY; ;
$23E9.byteVicIIColors.LIGHT_RED; ;
$23EA.byteVicIIColors.RED; ;
$23EB.byteVicIIColors.BLACK; ;
tbl_background_color_6e_1
$23EC.byteVicIIColors.RED; ; ; x-ref: $2291
$23ED.byteVicIIColors.LIGHT_RED; ;
$23EE.byteVicIIColors.RED; ;
$23EF.byteVicIIColors.BLACK; ;
$23F0.byteVicIIColors.BLACK; ;
$23F1.byteVicIIColors.BLACK; ;
tbl_background_color_6e_2
$23F2.byteVicIIColors.LIGHT_RED; ; ; x-ref: $2297
$23F3.byteVicIIColors.LIGHT_GREY; ;
$23F4.byteVicIIColors.LIGHT_RED; ;
$23F5.byteVicIIColors.RED; ;
$23F6.byteVicIIColors.BLACK; ;
$23F7.fill9, $00; ;
; screen
$2400font_row_0.byte$01, $02, $03, $04, $01, $02, $03, $04; x-ref: $0ED2
$2408.byte$01, $02, $03, $04, $05, $06, $07, $04
$2410.byte$08, $02, $03, $04, $01, $02, $03, $04
$2418.byte$01, $02, $03, $04, $05, $09, $0a, $0b
$2420.byte$05, $09, $00, $0c, $0d, $0b, $05, $09
$2428.byte$0a, $0b, $05, $09, $00, $00, $01, $02
$2430.byte$0d, $35, $36, $37, $38, $02, $03, $04
$2438.byte$01, $02, $03, $04, $01, $02, $03, $04
$2440.byte$01, $02, $03, $04, $01, $39, $03, $04
$2448.byte$01, $02, $03, $04, $01, $02, $03, $04
$2450.byte$4c, $09, $0a, $0b, $4c, $09, $0a, $0b
$2458.byte$4c, $09, $0a, $0b, $4c, $09, $05, $09
$2460.byte$0a, $0b, $05, $09, $0a, $0b, $05, $4d
$2468.byte$0d, $0b, $01, $02, $03, $04, $0c, $0d
$2470.byte$0b, $01, $39, $03, $04, $01, $39, $4e
$2478.byte$04, $4c, $09, $0a, $0b, $05, $66, $67
$2480.byte$68, $01, $39, $03, $04, $69, $6a, $03
$2488.byte$04, $01, $02, $03, $04, $01, $6b, $6c
$2490.byte$04, $6d, $02, $6e, $6f, $70, $71, $05
$2498.byte$4d, $6e, $69, $72, $73
$249D.fill8, $00
$24A5.byte$4c, $09
$24A7.fill8, $00
$24AF.byte$69, $8f, $69, $8f, $00, $00, $00, $00
$24B7.byte$01, $02, $03, $04, $00, $90, $91, $92
$24BF.byte$69, $93, $91, $92, $01, $02, $03, $04
$24C7.byte$00, $00, $00
$24CAfont_row_1.byte$0e, $0f, $10, $11, $0e, $12, $13, $14; x-ref: $0ED8
$24D2.byte$0e, $15, $16, $17, $0e, $15, $10, $11
$24DA.byte$0e, $0f, $18, $17, $0e, $0f, $18, $17
$24E2.byte$0e, $15, $19, $1a, $0e, $0f, $10, $11
$24EA.byte$0e, $15, $00, $00, $10, $11, $0e, $12
$24F2.byte$13, $3a, $0e, $15, $00, $00, $0e, $15
$24FA.byte$10, $11, $0e, $15, $0e, $15, $10, $11
$2502.byte$0e, $15, $10, $11, $0e, $12, $3b, $3c
$250A.byte$0e, $15, $10, $11, $0e, $12, $13, $3a
$2512.byte$3d, $3e, $3f, $40, $16, $41, $10, $11
$251A.byte$0e, $15, $10, $11, $0e, $15, $10, $11
$2522.byte$0e, $15, $10, $11, $0e, $15, $4f, $50
$252A.byte$13, $3a, $3d, $50, $10, $11, $51, $52
$2532.byte$53, $3c, $0e, $15, $10, $11, $00, $10
$253A.byte$11, $51, $52, $53, $3c, $54, $55, $13
$2542.byte$3a, $74, $50, $10, $11, $75, $50, $76
$254A.byte$77, $0e, $50, $3f, $40, $78, $79, $10
$2552.byte$11, $7a, $50, $13, $3a, $74, $50, $10
$255A.byte$11, $0e, $15, $00, $00, $10, $11, $0e
$2562.byte$7b, $00, $00, $10, $11, $7c, $7d, $7e
$256A.byte$94, $7c, $95, $96, $94, $0e, $15, $00
$2572.byte$00, $97, $98, $99, $9a, $9b, $9c
$2579.fill8, $00
$2581.byte$51, $9d, $3b, $9e, $00, $9f, $a0, $a1
$2589.byte$00, $a2, $a3, $a1, $7a, $50, $13, $3a
$2591.byte$00, $00, $00
$2594font_row_2.byte$1b, $1c, $1d, $1e, $1b, $1f, $20, $21; x-ref: $0EDE
$259C.byte$1b, $1e, $22, $23, $1b, $1e, $1b, $1e
$25A4.byte$1b, $1c, $24, $23, $25, $1c, $26, $00
$25AC.byte$1b, $1e, $1b, $1e, $1b, $1c, $1d, $1e
$25B4.byte$1b, $1e, $27, $28, $1b, $1e, $1b, $1f
$25BC.byte$20, $21, $1b, $1e, $22, $23, $1b, $1e
$25C4.byte$1b, $1e, $1b, $1e, $1b, $1e, $1b, $1e
$25CC.byte$1b, $1e, $1b, $1e, $1b, $1c, $42, $43
$25D4.byte$1b, $1e, $44, $45, $1b, $1f, $20, $21
$25DC.byte$46, $47, $48, $49, $00, $00, $1b, $1e
$25E4.byte$1b, $1e, $1b, $1e, $1b, $1e, $1b, $1e
$25EC.byte$1b, $1e, $1b, $1e, $1b, $1e, $56, $57
$25F4.byte$20, $21, $46, $58, $1d, $1e, $59, $5a
$25FC.byte$5b, $5c, $1b, $1e, $1b, $1e, $00, $1b
$2604.byte$1e, $5d, $5a, $5b, $5c, $5e, $47, $20
$260C.byte$21, $7f, $80, $1d, $1e, $46, $47, $48
$2614.byte$49, $1b, $1f, $48, $49, $81, $80, $1d
$261C.byte$1e, $56, $82, $20, $21, $83, $47, $1d
$2624.byte$1e, $1b, $1e, $00, $00, $1b, $1e, $1b
$262C.byte$1e, $00, $00, $1b, $1e, $84, $85, $85
$2634.byte$a4, $84, $a5, $a6, $a4, $a7, $a8, $00
$263C.byte$00, $a9, $aa, $ab, $ac, $ad, $ae, $00
$2644.byte$00, $00, $00, $00, $00, $af, $b0, $b1
$264C.byte$b2, $42, $43, $b3, $b4, $b5, $00, $b3
$2654.byte$b4, $b5, $00, $b6, $57, $b7, $b8, $00
$265C.byte$00, $00
$265Efont_row_3.byte$29, $2a, $29, $2b, $29, $2c, $2d, $2e; x-ref: $0EE4
$2666.byte$2f, $30, $31, $2e, $29, $2c, $2d, $2e
$266E.byte$32, $30, $31, $2e, $29, $2a, $00, $00
$2676.byte$32, $33, $34, $2b, $29, $2a, $29, $2b
$267E.byte$29, $2a, $32, $30, $2d, $2e, $29, $2a
$2686.byte$29, $2b, $32, $30, $31, $2e, $29, $2a
$268E.byte$29, $2b, $29, $2a, $29, $2a, $29, $2b
$2696.byte$32, $33, $2d, $2e, $29, $2a, $00, $00
$269E.byte$32, $30, $4a, $4b, $29, $2a, $29, $2b
$26A6.byte$32, $30, $2d, $2e, $00, $00, $29, $2b
$26AE.byte$32, $30, $2d, $2e, $32, $30, $34, $2b
$26B6.byte$32, $30, $34, $5f, $2d, $60, $29, $2a
$26BE.byte$29, $2b, $32, $30, $2d, $2e, $29, $61
$26C6.byte$62, $2b, $32, $33, $2d, $2e, $00, $63
$26CE.byte$2b, $29, $61, $64, $2b, $65, $30, $2d
$26D6.byte$2e, $00, $00, $63, $2b, $32, $30, $2d
$26DE.byte$2e, $32, $30, $2d, $2e, $00, $00, $63
$26E6.byte$2b, $32, $30, $86, $2e, $32, $30, $86
$26EE.byte$2e, $32, $33, $87, $88, $89, $8a, $29
$26F6.byte$8b, $87, $8c, $8d, $8e
$26FB.fill8, $00
$2703.byte$b9, $87, $8c, $87
$2707.fill10, $00
$2711.byte$ba, $bb, $ba, $bb, $8c, $87, $00, $00
$2719.byte$bc, $bd, $be, $00, $bc, $bd, $bf, $4b
$2721.byte$32, $33, $4a, $4b, $00, $00, $00
$2728.fill88, $dd
$2780char_to_font_idx.byte$ff, $00, $04, $08, $0c, $10, $14, $18; x-ref: $0EC7
$2788.byte$1c, $20, $22, $26, $2a, $2e, $34, $38
$2790.byte$3c, $40, $44, $48, $4c, $50, $54, $58
$2798.byte$5e, $62, $66, $97, $ff, $9a, $ff, $ff
$27A0.byte$c7, $a5, $af, $ff, $ff, $bf, $c3, $af
$27A8.byte$91, $94, $ff, $a1, $b3, $9d, $a7, $bb
$27B0.byte$6a, $6e, $71, $75, $79, $7d, $81, $85
$27B8.byte$89, $8d, $a9, $b5, $ff, $ab, $ff, $b7
$27C0char_col_width.byte$ff; x-ref: $0EC1
$27C1.fill8, $04
$27C9.byte$02, $04, $04, $04, $06
$27CE.fill9, $04
$27D7.byte$06, $04, $04, $04, $03, $ff, $03, $02
$27DF.byte$02, $02, $02, $04, $ff, $ff, $04, $04
$27E7.byte$02, $03, $03, $04, $04, $02, $04, $02
$27EF.byte$04, $04, $03
$27F2.fill8, $04
$27FA.byte$02, $02, $03, $04, $03, $04
; charset
$2800.fill9, $ff
$2809.byte$f5, $d8, $e0, $60, $42, $82, $82, $5a
$2811.byte$80, $02, $29, $a5, $96, $59, $9b, $57
$2819.byte$89, $27, $6d, $a9, $0a, $02, $82, $ff
$2821.byte$7f, $5f, $ef, $67, $57, $5b, $5b, $d6
$2829.byte$58, $62, $82, $82, $82, $82, $82, $aa
$2831.byte$00, $02, $55, $55, $9a, $59, $9b, $67
$2839.byte$89, $27, $6d, $a9, $0a, $02, $82, $ff
$2841.byte$f5, $d8, $e0, $60, $82, $82, $82, $9f
$2849.byte$27, $9b, $5b, $5b, $9b, $5b, $9b, $d5
$2851.byte$5a, $a2, $8a, $82, $82, $02, $82, $5f
$2859.byte$a7, $5b, $db, $5b, $5b, $5b, $5b, $da
$2861.byte$60, $82, $89, $65, $da, $ff, $ff, $65
$2869.byte$8a, $22, $5a, $62, $82, $02, $82, $02
$2871.byte$80, $02, $80, $00, $00, $00, $00, $63
$2879.byte$9b, $63, $9b, $a3, $a0, $80, $00, $02
$2881.byte$00, $02, $00, $02, $00, $02, $00, $63
$2889.byte$5b, $63, $9b, $63, $a3, $63, $a3, $63
$2891.byte$9b, $63, $9b, $a1, $a0, $80, $00, $02
$2899.byte$00, $02, $00, $02, $02, $0a, $2a, $63
$28A1.byte$5b, $6b, $97, $47, $af, $1f, $7f, $63
$28A9.byte$9b, $63, $9b, $a3, $9b, $a3, $a3, $89
$28B1.byte$69, $da, $ff, $ff, $ff, $ff, $ff, $6b
$28B9.byte$67, $9f, $ff, $ff, $ff, $ff, $ff, $89
$28C1.byte$69, $da, $ff, $ff, $27, $09, $0a, $89
$28C9.byte$69, $da, $ff, $ff, $d8, $60, $80, $6b
$28D1.byte$67, $9f, $ff, $ff, $9f, $27, $2b, $69
$28D9.byte$69, $69, $69, $62, $69, $62, $89, $ff
$28E1.byte$ff, $f5, $f7, $f7, $db, $f7, $db, $f5
$28E9.byte$d9, $69, $69, $62, $69, $62, $89, $f7
$28F1.byte$f7, $f7, $f7, $f7, $db, $f7, $db, $ff
$28F9.byte$ff, $f5, $f5, $f7, $db, $f7, $db, $df
$2901.byte$57, $a7, $69, $62, $69, $62, $89, $5f
$2909.byte$df, $d7, $f7, $f7, $db, $f7, $db, $ff
$2911.byte$ff, $ff, $ff, $ff, $d5, $5a, $aa, $ff
$2919.byte$ff, $ff, $ff, $ff, $5f, $97, $9b, $fd
$2921.byte$f5, $57, $ff, $ff, $d5, $5a, $aa, $69
$2929.byte$69, $69, $69, $62, $69, $62, $49, $fd
$2931.byte$f5, $57
$2933.fill10, $ff
$293D.byte$d5, $6a, $48, $ff, $ff, $ff, $ff, $ff
$2945.byte$5f, $a7, $9b, $62, $89, $62, $82, $82
$294D.byte$89, $65, $da, $77, $5b, $5b, $5b, $5b
$2955.byte$5b, $67, $9f, $77, $db, $5b, $db, $5b
$295D.byte$5b, $67, $9f, $77, $59, $5a, $60, $80
$2965.byte$55, $55, $88, $62, $89, $26, $29, $a5
$296D.byte$55, $5a, $97, $77, $db, $57, $e7, $6f
$2975.byte$9f, $7f, $ff, $62, $89, $62, $40, $60
$297D.byte$d8, $f6, $ff, $77, $59, $96, $a8, $a0
$2985.byte$25, $15, $58, $61, $89, $26, $29, $a5
$298D.byte$55, $5a, $97, $62, $89, $62, $40, $e0
$2995.byte$d8, $f6, $ff, $7b, $59, $96, $a8, $a0
$299D.byte$25, $15, $58, $62, $89, $a2, $0a, $02
$29A5.byte$55, $55, $aa, $66, $88, $00, $d5, $55
$29AD.byte$5a, $59, $5b, $57, $a9, $27, $e5, $a9
$29B5.byte$0a, $82, $82, $ff, $7f, $9f, $6f, $67
$29BD.byte$57, $5b, $9b, $ff, $f5, $d2, $e0, $60
$29C5.byte$42, $82, $82, $5a, $80, $02, $29, $a5
$29CD.byte$96, $5a, $9b, $63, $5b, $6b, $a7, $47
$29D5.byte$af, $9f, $7f, $02, $00, $02, $00, $00
$29DD.byte$00, $02, $0a, $63, $5b, $63, $9b, $6b
$29E5.byte$a7, $67, $9f, $02, $80, $02, $80, $80
$29ED.byte$40, $60, $d8, $63, $9b, $63, $93, $a1
$29F5.byte$28, $00, $00, $89, $69, $da, $ff, $ff
$29FD.byte$97, $02, $0a, $6b, $67, $9f, $ff, $ff
$2A05.byte$ff, $7f, $9f, $6b, $a7, $9f, $ff, $ff
$2A0D.byte$ff, $ff, $ff, $ff, $f5, $57, $ff, $ff
$2A15.byte$ff, $ff, $ff, $5f, $7f, $ff, $ff, $ff
$2A1D.byte$ff, $ff, $ff, $69, $69, $69, $69, $69
$2A25.byte$67, $5f, $d9, $f7, $f7, $f7, $f7, $f7
$2A2D.byte$db, $57, $9f, $d6, $f5, $ff, $ff, $ff
$2A35.byte$d5, $6a, $48, $9f, $7f, $55, $fd, $ff
$2A3D.byte$5f, $a7, $9b, $5f, $57, $a5, $69, $62
$2A45.byte$69, $62, $89, $df, $d7, $f7, $f7, $f7
$2A4D.byte$db, $f7, $db, $ff, $ff, $a6, $08, $00
$2A55.byte$55, $55, $aa, $ff, $ff, $5f, $a7, $9b
$2A5D.byte$5b, $67, $9f, $d6, $58, $62, $82, $82
$2A65.byte$80, $82, $80, $aa, $00, $02, $55, $55
$2A6D.byte$9a, $5b, $9b, $57, $89, $27, $ad, $a9
$2A75.byte$0a, $02, $82, $02, $80, $82, $80, $40
$2A7D.byte$40, $e0, $d8, $63, $9b, $63, $9b, $a1
$2A85.byte$28, $00, $00, $89, $69, $da, $ff, $ff
$2A8D.byte$ff, $f6, $d8, $6b, $a7, $9f, $ff, $fd
$2A95.byte$58, $00, $00, $02, $00, $02, $00, $02
$2A9D.byte$00, $02, $0a, $89, $69, $da, $ff, $ff
$2AA5.byte$ff, $fd, $fe, $6b, $a7, $9f, $ff, $fd
$2AAD.byte$60, $80, $00, $f5, $d6, $da, $5a, $62
$2AB5.byte$69, $62, $89, $a7, $9f, $7d, $f5, $f7
$2ABD.byte$db, $f7, $db, $9f, $7f, $55, $ff, $ff
$2AC5.byte$5f, $a7, $9b, $da, $5a, $69, $69, $62
$2ACD.byte$69, $62, $89, $97, $5f, $7d, $f5, $f7
$2AD5.byte$db, $f7, $db, $ff, $f5, $57, $ff, $ff
$2ADD.byte$d5, $5a, $aa, $5f, $7f, $ff, $ff, $ff
$2AE5.byte$5f, $97, $9b, $da, $5a, $69, $69, $62
$2AED.byte$69, $62, $49, $fd, $fd, $ff, $ff, $ff
$2AF5.byte$d5, $6a, $48, $77, $d9, $5a, $a0, $80
$2AFD.byte$55, $55, $8a, $77, $5b, $57, $67, $6f
$2B05.byte$9f, $7f, $ff, $77, $59, $96, $a8, $a0
$2B0D.byte$55, $55, $88, $61, $89, $a2, $02, $02
$2B15.byte$55, $55, $aa, $62, $89, $62, $8a, $82
$2B1D.byte$89, $65, $da, $61, $89, $a2, $0a, $02
$2B25.byte$55, $55, $aa, $62, $a9, $62, $60, $e0
$2B2D.byte$d8, $f6, $ff, $aa, $00, $02, $a9, $a5
$2B35.byte$96, $59, $9b, $65, $8a, $22, $5d, $55
$2B3D.byte$aa, $ff, $ff, $5f, $a7, $5b, $db, $67
$2B45.byte$9f, $ff, $ff, $d6, $58, $62, $89, $65
$2B4D.byte$da, $ff, $ff, $aa, $00, $02, $55, $55
$2B55.byte$aa, $fd, $ff, $6a, $80, $02, $29, $a5
$2B5D.byte$96, $59, $9b, $57, $99, $a7, $ad, $a9
$2B65.byte$0a, $02, $82, $ff, $f5, $da, $e0, $60
$2B6D.byte$42, $82, $82, $5f, $97, $b7, $5b, $67
$2B75.byte$9f, $ff, $ff, $d6, $58, $62, $89, $65
$2B7D.byte$da, $fd, $ff, $97, $09, $27, $65, $a9
$2B85.byte$0a, $02, $82, $ff, $7f, $9f, $6f, $67
$2B8D.byte$57, $5b, $5b, $aa, $00, $02, $5a, $62
$2B95.byte$82, $02, $80, $5f, $97, $b7, $5b, $5b
$2B9D.byte$5b, $5b, $5b, $02, $80, $02, $80, $80
$2BA5.byte$40, $40, $e0, $02, $80, $02, $80, $80
$2BAD.byte$40, $60, $d0, $ff, $ff, $ff, $ff, $ff
$2BB5.byte$97, $02, $0a, $ff, $ff, $ff, $ff, $ff
$2BBD.byte$ff, $7f, $9f, $ff, $ff, $ff, $ff, $ff
$2BC5.byte$ff, $fd, $fe, $ff, $ff, $ff, $ff, $ff
$2BCD.byte$60, $80, $00, $02, $80, $02, $80, $40
$2BD5.byte$40, $e0, $d8, $63, $9b, $63, $93, $a3
$2BDD.byte$93, $a3, $a3, $ff, $ff, $ff, $ff, $ff
$2BE5.byte$d6, $60, $80, $ff, $ff, $ff, $ff, $ff
$2BED.byte$00, $00, $00, $ff, $ff, $ff, $ff, $ff
$2BF5.byte$02, $00, $00, $d6, $f5, $ff, $ff, $ff
$2BFD.byte$ff, $ff, $ff, $9f, $7f, $55, $ff, $ff
$2C05.byte$ff, $ff, $ff, $fd, $fd, $ff, $ff, $ff
$2C0D.byte$ff, $ff, $ff, $a7, $9f, $7d, $75, $f7
$2C15.byte$db, $f7, $db, $d6, $f5, $ff, $ff, $ff
$2C1D.byte$d9, $62, $88, $67, $5f, $d5, $ff, $ff
$2C25.byte$ff, $ff, $ff, $ff, $ff, $55, $ff, $ff
$2C2D.byte$ff, $ff, $ff, $62, $89, $26, $09, $a5
$2C35.byte$55, $5a, $97, $ff, $ff, $9f, $27, $9b
$2C3D.byte$5b, $67, $9f, $ff, $fd, $da, $60, $80
$2C45.byte$89, $65, $da, $62, $81, $0a, $29, $a5
$2C4D.byte$55, $5a, $97, $77, $db, $57, $67, $6f
$2C55.byte$9f, $7f, $ff, $7b, $5b, $5a, $60, $80
$2C5D.byte$55, $55, $88, $ff, $ff, $da, $60, $80
$2C65.byte$89, $65, $da, $62, $81, $82, $02, $02
$2C6D.byte$55, $55, $88, $77, $db, $5b, $5b, $5b
$2C75.byte$5b, $67, $9f, $9f, $27, $9b, $5b, $67
$2C7D.byte$9f, $ff, $ff, $ff, $ff, $ff, $fd, $fd
$2C85.byte$fe, $fe, $f4, $d5, $5a, $a2, $8a, $09
$2C8D.byte$09, $2a, $09, $5f, $a7, $5b, $d7, $67
$2C95.byte$6f, $6f, $5f, $9f, $27, $9b, $59, $65
$2C9D.byte$9e, $fe, $f4, $ff, $ff, $ff, $ff, $ff
$2CA5.byte$5f, $27, $2b, $da, $60, $80, $00, $00
$2CAD.byte$00, $00, $00, $9f, $27, $2b, $9b, $a3
$2CB5.byte$a2, $80, $00, $da, $60, $80, $81, $6a
$2CBD.byte$d8, $ff, $ff, $9f, $27, $2b, $ab, $a7
$2CC5.byte$9f, $ff, $ff, $d6, $60, $80, $81, $6a
$2CCD.byte$d6, $ff, $ff, $22, $00, $00, $aa, $aa
$2CD5.byte$00, $ff, $ff, $22, $00, $00, $99, $aa
$2CDD.byte$02, $ff, $ff, $5f, $27, $2b, $ab, $a7
$2CE5.byte$5f, $ff, $ff, $6b, $a7, $9f, $ff, $fd
$2CED.byte$58, $00, $0a, $63, $5b, $63, $ab, $ab
$2CF5.byte$a7, $87, $af, $f4, $f8, $d8, $d0, $e0
$2CFD.byte$60, $42, $80, $25, $09, $26, $98, $26
$2D05.byte$99, $a1, $ab, $9f, $bf, $7f, $7f, $ff
$2D0D.byte$ff, $ff, $ff, $f4, $f8, $d8, $d0, $e0
$2D15.byte$60, $40, $80, $25, $09, $26, $18, $2a
$2D1D.byte$29, $a1, $ab, $f7, $d7, $5f, $ff, $ff
$2D25.byte$ff, $ff, $ff, $fd, $f6, $5a, $5a, $5a
$2D2D.byte$59, $67, $d9, $7f, $7f, $7d, $7f, $7f
$2D35.byte$ff, $d7, $9f, $69, $69, $69, $69, $69
$2D3D.byte$67, $6f, $d9, $f7, $f7, $f7, $f7, $f7
$2D45.byte$db, $67, $9f, $ff, $ff, $d5, $5a, $6a
$2D4D.byte$67, $6f, $d9, $ff, $ff, $5f, $97, $77
$2D55.byte$fb, $e7, $9f, $ff, $ff, $d5, $5a, $6a
$2D5D.byte$65, $67, $d5, $ff, $ff, $55, $aa, $aa
$2D65.byte$ff, $77, $99, $ff, $ff, $55, $aa, $aa
$2D6D.byte$dd, $77, $99, $ff, $ff, $5f, $97, $77
$2D75.byte$db, $57, $5f, $d5, $5a, $6a, $67, $5f
$2D7D.byte$d5, $ff, $ff, $5f, $97, $77, $f7, $d7
$2D85.byte$5f, $ff, $ff, $da, $5a, $69, $69, $69
$2D8D.byte$67, $6f, $d9, $97, $5f, $7d, $f5, $f7
$2D95.byte$db, $67, $9f, $ff, $fd, $fd, $fd, $f5
$2D9D.byte$f6, $f6, $d8, $69, $69, $a7, $a7, $a7
$2DA5.byte$9f, $a7, $9f, $f7, $f7, $d7, $df, $df
$2DAD.byte$5f, $7f, $bf, $f5, $d6, $da, $5a, $61
$2DB5.byte$69, $62, $89, $df, $57, $a7, $69, $69
$2DBD.byte$67, $5f, $d9, $5f, $df, $d7, $f7, $f7
$2DC5.byte$db, $57, $9f, $ff, $ff, $da, $60, $80
$2DCD.byte$89, $65, $d6, $d6, $58, $62, $8a, $66
$2DD5.byte$d8, $f6, $fd, $9f, $27, $9b, $5b, $5b
$2DDD.byte$9b, $27, $9f, $d2, $d8, $e2, $60, $42
$2DE5.byte$89, $65, $da, $b6, $95, $96, $95, $59
$2DED.byte$5b, $67, $9f, $7f, $ff, $ff, $ff, $ff
$2DF5.byte$ff, $ff, $ff, $7f, $ff, $d6, $68, $80
$2DFD.byte$89, $65, $d6
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Main entry point, initialization, and execution loop of the demo.
; Sets up VIC-II, clears screen, initializes tables, hooks raster IRQ,
; and runs the main loop with scroller and effect updates.
;
; Inputs: None
; Outputs: None
; Side Effects: Modifies VIC-II, SID, Screen RAM, Color RAM, and hooks IRQ.
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
$2E0078startsei; disable interrupts for safe hardware setup
$2E01a9 00lda#$00
$2E038d 11 d0sta$d011; blank screen during init to prevent visual glitches; VIC Control Register 1
$2E068d 20 d0sta$d020; black border; Border Color
$2E09a9 08lda#VicIIColors.ORANGE; dark gray background
$2E0B8d 21 d0sta$d021; Background Color 0
$2E0E8d 86 02staCHAR_COLOR; sync KERNAL background color shadow register
$2E1120 44 e5jsre_E544; clear screen RAM via KERNAL routine
$2E14a9 c1lda#<KERNAL_NMI_HANDLER; disable NMI (Restore key) to prevent unwanted resets
$2E168d 18 03staNMI_VECTOR_LO; NMI
$2E19a2 a0ldx#$a0; loop 1: 161 bytes; copy charset screen codes and color data, zero scroller rows
$2E1Bbd c7 0cb_2E1Bldalogo_rows_0_3,x; logo: rows 0-3 ; x-ref: $2E30
$2E1E9d 77 04staSCREEN_RAM_R2C39,x
$2E21bd 67 0dldalogo_rows_4_7,x; logo: rows 4-7
$2E249d 17 05staSCREEN_RAM_R6C39,x
$2E27a9 00lda#$00; zero scroller text rows ($062F, $06CF) — blank before scroller starts
$2E299d 2f 06staSCREEN_RAM_R13C39,x
$2E2C9d cf 06staSCREEN_RAM_R17C39,x
$2E2Fcadex
$2E30d0 e9bneb_2E1B
$2E32a2 27ldx#$27; loop 2: 40 bytes; fill screen/color rows for tube tiles and scroller band
$2E34a9 00b_2E34lda#$00; screen $0450/$05B8: zero = tube tile char 0 (filled by update_scroller_and_tubes) ; x-ref: $2E5D
$2E369d 50 04staSCREEN_RAM_R2C0,x
$2E399d b8 05staSCREEN_RAM_R11C0,x
$2E3Ca9 felda#$fe; screen $0630/$0748: $FE = blank scroller char (placeholder until scroller runs)
$2E3E9d 30 06staSCREEN_RAM_R14C0,x
$2E419d 48 07staSCREEN_RAM_R21C0,x
$2E44a9 08lda#VicIIColors.ORANGE; color RAM $DA30/$DB48: $08 = orange for tube tile rows
$2E469d 30 dastaCOLOR_RAM_R14C0,x
$2E499d 48 dbstaCOLOR_RAM_R21C0,x
$2E4Ca9 fflda#$ff; screen $0658/$0720: $FF = tube tile char 255 (filled by update_scroller_and_tubes)
$2E4E9d 58 06staSCREEN_RAM_R15C0,x
$2E519d 20 07staSCREEN_RAM_R20C0,x
$2E54a9 09lda#VicIIColors.BROWN; color RAM $DA58/$DB20: $09 = light brown for remaining tube rows
$2E569d 58 dastaCOLOR_RAM_R15C0,x
$2E599d 20 dbstaCOLOR_RAM_R20C0,x
$2E5Ccadex
$2E5D10 d5bplb_2E34
$2E5Fa9 01lda#$01; enable VIC raster interrupt
$2E618d 1a d0sta$d01a; VIC Interrupt Mask Register (IMR)
$2E648d 0d dcsta$dc0d; disable CIA1 timer interrupts (prevent conflict with raster IRQ); CIA1: CIA Interrupt Control Register
$2E67ad 0d dclda$dc0d; read CIA1 ICR to clear any pending interrupt; CIA1: CIA Interrupt Control Register
$2E6Aa9 f8lda#$f8; arm first IRQ handler (irq_hanlder_f8) at raster $F8; starts the full raster chain
$2E6Ca2 c5ldx#<irq_hanlder_f8
$2E6Ea0 23ldy#>irq_hanlder_f8
$2E7020 9a 2ejsrset_next_irq_state
$2E73a9 00lda#$00
$2E7520 00 10jsrsid_init; initialize SID music driver; A=0 selects song 0
$2E7820 08 0ejsrupdate_scroller_and_tubes; prime tube/scroller state before IRQs start firing (avoids first-frame glitch)
$2E7B58cli; enable interrupts — raster chain begins firing
$2E7Ca2 c1ldx#$c1; startup delay: wait $C1 (193) frames before activating logo color animation
$2E7E20 a4 2eb_2E7Ejsrwait_frame_or_exit; x-ref: $2E82
$2E81cadex
$2E82d0 fabneb_2E7E
$2E84a9 2clda#$2c; self-modify: write $2C (BIT opcode) over $4C (JMP) at a2272 to fall through to DEX — activates animation
$2E868d 72 22stalogo_shimmer_enable_gate
$2E89a2 c1ldx#$c1; second startup delay: another $C1 frames before entering main loop
$2E8B20 a4 2eb_2E8Bjsrwait_frame_or_exit; x-ref: $2E8F
$2E8Ecadex
$2E8Fd0 fabneb_2E8B
$2E9120 a4 2emain_loopjsrwait_frame_or_exit; wait for frame tick (gated by raster_irq_bottom_tube via a2EA5) ; x-ref: $2E97
$2E9420 08 0ejsrupdate_scroller_and_tubes; update tube sine scroll positions and advance text scroller one step
$2E974c 91 2ejmpmain_loop
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Configures the next raster interrupt in the VIC-II IRQ chain.
; Sets the target scanline in $D012 and updates the KERNAL IRQ vector ($0314/$0315).
; Inputs: A = target raster scanline
; X = low byte of next IRQ handler address
; Y = high byte of next IRQ handler address
; Outputs: None
; Side Effects: Programs VIC-II $D012 and KERNAL IRQ shadow vector $0314-$0315
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
$2E9A8c 15 03set_next_irq_statestyIRQ_VECTOR_HI; x-ref: $23CB, $2E70, $2ED3 IRQ
$2E9D8e 14 03stxIRQ_VECTOR_LO; IRQ
$2EA08d 12 d0sta$d012; Raster Position
$2EA360rts
frame_sync_tick_ctr =*+$01 ; x-ref: $23A8, $2EA8
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Synchronizes execution with the raster frame tick and polls joystick exit.
;
; Uses a self-modifying loop:
; 1. Busy-waits until the immediate operand of the LDA at $2EA5 (which is
; incremented at 50Hz by the bottom-tube raster IRQ) becomes non-zero.
; 2. Decrements that operand at $2EA5 back down to consume the tick.
; 3. Checks CIA1 Port B ($DC01) for the Port 2 Joystick fire button.
; 4. If fire is pressed, discards the JSR return address and jumps to handle_exit.
; 5. Otherwise, returns to continue execution.
;
; Inputs: Self-modified tick count at $2EA5
; Outputs: None
; Side Effects: Resets tick count, may abort main loop and branch to handle_exit
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
$2EA4a9 00wait_frame_or_exitlda#$00; x-ref: $2E7E, $2E8B, $2E91, $2EA6
$2EA6f0 fcbeqwait_frame_or_exit
$2EA8ce a5 2edecframe_sync_tick_ctr
$2EABad 01 dclda$dc01; CIA1: Data Port Register B
$2EAEc9 efcmp#$ef
$2EB0d0 03bner_2EB5
$2EB24c b6 2ejmphandle_exit
$2EB560r_2EB5rts; x-ref: $2EB0
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Demo exit and full system cleanup handler.
; Triggered by joystick fire button (port 2) detected in wait_frame_or_exit.
; Does NOT return — ends with a warm RESET back to BASIC.
;
; Sequence:
; 1. Discard JSR return address (2x PLA) to escape the main loop
; 2. Silence SID (zero all 29 registers), blank screen
; 3. Restore KERNAL IRQ vector, VIC-II defaults, CIA/IRQ via IOINIT
; 4. Display credits row: "CODE:DIDI LOGO:AGD 4X4:DMD MUSIC:DEEK"
; 5. Relocate cleanup_reloc_0340 stub to $0340 (tape buffer), jump there;
; stub restores BASIC ROM from $3200 -> $0801, then JMPs to RESET
;
; The cleanup stub is relocated because it overwrites $0801+ (BASIC program
; RAM) and cannot safely run in place from its original location.
;
; Inputs: None
; Outputs: Does not return
; Side Effects: SID silenced; VIC-II reset to defaults; IRQ vector restored;
; credits written to screen row 23; BASIC ROM restored;
; warm RESET via JMP $FCE2
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
$2EB668handle_exitpla; discard JSR return address from stack to escape the main loop ; x-ref: $2EB2
$2EB768pla
$2EB878sei; disable interrupts immediately during teardown
$2EB9a9 00lda#$00
$2EBB8d 11 d0sta$d011; blank screen; VIC Control Register 1
$2EBE8d 21 d0sta$d021; black background; Background Color 0
$2EC185 c6staKEY_BUF_COUNT; clear KERNAL keyboard buffer count
$2EC3a2 1cldx#$1c; silence SID: zero all 29 registers ($D400-$D41C)
$2EC59d 00 d4b_2EC5sta$d400,x; x-ref: $2EC9 Voice 1: Frequency Control - Low-Byte
$2EC8cadex
$2EC910 fabplb_2EC5
$2ECB20 44 e5jsre_E544; clear screen RAM via KERNAL
$2ECEa9 31lda#<KERNAL_IRQ_HANDLER; restore IRQ vector to KERNAL default ($EA31)
$2ED0aatax
$2ED1a0 ealdy#>KERNAL_IRQ_HANDLER
$2ED320 9a 2ejsrset_next_irq_state
$2ED6a2 1fldx#$1f; restore VIC-II registers to KERNAL defaults (X=31 selects full register set)
$2ED820 aa e5jsre_E5AA; set VIC registers to default ones
$2EDB20 a3 fdjsrKERNAL_IOINITj; re-initialize CIA chips and IRQ system via KERNAL IOINIT; $FDA3 (jmp) - initialize CIA & IRQ
$2EDE78sei; re-disable IRQs after IOINIT re-enabled them (CLI inside IOINIT)
$2EDFa2 27ldx#$27
$2EE1a9 08b_2EE1lda#VicIIColors.ORANGE; set color RAM to orange for the whole row ; x-ref: $2EED
$2EE39d e0 d9staCOLOR_RAM_R12C0,x; screen color
$2EE6bd b8 21ldatxt_credits_exit,x; write credits text to screen row 23
$2EE99d e0 05staSCREEN_RAM_R12C0,x
$2EECcadex
$2EED10 f2bplb_2EE1
$2EEFa2 34ldx#$34; set counter for cleanup code relocation (53 bytes)
$2EF186 01stxCPU_PORT
$2EF3bd e0 21b_2EF3ldacleanup_reloc_0340,x; copy cleanup stub from original binary to $0340 ; x-ref: $2EFA
$2EF69d 40 03staexit_stub_buffer,x
$2EF9cadex
$2EFA10 f7bplb_2EF3
$2EFC4c 40 03jmpexit_stub_buffer; execute cleanup stub from safe memory (tape buffer area)
$2EFF.byte$00
.encode
.enc"screen"
$2F00scroller_txt.text"WELCOME TO AN OLDSCHOOL INTRO BY DIDI CA"; x-ref: $0EA5, $0EAA, $0EAF
$2F28.text"LLED ""MOVING TUBES"" FOR THE 16K CATEGORY"
$2F50.text" OF ICC 2026! IT USES A LOGO BY AGD, TUB"
$2F78.text"ES AND 4X4 CHARSET BY DMD AND COOL OLD M"
$2FA0.text"USIC BY DEEK. ALL WAS CODED ON FEBRUARY "
$2FC8.text"11TH IN 2026, AFTER SOME DATA COLLECTING"
$2FF0.text" THE DAY BEFORE. ENJOY! "
$3018.text" "
.endencode
$301Bpadding_zeros.fill485, $00