arcade: move dip settings to mra.
This commit is contained in:
176
menu.cpp
176
menu.cpp
@@ -164,7 +164,10 @@ enum MENU
|
||||
MENU_8BIT_INFO,
|
||||
MENU_8BIT_INFO2,
|
||||
MENU_8BIT_ABOUT1,
|
||||
MENU_8BIT_ABOUT2
|
||||
MENU_8BIT_ABOUT2,
|
||||
|
||||
MENU_ARCADE_DIP1,
|
||||
MENU_ARCADE_DIP2
|
||||
};
|
||||
|
||||
static uint32_t menustate = MENU_NONE1;
|
||||
@@ -820,6 +823,7 @@ void HandleUI(void)
|
||||
static int has_fb_terminal = 0;
|
||||
static unsigned long flash_timer = 0;
|
||||
static int flash_state = 0;
|
||||
static uint32_t dip_submenu;
|
||||
|
||||
static char cp_MenuCancel;
|
||||
|
||||
@@ -1293,6 +1297,7 @@ void HandleUI(void)
|
||||
else OsdCoreNameSet(p);
|
||||
|
||||
OsdSetTitle(OsdCoreName(), 0);
|
||||
dip_submenu = -1;
|
||||
|
||||
// add options as requested by core
|
||||
int i = 2;
|
||||
@@ -1307,15 +1312,29 @@ void HandleUI(void)
|
||||
{
|
||||
int h = 0, d = 0;
|
||||
|
||||
//Hide or Disable flag (small letter - opposite action)
|
||||
while((p[0] == 'H' || p[0] == 'D' || p[0] == 'h' || p[0] == 'd') && strlen(p)>2)
|
||||
if (!strcmp(p, "DIP"))
|
||||
{
|
||||
int flg = (hdmask & (1<<getIdx(p))) ? 1 : 0;
|
||||
if (p[0] == 'H') h |= flg;
|
||||
if (p[0] == 'h') h |= (flg ^ 1);
|
||||
if (p[0] == 'D') d |= flg;
|
||||
if (p[0] == 'd') d |= (flg ^ 1);
|
||||
p += 2;
|
||||
if (arcade_sw()->dip_num)
|
||||
{
|
||||
dip_submenu = selentry;
|
||||
MenuWrite(entry, " DIP Switches \x16", menusub == selentry, 0);
|
||||
entry++;
|
||||
selentry++;
|
||||
menumask = (menumask << 1) | 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Hide or Disable flag (small letter - opposite action)
|
||||
while ((p[0] == 'H' || p[0] == 'D' || p[0] == 'h' || p[0] == 'd') && strlen(p) > 2)
|
||||
{
|
||||
int flg = (hdmask & (1 << getIdx(p))) ? 1 : 0;
|
||||
if (p[0] == 'H') h |= flg;
|
||||
if (p[0] == 'h') h |= (flg ^ 1);
|
||||
if (p[0] == 'D') d |= flg;
|
||||
if (p[0] == 'd') d |= (flg ^ 1);
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (!h)
|
||||
@@ -1505,6 +1524,11 @@ void HandleUI(void)
|
||||
{
|
||||
menustate = MENU_NONE1;
|
||||
}
|
||||
else if (dip_submenu == menusub)
|
||||
{
|
||||
menustate = MENU_ARCADE_DIP1;
|
||||
menusub = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
static char ext[256];
|
||||
@@ -1513,6 +1537,7 @@ void HandleUI(void)
|
||||
int h = 0, d = 0;
|
||||
uint32_t entry = 0;
|
||||
int i = 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
p = user_io_get_confstr(i++);
|
||||
@@ -1521,15 +1546,18 @@ void HandleUI(void)
|
||||
h = 0;
|
||||
d = 0;
|
||||
|
||||
//Hide or Disable flag
|
||||
while ((p[0] == 'H' || p[0] == 'D' || p[0] == 'h' || p[0] == 'd') && strlen(p) > 2)
|
||||
if (strcmp(p, "DIP"))
|
||||
{
|
||||
int flg = (hdmask & (1 << getIdx(p))) ? 1 : 0;
|
||||
if (p[0] == 'H') h |= flg;
|
||||
if (p[0] == 'h') h |= (flg ^ 1);
|
||||
if (p[0] == 'D') d |= flg;
|
||||
if (p[0] == 'd') d |= (flg ^ 1);
|
||||
p += 2;
|
||||
//Hide or Disable flag
|
||||
while ((p[0] == 'H' || p[0] == 'D' || p[0] == 'h' || p[0] == 'd') && strlen(p) > 2)
|
||||
{
|
||||
int flg = (hdmask & (1 << getIdx(p))) ? 1 : 0;
|
||||
if (p[0] == 'H') h |= flg;
|
||||
if (p[0] == 'h') h |= (flg ^ 1);
|
||||
if (p[0] == 'D') d |= flg;
|
||||
if (p[0] == 'd') d |= (flg ^ 1);
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (h || p[0] < 'A') continue;
|
||||
@@ -1989,6 +2017,111 @@ void HandleUI(void)
|
||||
if(!hold_cnt && reboot_req) fpga_load_rbf("menu.rbf");
|
||||
break;
|
||||
|
||||
case MENU_ARCADE_DIP1:
|
||||
helptext = 0;
|
||||
menumask = 0;
|
||||
OsdSetTitle("DIP Switches");
|
||||
menustate = MENU_ARCADE_DIP2;
|
||||
parentstate = MENU_ARCADE_DIP1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int entry = 0;
|
||||
if (!menusub) firstmenu = 0;
|
||||
|
||||
adjvisible = 0;
|
||||
uint32_t selentry = 0;
|
||||
menumask = 0;
|
||||
|
||||
sw_struct *sw = arcade_sw();
|
||||
|
||||
int n = (sw->dip_num < OsdGetSize() - 1) ? (OsdGetSize() - 1 - sw->dip_num) / 2 : 0;
|
||||
for (; entry < n; entry++) MenuWrite(entry);
|
||||
|
||||
for (int i = 0; i < sw->dip_num; i++)
|
||||
{
|
||||
uint64_t status = sw->dip_cur & sw->dip[i].mask;
|
||||
int m = 0;
|
||||
for (int n = 0; n < sw->dip[i].num; n++)
|
||||
{
|
||||
if (status == sw->dip[i].val[n])
|
||||
{
|
||||
m = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char l = strlen(sw->dip[i].id[m]);
|
||||
s[0] = ' ';
|
||||
strcpy(s + 1, sw->dip[i].name);
|
||||
|
||||
char *end = s + strlen(s) - 1;
|
||||
while ((end > s + 1) && (*end == ' ')) end--;
|
||||
*(end + 1) = 0;
|
||||
|
||||
strcat(s, ":");
|
||||
l = 28 - l - strlen(s);
|
||||
while (l--) strcat(s, " ");
|
||||
|
||||
strcat(s, sw->dip[i].id[m]);
|
||||
|
||||
MenuWrite(entry, s, menusub == selentry);
|
||||
|
||||
menumask = (menumask << 1) | 1;
|
||||
entry++;
|
||||
selentry++;
|
||||
};
|
||||
|
||||
for (; entry < OsdGetSize() - 1; entry++) MenuWrite(entry, "", 0, 0);
|
||||
|
||||
MenuWrite(entry, " Reset to apply", menusub == selentry);
|
||||
menusub_last = selentry;
|
||||
menumask = (menumask << 1) | 1;
|
||||
|
||||
if (!adjvisible) break;
|
||||
firstmenu += adjvisible;
|
||||
}
|
||||
break;
|
||||
|
||||
case MENU_ARCADE_DIP2:
|
||||
if (menu)
|
||||
{
|
||||
menustate = MENU_8BIT_MAIN1;
|
||||
menusub = dip_submenu;
|
||||
arcade_sw_save();
|
||||
}
|
||||
|
||||
if (select)
|
||||
{
|
||||
if (menusub == menusub_last)
|
||||
{
|
||||
arcade_sw_save();
|
||||
user_io_8bit_set_status(UIO_STATUS_RESET, UIO_STATUS_RESET);
|
||||
user_io_8bit_set_status(0, UIO_STATUS_RESET);
|
||||
menustate = MENU_NONE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sw_struct *sw = arcade_sw();
|
||||
uint64_t status = sw->dip_cur & sw->dip[menusub].mask;
|
||||
int m = 0;
|
||||
for (int n = 0; n < sw->dip[menusub].num; n++)
|
||||
{
|
||||
if (status == sw->dip[menusub].val[n])
|
||||
{
|
||||
m = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m = (m + 1) % sw->dip[menusub].num;
|
||||
sw->dip_cur = (sw->dip_cur & ~sw->dip[menusub].mask) | sw->dip[menusub].val[m];
|
||||
menustate = MENU_ARCADE_DIP1;
|
||||
arcade_sw_send();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MENU_UART1:
|
||||
{
|
||||
helptext = 0;
|
||||
@@ -3592,6 +3725,15 @@ void HandleUI(void)
|
||||
printf("Saving config to %s\n", filename);
|
||||
FileSaveConfig(filename, status, 8);
|
||||
menustate = MENU_8BIT_MAIN1;
|
||||
if (arcade_sw()->dip_num)
|
||||
{
|
||||
arcade_sw()->dip_cur = arcade_sw()->dip_def;
|
||||
arcade_sw_send();
|
||||
arcade_sw_save();
|
||||
user_io_8bit_set_status(UIO_STATUS_RESET, UIO_STATUS_RESET);
|
||||
user_io_8bit_set_status(0, UIO_STATUS_RESET);
|
||||
menustate = MENU_NONE1;
|
||||
}
|
||||
menusub = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "../../lib/md5/md5.h"
|
||||
|
||||
#include "buffer.h"
|
||||
#include "romutils.h"
|
||||
|
||||
#define kBigTextSize 1024
|
||||
struct arc_struct {
|
||||
@@ -29,6 +30,7 @@ struct arc_struct {
|
||||
int insiderom;
|
||||
int patchaddr;
|
||||
int validrom0;
|
||||
int insidesw;
|
||||
buffer_data *data;
|
||||
struct MD5Context context;
|
||||
};
|
||||
@@ -37,6 +39,45 @@ static char arcade_error_msg[kBigTextSize] = {};
|
||||
static char arcade_root[kBigTextSize];
|
||||
static char mame_root[kBigTextSize];
|
||||
|
||||
static sw_struct switches = {};
|
||||
|
||||
sw_struct *arcade_sw()
|
||||
{
|
||||
return &switches;
|
||||
}
|
||||
|
||||
void arcade_sw_send()
|
||||
{
|
||||
if (switches.dip_num)
|
||||
{
|
||||
user_io_set_index(254);
|
||||
user_io_set_download(1);
|
||||
user_io_file_tx_write((uint8_t*)&switches.dip_cur, sizeof(switches.dip_cur));
|
||||
user_io_set_download(0);
|
||||
}
|
||||
}
|
||||
|
||||
void arcade_sw_save()
|
||||
{
|
||||
if (switches.dip_saved != switches.dip_cur)
|
||||
{
|
||||
char path[256] = CONFIG_DIR"/dips/";
|
||||
FileCreatePath(path);
|
||||
strcat(path, switches.name);
|
||||
if (FileSave(path, &switches.dip_cur, sizeof(switches.dip_cur)))
|
||||
{
|
||||
switches.dip_saved = switches.dip_cur;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void arcade_sw_load()
|
||||
{
|
||||
char path[256] = "dips/";
|
||||
strcat(path, switches.name);
|
||||
FileLoadConfig(path, &switches.dip_cur, sizeof(switches.dip_cur));
|
||||
}
|
||||
|
||||
static void set_arcade_root(const char *path)
|
||||
{
|
||||
strcpy(arcade_root, path);
|
||||
@@ -213,13 +254,13 @@ static void file_finish(int send)
|
||||
unsigned char* hexstr_to_char(const char* hexstr, size_t *out_len)
|
||||
{
|
||||
size_t len = strlen(hexstr);
|
||||
unsigned char* chrs = (unsigned char*)malloc((len + 1) * sizeof(*chrs));
|
||||
unsigned char* chrs = (unsigned char*)malloc(len + 1);
|
||||
int dest = 0;
|
||||
// point to the beginning of the array
|
||||
const char *ptr = hexstr;
|
||||
while (*ptr) {
|
||||
// check to see if we have a space
|
||||
while (*ptr == '\n' || *ptr == '\r' || *ptr == ' ' || *ptr == '\t' || *ptr == 9 /*horiz tab*/) ptr++;
|
||||
while (*ptr == '\n' || *ptr == '\r' || *ptr == ' ' || *ptr == ',' || *ptr == '\t' || *ptr == 9 /*horiz tab*/) ptr++;
|
||||
if (*ptr == 0) break;
|
||||
|
||||
// pull two characters off
|
||||
@@ -256,6 +297,7 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons
|
||||
{
|
||||
case XML_EVENT_START_DOC:
|
||||
arc_info->insiderom = 0;
|
||||
arc_info->insidesw = 0;
|
||||
break;
|
||||
|
||||
case XML_EVENT_START_NODE:
|
||||
@@ -279,6 +321,15 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons
|
||||
MD5Init(&arc_info->context);
|
||||
}
|
||||
|
||||
if (!strcasecmp(node->tag, "switches"))
|
||||
{
|
||||
arc_info->insidesw = 1;
|
||||
switches.dip_cur = 0;
|
||||
switches.dip_def = 0;
|
||||
switches.dip_num = 0;
|
||||
memset(&switches.dip, 0, sizeof(switches.dip));
|
||||
}
|
||||
|
||||
// for each part tag, we clear the partzipname since it is optional and may not appear in the part tag
|
||||
if (!strcasecmp(node->tag, "part"))
|
||||
arc_info->partzipname[0] = 0;
|
||||
@@ -335,6 +386,87 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons
|
||||
arc_info->patchaddr = strtoul(node->attributes[i].value, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (arc_info->insidesw)
|
||||
{
|
||||
if (!strcasecmp(node->tag, "switches"))
|
||||
{
|
||||
if (!strcasecmp(node->attributes[i].name, "default"))
|
||||
{
|
||||
size_t len = 0;
|
||||
unsigned char* binary = hexstr_to_char(node->attributes[i].value, &len);
|
||||
for (size_t i = 0; i < len; i++) switches.dip_def |= binary[i] << (i * 8);
|
||||
free(binary);
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcasecmp(node->tag, "dip"))
|
||||
{
|
||||
if (!strcasecmp(node->attributes[i].name, "name"))
|
||||
{
|
||||
snprintf(switches.dip[switches.dip_num].name, sizeof(switches.dip[switches.dip_num].name), node->attributes[i].value);
|
||||
}
|
||||
|
||||
if (!strcasecmp(node->attributes[i].name, "bits"))
|
||||
{
|
||||
int b = 0, e = 0;
|
||||
int num = sscanf(node->attributes[i].value, "%d,%d", &b, &e);
|
||||
if (num <= 0 || b < 0 || b > 63 || e < 0 || e > 63 || (num == 2 && e < b))
|
||||
{
|
||||
printf("Invalid bits field: ""%s"" (%d, %d, %d)\n", node->attributes[i].value, num, b, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t mask = 1;
|
||||
if (num == 1) e = b;
|
||||
switches.dip[switches.dip_num].start = b;
|
||||
for (int i = 0; i < (e - b); i++) mask = (mask << 1) | 1;
|
||||
switches.dip[switches.dip_num].mask = mask << b;
|
||||
switches.dip[switches.dip_num].size = e - b + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcasecmp(node->attributes[i].name, "ids"))
|
||||
{
|
||||
int n = 0;
|
||||
char *val = node->attributes[i].value;
|
||||
while (*val && n < 32)
|
||||
{
|
||||
char *p = strchr(val, ',');
|
||||
size_t len = p ? p - val : strlen(val);
|
||||
size_t sz = len + 1;
|
||||
if (sz > sizeof(switches.dip[0].id[0])) sz = sizeof(switches.dip[0].id[0]);
|
||||
snprintf(switches.dip[switches.dip_num].id[n], sz, val);
|
||||
val += len;
|
||||
if (*val == ',') val++;
|
||||
n++;
|
||||
}
|
||||
switches.dip[switches.dip_num].num = n;
|
||||
}
|
||||
|
||||
if (!strcasecmp(node->attributes[i].name, "values"))
|
||||
{
|
||||
int n = 0;
|
||||
char *val = node->attributes[i].value;
|
||||
while (*val && n < 32)
|
||||
{
|
||||
char *endp = 0;
|
||||
uint64_t v = strtoul(val, &endp, 0);
|
||||
if (endp <= val)
|
||||
{
|
||||
printf("Invalid values field: ""%s""\n", node->attributes[i].value);
|
||||
break;
|
||||
}
|
||||
|
||||
switches.dip[switches.dip_num].val[n] = v;
|
||||
val = endp;
|
||||
while (*val && (*val == ' ' || *val == ',')) val++;
|
||||
n++;
|
||||
}
|
||||
switches.dip[switches.dip_num].has_val = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* at the beginning of each rom - tell the user_io to start a new message */
|
||||
@@ -480,6 +612,22 @@ static int xml_send_rom(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons
|
||||
free(binary);
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcasecmp(node->tag, "dip"))
|
||||
{
|
||||
int n = switches.dip_num;
|
||||
for (int i = 0; i < switches.dip[n].num; i++)
|
||||
{
|
||||
switches.dip[n].val[i] = ((switches.dip[n].has_val) ? switches.dip[n].val[i] : i) << switches.dip[n].start;
|
||||
}
|
||||
|
||||
if (switches.dip_num < 63) switches.dip_num++;
|
||||
}
|
||||
|
||||
if (!strcasecmp(node->tag, "switches"))
|
||||
{
|
||||
arc_info->insidesw = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case XML_EVENT_ERROR:
|
||||
@@ -530,8 +678,22 @@ static int xml_scan_rbf(XMLEvent evt, const XMLNode* node, SXML_CHAR* text, cons
|
||||
return true;
|
||||
}
|
||||
|
||||
static int arcade_type = 0;
|
||||
int is_arcade()
|
||||
{
|
||||
return arcade_type;
|
||||
}
|
||||
|
||||
int arcade_send_rom(const char *xml)
|
||||
{
|
||||
arcade_type = 1;
|
||||
|
||||
const char *p = strrchr(xml, '/');
|
||||
p = p ? p + 1 : xml;
|
||||
snprintf(switches.name, sizeof(switches.name), p);
|
||||
char *ext = strcasestr(switches.name, ".mra");
|
||||
if (ext) strcpy(ext, ".dip");
|
||||
|
||||
SAX_Callbacks sax;
|
||||
SAX_Callbacks_init(&sax);
|
||||
|
||||
@@ -553,6 +715,11 @@ int arcade_send_rom(const char *xml)
|
||||
printf("arcade_send_rom: pretty error: [%s]\n", arcade_error_msg);
|
||||
}
|
||||
buffer_destroy(arc_info.data);
|
||||
|
||||
switches.dip_cur = switches.dip_def;
|
||||
arcade_sw_load();
|
||||
switches.dip_saved = switches.dip_cur;
|
||||
arcade_sw_send();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,5 +4,33 @@
|
||||
int arcade_send_rom(const char *xml);
|
||||
int arcade_load(const char *xml);
|
||||
void arcade_check_error();
|
||||
int is_arcade();
|
||||
|
||||
struct dip_struct
|
||||
{
|
||||
int start;
|
||||
int size;
|
||||
int num;
|
||||
int has_val;
|
||||
uint64_t mask;
|
||||
char name[32];
|
||||
char id[32][32];
|
||||
uint64_t val[32];
|
||||
};
|
||||
|
||||
struct sw_struct
|
||||
{
|
||||
char name[1024];
|
||||
int dip_num;
|
||||
uint64_t dip_def;
|
||||
uint64_t dip_cur;
|
||||
uint64_t dip_saved;
|
||||
dip_struct dip[64];
|
||||
};
|
||||
|
||||
sw_struct *arcade_sw();
|
||||
void arcade_sw_send();
|
||||
void arcade_sw_save();
|
||||
void arcade_sw_load();
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user