Skip to content

Instantly share code, notes, and snippets.

@JettMonstersGoBoom
Created December 27, 2020 23:27
Show Gist options
  • Save JettMonstersGoBoom/1876369f65d91abb36bcdccbd79b877c to your computer and use it in GitHub Desktop.
Save JettMonstersGoBoom/1876369f65d91abb36bcdccbd79b877c to your computer and use it in GitHub Desktop.
millfork menu system
// ----------------------------------------------------------
// 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
}
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