Instantly share code, notes, and snippets.
Created
December 27, 2020 23:27
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save JettMonstersGoBoom/1876369f65d91abb36bcdccbd79b877c to your computer and use it in GitHub Desktop.
millfork menu system
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ---------------------------------------------------------- | |
| // Menu Code | |
| // ---------------------------------------------------------- | |
| const byte DEBOUNCE = %10000000 // or type with this to only change value when input is toggled vs held | |
| const byte CLAMP = %01000000 // stop at min max | |
| const byte WRAP = %00100000 // wrap at min max | |
| // types | |
| enum ItemType { NONE, BYTE ,WORD ,LWORD ,BOOL, MENU } | |
| // struct for menu type | |
| struct menuitem_t { | |
| pointer string | |
| byte type | |
| pointer variable | |
| int24 step | |
| function.void.to.void OnChange | |
| } | |
| byte old_input_dx,old_input_dy,old_input_btn | |
| byte MenuSelection = 0 | |
| pointer.menuitem_t current_menu | |
| void MenuProcess(pointer.menuitem_t menu) | |
| { | |
| word offset | |
| byte len | |
| pointer.byte v8 | |
| pointer.word v16 | |
| pointer.int24 v24 | |
| byte index | |
| int24 t24 | |
| bool selected | |
| byte color | |
| byte direction | |
| byte type | |
| bool changed | |
| offset = 160 | |
| index = 0 | |
| // loop until we hit NULL | |
| while(menu->string!=nullptr) { | |
| // check if we're selected | |
| selected = (index == MenuSelection) | |
| changed = false | |
| // change colors if so | |
| if (selected==true) { | |
| color = $1 | |
| } else { | |
| color = $e | |
| } | |
| // print the string part | |
| // len is the string length printed | |
| len = put_strz(offset,menu->string,color) | |
| // clear out these pointers | |
| v8 = nullptr | |
| v16 = nullptr | |
| v24 = nullptr | |
| type = menu->type & $f | |
| // if we're yes/no | |
| if type == BOOL { | |
| v8 = pointer.byte(menu->variable) | |
| if (v8[0]&1)==0 { | |
| put_strz(offset+len+1,"false"z,color) | |
| } | |
| else { | |
| put_strz(offset+len+1,"true "z,color) | |
| } | |
| } | |
| // check if we're a byte type | |
| if type == BYTE { | |
| // grab the correct pointer type | |
| v8 = pointer.byte(menu->variable) | |
| // print hex byte | |
| put_hex(offset+len+1,menu->variable[0],color) | |
| } | |
| if type == WORD { | |
| // grab the correct pointer type | |
| v16 = pointer.word(menu->variable) | |
| // print hex word | |
| put_hex(offset+len+1,menu->variable[1],color) | |
| put_hex(offset+len+3,menu->variable[0],color) | |
| } | |
| if type == LWORD { | |
| // grab the correct pointer type | |
| v24 = pointer.int24(menu->variable) | |
| // print hex 24 bit value | |
| put_hex(offset+len+1,menu->variable[2],color) | |
| put_hex(offset+len+3,menu->variable[1],color) | |
| put_hex(offset+len+5,menu->variable[0],color) | |
| } | |
| // now we handle editing | |
| if (selected==true) { | |
| // input dx = left or right | |
| direction = input_dx | |
| // if the type has DEBOUNCE flag , then check for that | |
| // if not zero direction | |
| if (menu->type & DEBOUNCE)!=0 { | |
| if input_dx==old_input_dx { | |
| direction = 0 | |
| } | |
| } | |
| // if left | |
| if (direction==$ff) { | |
| // if byte | |
| if (v8!=nullptr) { | |
| changed = true | |
| v8[0]-=menu->step.b0 | |
| } | |
| // if word | |
| if (v16!=nullptr) { | |
| changed = true | |
| v16[0]-=menu->step.loword | |
| } | |
| // 24 bit | |
| if (v24!=nullptr) { | |
| changed = true | |
| t24 = menu->step | |
| v24[0]-= t24 | |
| } | |
| } | |
| // if right | |
| if (direction==$01) { | |
| // if byte | |
| if (v8!=nullptr) { | |
| changed = true | |
| v8[0]+=menu->step.b0 | |
| } | |
| // if word | |
| if (v16!=nullptr) { | |
| changed = true | |
| v16[0]+=menu->step.loword | |
| } | |
| // if 24 bit | |
| if (v24!=nullptr) { | |
| changed = true | |
| t24 = menu->step | |
| v24[0]+= t24 | |
| } | |
| } | |
| if (changed == true) && (menu->OnChange!=nullptr) | |
| { | |
| call(menu->OnChange) | |
| } | |
| // if a change menu type | |
| if menu->type&$7f == MENU { | |
| // check for press ( not held ) | |
| if (input_btn==1) && (old_input_btn==0) { | |
| if (menu->OnChange!=nullptr) | |
| { | |
| call(menu->OnChange) | |
| } | |
| // reset selection | |
| MenuSelection = 0 | |
| // set current_menu to this variable | |
| current_menu = pointer.menuitem_t(menu->variable) | |
| return | |
| } | |
| } | |
| } | |
| // step the struct along one | |
| menu.raw+=sizeof(menuitem_t) | |
| // step down one line | |
| offset+=40 | |
| // increment index | |
| index+=1 | |
| } | |
| // index is number of items | |
| // check if we've moved the cursor up or down | |
| if (old_input_dy!=input_dy) { | |
| // change selection if so ( checking range ) | |
| if (input_dy==1) { | |
| MenuSelection+=1 | |
| if (MenuSelection>=index){ | |
| MenuSelection = 0 | |
| } | |
| } | |
| if (input_dy==$ff) { | |
| MenuSelection-=1 | |
| if (MenuSelection==$ff){ | |
| MenuSelection = index-1 | |
| } | |
| } | |
| } | |
| // save the inputs to debounce against | |
| old_input_dx = input_dx | |
| old_input_dy = input_dy | |
| old_input_btn = input_btn | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import c64_joy | |
| import menu_system | |
| array c64_screen[1000] @$400 | |
| // ---------------------------------------------------------- | |
| // example data | |
| byte var8=$32 | |
| word var16=$1234 | |
| int24 var24=$123456 | |
| bool booltest=0 | |
| void Changed() | |
| { | |
| vic_border=byte(booltest)&1 | |
| } | |
| void ChangedMenu() | |
| { | |
| cls() | |
| } | |
| // example menu | |
| array(menuitem_t) Menu = [ | |
| menuitem_t("hello"z ,DEBOUNCE|BYTE ,var8.pointer ,1 ,nullptr), | |
| menuitem_t("goodbye"z ,WORD ,var16.pointer ,16 ,nullptr), | |
| menuitem_t("test"z ,LWORD ,var24.pointer ,$1000 ,nullptr), | |
| menuitem_t("next"z ,MENU ,MenuTwo.pointer,0 ,ChangedMenu.pointer), | |
| menuitem_t(nullptr,NONE,nullptr,0,nullptr) | |
| ] | |
| // example second menu | |
| array(menuitem_t) MenuTwo = [ | |
| menuitem_t("hello"z ,DEBOUNCE|BYTE ,var8.pointer ,1 ,nullptr), | |
| menuitem_t("boolean"z ,DEBOUNCE|BOOL ,booltest.pointer ,1 ,Changed.pointer), | |
| menuitem_t("back"z ,MENU ,Menu.pointer ,0 ,ChangedMenu.pointer), | |
| menuitem_t(nullptr,NONE,nullptr,0,nullptr) | |
| ] | |
| // ---------------------------------------------------------- | |
| // show hex number | |
| const array hex_table=[$30,$31,$32,$33,$34,$35,$36,$37,$38,$39,$1,$2,$3,$4,$5,$6] | |
| void put_hex(word offset,byte value,byte color) { | |
| c64_screen[offset] = hex_table[value>>4] | |
| c64_screen[offset+1] = hex_table[value&$f] | |
| c64_color_ram[offset] = color | |
| c64_color_ram[offset+1] = color | |
| } | |
| // ---------------------------------------------------------- | |
| // show string | |
| byte put_strz(word offset,pointer str,byte color) { | |
| byte z | |
| z = 0 | |
| while str[z] != $e0 { | |
| c64_screen[offset+z]=str[z] | |
| c64_color_ram[offset+z] = color | |
| z += 1 | |
| } | |
| return z | |
| } | |
| void cls() | |
| { | |
| word size | |
| for size,0,until,1024 { | |
| c64_screen[size]=$20 | |
| } | |
| } | |
| void main() { | |
| vic_border = 0 | |
| vic_bg_color0 =0 | |
| cls() | |
| current_menu = Menu[0].pointer | |
| while true { | |
| while(vic_raster<$82) {} | |
| read_joy2() | |
| MenuProcess(current_menu) | |
| } | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment