mirror of
https://github.com/RaySollium99/libpicofe.git
synced 2025-09-05 14:57:46 -04:00

git-svn-id: file:///home/notaz/opt/svn/PicoDrive/platform@638 be3aeb3a-fb24-0410-a615-afba39da0efa
840 lines
20 KiB
C
840 lines
20 KiB
C
// (c) Copyright 2006,2007 notaz, All rights reserved.
|
|
// Free for non-commercial use.
|
|
|
|
// For commercial use, separate licencing terms must be obtained.
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
|
|
#include "menu.h"
|
|
#include "fonts.h"
|
|
#include "readpng.h"
|
|
#include "lprintf.h"
|
|
#include "common.h"
|
|
#include "input.h"
|
|
#include "emu.h"
|
|
#include "plat.h"
|
|
|
|
#include <pico/patch.h>
|
|
|
|
char menuErrorMsg[64] = { 0, };
|
|
|
|
// PicoPad[] format: MXYZ SACB RLDU
|
|
me_bind_action me_ctrl_actions[15] =
|
|
{
|
|
{ "UP ", 0x0001 },
|
|
{ "DOWN ", 0x0002 },
|
|
{ "LEFT ", 0x0004 },
|
|
{ "RIGHT ", 0x0008 },
|
|
{ "A ", 0x0040 },
|
|
{ "B ", 0x0010 },
|
|
{ "C ", 0x0020 },
|
|
{ "A turbo", 0x4000 },
|
|
{ "B turbo", 0x1000 },
|
|
{ "C turbo", 0x2000 },
|
|
{ "START ", 0x0080 },
|
|
{ "MODE ", 0x0800 },
|
|
{ "X ", 0x0400 },
|
|
{ "Y ", 0x0200 },
|
|
{ "Z ", 0x0100 }
|
|
};
|
|
|
|
|
|
#ifndef UIQ3
|
|
|
|
static unsigned char menu_font_data[10240];
|
|
static int menu_text_color = 0xffff; // default to white
|
|
static int menu_sel_color = -1; // disabled
|
|
|
|
// draws text to current bbp16 screen
|
|
static void text_out16_(int x, int y, const char *text, int color)
|
|
{
|
|
int i, l, u, tr, tg, tb, len;
|
|
unsigned short *dest = (unsigned short *)SCREEN_BUFFER + x + y*SCREEN_WIDTH;
|
|
tr = (color & 0xf800) >> 8;
|
|
tg = (color & 0x07e0) >> 3;
|
|
tb = (color & 0x001f) << 3;
|
|
|
|
if (text == (void *)1)
|
|
{
|
|
// selector symbol
|
|
text = "";
|
|
len = 1;
|
|
}
|
|
else
|
|
len = strlen(text);
|
|
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
unsigned char *src = menu_font_data + (unsigned int)text[i]*4*10;
|
|
unsigned short *dst = dest;
|
|
for (l = 0; l < 10; l++, dst += SCREEN_WIDTH-8)
|
|
{
|
|
for (u = 8/2; u > 0; u--, src++)
|
|
{
|
|
int c, r, g, b;
|
|
c = *src >> 4;
|
|
r = (*dst & 0xf800) >> 8;
|
|
g = (*dst & 0x07e0) >> 3;
|
|
b = (*dst & 0x001f) << 3;
|
|
r = (c^0xf)*r/15 + c*tr/15;
|
|
g = (c^0xf)*g/15 + c*tg/15;
|
|
b = (c^0xf)*b/15 + c*tb/15;
|
|
*dst++ = ((r<<8)&0xf800) | ((g<<3)&0x07e0) | (b>>3);
|
|
c = *src & 0xf;
|
|
r = (*dst & 0xf800) >> 8;
|
|
g = (*dst & 0x07e0) >> 3;
|
|
b = (*dst & 0x001f) << 3;
|
|
r = (c^0xf)*r/15 + c*tr/15;
|
|
g = (c^0xf)*g/15 + c*tg/15;
|
|
b = (c^0xf)*b/15 + c*tb/15;
|
|
*dst++ = ((r<<8)&0xf800) | ((g<<3)&0x07e0) | (b>>3);
|
|
}
|
|
}
|
|
dest += 8;
|
|
}
|
|
}
|
|
|
|
void text_out16(int x, int y, const char *texto, ...)
|
|
{
|
|
va_list args;
|
|
char buffer[256];
|
|
int maxw = (SCREEN_WIDTH - x) / 8;
|
|
|
|
va_start(args, texto);
|
|
vsnprintf(buffer, sizeof(buffer), texto, args);
|
|
va_end(args);
|
|
|
|
if (maxw > 255)
|
|
maxw = 255;
|
|
buffer[maxw] = 0;
|
|
|
|
text_out16_(x,y,buffer,menu_text_color);
|
|
}
|
|
|
|
|
|
void smalltext_out16(int x, int y, const char *texto, int color)
|
|
{
|
|
int i;
|
|
unsigned char *src;
|
|
unsigned short *dst;
|
|
|
|
for (i = 0;; i++, x += 6)
|
|
{
|
|
unsigned char c = (unsigned char) texto[i];
|
|
int h = 8;
|
|
|
|
if (!c) break;
|
|
|
|
src = fontdata6x8[c];
|
|
dst = (unsigned short *)SCREEN_BUFFER + x + y*SCREEN_WIDTH;
|
|
|
|
while (h--)
|
|
{
|
|
int w = 0x20;
|
|
while (w)
|
|
{
|
|
if( *src & w ) *dst = color;
|
|
dst++;
|
|
w>>=1;
|
|
}
|
|
src++;
|
|
|
|
dst += SCREEN_WIDTH-6;
|
|
}
|
|
}
|
|
}
|
|
|
|
void smalltext_out16_lim(int x, int y, const char *texto, int color, int max)
|
|
{
|
|
char buffer[SCREEN_WIDTH/6+1];
|
|
|
|
strncpy(buffer, texto, SCREEN_WIDTH/6);
|
|
if (max > SCREEN_WIDTH/6) max = SCREEN_WIDTH/6;
|
|
if (max < 0) max = 0;
|
|
buffer[max] = 0;
|
|
|
|
smalltext_out16(x, y, buffer, color);
|
|
}
|
|
|
|
void menu_draw_selection(int x, int y, int w)
|
|
{
|
|
int i, h;
|
|
unsigned short *dst, *dest;
|
|
|
|
text_out16_(x, y, (void *)1, (menu_sel_color < 0) ? menu_text_color : menu_sel_color);
|
|
|
|
if (menu_sel_color < 0) return; // no selection hilight
|
|
|
|
if (y > 0) y--;
|
|
dest = (unsigned short *)SCREEN_BUFFER + x + y*SCREEN_WIDTH + 14;
|
|
for (h = 11; h > 0; h--)
|
|
{
|
|
dst = dest;
|
|
for (i = w; i > 0; i--)
|
|
*dst++ = menu_sel_color;
|
|
dest += SCREEN_WIDTH;
|
|
}
|
|
}
|
|
|
|
static int parse_hex_color(char *buff)
|
|
{
|
|
char *endp = buff;
|
|
int t = (int) strtoul(buff, &endp, 16);
|
|
if (endp != buff)
|
|
#ifdef PSP
|
|
return ((t<<8)&0xf800) | ((t>>5)&0x07e0) | ((t>>19)&0x1f);
|
|
#else
|
|
return ((t>>8)&0xf800) | ((t>>5)&0x07e0) | ((t>>3)&0x1f);
|
|
#endif
|
|
return -1;
|
|
}
|
|
|
|
void menu_init(void)
|
|
{
|
|
int c, l;
|
|
unsigned char *fd = menu_font_data;
|
|
char buff[256];
|
|
FILE *f;
|
|
|
|
// generate default font from fontdata8x8
|
|
memset(menu_font_data, 0, sizeof(menu_font_data));
|
|
for (c = 0; c < 256; c++)
|
|
{
|
|
for (l = 0; l < 8; l++)
|
|
{
|
|
unsigned char fd8x8 = fontdata8x8[c*8+l];
|
|
if (fd8x8&0x80) *fd |= 0xf0;
|
|
if (fd8x8&0x40) *fd |= 0x0f; fd++;
|
|
if (fd8x8&0x20) *fd |= 0xf0;
|
|
if (fd8x8&0x10) *fd |= 0x0f; fd++;
|
|
if (fd8x8&0x08) *fd |= 0xf0;
|
|
if (fd8x8&0x04) *fd |= 0x0f; fd++;
|
|
if (fd8x8&0x02) *fd |= 0xf0;
|
|
if (fd8x8&0x01) *fd |= 0x0f; fd++;
|
|
}
|
|
fd += 8*2/2; // 2 empty lines
|
|
}
|
|
|
|
// load custom font and selector (stored as 1st symbol in font table)
|
|
readpng(menu_font_data, "skin/font.png", READPNG_FONT);
|
|
memcpy(menu_font_data, menu_font_data + ((int)'>')*4*10, 4*10); // default selector symbol is '>'
|
|
readpng(menu_font_data, "skin/selector.png", READPNG_SELECTOR);
|
|
|
|
// load custom colors
|
|
f = fopen("skin/skin.txt", "r");
|
|
if (f != NULL)
|
|
{
|
|
lprintf("found skin.txt\n");
|
|
while (!feof(f))
|
|
{
|
|
fgets(buff, sizeof(buff), f);
|
|
if (buff[0] == '#' || buff[0] == '/') continue; // comment
|
|
if (buff[0] == '\r' || buff[0] == '\n') continue; // empty line
|
|
if (strncmp(buff, "text_color=", 11) == 0)
|
|
{
|
|
int tmp = parse_hex_color(buff+11);
|
|
if (tmp >= 0) menu_text_color = tmp;
|
|
else lprintf("skin.txt: parse error for text_color\n");
|
|
}
|
|
else if (strncmp(buff, "selection_color=", 16) == 0)
|
|
{
|
|
int tmp = parse_hex_color(buff+16);
|
|
if (tmp >= 0) menu_sel_color = tmp;
|
|
else lprintf("skin.txt: parse error for selection_color\n");
|
|
}
|
|
else
|
|
lprintf("skin.txt: parse error: %s\n", buff);
|
|
}
|
|
fclose(f);
|
|
}
|
|
}
|
|
|
|
|
|
int me_id2offset(const menu_entry *ent, menu_id id)
|
|
{
|
|
int i;
|
|
for (i = 0; ent->name; ent++, i++)
|
|
if (ent->id == id) return i;
|
|
|
|
lprintf("%s: id %i not found\n", __FUNCTION__, id);
|
|
return 0;
|
|
}
|
|
|
|
void me_enable(menu_entry *entries, menu_id id, int enable)
|
|
{
|
|
int i = me_id2offset(entries, id);
|
|
entries[i].enabled = enable;
|
|
}
|
|
|
|
int me_count(const menu_entry *ent)
|
|
{
|
|
int ret;
|
|
|
|
for (ret = 0; ent->name; ent++, ret++)
|
|
;
|
|
|
|
return ret;
|
|
}
|
|
|
|
menu_id me_index2id(const menu_entry *ent, int index)
|
|
{
|
|
const menu_entry *last;
|
|
|
|
for (; ent->name; ent++)
|
|
{
|
|
if (ent->enabled)
|
|
{
|
|
if (index == 0) break;
|
|
index--;
|
|
}
|
|
last = ent;
|
|
}
|
|
if (ent->name == NULL)
|
|
ent = last;
|
|
return ent->id;
|
|
}
|
|
|
|
/* TODO rm */
|
|
void me_draw(const menu_entry *entries, int count, int x, int y, me_draw_custom_f *cust_draw, void *param)
|
|
{
|
|
int i, y1 = y;
|
|
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
if (!entries[i].enabled) continue;
|
|
if (entries[i].name == NULL)
|
|
{
|
|
if (cust_draw != NULL)
|
|
cust_draw(&entries[i], x, y1, param);
|
|
y1 += 10;
|
|
continue;
|
|
}
|
|
text_out16(x, y1, entries[i].name);
|
|
if (entries[i].beh == MB_OPT_ONOFF)
|
|
text_out16(x + 27*8, y1, (*(int *)entries[i].var & entries[i].mask) ? "ON" : "OFF");
|
|
else if (entries[i].beh == MB_OPT_RANGE)
|
|
text_out16(x + 27*8, y1, "%i", *(int *)entries[i].var);
|
|
y1 += 10;
|
|
}
|
|
|
|
}
|
|
|
|
static void me_draw2(const menu_entry *entries, int sel)
|
|
{
|
|
const menu_entry *ent;
|
|
int x, y, w = 0, h = 0;
|
|
int opt_offs = 27*8;
|
|
const char *name;
|
|
int asel = 0;
|
|
int i, n;
|
|
|
|
/* calculate size of menu rect */
|
|
for (ent = entries, i = n = 0; ent->name; ent++, i++)
|
|
{
|
|
int wt;
|
|
|
|
if (!ent->enabled)
|
|
continue;
|
|
|
|
if (i == sel)
|
|
asel = n;
|
|
|
|
name = NULL;
|
|
wt = strlen(ent->name) * 8; /* FIXME: unhardcode font width */
|
|
if (wt == 0 && ent->generate_name)
|
|
name = ent->generate_name(1);
|
|
if (name != NULL)
|
|
wt = strlen(name) * 8;
|
|
|
|
if (ent->beh != MB_NONE)
|
|
{
|
|
if (wt > opt_offs)
|
|
opt_offs = wt + 8;
|
|
wt = opt_offs;
|
|
|
|
switch (ent->beh) {
|
|
case MB_NONE: break;
|
|
case MB_OPT_ONOFF:
|
|
case MB_OPT_RANGE: wt += 8*3; break;
|
|
case MB_OPT_CUSTOM:
|
|
name = NULL;
|
|
if (ent->generate_name != NULL)
|
|
name = ent->generate_name(0);
|
|
if (name != NULL)
|
|
wt += strlen(name) * 8;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (wt > w)
|
|
w = wt;
|
|
n++;
|
|
}
|
|
h = n * 10;
|
|
w += 16; /* selector */
|
|
|
|
if (w > SCREEN_WIDTH) {
|
|
lprintf("width %d > %d\n", w, SCREEN_WIDTH);
|
|
w = SCREEN_WIDTH;
|
|
}
|
|
if (h > SCREEN_HEIGHT) {
|
|
lprintf("height %d > %d\n", w, SCREEN_HEIGHT);
|
|
h = SCREEN_HEIGHT;
|
|
}
|
|
|
|
x = SCREEN_WIDTH / 2 - w / 2;
|
|
y = SCREEN_HEIGHT / 2 - h / 2;
|
|
|
|
/* draw */
|
|
plat_video_menu_begin();
|
|
menu_draw_selection(x, y + asel * 10, w);
|
|
|
|
for (ent = entries; ent->name; ent++)
|
|
{
|
|
if (!ent->enabled)
|
|
continue;
|
|
|
|
name = ent->name;
|
|
if (strlen(name) == 0) {
|
|
if (ent->generate_name)
|
|
name = ent->generate_name(1);
|
|
}
|
|
if (name != NULL)
|
|
text_out16(x + 16, y, name);
|
|
|
|
switch (ent->beh) {
|
|
case MB_NONE:
|
|
break;
|
|
case MB_OPT_ONOFF:
|
|
text_out16(x + 16 + opt_offs, y, (*(int *)ent->var & ent->mask) ? "ON" : "OFF");
|
|
break;
|
|
case MB_OPT_RANGE:
|
|
text_out16(x + 16 + opt_offs, y, "%i", *(int *)ent->var);
|
|
break;
|
|
case MB_OPT_CUSTOM:
|
|
name = NULL;
|
|
if (ent->generate_name)
|
|
name = ent->generate_name(0);
|
|
if (name != NULL)
|
|
text_out16(x + 16 + opt_offs, y, "%s", name);
|
|
break;
|
|
}
|
|
|
|
y += 10;
|
|
}
|
|
|
|
plat_video_menu_end();
|
|
}
|
|
|
|
int me_process(menu_entry *entries, menu_id id, int is_next)
|
|
{
|
|
int i = me_id2offset(entries, id);
|
|
menu_entry *entry = &entries[i];
|
|
switch (entry->beh)
|
|
{
|
|
case MB_OPT_ONOFF:
|
|
*(int *)entry->var ^= entry->mask;
|
|
return 1;
|
|
case MB_OPT_RANGE:
|
|
*(int *)entry->var += is_next ? 1 : -1;
|
|
if (*(int *)entry->var < (int)entry->min) *(int *)entry->var = (int)entry->min;
|
|
if (*(int *)entry->var > (int)entry->max) *(int *)entry->var = (int)entry->max;
|
|
return 1;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static void me_loop(menu_entry *menu, int *menu_sel)
|
|
{
|
|
int ret, inp, sel = *menu_sel, menu_sel_max;
|
|
|
|
menu_sel_max = me_count(menu) - 1;
|
|
if (menu_sel_max < 1) {
|
|
lprintf("no enabled menu entries\n");
|
|
return;
|
|
}
|
|
|
|
while (!menu[sel].enabled && sel < menu_sel_max)
|
|
sel++;
|
|
|
|
/* make sure action buttons are not pressed on entering menu */
|
|
me_draw2(menu, sel);
|
|
while (in_menu_wait_any(50) & (PBTN_MOK|PBTN_MBACK|PBTN_MENU));
|
|
|
|
for (;;)
|
|
{
|
|
me_draw2(menu, sel);
|
|
inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_MOK|PBTN_MBACK|PBTN_MENU|PBTN_L|PBTN_R);
|
|
if (inp & PBTN_UP ) {
|
|
do {
|
|
sel--;
|
|
if (sel < 0)
|
|
sel = menu_sel_max;
|
|
}
|
|
while (!menu[sel].enabled);
|
|
}
|
|
if (inp & PBTN_DOWN) {
|
|
do {
|
|
sel++;
|
|
if (sel > menu_sel_max)
|
|
sel = 0;
|
|
}
|
|
while (!menu[sel].enabled);
|
|
}
|
|
// if ((inp & (PBTN_L|PBTN_R)) == (PBTN_L|PBTN_R)) debug_menu_loop(); // TODO
|
|
if (inp & (PBTN_MENU|PBTN_MBACK))
|
|
break;
|
|
|
|
if (inp & PBTN_MOK)
|
|
{
|
|
if (menu[sel].submenu_handler != NULL) {
|
|
ret = menu[sel].submenu_handler(menu[sel].id);
|
|
if (ret) break;
|
|
}
|
|
}
|
|
// menuErrorMsg[0] = 0; // TODO: clear error msg
|
|
}
|
|
*menu_sel = sel;
|
|
}
|
|
|
|
/* ***************************************** */
|
|
|
|
/* TODO s */
|
|
int menu_loop_tray(void) { return 0; }
|
|
void menu_romload_prepare(const char *rom_name) {}
|
|
void menu_romload_end(void) {}
|
|
me_bind_action emuctrl_actions[1];
|
|
menu_entry opt_entries[1];
|
|
menu_entry opt2_entries[1];
|
|
menu_entry cdopt_entries[1];
|
|
menu_entry ctrlopt_entries[1];
|
|
const int opt_entry_count = 0;
|
|
const int opt2_entry_count = 0;
|
|
const int cdopt_entry_count = 0;
|
|
const int ctrlopt_entry_count = 0;
|
|
|
|
extern int engineState;
|
|
|
|
int savestate_menu_loop(int a) { return 1; }
|
|
int menu_loop_options() { return 1; }
|
|
void kc_sel_loop() {}
|
|
void draw_menu_credits() {}
|
|
void patches_menu_loop() {}
|
|
|
|
// ------------ main menu ------------
|
|
|
|
static int main_menu_handler(menu_id id)
|
|
{
|
|
int ret;
|
|
|
|
switch (id)
|
|
{
|
|
case MA_MAIN_RESUME_GAME:
|
|
if (rom_loaded) {
|
|
while (in_menu_wait_any(50) & PBTN_MOK);
|
|
engineState = PGS_Running;
|
|
return 1;
|
|
}
|
|
break;
|
|
case MA_MAIN_SAVE_STATE:
|
|
if (rom_loaded) {
|
|
if (savestate_menu_loop(0))
|
|
break;
|
|
engineState = PGS_Running;
|
|
return 1;
|
|
}
|
|
break;
|
|
case MA_MAIN_LOAD_STATE:
|
|
if (rom_loaded) {
|
|
if (savestate_menu_loop(1))
|
|
break;
|
|
while (in_menu_wait_any(50) & PBTN_MOK);
|
|
engineState = PGS_Running;
|
|
return 1;
|
|
}
|
|
break;
|
|
case MA_MAIN_RESET_GAME:
|
|
if (rom_loaded) {
|
|
emu_ResetGame();
|
|
while (in_menu_wait_any(50) & PBTN_MOK);
|
|
engineState = PGS_Running;
|
|
return 1;
|
|
}
|
|
break;
|
|
case MA_MAIN_LOAD_ROM:
|
|
{
|
|
/* char curr_path[PATH_MAX], *selfname;
|
|
FILE *tstf;
|
|
if ( (tstf = fopen(loadedRomFName, "rb")) )
|
|
{
|
|
fclose(tstf);
|
|
strcpy(curr_path, loadedRomFName);
|
|
}
|
|
else
|
|
getcwd(curr_path, PATH_MAX);
|
|
selfname = romsel_loop(curr_path);
|
|
if (selfname) {
|
|
printf("selected file: %s\n", selfname);
|
|
engineState = PGS_ReloadRom;
|
|
return;
|
|
}*/
|
|
break;
|
|
}
|
|
case MA_MAIN_OPTIONS:
|
|
ret = menu_loop_options();
|
|
if (ret == 1) break; // status update
|
|
if (engineState == PGS_ReloadRom)
|
|
return 1; // BIOS test
|
|
break;
|
|
case MA_MAIN_CONTROLS:
|
|
kc_sel_loop();
|
|
break;
|
|
case MA_MAIN_CREDITS:
|
|
draw_menu_credits();
|
|
usleep(500*1000); /* FIXME */
|
|
in_menu_wait(PBTN_MOK|PBTN_MBACK);
|
|
break;
|
|
case MA_MAIN_EXIT:
|
|
engineState = PGS_Quit;
|
|
return 1;
|
|
case MA_MAIN_PATCHES:
|
|
if (rom_loaded && PicoPatches) {
|
|
patches_menu_loop();
|
|
PicoPatchApply();
|
|
strcpy(menuErrorMsg, "Patches applied");
|
|
}
|
|
break;
|
|
default:
|
|
lprintf("%s: something unknown selected\n", __FUNCTION__);
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
menu_entry e_main_menu[] =
|
|
{
|
|
mee_submenu_id("Resume game", MA_MAIN_RESUME_GAME, main_menu_handler),
|
|
mee_submenu_id("Save State", MA_MAIN_SAVE_STATE, main_menu_handler),
|
|
mee_submenu_id("Load State", MA_MAIN_LOAD_STATE, main_menu_handler),
|
|
mee_submenu_id("Reset game", MA_MAIN_RESET_GAME, main_menu_handler),
|
|
mee_submenu_id("Load new ROM/ISO", MA_MAIN_LOAD_ROM, main_menu_handler),
|
|
mee_submenu_id("Change options", MA_MAIN_OPTIONS, main_menu_handler),
|
|
mee_submenu_id("Credits", MA_MAIN_CREDITS, main_menu_handler),
|
|
mee_submenu_id("Patches / GameGenie",MA_MAIN_PATCHES, main_menu_handler),
|
|
mee_submenu_id("Exit", MA_MAIN_EXIT, main_menu_handler),
|
|
mee_end,
|
|
};
|
|
|
|
void menu_loop(void)
|
|
{
|
|
static int sel = 0;
|
|
|
|
me_enable(e_main_menu, MA_MAIN_RESUME_GAME, rom_loaded);
|
|
me_enable(e_main_menu, MA_MAIN_SAVE_STATE, rom_loaded);
|
|
me_enable(e_main_menu, MA_MAIN_LOAD_STATE, rom_loaded);
|
|
me_enable(e_main_menu, MA_MAIN_RESET_GAME, rom_loaded);
|
|
me_enable(e_main_menu, MA_MAIN_PATCHES, PicoPatches != NULL);
|
|
|
|
plat_video_menu_enter(rom_loaded);
|
|
in_set_blocking(1);
|
|
me_loop(e_main_menu, &sel);
|
|
in_set_blocking(0);
|
|
|
|
if (rom_loaded) {
|
|
while (in_menu_wait_any(50) & (PBTN_MENU|PBTN_MBACK)); // wait until select is released
|
|
engineState = PGS_Running;
|
|
}
|
|
|
|
}
|
|
|
|
// ------------ debug menu ------------
|
|
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <pico/pico.h>
|
|
#include <pico/debug.h>
|
|
|
|
void SekStepM68k(void);
|
|
|
|
static void mplayer_loop(void)
|
|
{
|
|
emu_startSound();
|
|
|
|
while (1)
|
|
{
|
|
PDebugZ80Frame();
|
|
if (in_menu_wait_any(0) & PBTN_NORTH) break;
|
|
emu_waitSound();
|
|
}
|
|
|
|
emu_endSound();
|
|
}
|
|
|
|
static void draw_text_debug(const char *str, int skip, int from)
|
|
{
|
|
const char *p;
|
|
int len, line;
|
|
|
|
p = str;
|
|
while (skip-- > 0)
|
|
{
|
|
while (*p && *p != '\n') p++;
|
|
if (*p == 0 || p[1] == 0) return;
|
|
p++;
|
|
}
|
|
|
|
str = p;
|
|
for (line = from; line < SCREEN_HEIGHT/10; line++)
|
|
{
|
|
while (*p && *p != '\n') p++;
|
|
len = p - str;
|
|
if (len > 55) len = 55;
|
|
smalltext_out16_lim(1, line*10, str, 0xffff, len);
|
|
if (*p == 0) break;
|
|
p++; str = p;
|
|
}
|
|
}
|
|
|
|
static void draw_frame_debug(void)
|
|
{
|
|
char layer_str[48] = "layers: ";
|
|
if (PicoDrawMask & PDRAW_LAYERB_ON) memcpy(layer_str + 8, "B", 1);
|
|
if (PicoDrawMask & PDRAW_LAYERA_ON) memcpy(layer_str + 10, "A", 1);
|
|
if (PicoDrawMask & PDRAW_SPRITES_LOW_ON) memcpy(layer_str + 12, "spr_lo", 6);
|
|
if (PicoDrawMask & PDRAW_SPRITES_HI_ON) memcpy(layer_str + 19, "spr_hi", 6);
|
|
|
|
clear_screen();
|
|
emu_forcedFrame(0);
|
|
smalltext_out16(4, SCREEN_HEIGHT-8, layer_str, 0xffff);
|
|
}
|
|
|
|
void debug_menu_loop(void)
|
|
{
|
|
int inp, mode = 0;
|
|
int spr_offs = 0, dumped = 0;
|
|
char *tmp;
|
|
|
|
while (1)
|
|
{
|
|
switch (mode)
|
|
{
|
|
case 0: plat_video_menu_begin();
|
|
tmp = PDebugMain();
|
|
emu_platformDebugCat(tmp);
|
|
draw_text_debug(tmp, 0, 0);
|
|
if (dumped) {
|
|
smalltext_out16(SCREEN_WIDTH-6*10, SCREEN_HEIGHT-8, "dumped", 0xffff);
|
|
dumped = 0;
|
|
}
|
|
break;
|
|
case 1: draw_frame_debug(); break;
|
|
case 2: clear_screen();
|
|
emu_forcedFrame(0);
|
|
darken_screen();
|
|
PDebugShowSpriteStats((unsigned short *)SCREEN_BUFFER + (SCREEN_HEIGHT/2 - 240/2)*SCREEN_WIDTH +
|
|
SCREEN_WIDTH/2 - 320/2, SCREEN_WIDTH); break;
|
|
case 3: clear_screen();
|
|
PDebugShowPalette(SCREEN_BUFFER, SCREEN_WIDTH);
|
|
PDebugShowSprite((unsigned short *)SCREEN_BUFFER + SCREEN_WIDTH*120+SCREEN_WIDTH/2+16,
|
|
SCREEN_WIDTH, spr_offs);
|
|
draw_text_debug(PDebugSpriteList(), spr_offs, 6);
|
|
break;
|
|
}
|
|
plat_video_menu_end();
|
|
|
|
inp = in_menu_wait(PBTN_EAST|PBTN_MBACK|PBTN_WEST|PBTN_NORTH|PBTN_L|PBTN_R|PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT);
|
|
if (inp & PBTN_MBACK) return;
|
|
if (inp & PBTN_L) { mode--; if (mode < 0) mode = 3; }
|
|
if (inp & PBTN_R) { mode++; if (mode > 3) mode = 0; }
|
|
switch (mode)
|
|
{
|
|
case 0:
|
|
if (inp & PBTN_EAST) SekStepM68k();
|
|
if (inp & PBTN_NORTH) {
|
|
while (inp & PBTN_NORTH) inp = in_menu_wait_any(-1);
|
|
mplayer_loop();
|
|
}
|
|
if ((inp & (PBTN_WEST|PBTN_LEFT)) == (PBTN_WEST|PBTN_LEFT)) {
|
|
mkdir("dumps", 0777);
|
|
PDebugDumpMem();
|
|
while (inp & PBTN_WEST) inp = in_menu_wait_any(-1);
|
|
dumped = 1;
|
|
}
|
|
break;
|
|
case 1:
|
|
if (inp & PBTN_LEFT) PicoDrawMask ^= PDRAW_LAYERB_ON;
|
|
if (inp & PBTN_RIGHT) PicoDrawMask ^= PDRAW_LAYERA_ON;
|
|
if (inp & PBTN_DOWN) PicoDrawMask ^= PDRAW_SPRITES_LOW_ON;
|
|
if (inp & PBTN_UP) PicoDrawMask ^= PDRAW_SPRITES_HI_ON;
|
|
if (inp & PBTN_EAST) {
|
|
PsndOut = NULL; // just in case
|
|
PicoSkipFrame = 1;
|
|
PicoFrame();
|
|
PicoSkipFrame = 0;
|
|
while (inp & PBTN_EAST) inp = in_menu_wait_any(-1);
|
|
}
|
|
break;
|
|
case 3:
|
|
if (inp & PBTN_DOWN) spr_offs++;
|
|
if (inp & PBTN_UP) spr_offs--;
|
|
if (spr_offs < 0) spr_offs = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif // !UIQ3
|
|
|
|
// ------------ util ------------
|
|
|
|
const char *me_region_name(unsigned int code, int auto_order)
|
|
{
|
|
static const char *names[] = { "Auto", " Japan NTSC", " Japan PAL", " USA", " Europe" };
|
|
static const char *names_short[] = { "", " JP", " JP", " US", " EU" };
|
|
int u, i = 0;
|
|
if (code) {
|
|
code <<= 1;
|
|
while((code >>= 1)) i++;
|
|
if (i > 4) return "unknown";
|
|
return names[i];
|
|
} else {
|
|
static char name[24];
|
|
strcpy(name, "Auto:");
|
|
for (u = 0; u < 3; u++) {
|
|
i = 0; code = ((auto_order >> u*4) & 0xf) << 1;
|
|
while((code >>= 1)) i++;
|
|
strcat(name, names_short[i]);
|
|
}
|
|
return name;
|
|
}
|
|
}
|
|
|
|
/* TODO: rename */
|
|
void menu_darken_bg(void *dst, int pixels, int darker)
|
|
{
|
|
unsigned int *screen = dst;
|
|
pixels /= 2;
|
|
if (darker)
|
|
{
|
|
while (pixels--)
|
|
{
|
|
unsigned int p = *screen;
|
|
*screen++ = ((p&0xf79ef79e)>>1) - ((p&0xc618c618)>>3);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (pixels--)
|
|
{
|
|
unsigned int p = *screen;
|
|
*screen++ = (p&0xf79ef79e)>>1;
|
|
}
|
|
}
|
|
}
|
|
|