diff --git a/Audio.inc b/Audio.inc index 07db592..849e369 100644 --- a/Audio.inc +++ b/Audio.inc @@ -1,534 +1,629 @@ +SECTION "Audio Interface", ROM0 SoundSetup: - ld a, BANK(gbt_play) + ld a, BANK(AudioEngineInit) ld [rROMB0], a - ld de,pythonrangetest - ld bc,BANK(instr_test_data) - ld a,$05 - call gbt_play ; Play song - - ld a, 1 - call gbt_loop + ld de, gb_tarot_theme + ld c, BANK(gb_tarot_theme) + call AudioEngineInit ; Play song ld a, [cvCardBank] ld [rROMB0], a ret SoundUpdate: - ld a, BANK(gbt_play) - ld [rROMB0], a - - call gbt_update + call AudioEngineUpdate ld a, [cvCardBank] ld [rROMB0], a ret + +SECTION "Audio Variables", WRAM0[AUDIO_VARS_START] +ordersBank: db +orders: dw + +speed: db + +readHead: dw + +tick: db +println "ticks are at ", tick +row: db +println "rows are at ", row +order: db +println "order index at ", order + +; i've chosen to pack the variables for each instrument sequentially in memory +; so all of channel 1's vars, then all of channel 2's vars, etc. +; gbt-player instead packs all four notes together, then all four volumes, +; then all four instruments. having thought about it more, gbt-player's approach +; may be better - it makes indexing to a channel's value simpler. but i've +; already written GetChannelAttributeAddress so it's neither here nor there +; at this point. +macro channel_vars + channel_\1: + ; inherents + channel_\1_note: db + channel_\1_volume: db + channel_\1_instrument: db + channel_\1_pan: db + ; special features! + channel_\1_arpeggio: db + channel_\1_vibrato: db + channel_\1_volume_slide: db + channel_\1_note_cut: db -; File created by mod2gbt -; s3m2gbt modified by shoofle to output rgbds-compatible asm files -SECTION "pythonrangetest_0", ROMX -pythonrangetest_0: - db $BF,$00,$30,$10,$10,$10, - db $00,$00,$00,$00, - db $BF,$01,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$02,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$03,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$04,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$05,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$06,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$07,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$08,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$09,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$0A,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$0B,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$0C,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$0D,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$0E,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$0F,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$10,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$11,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$12,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$13,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$14,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$15,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$16,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$17,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$18,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$19,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$1A,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$1B,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$1C,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$1D,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$1E,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$1F,$30,$00,$00,$00, - db $00,$00,$00,$00, - - -SECTION "pythonrangetest_1", ROMX -pythonrangetest_1: - db $BF,$20,$30,$10,$10,$10, - db $00,$00,$00,$00, - db $BF,$21,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$22,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$23,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$24,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$25,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$26,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$27,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$28,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$29,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$2A,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$2B,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$2C,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$2D,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$2E,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$2F,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$30,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$31,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$32,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$33,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$34,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$35,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$36,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$37,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$38,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$39,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$3A,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$3B,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$3C,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$3D,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$3E,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$3F,$30,$00,$00,$00, - db $00,$00,$00,$00, - - -SECTION "pythonrangetest_2", ROMX -pythonrangetest_2: - db $BF,$40,$30,$10,$10,$10, - db $00,$00,$00,$00, - db $BF,$41,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$42,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$43,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$44,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$45,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$46,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $BF,$47,$30,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - db $00,$00,$00,$00, - - -pythonrangetest_init_state: - db 0x01,0x06,0x02,0x11,0x22,0x44,0x88,0x00, - -SECTION "pythonrangetest", ROMX -pythonrangetest: - db BANK(pythonrangetest_0) - dw pythonrangetest_0 - - db BANK(pythonrangetest_1) - dw pythonrangetest_1 - - db BANK(pythonrangetest_2) - dw pythonrangetest_2 - - db $00 - dw $0000 - - - SECTION "instr_test_0", ROMX -instr_test_0: - DB $98, $1F, $20, $20, $4A, $07 - DB $2F, $00, $00, $20 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $98, $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $98, $3F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $98, $0F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $2F, $00, $00, $00 - DB $20, $00, $98, $10, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $98, $11, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $98, $12, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $98, $13, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - - SECTION "instr_test_1", ROMX -instr_test_1: - DB $00, $00, $98, $14, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $98, $15, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $98, $16, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $98, $17, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $21, $00 - DB $00, $00, $20, $80, $0F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $81, $0F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $82, $0F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $83, $0F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - - SECTION "instr_test_2", ROMX -instr_test_2: - DB $00, $00, $00, $84, $0F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $85, $0F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $86, $0F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $87, $0F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $88, $0F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $89, $0F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $8A, $0F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $8B, $0F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - - SECTION "instr_test_3", ROMX -instr_test_3: - DB $00, $00, $00, $8C, $0F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $8D, $0F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $8E, $0F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $8F, $0F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $2F - DB $00, $00, $00, $20 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - DB $00, $00, $00, $00 - - SECTION "instr_test_data", ROM0 -instr_test_data:: - DB BANK(instr_test_0) - DW instr_test_0 - DB BANK(instr_test_1) - DW instr_test_1 - DB BANK(instr_test_2) - DW instr_test_2 - DB BANK(instr_test_3) - DW instr_test_3 - DB $00 - DW $0000 - + channel_\1_trigger: db +endm + +channel_vars 1 +channel_vars 2 +channel_vars 3 +channel_3_loaded_instrument: db +channel_vars 4 + +SECTION "Audio Engine", ROM0 + +Periods: + DW 44, 156, 262, 363, 457, 547, 631, 710, 786, 854, 923, 986 + DW 1046, 1102, 1155, 1205, 1253, 1297, 1339, 1379, 1417, 1452, 1486, 1517 + DW 1546, 1575, 1602, 1627, 1650, 1673, 1694, 1714, 1732, 1750, 1767, 1783 + DW 1798, 1812, 1825, 1837, 1849, 1860, 1871, 1881, 1890, 1899, 1907, 1915 + DW 1923, 1930, 1936, 1943, 1949, 1954, 1959, 1964, 1969, 1974, 1978, 1982 + DW 1985, 1988, 1992, 1995, 1998, 2001, 2004, 2006, 2009, 2011, 2013, 2015 +WaveSamples: ; 8 sounds, pilfered from gbt like so many things + DB $A5,$D7,$C9,$E1,$BC,$9A,$76,$31,$0C,$BA,$DE,$60,$1B,$CA,$03,$93 ; random + DB $F0,$E1,$D2,$C3,$B4,$A5,$96,$87,$78,$69,$5A,$4B,$3C,$2D,$1E,$0F + DB $FD,$EC,$DB,$CA,$B9,$A8,$97,$86,$79,$68,$57,$46,$35,$24,$13,$02 ; up-downs + DB $DE,$FE,$DC,$BA,$9A,$A9,$87,$77,$88,$87,$65,$56,$54,$32,$10,$12 + DB $AB,$CD,$EF,$ED,$CB,$A0,$12,$3E,$DC,$BA,$BC,$DE,$FE,$DC,$32,$10 ; tri. broken + DB $FF,$EE,$DD,$CC,$BB,$AA,$99,$88,$77,$66,$55,$44,$33,$22,$11,$00 ; triangular + DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$00,$00,$00,$00,$00,$00,$00,$00 ; square + DB $79,$BC,$DE,$EF,$FF,$EE,$DC,$B9,$75,$43,$21,$10,$00,$11,$23,$45 ; sine +NoiseOptions: ; 16 different ways to configure NR43 for different sounds +; once again this method is from gbt. if you use the gbt sample# as an index into +; this, it will match the gbt s3m template. + DB $5F,$5B,$4B,$2F,$3B,$58,$1F,$0F ; 7 bit + DB $90,$80,$70,$50,$00 ; 15 bit + DB $67,$63,$53 +AudioEngineInit: + ld a, c + ld [ordersBank], a + + ld a, e + ld [orders], a + ld a, d + ld [orders+1], a + + ld a, 6 + ld [speed], a + + ld a, $ff + ld [tick], a + ld [row], a + ld [order], a + + ld a, AUDENA_ON + ld [rNR52], a ; master audio enable + ld a, $ff + ld [rNR51], a ; panning + ld a, $ff + ld [rNR50], a ; stereo volume + + ld a, $ff + ld [channel_1_note_cut], a + ld [channel_2_note_cut], a + ld [channel_3_note_cut], a + ld [channel_4_note_cut], a + ld [channel_3_loaded_instrument], a + ret + +AudioEngineUpdate: + ld a, [ordersBank] + ld [rROMB0], a + + call IncrementTick + ld a, [tick] + cp a, 0 + jp nz, .updateRegisters + call z, IncrementRow + + ld a, [row] + cp a, 0 + call z, IncrementOrder + + ld a, [row] + cp a, 0 + call z, hitit + + ld a, [row] + cp a, 0 + call z, FreshOrder + + call FreshRow +.updateRegisters + + call UpdateRegisters1 + call UpdateRegisters2 + call UpdateRegisters3 + call UpdateRegisters4 + + nop ; just throwiing this in here so i can break on it for timing + + ret +hitit: + ret +IncrementTick: + ld a, [speed] + ld b, a + ld a, [tick] + inc a + call ArrayClampLoopingB + ld [tick], a + ret +IncrementRow: + ld b, 64 + ld a, [row] + inc a + call ArrayClampLoopingB + ld [row], a + ret +IncrementOrder: + ld a, [orders] + ld l, a + ld a, [orders+1] + ld h, a + ld a, [order] + inc a + call ArrayClampLooping + ld [order], a + ret + +FreshOrder: + ld a, [orders] + ld l, a + ld a, [orders+1] + ld h, a + inc hl + ld a, [order] + ld c, a + ld b, 0 + + add hl, bc + add hl, bc + ld b, h + ld c, l + + ld a, [bc] + ld [readHead], a + inc bc + ld a, [bc] + ld [readHead+1], a + + ret + +FreshRow: + ld a, [readHead] + ld l, a + ld a, [readHead+1] + ld h, a + + ld a, [hl] + and a, $F0 + cp a, 0 + ; this should always be zero. + + inc hl + ld a, [row] + cp a, [hl] + + ret nz ; not ready for a fresh row until the current row matches the upcoming row + inc hl + + ld e, l + ld a, l + ld [readHead], a + ld d, h + ld a, h + ld [readHead+1], a + +.examinePacket + ; de is our read head for the time being so we don't have to write + ; so many loads in and out of memory + ld a, [de] + and a, $F0 + swap a + ld hl, .packetJumpTable ; this all jumps based on what the top nibble is + ld c, a + ld b, 0 + add hl, bc + add hl, bc + ld c, [hl] + inc hl + ld b, [hl] + ld l, c + ld h, b + + jp hl +.packetJumpTable + dw .newRow ;$0x + dw .setNote ;$1x + dw .setVolume ;$2x + dw .setInstrument ;$3x + dw .setPan ;$4x + dw .setArpeggio ;$5x + dw .setVibrato ;$6x + dw .setVolumeSlide;$7x + dw .setNoteCut ;$8x + dw .jumpOrder ;$90 + dw .breakAndSetRow;$A0 + dw .setSpeed ;$B0 + dw .callbackEvent ;$C0 +.newRow + ; if we find a new row, set the read head to that value and return + ld a, e + ld [readHead], a + ld a, d + ld [readHead+1], a + ret +.setNote + call TriggerIt ; always trigger on notes + ld hl, channel_1_note - channel_1 + jp .WriteAttributeButDoNotTrigger +.setVolume + ld hl, channel_1_volume - channel_1 + jp .WriteAttributeAndTriggerIfDifferent +.setInstrument + ld hl, channel_1_instrument - channel_1 + jp .WriteAttributeAndTriggerIfDifferent +.setPan + ld hl, channel_1_pan - channel_1 + jp .WriteAttributeButDoNotTrigger +.setArpeggio + ld hl, channel_1_arpeggio - channel_1 + jp .WriteAttributeAndTriggerIfDifferent +.setVibrato + ld hl, channel_1_vibrato - channel_1 + jp .WriteAttributeAndTriggerIfDifferent +.setVolumeSlide + ld hl, channel_1_volume_slide - channel_1 + jp .WriteAttributeAndTriggerIfDifferent +.setNoteCut + ld hl, channel_1_note_cut - channel_1 + jp .WriteAttributeButDoNotTrigger +.jumpOrder + inc de + ld a, [de] + ld [order], a + + ld a, 0 + ld [row], a + ld [tick], a + + call FreshOrder + call FreshRow + ret +.breakAndSetRow + inc de + + call IncrementOrder + + call FreshOrder + call FreshRow + ret +.setSpeed + inc de + ld a, [de] + ld [speed], a + inc de + jp .examinePacket +.callbackEvent + ; todo, fall through +.skipIt + inc de + inc de + jp .examinePacket + +.WriteAttributeAndTriggerIfDifferent: + ; de points to a packet + ; hl holds an offset to an attribute (e.g. channel_1_volume - channel_1) + ld a, [de] + and a, $0F + call GetChannelAttributeAddress + push hl + + inc de + ld a, [de] + cp a, [hl] + call nz, TriggerBack + ld a, [de] + pop hl + ld [hl], a + + inc de + jp .examinePacket + +.WriteAttributeButDoNotTrigger: + ld a, [de] + and a, $0F + call GetChannelAttributeAddress + + inc de + ld a, [de] + ld [hl], a + + inc de + jp .examinePacket + +GetChannelAttributeAddress: + ; this is a weird one. + ; a should have the channel number (1, 2, 3, 4) + ; hl shoulld have an offset into a channel attribute (like channel_1_note - channel_1) + ; htis will fetch into hl that attribute's address on that channel. + push hl + ld hl, .beginningsOfNoteData + ld b, 0 + ld c, a + add hl, bc + add hl, bc + ld c, [hl] + inc hl + ld b, [hl] + pop hl + add hl, bc + ret + +.beginningsOfNoteData + dw 0 + dw channel_1 + dw channel_2 + dw channel_3 + dw channel_4 + +TriggerBack: + ; de points to an address. get the low nibble one address previous, + ; take as a channel number, and write 1 to the corresponding channel_1_trigger + ; address + dec de + call TriggerIt + inc de + ret + +TriggerIt: + ld a, [de] + and a, $0F + ld hl, channel_1_trigger - channel_1 + call GetChannelAttributeAddress + ld [hl], 1 + ret + +UpdateRegisters1: + ld a, [tick] + ld b, a + ld a, [channel_1_note_cut] + cp a, b + jp nz, :+ + ld a, 0 + ld [channel_1_volume], a + + cpl + ld [channel_1_trigger], a + + ld a, $ff + ld [channel_1_note_cut], a +: + ld a, [channel_1_trigger] + cp a, 0 + ret z + + ld a, 0 + ld [rNR10], a + + + ld a, [channel_1_instrument] + ld [rNR11], a + + + ld a, [channel_1_volume] + swap a + and a, $70 + ld [rNR12], a + + ld a, [channel_1_note] + ld b, 0 + ld c, a + ld hl, Periods + add hl, bc + add hl, bc + ld a, [hl+] + ld [rNR13], a + + ld a, [hl] + or a, AUDHIGH_RESTART + ld [rNR14], a + + ld a, 0 + ld [channel_1_trigger], a + ret +UpdateRegisters2: + ld a, [tick] + ld b, a + ld a, [channel_2_note_cut] + cp a, b + jp nz, :+ + ld a, 0 + ld [channel_2_volume], a + + cpl + ld [channel_2_trigger], a + + ld a, $ff + ld [channel_2_note_cut], a +: + ld a, [channel_2_trigger] + cp a, 0 + ret z + + ld a, [channel_2_instrument] + ld [rNR21], a + + + ld a, [channel_2_volume] + swap a + and a, $f0 + ld [rNR22], a + + ld a, [channel_2_note] + ld b, 0 + ld c, a + ld hl, Periods + add hl, bc + add hl, bc + ld a, [hl+] + ld [rNR23], a + + ld a, [hl] + or a, AUDHIGH_RESTART + ld [rNR24], a + + ld a, 0 + ld [channel_2_trigger], a + ret +UpdateRegisters3: + ld a, [tick] + ld b, a + ld a, [channel_3_note_cut] + cp a, b + jp nz, :+ + ld a, 0 + ld [rNR30], a ; turn off channel 3 if we hit a note cut. + + ld a, 0 + ld [channel_3_volume], a + + ; we don't need to retrigger because we already turned off the dac. + ;ld a, 1 + ;ld [channel_3_trigger], a + + ; we do want to reset the note cut tho. + ld a, $ff + ld [channel_3_note_cut], a +: + ld a, [channel_3_trigger] + cp a, 0 + ret z ; if we don't have a trigger, then don't do anything else. + + ; instrument has a special meaning for channel 3; it refers to an index into + ; an array of 16 (could be more!) samples, defined at the top of this file. + ; (each "sample" is a 16-byte sequence of 4-bit values blah blah read the + ; pandoc for that) + ld a, [channel_3_instrument] + ld hl, channel_3_loaded_instrument + cp a, [hl] + call nz, ChangeLoadedWave + + ld a, 0 ; length should always be zero + ld [rNR31], a + + + ; volumes are pre-processed by the export script. + ld a, [channel_3_volume] + swap a + and a, $f0 + ld [rNR32], a + cp a, 0 + call nz, .turnOnDAC + ld a, [channel_3_trigger] + cp a, 0 + call nz, .turnOnDAC + ; periods don't seem to be different for channel 3, so leave it as is + ld a, [channel_3_note] + ld b, 0 + ld c, a + ld hl, Periods + add hl, bc + add hl, bc + ld a, [hl+] + ld [rNR33], a + + ld a, [hl] + or a, AUDHIGH_RESTART + ld [rNR34], a + + ld a, 0 + ld [channel_3_trigger], a + ret +.turnOnDAC: + ld a, $80 + ld [rNR30], a + ret +ChangeLoadedWave: + ; a has the nidex of the wave in the wave table at the top of the file + ld b, a + ld a, [rNR30] + push af ; save thsi for later so we can restore it. + ld a, 0 + ld [rNR30], a ; turn off the DAC for channel 3 + ld a, b + ld [channel_3_loaded_instrument], a ; mark that we've switched to it + + and a, $0F + swap a ; fast multiply by 16 + + ld hl, WaveSamples + ld b, 0 + ld c, a + add hl, bc ; hl shoulld now ponit to the appropriate wave + ld de, _AUD3WAVERAM + ld bc, 16 / 8 ; using by8s for unnecessary optimization, so divide length by 8 + call CopyRangeBy8s + + pop af + ld [rNR30], a + ret + +UpdateRegisters4: + ld a, [tick] + ld b, a + ld a, [channel_4_note_cut] + cp a, b + jp nz, :+ + ld a, 0 + ld [channel_4_volume], a + + cpl + ld [channel_4_trigger], a + + ld a, $ff + ld [channel_4_note_cut], a +: + ld a, [channel_4_trigger] + cp a, 0 + ret z + + ld a, 0; [channel_2_instrument] + ld [rNR41], a + + + ld a, [channel_4_volume] + swap a + and a, $f0 + ld [rNR42], a + ld a, [channel_4_instrument] + ld b, 0 + ld c, a + ld hl, NoiseOptions + add hl, bc + ld a, [hl] + ld [rNR43], a + + ld a, AUDHIGH_RESTART + ld [rNR44], a + + ld a, 0 + ld [channel_4_trigger], a + ret + ret \ No newline at end of file diff --git a/gb_tarot_theme.inc b/gb_tarot_theme.inc new file mode 100644 index 0000000..ae0abff --- /dev/null +++ b/gb_tarot_theme.inc @@ -0,0 +1,335 @@ +; File created by shoofle's s3m2gbt edit + +gb_tarot_theme_0: + db $00, $00, +db $11, $00, +db $21, $0F, +db $31, $40, +db $12, $18, +db $22, $04, +db $32, $40, +db $23, $00, +db $14, $18, +db $24, $0F, +db $34, $08, + + db $0F, $01, +db $84, $00, + + db $0F, $02, +db $11, $00, +db $21, $0F, +db $31, $80, +db $12, $1C, +db $22, $04, +db $32, $40, + + db $0F, $03, + + db $0F, $04, +db $11, $00, +db $21, $0F, +db $31, $C0, +db $12, $1F, +db $22, $04, +db $32, $40, +db $14, $18, +db $24, $0F, +db $34, $0B, + + db $0F, $05, +db $84, $00, + + db $0F, $06, +db $81, $00, +db $12, $18, +db $22, $04, +db $32, $40, + + db $0F, $07, + + db $0F, $08, +db $12, $1C, +db $22, $04, +db $32, $40, +db $13, $26, +db $23, $0F, +db $33, $01, +db $14, $18, +db $24, $0F, +db $34, $0B, + + db $0F, $09, +db $84, $00, + + db $0F, $0A, +db $12, $1F, +db $22, $04, +db $32, $40, + + db $0F, $0B, + + db $0F, $0C, +db $11, $00, +db $21, $0F, +db $31, $00, +db $12, $18, +db $22, $04, +db $32, $40, +db $13, $24, +db $23, $0F, +db $33, $00, +db $14, $18, +db $24, $0F, +db $34, $0B, + + db $0F, $0D, +db $84, $00, + + db $0F, $0E, +db $11, $00, +db $21, $0F, +db $31, $00, +db $12, $1C, +db $22, $04, +db $32, $40, + + db $0F, $0F, + + db $0F, $10, +db $11, $04, +db $21, $0F, +db $31, $40, +db $12, $1C, +db $22, $04, +db $32, $40, +db $13, $21, +db $23, $0F, +db $33, $00, +db $14, $18, +db $24, $0F, +db $34, $08, + + db $0F, $11, +db $84, $00, + + db $0F, $12, +db $11, $04, +db $21, $0F, +db $31, $80, +db $12, $1F, +db $22, $04, +db $32, $40, + + db $0F, $13, + + db $0F, $14, +db $11, $04, +db $21, $0F, +db $31, $C0, +db $12, $23, +db $22, $04, +db $32, $40, +db $14, $18, +db $24, $0F, +db $34, $0B, + + db $0F, $15, +db $84, $00, + + db $0F, $16, +db $81, $00, +db $12, $1C, +db $22, $04, +db $32, $40, + + db $0F, $17, + + db $0F, $18, +db $12, $1F, +db $22, $04, +db $32, $40, +db $14, $18, +db $24, $0F, +db $34, $0B, + + db $0F, $19, +db $84, $00, + + db $0F, $1A, +db $12, $23, +db $22, $04, +db $32, $40, + + db $0F, $1B, + + db $0F, $1C, +db $11, $04, +db $21, $0F, +db $31, $00, +db $12, $1C, +db $22, $04, +db $32, $40, +db $14, $18, +db $24, $0F, +db $34, $0B, + + db $0F, $1D, +db $84, $00, + + db $0F, $1E, +db $11, $04, +db $21, $0F, +db $31, $00, +db $12, $1F, +db $22, $04, +db $32, $40, + + db $0F, $1F, + + db $0F, $20, +db $11, $06, +db $21, $0F, +db $31, $40, +db $12, $1F, +db $22, $03, +db $32, $40, +db $13, $28, +db $23, $0F, +db $33, $01, +db $14, $18, +db $24, $0F, +db $34, $08, + + db $0F, $21, +db $84, $00, + + db $0F, $22, +db $11, $06, +db $21, $0F, +db $31, $80, + + db $0F, $23, + + db $0F, $24, +db $11, $06, +db $21, $0F, +db $31, $C0, +db $22, $03, +db $14, $18, +db $24, $0F, +db $34, $0B, + + db $0F, $25, +db $84, $00, + + db $0F, $26, +db $81, $00, + + db $0F, $27, + + db $0F, $28, +db $22, $02, +db $14, $18, +db $24, $0F, +db $34, $0B, + + db $0F, $29, +db $84, $00, + + db $0F, $2A, + + db $0F, $2B, + + db $0F, $2C, +db $11, $06, +db $21, $0F, +db $31, $00, +db $22, $02, +db $14, $18, +db $24, $0F, +db $34, $0B, + + db $0F, $2D, +db $84, $00, + + db $0F, $2E, +db $11, $06, +db $21, $0F, +db $31, $00, + + db $0F, $2F, + + db $0F, $30, +db $11, $05, +db $21, $0F, +db $31, $40, +db $22, $01, +db $14, $18, +db $24, $0F, +db $34, $08, + + db $0F, $31, +db $84, $00, + + db $0F, $32, +db $11, $05, +db $21, $0F, +db $31, $80, + + db $0F, $33, + + db $0F, $34, +db $11, $05, +db $21, $0F, +db $31, $C0, +db $22, $01, +db $14, $18, +db $24, $0F, +db $34, $0B, + + db $0F, $35, +db $84, $00, + + db $0F, $36, +db $81, $00, + + db $0F, $37, + + db $0F, $38, +db $22, $00, +db $14, $18, +db $24, $0F, +db $34, $0B, + + db $0F, $39, +db $84, $00, + + db $0F, $3A, + + db $0F, $3B, + + db $0F, $3C, +db $11, $11, +db $21, $0F, +db $31, $00, +db $22, $00, +db $14, $18, +db $24, $0F, +db $34, $0B, + + db $0F, $3D, +db $84, $00, + + db $0F, $3E, +db $11, $11, +db $21, $0F, +db $31, $00, + + db $0F, $3F, + +gb_tarot_theme: + db 3 + dw gb_tarot_theme_0 + dw gb_tarot_theme_0 + dw gb_tarot_theme_0 diff --git a/gb_tarot_theme.s3m b/gb_tarot_theme.s3m index 2d06bb5..7c378f8 100644 Binary files a/gb_tarot_theme.s3m and b/gb_tarot_theme.s3m differ diff --git a/gb_tarot_theme1.inc b/gb_tarot_theme1.inc new file mode 100644 index 0000000..7426525 --- /dev/null +++ b/gb_tarot_theme1.inc @@ -0,0 +1,262 @@ +; File created by shoofle's s3m2gbt edit + +gb_tarot_theme1_0: + db $00, $00, +db $11, $00, +db $21, $0F, +db $31, $40, +db $12, $18, +db $22, $0F, +db $32, $40, +db $23, $00, +db $24, $00, + + db $0F, $01, + + db $0F, $02, +db $11, $00, +db $21, $0F, +db $31, $80, +db $12, $1C, +db $22, $0F, +db $32, $40, + + db $0F, $03, + + db $0F, $04, +db $11, $00, +db $21, $0F, +db $31, $C0, +db $12, $1F, +db $22, $0F, +db $32, $40, + + db $0F, $05, + + db $0F, $06, +db $81, $00, +db $12, $18, +db $22, $0F, +db $32, $40, + + db $0F, $07, + + db $0F, $08, +db $12, $1C, +db $22, $0F, +db $32, $40, + + db $0F, $09, + + db $0F, $0A, +db $12, $1F, +db $22, $0F, +db $32, $40, + + db $0F, $0B, + + db $0F, $0C, +db $11, $00, +db $21, $0F, +db $31, $00, +db $12, $18, +db $22, $0F, +db $32, $40, + + db $0F, $0D, + + db $0F, $0E, +db $11, $00, +db $21, $0F, +db $31, $00, +db $12, $1C, +db $22, $0F, +db $32, $40, + + db $0F, $0F, + + db $0F, $10, +db $11, $04, +db $21, $0F, +db $31, $40, +db $12, $1C, +db $22, $0F, +db $32, $40, + + db $0F, $11, + + db $0F, $12, +db $11, $04, +db $21, $0F, +db $31, $80, +db $12, $1F, +db $22, $0F, +db $32, $40, + + db $0F, $13, + + db $0F, $14, +db $11, $04, +db $21, $0F, +db $31, $C0, +db $12, $23, +db $22, $0F, +db $32, $40, + + db $0F, $15, + + db $0F, $16, +db $81, $00, +db $12, $1C, +db $22, $0F, +db $32, $40, + + db $0F, $17, + + db $0F, $18, +db $12, $1F, +db $22, $0F, +db $32, $40, + + db $0F, $19, + + db $0F, $1A, +db $12, $23, +db $22, $0F, +db $32, $40, + + db $0F, $1B, + + db $0F, $1C, +db $11, $04, +db $21, $0F, +db $31, $00, +db $12, $1C, +db $22, $0F, +db $32, $40, + + db $0F, $1D, + + db $0F, $1E, +db $11, $04, +db $21, $0F, +db $31, $00, +db $12, $1F, +db $22, $0F, +db $32, $40, + + db $0F, $1F, + + db $0F, $20, +db $11, $06, +db $21, $0F, +db $31, $40, +db $12, $1F, +db $22, $0F, +db $32, $40, + + db $0F, $21, + + db $0F, $22, +db $11, $06, +db $21, $0F, +db $31, $80, +db $22, $0C, + + db $0F, $23, + + db $0F, $24, +db $11, $06, +db $21, $0F, +db $31, $C0, +db $22, $0C, + + db $0F, $25, + + db $0F, $26, +db $81, $00, +db $22, $0C, + + db $0F, $27, + + db $0F, $28, +db $22, $07, + + db $0F, $29, + + db $0F, $2A, + + db $0F, $2B, + + db $0F, $2C, +db $11, $06, +db $21, $0F, +db $31, $00, +db $22, $07, + + db $0F, $2D, + + db $0F, $2E, +db $11, $06, +db $21, $0F, +db $31, $00, + + db $0F, $2F, + + db $0F, $30, +db $11, $05, +db $21, $0F, +db $31, $40, +db $22, $07, + + db $0F, $31, + + db $0F, $32, +db $11, $05, +db $21, $0F, +db $31, $80, + + db $0F, $33, + + db $0F, $34, +db $11, $05, +db $21, $0F, +db $31, $C0, +db $22, $03, + + db $0F, $35, + + db $0F, $36, +db $81, $00, + + db $0F, $37, + + db $0F, $38, +db $22, $03, + + db $0F, $39, + + db $0F, $3A, + + db $0F, $3B, + + db $0F, $3C, +db $11, $11, +db $21, $0F, +db $31, $00, +db $22, $03, + + db $0F, $3D, + + db $0F, $3E, +db $11, $11, +db $21, $0F, +db $31, $00, + + db $0F, $3F, + +gb_tarot_theme1: + db 3 + dw gb_tarot_theme1_0 + dw gb_tarot_theme1_0 + dw gb_tarot_theme1_0 diff --git a/main.asm b/main.asm index e7b2b6f..c5d8c1c 100644 --- a/main.asm +++ b/main.asm @@ -23,25 +23,25 @@ DEF INTERRUPT_LCD EQU SCENE_TEARDOWN + 4 def CARD_INIT equ INTERRUPT_LCD + 4 def CARD_UPDATE equ CARD_INIT + 4 def CARD_DRAW equ CARD_UPDATE + 4 -println "Card Draw is ", CARD_DRAW +println "Card Draw is ", SCENE_DRAW ; each of these sections is way bgger than it needs to be ; i doubt any of them will hold more than $20 bytes at all ; but might as well put them at round numbers for now def ASYNC_VARS_START equ $c200 ; this space's layout defined manually in async.inc -def SYSTEM_VARS_START equ $c300 ; system variables like buttons pressed, rng, time -def GLOBAL_VARS_START equ $c400 ; defined mostly in mainmenu, program-wide state +def SYSTEM_VARS_START equ $c300 ; system variables like buttons pressed, rng, dtime +def GLOBAL_VARS_START equ $c400 ; program-wide state defined mostly in mainmenu def SCREEN_VARS_START equ $c500 ; per-screen variables like animation stuff -def CARD_HELPER_VARS_START equ $c600 +def CARD_HELPER_VARS_START equ $c600 ; variables for card data def CARD_VARS_START equ $c700 ; variables for animation of individual cards -def CVS equ CARD_VARS_START -def SHUFFLED_DECK equ $c800 ; location for the shuffled deck -def AUDIO_VARS_START equ $c900 +def CVS equ CARD_VARS_START ; handy to be able to refer to CVS by a short name +def AUDIO_VARS_START equ $c800 ; variables for the audio subsystem +def SHUFFLED_DECK equ $c900 ; location for the shuffled deck def ZEROES equ $D000 def ONES equ $D200 -; allocating $8 spaces for system variables, currently only using $4 bytes +; system variables, which are like program-wide state vars but More Different PUSHS "System Variables", WRAM0[SYSTEM_VARS_START] rMYBTN: db ; EQU SYSTEM_VARS_START rMYBTNP: db ;EQU rMYBTN + 1 @@ -50,7 +50,6 @@ rLFSR: dw ; equ rDELTAT + 1 ; 16 bit POPS - def SAFE_DMA_LOCATION equ $ffc0 def VARIABLE_TILES_START equ 26 ; where in VRAM the variable tiles start @@ -559,11 +558,10 @@ LetterTiles: db $c0,$c0,$a0,$a0,$b8,$b8,$b0,$b0,$da,$da,$12,$12,$1a,$1a,$03,$03 .end -INCLUDE "Async.inc" -INCLUDE "Audio.inc" -INCLUDE "Random.inc" INCLUDE "CopyRange.inc" INCLUDE "CopyTiles.inc" +INCLUDE "Async.inc" +INCLUDE "Random.inc" INCLUDE "ScreenMainMenu.inc" INCLUDE "ScreenSpreadSelect.inc" INCLUDE "CardHelpers.inc" @@ -573,4 +571,6 @@ INCLUDE "ScreenShuffle.inc" INCLUDE "CardLibrary.inc" -include "gbt_player_bank1.inc" \ No newline at end of file +INCLUDE "Audio.inc" + +INCLUDE "theme.inc" diff --git a/range_test.s3m b/range_test.s3m index a55bcb2..8ca03c0 100644 Binary files a/range_test.s3m and b/range_test.s3m differ diff --git a/rangetest.inc b/rangetest.inc new file mode 100644 index 0000000..dafaae6 --- /dev/null +++ b/rangetest.inc @@ -0,0 +1,672 @@ +; File created by shoofle's s3m2gbt edit + +rangetest_0: + db $00, $00, +db $11, $00, +db $21, $0F, +db $31, $40, +db $22, $00, +db $23, $00, +db $14, $18, +db $24, $0F, +db $34, $00, + + db $0F, $01, +db $84, $00, + + db $0F, $02, +db $21, $00, + + db $0F, $03, + + db $0F, $04, +db $11, $02, +db $21, $0E, +db $31, $C0, +db $14, $18, +db $24, $0F, +db $34, $00, + + db $0F, $05, +db $84, $00, + + db $0F, $06, +db $21, $00, + + db $0F, $07, + + db $0F, $08, +db $11, $04, +db $21, $0C, +db $31, $C0, +db $14, $18, +db $24, $0F, +db $34, $00, + + db $0F, $09, +db $84, $00, + + db $0F, $0A, +db $21, $00, + + db $0F, $0B, + + db $0F, $0C, +db $11, $06, +db $21, $0A, +db $31, $C0, +db $14, $18, +db $24, $0F, +db $34, $00, + + db $0F, $0D, +db $84, $00, + + db $0F, $0E, +db $21, $09, + + db $0F, $0F, + + db $0F, $10, +db $11, $08, +db $21, $08, +db $31, $C0, +db $14, $18, +db $24, $0F, +db $34, $00, + + db $0F, $11, +db $84, $00, + + db $0F, $12, +db $21, $07, + + db $0F, $13, + + db $0F, $14, +db $11, $0A, +db $21, $06, +db $31, $C0, +db $14, $18, +db $24, $0F, +db $34, $00, + + db $0F, $15, +db $84, $00, + + db $0F, $16, +db $11, $0B, +db $21, $05, +db $31, $C0, + + db $0F, $17, + + db $0F, $18, +db $11, $0C, +db $21, $04, +db $31, $C0, +db $14, $18, +db $24, $0F, +db $34, $00, + + db $0F, $19, +db $84, $00, + + db $0F, $1A, +db $11, $0D, +db $21, $03, +db $31, $C0, + + db $0F, $1B, + + db $0F, $1C, +db $11, $0E, +db $21, $02, +db $31, $C0, +db $14, $18, +db $24, $0F, +db $34, $00, + + db $0F, $1D, +db $84, $00, + + db $0F, $1E, +db $11, $0F, +db $21, $01, +db $31, $C0, + + db $0F, $1F, + + db $0F, $20, +db $11, $10, +db $21, $00, +db $31, $C0, +db $14, $18, +db $24, $0F, +db $34, $00, + + db $0F, $21, +db $84, $00, + + db $0F, $22, +db $11, $11, +db $21, $0F, +db $31, $C0, + + db $0F, $23, + + db $0F, $24, +db $11, $12, +db $21, $0F, +db $31, $C0, +db $14, $18, +db $24, $0F, +db $34, $00, + + db $0F, $25, +db $84, $00, + + db $0F, $26, +db $11, $13, +db $21, $0F, +db $31, $C0, + + db $0F, $27, + + db $0F, $28, +db $11, $14, +db $21, $0F, +db $31, $C0, +db $14, $18, +db $24, $0F, +db $34, $00, + + db $0F, $29, +db $84, $00, + + db $0F, $2A, +db $11, $15, +db $21, $0F, +db $31, $C0, + + db $0F, $2B, + + db $0F, $2C, +db $11, $16, +db $21, $0F, +db $31, $C0, +db $14, $18, +db $24, $0F, +db $34, $00, + + db $0F, $2D, +db $84, $00, + + db $0F, $2E, +db $11, $17, +db $21, $0F, +db $31, $C0, + + db $0F, $2F, + + db $0F, $30, +db $11, $18, +db $21, $0F, +db $31, $C0, +db $14, $18, +db $24, $0F, +db $34, $00, + + db $0F, $31, +db $84, $00, + + db $0F, $32, +db $11, $19, +db $21, $0F, +db $31, $C0, + + db $0F, $33, + + db $0F, $34, +db $11, $1A, +db $21, $0F, +db $31, $C0, +db $14, $18, +db $24, $0F, +db $34, $00, + + db $0F, $35, +db $84, $00, + + db $0F, $36, +db $11, $1B, +db $21, $0F, +db $31, $C0, + + db $0F, $37, + + db $0F, $38, +db $11, $1C, +db $21, $0F, +db $31, $C0, +db $14, $18, +db $24, $0F, +db $34, $00, + + db $0F, $39, +db $84, $00, + + db $0F, $3A, +db $11, $1D, +db $21, $0F, +db $31, $C0, + + db $0F, $3B, + + db $0F, $3C, +db $11, $1E, +db $21, $0F, +db $31, $C0, +db $14, $18, +db $24, $0F, +db $34, $00, + + db $0F, $3D, +db $84, $00, + + db $0F, $3E, +db $11, $1F, +db $21, $0F, +db $31, $C0, + + db $0F, $3F, + +rangetest_1: + db $00, $00, +db $11, $20, +db $21, $0F, +db $31, $C0, +db $22, $00, +db $23, $00, +db $24, $00, + + db $0F, $01, + + db $0F, $02, +db $11, $21, +db $21, $0F, +db $31, $C0, + + db $0F, $03, + + db $0F, $04, +db $11, $22, +db $21, $0F, +db $31, $C0, + + db $0F, $05, + + db $0F, $06, +db $11, $23, +db $21, $0F, +db $31, $C0, + + db $0F, $07, + + db $0F, $08, +db $11, $24, +db $21, $0F, +db $31, $C0, + + db $0F, $09, + + db $0F, $0A, +db $11, $25, +db $21, $0F, +db $31, $C0, + + db $0F, $0B, + + db $0F, $0C, +db $11, $26, +db $21, $0F, +db $31, $C0, + + db $0F, $0D, + + db $0F, $0E, +db $11, $27, +db $21, $0F, +db $31, $C0, + + db $0F, $0F, + + db $0F, $10, +db $11, $28, +db $21, $0F, +db $31, $C0, + + db $0F, $11, + + db $0F, $12, +db $11, $29, +db $21, $0F, +db $31, $C0, + + db $0F, $13, + + db $0F, $14, +db $11, $2A, +db $21, $0F, +db $31, $C0, + + db $0F, $15, + + db $0F, $16, +db $11, $2B, +db $21, $0F, +db $31, $C0, + + db $0F, $17, + + db $0F, $18, +db $11, $2C, +db $21, $0F, +db $31, $C0, + + db $0F, $19, + + db $0F, $1A, +db $11, $2D, +db $21, $0F, +db $31, $C0, + + db $0F, $1B, + + db $0F, $1C, +db $11, $2E, +db $21, $0F, +db $31, $C0, + + db $0F, $1D, + + db $0F, $1E, +db $11, $2F, +db $21, $0F, +db $31, $C0, + + db $0F, $1F, + + db $0F, $20, +db $11, $30, +db $21, $0F, +db $31, $C0, + + db $0F, $21, + + db $0F, $22, +db $11, $31, +db $21, $0F, +db $31, $C0, + + db $0F, $23, + + db $0F, $24, +db $11, $32, +db $21, $0F, +db $31, $C0, + + db $0F, $25, + + db $0F, $26, +db $11, $33, +db $21, $0F, +db $31, $C0, + + db $0F, $27, + + db $0F, $28, +db $11, $34, +db $21, $0F, +db $31, $C0, + + db $0F, $29, + + db $0F, $2A, +db $11, $35, +db $21, $0F, +db $31, $C0, + + db $0F, $2B, + + db $0F, $2C, +db $11, $36, +db $21, $0F, +db $31, $C0, + + db $0F, $2D, + + db $0F, $2E, +db $11, $37, +db $21, $0F, +db $31, $C0, + + db $0F, $2F, + + db $0F, $30, +db $11, $38, +db $21, $0F, +db $31, $C0, + + db $0F, $31, + + db $0F, $32, +db $11, $39, +db $21, $0F, +db $31, $C0, + + db $0F, $33, + + db $0F, $34, +db $11, $3A, +db $21, $0F, +db $31, $C0, + + db $0F, $35, + + db $0F, $36, +db $11, $3B, +db $21, $0F, +db $31, $C0, + + db $0F, $37, + + db $0F, $38, +db $11, $3C, +db $21, $0F, +db $31, $C0, + + db $0F, $39, + + db $0F, $3A, +db $11, $3D, +db $21, $0F, +db $31, $C0, + + db $0F, $3B, + + db $0F, $3C, +db $11, $3E, +db $21, $0F, +db $31, $C0, + + db $0F, $3D, + + db $0F, $3E, +db $11, $3F, +db $21, $0F, +db $31, $C0, + + db $0F, $3F, + +rangetest_2: + db $00, $00, +db $11, $40, +db $21, $0B, +db $31, $80, +db $22, $00, +db $23, $00, +db $24, $00, + + db $0F, $01, + + db $0F, $02, +db $11, $41, +db $21, $0B, +db $31, $80, + + db $0F, $03, + + db $0F, $04, +db $11, $42, +db $21, $0B, +db $31, $80, + + db $0F, $05, + + db $0F, $06, +db $11, $43, +db $21, $0B, +db $31, $80, + + db $0F, $07, + + db $0F, $08, +db $11, $44, +db $21, $0B, +db $31, $80, + + db $0F, $09, + + db $0F, $0A, +db $11, $45, +db $21, $0B, +db $31, $80, + + db $0F, $0B, + + db $0F, $0C, +db $11, $46, +db $21, $0B, +db $31, $80, + + db $0F, $0D, + + db $0F, $0E, +db $11, $47, +db $21, $0B, +db $31, $80, + + db $0F, $0F, + + db $0F, $10, + + db $0F, $11, + + db $0F, $12, + + db $0F, $13, + + db $0F, $14, + + db $0F, $15, + + db $0F, $16, + + db $0F, $17, + + db $0F, $18, + + db $0F, $19, + + db $0F, $1A, + + db $0F, $1B, + + db $0F, $1C, + + db $0F, $1D, + + db $0F, $1E, + + db $0F, $1F, + + db $0F, $20, + + db $0F, $21, + + db $0F, $22, + + db $0F, $23, + + db $0F, $24, + + db $0F, $25, + + db $0F, $26, + + db $0F, $27, + + db $0F, $28, + + db $0F, $29, + + db $0F, $2A, + + db $0F, $2B, + + db $0F, $2C, + + db $0F, $2D, + + db $0F, $2E, + + db $0F, $2F, + + db $0F, $30, + + db $0F, $31, + + db $0F, $32, + + db $0F, $33, + + db $0F, $34, + + db $0F, $35, + + db $0F, $36, + + db $0F, $37, + + db $0F, $38, + + db $0F, $39, + + db $0F, $3A, + + db $0F, $3B, + + db $0F, $3C, + + db $0F, $3D, + + db $0F, $3E, + + db $0F, $3F, + +rangetest: + db 4 + dw rangetest_0 + dw rangetest_1 + dw rangetest_2 diff --git a/s3m2gbt.py b/s3m2gbt.py index 71d74c6..0ba7e82 100755 --- a/s3m2gbt.py +++ b/s3m2gbt.py @@ -185,21 +185,23 @@ class S3MFile(S3MFormatReader): if self.read_string(4) != b'SCRM': raise S3MFormatError("Invalid magic string in file") - self.read_ptr += 1 # Ignore global volume + self.global_volume = self.read_u8() self.initial_speed = self.read_u8() if self.read_u8() != 150: raise S3MFormatError("Invalid tempo: It must be 150") - self.read_ptr += 2 # Ignore master volume and ultraclick removal + self.master_volume = self.read_u8() & 0b00111111 # master volume + + self.read_ptr += 1 # Ignore ultraclick removal # Save this for later has_custom_pan = False if self.read_u8() == 252: has_custom_pan = True - self.read_ptr = 0x40 + self.read_ptr = 0x40 # jump forward to uint8[32] channelSettings channel_settings = self.read_string(4) if channel_settings[0] >= 16 or channel_settings[1] >= 16 or \ channel_settings[2] >= 16 or channel_settings[3] >= 16: @@ -207,7 +209,7 @@ class S3MFile(S3MFormatReader): # Read orders - self.read_ptr = 0x60 + self.read_ptr = 0x60 # jump forward to uint8[orderCount] orderList self.song_orders = self.read_string(self.song_length) if self.song_length % 2 == 1: @@ -258,14 +260,14 @@ class S3MFile(S3MFormatReader): self.data = [] # Channels 1, 2, 4 -def s3m_volume_to_gb(s3m_vol): +def s3m_volume_to_gb(s3m_vol): # this is identical to mod files. if s3m_vol >= 64: return 15 else: return s3m_vol >> 2; # Channel 3 -def s3m_volume_to_gb_ch3(s3m_vol): +def s3m_volume_to_gb_ch3(s3m_vol): # also identicll to mod files vol = s3m_volume_to_gb(s3m_vol) if vol >= 0 and vol <= 3: @@ -281,7 +283,7 @@ def s3m_volume_to_gb_ch3(s3m_vol): else: return 0 -def s3m_note_to_gb(note): +def s3m_note_to_gb(note): # Note cut with ^^ if note == 0xFE: return 0xFE @@ -334,22 +336,25 @@ EFFECT_EVENT = 15 # the channel (like panning). def effect_s3m_to_gb(channel, effectnum, effectparams): - if effectnum == 'A': # Set Speed + if effectnum == 'A': # Set Speed. compatible + if effectparams > 0x1F: + raise RowConversionError("Unsupported BPM speed effect") + if effectparams == 0: raise RowConversionError("Speed must not be zero") - return (EFFECT_SPEED, effectparams) + return (EFFECT_SPEED, effectparams) - if effectnum == 'B': # Pattern jump + if effectnum == 'B': # Pattern jump compatible # TODO: Fail if this jumps out of bounds return (EFFECT_PATTERN_JUMP, effectparams) - elif effectnum == 'C': # Break + Set row + elif effectnum == 'C': # Break + Set row compatiblle # Effect value is BCD, convert to integer val = (((effectparams & 0xF0) >> 4) * 10) + (effectparams & 0x0F) return (EFFECT_BREAK_SET_STEP, val) - elif effectnum == 'D': # Volume Slide + elif effectnum == 'D': # Volume Slide not present in .mod if channel == 3: raise RowConversionError("Volume slide not supported in channel 3") @@ -394,14 +399,15 @@ def effect_s3m_to_gb(channel, effectnum, effectparams): subeffectnum = (effectparams & 0xF0) >> 4 subeffectparams = effectparams & 0x0F - if subeffectnum == 0x8: # Pan position + if subeffectnum == 0x8: # Pan position compatible val = s3m_pan_to_gb(subeffectparams, channel) return (EFFECT_PAN, val) - elif subeffectnum == 0xC: # Notecut + elif subeffectnum == 0xC: # Notecut compatible + print(f"fofund a note cut, {effectnum}, {subeffectnum}, {subeffectparams}") return (EFFECT_NOTE_CUT, subeffectparams) - elif subeffectnum == 0xF: # Funkrepeat? Set active macro? + elif subeffectnum == 0xF: # Funkrepeat? Set active macro? not present in .mod # This effect is either unused, or it's the "set active macro" # command, which doesn't have any effect if you don't use the macro # afterwards. It can safely be overloaded for event callbacks. @@ -409,167 +415,86 @@ def effect_s3m_to_gb(channel, effectnum, effectparams): raise RowConversionError(f"Unsupported effect: {effectnum}{effectparams:02X}") -HAS_VOLUME = 1 << 4 -HAS_INSTRUMENT = 1 << 5 -HAS_EFFECT = 1 << 6 +HAS_VOLUME = 1 << 5 # changing these to be compatible with old gbt +HAS_DRUM_EFFECT = 1 << 6 +HAS_EFFECT = 1 << 7 HAS_NOTE = 1 << 7 HAS_KIT = 1 << 7 -def convert_channel1(note_index, samplenum, volume, effectnum, effectparams): - command = [ 0, 0, 0, 0 ] # NOP - command_ptr = 1 +def convert_channel(channel, note_index, samplenum, volume, effectnum, effectparams): + #print(f"{channel}: {note_index}, using {samplenum} @ volume {volume}") + if channel == 4: + return convert_channel4(note_index, samplenum, volume, effectnum, effectparams) + + command = [ 0, 0, 0 ] # NOP + command_len = 1 + + if channel == 3: + shifted_instrument = (samplenum) << 7 + converted_volume = s3m_volume_to_gb_ch3(volume) + else: + shifted_instrument = (samplenum & 3) << 4 + converted_volume = s3m_volume_to_gb(volume) # Check if it's needed to add a note if note_index != -1: - note_index = s3m_note_to_gb(note_index) - command[0] |= HAS_NOTE - command[command_ptr] = note_index - command_ptr = command_ptr + 1 + command[0] = HAS_NOTE | note_index + command[1] = shifted_instrument | converted_volume + command_len = 2 - # Check if there is a sample defined - if samplenum > 0: - instrument = samplenum & 3 + if effectnum is not None: + [num, params] = effect_s3m_to_gb(channel, effectnum, effectparams) + command[1] = HAS_EFFECT | shifted_instrument | num + command[2] = params + command_len = 3 + else: + command[0] = HAS_VOLUME | converted_volume + command_len = 1 - command[0] |= HAS_INSTRUMENT - command[command_ptr] = (instrument << 4) & 0x30 + if effectnum is not None: + [num, params] = effect_s3m_to_gb(channel, effectnum, effectparams) + command[1] = HAS_EFFECT | shifted_instrument | num + command[2] = params + command_len = 3 + + return command[:command_len] - if effectnum is not None: - [num, params] = effect_s3m_to_gb(1, effectnum, effectparams) - - if num is not None: - command[0] |= HAS_EFFECT - command[command_ptr] |= num & 0x0F - command_ptr += 1 - command[command_ptr] = params & 0xFF - - # Check if it's needed to add a volume - if volume > -1: - command[0] |= HAS_VOLUME - command[0] |= s3m_volume_to_gb(volume) & 0x0F - - # Note: The volume bit doesn't affect the final size. - sizes = [ 1, 2, 3, 3, 2, 3, 4, 4 ] - command_size = sizes[command[0] >> 5] - - return command[:command_size] - -def convert_channel2(note_index, samplenum, volume, effectnum, effectparams): - command = [ 0, 0, 0, 0 ] # NOP - command_ptr = 1 - - # Check if it's needed to add a note - if note_index != -1: - note_index = s3m_note_to_gb(note_index) - command[0] |= HAS_NOTE - command[command_ptr] = note_index - command_ptr = command_ptr + 1 - - # Check if there is a sample defined - if samplenum > 0: - instrument = samplenum & 3 - - command[0] |= HAS_INSTRUMENT - command[command_ptr] = (instrument << 4) & 0x30 - - if effectnum is not None: - [num, params] = effect_s3m_to_gb(2, effectnum, effectparams) - - if num is not None: - command[0] |= HAS_EFFECT - command[command_ptr] |= num & 0x0F - command_ptr += 1 - command[command_ptr] = params & 0xFF - - # Check if it's needed to add a volume - if volume > -1: - command[0] |= HAS_VOLUME - command[0] |= s3m_volume_to_gb(volume) & 0x0F - - # Note: The volume bit doesn't affect the final size. - sizes = [ 1, 2, 3, 3, 2, 3, 4, 4 ] - command_size = sizes[command[0] >> 5] - - return command[:command_size] - -def convert_channel3(note_index, samplenum, volume, effectnum, effectparams): - command = [ 0, 0, 0, 0 ] # NOP - command_ptr = 1 - - # Check if it's needed to add a note - if note_index != -1: - note_index = s3m_note_to_gb(note_index) - command[0] |= HAS_NOTE - command[command_ptr] = note_index - command_ptr = command_ptr + 1 - - # Check if there is a sample defined - if samplenum > 0: - instrument = samplenum & 7 - - command[0] |= HAS_INSTRUMENT - command[command_ptr] = (instrument << 4) & 0xF0 - - if effectnum is not None: - [num, params] = effect_s3m_to_gb(3, effectnum, effectparams) - - if num is not None: - command[0] |= HAS_EFFECT - command[command_ptr] |= num & 0x0F - command_ptr += 1 - command[command_ptr] = params & 0xFF - - # Check if it's needed to add a volume - if volume > -1: - command[0] |= HAS_VOLUME - command[0] |= s3m_volume_to_gb_ch3(volume) & 0x0F - - # Note: The volume bit doesn't affect the final size. - sizes = [ 1, 2, 3, 3, 2, 3, 4, 4 ] - command_size = sizes[command[0] >> 5] - - return command[:command_size] def convert_channel4(note_index, samplenum, volume, effectnum, effectparams): - command = [ 0, 0, 0, 0 ] # NOP - command_ptr = 1 + command = [ 0, 0, 0 ] # NOP + command_len = 1 + #print(f"we found a note with index {note_index}") # Note cut using ^^ as note - if note_index == 0xFE: + if note_index == 169 or note_index == -1: if samplenum > 0: # This limitation is only for channel 4. It should never happen in a # regular song. raise("Note cut + Sample in same row: Not supported in channel 4") samplenum = 0xFE - # Check if there is a sample defined - if samplenum > 0: - if samplenum == 0xFE: - kit = 0xFE; - else: - kit = samplenum & 0xF; - command[0] |= HAS_KIT - command[command_ptr] = kit - command_ptr += 1 + if note_index != 169 and note_index != -1 and samplenum > 0: + command[0] = HAS_KIT | (samplenum & 0xF) + command[1] = s3m_volume_to_gb(volume) & 0xF + command_len = 2 + else: + if note_index == 169: + command[0] = HAS_DRUM_EFFECT | EFFECT_NOTE_CUT + command[1] = 1 # 0 ticks + command_len = 2 + elif effectnum is not None: + [num, params] = effect_s3m_to_gb(4, effectnum, effectparams) - if effectnum is not None: - [num, params] = effect_s3m_to_gb(4, effectnum, effectparams) + if num is not None: + command[0] = HAS_DRUM_EFFECT | (num & 0x0F) + command[1] = (params & 0xFF) | 1 + command_len = 2 + elif volume > -1: + #command[0] = HAS_VOLUME | (s3m_volume_to_gb(volume) & 0xF) + command[0] = 0 + command_len = 1 - if num is not None: - command[0] |= HAS_EFFECT - command[command_ptr] |= num & 0x0F - command_ptr += 1 - command[command_ptr] = params & 0xFF - - # Check if it's needed to add a volume - if volume > -1: - command[0] |= HAS_VOLUME - command[0] |= s3m_volume_to_gb(volume) & 0x0F - - # Note: The volume bit doesn't affect the final size. - sizes = [ 1, 2, 3, 3, 2, 3, 4, 4 ] - command_size = sizes[command[0] >> 5] - - return command[:command_size] + return command[:command_len] STARTUP_CMD_DONE = 0 STARTUP_CMD_SPEED = 1 @@ -685,7 +610,8 @@ def convert_file(module_path, song_name, output_path, export_instruments): cmd = cmd1 + cmd2 + cmd3 + cmd4 for b in cmd: - fileout.write(f"${b:02X},") + if b == -1: fileout.write(f"$FF, ") + else: fileout.write(f"${b:02X},") fileout.write("\n") @@ -707,7 +633,10 @@ def convert_file(module_path, song_name, output_path, export_instruments): note = -1 instrument = 0 if c.has_note_and_instrument: - note = c.note + note = c.note - 0b0010_0001 # note indices should start from 0=C3 + note = note + 1 # s3m note values go 00..0A, 0F, 10..1A, 1F, etc. + note = (note // 16) * 12 + (note % 16) #these expressions compensate for it. + note = note - 1 instrument = c.instrument # Rows with note and instrument but no volume use the @@ -727,17 +656,13 @@ def convert_file(module_path, song_name, output_path, export_instruments): try: if channel == 1: - cmd1 = convert_channel1(note, instrument, volume, - effectnum, effectparams) + cmd1 = convert_channel(channel, note, instrument, volume, effectnum, effectparams) elif channel == 2: - cmd2 = convert_channel2(note, instrument, volume, - effectnum, effectparams) + cmd2 = convert_channel(channel, note, instrument, volume, effectnum, effectparams) elif channel == 3: - cmd3 = convert_channel3(note, instrument, volume, - effectnum, effectparams) + cmd3 = convert_channel(channel, note, instrument, volume, effectnum, effectparams) elif channel == 4: - cmd4 = convert_channel4(note, instrument, volume, - effectnum, effectparams) + cmd4 = convert_channel(channel, note, instrument, volume, effectnum, effectparams) else: raise S3MFormatError(f"Too many channels: {channel}") except RowConversionError as e: diff --git a/s3m2shoofmt.py b/s3m2shoofmt.py index d7f03a8..3c6cb48 100644 --- a/s3m2shoofmt.py +++ b/s3m2shoofmt.py @@ -290,6 +290,7 @@ def s3m_volume_to_gb(s3m_vol): if s3m_vol >= 64: return 15 else: + print(f"found a decreased volume: {s3m_vol}, returning {s3m_vol>>2}") return s3m_vol >> 2; # Channel 3 @@ -297,28 +298,30 @@ def s3m_volume_to_gb_ch3(s3m_vol): vol = s3m_volume_to_gb(s3m_vol) if vol >= 0 and vol <= 3: - return 0 # 0% + return 0<<1 # 0% elif vol >= 4 and vol <= 6: - return 3 # 25% + return 3<<1 # 25% elif vol >= 7 and vol <= 9: - return 2 # 50% + return 2<<1 # 50% elif vol >= 10 and vol <= 12: - return 4 # 75% + return 1<<1 # 75% elif vol >= 13 and vol <= 15: - return 1 # 100% + return 1<<1 # 100% else: return 0 def s3m_note_to_gb(note): # Note cut with ^^ if note == 0xFE: + print(f"note cut found: {note}") return 0xFE if note == 0xFF: + print(f"note cut found: {note}") return 0xFF # Note off and ^^ note cut should be handled before reaching this point #note = note & 0x7F - if note > 0x7F: + if note > 0x7F or note < 0: print(note) assert note <= 0x7F @@ -433,6 +436,7 @@ def effect_s3m_to_gb(channel, effectnum, effectparams): return (EFFECT_PAN, val) elif subeffectnum == 0xC: # Notecut + print(f"found a note cut! with params {subeffectparams}") return (EFFECT_NOTE_CUT, subeffectparams) elif subeffectnum == 0xF: # Funkrepeat? Set active macro? @@ -447,19 +451,27 @@ def convert_channel(channel, note_index, samplenum, volume, effectnum, effectpar commands = [] # Check if it's needed to add a note - if note_index != -1 and note_index != 0xFF and note_index != 0xFE: + if note_index != -1 and note_index != 0xFF and note_index != 0xFE and note_index != 169: note_index = s3m_note_to_gb(note_index) commands.append([0x10 | channel, note_index]) - if note_index == 0xFF or note_index == 0xFE: - commands.append([0x80 | channel, note_index]) + if note_index == 0xFF or note_index == 0xFE or note_index == 169: + print(f"found a note cut by note value: {note_index}") + commands.append([0x80 | channel, 0]) if volume > -1: + print(channel) + print(f"converting volume {volume} to {s3m_volume_to_gb(volume) & 0x0F}") commands.append([0x20 | channel, s3m_volume_to_gb(volume) & 0x0F]) + print(commands) # Check if there is a sample defined if samplenum > 0: - instrument = samplenum & 3 - commands.append([0x30 | channel, instrument << 6]) + if channel == 1 or channel == 2: + commands.append([0x30 | channel, (samplenum & 3) << 6]) + if channel == 3: + commands.append([0x30 | channel, samplenum & 7]) + if channel == 4: + commands.append([0x30 | channel, samplenum & 15]) if effectnum is not None: [num, params] = effect_s3m_to_gb(1, effectnum, effectparams) @@ -583,7 +595,7 @@ def convert_file(module_path, song_name, output_path, export_instruments): fileout.write(f"{song_name}:\n") - fileout.write(f"\tdb {len(s3m.song_orders)}\n") + fileout.write(f"\tdb {len(s3m.song_orders)-1}\n") for o in s3m.song_orders: pattern = int(o) if pattern >= s3m.num_patterns: diff --git a/source.zip b/source.zip index dde3c62..64ecc98 100644 Binary files a/source.zip and b/source.zip differ diff --git a/theme.inc b/theme.inc index 5a995e8..ae0abff 100644 --- a/theme.inc +++ b/theme.inc @@ -1,182 +1,309 @@ ; File created by shoofle's s3m2gbt edit -gbtarottheme_0: +gb_tarot_theme_0: db $00, $00, -db $11, $0C, +db $11, $00, db $21, $0F, db $31, $40, -db $22, $00, +db $12, $18, +db $22, $04, +db $32, $40, db $23, $00, -db $24, $00, +db $14, $18, +db $24, $0F, +db $34, $08, db $0F, $01, +db $84, $00, db $0F, $02, -db $11, $0C, +db $11, $00, db $21, $0F, db $31, $80, +db $12, $1C, +db $22, $04, +db $32, $40, db $0F, $03, db $0F, $04, -db $11, $0C, +db $11, $00, db $21, $0F, db $31, $C0, +db $12, $1F, +db $22, $04, +db $32, $40, +db $14, $18, +db $24, $0F, +db $34, $0B, db $0F, $05, +db $84, $00, db $0F, $06, -db $81, $FE, +db $81, $00, +db $12, $18, +db $22, $04, +db $32, $40, db $0F, $07, db $0F, $08, +db $12, $1C, +db $22, $04, +db $32, $40, +db $13, $26, +db $23, $0F, +db $33, $01, +db $14, $18, +db $24, $0F, +db $34, $0B, db $0F, $09, +db $84, $00, db $0F, $0A, +db $12, $1F, +db $22, $04, +db $32, $40, db $0F, $0B, db $0F, $0C, -db $11, $0C, +db $11, $00, db $21, $0F, db $31, $00, +db $12, $18, +db $22, $04, +db $32, $40, +db $13, $24, +db $23, $0F, +db $33, $00, +db $14, $18, +db $24, $0F, +db $34, $0B, db $0F, $0D, +db $84, $00, db $0F, $0E, -db $11, $0C, +db $11, $00, db $21, $0F, db $31, $00, +db $12, $1C, +db $22, $04, +db $32, $40, db $0F, $0F, db $0F, $10, -db $11, $10, +db $11, $04, db $21, $0F, db $31, $40, +db $12, $1C, +db $22, $04, +db $32, $40, +db $13, $21, +db $23, $0F, +db $33, $00, +db $14, $18, +db $24, $0F, +db $34, $08, db $0F, $11, +db $84, $00, db $0F, $12, -db $11, $10, +db $11, $04, db $21, $0F, db $31, $80, +db $12, $1F, +db $22, $04, +db $32, $40, db $0F, $13, db $0F, $14, -db $11, $10, +db $11, $04, db $21, $0F, db $31, $C0, +db $12, $23, +db $22, $04, +db $32, $40, +db $14, $18, +db $24, $0F, +db $34, $0B, db $0F, $15, +db $84, $00, db $0F, $16, -db $81, $FE, +db $81, $00, +db $12, $1C, +db $22, $04, +db $32, $40, db $0F, $17, db $0F, $18, +db $12, $1F, +db $22, $04, +db $32, $40, +db $14, $18, +db $24, $0F, +db $34, $0B, db $0F, $19, +db $84, $00, db $0F, $1A, +db $12, $23, +db $22, $04, +db $32, $40, db $0F, $1B, db $0F, $1C, -db $11, $10, +db $11, $04, db $21, $0F, db $31, $00, +db $12, $1C, +db $22, $04, +db $32, $40, +db $14, $18, +db $24, $0F, +db $34, $0B, db $0F, $1D, +db $84, $00, db $0F, $1E, -db $11, $10, +db $11, $04, db $21, $0F, db $31, $00, +db $12, $1F, +db $22, $04, +db $32, $40, db $0F, $1F, db $0F, $20, -db $11, $12, +db $11, $06, db $21, $0F, db $31, $40, +db $12, $1F, +db $22, $03, +db $32, $40, +db $13, $28, +db $23, $0F, +db $33, $01, +db $14, $18, +db $24, $0F, +db $34, $08, db $0F, $21, +db $84, $00, db $0F, $22, -db $11, $12, +db $11, $06, db $21, $0F, db $31, $80, db $0F, $23, db $0F, $24, -db $11, $12, +db $11, $06, db $21, $0F, db $31, $C0, +db $22, $03, +db $14, $18, +db $24, $0F, +db $34, $0B, db $0F, $25, +db $84, $00, db $0F, $26, -db $81, $FE, +db $81, $00, db $0F, $27, db $0F, $28, +db $22, $02, +db $14, $18, +db $24, $0F, +db $34, $0B, db $0F, $29, +db $84, $00, db $0F, $2A, db $0F, $2B, db $0F, $2C, -db $11, $12, +db $11, $06, db $21, $0F, db $31, $00, +db $22, $02, +db $14, $18, +db $24, $0F, +db $34, $0B, db $0F, $2D, +db $84, $00, db $0F, $2E, -db $11, $12, +db $11, $06, db $21, $0F, db $31, $00, db $0F, $2F, db $0F, $30, -db $11, $11, +db $11, $05, db $21, $0F, db $31, $40, +db $22, $01, +db $14, $18, +db $24, $0F, +db $34, $08, db $0F, $31, +db $84, $00, db $0F, $32, -db $11, $11, +db $11, $05, db $21, $0F, db $31, $80, db $0F, $33, db $0F, $34, -db $11, $11, +db $11, $05, db $21, $0F, db $31, $C0, +db $22, $01, +db $14, $18, +db $24, $0F, +db $34, $0B, db $0F, $35, +db $84, $00, db $0F, $36, -db $81, $FE, +db $81, $00, db $0F, $37, db $0F, $38, +db $22, $00, +db $14, $18, +db $24, $0F, +db $34, $0B, db $0F, $39, +db $84, $00, db $0F, $3A, @@ -186,8 +313,13 @@ db $81, $FE, db $11, $11, db $21, $0F, db $31, $00, +db $22, $00, +db $14, $18, +db $24, $0F, +db $34, $0B, db $0F, $3D, +db $84, $00, db $0F, $3E, db $11, $11, @@ -196,8 +328,8 @@ db $31, $00, db $0F, $3F, -gbtarottheme: - db 4 - dw gbtarottheme_0 - dw gbtarottheme_0 - dw gbtarottheme_0 +gb_tarot_theme: + db 3 + dw gb_tarot_theme_0 + dw gb_tarot_theme_0 + dw gb_tarot_theme_0