Genesis-Plus-GX/source/ngc/gui/ggentry.c

352 lines
8.0 KiB
C
Raw Normal View History

2007-08-10 22:34:06 +02:00
/****************************************************************************
* Genesis Plus 1.2a
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Nintendo Gamecube Game Genie Entry
***************************************************************************/
#include "shared.h"
#include "font.h"
#include "rominfo.h"
#define MAXCODES 8
typedef struct
{
int address;
unsigned short data;
} GGPATCH;
/*** Game Genie Codes Array ***/
unsigned char ggcodes[MAXCODES][10]; /*** Codes are entered as XXXX-XXXX ***/
int gghpos[MAXCODES]; /*** Edit positions ***/
int ggrow = 0;
int editing = 0;
char ggvalidchars[] = "ABCDEFGHJKLMNPRSTVWXYZ0123456789*";
GGPATCH ggpatch[8];
extern char menutitle[];
/****************************************************************************
* Decode Game Genie entries to memory patches
****************************************************************************/
void decode_genie (char *code, int which)
{
char *p;
int n, i;
for (i = 0; i < 8; i++)
{
/*** This should only happen if memory is corrupt! ***/
p = strchr (ggvalidchars, code[i]);
if (p == NULL)
{
ggpatch[which].address = ggpatch[which].data = 0;
return;
}
n = p - ggvalidchars;
switch (i)
{
case 0:
ggpatch[which].data |= n << 3;
break;
case 1:
ggpatch[which].data |= n >> 2;
ggpatch[which].address |= (n & 3) << 14;
break;
case 2:
ggpatch[which].address |= n << 9;
break;
case 3:
ggpatch[which].address |= (n & 0xF) << 20 | (n >> 4) << 8;
break;
case 4:
ggpatch[which].data |= (n & 1) << 12;
ggpatch[which].address |= (n >> 1) << 16;
break;
case 5:
ggpatch[which].data |= (n & 1) << 15 | (n >> 1) << 8;
break;
case 6:
ggpatch[which].data |= (n >> 3) << 13;
ggpatch[which].address |= (n & 7) << 5;
break;
case 7:
ggpatch[which].address |= n;
break;
}
}
}
void decode_ggcodes ()
{
int i, j;
char thiscode[10];
/*** Clear out any old patches ***/
memset (&ggpatch[0], 0, 8 * sizeof (GGPATCH));
memset (&thiscode, 0, 10);
j = 0;
for (i = 0; i < 8; i++)
{
if (strcmp (ggcodes[i], "AAAA-AAAA"))
{
/*** Move the code into thiscode ***/
memcpy (&thiscode, &ggcodes[i], 4);
memcpy (&thiscode[4], &ggcodes[i][5], 4);
decode_genie (thiscode, j);
j++;
}
}
/*** And now apply the patches ***/
if (j)
{
for (i = 0; i < j; i++)
{
if (ggpatch[i].address < rominfo.romend)
{
/*** Patching ROM space ***/
cart_rom[ggpatch[i].address] = ggpatch[i].data & 0x0ff;
cart_rom[ggpatch[i].address + 1] = (ggpatch[i].data & 0xff00) >> 8;
}
else
{
/*** Patching 68K memory ***/
m68k_write_memory_16 (ggpatch[i].address, ggpatch[i].data);
}
}
/* TODO : Fix Checksum */
}
}
/****************************************************************************
* ClearGGCodes
*
* Should be called whenever a new rom is loaded
****************************************************************************/
void ClearGGCodes ()
{
int i;
for (i = 0; i < MAXCODES; i++)
{
strcpy (ggcodes[i], "AAAA-AAAA");
gghpos[i] = 0;
}
ggrow = 0;
}
/****************************************************************************
* DrawGGCodes
*
* Just draw the codes, with the current one highlighted.
****************************************************************************/
void DrawGGCodes ()
{
int i,j;
unsigned char c[2] = { 0, 0 };
ClearScreen ();
WriteCentre (134, menutitle);
for (i = 0; i < MAXCODES; i++)
{
if (i == ggrow)
{
/*** Highlight selected ***/
WriteCentre_HL (i * fheight + 224, ggcodes[i]);
/*** If editing, highlight the current character ***/
if (editing)
{
int hpos = 0;
for (j=0; j<strlen (ggcodes[i]); j++) hpos += font_size[ggcodes[i][j]];
hpos = ((640 - hpos) >> 1);
for (j=0; j<gghpos[i]; j++) hpos += font_size[ggcodes[i][j]];
c[0] = ggcodes[i][gghpos[i]];
fntDrawBoxFilled (hpos, (i * fheight) + 224, hpos + font_size[c[0]],
((i + 1) * fheight) + 224, COLOR_YELLOW);
setfontcolour (COLOR_BLUE);
write_font (hpos, (i * fheight) + 224, c);
setfontcolour (COLOR_WHITE);
}
}
else WriteCentre ((i * fheight) + 224, ggcodes[i]);
}
SetScreen ();
}
/****************************************************************************
* GGEditLine
*
* Up/Down traverses valid character array
* Left/Right moves along current line
* A exits edit mode
****************************************************************************/
void GGEditLine ()
{
short p;
char c[2] = { 0, 0 };
char *v;
int redraw = 1;
signed char x, y;
/** Lose any previous A press **/
while (PAD_ButtonsDown (0) & PAD_BUTTON_A);
editing = 1;
while (!(PAD_ButtonsDown (0) & PAD_BUTTON_A))
{
if (redraw)
{
DrawGGCodes ();
redraw = 0;
}
p = PAD_ButtonsDown (0);
x = PAD_StickX (0);
y = PAD_StickY (0);
if ((p & PAD_BUTTON_UP) || (y > 70))
{
/*** Increment the entry ***/
redraw = 1;
c[0] = ggcodes[ggrow][gghpos[ggrow]];
v = strstr (ggvalidchars, c);
v++;
if (*v == '*') ggcodes[ggrow][gghpos[ggrow]] = 'A';
else ggcodes[ggrow][gghpos[ggrow]] = *v;
}
if ((p & PAD_BUTTON_DOWN) || (y < -70))
{
/*** Decrement entry ***/
redraw = 1;
c[0] = ggcodes[ggrow][gghpos[ggrow]];
v = strstr (ggvalidchars, c);
if (*v == 'A') ggcodes[ggrow][gghpos[ggrow]] = '9';
else
{
v--;
ggcodes[ggrow][gghpos[ggrow]] = *v;
}
}
if ((p & PAD_BUTTON_LEFT) || (x < -70))
{
redraw = 1;
gghpos[ggrow]--;
if (gghpos[ggrow] == 4) gghpos[ggrow]--;
}
if ((p & PAD_BUTTON_RIGHT) || (x > 70))
{
redraw = 1;
gghpos[ggrow]++;
if (gghpos[ggrow] == 4) gghpos[ggrow]++;
}
if (gghpos[ggrow] < 0) gghpos[ggrow] = 8;
if (gghpos[ggrow] > 8) gghpos[ggrow] = 0;
}
/** Lose any previous A press **/
while (PAD_ButtonsDown (0) & PAD_BUTTON_A);
editing = 0;
}
/****************************************************************************
* GGSelectLine
*
* Select which line to edit
****************************************************************************/
void GGSelectLine ()
{
int redraw = 1;
int quit = 0;
short j;
signed char y;
/*** To select a line, just move up or down.
Pressing A will enter edit mode.
Pressing B will exit to caller. ***/
while (!(PAD_ButtonsDown (0) & PAD_BUTTON_B) && (quit == 0))
{
if (redraw)
{
DrawGGCodes ();
redraw = 0;
}
j = PAD_ButtonsDown (0);
y = PAD_StickY (0);
if ((j & PAD_BUTTON_UP) || (y > 70))
{
ggrow--;
redraw = 1;
}
if ((j & PAD_BUTTON_DOWN) || (y < -70))
{
ggrow++;
redraw = 1;
}
if (ggrow < 0) ggrow = MAXCODES - 1;
if (ggrow == MAXCODES) ggrow = 0;
if (j & PAD_BUTTON_B) quit = 1;
if (j & PAD_BUTTON_A)
{
GGEditLine ();
redraw = 1;
}
}
}
/****************************************************************************
* GetGGEntries
*
* Screen to return encoded Game Genie codes.
* No keyboard is available, so it's just a simple wrap round each line kind
* of thing.
****************************************************************************/
void GetGGEntries ()
{
editing = 0;
strcpy (menutitle, "Game Genie Entry");
GGSelectLine ();
}