1
0
mirror of https://github.com/mist-devel/mist-firmware.git synced 2026-01-11 23:43:04 +00:00

menu.c: factor out 8bit menu

This commit is contained in:
Gyorgy Szombathelyi 2022-01-31 21:07:08 +01:00
parent f1ceeaacbe
commit f50ca14752
8 changed files with 436 additions and 376 deletions

View File

@ -11,7 +11,7 @@ TODAY = `date +"%m/%d/%y"`
PRJ = firmware
SRC = hw/AT91SAM/Cstartup_SAM7.c hw/AT91SAM/hardware.c hw/AT91SAM/spi.c hw/AT91SAM/mmc.c hw/AT91SAM/at91sam_usb.c hw/AT91SAM/usbdev.c
SRC += fdd.c firmware.c fpga.c hdd.c main.c menu.c minimig-menu.c osd.c state.c syscalls.c user_io.c settings.c data_io.c boot.c idxfile.c config.c tos.c ikbd.c xmodem.c ini_parser.c cue_parser.c mist_cfg.c archie.c pcecd.c arc_file.c font.c utils.c
SRC += fdd.c firmware.c fpga.c hdd.c main.c menu.c menu-minimig.c menu-8bit.c osd.c state.c syscalls.c user_io.c settings.c data_io.c boot.c idxfile.c config.c tos.c ikbd.c xmodem.c ini_parser.c cue_parser.c mist_cfg.c archie.c pcecd.c arc_file.c font.c utils.c
SRC += usb/max3421e.c usb/usb.c usb/usbdebug.c usb/hub.c usb/hid.c usb/hidparser.c usb/xboxusb.c usb/timer.c usb/asix.c usb/pl2303.c usb/usbrtc.c usb/joymapping.c usb/joystick.c
SRC += fat_compat.c
SRC += FatFs/diskio.c FatFs/ff.c FatFs/ffunicode.c

View File

@ -18,7 +18,7 @@
#include "user_io.h"
#include "usb/usb.h"
#include "misc_cfg.h"
#include "minimig-menu.h"
#include "menu-minimig.h"
configTYPE config;
static configTYPE tmpconf;

400
menu-8bit.c Normal file
View File

@ -0,0 +1,400 @@
/*
This file is part of MiST-firmware
MiST-firmware is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
MiST-firmware is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <inttypes.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "debug.h"
#include "menu.h"
#include "osd.h"
#include "menu-8bit.h"
#include "user_io.h"
#include "data_io.h"
#include "fat_compat.h"
extern char s[FF_LFN_BUF + 1];
// TODO: remove these extern hacks to private variables
extern unsigned char menusub;
extern char fs_pFileExt[13];
//////////////////////////
/////// 8-bit menu ///////
//////////////////////////
static unsigned char selected_drive_slot;
static void substrcpy(char *d, char *s, char idx) {
char p = 0;
while(*s) {
if((p == idx) && *s && (*s != ','))
*d++ = *s;
if(*s == ',')
p++;
s++;
}
*d = 0;
}
static char* GetExt(char *ext) {
static char extlist[32];
char *p = extlist;
while(*ext) {
strcpy(p, ",");
strncat(p, ext, 3);
if(strlen(ext)<=3) break;
ext +=3;
p += strlen(p);
}
return extlist+1;
}
static unsigned char getIdx(char *opt) {
if((opt[1]>='0') && (opt[1]<='9')) return opt[1]-'0'; // bits 0-9
if((opt[1]>='A') && (opt[1]<='Z')) return opt[1]-'A'+10; // bits 10-35
if((opt[1]>='a') && (opt[1]<='z')) return opt[1]-'a'+36; // bits 36-61
return 0; // basically 0 cannot be valid because used as a reset. Thus can be used as a error.
}
static unsigned char getStatus(char *opt, unsigned long long status) {
char idx1 = getIdx(opt);
char idx2 = getIdx(opt+1);
unsigned char x = (status & ((unsigned long long)1<<idx1)) ? 1 : 0;
if(idx2>idx1) {
x = status >> idx1;
x = x & ~(~0 << (idx2 - idx1 + 1));
}
return x;
}
static unsigned long long setStatus(char *opt, unsigned long long status, unsigned char value) {
unsigned char idx1 = getIdx(opt);
unsigned char idx2 = getIdx(opt+1);
unsigned long long x = 1;
if(idx2>idx1) x = ~(~0 << (idx2 - idx1 + 1));
x = x << idx1;
return (status & ~x) | (((unsigned long long)value << idx1) & x);
}
static unsigned long long getStatusMask(char *opt) {
char idx1 = getIdx(opt);
char idx2 = getIdx(opt+1);
unsigned long long x = 1;
if(idx2>idx1) x = ~(~0 << (idx2 - idx1 + 1));
//iprintf("grtStatusMask %d %d %x\n", idx1, idx2, x);
return x << idx1;
}
static char RomFileSelected(uint8_t idx, const char *SelectedName) {
FIL file;
// this assumes that further file entries only exist if the first one also exists
if (f_open(&file, SelectedName, FA_READ) == FR_OK) {
data_io_file_tx(&file, user_io_ext_idx(SelectedName, fs_pFileExt)<<6 | (menusub+1), GetExtension(SelectedName));
f_close(&file);
}
// close menu afterwards
CloseMenu();
return 0;
}
static char ImageFileSelected(uint8_t idx, const char *SelectedName) {
// select image for SD card
iprintf("Image selected: %s\n", SelectedName);
data_io_set_index(user_io_ext_idx(SelectedName, fs_pFileExt)<<6 | (menusub+1));
user_io_file_mount(SelectedName, selected_drive_slot);
CloseMenu();
return 0;
}
static char CueFileSelected(uint8_t idx, const char *SelectedName) {
char res;
iprintf("Cue file selected: %s\n", SelectedName);
data_io_set_index(user_io_ext_idx(SelectedName, fs_pFileExt)<<6 | (menusub+1));
res = user_io_cue_mount(SelectedName);
if (res) ErrorMessage("\n Error mounting CD image!\n", res);
else CloseMenu();
return 0;
}
static char GetMenuPage_8bit(uint8_t idx, char action, menu_page_t *page) {
if (action == MENU_PAGE_EXIT) return 0;
char *p = user_io_get_core_name();
if(!p[0]) page->title = "8BIT";
else page->title = p;
page->flags = OSD_ARROW_RIGHT;
page->timer = 0;
page->stdexit = MENU_STD_EXIT;
return 0;
}
static char GetMenuItem_8bit(uint8_t idx, char action, menu_item_t *item) {
char *p;
char *pos;
unsigned long long status = user_io_8bit_set_status(0,0); // 0,0 gets status
if (action == MENU_ACT_RIGHT) {
SetupSystemMenu();
return 0;
}
item->item = "";
item->active = 0;
item->stipple = 0;
item->page = 0;
item->newpage = 0;
item->newsub = 0;
if(idx == 0) {
item->page = 0xff; // hide
return 1;
}
p = user_io_8bit_get_string(idx);
menu_debugf("Option %d: %s\n", idx, p);
if (idx > 1 && !p) return 0;
// check if there's a file type supported
if(idx == 1) {
if (p && strlen(p)) {
if (action == MENU_ACT_SEL) {
// use a local copy of "p" since SelectFile will destroy the buffer behind it
static char ext[13];
strncpy(ext, p, 13);
while(strlen(ext) < 3) strcat(ext, " ");
SelectFileNG(ext, SCAN_DIR | SCAN_LFN, RomFileSelected, 1);
} else if (action == MENU_ACT_GET) {
//menumask = 1;
strcpy(s, " Load *.");
strcat(s, GetExt(p));
item->item = s;
item->active = 1;
return 1;
} else {
return 0;
}
} else {
item->page = 0xff; // hide
return 1;
}
}
// check for 'V'ersion strings
if(p && (p[0] == 'V')) {
item->page = 0xff; // hide
return 1;
}
// check for 'P'age
char page = 0;
if(p && (p[0] == 'P')) {
if (p[2] == ',') {
// 'P' is to open a submenu
s[0] = ' ';
substrcpy(s+1, p, 1);
item->newpage = getIdx(p);
} else {
// 'P' is a prefix fo F,S,O,T,R
page = getIdx(p);
p+=2;
menu_debugf("P is prefix for: %s\n", p);
}
}
// check for 'F'ile or 'S'D image strings
if(p && ((p[0] == 'F') || (p[0] == 'S'))) {
if(action == MENU_ACT_SEL) {
static char ext[13];
selected_drive_slot = 0;
if (p[1]>='0' && p[1]<='9') selected_drive_slot = p[1]-'0';
substrcpy(ext, p, 1);
while(strlen(ext) < 3) strcat(ext, " ");
SelectFileNG(ext, SCAN_DIR | SCAN_LFN, (p[0] == 'F')?RomFileSelected:(p[1] == 'C')?CueFileSelected:ImageFileSelected, 1);
} else if (action == MENU_ACT_BKSP) {
if (p[0] == 'S' && p[1] && p[2] == 'U') {
// umount image
char slot = 0;
if (p[1]>='0' && p[1]<='9') slot = p[1]-'0';
if (user_io_is_mounted(slot)) {
user_io_file_mount(0, slot);
}
}
if (p[0] == 'S' && p[1] == 'C') {
// umount cue
if (user_io_is_cue_mounted())
user_io_cue_mount(NULL);
}
} else if (action == MENU_ACT_GET) {
substrcpy(s, p, 2);
if(strlen(s)) {
strcpy(s, " ");
substrcpy(s+1, p, 2);
strcat(s, " *.");
} else {
if(p[0] == 'F') strcpy(s, " Load *.");
else strcpy(s, " Mount *.");
}
pos = s+strlen(s);
substrcpy(pos, p, 1);
strcpy(pos, GetExt(pos));
if (p[0] == 'S' && p[1] && p[2] == 'U') {
char slot = 0;
if (p[1]>='0' && p[1]<='9') slot = p[1]-'0';
if (user_io_is_mounted(slot)) {
s[0] = '\x1e';
}
}
if (p[0] == 'S' && p[1] == 'C') {
if (user_io_is_cue_mounted())
s[0] = '\x1f';
}
} else {
return 0;
}
}
// check for 'T'oggle strings
if(p && (p[0] == 'T')) {
if (action == MENU_ACT_SEL || action == MENU_ACT_PLUS || action == MENU_ACT_MINUS) {
unsigned long long mask = 1<<getIdx(p);
menu_debugf("Option %s %x\n", p, status ^ mask);
// change bit
user_io_8bit_set_status(status ^ mask, mask);
// ... and change it again in case of a toggle bit
user_io_8bit_set_status(status, mask);
} else if (action == MENU_ACT_GET) {
s[0] = ' ';
substrcpy(s+1, p, 1);
} else {
return 0;
}
}
// check for 'O'ption strings
if(p && (p[0] == 'O')) {
if(action == MENU_ACT_SEL) {
unsigned char x = getStatus(p, status) + 1;
// check if next value available
substrcpy(s, p, 2+x);
if(!strlen(s)) x = 0;
//menu_debugf("Option %s %llx %llx %x %x\n", p, status, mask, x2, x);
user_io_8bit_set_status(setStatus(p, status, x), ~0);
} else if (action == MENU_ACT_GET) {
unsigned char x = getStatus(p, status);
menu_debugf("Option %s %llx %llx\n", p, x, status);
// get currently active option
substrcpy(s, p, 2+x);
char l = strlen(s);
if(!l) {
// option's index is outside of available values.
// reset to 0.
x = 0;
user_io_8bit_set_status(setStatus(p, status, x), ~0);
substrcpy(s, p, 2+x);
l = strlen(s);
}
s[0] = ' ';
substrcpy(s+1, p, 1);
strcat(s, ":");
l = 26-l-strlen(s);
while(l-- >= 0) strcat(s, " ");
substrcpy(s+strlen(s), p, 2+x);
} else {
return 0;
}
}
// check for 'R'AM strings
if(p && (p[0] == 'R')) {
if (action == MENU_ACT_SEL) {
int len = strtol(p+1,0,0);
menu_debugf("Option %s %d\n", p, len);
if (len) {
FIL file;
if (!user_io_create_config_name(s, "RAM", CONFIG_ROOT)) {
menu_debugf("Saving RAM file");
if (f_open(&file, s, FA_READ | FA_WRITE | FA_OPEN_ALWAYS) == FR_OK) {
data_io_file_rx(&file, -1, len);
f_close(&file);
} else {
ErrorMessage("\n Error saving RAM file!\n", 0);
}
}
}
} else if (action == MENU_ACT_GET) {
s[0] = ' ';
substrcpy(s+1, p, 1);
} else {
return 0;
}
}
item->item = s;
item->active = 1;
item->page = page;
return 1;
}
void Setup8bitMenu() {
char *c, *p;
int i;
// set helptext with core display on top of basic info
strcpy(helptext_custom, HELPTEXT_SPACER);
strcat(helptext_custom, OsdCoreName());
strcat(helptext_custom, helptexts[HELPTEXT_MAIN]);
helptext=helptext_custom;
c = user_io_get_core_name();
if(!c[0]) OsdCoreNameSet("8BIT");
else OsdCoreNameSet(c);
i = 2;
// search for 'V'ersion string
while (p = user_io_8bit_get_string(i++)) {
if(p[0] == 'V') {
// p[1] is not used but kept for future use
char x = p[1];
// get version string
strcpy(s, user_io_get_core_name());
strcat(s," ");
substrcpy(s+strlen(s), p, 1);
OsdCoreNameSet(s);
}
}
SetupMenu(GetMenuPage_8bit, GetMenuItem_8bit, NULL);
}

23
menu-8bit.h Normal file
View File

@ -0,0 +1,23 @@
/*
This file is part of MiST-firmware
MiST-firmware is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
MiST-firmware is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MENU_8BIT_H
#define MENU_8BIT_H
void Setup8bitMenu();
#endif

View File

@ -53,11 +53,6 @@ const char *KickstartSelectedName;
// TODO: remove these extern hacks to private variables
extern char DiskInfo[5]; // disk number info of selected entry
extern unsigned char menusub;
enum HelpText_Message {HELPTEXT_NONE,HELPTEXT_MAIN,HELPTEXT_HARDFILE,HELPTEXT_CHIPSET,HELPTEXT_MEMORY,HELPTEXT_VIDEO,HELPTEXT_FEATURES};
extern const char *helptexts[];
extern const char* HELPTEXT_SPACER;
extern char helptext_custom[450];
extern const char *helptext;
////////////////////////////
/////// Minimig menu ///////

View File

@ -1,5 +1,5 @@
#ifndef MINIMIG_MENU_H
#define MINIMIG_MENU_H
#ifndef MENU_MINIMIG_H
#define MENU_MINIMIG_H
// UI strings, used by boot messages
extern const char *config_filter_msg[];

369
menu.c
View File

@ -46,7 +46,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "arc_file.h"
#include "usb/joymapping.h"
#include "mist_cfg.h"
#include "minimig-menu.h"
#include "menu-minimig.h"
#include "menu-8bit.h"
#include "settings.h"
// test features (not used right now)
@ -97,7 +98,6 @@ const char *config_cpu_msg[] = {"68000 ", "68010", "-----","68020"};
const char *config_autofire_msg[] = {"\n\n AUTOFIRE OFF", "\n\n AUTOFIRE FAST", "\n\n AUTOFIRE MEDIUM", "\n\n AUTOFIRE SLOW"};
const char *days[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
enum HelpText_Message {HELPTEXT_NONE,HELPTEXT_MAIN,HELPTEXT_HARDFILE,HELPTEXT_CHIPSET,HELPTEXT_MEMORY,HELPTEXT_VIDEO,HELPTEXT_FEATURES,HELPTEXT_INPUT};
const char *helptexts[]={
0,
" Welcome to MiST! Use the cursor keys to navigate the menus. Use space bar or enter to select an item. Press Esc or F12 to exit the menus. Joystick emulation on the numeric keypad can be toggled with the numlock key, while pressing Ctrl-Alt-0 (numeric keypad) toggles autofire mode.",
@ -127,371 +127,6 @@ unsigned char fs_MenuSelect;
#define HELPTEXT_DELAY 10000
#define FRAME_DELAY 150
//////////////////////////
/////// 8-bit menu ///////
//////////////////////////
static unsigned char selected_drive_slot;
static void substrcpy(char *d, char *s, char idx) {
char p = 0;
while(*s) {
if((p == idx) && *s && (*s != ','))
*d++ = *s;
if(*s == ',')
p++;
s++;
}
*d = 0;
}
static char* GetExt(char *ext) {
static char extlist[32];
char *p = extlist;
while(*ext) {
strcpy(p, ",");
strncat(p, ext, 3);
if(strlen(ext)<=3) break;
ext +=3;
p += strlen(p);
}
return extlist+1;
}
static unsigned char getIdx(char *opt) {
if((opt[1]>='0') && (opt[1]<='9')) return opt[1]-'0'; // bits 0-9
if((opt[1]>='A') && (opt[1]<='Z')) return opt[1]-'A'+10; // bits 10-35
if((opt[1]>='a') && (opt[1]<='z')) return opt[1]-'a'+36; // bits 36-61
return 0; // basically 0 cannot be valid because used as a reset. Thus can be used as a error.
}
static unsigned char getStatus(char *opt, unsigned long long status) {
char idx1 = getIdx(opt);
char idx2 = getIdx(opt+1);
unsigned char x = (status & ((unsigned long long)1<<idx1)) ? 1 : 0;
if(idx2>idx1) {
x = status >> idx1;
x = x & ~(~0 << (idx2 - idx1 + 1));
}
return x;
}
static unsigned long long setStatus(char *opt, unsigned long long status, unsigned char value) {
unsigned char idx1 = getIdx(opt);
unsigned char idx2 = getIdx(opt+1);
unsigned long long x = 1;
if(idx2>idx1) x = ~(~0 << (idx2 - idx1 + 1));
x = x << idx1;
return (status & ~x) | (((unsigned long long)value << idx1) & x);
}
static unsigned long long getStatusMask(char *opt) {
char idx1 = getIdx(opt);
char idx2 = getIdx(opt+1);
unsigned long long x = 1;
if(idx2>idx1) x = ~(~0 << (idx2 - idx1 + 1));
//iprintf("grtStatusMask %d %d %x\n", idx1, idx2, x);
return x << idx1;
}
static char RomFileSelected(uint8_t idx, const char *SelectedName) {
FIL file;
// this assumes that further file entries only exist if the first one also exists
if (f_open(&file, SelectedName, FA_READ) == FR_OK) {
data_io_file_tx(&file, user_io_ext_idx(SelectedName, fs_pFileExt)<<6 | (menusub+1), GetExtension(SelectedName));
f_close(&file);
}
// close menu afterwards
CloseMenu();
return 0;
}
static char ImageFileSelected(uint8_t idx, const char *SelectedName) {
// select image for SD card
iprintf("Image selected: %s\n", SelectedName);
data_io_set_index(user_io_ext_idx(SelectedName, fs_pFileExt)<<6 | (menusub+1));
user_io_file_mount(SelectedName, selected_drive_slot);
CloseMenu();
return 0;
}
static char CueFileSelected(uint8_t idx, const char *SelectedName) {
char res;
iprintf("Cue file selected: %s\n", SelectedName);
data_io_set_index(user_io_ext_idx(SelectedName, fs_pFileExt)<<6 | (menusub+1));
res = user_io_cue_mount(SelectedName);
if (res) ErrorMessage("\n Error mounting CD image!\n", res);
else CloseMenu();
return 0;
}
static char GetMenuPage_8bit(uint8_t idx, char action, menu_page_t *page) {
if (action == MENU_PAGE_EXIT) return 0;
char *p = user_io_get_core_name();
if(!p[0]) page->title = "8BIT";
else page->title = p;
page->flags = OSD_ARROW_RIGHT;
page->timer = 0;
page->stdexit = MENU_STD_EXIT;
return 0;
}
static char GetMenuItem_8bit(uint8_t idx, char action, menu_item_t *item) {
char *p;
char *pos;
unsigned long long status = user_io_8bit_set_status(0,0); // 0,0 gets status
if (action == MENU_ACT_RIGHT) {
SetupSystemMenu();
return 0;
}
item->item = "";
item->active = 0;
item->stipple = 0;
item->page = 0;
item->newpage = 0;
item->newsub = 0;
if(idx == 0) {
item->page = 0xff; // hide
return 1;
}
p = user_io_8bit_get_string(idx);
menu_debugf("Option %d: %s\n", idx, p);
if (idx > 1 && !p) return 0;
// check if there's a file type supported
if(idx == 1) {
if (p && strlen(p)) {
if (action == MENU_ACT_SEL) {
// use a local copy of "p" since SelectFile will destroy the buffer behind it
static char ext[13];
strncpy(ext, p, 13);
while(strlen(ext) < 3) strcat(ext, " ");
SelectFileNG(ext, SCAN_DIR | SCAN_LFN, RomFileSelected, 1);
} else if (action == MENU_ACT_GET) {
//menumask = 1;
strcpy(s, " Load *.");
strcat(s, GetExt(p));
item->item = s;
item->active = 1;
return 1;
} else {
return 0;
}
} else {
item->page = 0xff; // hide
return 1;
}
}
// check for 'V'ersion strings
if(p && (p[0] == 'V')) {
item->page = 0xff; // hide
return 1;
}
// check for 'P'age
char page = 0;
if(p && (p[0] == 'P')) {
if (p[2] == ',') {
// 'P' is to open a submenu
s[0] = ' ';
substrcpy(s+1, p, 1);
item->newpage = getIdx(p);
} else {
// 'P' is a prefix fo F,S,O,T,R
page = getIdx(p);
p+=2;
menu_debugf("P is prefix for: %s\n", p);
}
}
// check for 'F'ile or 'S'D image strings
if(p && ((p[0] == 'F') || (p[0] == 'S'))) {
if(action == MENU_ACT_SEL) {
static char ext[13];
selected_drive_slot = 0;
if (p[1]>='0' && p[1]<='9') selected_drive_slot = p[1]-'0';
substrcpy(ext, p, 1);
while(strlen(ext) < 3) strcat(ext, " ");
SelectFileNG(ext, SCAN_DIR | SCAN_LFN, (p[0] == 'F')?RomFileSelected:(p[1] == 'C')?CueFileSelected:ImageFileSelected, 1);
} else if (action == MENU_ACT_BKSP) {
if (p[0] == 'S' && p[1] && p[2] == 'U') {
// umount image
char slot = 0;
if (p[1]>='0' && p[1]<='9') slot = p[1]-'0';
if (user_io_is_mounted(slot)) {
user_io_file_mount(0, slot);
}
}
if (p[0] == 'S' && p[1] == 'C') {
// umount cue
if (user_io_is_cue_mounted())
user_io_cue_mount(NULL);
}
} else if (action == MENU_ACT_GET) {
substrcpy(s, p, 2);
if(strlen(s)) {
strcpy(s, " ");
substrcpy(s+1, p, 2);
strcat(s, " *.");
} else {
if(p[0] == 'F') strcpy(s, " Load *.");
else strcpy(s, " Mount *.");
}
pos = s+strlen(s);
substrcpy(pos, p, 1);
strcpy(pos, GetExt(pos));
if (p[0] == 'S' && p[1] && p[2] == 'U') {
char slot = 0;
if (p[1]>='0' && p[1]<='9') slot = p[1]-'0';
if (user_io_is_mounted(slot)) {
s[0] = '\x1e';
}
}
if (p[0] == 'S' && p[1] == 'C') {
if (user_io_is_cue_mounted())
s[0] = '\x1f';
}
} else {
return 0;
}
}
// check for 'T'oggle strings
if(p && (p[0] == 'T')) {
if (action == MENU_ACT_SEL || action == MENU_ACT_PLUS || action == MENU_ACT_MINUS) {
unsigned long long mask = 1<<getIdx(p);
menu_debugf("Option %s %x\n", p, status ^ mask);
// change bit
user_io_8bit_set_status(status ^ mask, mask);
// ... and change it again in case of a toggle bit
user_io_8bit_set_status(status, mask);
} else if (action == MENU_ACT_GET) {
s[0] = ' ';
substrcpy(s+1, p, 1);
} else {
return 0;
}
}
// check for 'O'ption strings
if(p && (p[0] == 'O')) {
if(action == MENU_ACT_SEL) {
unsigned char x = getStatus(p, status) + 1;
// check if next value available
substrcpy(s, p, 2+x);
if(!strlen(s)) x = 0;
//menu_debugf("Option %s %llx %llx %x %x\n", p, status, mask, x2, x);
user_io_8bit_set_status(setStatus(p, status, x), ~0);
} else if (action == MENU_ACT_GET) {
unsigned char x = getStatus(p, status);
menu_debugf("Option %s %llx %llx\n", p, x, status);
// get currently active option
substrcpy(s, p, 2+x);
char l = strlen(s);
if(!l) {
// option's index is outside of available values.
// reset to 0.
x = 0;
user_io_8bit_set_status(setStatus(p, status, x), ~0);
substrcpy(s, p, 2+x);
l = strlen(s);
}
s[0] = ' ';
substrcpy(s+1, p, 1);
strcat(s, ":");
l = 26-l-strlen(s);
while(l-- >= 0) strcat(s, " ");
substrcpy(s+strlen(s), p, 2+x);
} else {
return 0;
}
}
// check for 'R'AM strings
if(p && (p[0] == 'R')) {
if (action == MENU_ACT_SEL) {
int len = strtol(p+1,0,0);
menu_debugf("Option %s %d\n", p, len);
if (len) {
FIL file;
if (!user_io_create_config_name(s, "RAM", CONFIG_ROOT)) {
menu_debugf("Saving RAM file");
if (f_open(&file, s, FA_READ | FA_WRITE | FA_OPEN_ALWAYS) == FR_OK) {
data_io_file_rx(&file, -1, len);
f_close(&file);
} else {
ErrorMessage("\n Error saving RAM file!\n", 0);
}
}
}
} else if (action == MENU_ACT_GET) {
s[0] = ' ';
substrcpy(s+1, p, 1);
} else {
return 0;
}
}
item->item = s;
item->active = 1;
item->page = page;
return 1;
}
static void Setup8bitMenu() {
char *c, *p;
int i;
// set helptext with core display on top of basic info
strcpy(helptext_custom, HELPTEXT_SPACER);
strcat(helptext_custom, OsdCoreName());
strcat(helptext_custom, helptexts[HELPTEXT_MAIN]);
helptext=helptext_custom;
c = user_io_get_core_name();
if(!c[0]) OsdCoreNameSet("8BIT");
else OsdCoreNameSet(c);
i = 2;
// search for 'V'ersion string
while (p = user_io_8bit_get_string(i++)) {
if(p[0] == 'V') {
// p[1] is not used but kept for future use
char x = p[1];
// get version string
strcpy(s, user_io_get_core_name());
strcat(s," ");
substrcpy(s+strlen(s), p, 1);
OsdCoreNameSet(s);
}
}
SetupMenu(GetMenuPage_8bit, GetMenuItem_8bit, NULL);
}
///////////////////////////
/////// System menu ///////
///////////////////////////

7
menu.h
View File

@ -78,8 +78,15 @@ void ClosePage();
void ChangePage(char);
void HandleUI(void);
void ErrorMessage(const char *message, unsigned char code);
void InfoMessage(const char *message);
extern const char *config_cpu_msg[];
enum HelpText_Message {HELPTEXT_NONE,HELPTEXT_MAIN,HELPTEXT_HARDFILE,HELPTEXT_CHIPSET,HELPTEXT_MEMORY,HELPTEXT_VIDEO,HELPTEXT_FEATURES,HELPTEXT_INPUT};
extern const char *helptexts[];
extern const char* HELPTEXT_SPACER;
extern char helptext_custom[450];
extern const char *helptext;
#endif