123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706 |
- /*
- tiny menu system for snes by d4s in 2006
- depends on:
- printstring.asm, function: LoadTextString
- execute with:
- ldx.w #number_of_menu_file_to_load
- jsr LoadMenuFile
- features:
- -1 column, x rows
- -seperate bytes and bits manipulation
- -print text and menu options with palette highlighting
- -subroutine jump upon option change
- -load complete menu from table, no hardcoded stuff
- -menus tables should be compressable, relative pointers only!
- menu table format:
- byte function
- 2 starting position of first option text on bg3 tilemap
- 1 relative starting position of first option variable(*2+starting position of first option text on bg3 tilemap)
- 1 number of seperating rows between options
- 1 number of rows/options
- 2xrow quantity relative pointer to data for each row
- row table format:
- 1 option data type (maximum number:7)
- 0x0=no options, only exec subroutine
- 0x1=1 byte
- 0x2=8 bits
- 0x3=2 interchangeable options with description text (eg: "sound: mono/stereo)
- 1 bitmask for changeable bits if data type=0x2; bitmask(usually only one bit) to determine the string to choose if data type=0x3(if zero=string 1, if not zero=string 2)
- 1 minimum value for option, wrap to maximum value if changed value equals this
- 1 maximum value for option, wrap to minimum value if changed value equals this
- 3 24bit adress of option byte to change
- 1 number of subroutine to execute when option is changed(push status and registers before executing)
- 1 palette number when unselected
- 1 palette number when selected
- 1 number of option text strings(max=3, AND with 0x3)
- 2xstring quant. relative pointer to text string
- x option text string(s), #$00 terminated
- processing flow:
- 1. setup pointer to menu file
- 2. load all general menu options and save to variables
- 3. process and draw each option string onto screen once
- -setup pointer to row table
- -draw each option with corresponding option value once
- 4. go to first option
- -if up pressed, redraw current line in unselected, decrease current line, redraw new current line in selected
- -if down pressed, redraw current line in unselected, increase current line, redraw new current line in selected
-
- -if right pressed, increase options variable pointer
- -if left pressed, decrease options variable pointer
-
- data files:
- MenuFiles
- Pointer Tables
- MenuFilesPTable
- variables:
- MenuFileThreeBytePointerLo
- MenuFileThreeBytePointerHi
- MenuFileThreeBytePointerBank
- MenuRowsThreeBytePointerLo
- MenuRowsThreeBytePointerHi
- MenuRowsThreeBytePointerBank
- MenuRowsThreeByteOptionPointerLo
- MenuRowsThreeByteOptionPointerHi
- MenuRowsThreeByteOptionPointerBank
- MenuRowsThreeByteCodePointerLo
- MenuRowsThreeByteCodePointerHi
- MenuRowsThreeByteCodePointerBank
- LoadMenuInitialOffset
- LoadMenuInitialOptionOffset
- LoadMenuVerticalSpacing
- LoadMenuNumberOfRows
- LoadMenuCurrentRow
- LoadMenuStringPosLo
- ram areas:
- LoadMenuStringBuffer(16bytes)
- string printing area, 16 bytes:
- 0 - LoadMenuStringBuffer
- 1 - LoadMenuStringSetOff ;always #$01, set new position
- 2 - LoadMenuStringPosLo ;position of string
- 3 - LoadMenuStringPosHi
- 4 - LoadMenuStringSetPal ;always #$07, set palette
- 5 - LoadMenuStringPal ;palette number
- 6 - LoadMenuStringNewAddr ;draw variable length string, always #$04
- 7 - LoadMenuStringVectLo
- 8 - LoadMenuStringVectHi
- 9 - LoadMenuStringVectBa
- a - LoadMenuStringSetOff2
- b - LoadMenuStringPosLo2 ;position of string
- c - LoadMenuStringPosHi2
- d - LoadMenuStringByte/binary/string
- ;this is the textstring for the text buffer of the menu system
- TextString20:
- .dw $0000 ;offset on bg1 tilemap
- .db $04 ;terminator
- .dw LoadMenuStringBuffer
- .db $7e
- */
- LoadMenuFile:
- php
- sep #$20
- phb ;set data bank = wram
- lda.b #$7e
- pha
- plb
- lda.b LoadMenuDoInit ;check if menu was already initialized
- bne LoadMenuFileAlreadyInitialized
- lda #(:MenuFiles+BaseAdress>>16) ;get source bank of strings
- sta MenuFileThreeBytePointerBank ;
- rep #$30 ;accu 16bit
- txa ;get number of string
- asl ;multiply by 2 to get pointertable entry
- tax
- lda.l (MenuFilesPTable+BaseAdress),x ;get source offset of string
- sta MenuFileThreeBytePointerLo
- ldy.w #$0000
- lda [MenuFileThreeBytePointerLo],y ;get target buffer in wram
- iny ;increment source position, word
- iny
- and.w #$fffe ;mask off bit 0 to ensure text is word-formatted properly
- sta.b LoadMenuInitialOffset
- lda.b [MenuFileThreeBytePointerLo],y ;get option position
- iny
- clc
- sep #$20
- asl a
- sta.b LoadMenuInitialOptionOffset ;store in variable
- lda.b [MenuFileThreeBytePointerLo],y ;get vertical spacing position
- iny
- and.b #$0f ;maximum range:16
- inc a
- tax
- lda.b #$00
- LoadMenuCalcVerticalSpacingLoop:
- clc
- adc.b #$40
- dex
- bne LoadMenuCalcVerticalSpacingLoop ;add one tileline for every loop, but do it at least once
- sta.b LoadMenuVerticalSpacing
- lda.b [MenuFileThreeBytePointerLo],y ;get number of rows/options
- iny
- and.b #$1f ;maximum number:32
- bne LoadMenuNumberOfRowsNotZero
-
- plb ;exit if number of rows=0
- plp
- rts
-
- LoadMenuNumberOfRowsNotZero:
- sta.b LoadMenuNumberOfRows
- stz.b LoadMenuCurrentRow ;start processing at first row
- stz.b LoadMenuPalUnselSel ;draw unselected palette
-
- LoadMenuInitialOptionDrawLoop:
- jsr LoadMenuSetupRowPointer
- jsr LoadMenuDrawDescString
- jsr LoadMenuDrawOptionValue
- sep #$20
- lda.b LoadMenuCurrentRow
- inc a
- sta.b LoadMenuCurrentRow
- cmp.b LoadMenuNumberOfRows
- bne LoadMenuInitialOptionDrawLoop
- stz.b LoadMenuCurrentRow ;start at row 1
- inc.b LoadMenuDoInit ;store "menu initialized"
- lda.b #$01
- sta.b LoadMenuPalUnselSel ;draw first row highlighted
- jsr LoadMenuSetupRowPointer
- jsr LoadMenuDrawDescString
- jsr LoadMenuDrawOptionValue
- LoadMenuFileAlreadyInitialized:
- sep #$20
- jsr LoadMenuSetupRowPointer
- jsr LoadMenuDrawOptionValue
- rep #$31
- lda.w JoyPortBufferTrigger&$ffff
- ldx.w #$ffff ;clear number of loaded button-1
- LoadMenuFileCheckNextButton:
- inx
- cpx.w #$0010 ;check if all buttons have been checked
- beq LoadMenuFileCheckNextButtonDone
- lsr a ;start at button bit 0
- bcc LoadMenuFileCheckNextButton
-
- pha
- phx
- txa
- clc
- asl a
- tax
- jsr (LoadMenuFileCheckNextButtonJumpTbl,x)
-
- plx
- pla
- bra LoadMenuFileCheckNextButton
- LoadMenuFileCheckNextButtonDone:
- plb ;exit if number of rows=0
- plp
- rts
- LoadMenuFileCheckNextButtonJumpTbl:
- .dw LoadMenuButtonVoid
- .dw LoadMenuButtonVoid
- .dw LoadMenuButtonVoid
- .dw LoadMenuButtonVoid
- .dw LoadMenuButtonVoid ;r
- .dw LoadMenuButtonVoid ;l
- .dw LoadMenuButtonVoid ;x
- .dw LoadMenuExecuteSubroutine ;a
- .dw LoadMenuIncreaseOption ;right
- .dw LoadMenuDecreaseOption ;left
- .dw LoadMenuIncreaseRow ;down
- .dw LoadMenuDecreaseRow ;up
- .dw LoadMenuButtonVoid ;start
- .dw LoadMenuButtonVoid ;select
- .dw LoadMenuButtonVoid ;a
- .dw LoadMenuButtonVoid ;b
- .dw LoadMenuButtonVoid
- LoadMenuButtonVoid:
- rts
- LoadMenuIncreaseRow:
- php
- rep #$31
- sep #$20
- stz.b LoadMenuPalUnselSel ;draw current row unselected
- jsr LoadMenuSetupRowPointer
- jsr LoadMenuDrawDescString
- jsr LoadMenuDrawOptionValue
- lda.b LoadMenuCurrentRow
- inc a
- cmp.b LoadMenuNumberOfRows
- bcc LoadMenuIncreaseRowNoOverflow
- lda.b #$00 ;wrap around to zero if maximum number of options is reached
- LoadMenuIncreaseRowNoOverflow:
- sta.b LoadMenuCurrentRow
- lda.b #$01
- sta.b LoadMenuPalUnselSel ;draw current row
- jsr LoadMenuSetupRowPointer
- jsr LoadMenuDrawDescString
- jsr LoadMenuDrawOptionValue
- plp
- rts
- LoadMenuDecreaseRow:
- php
- rep #$31
- sep #$20
- stz.b LoadMenuPalUnselSel ;draw current row unselected
- jsr LoadMenuSetupRowPointer
- jsr LoadMenuDrawDescString
- jsr LoadMenuDrawOptionValue
- lda.b LoadMenuCurrentRow
- dec a
- bpl LoadMenuIncreaseRowNoOverflow
- lda.b LoadMenuNumberOfRows ;wrap around to highest row if minimum number of options is reached
- dec a
- LoadMenuDecreaseRowNoOverflow:
- sta.b LoadMenuCurrentRow
- lda.b #$01
- sta.b LoadMenuPalUnselSel ;draw current row
- jsr LoadMenuSetupRowPointer
- jsr LoadMenuDrawDescString
- jsr LoadMenuDrawOptionValue
- plp
- rts
- LoadMenuIncreaseOption:
- phy
- php
- rep #$31
- sep #$20
- jsr LoadMenuSetupRowPointer
- ldy.w #$0000
- lda.b [MenuRowsThreeBytePointerLo],y ;do nothing if were processing a subroutine-only option
- bne LoadMenuIncreaseOptionNoEnd
-
- plp
- ply
- rts
-
- LoadMenuIncreaseOptionNoEnd:
- ldy.w #$0000
- lda.b [MenuRowsThreeByteOptionPointerLo],y ;get byte, increase it and compare if its greater than the maximum value
- ldy.w #$0003
- cmp.b [MenuRowsThreeBytePointerLo],y
- bcc LoadMenuIncreaseOptionNoOverflow
-
- dey
- lda.b [MenuRowsThreeBytePointerLo],y ;get minimum value if wrap around
- dec a
-
- LoadMenuIncreaseOptionNoOverflow:
- ldy.w #$0000
- inc a
- sta.b [MenuRowsThreeByteOptionPointerLo],y ;save back changed value
- ; ldy.w #0
- lda.b [MenuRowsThreeBytePointerLo],y
- cmp.b #1
- bne LoadMenuIncNoByte ;only check for b if we're processing a byte-option
- lda.w JoyPortBufferTrigger&$ffff+1
- bpl LoadMenuIncNoByte
- clc
- lda.b [MenuRowsThreeByteOptionPointerLo],y ;save back changed value
- adc.b #$f ;add a whole nibble if b is pressed
- sta.b [MenuRowsThreeByteOptionPointerLo],y
- LoadMenuIncNoByte:
- lda.b #$01
- sta.b LoadMenuPalUnselSel ;redraw current option
- jsr LoadMenuDrawDescString
- jsr LoadMenuDrawOptionValue
- plp
- ply
- rts
- LoadMenuDecreaseOption:
- phy
- php
- rep #$31
- sep #$20
- jsr LoadMenuSetupRowPointer
- ldy.w #$0000
- lda.b [MenuRowsThreeBytePointerLo],y ;do nothing if were processing a subroutine-only option
- bne LoadMenuDecreaseOptionNoEnd
-
- plp
- ply
- rts
-
- LoadMenuDecreaseOptionNoEnd:
-
- ldy.w #$0000
- ; lda.b [MenuRowsThreeByteOptionPointerLo],y ;get byte, increase it and compare if its greater than the maximum value
- lda.b [MenuRowsThreeBytePointerLo],y
- cmp.b #1
- bne LoadMenuDecNoByte ;only check for b if we're processing a byte-option
- lda.w JoyPortBufferTrigger&$ffff+1
- bpl LoadMenuDecNoByte
- sec
- lda.b [MenuRowsThreeByteOptionPointerLo],y ;save back changed value
- sbc.b #$f ;add a whole nibble if b is pressed
- sta.b [MenuRowsThreeByteOptionPointerLo],y
- LoadMenuDecNoByte:
- lda.b [MenuRowsThreeByteOptionPointerLo],y ;get byte, increase it and compare if its greater than the maximum value
- dec a
-
- cmp.b #$ff
- beq LoadMenuDecreaseOptionOverflow
- ldy.w #$0002
- cmp.b [MenuRowsThreeBytePointerLo],y
- bcs LoadMenuDecreaseOptionNoOverflow
- LoadMenuDecreaseOptionOverflow:
- ldy.w #$0003
- lda.b [MenuRowsThreeBytePointerLo],y ;get minimum value if wrap around
-
- LoadMenuDecreaseOptionNoOverflow:
- ldy.w #$0000
- sta.b [MenuRowsThreeByteOptionPointerLo],y ;save back changed value
- lda.b #$01
- sta.b LoadMenuPalUnselSel ;redraw current option
- jsr LoadMenuDrawDescString
- jsr LoadMenuDrawOptionValue
- plp
- ply
- rts
- LoadMenuExecuteSubroutine:
- pha
- phy
- phx
- php
- phd
- phb
- rep #$31
- sep #$20
- lda.b #$7e
- pha
- plb
-
- ldy.w #0007
- lda.b [MenuRowsThreeBytePointerLo],y ;get number of subroutine to execute
- clc
- asl a
- tax
- jsr (MenuSubroutineLUT,x)
-
-
- plb
- pld
- plp
- plx
- ply
- pla
- rts
-
-
-
-
- MenuDataTypeVoid:
- MenuDataType0:
- rts ;no action if theres no string to draw
- MenuDataType1:
- phx
- phy
- php
- rep #$31
- lda.b LoadMenuInitialOptionOffset ;get relative offset of option
- and.w #$00ff
- adc.b LoadMenuStringPosLo ;add offset of current row
- sta.w LoadMenuStringBuffer&$ffff+1 ;store in string position
- ldy.w #$0004
- lda.b [MenuRowsThreeBytePointerLo],y ;get pointer to byte
- sta.w LoadMenuStringBuffer&$ffff+6
- sep #$20
- iny
- iny
- lda.b [MenuRowsThreeBytePointerLo],y ;get bank pointer to byte
- sta.w LoadMenuStringBuffer&$ffff+8
- lda.b #$05 ;write "draw byte" command"
- sta.w LoadMenuStringBuffer&$ffff+5
- ldx.w #2 ;print to screen
- jsr LoadTextString
- plp
- ply
- plx
- rts
- MenuDataType2:
- phx
- phy
- php
- rep #$31
- lda.b LoadMenuInitialOptionOffset ;get relative offset of option
- and.w #$00ff
- adc.b LoadMenuStringPosLo ;add offset of current row
- sta.w LoadMenuStringBuffer&$ffff+1 ;store in string position
- ldy.w #$0004
- lda.b [MenuRowsThreeBytePointerLo],y ;get pointer to byte
- sta.w LoadMenuStringBuffer&$ffff+6
- sep #$20
- iny
- iny
- lda.b [MenuRowsThreeBytePointerLo],y ;get bank pointer to byte
- sta.w LoadMenuStringBuffer&$ffff+8
- lda.b #$06 ;write "draw byte" command"
- sta.w LoadMenuStringBuffer&$ffff+5
- ldx.w #2 ;print to screen
- jsr LoadTextString
- plp
- ply
- plx
- rts
- MenuDataType3:
- phx
- phy
- php
- rep #$31
- lda.b LoadMenuInitialOptionOffset ;get relative offset of option
- and.w #$00ff
- adc.b LoadMenuStringPosLo ;add offset of current row
- sta.w LoadMenuStringBuffer&$ffff+1 ;store in string position
- lda.w #$0000 ;clear a
- sep #$20
- ldy.w #$0001
- lda.b [MenuRowsThreeBytePointerLo],y ;get bitmask
- sta.w LoadMenuStringBuffer&$ffff+6 ;just a temporary buffer
- ldy.w #$0000
- lda.b [MenuRowsThreeByteOptionPointerLo],y
- and.w LoadMenuStringBuffer&$ffff+6 ;check which string to choose
- rep #$31 ;if string1, a=0
- and.w #$ff
- ; beq MenuDataType3String1
-
- ; lda.b #$02 ;load textstring 2, two byte pointer
- ;MenuDataType3String1:
- asl a ;2byte pointer
- adc.w #0012 ;add until we're at pointer for string 1 or 2
- tay
- lda.b [MenuRowsThreeBytePointerLo],y ;get relative string pointer
- clc
- adc.b MenuFileThreeBytePointerLo ;add file offset to get real pointer
- sta.w LoadMenuStringBuffer&$ffff+6
- sep #$20
- lda.b MenuFileThreeBytePointerBank
- sta.w LoadMenuStringBuffer&$ffff+8
- lda.b #$04 ;write "draw string from adress" command"
- sta.w LoadMenuStringBuffer&$ffff+5
- ldx.w #2 ;print to screen
- jsr LoadTextString
- plp
- ply
- plx
- rts
- LoadMenuInitialOptionDrawDataTypeJumpTable:
- .dw MenuDataType0
- .dw MenuDataType1
- .dw MenuDataType2
- .dw MenuDataType3
- .dw MenuDataTypeVoid
- .dw MenuDataTypeVoid
- .dw MenuDataTypeVoid
- .dw MenuDataTypeVoid
- LoadMenuDrawDescString:
- phy
- phx
- php
- rep #$31 ;16bit and carry clear
- lda.w #$0000
- tax
- LoadMenuDrawDescStringClearBufferLoop:
- sta.w LoadMenuStringBuffer&$ffff,x
- inx
- inx
- cpx.w #$0008 ;clear 16 bytes of string buffer
- bcc LoadMenuDrawDescStringClearBufferLoop
-
-
- lda.b LoadMenuCurrentRow
- and.w #$001f
- tax
- lda.w #$0000
-
- LoadMenuDrawDescStringVertPosLoop:
- cpx.w #$0000
- beq LoadMenuDrawDescStringVertPosLoopExit
- clc
- adc.b LoadMenuVerticalSpacing
- dex
- bra LoadMenuDrawDescStringVertPosLoop
- LoadMenuDrawDescStringVertPosLoopExit:
- clc
- adc.b LoadMenuInitialOffset ;add offset of whole menu
- sta.b LoadMenuStringPosLo ;store in initial offset of current row
- sta.w LoadMenuStringBuffer&$ffff+1
- lda.b LoadMenuPalUnselSel
- and.b #$0001 ;only get lowest bit to check if we should draw highlighted or not
- clc
- adc.w #0008 ;get palette number 10=unselected, 11=selected
- tay
- sep #$20
- lda.b [MenuRowsThreeBytePointerLo],y
- sta.w LoadMenuStringBuffer&$ffff+4
- lda.b #$04 ;script command "set string adress"
- sta.w LoadMenuStringBuffer&$ffff+5
- inc.w LoadMenuStringBuffer&$ffff ;script command "set position" for description text
- lda.b #$07 ;script command "set palette"
- sta.w LoadMenuStringBuffer&$ffff+3
-
- rep #$31
- ldy.w #0010 ;get string offset
- lda.b [MenuRowsThreeBytePointerLo],y
- adc.b MenuFileThreeBytePointerLo ;add file offset to get real pointer
- sta.w LoadMenuStringBuffer&$ffff+6
- sep #$20
- lda.b MenuFileThreeBytePointerBank
- sta.w LoadMenuStringBuffer&$ffff+8
- ldx.w #2 ;print to screen
- jsr LoadTextString
- plp
- plx
- ply
- rts
- LoadMenuSetupRowPointer:
- phy
- php
- rep #$31 ;16bit and carry clear
- lda.b LoadMenuCurrentRow
- and.w #$001f
- asl a
- adc.w #$0005 ;add offset of relative pointertable in menu file
- tay
- lda.b [MenuFileThreeBytePointerLo],y
- adc.b MenuFileThreeBytePointerLo ;add file offset to get real pointer
- sta.b MenuRowsThreeBytePointerLo
- sep #$20
- lda.b MenuFileThreeBytePointerBank
- sta.b MenuRowsThreeBytePointerBank
- ldy.w #$0006 ;get option byte bank pointer
- lda.b [MenuRowsThreeBytePointerLo],y
- sta.b MenuRowsThreeByteOptionPointerBank
- rep #$30
- ldy.w #$0004 ;get option byte pointer
- lda.b [MenuRowsThreeBytePointerLo],y
- sta.b MenuRowsThreeByteOptionPointerLo
- sep #$20
- /*
- ldy.w #$0009 ;get options subroutine byte bank pointer
- lda.b [MenuRowsThreeBytePointerLo],y
- sta.b MenuRowsThreeByteCodePointerBank
- rep #$30
- ldy.w #$0007 ;get options subroutine byte pointer
- lda.b [MenuRowsThreeBytePointerLo],y
- sta.b MenuRowsThreeByteCodePointerLo
- sep #$20
- */
-
- plp
- ply
- rts
-
- LoadMenuDrawOptionValue:
- phy
- phx
- php
- rep #$31
- ldy.w #0000 ;get option data type
- tya
- sep #$20
- lda.b [MenuRowsThreeBytePointerLo],y
- and.b #$07 ;maximum number of types=7
- asl
- tax
- jsr (LoadMenuInitialOptionDrawDataTypeJumpTable,x)
- plp
- plx
- ply
- rts
-
|