got frustrated, wrote an audio engine

This commit is contained in:
Shoofle 2025-04-07 12:20:57 -04:00
parent f3a852edc3
commit 45ca20d569
11 changed files with 2170 additions and 737 deletions

1103
Audio.inc

File diff suppressed because it is too large Load Diff

335
gb_tarot_theme.inc Normal file
View File

@ -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

Binary file not shown.

262
gb_tarot_theme1.inc Normal file
View File

@ -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

View File

@ -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"
INCLUDE "Audio.inc"
INCLUDE "theme.inc"

Binary file not shown.

672
rangetest.inc Normal file
View File

@ -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

View File

@ -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:
@ -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)
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
# Check if there is a sample defined
if samplenum > 0:
instrument = samplenum & 3
command[0] |= HAS_INSTRUMENT
command[command_ptr] = (instrument << 4) & 0x30
command[0] = HAS_NOTE | note_index
command[1] = shifted_instrument | converted_volume
command_len = 2
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
[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
if effectnum is not None:
[num, params] = effect_s3m_to_gb(2, effectnum, effectparams)
[num, params] = effect_s3m_to_gb(channel, effectnum, effectparams)
command[1] = HAS_EFFECT | shifted_instrument | num
command[2] = params
command_len = 3
if num is not None:
command[0] |= HAS_EFFECT
command[command_ptr] |= num & 0x0F
command_ptr += 1
command[command_ptr] = params & 0xFF
return command[:command_len]
# 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;
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:
kit = samplenum & 0xF;
command[0] |= HAS_KIT
command[command_ptr] = kit
command_ptr += 1
if effectnum is not None:
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 num is not None:
command[0] |= HAS_EFFECT
command[command_ptr] |= num & 0x0F
command_ptr += 1
command[command_ptr] = params & 0xFF
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
# 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:

View File

@ -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:

Binary file not shown.

192
theme.inc
View File

@ -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