mirror of
https://github.com/dborth/vbagx.git
synced 2024-11-26 04:24:16 +01:00
structure/system overhaul - partially working
This commit is contained in:
parent
e7dc70438e
commit
fc4c229edc
@ -16,6 +16,8 @@ static int tail = 0;
|
|||||||
static u8 mixerdata[MIXBUFFSIZE];
|
static u8 mixerdata[MIXBUFFSIZE];
|
||||||
#define MIXERMASK ((MIXBUFFSIZE >> 2) - 1)
|
#define MIXERMASK ((MIXBUFFSIZE >> 2) - 1)
|
||||||
|
|
||||||
|
static u8 soundbuffer[3200] ATTRIBUTE_ALIGN(32);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* MIXER_AddSamples
|
* MIXER_AddSamples
|
||||||
*
|
*
|
||||||
@ -71,3 +73,29 @@ int MIXER_GetSamples( u8 *dstbuffer, int maxlen )
|
|||||||
return 3200;
|
return 3200;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void AudioPlayer()
|
||||||
|
{
|
||||||
|
AUDIO_StopDMA();
|
||||||
|
MIXER_GetSamples(soundbuffer, 3200);
|
||||||
|
DCFlushRange(soundbuffer,3200);
|
||||||
|
AUDIO_InitDMA((u32)soundbuffer,3200);
|
||||||
|
AUDIO_StartDMA();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitialiseSound()
|
||||||
|
{
|
||||||
|
AUDIO_Init(NULL); // Start audio subsystem
|
||||||
|
AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
|
||||||
|
AUDIO_RegisterDMACallback(AudioPlayer);
|
||||||
|
memset(soundbuffer, 0, 3200);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopAudio()
|
||||||
|
{
|
||||||
|
AUDIO_StopDMA();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartAudio()
|
||||||
|
{
|
||||||
|
AUDIO_StartDMA();
|
||||||
|
}
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
void MIXER_AddSamples( u8 *sampledata, int len );
|
void MIXER_AddSamples( u8 *sampledata, int len );
|
||||||
int MIXER_GetSamples( u8 *dstbuffer, int maxlen );
|
int MIXER_GetSamples( u8 *dstbuffer, int maxlen );
|
||||||
|
void StopAudio();
|
||||||
|
void StartAudio();
|
||||||
|
void InitialiseSound();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
117
source/ngc/button_mapping.c
Normal file
117
source/ngc/button_mapping.c
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* michniewski August 2008
|
||||||
|
*
|
||||||
|
* button_mapping.c
|
||||||
|
*
|
||||||
|
* Controller button mapping
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <wiiuse/wpad.h>
|
||||||
|
|
||||||
|
#include "button_mapping.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Controller Button Descriptions:
|
||||||
|
* used for identifying which buttons have been pressed when configuring
|
||||||
|
* and for displaying the name of said button
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
CtrlrMap ctrlr_def[4] = {
|
||||||
|
// Nunchuk btn def
|
||||||
|
{
|
||||||
|
CTRLR_NUNCHUK,
|
||||||
|
13,
|
||||||
|
{
|
||||||
|
{WPAD_BUTTON_DOWN, "DOWN"},
|
||||||
|
{WPAD_BUTTON_UP, "UP"},
|
||||||
|
{WPAD_BUTTON_LEFT, "LEFT"},
|
||||||
|
{WPAD_BUTTON_RIGHT, "RIGHT"},
|
||||||
|
{WPAD_BUTTON_A, "A"},
|
||||||
|
{WPAD_BUTTON_B, "B"},
|
||||||
|
{WPAD_BUTTON_1, "1"},
|
||||||
|
{WPAD_BUTTON_2, "2"},
|
||||||
|
{WPAD_BUTTON_PLUS, "PLUS"},
|
||||||
|
{WPAD_BUTTON_MINUS, "MINUS"},
|
||||||
|
{WPAD_BUTTON_HOME, "HOME"},
|
||||||
|
{WPAD_NUNCHUK_BUTTON_Z, "Z"},
|
||||||
|
{WPAD_NUNCHUK_BUTTON_C, "C"},
|
||||||
|
{0, ""},
|
||||||
|
{0, ""}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Classic btn def
|
||||||
|
{
|
||||||
|
CTRLR_CLASSIC,
|
||||||
|
15,
|
||||||
|
{
|
||||||
|
{WPAD_CLASSIC_BUTTON_DOWN, "DOWN"},
|
||||||
|
{WPAD_CLASSIC_BUTTON_UP, "UP"},
|
||||||
|
{WPAD_CLASSIC_BUTTON_LEFT, "LEFT"},
|
||||||
|
{WPAD_CLASSIC_BUTTON_RIGHT, "RIGHT"},
|
||||||
|
{WPAD_CLASSIC_BUTTON_A, "A"},
|
||||||
|
{WPAD_CLASSIC_BUTTON_B, "B"},
|
||||||
|
{WPAD_CLASSIC_BUTTON_X, "X"},
|
||||||
|
{WPAD_CLASSIC_BUTTON_Y, "Y"},
|
||||||
|
{WPAD_CLASSIC_BUTTON_PLUS, "PLUS"},
|
||||||
|
{WPAD_CLASSIC_BUTTON_MINUS, "MINUS"},
|
||||||
|
{WPAD_CLASSIC_BUTTON_HOME, "HOME"},
|
||||||
|
{WPAD_CLASSIC_BUTTON_FULL_L, "L TRIG"},
|
||||||
|
{WPAD_CLASSIC_BUTTON_FULL_R, "R TRIG"},
|
||||||
|
{WPAD_CLASSIC_BUTTON_ZL, "ZL"},
|
||||||
|
{WPAD_CLASSIC_BUTTON_ZR, "ZR"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Gamecube controller btn def
|
||||||
|
{
|
||||||
|
CTRLR_GCPAD,
|
||||||
|
13,
|
||||||
|
{
|
||||||
|
{PAD_BUTTON_DOWN, "DOWN"},
|
||||||
|
{PAD_BUTTON_UP, "UP"},
|
||||||
|
{PAD_BUTTON_LEFT, "LEFT"},
|
||||||
|
{PAD_BUTTON_RIGHT, "RIGHT"},
|
||||||
|
{PAD_BUTTON_A, "A"},
|
||||||
|
{PAD_BUTTON_B, "B"},
|
||||||
|
{PAD_BUTTON_X, "X"},
|
||||||
|
{PAD_BUTTON_Y, "Y"},
|
||||||
|
{PAD_BUTTON_MENU, "MENU"},
|
||||||
|
{PAD_BUTTON_START, "START"},
|
||||||
|
{PAD_TRIGGER_L, "L TRIG"},
|
||||||
|
{PAD_TRIGGER_R, "R TRIG"},
|
||||||
|
{PAD_TRIGGER_Z, "Z"},
|
||||||
|
{0, ""},
|
||||||
|
{0, ""}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Wiimote btn def
|
||||||
|
{
|
||||||
|
CTRLR_WIIMOTE,
|
||||||
|
11,
|
||||||
|
{
|
||||||
|
{WPAD_BUTTON_DOWN, "DOWN"},
|
||||||
|
{WPAD_BUTTON_UP, "UP"},
|
||||||
|
{WPAD_BUTTON_LEFT, "LEFT"},
|
||||||
|
{WPAD_BUTTON_RIGHT, "RIGHT"},
|
||||||
|
{WPAD_BUTTON_A, "A"},
|
||||||
|
{WPAD_BUTTON_B, "B"},
|
||||||
|
{WPAD_BUTTON_1, "1"},
|
||||||
|
{WPAD_BUTTON_2, "2"},
|
||||||
|
{WPAD_BUTTON_PLUS, "PLUS"},
|
||||||
|
{WPAD_BUTTON_MINUS, "MINUS"},
|
||||||
|
{WPAD_BUTTON_HOME, "HOME"},
|
||||||
|
{0, ""},
|
||||||
|
{0, ""},
|
||||||
|
{0, ""},
|
||||||
|
{0, ""}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
38
source/ngc/button_mapping.h
Normal file
38
source/ngc/button_mapping.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* michniewski August 2008
|
||||||
|
*
|
||||||
|
* button_mapping.h
|
||||||
|
*
|
||||||
|
* Controller button mapping
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef BTN_MAP_H
|
||||||
|
#define BTN_MAP_H
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CTRLR_NONE = -1,
|
||||||
|
CTRLR_NUNCHUK,
|
||||||
|
CTRLR_CLASSIC,
|
||||||
|
CTRLR_GCPAD,
|
||||||
|
CTRLR_WIIMOTE,
|
||||||
|
CTRLR_SNES = 7 // give some other value for the snes padmap
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _btn_map {
|
||||||
|
u32 btn; // button 'id'
|
||||||
|
char* name; // button name
|
||||||
|
} BtnMap;
|
||||||
|
|
||||||
|
typedef struct _ctrlr_map {
|
||||||
|
u16 type; // controller type
|
||||||
|
int num_btns; // number of buttons on the controller
|
||||||
|
BtnMap map[15]; // controller button map
|
||||||
|
} CtrlrMap;
|
||||||
|
|
||||||
|
// externs:
|
||||||
|
|
||||||
|
extern CtrlrMap ctrlr_def[4];
|
||||||
|
|
||||||
|
#endif
|
573
source/ngc/dvd.cpp
Normal file
573
source/ngc/dvd.cpp
Normal file
@ -0,0 +1,573 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* svpe & crunchy2 June 2007
|
||||||
|
* Tantric September 2008
|
||||||
|
*
|
||||||
|
* dvd.cpp
|
||||||
|
*
|
||||||
|
* DVD I/O functions
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef WII_DVD
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#include <di/di.h>
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "menudraw.h"
|
||||||
|
#include "gcunzip.h"
|
||||||
|
|
||||||
|
extern int offset;
|
||||||
|
extern int selection;
|
||||||
|
extern FILEENTRIES filelist[MAXFILES];
|
||||||
|
extern int maxfiles;
|
||||||
|
u64 dvddir = 0;
|
||||||
|
u64 dvdrootdir = 0;
|
||||||
|
int dvddirlength = 0;
|
||||||
|
bool isWii = false;
|
||||||
|
|
||||||
|
#ifdef HW_DOL
|
||||||
|
/** DVD I/O Address base **/
|
||||||
|
volatile unsigned long *dvd = (volatile unsigned long *) 0xCC006000;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Due to lack of memory, we'll use this little 2k keyhole for all DVD operations **/
|
||||||
|
unsigned char DVDreadbuffer[2048] ATTRIBUTE_ALIGN (32);
|
||||||
|
unsigned char dvdbuffer[2048];
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* dvd_read
|
||||||
|
*
|
||||||
|
* The only DVD function we need - you gotta luv gc-linux self-boots!
|
||||||
|
* returns: 1 - ok ; 0 - error
|
||||||
|
***************************************************************************/
|
||||||
|
int
|
||||||
|
dvd_read (void *dst, unsigned int len, u64 offset)
|
||||||
|
{
|
||||||
|
|
||||||
|
unsigned char *buffer = (unsigned char *) (unsigned int) DVDreadbuffer;
|
||||||
|
|
||||||
|
if (len > 2048)
|
||||||
|
return 0; /*** We only allow 2k reads **/
|
||||||
|
|
||||||
|
DCInvalidateRange ((void *) buffer, len);
|
||||||
|
|
||||||
|
// don't read past the end of the DVD (1.5 GB for GC DVD, 4.7 GB for DVD)
|
||||||
|
if(offset < 0x57057C00 || (isWii && offset < 0x118244F00LL))
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef HW_DOL
|
||||||
|
|
||||||
|
dvd[0] = 0x2E;
|
||||||
|
dvd[1] = 0;
|
||||||
|
dvd[2] = 0xA8000000;
|
||||||
|
dvd[3] = (u32)(offset >> 2);
|
||||||
|
dvd[4] = len;
|
||||||
|
dvd[5] = (u32) buffer;
|
||||||
|
dvd[6] = len;
|
||||||
|
dvd[7] = 3; /*** Enable reading with DMA ***/
|
||||||
|
while (dvd[7] & 1);
|
||||||
|
memcpy (dst, buffer, len);
|
||||||
|
|
||||||
|
if (dvd[0] & 0x4) /* Ensure it has completed */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
#elif WII_DVD
|
||||||
|
int ret = 1;
|
||||||
|
ret = DI_ReadDVD(dst, len >> 11, (u32)(offset >> 11));
|
||||||
|
if (ret==0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Minimal ISO Directory Definition **/
|
||||||
|
#define RECLEN 0 /* Record length */
|
||||||
|
#define EXTENT 6 /* Extent */
|
||||||
|
#define FILE_LENGTH 14 /* File length (BIG ENDIAN) */
|
||||||
|
#define FILE_FLAGS 25 /* File flags */
|
||||||
|
#define FILENAME_LENGTH 32 /* Filename length */
|
||||||
|
#define FILENAME 33 /* ASCIIZ filename */
|
||||||
|
|
||||||
|
/** Minimal Primary Volume Descriptor **/
|
||||||
|
#define PVDROOT 0x9c
|
||||||
|
static int IsJoliet = 0;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Primary Volume Descriptor
|
||||||
|
*
|
||||||
|
* The PVD should reside between sector 16 and 31.
|
||||||
|
* This is for single session DVD only.
|
||||||
|
***************************************************************************/
|
||||||
|
int
|
||||||
|
getpvd ()
|
||||||
|
{
|
||||||
|
int sector = 16;
|
||||||
|
u32 rootdir32;
|
||||||
|
|
||||||
|
dvddir = dvddirlength = 0;
|
||||||
|
IsJoliet = -1;
|
||||||
|
|
||||||
|
/** Look for Joliet PVD first **/
|
||||||
|
while (sector < 32)
|
||||||
|
{
|
||||||
|
if (dvd_read (&dvdbuffer, 2048, (u64)(sector << 11)))
|
||||||
|
{
|
||||||
|
if (memcmp (&dvdbuffer, "\2CD001\1", 8) == 0)
|
||||||
|
{
|
||||||
|
memcpy(&rootdir32, &dvdbuffer[PVDROOT + EXTENT], 4);
|
||||||
|
dvddir = (u64)rootdir32;
|
||||||
|
dvddir <<= 11;
|
||||||
|
dvdrootdir = dvddir;
|
||||||
|
memcpy (&dvddirlength, &dvdbuffer[PVDROOT + FILE_LENGTH], 4);
|
||||||
|
IsJoliet = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0; /*** Can't read sector! ***/
|
||||||
|
sector++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsJoliet > 0) /*** Joliet PVD Found ? ***/
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
sector = 16;
|
||||||
|
|
||||||
|
/*** Look for standard ISO9660 PVD ***/
|
||||||
|
while (sector < 32)
|
||||||
|
{
|
||||||
|
if (dvd_read (&dvdbuffer, 2048, sector << 11))
|
||||||
|
{
|
||||||
|
if (memcmp (&dvdbuffer, "\1CD001\1", 8) == 0)
|
||||||
|
{
|
||||||
|
memcpy (&rootdir32, &dvdbuffer[PVDROOT + EXTENT], 4);
|
||||||
|
dvddir = (u64)rootdir32;
|
||||||
|
dvddir <<= 11;
|
||||||
|
dvdrootdir = dvddir;
|
||||||
|
memcpy (&dvddirlength, &dvdbuffer[PVDROOT + FILE_LENGTH], 4);
|
||||||
|
IsJoliet = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0; /*** Can't read sector! ***/
|
||||||
|
sector++;
|
||||||
|
}
|
||||||
|
return (IsJoliet == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* TestDVD()
|
||||||
|
*
|
||||||
|
* Tests if a ISO9660 DVD is inserted and available
|
||||||
|
***************************************************************************/
|
||||||
|
bool TestDVD()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!getpvd())
|
||||||
|
{
|
||||||
|
#ifdef HW_DOL
|
||||||
|
DVD_Mount();
|
||||||
|
#elif WII_DVD
|
||||||
|
DI_Mount();
|
||||||
|
while(DI_GetStatus() & DVD_INIT);
|
||||||
|
#endif
|
||||||
|
if (!getpvd())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* getentry
|
||||||
|
*
|
||||||
|
* Support function to return the next file entry, if any
|
||||||
|
* Declared static to avoid accidental external entry.
|
||||||
|
***************************************************************************/
|
||||||
|
static int diroffset = 0;
|
||||||
|
static int
|
||||||
|
getentry (int entrycount)
|
||||||
|
{
|
||||||
|
char fname[512]; /* Huge, but experience has determined this */
|
||||||
|
char *ptr;
|
||||||
|
char *filename;
|
||||||
|
char *filenamelength;
|
||||||
|
char *rr;
|
||||||
|
int j;
|
||||||
|
u32 offset32;
|
||||||
|
|
||||||
|
/* Basic checks */
|
||||||
|
if (entrycount >= MAXFILES)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (diroffset >= 2048)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/** Decode this entry **/
|
||||||
|
if (dvdbuffer[diroffset]) /* Record length available */
|
||||||
|
{
|
||||||
|
/* Update offsets into sector buffer */
|
||||||
|
ptr = (char *) &dvdbuffer[0];
|
||||||
|
ptr += diroffset;
|
||||||
|
filename = ptr + FILENAME;
|
||||||
|
filenamelength = ptr + FILENAME_LENGTH;
|
||||||
|
|
||||||
|
/* Check for wrap round - illegal in ISO spec,
|
||||||
|
* but certain crap writers do it! */
|
||||||
|
if ((diroffset + dvdbuffer[diroffset]) > 2048)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (*filenamelength)
|
||||||
|
{
|
||||||
|
memset (&fname, 0, 512);
|
||||||
|
|
||||||
|
if (!IsJoliet) /*** Do ISO 9660 first ***/
|
||||||
|
strcpy (fname, filename);
|
||||||
|
else
|
||||||
|
{ /*** The more tortuous unicode joliet entries ***/
|
||||||
|
for (j = 0; j < (*filenamelength >> 1); j++)
|
||||||
|
{
|
||||||
|
fname[j] = filename[j * 2 + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
fname[j] = 0;
|
||||||
|
|
||||||
|
if (strlen (fname) >= MAXJOLIET)
|
||||||
|
fname[MAXJOLIET - 1] = 0;
|
||||||
|
|
||||||
|
if (strlen (fname) == 0)
|
||||||
|
fname[0] = filename[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen (fname) == 0) // root entry
|
||||||
|
{
|
||||||
|
fname[0] = 0; // we'll skip it by setting the filename to 0 length
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fname[0] == 1)
|
||||||
|
{
|
||||||
|
if(dvddir == dvdrootdir) // at root already, don't show ..
|
||||||
|
fname[0] = 0;
|
||||||
|
else
|
||||||
|
strcpy (fname, "..");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Move *filenamelength to t,
|
||||||
|
* Only to stop gcc warning for noobs :)
|
||||||
|
*/
|
||||||
|
int t = *filenamelength;
|
||||||
|
fname[t] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** Rockridge Check **/
|
||||||
|
rr = strstr (fname, ";");
|
||||||
|
if (rr != NULL)
|
||||||
|
*rr = 0;
|
||||||
|
|
||||||
|
strcpy (filelist[entrycount].filename, fname);
|
||||||
|
fname[MAXDISPLAY - 1] = 0;
|
||||||
|
strcpy (filelist[entrycount].displayname, fname);
|
||||||
|
|
||||||
|
memcpy (&offset32, &dvdbuffer[diroffset + EXTENT], 4);
|
||||||
|
|
||||||
|
filelist[entrycount].offset = (u64)offset32;
|
||||||
|
memcpy (&filelist[entrycount].length, &dvdbuffer[diroffset + FILE_LENGTH], 4);
|
||||||
|
memcpy (&filelist[entrycount].flags, &dvdbuffer[diroffset + FILE_FLAGS], 1);
|
||||||
|
|
||||||
|
filelist[entrycount].offset <<= 11;
|
||||||
|
filelist[entrycount].flags = filelist[entrycount].flags & 2;
|
||||||
|
|
||||||
|
/*** Prepare for next entry ***/
|
||||||
|
|
||||||
|
diroffset += dvdbuffer[diroffset];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* parseDVDdirectory
|
||||||
|
*
|
||||||
|
* This function will parse the directory tree.
|
||||||
|
* It relies on dvddir and dvddirlength being pre-populated by a call to
|
||||||
|
* getpvd, a previous parse or a menu selection.
|
||||||
|
*
|
||||||
|
* The return value is number of files collected, or 0 on failure.
|
||||||
|
***************************************************************************/
|
||||||
|
int
|
||||||
|
ParseDVDdirectory ()
|
||||||
|
{
|
||||||
|
int pdlength;
|
||||||
|
u64 pdoffset;
|
||||||
|
u64 rdoffset;
|
||||||
|
int len = 0;
|
||||||
|
int filecount = 0;
|
||||||
|
|
||||||
|
// initialize selection
|
||||||
|
selection = offset = 0;
|
||||||
|
|
||||||
|
pdoffset = rdoffset = dvddir;
|
||||||
|
pdlength = dvddirlength;
|
||||||
|
filecount = 0;
|
||||||
|
|
||||||
|
// Clear any existing values
|
||||||
|
memset (&filelist, 0, sizeof (FILEENTRIES) * MAXFILES);
|
||||||
|
|
||||||
|
/*** Get as many files as possible ***/
|
||||||
|
while (len < pdlength)
|
||||||
|
{
|
||||||
|
if (dvd_read (&dvdbuffer, 2048, pdoffset) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
diroffset = 0;
|
||||||
|
|
||||||
|
while (getentry (filecount))
|
||||||
|
{
|
||||||
|
if(strlen(filelist[filecount].filename) > 0 && filecount < MAXFILES)
|
||||||
|
filecount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
len += 2048;
|
||||||
|
pdoffset = rdoffset + len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the file list
|
||||||
|
qsort(filelist, filecount, sizeof(FILEENTRIES), FileSortCallback);
|
||||||
|
|
||||||
|
return filecount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* DirectorySearch
|
||||||
|
*
|
||||||
|
* Searches for the directory name specified within the current directory
|
||||||
|
* Returns the index of the directory, or -1 if not found
|
||||||
|
***************************************************************************/
|
||||||
|
int DirectorySearch(char dir[512])
|
||||||
|
{
|
||||||
|
for (int i = 0; i < maxfiles; i++ )
|
||||||
|
if (strcmp(filelist[i].filename, dir) == 0)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* SwitchDVDFolder
|
||||||
|
*
|
||||||
|
* Recursively searches for any directory path 'dir' specified
|
||||||
|
* Also loads the directory contents via ParseDVDdirectory()
|
||||||
|
* It relies on dvddir, dvddirlength, and filelist being pre-populated
|
||||||
|
***************************************************************************/
|
||||||
|
bool SwitchDVDFolder(char * dir, int maxDepth)
|
||||||
|
{
|
||||||
|
if(maxDepth > 8) // only search to a max depth of 8 levels
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool lastdir = false;
|
||||||
|
char * nextdir = NULL;
|
||||||
|
unsigned int t = strcspn(dir, "/");
|
||||||
|
|
||||||
|
if(t != strlen(dir))
|
||||||
|
nextdir = dir + t + 1; // next directory path to find
|
||||||
|
else
|
||||||
|
lastdir = true;
|
||||||
|
|
||||||
|
dir[t] = 0;
|
||||||
|
|
||||||
|
int dirindex = DirectorySearch(dir);
|
||||||
|
|
||||||
|
if(dirindex >= 0)
|
||||||
|
{
|
||||||
|
dvddir = filelist[dirindex].offset;
|
||||||
|
dvddirlength = filelist[dirindex].length;
|
||||||
|
maxfiles = ParseDVDdirectory();
|
||||||
|
|
||||||
|
if(lastdir)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return SwitchDVDFolder(nextdir, maxDepth++);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SwitchDVDFolder(char origdir[])
|
||||||
|
{
|
||||||
|
// make a copy of origdir so we don't mess with original
|
||||||
|
char dir[200];
|
||||||
|
strcpy(dir, origdir);
|
||||||
|
|
||||||
|
char * dirptr = dir;
|
||||||
|
|
||||||
|
// strip off leading/trailing slashes on the directory path
|
||||||
|
// we don't want to screw up our recursion!
|
||||||
|
if(dir[0] == '/')
|
||||||
|
dirptr = dirptr + 1;
|
||||||
|
if(dir[strlen(dir)-1] == '/')
|
||||||
|
dir[strlen(dir)-1] = 0;
|
||||||
|
|
||||||
|
return SwitchDVDFolder(dirptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* LoadDVDFile
|
||||||
|
* This function will load a file from DVD, in BIN, SMD or ZIP format.
|
||||||
|
* The values for offset and length are inherited from dvddir and
|
||||||
|
* dvddirlength.
|
||||||
|
*
|
||||||
|
* The buffer parameter should re-use the initial ROM buffer.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
int
|
||||||
|
LoadDVDFile (unsigned char *buffer)
|
||||||
|
{
|
||||||
|
int offset;
|
||||||
|
int blocks;
|
||||||
|
int i;
|
||||||
|
u64 discoffset;
|
||||||
|
char readbuffer[2048];
|
||||||
|
|
||||||
|
// How many 2k blocks to read
|
||||||
|
blocks = dvddirlength / 2048;
|
||||||
|
offset = 0;
|
||||||
|
discoffset = dvddir;
|
||||||
|
ShowAction ((char*) "Loading...");
|
||||||
|
dvd_read (readbuffer, 2048, discoffset);
|
||||||
|
|
||||||
|
if (!IsZipFile (readbuffer))
|
||||||
|
{
|
||||||
|
for (i = 0; i < blocks; i++)
|
||||||
|
{
|
||||||
|
dvd_read (readbuffer, 2048, discoffset);
|
||||||
|
memcpy (buffer + offset, readbuffer, 2048);
|
||||||
|
offset += 2048;
|
||||||
|
discoffset += 2048;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** And final cleanup ***/
|
||||||
|
if (dvddirlength % 2048)
|
||||||
|
{
|
||||||
|
i = dvddirlength % 2048;
|
||||||
|
dvd_read (readbuffer, 2048, discoffset);
|
||||||
|
memcpy (buffer + offset, readbuffer, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return UnZipFile (buffer, discoffset); // unzip from dvd
|
||||||
|
}
|
||||||
|
return dvddirlength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* uselessinquiry
|
||||||
|
*
|
||||||
|
* As the name suggests, this function is quite useless.
|
||||||
|
* It's only purpose is to stop any pending DVD interrupts while we use the
|
||||||
|
* memcard interface.
|
||||||
|
*
|
||||||
|
* libOGC tends to foul up if you don't, and sometimes does if you do!
|
||||||
|
***************************************************************************/
|
||||||
|
#ifdef HW_DOL
|
||||||
|
void uselessinquiry ()
|
||||||
|
{
|
||||||
|
dvd[0] = 0;
|
||||||
|
dvd[1] = 0;
|
||||||
|
dvd[2] = 0x12000000;
|
||||||
|
dvd[3] = 0;
|
||||||
|
dvd[4] = 0x20;
|
||||||
|
dvd[5] = 0x80000000;
|
||||||
|
dvd[6] = 0x20;
|
||||||
|
dvd[7] = 1;
|
||||||
|
|
||||||
|
while (dvd[7] & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* dvd_motor_off( )
|
||||||
|
* Turns off DVD drive motor so it doesn't make noise (Gamecube only)
|
||||||
|
***************************************************************************/
|
||||||
|
void dvd_motor_off( )
|
||||||
|
{
|
||||||
|
dvd[0] = 0x2e;
|
||||||
|
dvd[1] = 0;
|
||||||
|
dvd[2] = 0xe3000000;
|
||||||
|
dvd[3] = 0;
|
||||||
|
dvd[4] = 0;
|
||||||
|
dvd[5] = 0;
|
||||||
|
dvd[6] = 0;
|
||||||
|
dvd[7] = 1; // Do immediate
|
||||||
|
while (dvd[7] & 1);
|
||||||
|
|
||||||
|
/*** PSO Stops blackscreen at reload ***/
|
||||||
|
dvd[0] = 0x14;
|
||||||
|
dvd[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* dvd_driveid
|
||||||
|
*
|
||||||
|
* Gets and returns the dvd driveid
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
int dvd_driveid()
|
||||||
|
{
|
||||||
|
static unsigned char *inquiry=(unsigned char *)0x80000004;
|
||||||
|
|
||||||
|
dvd[0] = 0x2e;
|
||||||
|
dvd[1] = 0;
|
||||||
|
dvd[2] = 0x12000000;
|
||||||
|
dvd[3] = 0;
|
||||||
|
dvd[4] = 0x20;
|
||||||
|
dvd[5] = 0x80000000;
|
||||||
|
dvd[6] = 0x20;
|
||||||
|
dvd[7] = 3;
|
||||||
|
|
||||||
|
while( dvd[7] & 1 )
|
||||||
|
;
|
||||||
|
DCFlushRange((void *)0x80000000, 32);
|
||||||
|
|
||||||
|
return (int)inquiry[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* SetDVDDriveType()
|
||||||
|
*
|
||||||
|
* Sets the DVD drive ID for use to determine disc size (1.5 GB or 4.7 GB)
|
||||||
|
***************************************************************************/
|
||||||
|
void SetDVDDriveType()
|
||||||
|
{
|
||||||
|
#ifdef HW_RVL
|
||||||
|
isWii = true;
|
||||||
|
#else
|
||||||
|
int drvid = dvd_driveid ();
|
||||||
|
if ( drvid == 4 || drvid == 6 || drvid == 8 )
|
||||||
|
isWii = false;
|
||||||
|
else
|
||||||
|
isWii = true;
|
||||||
|
#endif
|
||||||
|
}
|
24
source/ngc/dvd.h
Normal file
24
source/ngc/dvd.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* svpe & crunchy2 June 2007
|
||||||
|
* Tantric September 2008
|
||||||
|
*
|
||||||
|
* dvd.h
|
||||||
|
*
|
||||||
|
* DVD I/O functions
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _NGCDVD_
|
||||||
|
#define _NGCDVD_
|
||||||
|
|
||||||
|
int getpvd ();
|
||||||
|
int ParseDVDdirectory ();
|
||||||
|
int LoadDVDFile (unsigned char *buffer);
|
||||||
|
bool TestDVD();
|
||||||
|
int dvd_read (void *dst, unsigned int len, u64 offset);
|
||||||
|
bool SwitchDVDFolder(char dir[]);
|
||||||
|
void SetDVDDriveType();
|
||||||
|
|
||||||
|
#endif
|
286
source/ngc/fileop.cpp
Normal file
286
source/ngc/fileop.cpp
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* crunchy2 May 2007
|
||||||
|
* Tantric August 2008
|
||||||
|
*
|
||||||
|
* fileop.cpp
|
||||||
|
*
|
||||||
|
* FAT File operations
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#include "vba.h"
|
||||||
|
#include "vbasupport.h"
|
||||||
|
#include "fileop.h"
|
||||||
|
#include "gcunzip.h"
|
||||||
|
#include "video.h"
|
||||||
|
#include "menudraw.h"
|
||||||
|
#include "filesel.h"
|
||||||
|
#include "preferences.h"
|
||||||
|
|
||||||
|
FILE * filehandle;
|
||||||
|
|
||||||
|
extern unsigned char savebuffer[];
|
||||||
|
extern char output[16384];
|
||||||
|
extern int offset;
|
||||||
|
extern int selection;
|
||||||
|
extern char currentdir[MAXPATHLEN];
|
||||||
|
extern FILEENTRIES filelist[MAXFILES];
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* fat_is_mounted
|
||||||
|
* to check whether FAT media are detected.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
bool FatIsMounted(PARTITION_INTERFACE partition) {
|
||||||
|
char prefix[] = "fatX:/";
|
||||||
|
prefix[3] = partition + '0';
|
||||||
|
DIR_ITER *dir = diropen(prefix);
|
||||||
|
if (dir) {
|
||||||
|
dirclose(dir);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* changeFATInterface
|
||||||
|
* Checks if the device (method) specified is available, and
|
||||||
|
* sets libfat to use the device
|
||||||
|
***************************************************************************/
|
||||||
|
bool ChangeFATInterface(int method, bool silent)
|
||||||
|
{
|
||||||
|
bool devFound = false;
|
||||||
|
|
||||||
|
if(method == METHOD_SD)
|
||||||
|
{
|
||||||
|
// check which SD device is loaded
|
||||||
|
|
||||||
|
#ifdef HW_RVL
|
||||||
|
if (FatIsMounted(PI_INTERNAL_SD))
|
||||||
|
{
|
||||||
|
devFound = true;
|
||||||
|
fatSetDefaultInterface(PI_INTERNAL_SD);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!devFound && FatIsMounted(PI_SDGECKO_A))
|
||||||
|
{
|
||||||
|
devFound = true;
|
||||||
|
fatSetDefaultInterface(PI_SDGECKO_A);
|
||||||
|
}
|
||||||
|
if(!devFound && FatIsMounted(PI_SDGECKO_B))
|
||||||
|
{
|
||||||
|
devFound = true;
|
||||||
|
fatSetDefaultInterface(PI_SDGECKO_B);
|
||||||
|
}
|
||||||
|
if(!devFound)
|
||||||
|
{
|
||||||
|
if(!silent)
|
||||||
|
WaitPrompt ((char *)"SD card not found!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(method == METHOD_USB)
|
||||||
|
{
|
||||||
|
#ifdef HW_RVL
|
||||||
|
if(FatIsMounted(PI_USBSTORAGE))
|
||||||
|
{
|
||||||
|
devFound = true;
|
||||||
|
fatSetDefaultInterface(PI_USBSTORAGE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!silent)
|
||||||
|
WaitPrompt ((char *)"USB flash drive not found!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return devFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* Browse FAT subdirectories
|
||||||
|
**************************************************************************/
|
||||||
|
int
|
||||||
|
ParseFATdirectory(int method)
|
||||||
|
{
|
||||||
|
int nbfiles = 0;
|
||||||
|
DIR_ITER *fatdir;
|
||||||
|
char filename[MAXPATHLEN];
|
||||||
|
struct stat filestat;
|
||||||
|
char msg[128];
|
||||||
|
|
||||||
|
// initialize selection
|
||||||
|
selection = offset = 0;
|
||||||
|
|
||||||
|
// Clear any existing values
|
||||||
|
memset (&filelist, 0, sizeof (FILEENTRIES) * MAXFILES);
|
||||||
|
|
||||||
|
// open the directory
|
||||||
|
fatdir = diropen(currentdir);
|
||||||
|
if (fatdir == NULL)
|
||||||
|
{
|
||||||
|
sprintf(msg, "Couldn't open %s", currentdir);
|
||||||
|
WaitPrompt(msg);
|
||||||
|
|
||||||
|
// if we can't open the dir, open root dir
|
||||||
|
sprintf(currentdir,"%s",ROOTFATDIR);
|
||||||
|
|
||||||
|
fatdir = diropen(currentdir);
|
||||||
|
|
||||||
|
if (fatdir == NULL)
|
||||||
|
{
|
||||||
|
sprintf(msg, "Error opening %s", currentdir);
|
||||||
|
WaitPrompt(msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// index files/folders
|
||||||
|
while(dirnext(fatdir,filename,&filestat) == 0)
|
||||||
|
{
|
||||||
|
if(strcmp(filename,".") != 0)
|
||||||
|
{
|
||||||
|
memset(&filelist[nbfiles], 0, sizeof(FILEENTRIES));
|
||||||
|
strncpy(filelist[nbfiles].filename, filename, MAXPATHLEN);
|
||||||
|
strncpy(filelist[nbfiles].displayname, filename, MAXDISPLAY+1); // crop name for display
|
||||||
|
filelist[nbfiles].length = filestat.st_size;
|
||||||
|
filelist[nbfiles].flags = (filestat.st_mode & _IFDIR) == 0 ? 0 : 1; // flag this as a dir
|
||||||
|
nbfiles++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// close directory
|
||||||
|
dirclose(fatdir);
|
||||||
|
|
||||||
|
// Sort the file list
|
||||||
|
qsort(filelist, nbfiles, sizeof(FILEENTRIES), FileSortCallback);
|
||||||
|
|
||||||
|
return nbfiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* LoadFATFile
|
||||||
|
***************************************************************************/
|
||||||
|
int
|
||||||
|
LoadFATFile (char *filename, int length)
|
||||||
|
{
|
||||||
|
char zipbuffer[2048];
|
||||||
|
char filepath[MAXPATHLEN];
|
||||||
|
FILE *handle;
|
||||||
|
unsigned char *rbuffer;
|
||||||
|
u32 size;
|
||||||
|
|
||||||
|
/* Check filename length */
|
||||||
|
if ((strlen(currentdir)+1+strlen(filelist[selection].filename)) < MAXPATHLEN)
|
||||||
|
sprintf(filepath, "%s/%s",currentdir,filelist[selection].filename);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WaitPrompt((char*) "Maximum filepath length reached!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return loadVBAROM(filepath);
|
||||||
|
/*
|
||||||
|
handle = fopen (filepath, "rb");
|
||||||
|
if (handle > 0)
|
||||||
|
{
|
||||||
|
fread (zipbuffer, 1, 2048, handle);
|
||||||
|
|
||||||
|
if (IsZipFile (zipbuffer))
|
||||||
|
{
|
||||||
|
size = UnZipFile (rbuffer, handle); // unzip from FAT
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Just load the file up
|
||||||
|
fseek(handle, 0, SEEK_END);
|
||||||
|
length = ftell(handle); // get filesize
|
||||||
|
fseek(handle, 2048, SEEK_SET); // seek back to point where we left off
|
||||||
|
memcpy (rbuffer, zipbuffer, 2048); // copy what we already read
|
||||||
|
fread (rbuffer + 2048, 1, length - 2048, handle);
|
||||||
|
size = length;
|
||||||
|
}
|
||||||
|
fclose (handle);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WaitPrompt((char*) "Error opening file");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Load savebuffer from FAT file
|
||||||
|
***************************************************************************/
|
||||||
|
int
|
||||||
|
LoadBufferFromFAT (char *filepath, bool silent)
|
||||||
|
{
|
||||||
|
FILE *handle;
|
||||||
|
int boffset = 0;
|
||||||
|
int read = 0;
|
||||||
|
|
||||||
|
ClearSaveBuffer ();
|
||||||
|
|
||||||
|
handle = fopen (filepath, "rb");
|
||||||
|
|
||||||
|
if (handle <= 0)
|
||||||
|
{
|
||||||
|
if ( !silent )
|
||||||
|
{
|
||||||
|
char msg[100];
|
||||||
|
sprintf(msg, "Couldn't open %s", filepath);
|
||||||
|
WaitPrompt (msg);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** This is really nice, just load the file and decode it ***/
|
||||||
|
while ((read = fread (savebuffer + boffset, 1, 1024, handle)) > 0)
|
||||||
|
{
|
||||||
|
boffset += read;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose (handle);
|
||||||
|
|
||||||
|
return boffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Write savebuffer to FAT card file
|
||||||
|
***************************************************************************/
|
||||||
|
int
|
||||||
|
SaveBufferToFAT (char *filepath, int datasize, bool silent)
|
||||||
|
{
|
||||||
|
FILE *handle;
|
||||||
|
|
||||||
|
if (datasize)
|
||||||
|
{
|
||||||
|
handle = fopen (filepath, "wb");
|
||||||
|
|
||||||
|
if (handle <= 0)
|
||||||
|
{
|
||||||
|
char msg[100];
|
||||||
|
sprintf(msg, "Couldn't save %s", filepath);
|
||||||
|
WaitPrompt (msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite (savebuffer, 1, datasize, handle);
|
||||||
|
fclose (handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearSaveBuffer ();
|
||||||
|
return datasize;
|
||||||
|
}
|
34
source/ngc/fileop.h
Normal file
34
source/ngc/fileop.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* crunchy2 May 2007
|
||||||
|
* Tantric August 2008
|
||||||
|
*
|
||||||
|
* fileop.h
|
||||||
|
*
|
||||||
|
* FAT File operations
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _FATFILESC_
|
||||||
|
#define _FATFILESC_
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <fat.h>
|
||||||
|
#include <sys/dir.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define ROOTFATDIR "fat:/"
|
||||||
|
|
||||||
|
bool ChangeFATInterface(int method, bool silent);
|
||||||
|
int ParseFATdirectory(int method);
|
||||||
|
int LoadFATFile (char *filename, int length);
|
||||||
|
int SaveBufferToFAT (char *filepath, int datasize, bool silent);
|
||||||
|
int LoadBufferFromFAT (char *filepath, bool silent);
|
||||||
|
|
||||||
|
extern char currFATdir[MAXPATHLEN];
|
||||||
|
|
||||||
|
#endif
|
587
source/ngc/filesel.cpp
Normal file
587
source/ngc/filesel.cpp
Normal file
@ -0,0 +1,587 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* svpe June 2007
|
||||||
|
* crunchy2 May-July 2007
|
||||||
|
* Tantric August 2008
|
||||||
|
*
|
||||||
|
* filesel.cpp
|
||||||
|
*
|
||||||
|
* Generic file routines - reading, writing, browsing
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <wiiuse/wpad.h>
|
||||||
|
#include <sys/dir.h>
|
||||||
|
|
||||||
|
#ifdef WII_DVD
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#include <di/di.h>
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "vba.h"
|
||||||
|
#include "vbasupport.h"
|
||||||
|
#include "vmmem.h"
|
||||||
|
#include "menudraw.h"
|
||||||
|
#include "video.h"
|
||||||
|
#include "filesel.h"
|
||||||
|
#include "fileop.h"
|
||||||
|
#include "memcardop.h"
|
||||||
|
#include "input.h"
|
||||||
|
#include "dvd.h"
|
||||||
|
#include "smbop.h"
|
||||||
|
|
||||||
|
int offset;
|
||||||
|
int selection;
|
||||||
|
char currentdir[MAXPATHLEN];
|
||||||
|
int maxfiles;
|
||||||
|
extern int screenheight;
|
||||||
|
|
||||||
|
int havedir = -1;
|
||||||
|
extern u64 dvddir;
|
||||||
|
extern int dvddirlength;
|
||||||
|
|
||||||
|
int hasloaded = 0;
|
||||||
|
|
||||||
|
// Global file entry table
|
||||||
|
FILEENTRIES filelist[MAXFILES];
|
||||||
|
|
||||||
|
unsigned char savebuffer[SAVEBUFFERSIZE] ATTRIBUTE_ALIGN (32);
|
||||||
|
|
||||||
|
char ROMFilename[512];
|
||||||
|
int ROMSize = 0;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* ClearSaveBuffer ()
|
||||||
|
* Clear the savebuffer
|
||||||
|
***************************************************************************/
|
||||||
|
void
|
||||||
|
ClearSaveBuffer ()
|
||||||
|
{
|
||||||
|
memset (savebuffer, 0, SAVEBUFFERSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* autoLoadMethod()
|
||||||
|
* Auto-determines and sets the load method
|
||||||
|
* Returns method set
|
||||||
|
****************************************************************************/
|
||||||
|
int autoLoadMethod()
|
||||||
|
{
|
||||||
|
ShowAction ((char*) "Attempting to determine load method...");
|
||||||
|
|
||||||
|
if(ChangeFATInterface(METHOD_SD, SILENT))
|
||||||
|
return METHOD_SD;
|
||||||
|
else if(ChangeFATInterface(METHOD_USB, SILENT))
|
||||||
|
return METHOD_USB;
|
||||||
|
else if(TestDVD())
|
||||||
|
return METHOD_DVD;
|
||||||
|
else if(ConnectShare (SILENT))
|
||||||
|
return METHOD_SMB;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WaitPrompt((char*) "Unable to auto-determine load method!");
|
||||||
|
return 0; // no method found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* autoSaveMethod()
|
||||||
|
* Auto-determines and sets the save method
|
||||||
|
* Returns method set
|
||||||
|
****************************************************************************/
|
||||||
|
int autoSaveMethod()
|
||||||
|
{
|
||||||
|
ShowAction ((char*) "Attempting to determine save method...");
|
||||||
|
|
||||||
|
if(ChangeFATInterface(METHOD_SD, SILENT))
|
||||||
|
return METHOD_SD;
|
||||||
|
else if(ChangeFATInterface(METHOD_USB, SILENT))
|
||||||
|
return METHOD_USB;
|
||||||
|
else if(TestCard(CARD_SLOTA, SILENT))
|
||||||
|
return METHOD_MC_SLOTA;
|
||||||
|
else if(TestCard(CARD_SLOTB, SILENT))
|
||||||
|
return METHOD_MC_SLOTB;
|
||||||
|
else if(ConnectShare (SILENT))
|
||||||
|
return METHOD_SMB;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WaitPrompt((char*) "Unable to auto-determine save method!");
|
||||||
|
return 0; // no method found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* UpdateDirName()
|
||||||
|
* Update curent directory name for file browser
|
||||||
|
***************************************************************************/
|
||||||
|
int UpdateDirName(int method)
|
||||||
|
{
|
||||||
|
int size=0;
|
||||||
|
char *test;
|
||||||
|
char temp[1024];
|
||||||
|
|
||||||
|
// update DVD directory (does not utilize 'currentdir')
|
||||||
|
if(method == METHOD_DVD)
|
||||||
|
{
|
||||||
|
dvddir = filelist[selection].offset;
|
||||||
|
dvddirlength = filelist[selection].length;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* current directory doesn't change */
|
||||||
|
if (strcmp(filelist[selection].filename,".") == 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* go up to parent directory */
|
||||||
|
else if (strcmp(filelist[selection].filename,"..") == 0)
|
||||||
|
{
|
||||||
|
/* determine last subdirectory namelength */
|
||||||
|
sprintf(temp,"%s",currentdir);
|
||||||
|
test = strtok(temp,"/");
|
||||||
|
while (test != NULL)
|
||||||
|
{
|
||||||
|
size = strlen(test);
|
||||||
|
test = strtok(NULL,"/");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove last subdirectory name */
|
||||||
|
size = strlen(currentdir) - size - 1;
|
||||||
|
currentdir[size] = 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* Open a directory */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* test new directory namelength */
|
||||||
|
if ((strlen(currentdir)+1+strlen(filelist[selection].filename)) < MAXPATHLEN)
|
||||||
|
{
|
||||||
|
/* update current directory name */
|
||||||
|
sprintf(currentdir, "%s/%s",currentdir, filelist[selection].filename);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WaitPrompt((char*)"Directory name is too long !");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* FileSortCallback
|
||||||
|
*
|
||||||
|
* Quick sort callback to sort file entries with the following order:
|
||||||
|
* .
|
||||||
|
* ..
|
||||||
|
* <dirs>
|
||||||
|
* <files>
|
||||||
|
***************************************************************************/
|
||||||
|
int FileSortCallback(const void *f1, const void *f2)
|
||||||
|
{
|
||||||
|
/* Special case for implicit directories */
|
||||||
|
if(((FILEENTRIES *)f1)->filename[0] == '.' || ((FILEENTRIES *)f2)->filename[0] == '.')
|
||||||
|
{
|
||||||
|
if(strcmp(((FILEENTRIES *)f1)->filename, ".") == 0) { return -1; }
|
||||||
|
if(strcmp(((FILEENTRIES *)f2)->filename, ".") == 0) { return 1; }
|
||||||
|
if(strcmp(((FILEENTRIES *)f1)->filename, "..") == 0) { return -1; }
|
||||||
|
if(strcmp(((FILEENTRIES *)f2)->filename, "..") == 0) { return 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If one is a file and one is a directory the directory is first. */
|
||||||
|
if(((FILEENTRIES *)f1)->flags && !(((FILEENTRIES *)f2)->flags)) return -1;
|
||||||
|
if(!(((FILEENTRIES *)f1)->flags) && ((FILEENTRIES *)f2)->flags) return 1;
|
||||||
|
|
||||||
|
return stricmp(((FILEENTRIES *)f1)->filename, ((FILEENTRIES *)f2)->filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* StripExt
|
||||||
|
*
|
||||||
|
* Strips an extension from a filename
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
void StripExt(char* returnstring, char * inputstring)
|
||||||
|
{
|
||||||
|
char* loc_dot;
|
||||||
|
|
||||||
|
strcpy (returnstring, inputstring);
|
||||||
|
loc_dot = strrchr(returnstring,'.');
|
||||||
|
if (loc_dot != NULL)
|
||||||
|
*loc_dot = '\0'; // strip file extension
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* FileSelector
|
||||||
|
*
|
||||||
|
* Let user select a file from the listing
|
||||||
|
***************************************************************************/
|
||||||
|
int FileSelector (int method)
|
||||||
|
{
|
||||||
|
u32 p = 0;
|
||||||
|
u32 wp = 0;
|
||||||
|
u32 ph = 0;
|
||||||
|
u32 wh = 0;
|
||||||
|
signed char gc_ay = 0;
|
||||||
|
signed char gc_sx = 0;
|
||||||
|
signed char wm_ay = 0;
|
||||||
|
signed char wm_sx = 0;
|
||||||
|
|
||||||
|
int haverom = 0;
|
||||||
|
int redraw = 1;
|
||||||
|
int selectit = 0;
|
||||||
|
|
||||||
|
int scroll_delay = 0;
|
||||||
|
bool move_selection = 0;
|
||||||
|
#define SCROLL_INITIAL_DELAY 15
|
||||||
|
#define SCROLL_LOOP_DELAY 2
|
||||||
|
|
||||||
|
while (haverom == 0)
|
||||||
|
{
|
||||||
|
if (redraw)
|
||||||
|
ShowFiles (filelist, maxfiles, offset, selection);
|
||||||
|
redraw = 0;
|
||||||
|
|
||||||
|
VIDEO_WaitVSync(); // slow things down a bit so we don't overread the pads
|
||||||
|
|
||||||
|
gc_ay = PAD_StickY (0);
|
||||||
|
gc_sx = PAD_SubStickX (0);
|
||||||
|
|
||||||
|
p = PAD_ButtonsDown (0);
|
||||||
|
ph = PAD_ButtonsHeld (0);
|
||||||
|
#ifdef HW_RVL
|
||||||
|
wm_ay = WPAD_StickY (0, 0);
|
||||||
|
wm_sx = WPAD_StickX (0, 1);
|
||||||
|
|
||||||
|
wp = WPAD_ButtonsDown (0);
|
||||||
|
wh = WPAD_ButtonsHeld (0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*** Check for exit combo ***/
|
||||||
|
if ( (gc_sx < -70) || (wm_sx < -70) || (wp & WPAD_BUTTON_HOME) || (wp & WPAD_CLASSIC_BUTTON_HOME) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*** Check buttons, perform actions ***/
|
||||||
|
if ( (p & PAD_BUTTON_A) || selectit || (wp & (WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A)) )
|
||||||
|
{
|
||||||
|
if ( selectit )
|
||||||
|
selectit = 0;
|
||||||
|
if (filelist[selection].flags) // This is directory
|
||||||
|
{
|
||||||
|
/* update current directory and set new entry list if directory has changed */
|
||||||
|
int status = UpdateDirName(method);
|
||||||
|
if (status == 1) // ok, open directory
|
||||||
|
{
|
||||||
|
switch (method)
|
||||||
|
{
|
||||||
|
case METHOD_SD:
|
||||||
|
case METHOD_USB:
|
||||||
|
maxfiles = ParseFATdirectory(method);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case METHOD_DVD:
|
||||||
|
maxfiles = ParseDVDdirectory();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case METHOD_SMB:
|
||||||
|
maxfiles = ParseSMBdirectory();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!maxfiles)
|
||||||
|
{
|
||||||
|
WaitPrompt ((char*) "Error reading directory !");
|
||||||
|
haverom = 1; // quit menu
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (status == -1) // directory name too long
|
||||||
|
{
|
||||||
|
haverom = 1; // quit menu
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // this is a file
|
||||||
|
{
|
||||||
|
// store the filename (w/o ext) - used for sram/freeze naming
|
||||||
|
StripExt(ROMFilename, filelist[selection].filename);
|
||||||
|
|
||||||
|
ShowAction ((char *)"Loading...");
|
||||||
|
|
||||||
|
switch (method)
|
||||||
|
{
|
||||||
|
case METHOD_SD:
|
||||||
|
case METHOD_USB:
|
||||||
|
ROMSize = LoadFATFile (filelist[selection].filename, filelist[selection].length);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case METHOD_DVD:
|
||||||
|
dvddir = filelist[selection].offset;
|
||||||
|
dvddirlength = filelist[selection].length;
|
||||||
|
//ROMSize = LoadDVDFile (Memory.ROM);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case METHOD_SMB:
|
||||||
|
//ROMSize = LoadSMBFile (filelist[selection].filename, filelist[selection].length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ROMSize > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WaitPrompt((char*) "Error loading ROM!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
redraw = 1;
|
||||||
|
} // End of A
|
||||||
|
if ( (p & PAD_BUTTON_B) || (wp & (WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B)) )
|
||||||
|
{
|
||||||
|
while ( (PAD_ButtonsDown(0) & PAD_BUTTON_B)
|
||||||
|
#ifdef HW_RVL
|
||||||
|
|| (WPAD_ButtonsDown(0) & (WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B))
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
if ( strcmp(filelist[0].filename,"..") == 0 )
|
||||||
|
{
|
||||||
|
selection = 0;
|
||||||
|
selectit = 1;
|
||||||
|
}
|
||||||
|
else if ( strcmp(filelist[1].filename,"..") == 0 )
|
||||||
|
{
|
||||||
|
selection = selectit = 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} // End of B
|
||||||
|
if ( ((p | ph) & PAD_BUTTON_DOWN) || ((wp | wh) & (WPAD_BUTTON_DOWN | WPAD_CLASSIC_BUTTON_DOWN)) || (gc_ay < -PADCAL) || (wm_ay < -PADCAL) )
|
||||||
|
{
|
||||||
|
if ( (p & PAD_BUTTON_DOWN) || (wp & (WPAD_BUTTON_DOWN | WPAD_CLASSIC_BUTTON_DOWN)) ) { /*** Button just pressed ***/
|
||||||
|
scroll_delay = SCROLL_INITIAL_DELAY; // reset scroll delay.
|
||||||
|
move_selection = 1; //continue (move selection)
|
||||||
|
}
|
||||||
|
else if (scroll_delay == 0) { /*** Button is held ***/
|
||||||
|
scroll_delay = SCROLL_LOOP_DELAY;
|
||||||
|
move_selection = 1; //continue (move selection)
|
||||||
|
} else {
|
||||||
|
scroll_delay--; // wait
|
||||||
|
}
|
||||||
|
|
||||||
|
if (move_selection)
|
||||||
|
{
|
||||||
|
selection++;
|
||||||
|
if (selection == maxfiles)
|
||||||
|
selection = offset = 0;
|
||||||
|
if ((selection - offset) >= PAGESIZE)
|
||||||
|
offset += PAGESIZE;
|
||||||
|
redraw = 1;
|
||||||
|
move_selection = 0;
|
||||||
|
}
|
||||||
|
} // End of down
|
||||||
|
if ( ((p | ph) & PAD_BUTTON_UP) || ((wp | wh) & (WPAD_BUTTON_UP | WPAD_CLASSIC_BUTTON_UP)) || (gc_ay > PADCAL) || (wm_ay > PADCAL) )
|
||||||
|
{
|
||||||
|
if ( (p & PAD_BUTTON_UP) || (wp & (WPAD_BUTTON_UP | WPAD_CLASSIC_BUTTON_UP)) ) { /*** Button just pressed***/
|
||||||
|
scroll_delay = SCROLL_INITIAL_DELAY; // reset scroll delay.
|
||||||
|
move_selection = 1; //continue (move selection)
|
||||||
|
}
|
||||||
|
else if (scroll_delay == 0) { /*** Button is held ***/
|
||||||
|
scroll_delay = SCROLL_LOOP_DELAY;
|
||||||
|
move_selection = 1; //continue (move selection)
|
||||||
|
} else {
|
||||||
|
scroll_delay--; // wait
|
||||||
|
}
|
||||||
|
|
||||||
|
if (move_selection)
|
||||||
|
{
|
||||||
|
selection--;
|
||||||
|
if (selection < 0) {
|
||||||
|
selection = maxfiles - 1;
|
||||||
|
offset = selection - PAGESIZE + 1;
|
||||||
|
}
|
||||||
|
if (selection < offset)
|
||||||
|
offset -= PAGESIZE;
|
||||||
|
if (offset < 0)
|
||||||
|
offset = 0;
|
||||||
|
redraw = 1;
|
||||||
|
move_selection = 0;
|
||||||
|
}
|
||||||
|
} // End of Up
|
||||||
|
if ( (p & PAD_BUTTON_LEFT) || (wp & (WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT)) )
|
||||||
|
{
|
||||||
|
/*** Go back a page ***/
|
||||||
|
selection -= PAGESIZE;
|
||||||
|
if (selection < 0)
|
||||||
|
{
|
||||||
|
selection = maxfiles - 1;
|
||||||
|
offset = selection - PAGESIZE + 1;
|
||||||
|
}
|
||||||
|
if (selection < offset)
|
||||||
|
offset -= PAGESIZE;
|
||||||
|
if (offset < 0)
|
||||||
|
offset = 0;
|
||||||
|
redraw = 1;
|
||||||
|
}
|
||||||
|
if ( (p & PAD_BUTTON_RIGHT) || (wp & (WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT)) )
|
||||||
|
{
|
||||||
|
/*** Go forward a page ***/
|
||||||
|
selection += PAGESIZE;
|
||||||
|
if (selection > maxfiles - 1)
|
||||||
|
selection = offset = 0;
|
||||||
|
if ((selection - offset) >= PAGESIZE)
|
||||||
|
offset += PAGESIZE;
|
||||||
|
redraw = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* OpenDVD
|
||||||
|
*
|
||||||
|
* Function to load a DVD directory and display to user.
|
||||||
|
***************************************************************************/
|
||||||
|
int
|
||||||
|
OpenDVD (int method)
|
||||||
|
{
|
||||||
|
if (!getpvd())
|
||||||
|
{
|
||||||
|
ShowAction((char*) "Loading DVD...");
|
||||||
|
#ifdef HW_DOL
|
||||||
|
DVD_Mount(); // mount the DVD unit again
|
||||||
|
#elif WII_DVD
|
||||||
|
u32 val;
|
||||||
|
DI_GetCoverRegister(&val);
|
||||||
|
if(val & 0x1) // True if no disc inside, use (val & 0x2) for true if disc inside.
|
||||||
|
{
|
||||||
|
WaitPrompt((char *)"No disc inserted!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DI_Mount();
|
||||||
|
while(DI_GetStatus() & DVD_INIT);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!getpvd())
|
||||||
|
{
|
||||||
|
WaitPrompt ((char *)"Invalid DVD.");
|
||||||
|
return 0; // not a ISO9660 DVD
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
maxfiles = ParseDVDdirectory(); // load root folder
|
||||||
|
|
||||||
|
// switch to rom folder
|
||||||
|
SwitchDVDFolder(GCSettings.LoadFolder);
|
||||||
|
|
||||||
|
if (maxfiles > 0)
|
||||||
|
{
|
||||||
|
return FileSelector (method);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no entries found
|
||||||
|
WaitPrompt ((char *)"No Files Found!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* OpenSMB
|
||||||
|
*
|
||||||
|
* Function to load from an SMB share
|
||||||
|
***************************************************************************/
|
||||||
|
int
|
||||||
|
OpenSMB (int method)
|
||||||
|
{
|
||||||
|
// Connect to network share
|
||||||
|
if(ConnectShare (NOTSILENT))
|
||||||
|
{
|
||||||
|
// change current dir to root dir
|
||||||
|
sprintf(currentdir, "/%s", GCSettings.LoadFolder);
|
||||||
|
|
||||||
|
maxfiles = ParseSMBdirectory ();
|
||||||
|
if (maxfiles > 0)
|
||||||
|
{
|
||||||
|
return FileSelector (method);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no entries found
|
||||||
|
WaitPrompt ((char *)"No Files Found!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* OpenFAT
|
||||||
|
*
|
||||||
|
* Function to load from FAT
|
||||||
|
***************************************************************************/
|
||||||
|
int
|
||||||
|
OpenFAT (int method)
|
||||||
|
{
|
||||||
|
if(ChangeFATInterface(method, NOTSILENT))
|
||||||
|
{
|
||||||
|
// change current dir to snes roms directory
|
||||||
|
sprintf ( currentdir, "%s/%s", ROOTFATDIR, GCSettings.LoadFolder );
|
||||||
|
|
||||||
|
// Parse initial root directory and get entries list
|
||||||
|
maxfiles = ParseFATdirectory (method);
|
||||||
|
if (maxfiles > 0)
|
||||||
|
{
|
||||||
|
// Select an entry
|
||||||
|
return FileSelector (method);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no entries found
|
||||||
|
WaitPrompt ((char *)"No Files Found!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* OpenROM
|
||||||
|
* Opens device specified by method, displays a list of ROMS
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
int
|
||||||
|
OpenROM (int method)
|
||||||
|
{
|
||||||
|
int loadROM = 0;
|
||||||
|
|
||||||
|
if(method == METHOD_AUTO)
|
||||||
|
method = autoLoadMethod();
|
||||||
|
|
||||||
|
switch (method)
|
||||||
|
{
|
||||||
|
case METHOD_SD:
|
||||||
|
case METHOD_USB:
|
||||||
|
loadROM = OpenFAT (method);
|
||||||
|
break;
|
||||||
|
case METHOD_DVD:
|
||||||
|
// Load from DVD
|
||||||
|
loadROM = OpenDVD (method);
|
||||||
|
break;
|
||||||
|
case METHOD_SMB:
|
||||||
|
// Load from Network (SMB)
|
||||||
|
loadROM = OpenSMB (method);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadROM;
|
||||||
|
}
|
39
source/ngc/filesel.h
Normal file
39
source/ngc/filesel.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* crunchy2 May 2007
|
||||||
|
* Tantric August 2008
|
||||||
|
*
|
||||||
|
* filesel.h
|
||||||
|
*
|
||||||
|
* Generic file routines - reading, writing, browsing
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _NGCFILESEL_
|
||||||
|
#define _NGCFILESEL_
|
||||||
|
|
||||||
|
#define SAVEBUFFERSIZE ((512 * 1024) + 2048 + 64 + 4 + 4)
|
||||||
|
#define MAXJOLIET 255
|
||||||
|
#define MAXDISPLAY 54
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u64 offset;
|
||||||
|
unsigned int length;
|
||||||
|
char flags;
|
||||||
|
char filename[MAXJOLIET + 1];
|
||||||
|
char displayname[MAXDISPLAY + 1];
|
||||||
|
} FILEENTRIES;
|
||||||
|
|
||||||
|
#define MAXFILES 2000 // Restrict to 2000 files per dir
|
||||||
|
extern FILEENTRIES filelist[MAXFILES];
|
||||||
|
|
||||||
|
void ClearSaveBuffer ();
|
||||||
|
int OpenROM (int method);
|
||||||
|
int autoLoadMethod();
|
||||||
|
int autoSaveMethod();
|
||||||
|
int FileSortCallback(const void *f1, const void *f2);
|
||||||
|
void StripExt(char* returnstring, char * inputstring);
|
||||||
|
|
||||||
|
#endif
|
12
source/ngc/fontface.s
Normal file
12
source/ngc/fontface.s
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Fonts
|
||||||
|
|
||||||
|
.rodata
|
||||||
|
.globl fontface
|
||||||
|
.balign 32
|
||||||
|
fontface:
|
||||||
|
.incbin "../source/ngc/ttf/font.ttf"
|
||||||
|
|
||||||
|
|
||||||
|
.globl fontsize
|
||||||
|
fontsize: .long 28736
|
||||||
|
|
@ -1,302 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* VisualBoyAdvance 1.7.2
|
|
||||||
*
|
|
||||||
* Nintendo GameCube Joypad Wrapper
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include <gccore.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define VBA_BUTTON_A 1
|
|
||||||
#define VBA_BUTTON_B 2
|
|
||||||
#define VBA_BUTTON_SELECT 4
|
|
||||||
#define VBA_BUTTON_START 8
|
|
||||||
#define VBA_RIGHT 16
|
|
||||||
#define VBA_LEFT 32
|
|
||||||
#define VBA_UP 64
|
|
||||||
#define VBA_DOWN 128
|
|
||||||
#define VBA_BUTTON_R 256
|
|
||||||
#define VBA_BUTTON_L 512
|
|
||||||
#define VBA_SPEED 1024
|
|
||||||
#define VBA_CAPTURE 2048
|
|
||||||
|
|
||||||
#ifdef WII_BUILD
|
|
||||||
#include <math.h>
|
|
||||||
#include <wiiuse/wpad.h>
|
|
||||||
int isClassicAvailable = 0;
|
|
||||||
int isWiimoteAvailable = 0;
|
|
||||||
/*
|
|
||||||
#ifndef PI
|
|
||||||
#define PI 3.14159f
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum { STICK_X, STICK_Y };
|
|
||||||
static int getStickValue(joystick_t* j, int axis, int maxAbsValue){
|
|
||||||
double angle = PI * j->ang/180.0f;
|
|
||||||
double magnitude = (j->mag > 1.0f) ? 1.0f :
|
|
||||||
(j->mag < -1.0f) ? -1.0f : j->mag;
|
|
||||||
double value;
|
|
||||||
if(axis == STICK_X)
|
|
||||||
value = magnitude * sin( angle );
|
|
||||||
else
|
|
||||||
value = magnitude * cos( angle );
|
|
||||||
return (int)(value * maxAbsValue);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
#endif
|
|
||||||
int menuCalled = 0;
|
|
||||||
u32
|
|
||||||
NGCPad()
|
|
||||||
{
|
|
||||||
u32 res = 0;
|
|
||||||
short p;
|
|
||||||
signed char x,
|
|
||||||
y;
|
|
||||||
int padcal = 90;
|
|
||||||
float t;
|
|
||||||
|
|
||||||
#ifdef WII_BUILD
|
|
||||||
//wiimote
|
|
||||||
WPADData *wpad;
|
|
||||||
WPAD_ScanPads();
|
|
||||||
wpad = WPAD_Data(0);
|
|
||||||
if (isWiimoteAvailable)
|
|
||||||
{
|
|
||||||
unsigned short b = wpad->btns_h;
|
|
||||||
|
|
||||||
if (b & WPAD_BUTTON_2)
|
|
||||||
res |= VBA_BUTTON_A;
|
|
||||||
|
|
||||||
if (b & WPAD_BUTTON_1)
|
|
||||||
res |= VBA_BUTTON_B;
|
|
||||||
|
|
||||||
if (b & WPAD_BUTTON_MINUS)
|
|
||||||
res |= VBA_BUTTON_SELECT;
|
|
||||||
|
|
||||||
if (b & WPAD_BUTTON_PLUS)
|
|
||||||
res |= VBA_BUTTON_START;
|
|
||||||
|
|
||||||
if (b & WPAD_BUTTON_RIGHT)
|
|
||||||
res |= VBA_UP;
|
|
||||||
|
|
||||||
if (b & WPAD_BUTTON_LEFT)
|
|
||||||
res |= VBA_DOWN;
|
|
||||||
|
|
||||||
if (b & WPAD_BUTTON_UP)
|
|
||||||
res |= VBA_LEFT;
|
|
||||||
|
|
||||||
if (b & WPAD_BUTTON_DOWN)
|
|
||||||
res |= VBA_RIGHT;
|
|
||||||
|
|
||||||
if (b & WPAD_BUTTON_A)
|
|
||||||
res |= VBA_BUTTON_L;
|
|
||||||
|
|
||||||
if (b & WPAD_BUTTON_B)
|
|
||||||
res |= VBA_BUTTON_R;
|
|
||||||
|
|
||||||
if (b & WPAD_BUTTON_HOME)
|
|
||||||
menuCalled = 1;
|
|
||||||
}
|
|
||||||
//classic controller
|
|
||||||
if (isClassicAvailable)
|
|
||||||
{
|
|
||||||
float mag,ang;
|
|
||||||
int b = wpad->exp.classic.btns;
|
|
||||||
ang = wpad->exp.classic.ljs.ang;
|
|
||||||
mag = wpad->exp.classic.ljs.mag;
|
|
||||||
|
|
||||||
if (mag > 0.4) {
|
|
||||||
if (ang > 292.5 | ang <= 67.5)
|
|
||||||
res |= VBA_UP;
|
|
||||||
if (ang > 22.5 & ang <= 157.5)
|
|
||||||
res |= VBA_RIGHT;
|
|
||||||
if (ang > 113.5 & ang <= 247.5)
|
|
||||||
res |= VBA_DOWN;
|
|
||||||
if (ang > 203.5 & ang <= 337.5)
|
|
||||||
res |= VBA_LEFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
int x_s = 0; //getStickValue(&wpad.exp.classic.ljs, STICK_X, 127);
|
|
||||||
int y_s = 0; //getStickValue(&wpad.exp.classic.ljs, STICK_Y, 127);
|
|
||||||
if (b & CLASSIC_CTRL_BUTTON_A)
|
|
||||||
res |= VBA_BUTTON_A;
|
|
||||||
|
|
||||||
if (b & CLASSIC_CTRL_BUTTON_B)
|
|
||||||
res |= VBA_BUTTON_B;
|
|
||||||
|
|
||||||
if (b & CLASSIC_CTRL_BUTTON_MINUS)
|
|
||||||
res |= VBA_BUTTON_SELECT;
|
|
||||||
|
|
||||||
if (b & CLASSIC_CTRL_BUTTON_PLUS)
|
|
||||||
res |= VBA_BUTTON_START;
|
|
||||||
|
|
||||||
if ((b & CLASSIC_CTRL_BUTTON_UP) || (y_s > 0))
|
|
||||||
res |= VBA_UP;
|
|
||||||
|
|
||||||
if ((b & CLASSIC_CTRL_BUTTON_DOWN) || (y_s < 0))
|
|
||||||
res |= VBA_DOWN;
|
|
||||||
|
|
||||||
if ((b & CLASSIC_CTRL_BUTTON_LEFT) || (x_s < 0))
|
|
||||||
res |= VBA_LEFT;
|
|
||||||
|
|
||||||
if ((b & CLASSIC_CTRL_BUTTON_RIGHT) || (x_s > 0))
|
|
||||||
res |= VBA_RIGHT;
|
|
||||||
|
|
||||||
if (b & CLASSIC_CTRL_BUTTON_FULL_L)
|
|
||||||
res |= VBA_BUTTON_L;
|
|
||||||
|
|
||||||
if (b & CLASSIC_CTRL_BUTTON_FULL_R)
|
|
||||||
res |= VBA_BUTTON_R;
|
|
||||||
|
|
||||||
if (b & CLASSIC_CTRL_BUTTON_HOME)
|
|
||||||
menuCalled = 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
//user needs a GC remote
|
|
||||||
PAD_ScanPads();
|
|
||||||
p = PAD_ButtonsHeld(0);
|
|
||||||
x = PAD_StickX(0);
|
|
||||||
y = PAD_StickY(0);
|
|
||||||
if (x * x + y * y > padcal * padcal)
|
|
||||||
{
|
|
||||||
if (x > 0 && y == 0)
|
|
||||||
res |= VBA_RIGHT;
|
|
||||||
if (x < 0 && y == 0)
|
|
||||||
res |= VBA_LEFT;
|
|
||||||
if (x == 0 && y > 0)
|
|
||||||
res |= VBA_UP;
|
|
||||||
if (x == 0 && y < 0)
|
|
||||||
res |= VBA_DOWN;
|
|
||||||
|
|
||||||
/*** Recalc left / right ***/
|
|
||||||
t = (float) y / x;
|
|
||||||
if (t >= -2.41421356237 && t < 2.41421356237)
|
|
||||||
{
|
|
||||||
if (x >= 0)
|
|
||||||
res |= VBA_RIGHT;
|
|
||||||
else
|
|
||||||
res |= VBA_LEFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Recalc up / down ***/
|
|
||||||
t = (float) x / y;
|
|
||||||
if (t >= -2.41421356237 && t < 2.41421356237)
|
|
||||||
{
|
|
||||||
if (y >= 0)
|
|
||||||
res |= VBA_UP;
|
|
||||||
else
|
|
||||||
res |= VBA_DOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p & PAD_BUTTON_A)
|
|
||||||
res |= VBA_BUTTON_A;
|
|
||||||
|
|
||||||
if (p & PAD_BUTTON_B)
|
|
||||||
res |= VBA_BUTTON_B;
|
|
||||||
|
|
||||||
if (p & PAD_TRIGGER_Z)
|
|
||||||
res |= VBA_BUTTON_SELECT;
|
|
||||||
|
|
||||||
if (p & PAD_BUTTON_START)
|
|
||||||
res |= VBA_BUTTON_START;
|
|
||||||
|
|
||||||
if (p & PAD_BUTTON_UP)
|
|
||||||
res |= VBA_UP;
|
|
||||||
|
|
||||||
if (p & PAD_BUTTON_DOWN)
|
|
||||||
res |= VBA_DOWN;
|
|
||||||
|
|
||||||
if (p & PAD_BUTTON_LEFT)
|
|
||||||
res |= VBA_LEFT;
|
|
||||||
|
|
||||||
if (p & PAD_BUTTON_RIGHT)
|
|
||||||
res |= VBA_RIGHT;
|
|
||||||
|
|
||||||
if (p & PAD_TRIGGER_L)
|
|
||||||
res |= VBA_BUTTON_L;
|
|
||||||
|
|
||||||
if (p & PAD_TRIGGER_R)
|
|
||||||
res |= VBA_BUTTON_R;
|
|
||||||
|
|
||||||
if((p & PAD_BUTTON_X) && (p & PAD_BUTTON_Y))
|
|
||||||
menuCalled = 1;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef GC_BUILD
|
|
||||||
p = PAD_ButtonsHeld(0);
|
|
||||||
x = PAD_StickX(0);
|
|
||||||
y = PAD_StickY(0);
|
|
||||||
if (x * x + y * y > padcal * padcal)
|
|
||||||
{
|
|
||||||
if (x > 0 && y == 0)
|
|
||||||
res |= VBA_RIGHT;
|
|
||||||
if (x < 0 && y == 0)
|
|
||||||
res |= VBA_LEFT;
|
|
||||||
if (x == 0 && y > 0)
|
|
||||||
res |= VBA_UP;
|
|
||||||
if (x == 0 && y < 0)
|
|
||||||
res |= VBA_DOWN;
|
|
||||||
|
|
||||||
/*** Recalc left / right ***/
|
|
||||||
t = (float) y / x;
|
|
||||||
if (t >= -2.41421356237 && t < 2.41421356237)
|
|
||||||
{
|
|
||||||
if (x >= 0)
|
|
||||||
res |= VBA_RIGHT;
|
|
||||||
else
|
|
||||||
res |= VBA_LEFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Recalc up / down ***/
|
|
||||||
t = (float) x / y;
|
|
||||||
if (t >= -2.41421356237 && t < 2.41421356237)
|
|
||||||
{
|
|
||||||
if (y >= 0)
|
|
||||||
res |= VBA_UP;
|
|
||||||
else
|
|
||||||
res |= VBA_DOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p & PAD_BUTTON_A)
|
|
||||||
res |= VBA_BUTTON_A;
|
|
||||||
|
|
||||||
if (p & PAD_BUTTON_B)
|
|
||||||
res |= VBA_BUTTON_B;
|
|
||||||
|
|
||||||
if (p & PAD_TRIGGER_Z)
|
|
||||||
res |= VBA_BUTTON_SELECT;
|
|
||||||
|
|
||||||
if (p & PAD_BUTTON_START)
|
|
||||||
res |= VBA_BUTTON_START;
|
|
||||||
|
|
||||||
if ((p & PAD_BUTTON_UP))
|
|
||||||
res |= VBA_UP;
|
|
||||||
|
|
||||||
if ((p & PAD_BUTTON_DOWN))
|
|
||||||
res |= VBA_DOWN;
|
|
||||||
|
|
||||||
if ((p & PAD_BUTTON_LEFT))
|
|
||||||
res |= VBA_LEFT;
|
|
||||||
|
|
||||||
if ((p & PAD_BUTTON_RIGHT))
|
|
||||||
res |= VBA_RIGHT;
|
|
||||||
|
|
||||||
if (p & PAD_TRIGGER_L)
|
|
||||||
res |= VBA_BUTTON_L;
|
|
||||||
|
|
||||||
if (p & PAD_TRIGGER_R)
|
|
||||||
res |= VBA_BUTTON_R;
|
|
||||||
|
|
||||||
if((p & PAD_BUTTON_X) && (p & PAD_BUTTON_Y))
|
|
||||||
menuCalled = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((res & 48) == 48)
|
|
||||||
res &= ~16;
|
|
||||||
if ((res & 192) == 192)
|
|
||||||
res &= ~128;
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* VisualBoyAdvance 1.7.2
|
|
||||||
*
|
|
||||||
* Nintendo GameCube Joypad Wrapper
|
|
||||||
****************************************************************************/
|
|
||||||
#ifndef __NGCPADH__
|
|
||||||
#define __NGCPADH__
|
|
||||||
|
|
||||||
u32 NGCPad();
|
|
||||||
|
|
||||||
#endif
|
|
230
source/ngc/gcunzip.cpp
Normal file
230
source/ngc/gcunzip.cpp
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* Tantric September 2008
|
||||||
|
*
|
||||||
|
* unzip.cpp
|
||||||
|
*
|
||||||
|
* File unzip routines
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#include "dvd.h"
|
||||||
|
#include "smbop.h"
|
||||||
|
#include "video.h"
|
||||||
|
#include "menudraw.h"
|
||||||
|
#include "gcunzip.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PKWare Zip Header - adopted into zip standard
|
||||||
|
*/
|
||||||
|
#define PKZIPID 0x504b0304
|
||||||
|
#define MAXROM 0x500000
|
||||||
|
#define ZIPCHUNK 2048
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Zip files are stored little endian
|
||||||
|
* Support functions for short and int types
|
||||||
|
*/
|
||||||
|
u32
|
||||||
|
FLIP32 (u32 b)
|
||||||
|
{
|
||||||
|
unsigned int c;
|
||||||
|
|
||||||
|
c = (b & 0xff000000) >> 24;
|
||||||
|
c |= (b & 0xff0000) >> 8;
|
||||||
|
c |= (b & 0xff00) << 8;
|
||||||
|
c |= (b & 0xff) << 24;
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16
|
||||||
|
FLIP16 (u16 b)
|
||||||
|
{
|
||||||
|
u16 c;
|
||||||
|
|
||||||
|
c = (b & 0xff00) >> 8;
|
||||||
|
c |= (b & 0xff) << 8;
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* IsZipFile
|
||||||
|
*
|
||||||
|
* Returns TRUE when PKZIPID is first four characters of buffer
|
||||||
|
****************************************************************************/
|
||||||
|
int
|
||||||
|
IsZipFile (char *buffer)
|
||||||
|
{
|
||||||
|
unsigned int *check;
|
||||||
|
|
||||||
|
check = (unsigned int *) buffer;
|
||||||
|
|
||||||
|
if (check[0] == PKZIPID)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* unzip
|
||||||
|
*
|
||||||
|
* It should be noted that there is a limit of 5MB total size for any ROM
|
||||||
|
******************************************************************************/
|
||||||
|
FILE* fatfile; // FAT
|
||||||
|
u64 discoffset; // DVD
|
||||||
|
SMBFILE smbfile; // SMB
|
||||||
|
|
||||||
|
int
|
||||||
|
UnZipBuffer (unsigned char *outbuffer, short where)
|
||||||
|
{
|
||||||
|
PKZIPHEADER pkzip;
|
||||||
|
int zipoffset = 0;
|
||||||
|
int zipchunk = 0;
|
||||||
|
char out[ZIPCHUNK];
|
||||||
|
z_stream zs;
|
||||||
|
int res;
|
||||||
|
int bufferoffset = 0;
|
||||||
|
int readoffset = 0;
|
||||||
|
int have = 0;
|
||||||
|
char readbuffer[ZIPCHUNK];
|
||||||
|
char msg[128];
|
||||||
|
|
||||||
|
/*** Read Zip Header ***/
|
||||||
|
switch (where)
|
||||||
|
{
|
||||||
|
case 0: // SD Card
|
||||||
|
fseek(fatfile, 0, SEEK_SET);
|
||||||
|
fread (readbuffer, 1, ZIPCHUNK, fatfile);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // DVD
|
||||||
|
dvd_read (readbuffer, ZIPCHUNK, discoffset);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // From SMB
|
||||||
|
SMB_ReadFile(readbuffer, ZIPCHUNK, 0, smbfile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Copy PKZip header to local, used as info ***/
|
||||||
|
memcpy (&pkzip, readbuffer, sizeof (PKZIPHEADER));
|
||||||
|
|
||||||
|
pkzip.uncompressedSize = FLIP32 (pkzip.uncompressedSize);
|
||||||
|
|
||||||
|
sprintf (msg, "Unzipping %d bytes ... Wait",
|
||||||
|
pkzip.uncompressedSize);
|
||||||
|
ShowAction (msg);
|
||||||
|
|
||||||
|
/*** Prepare the zip stream ***/
|
||||||
|
memset (&zs, 0, sizeof (z_stream));
|
||||||
|
zs.zalloc = Z_NULL;
|
||||||
|
zs.zfree = Z_NULL;
|
||||||
|
zs.opaque = Z_NULL;
|
||||||
|
zs.avail_in = 0;
|
||||||
|
zs.next_in = Z_NULL;
|
||||||
|
res = inflateInit2 (&zs, -MAX_WBITS);
|
||||||
|
|
||||||
|
if (res != Z_OK)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*** Set ZipChunk for first pass ***/
|
||||||
|
zipoffset =
|
||||||
|
(sizeof (PKZIPHEADER) + FLIP16 (pkzip.filenameLength) +
|
||||||
|
FLIP16 (pkzip.extraDataLength));
|
||||||
|
zipchunk = ZIPCHUNK - zipoffset;
|
||||||
|
|
||||||
|
/*** Now do it! ***/
|
||||||
|
do
|
||||||
|
{
|
||||||
|
zs.avail_in = zipchunk;
|
||||||
|
zs.next_in = (Bytef *) & readbuffer[zipoffset];
|
||||||
|
|
||||||
|
/*** Now inflate until input buffer is exhausted ***/
|
||||||
|
do
|
||||||
|
{
|
||||||
|
zs.avail_out = ZIPCHUNK;
|
||||||
|
zs.next_out = (Bytef *) & out;
|
||||||
|
|
||||||
|
res = inflate (&zs, Z_NO_FLUSH);
|
||||||
|
|
||||||
|
if (res == Z_MEM_ERROR)
|
||||||
|
{
|
||||||
|
inflateEnd (&zs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
have = ZIPCHUNK - zs.avail_out;
|
||||||
|
if (have)
|
||||||
|
{
|
||||||
|
/*** Copy to normal block buffer ***/
|
||||||
|
memcpy (&outbuffer[bufferoffset], &out, have);
|
||||||
|
bufferoffset += have;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (zs.avail_out == 0);
|
||||||
|
|
||||||
|
/*** Readup the next 2k block ***/
|
||||||
|
zipoffset = 0;
|
||||||
|
zipchunk = ZIPCHUNK;
|
||||||
|
|
||||||
|
switch (where)
|
||||||
|
{
|
||||||
|
case 0: // SD Card
|
||||||
|
fread (readbuffer, 1, ZIPCHUNK, fatfile);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // DVD
|
||||||
|
readoffset += ZIPCHUNK;
|
||||||
|
dvd_read (readbuffer, ZIPCHUNK, discoffset+readoffset);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // From SMB
|
||||||
|
readoffset += ZIPCHUNK;
|
||||||
|
SMB_ReadFile(readbuffer, ZIPCHUNK, readoffset, smbfile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (res != Z_STREAM_END);
|
||||||
|
|
||||||
|
inflateEnd (&zs);
|
||||||
|
|
||||||
|
if (res == Z_STREAM_END)
|
||||||
|
{
|
||||||
|
if (pkzip.uncompressedSize == (u32) bufferoffset)
|
||||||
|
return bufferoffset;
|
||||||
|
else
|
||||||
|
return pkzip.uncompressedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// Reading from FAT
|
||||||
|
int
|
||||||
|
UnZipFile (unsigned char *outbuffer, FILE* infile)
|
||||||
|
{
|
||||||
|
fatfile = infile;
|
||||||
|
return UnZipBuffer(outbuffer, 0);
|
||||||
|
}
|
||||||
|
// Reading from DVD
|
||||||
|
int
|
||||||
|
UnZipFile (unsigned char *outbuffer, u64 inoffset)
|
||||||
|
{
|
||||||
|
discoffset = inoffset;
|
||||||
|
return UnZipBuffer(outbuffer, 1);
|
||||||
|
}
|
||||||
|
// Reading from SMB
|
||||||
|
int
|
||||||
|
UnZipFile (unsigned char *outbuffer, SMBFILE infile)
|
||||||
|
{
|
||||||
|
smbfile = infile;
|
||||||
|
return UnZipBuffer(outbuffer, 2);
|
||||||
|
}
|
44
source/ngc/gcunzip.h
Normal file
44
source/ngc/gcunzip.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* Tantric September 2008
|
||||||
|
*
|
||||||
|
* unzip.h
|
||||||
|
*
|
||||||
|
* File unzip routines
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef _UNZIP_
|
||||||
|
#define _UNZIP_
|
||||||
|
|
||||||
|
#include <smb.h>
|
||||||
|
|
||||||
|
extern int IsZipFile (char *buffer);
|
||||||
|
|
||||||
|
int UnZipFile (unsigned char *outbuffer, FILE* infile); // Reading from FAT
|
||||||
|
int UnZipFile (unsigned char *outbuffer, u64 inoffset); // Reading from DVD
|
||||||
|
int UnZipFile (unsigned char *outbuffer, SMBFILE infile); // Reading from SMB
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Zip file header definition
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned int zipid __attribute__ ((__packed__)); // 0x04034b50
|
||||||
|
unsigned short zipversion __attribute__ ((__packed__));
|
||||||
|
unsigned short zipflags __attribute__ ((__packed__));
|
||||||
|
unsigned short compressionMethod __attribute__ ((__packed__));
|
||||||
|
unsigned short lastmodtime __attribute__ ((__packed__));
|
||||||
|
unsigned short lastmoddate __attribute__ ((__packed__));
|
||||||
|
unsigned int crc32 __attribute__ ((__packed__));
|
||||||
|
unsigned int compressedSize __attribute__ ((__packed__));
|
||||||
|
unsigned int uncompressedSize __attribute__ ((__packed__));
|
||||||
|
unsigned short filenameLength __attribute__ ((__packed__));
|
||||||
|
unsigned short extraDataLength __attribute__ ((__packed__));
|
||||||
|
}
|
||||||
|
PKZIPHEADER;
|
||||||
|
|
||||||
|
u32 FLIP32 (u32 b);
|
||||||
|
u16 FLIP16 (u16 b);
|
||||||
|
|
||||||
|
#endif
|
@ -1,264 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Generic GX Support for Emulators
|
|
||||||
* softdev 2007
|
|
||||||
*
|
|
||||||
* 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.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* NGC GX Video Functions
|
|
||||||
*
|
|
||||||
* These are pretty standard functions to setup and use GX scaling.
|
|
||||||
****************************************************************************/
|
|
||||||
#include <gccore.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
|
|
||||||
/*** External 2D Video ***/
|
|
||||||
extern u32 whichfb;
|
|
||||||
extern u32 *xfb[2];
|
|
||||||
extern GXRModeObj *vmode;
|
|
||||||
|
|
||||||
/*** 3D GX ***/
|
|
||||||
#define DEFAULT_FIFO_SIZE ( 256 * 1024 )
|
|
||||||
static u8 gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN(32);
|
|
||||||
|
|
||||||
/*** Texture memory ***/
|
|
||||||
static u8 *texturemem;
|
|
||||||
static int texturesize;
|
|
||||||
|
|
||||||
GXTexObj texobj;
|
|
||||||
static Mtx view;
|
|
||||||
static int vwidth, vheight, oldvwidth, oldvheight;
|
|
||||||
|
|
||||||
#define HASPECT 80
|
|
||||||
#define VASPECT 45
|
|
||||||
|
|
||||||
/* New texture based scaler */
|
|
||||||
typedef struct tagcamera
|
|
||||||
{
|
|
||||||
Vector pos;
|
|
||||||
Vector up;
|
|
||||||
Vector view;
|
|
||||||
}
|
|
||||||
camera;
|
|
||||||
|
|
||||||
/*** Square Matrix
|
|
||||||
This structure controls the size of the image on the screen.
|
|
||||||
Think of the output as a -80 x 80 by -60 x 60 graph.
|
|
||||||
***/
|
|
||||||
static s16 square[] ATTRIBUTE_ALIGN(32) = {
|
|
||||||
/*
|
|
||||||
* X, Y, Z
|
|
||||||
* Values set are for roughly 4:3 aspect
|
|
||||||
*/
|
|
||||||
-HASPECT, VASPECT, 0, // 0
|
|
||||||
HASPECT, VASPECT, 0, // 1
|
|
||||||
HASPECT, -VASPECT, 0, // 2
|
|
||||||
-HASPECT, -VASPECT, 0, // 3
|
|
||||||
};
|
|
||||||
|
|
||||||
static camera cam = { {0.0F, 0.0F, 0.0F},
|
|
||||||
{0.0F, 0.5F, 0.0F},
|
|
||||||
{0.0F, 0.0F, -0.5F}
|
|
||||||
};
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Scaler Support Functions
|
|
||||||
****************************************************************************/
|
|
||||||
static void draw_init(void)
|
|
||||||
{
|
|
||||||
GX_ClearVtxDesc();
|
|
||||||
GX_SetVtxDesc(GX_VA_POS, GX_INDEX8);
|
|
||||||
GX_SetVtxDesc(GX_VA_CLR0, GX_INDEX8);
|
|
||||||
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
|
||||||
|
|
||||||
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
|
|
||||||
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
|
|
||||||
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
|
||||||
|
|
||||||
GX_SetArray(GX_VA_POS, square, 3 * sizeof(s16));
|
|
||||||
|
|
||||||
GX_SetNumTexGens(1);
|
|
||||||
GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
|
|
||||||
|
|
||||||
GX_InvalidateTexAll();
|
|
||||||
|
|
||||||
GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565,
|
|
||||||
GX_CLAMP, GX_CLAMP, GX_FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void draw_vert(u8 pos, u8 c, f32 s, f32 t)
|
|
||||||
{
|
|
||||||
GX_Position1x8(pos);
|
|
||||||
GX_Color1x8(c);
|
|
||||||
GX_TexCoord2f32(s, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void draw_square(Mtx v)
|
|
||||||
{
|
|
||||||
Mtx m; // model matrix.
|
|
||||||
Mtx mv; // modelview matrix.
|
|
||||||
|
|
||||||
guMtxIdentity(m);
|
|
||||||
guMtxTransApply(m, m, 0, 0, -100);
|
|
||||||
guMtxConcat(v, m, mv);
|
|
||||||
|
|
||||||
GX_LoadPosMtxImm(mv, GX_PNMTX0);
|
|
||||||
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
|
||||||
draw_vert(0, 0, 0.0, 0.0);
|
|
||||||
draw_vert(1, 0, 1.0, 0.0);
|
|
||||||
draw_vert(2, 0, 1.0, 1.0);
|
|
||||||
draw_vert(3, 0, 0.0, 1.0);
|
|
||||||
GX_End();
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* StartGX
|
|
||||||
****************************************************************************/
|
|
||||||
void GX_Start(int width, int height, int haspect, int vaspect)
|
|
||||||
{
|
|
||||||
Mtx p;
|
|
||||||
|
|
||||||
/*** Set new aspect (now with crap AR hack!) ***/
|
|
||||||
square[0] = square[9] = (-haspect - 7);
|
|
||||||
square[3] = square[6] = (haspect + 7);
|
|
||||||
square[1] = square[4] = (vaspect + 7);
|
|
||||||
square[7] = square[10] = (-vaspect - 7);
|
|
||||||
|
|
||||||
/*** Allocate 32byte aligned texture memory ***/
|
|
||||||
texturesize = (width * height) * 2;
|
|
||||||
texturemem = (u8 *) memalign(32, texturesize);
|
|
||||||
|
|
||||||
GXColor gxbackground = { 0, 0, 0, 0xff };
|
|
||||||
|
|
||||||
/*** Clear out FIFO area ***/
|
|
||||||
memset(&gp_fifo, 0, DEFAULT_FIFO_SIZE);
|
|
||||||
|
|
||||||
/*** Initialise GX ***/
|
|
||||||
GX_Init(&gp_fifo, DEFAULT_FIFO_SIZE);
|
|
||||||
GX_SetCopyClear(gxbackground, 0x00ffffff);
|
|
||||||
|
|
||||||
GX_SetViewport(0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1);
|
|
||||||
GX_SetDispCopyYScale((f32) vmode->xfbHeight / (f32) vmode->efbHeight);
|
|
||||||
GX_SetScissor(0, 0, vmode->fbWidth, vmode->efbHeight);
|
|
||||||
GX_SetDispCopySrc(0, 0, vmode->fbWidth, vmode->efbHeight);
|
|
||||||
GX_SetDispCopyDst(vmode->fbWidth, vmode->xfbHeight);
|
|
||||||
GX_SetCopyFilter(vmode->aa, vmode->sample_pattern, GX_TRUE,
|
|
||||||
vmode->vfilter);
|
|
||||||
GX_SetFieldMode(vmode->field_rendering,
|
|
||||||
((vmode->viHeight ==
|
|
||||||
2 * vmode->xfbHeight) ? GX_ENABLE : GX_DISABLE));
|
|
||||||
GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
|
|
||||||
GX_SetCullMode(GX_CULL_NONE);
|
|
||||||
GX_CopyDisp(xfb[whichfb ^ 1], GX_TRUE);
|
|
||||||
GX_SetDispCopyGamma(GX_GM_1_0);
|
|
||||||
|
|
||||||
guPerspective(p, 60, 1.33F, 10.0F, 1000.0F);
|
|
||||||
GX_LoadProjectionMtx(p, GX_PERSPECTIVE);
|
|
||||||
memset(texturemem, 0, texturesize);
|
|
||||||
|
|
||||||
/*** Setup for first call to scaler ***/
|
|
||||||
vwidth = vheight = -1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* GX_Render
|
|
||||||
*
|
|
||||||
* Pass in a buffer, width and height to update as a tiled RGB565 texture
|
|
||||||
****************************************************************************/
|
|
||||||
void GX_Render(int width, int height, u8 * buffer, int pitch)
|
|
||||||
{
|
|
||||||
int h, w;
|
|
||||||
long long int *dst = (long long int *) texturemem;
|
|
||||||
long long int *src1 = (long long int *) buffer;
|
|
||||||
long long int *src2 = (long long int *) (buffer + pitch);
|
|
||||||
long long int *src3 = (long long int *) (buffer + (pitch * 2));
|
|
||||||
long long int *src4 = (long long int *) (buffer + (pitch * 3));
|
|
||||||
int rowpitch = (pitch >> 3) * 3;
|
|
||||||
int rowadjust = ( pitch % 8 ) * 4;
|
|
||||||
char *ra = NULL;
|
|
||||||
|
|
||||||
vwidth = width;
|
|
||||||
vheight = height;
|
|
||||||
|
|
||||||
whichfb ^= 1;
|
|
||||||
|
|
||||||
if ((oldvheight != vheight) || (oldvwidth != vwidth))
|
|
||||||
{
|
|
||||||
/** Update scaling **/
|
|
||||||
oldvwidth = vwidth;
|
|
||||||
oldvheight = vheight;
|
|
||||||
draw_init();
|
|
||||||
memset(&view, 0, sizeof(Mtx));
|
|
||||||
guLookAt(view, &cam.pos, &cam.up, &cam.view);
|
|
||||||
GX_SetViewport(0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
GX_InvVtxCache();
|
|
||||||
GX_InvalidateTexAll();
|
|
||||||
GX_SetTevOp(GX_TEVSTAGE0, GX_DECAL);
|
|
||||||
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
|
|
||||||
|
|
||||||
for (h = 0; h < vheight; h += 4)
|
|
||||||
{
|
|
||||||
|
|
||||||
for (w = 0; w < (vwidth >> 2); w++)
|
|
||||||
{
|
|
||||||
*dst++ = *src1++;
|
|
||||||
*dst++ = *src2++;
|
|
||||||
*dst++ = *src3++;
|
|
||||||
*dst++ = *src4++;
|
|
||||||
}
|
|
||||||
|
|
||||||
src1 += rowpitch;
|
|
||||||
src2 += rowpitch;
|
|
||||||
src3 += rowpitch;
|
|
||||||
src4 += rowpitch;
|
|
||||||
|
|
||||||
if ( rowadjust )
|
|
||||||
{
|
|
||||||
ra = (char *)src1;
|
|
||||||
src1 = (long long int *)(ra + rowadjust);
|
|
||||||
ra = (char *)src2;
|
|
||||||
src2 = (long long int *)(ra + rowadjust);
|
|
||||||
ra = (char *)src3;
|
|
||||||
src3 = (long long int *)(ra + rowadjust);
|
|
||||||
ra = (char *)src4;
|
|
||||||
src4 = (long long int *)(ra + rowadjust);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DCFlushRange(texturemem, texturesize);
|
|
||||||
|
|
||||||
GX_SetNumChans(1);
|
|
||||||
GX_LoadTexObj(&texobj, GX_TEXMAP0);
|
|
||||||
|
|
||||||
draw_square(view);
|
|
||||||
|
|
||||||
GX_DrawDone();
|
|
||||||
|
|
||||||
GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
|
|
||||||
GX_SetColorUpdate(GX_TRUE);
|
|
||||||
GX_CopyDisp(xfb[whichfb], GX_TRUE);
|
|
||||||
GX_Flush();
|
|
||||||
|
|
||||||
VIDEO_SetNextFramebuffer(xfb[whichfb]);
|
|
||||||
VIDEO_Flush();
|
|
||||||
//VIDEO_WaitVSync();
|
|
||||||
|
|
||||||
}
|
|
354
source/ngc/input.cpp
Normal file
354
source/ngc/input.cpp
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* crunchy2 May-June 2007
|
||||||
|
* Tantric September 2008
|
||||||
|
*
|
||||||
|
* input.cpp
|
||||||
|
*
|
||||||
|
* Wii/Gamecube controller management
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <wiiuse/wpad.h>
|
||||||
|
|
||||||
|
#include "button_mapping.h"
|
||||||
|
#include "menu.h"
|
||||||
|
#include "video.h"
|
||||||
|
#include "input.h"
|
||||||
|
#include "tbtime.h"
|
||||||
|
|
||||||
|
#define MAXJP 10
|
||||||
|
|
||||||
|
#define VBA_BUTTON_A 1
|
||||||
|
#define VBA_BUTTON_B 2
|
||||||
|
#define VBA_BUTTON_SELECT 4
|
||||||
|
#define VBA_BUTTON_START 8
|
||||||
|
#define VBA_RIGHT 16
|
||||||
|
#define VBA_LEFT 32
|
||||||
|
#define VBA_UP 64
|
||||||
|
#define VBA_DOWN 128
|
||||||
|
#define VBA_BUTTON_R 256
|
||||||
|
#define VBA_BUTTON_L 512
|
||||||
|
#define VBA_SPEED 1024
|
||||||
|
#define VBA_CAPTURE 2048
|
||||||
|
|
||||||
|
// VBA controller buttons
|
||||||
|
// All other pads are mapped to this
|
||||||
|
unsigned int vbapadmap[] = {
|
||||||
|
VBA_BUTTON_A, VBA_BUTTON_B,
|
||||||
|
VBA_BUTTON_SELECT, VBA_BUTTON_START,
|
||||||
|
VBA_UP, VBA_DOWN,
|
||||||
|
VBA_LEFT, VBA_RIGHT,
|
||||||
|
VBA_BUTTON_L, VBA_BUTTON_R
|
||||||
|
};
|
||||||
|
|
||||||
|
/*** Gamecube controller Padmap ***/
|
||||||
|
unsigned int gcpadmap[] = {
|
||||||
|
PAD_BUTTON_A, PAD_BUTTON_B,
|
||||||
|
PAD_TRIGGER_Z, PAD_BUTTON_START,
|
||||||
|
PAD_BUTTON_UP, PAD_BUTTON_DOWN,
|
||||||
|
PAD_BUTTON_LEFT, PAD_BUTTON_RIGHT,
|
||||||
|
PAD_TRIGGER_L, PAD_TRIGGER_R
|
||||||
|
};
|
||||||
|
/*** Wiimote Padmap ***/
|
||||||
|
unsigned int wmpadmap[] = {
|
||||||
|
WPAD_BUTTON_1, WPAD_BUTTON_2,
|
||||||
|
WPAD_BUTTON_MINUS, WPAD_BUTTON_PLUS,
|
||||||
|
WPAD_BUTTON_RIGHT, WPAD_BUTTON_LEFT,
|
||||||
|
WPAD_BUTTON_UP, WPAD_BUTTON_DOWN,
|
||||||
|
0x0000, 0x0000
|
||||||
|
};
|
||||||
|
/*** Classic Controller Padmap ***/
|
||||||
|
unsigned int ccpadmap[] = {
|
||||||
|
WPAD_CLASSIC_BUTTON_A, WPAD_CLASSIC_BUTTON_B,
|
||||||
|
WPAD_CLASSIC_BUTTON_MINUS, WPAD_CLASSIC_BUTTON_PLUS,
|
||||||
|
WPAD_CLASSIC_BUTTON_UP, WPAD_CLASSIC_BUTTON_DOWN,
|
||||||
|
WPAD_CLASSIC_BUTTON_LEFT, WPAD_CLASSIC_BUTTON_RIGHT,
|
||||||
|
WPAD_CLASSIC_BUTTON_FULL_L, WPAD_CLASSIC_BUTTON_FULL_R
|
||||||
|
};
|
||||||
|
/*** Nunchuk + wiimote Padmap ***/
|
||||||
|
unsigned int ncpadmap[] = { WPAD_BUTTON_A, WPAD_BUTTON_B,
|
||||||
|
WPAD_NUNCHUK_BUTTON_C, WPAD_NUNCHUK_BUTTON_Z,
|
||||||
|
WPAD_BUTTON_MINUS, WPAD_BUTTON_PLUS,
|
||||||
|
WPAD_BUTTON_2, WPAD_BUTTON_1,
|
||||||
|
WPAD_BUTTON_UP, WPAD_BUTTON_DOWN,
|
||||||
|
WPAD_BUTTON_LEFT, WPAD_BUTTON_RIGHT
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef HW_RVL
|
||||||
|
/****************************************************************************
|
||||||
|
* WPAD_StickX
|
||||||
|
*
|
||||||
|
* Get X value from Wii Joystick (classic, nunchuk) input
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
s8 WPAD_StickX(u8 chan,u8 right)
|
||||||
|
{
|
||||||
|
float mag = 0.0;
|
||||||
|
float ang = 0.0;
|
||||||
|
WPADData *data = WPAD_Data(chan);
|
||||||
|
|
||||||
|
switch (data->exp.type)
|
||||||
|
{
|
||||||
|
case WPAD_EXP_NUNCHUK:
|
||||||
|
case WPAD_EXP_GUITARHERO3:
|
||||||
|
if (right == 0)
|
||||||
|
{
|
||||||
|
mag = data->exp.nunchuk.js.mag;
|
||||||
|
ang = data->exp.nunchuk.js.ang;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WPAD_EXP_CLASSIC:
|
||||||
|
if (right == 0)
|
||||||
|
{
|
||||||
|
mag = data->exp.classic.ljs.mag;
|
||||||
|
ang = data->exp.classic.ljs.ang;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mag = data->exp.classic.rjs.mag;
|
||||||
|
ang = data->exp.classic.rjs.ang;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* calculate X value (angle need to be converted into radian) */
|
||||||
|
if (mag > 1.0) mag = 1.0;
|
||||||
|
else if (mag < -1.0) mag = -1.0;
|
||||||
|
double val = mag * sin((PI * ang)/180.0f);
|
||||||
|
|
||||||
|
return (s8)(val * 128.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* WPAD_StickY
|
||||||
|
*
|
||||||
|
* Get Y value from Wii Joystick (classic, nunchuk) input
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
s8 WPAD_StickY(u8 chan, u8 right)
|
||||||
|
{
|
||||||
|
float mag = 0.0;
|
||||||
|
float ang = 0.0;
|
||||||
|
WPADData *data = WPAD_Data(chan);
|
||||||
|
|
||||||
|
switch (data->exp.type)
|
||||||
|
{
|
||||||
|
case WPAD_EXP_NUNCHUK:
|
||||||
|
case WPAD_EXP_GUITARHERO3:
|
||||||
|
if (right == 0)
|
||||||
|
{
|
||||||
|
mag = data->exp.nunchuk.js.mag;
|
||||||
|
ang = data->exp.nunchuk.js.ang;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WPAD_EXP_CLASSIC:
|
||||||
|
if (right == 0)
|
||||||
|
{
|
||||||
|
mag = data->exp.classic.ljs.mag;
|
||||||
|
ang = data->exp.classic.ljs.ang;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mag = data->exp.classic.rjs.mag;
|
||||||
|
ang = data->exp.classic.rjs.ang;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* calculate X value (angle need to be converted into radian) */
|
||||||
|
if (mag > 1.0) mag = 1.0;
|
||||||
|
else if (mag < -1.0) mag = -1.0;
|
||||||
|
double val = mag * cos((PI * ang)/180.0f);
|
||||||
|
|
||||||
|
return (s8)(val * 128.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* DecodeJoy
|
||||||
|
*
|
||||||
|
* Reads the changes (buttons pressed, etc) from a controller and reports
|
||||||
|
* these changes to VBA
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
u32 DecodeJoy(unsigned short pad)
|
||||||
|
{
|
||||||
|
signed char pad_x = PAD_StickX (pad);
|
||||||
|
signed char pad_y = PAD_StickY (pad);
|
||||||
|
u32 jp = PAD_ButtonsHeld (pad);
|
||||||
|
unsigned char J = 0;
|
||||||
|
|
||||||
|
#ifdef HW_RVL
|
||||||
|
signed char wm_ax = 0;
|
||||||
|
signed char wm_ay = 0;
|
||||||
|
u32 wp = 0;
|
||||||
|
wm_ax = WPAD_StickX ((u8)pad, 0);
|
||||||
|
wm_ay = WPAD_StickY ((u8)pad, 0);
|
||||||
|
wp = WPAD_ButtonsHeld (pad);
|
||||||
|
|
||||||
|
u32 exp_type;
|
||||||
|
if ( WPAD_Probe(pad, &exp_type) != 0 ) exp_type = WPAD_EXP_NONE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/***
|
||||||
|
Gamecube Joystick input
|
||||||
|
***/
|
||||||
|
// Is XY inside the "zone"?
|
||||||
|
if (pad_x * pad_x + pad_y * pad_y > PADCAL * PADCAL)
|
||||||
|
{
|
||||||
|
if (pad_x > 0 && pad_y == 0) J |= VBA_RIGHT;
|
||||||
|
if (pad_x < 0 && pad_y == 0) J |= VBA_LEFT;
|
||||||
|
if (pad_x == 0 && pad_y > 0) J |= VBA_UP;
|
||||||
|
if (pad_x == 0 && pad_y < 0) J |= VBA_DOWN;
|
||||||
|
|
||||||
|
if (pad_x != 0 && pad_y != 0)
|
||||||
|
{
|
||||||
|
if ((float)pad_y / pad_x >= -2.41421356237 && (float)pad_y / pad_x < 2.41421356237)
|
||||||
|
{
|
||||||
|
if (pad_x >= 0)
|
||||||
|
J |= VBA_RIGHT;
|
||||||
|
else
|
||||||
|
J |= VBA_LEFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((float)pad_x / pad_y >= -2.41421356237 && (float)pad_x / pad_y < 2.41421356237)
|
||||||
|
{
|
||||||
|
if (pad_y >= 0)
|
||||||
|
J |= VBA_UP;
|
||||||
|
else
|
||||||
|
J |= VBA_DOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef HW_RVL
|
||||||
|
/***
|
||||||
|
Wii Joystick (classic, nunchuk) input
|
||||||
|
***/
|
||||||
|
// Is XY inside the "zone"?
|
||||||
|
if (wm_ax * wm_ax + wm_ay * wm_ay > PADCAL * PADCAL)
|
||||||
|
{
|
||||||
|
/*** we don't want division by zero ***/
|
||||||
|
if (wm_ax > 0 && wm_ay == 0)
|
||||||
|
J |= VBA_RIGHT;
|
||||||
|
if (wm_ax < 0 && wm_ay == 0)
|
||||||
|
J |= VBA_LEFT;
|
||||||
|
if (wm_ax == 0 && wm_ay > 0)
|
||||||
|
J |= VBA_UP;
|
||||||
|
if (wm_ax == 0 && wm_ay < 0)
|
||||||
|
J |= VBA_DOWN;
|
||||||
|
|
||||||
|
if (wm_ax != 0 && wm_ay != 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*** Recalc left / right ***/
|
||||||
|
float t;
|
||||||
|
|
||||||
|
t = (float) wm_ay / wm_ax;
|
||||||
|
if (t >= -2.41421356237 && t < 2.41421356237)
|
||||||
|
{
|
||||||
|
if (wm_ax >= 0)
|
||||||
|
J |= VBA_RIGHT;
|
||||||
|
else
|
||||||
|
J |= VBA_LEFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Recalc up / down ***/
|
||||||
|
t = (float) wm_ax / wm_ay;
|
||||||
|
if (t >= -2.41421356237 && t < 2.41421356237)
|
||||||
|
{
|
||||||
|
if (wm_ay >= 0)
|
||||||
|
J |= VBA_UP;
|
||||||
|
else
|
||||||
|
J |= VBA_DOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*** Report pressed buttons (gamepads) ***/
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAXJP; i++)
|
||||||
|
{
|
||||||
|
if ( (jp & gcpadmap[i]) // gamecube controller
|
||||||
|
#ifdef HW_RVL
|
||||||
|
|| ( (exp_type == WPAD_EXP_NONE) && (wp & wmpadmap[i]) ) // wiimote
|
||||||
|
|| ( (exp_type == WPAD_EXP_CLASSIC) && (wp & ccpadmap[i]) ) // classic controller
|
||||||
|
|| ( (exp_type == WPAD_EXP_NUNCHUK) && (wp & ncpadmap[i]) ) // nunchuk + wiimote
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
J |= vbapadmap[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return J;
|
||||||
|
}
|
||||||
|
u32 GetJoy()
|
||||||
|
{
|
||||||
|
short i;
|
||||||
|
int pad = 0;
|
||||||
|
u32 res = 0;
|
||||||
|
|
||||||
|
s8 gc_px = PAD_SubStickX (0);
|
||||||
|
u32 jp = PAD_ButtonsHeld (0); // gamecube controller button info
|
||||||
|
|
||||||
|
#ifdef HW_RVL
|
||||||
|
s8 wm_sx = WPAD_StickX (0,1);
|
||||||
|
u32 wm_pb = WPAD_ButtonsHeld (0); // wiimote / expansion button info
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// request to go back to menu
|
||||||
|
if ((gc_px < -70) || (jp & PAD_BUTTON_START)
|
||||||
|
#ifdef HW_RVL
|
||||||
|
|| (wm_pb & WPAD_BUTTON_HOME)
|
||||||
|
|| (wm_pb & WPAD_CLASSIC_BUTTON_HOME)
|
||||||
|
|| (wm_sx < -70)
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
if (GCSettings.AutoSave == 1)
|
||||||
|
{
|
||||||
|
SaveRAM(GCSettings.SaveMethod, SILENT);
|
||||||
|
}
|
||||||
|
else if (GCSettings.AutoSave == 2)
|
||||||
|
{
|
||||||
|
SaveState(GCSettings.SaveMethod, SILENT);
|
||||||
|
}
|
||||||
|
else if(GCSettings.AutoSave == 3)
|
||||||
|
{
|
||||||
|
SaveRAM(GCSettings.SaveMethod, SILENT);
|
||||||
|
SaveState(GCSettings.SaveMethod, SILENT);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
mainmenu(3);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res = DecodeJoy(pad);
|
||||||
|
if ((res & 48) == 48)
|
||||||
|
res &= ~16;
|
||||||
|
if ((res & 192) == 192)
|
||||||
|
res &= ~128;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
31
source/ngc/input.h
Normal file
31
source/ngc/input.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* crunchy2 May-June 2007
|
||||||
|
* Tantric September 2008
|
||||||
|
*
|
||||||
|
* input.h
|
||||||
|
*
|
||||||
|
* Wii/Gamecube controller management
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _INPUT_H_
|
||||||
|
#define _INPUT_H_
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
|
||||||
|
#define PI 3.14159265f
|
||||||
|
#define PADCAL 50
|
||||||
|
|
||||||
|
extern unsigned int gcpadmap[];
|
||||||
|
extern unsigned int wmpadmap[];
|
||||||
|
extern unsigned int ccpadmap[];
|
||||||
|
extern unsigned int ncpadmap[];
|
||||||
|
|
||||||
|
s8 WPAD_StickX(u8 chan,u8 right);
|
||||||
|
s8 WPAD_StickY(u8 chan, u8 right);
|
||||||
|
|
||||||
|
u32 GetJoy();
|
||||||
|
|
||||||
|
#endif
|
@ -1 +0,0 @@
|
|||||||
|
|
419
source/ngc/memcardop.cpp
Normal file
419
source/ngc/memcardop.cpp
Normal file
@ -0,0 +1,419 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* crunchy2 May-June 2007
|
||||||
|
* Tantric September 2008
|
||||||
|
*
|
||||||
|
* memcardop.cpp
|
||||||
|
*
|
||||||
|
* Memory Card routines
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "vba.h"
|
||||||
|
#include "video.h"
|
||||||
|
#include "menudraw.h"
|
||||||
|
#include "menu.h"
|
||||||
|
#include "preferences.h"
|
||||||
|
#include "memcardop.h"
|
||||||
|
#include "fileop.h"
|
||||||
|
|
||||||
|
#define VERIFBUFFERSIZE 65536
|
||||||
|
static u8 SysArea[CARD_WORKAREA] ATTRIBUTE_ALIGN (32);
|
||||||
|
extern unsigned char savebuffer[];
|
||||||
|
unsigned char verifbuffer[VERIFBUFFERSIZE] ATTRIBUTE_ALIGN (32);
|
||||||
|
card_dir CardDir;
|
||||||
|
card_file CardFile;
|
||||||
|
card_stat CardStatus;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CardFileExists
|
||||||
|
*
|
||||||
|
* Wrapper to search through the files on the card.
|
||||||
|
* Returns TRUE if found.
|
||||||
|
***************************************************************************/
|
||||||
|
int
|
||||||
|
CardFileExists (char *filename, int slot)
|
||||||
|
{
|
||||||
|
int CardError;
|
||||||
|
|
||||||
|
CardError = CARD_FindFirst (slot, &CardDir, TRUE);
|
||||||
|
while (CardError != CARD_ERROR_NOFILE)
|
||||||
|
{
|
||||||
|
CardError = CARD_FindNext (&CardDir);
|
||||||
|
|
||||||
|
if (strcmp ((char *) CardDir.filename, filename) == 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* TestCard
|
||||||
|
*
|
||||||
|
* Checks to see if a card is in the card slot specified
|
||||||
|
***************************************************************************/
|
||||||
|
bool TestCard(int slot, bool silent)
|
||||||
|
{
|
||||||
|
// Memory Cards do not work in Wii mode - disable
|
||||||
|
#ifdef HW_RVL
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*** Initialize Card System ***/
|
||||||
|
memset (SysArea, 0, CARD_WORKAREA);
|
||||||
|
CARD_Init ("SNES", "00");
|
||||||
|
|
||||||
|
/*** Try to mount the card ***/
|
||||||
|
if (MountCard(slot, silent) == 0)
|
||||||
|
{
|
||||||
|
// Mount successful!
|
||||||
|
if(!silent)
|
||||||
|
{
|
||||||
|
if (slot == CARD_SLOTA)
|
||||||
|
WaitPrompt((char*) "Mounted Slot A Memory Card!");
|
||||||
|
else
|
||||||
|
WaitPrompt((char*) "Mounted Slot B Memory Card!");
|
||||||
|
}
|
||||||
|
CARD_Unmount (slot);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!silent)
|
||||||
|
{
|
||||||
|
if (slot == CARD_SLOTA)
|
||||||
|
WaitPrompt((char*) "Unable to Mount Slot A Memory Card!");
|
||||||
|
else
|
||||||
|
WaitPrompt((char*) "Unable to Mount Slot B Memory Card!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* MountCard
|
||||||
|
*
|
||||||
|
* Mounts the memory card in the given slot.
|
||||||
|
* Returns the result of the last attempted CARD_Mount command.
|
||||||
|
***************************************************************************/
|
||||||
|
int MountCard(int cslot, bool silent)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
int tries = 0;
|
||||||
|
|
||||||
|
// Mount the card
|
||||||
|
while ( tries < 10 && ret != 0)
|
||||||
|
{
|
||||||
|
EXI_ProbeReset ();
|
||||||
|
ret = CARD_Mount (cslot, SysArea, NULL);
|
||||||
|
VIDEO_WaitVSync ();
|
||||||
|
tries++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Verify Memory Card file against buffer
|
||||||
|
***************************************************************************/
|
||||||
|
int
|
||||||
|
VerifyMCFile (unsigned char *buf, int slot, char *filename, int datasize)
|
||||||
|
{
|
||||||
|
int CardError;
|
||||||
|
unsigned int blocks;
|
||||||
|
unsigned int SectorSize;
|
||||||
|
char msg[80];
|
||||||
|
int bytesleft = 0;
|
||||||
|
int bytesread = 0;
|
||||||
|
|
||||||
|
/*** Initialize Card System ***/
|
||||||
|
memset (SysArea, 0, CARD_WORKAREA);
|
||||||
|
CARD_Init ("SNES", "00");
|
||||||
|
|
||||||
|
/*** Try to mount the card ***/
|
||||||
|
CardError = MountCard(slot, NOTSILENT);
|
||||||
|
|
||||||
|
if (CardError == 0)
|
||||||
|
{
|
||||||
|
/*** Get Sector Size ***/
|
||||||
|
CARD_GetSectorSize (slot, &SectorSize);
|
||||||
|
|
||||||
|
if (!CardFileExists (filename, slot))
|
||||||
|
{
|
||||||
|
CARD_Unmount (slot);
|
||||||
|
WaitPrompt((char*) "Unable to open file for verify!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset (&CardFile, 0, sizeof (CardFile));
|
||||||
|
CardError = CARD_Open (slot, filename, &CardFile);
|
||||||
|
|
||||||
|
blocks = CardFile.len;
|
||||||
|
|
||||||
|
if (blocks < SectorSize)
|
||||||
|
blocks = SectorSize;
|
||||||
|
|
||||||
|
if (blocks % SectorSize)
|
||||||
|
blocks += SectorSize;
|
||||||
|
|
||||||
|
if (blocks > (unsigned int)datasize)
|
||||||
|
blocks = datasize;
|
||||||
|
|
||||||
|
memset (verifbuffer, 0, VERIFBUFFERSIZE);
|
||||||
|
bytesleft = blocks;
|
||||||
|
bytesread = 0;
|
||||||
|
while (bytesleft > 0)
|
||||||
|
{
|
||||||
|
CARD_Read (&CardFile, verifbuffer, SectorSize, bytesread);
|
||||||
|
if ( memcmp (buf + bytesread, verifbuffer, (unsigned int)bytesleft < SectorSize ? bytesleft : SectorSize) )
|
||||||
|
{
|
||||||
|
CARD_Close (&CardFile);
|
||||||
|
CARD_Unmount (slot);
|
||||||
|
WaitPrompt((char*) "File did not verify!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesleft -= SectorSize;
|
||||||
|
bytesread += SectorSize;
|
||||||
|
|
||||||
|
sprintf (msg, "Verified %d of %d bytes", bytesread, blocks);
|
||||||
|
ShowProgress (msg, bytesread, blocks);
|
||||||
|
}
|
||||||
|
CARD_Close (&CardFile);
|
||||||
|
CARD_Unmount (slot);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (slot == CARD_SLOTA)
|
||||||
|
WaitPrompt((char*) "Unable to Mount Slot A Memory Card!");
|
||||||
|
else
|
||||||
|
WaitPrompt((char*) "Unable to Mount Slot B Memory Card!");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Load savebuffer from Memory Card file
|
||||||
|
***************************************************************************/
|
||||||
|
int
|
||||||
|
LoadBufferFromMC (unsigned char *buf, int slot, char *filename, bool silent)
|
||||||
|
{
|
||||||
|
int CardError;
|
||||||
|
unsigned int blocks;
|
||||||
|
unsigned int SectorSize;
|
||||||
|
int bytesleft = 0;
|
||||||
|
int bytesread = 0;
|
||||||
|
|
||||||
|
/*** Initialize Card System ***/
|
||||||
|
memset (SysArea, 0, CARD_WORKAREA);
|
||||||
|
CARD_Init ("SNES", "00");
|
||||||
|
|
||||||
|
/*** Try to mount the card ***/
|
||||||
|
CardError = MountCard(slot, NOTSILENT);
|
||||||
|
|
||||||
|
if (CardError == 0)
|
||||||
|
{
|
||||||
|
/*** Get Sector Size ***/
|
||||||
|
CARD_GetSectorSize (slot, &SectorSize);
|
||||||
|
|
||||||
|
if (!CardFileExists (filename, slot))
|
||||||
|
{
|
||||||
|
if (!silent)
|
||||||
|
WaitPrompt((char*) "Unable to open file");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset (&CardFile, 0, sizeof (CardFile));
|
||||||
|
CardError = CARD_Open (slot, filename, &CardFile);
|
||||||
|
|
||||||
|
blocks = CardFile.len;
|
||||||
|
|
||||||
|
if (blocks < SectorSize)
|
||||||
|
blocks = SectorSize;
|
||||||
|
|
||||||
|
if (blocks % SectorSize)
|
||||||
|
blocks += SectorSize;
|
||||||
|
|
||||||
|
memset (buf, 0, 0x22000);
|
||||||
|
|
||||||
|
bytesleft = blocks;
|
||||||
|
bytesread = 0;
|
||||||
|
while (bytesleft > 0)
|
||||||
|
{
|
||||||
|
CARD_Read (&CardFile, buf + bytesread, SectorSize, bytesread);
|
||||||
|
bytesleft -= SectorSize;
|
||||||
|
bytesread += SectorSize;
|
||||||
|
}
|
||||||
|
CARD_Close (&CardFile);
|
||||||
|
CARD_Unmount (slot);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (slot == CARD_SLOTA)
|
||||||
|
WaitPrompt((char*) "Unable to Mount Slot A Memory Card!");
|
||||||
|
else
|
||||||
|
WaitPrompt((char*) "Unable to Mount Slot B Memory Card!");
|
||||||
|
|
||||||
|
return bytesread;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Write savebuffer to Memory Card file
|
||||||
|
***************************************************************************/
|
||||||
|
int
|
||||||
|
SaveBufferToMC (unsigned char *buf, int slot, char *filename, int datasize, bool silent)
|
||||||
|
{
|
||||||
|
int CardError;
|
||||||
|
unsigned int blocks;
|
||||||
|
unsigned int SectorSize;
|
||||||
|
char msg[80];
|
||||||
|
|
||||||
|
/*** Initialize Card System ***/
|
||||||
|
memset (SysArea, 0, CARD_WORKAREA);
|
||||||
|
CARD_Init ("SNES", "00");
|
||||||
|
|
||||||
|
/*** Try to mount the card ***/
|
||||||
|
CardError = MountCard(slot, NOTSILENT);
|
||||||
|
|
||||||
|
if (CardError == 0)
|
||||||
|
{
|
||||||
|
/*** Get Sector Size ***/
|
||||||
|
CARD_GetSectorSize (slot, &SectorSize);
|
||||||
|
|
||||||
|
if (datasize)
|
||||||
|
{
|
||||||
|
/*** Calculate number of blocks required ***/
|
||||||
|
blocks = (datasize / SectorSize) * SectorSize;
|
||||||
|
if (datasize % SectorSize)
|
||||||
|
blocks += SectorSize;
|
||||||
|
|
||||||
|
/*** Does this file exist ? ***/
|
||||||
|
if (CardFileExists (filename, slot))
|
||||||
|
{
|
||||||
|
/*** Try to open the file ***/
|
||||||
|
CardError = CARD_Open (slot, filename, &CardFile);
|
||||||
|
if (CardError)
|
||||||
|
{
|
||||||
|
CARD_Unmount (slot);
|
||||||
|
WaitPrompt((char*) "Unable to open card file!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (s32)blocks > CardFile.len ) /*** new data is longer ***/
|
||||||
|
{
|
||||||
|
CARD_Close (&CardFile);
|
||||||
|
|
||||||
|
/*** Try to create temp file to check available space ***/
|
||||||
|
CardError = CARD_Create (slot, "TEMPFILESNES9XGX201", blocks, &CardFile);
|
||||||
|
if (CardError)
|
||||||
|
{
|
||||||
|
CARD_Unmount (slot);
|
||||||
|
WaitPrompt((char*) "Not enough space to update file!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Delete the temporary file ***/
|
||||||
|
CARD_Close (&CardFile);
|
||||||
|
CardError = CARD_Delete(slot, "TEMPFILESNES9XGX201");
|
||||||
|
if (CardError)
|
||||||
|
{
|
||||||
|
CARD_Unmount (slot);
|
||||||
|
WaitPrompt((char*) "Unable to delete temporary file!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Delete the existing shorter file ***/
|
||||||
|
CardError = CARD_Delete(slot, filename);
|
||||||
|
if (CardError)
|
||||||
|
{
|
||||||
|
CARD_Unmount (slot);
|
||||||
|
WaitPrompt((char*) "Unable to delete existing file!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Create new, longer file ***/
|
||||||
|
CardError = CARD_Create (slot, filename, blocks, &CardFile);
|
||||||
|
if (CardError)
|
||||||
|
{
|
||||||
|
CARD_Unmount (slot);
|
||||||
|
WaitPrompt((char*) "Unable to create updated card file!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /*** no file existed, create new one ***/
|
||||||
|
{
|
||||||
|
/*** Create new file ***/
|
||||||
|
CardError = CARD_Create (slot, filename, blocks, &CardFile);
|
||||||
|
if (CardError)
|
||||||
|
{
|
||||||
|
CARD_Unmount (slot);
|
||||||
|
if ( CardError == CARD_ERROR_INSSPACE )
|
||||||
|
WaitPrompt((char*) "Not enough space to create file!");
|
||||||
|
else
|
||||||
|
WaitPrompt((char*) "Unable to create card file!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Now, have an open file handle, ready to send out the data ***/
|
||||||
|
CARD_GetStatus (slot, CardFile.filenum, &CardStatus);
|
||||||
|
CardStatus.icon_addr = 0x0;
|
||||||
|
CardStatus.icon_fmt = 2;
|
||||||
|
CardStatus.icon_speed = 1;
|
||||||
|
CardStatus.comment_addr = 2048;
|
||||||
|
CARD_SetStatus (slot, CardFile.filenum, &CardStatus);
|
||||||
|
|
||||||
|
int byteswritten = 0;
|
||||||
|
int bytesleft = blocks;
|
||||||
|
while (bytesleft > 0)
|
||||||
|
{
|
||||||
|
CardError =
|
||||||
|
CARD_Write (&CardFile, buf + byteswritten,
|
||||||
|
SectorSize, byteswritten);
|
||||||
|
bytesleft -= SectorSize;
|
||||||
|
byteswritten += SectorSize;
|
||||||
|
|
||||||
|
sprintf (msg, "Wrote %d of %d bytes", byteswritten, blocks);
|
||||||
|
ShowProgress (msg, byteswritten, blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
CARD_Close (&CardFile);
|
||||||
|
CARD_Unmount (slot);
|
||||||
|
|
||||||
|
if ( GCSettings.VerifySaves )
|
||||||
|
{
|
||||||
|
/*** Verify the written file, but only up to the length we wrote
|
||||||
|
because the file could be longer due to past writes ***/
|
||||||
|
if ( VerifyMCFile (buf, slot, filename, byteswritten) )
|
||||||
|
return byteswritten;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return byteswritten;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if ( !silent )
|
||||||
|
WaitPrompt((char*) "This game does not appear to use SRAM");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (slot == CARD_SLOTA)
|
||||||
|
WaitPrompt((char*) "Unable to Mount Slot A Memory Card!");
|
||||||
|
else
|
||||||
|
WaitPrompt((char*) "Unable to Mount Slot B Memory Card!");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
23
source/ngc/memcardop.h
Normal file
23
source/ngc/memcardop.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* crunchy2 May-June 2007
|
||||||
|
* Tantric September 2008
|
||||||
|
*
|
||||||
|
* memcardop.cpp
|
||||||
|
*
|
||||||
|
* Memory Card routines
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _NGCMCSAVE_
|
||||||
|
#define _NGCMCSAVE_
|
||||||
|
|
||||||
|
int VerifyMCFile (unsigned char *buf, int slot, char *filename, int datasize);
|
||||||
|
|
||||||
|
int LoadBufferFromMC (unsigned char *buf, int slot, char *filename, bool silent);
|
||||||
|
int SaveBufferToMC (unsigned char *buf, int slot, char *filename, int datasize, bool silent);
|
||||||
|
int MountCard(int cslot, bool silent);
|
||||||
|
bool TestCard(int slot, bool silent);
|
||||||
|
|
||||||
|
#endif
|
@ -1,265 +1,731 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* File Selection Menu
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
* softdev July 2006
|
||||||
|
* crunchy2 May-June 2007
|
||||||
|
* Tantric August 2008
|
||||||
|
*
|
||||||
|
* menu.cpp
|
||||||
|
*
|
||||||
|
* Menu flow routines - handles all menu logic
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <gccore.h>
|
|
||||||
#include "sdfileio.h"
|
|
||||||
|
|
||||||
extern GXRModeObj *vmode; /*** Graphics Mode Object ***/
|
|
||||||
extern u32 *xfb[2]; /*** Framebuffers ***/
|
|
||||||
extern int whichfb; /*** Frame buffer toggle ***/
|
|
||||||
|
|
||||||
/** Bits from SD lib **/
|
|
||||||
|
|
||||||
#define PAGE_SIZE 14
|
|
||||||
|
|
||||||
/*** Use OGC built in font ***/
|
|
||||||
extern u8 console_font_8x16[];
|
|
||||||
|
|
||||||
static u32 forecolour = COLOR_WHITE;
|
|
||||||
static u32 backcolour = COLOR_BLACK;
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* MENU_DrawChar
|
|
||||||
****************************************************************************/
|
|
||||||
void MENU_DrawChar( int x, int y, char c, int style )
|
|
||||||
{
|
|
||||||
u8 bits;
|
|
||||||
int offset;
|
|
||||||
int h,w;
|
|
||||||
u32 colour[2];
|
|
||||||
u32 scroffs;
|
|
||||||
|
|
||||||
offset = c << 4;
|
|
||||||
scroffs = ( y * 320 ) + ( x >> 1 );
|
|
||||||
|
|
||||||
for( h = 0; h < 16; h++ )
|
|
||||||
{
|
|
||||||
bits = console_font_8x16[ offset++ ];
|
|
||||||
|
|
||||||
if ( style )
|
|
||||||
{
|
|
||||||
for( w = 0; w < 8; w++ )
|
|
||||||
{
|
|
||||||
xfb[whichfb][scroffs + w] = ( bits & 0x80 ) ? forecolour : backcolour;
|
|
||||||
bits <<= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for( w = 0; w < 4; w++ )
|
|
||||||
{
|
|
||||||
colour[0] = ( bits & 0x80 ) ? forecolour : backcolour;
|
|
||||||
colour[1] = ( bits & 0x40 ) ? forecolour : backcolour;
|
|
||||||
|
|
||||||
xfb[whichfb][scroffs + w] = ( colour[0] & 0xFFFF00FF ) | ( colour[1] & 0x0000FF00 );
|
|
||||||
bits <<= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scroffs += 320;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* MENU_DrawString
|
|
||||||
****************************************************************************/
|
|
||||||
void MENU_DrawString( int x, int y, char *msg, int style )
|
|
||||||
{
|
|
||||||
int i,len;
|
|
||||||
|
|
||||||
/* Centred ? */
|
|
||||||
if ( x == -1 )
|
|
||||||
{
|
|
||||||
if ( style )
|
|
||||||
x = strlen(msg) << 4;
|
|
||||||
else
|
|
||||||
x = strlen(msg) << 3;
|
|
||||||
|
|
||||||
x = ( 640 - x ) >> 1;
|
|
||||||
}
|
|
||||||
if((int)strlen(msg) < 36)
|
|
||||||
len = (int)strlen(msg);
|
|
||||||
else
|
|
||||||
len = 36;
|
|
||||||
for ( i = 0; i < len; i++ )
|
|
||||||
{
|
|
||||||
MENU_DrawChar(x,y,msg[i],style);
|
|
||||||
x += ( style ? 16 : 8 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* MENU_Draw
|
|
||||||
****************************************************************************/
|
|
||||||
int MENU_Draw( int max, int current, int offset )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int ypos = 30;
|
|
||||||
int xpos = 30;
|
|
||||||
|
|
||||||
for ( i = offset; i < max && ( ( i - offset ) < PAGE_SIZE ); i++ )
|
|
||||||
{
|
|
||||||
if ( i == current )
|
|
||||||
{
|
|
||||||
forecolour = COLOR_BLACK;
|
|
||||||
backcolour = COLOR_WHITE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
forecolour = COLOR_WHITE;
|
|
||||||
backcolour = COLOR_BLACK;
|
|
||||||
}
|
|
||||||
MENU_DrawString( xpos, ypos, direntries[i], 1);
|
|
||||||
ypos += 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef WII_BUILD
|
|
||||||
#include <math.h>
|
|
||||||
#include <wiiuse/wpad.h>
|
#include <wiiuse/wpad.h>
|
||||||
extern int isClassicAvailable;
|
|
||||||
extern int isWiimoteAvailable;
|
#ifdef WII_DVD
|
||||||
extern void setup_controllers();
|
extern "C" {
|
||||||
|
#include <di/di.h>
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "vba.h"
|
||||||
|
#include "vbasupport.h"
|
||||||
|
#include "audio.h"
|
||||||
|
#include "video.h"
|
||||||
|
#include "filesel.h"
|
||||||
|
#include "gcunzip.h"
|
||||||
|
#include "smbop.h"
|
||||||
|
#include "memcardop.h"
|
||||||
|
#include "fileop.h"
|
||||||
|
#include "dvd.h"
|
||||||
|
#include "preferences.h"
|
||||||
|
#include "button_mapping.h"
|
||||||
|
#include "menudraw.h"
|
||||||
|
#include "input.h"
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "tbtime.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void DrawMenu (char items[][50], char *title, int maxitems, int selected, int fontsize);
|
||||||
|
|
||||||
|
extern int menu;
|
||||||
|
extern int ROMSize;
|
||||||
|
|
||||||
|
#define SOFTRESET_ADR ((volatile u32*)0xCC003024)
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* MENU_GetLoadFile
|
* Reboot / Exit
|
||||||
*
|
***************************************************************************/
|
||||||
* Returns the filename of the selected file
|
|
||||||
***************************************************************************/
|
#ifndef HW_RVL
|
||||||
char *MENU_GetLoadFile( char *whichdir )
|
#define PSOSDLOADID 0x7c6000a6
|
||||||
|
int *psoid = (int *) 0x80001800;
|
||||||
|
void (*PSOReload) () = (void (*)()) 0x80001800;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Reboot()
|
||||||
{
|
{
|
||||||
int count;
|
#ifdef HW_RVL
|
||||||
char *p = NULL;
|
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
|
||||||
int quit = 0;
|
#else
|
||||||
int redraw = 1;
|
#define SOFTRESET_ADR ((volatile u32*)0xCC003024)
|
||||||
int current = 0;
|
*SOFTRESET_ADR = 0x00000000;
|
||||||
int offset = 0;
|
#endif
|
||||||
u16 buttons;
|
}
|
||||||
int do_DOWN = 0;
|
|
||||||
int do_UP = 0;
|
|
||||||
int do_A = 0;
|
|
||||||
|
|
||||||
count = gen_getdir( whichdir );
|
/****************************************************************************
|
||||||
|
* Load Manager
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
int
|
||||||
|
LoadManager ()
|
||||||
|
{
|
||||||
|
int loadROM = OpenROM(GCSettings.LoadMethod);
|
||||||
|
|
||||||
if ( count == 0 )
|
/***
|
||||||
|
* check for autoloadsram / freeze
|
||||||
|
***/
|
||||||
|
if ( loadROM == 1 ) // if ROM was loaded, load the SRAM & settings
|
||||||
{
|
{
|
||||||
printf("No ROM files in %s\n", whichdir);
|
//if ( GCSettings.AutoLoad == 1 )
|
||||||
while(1);
|
// LoadSRAM(GCSettings.SaveMethod, SILENT);
|
||||||
|
//else if ( GCSettings.AutoLoad == 2 )
|
||||||
|
// NGCUnfreezeGame (GCSettings.SaveMethod, SILENT);
|
||||||
|
|
||||||
|
// setup cheats
|
||||||
|
//SetupCheats();
|
||||||
}
|
}
|
||||||
#ifdef WII_BUILD
|
|
||||||
setup_controllers();
|
|
||||||
#endif
|
|
||||||
if ( count == 1 )
|
|
||||||
return (char*)direntries[0];
|
|
||||||
|
|
||||||
/* Do menu */
|
return loadROM;
|
||||||
while ( !quit )
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Preferences Menu
|
||||||
|
***************************************************************************/
|
||||||
|
static int prefmenuCount = 9;
|
||||||
|
static char prefmenu[][50] = {
|
||||||
|
|
||||||
|
"Load Method",
|
||||||
|
"Load Folder",
|
||||||
|
"Save Method",
|
||||||
|
"Save Folder",
|
||||||
|
|
||||||
|
"Auto Load",
|
||||||
|
"Auto Save",
|
||||||
|
"Verify MC Saves",
|
||||||
|
|
||||||
|
"Save Preferences",
|
||||||
|
"Back to Main Menu"
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
PreferencesMenu ()
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
int quit = 0;
|
||||||
|
int oldmenu = menu;
|
||||||
|
menu = 0;
|
||||||
|
while (quit == 0)
|
||||||
{
|
{
|
||||||
if ( redraw )
|
// some load/save methods are not implemented - here's where we skip them
|
||||||
|
// they need to be skipped in the order they were enumerated in snes9xGX.h
|
||||||
|
|
||||||
|
// no USB ports on GameCube
|
||||||
|
#ifndef HW_RVL
|
||||||
|
if(GCSettings.LoadMethod == METHOD_USB)
|
||||||
|
GCSettings.LoadMethod++;
|
||||||
|
if(GCSettings.SaveMethod == METHOD_USB)
|
||||||
|
GCSettings.SaveMethod++;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// check if DVD access in Wii mode is disabled
|
||||||
|
#ifndef WII_DVD
|
||||||
|
if(GCSettings.LoadMethod == METHOD_DVD)
|
||||||
|
GCSettings.LoadMethod++;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// saving to DVD is impossible
|
||||||
|
if(GCSettings.SaveMethod == METHOD_DVD)
|
||||||
|
GCSettings.SaveMethod++;
|
||||||
|
|
||||||
|
// disable SMB in GC mode (stalls out)
|
||||||
|
#ifndef HW_RVL
|
||||||
|
if(GCSettings.LoadMethod == METHOD_SMB)
|
||||||
|
GCSettings.LoadMethod++;
|
||||||
|
if(GCSettings.SaveMethod == METHOD_SMB)
|
||||||
|
GCSettings.SaveMethod++;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// disable MC saving in Wii mode - does not work for some reason!
|
||||||
|
#ifdef HW_RVL
|
||||||
|
if(GCSettings.SaveMethod == METHOD_MC_SLOTA)
|
||||||
|
GCSettings.SaveMethod++;
|
||||||
|
if(GCSettings.SaveMethod == METHOD_MC_SLOTB)
|
||||||
|
GCSettings.SaveMethod++;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// correct load/save methods out of bounds
|
||||||
|
if(GCSettings.LoadMethod > 4)
|
||||||
|
GCSettings.LoadMethod = 0;
|
||||||
|
if(GCSettings.SaveMethod > 6)
|
||||||
|
GCSettings.SaveMethod = 0;
|
||||||
|
|
||||||
|
if (GCSettings.LoadMethod == METHOD_AUTO) sprintf (prefmenu[0],"Load Method AUTO");
|
||||||
|
else if (GCSettings.LoadMethod == METHOD_SD) sprintf (prefmenu[0],"Load Method SD");
|
||||||
|
else if (GCSettings.LoadMethod == METHOD_USB) sprintf (prefmenu[0],"Load Method USB");
|
||||||
|
else if (GCSettings.LoadMethod == METHOD_DVD) sprintf (prefmenu[0],"Load Method DVD");
|
||||||
|
else if (GCSettings.LoadMethod == METHOD_SMB) sprintf (prefmenu[0],"Load Method Network");
|
||||||
|
|
||||||
|
sprintf (prefmenu[1], "Load Folder %s", GCSettings.LoadFolder);
|
||||||
|
|
||||||
|
if (GCSettings.SaveMethod == METHOD_AUTO) sprintf (prefmenu[2],"Save Method AUTO");
|
||||||
|
else if (GCSettings.SaveMethod == METHOD_SD) sprintf (prefmenu[2],"Save Method SD");
|
||||||
|
else if (GCSettings.SaveMethod == METHOD_USB) sprintf (prefmenu[2],"Save Method USB");
|
||||||
|
else if (GCSettings.SaveMethod == METHOD_SMB) sprintf (prefmenu[2],"Save Method Network");
|
||||||
|
else if (GCSettings.SaveMethod == METHOD_MC_SLOTA) sprintf (prefmenu[2],"Save Method MC Slot A");
|
||||||
|
else if (GCSettings.SaveMethod == METHOD_MC_SLOTB) sprintf (prefmenu[2],"Save Method MC Slot B");
|
||||||
|
|
||||||
|
sprintf (prefmenu[3], "Save Folder %s", GCSettings.SaveFolder);
|
||||||
|
|
||||||
|
// disable changing load/save directories for now
|
||||||
|
prefmenu[1][0] = '\0';
|
||||||
|
prefmenu[3][0] = '\0';
|
||||||
|
|
||||||
|
if (GCSettings.AutoLoad == 0) sprintf (prefmenu[4],"Auto Load OFF");
|
||||||
|
else if (GCSettings.AutoLoad == 1) sprintf (prefmenu[4],"Auto Load SRAM");
|
||||||
|
else if (GCSettings.AutoLoad == 2) sprintf (prefmenu[4],"Auto Load SNAPSHOT");
|
||||||
|
|
||||||
|
if (GCSettings.AutoSave == 0) sprintf (prefmenu[5],"Auto Save OFF");
|
||||||
|
else if (GCSettings.AutoSave == 1) sprintf (prefmenu[5],"Auto Save SRAM");
|
||||||
|
else if (GCSettings.AutoSave == 2) sprintf (prefmenu[5],"Auto Save SNAPSHOT");
|
||||||
|
else if (GCSettings.AutoSave == 3) sprintf (prefmenu[5],"Auto Save BOTH");
|
||||||
|
|
||||||
|
sprintf (prefmenu[6], "Verify MC Saves %s",
|
||||||
|
GCSettings.VerifySaves == true ? " ON" : "OFF");
|
||||||
|
|
||||||
|
|
||||||
|
ret = RunMenu (prefmenu, prefmenuCount, (char*)"Preferences", 16);
|
||||||
|
|
||||||
|
switch (ret)
|
||||||
{
|
{
|
||||||
whichfb ^= 1;
|
case 0:
|
||||||
VIDEO_ClearFrameBuffer(vmode, xfb[whichfb], COLOR_BLACK);
|
GCSettings.LoadMethod ++;
|
||||||
MENU_Draw( count, current, offset );
|
break;
|
||||||
VIDEO_SetNextFramebuffer(xfb[whichfb]);
|
|
||||||
VIDEO_Flush();
|
case 1:
|
||||||
VIDEO_WaitVSync();
|
break;
|
||||||
redraw = 0;
|
|
||||||
|
case 2:
|
||||||
|
GCSettings.SaveMethod ++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
GCSettings.AutoLoad ++;
|
||||||
|
if (GCSettings.AutoLoad > 2)
|
||||||
|
GCSettings.AutoLoad = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
GCSettings.AutoSave ++;
|
||||||
|
if (GCSettings.AutoSave > 3)
|
||||||
|
GCSettings.AutoSave = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
GCSettings.VerifySaves ^= 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7:
|
||||||
|
SavePrefs(GCSettings.SaveMethod, NOTSILENT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case -1: /*** Button B ***/
|
||||||
|
case 8:
|
||||||
|
quit = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
#ifdef WII_BUILD
|
}
|
||||||
WPAD_ScanPads();
|
menu = oldmenu;
|
||||||
WPADData *wpad;
|
}
|
||||||
wpad = WPAD_Data(0);
|
|
||||||
int b = wpad->exp.classic.btns;
|
/****************************************************************************
|
||||||
unsigned short b1 = wpad->btns_d;
|
* Game Options Menu
|
||||||
if (isClassicAvailable){
|
***************************************************************************/
|
||||||
if (b & CLASSIC_CTRL_BUTTON_DOWN){
|
|
||||||
do_DOWN = 1;
|
int
|
||||||
do{WPAD_ScanPads(); wpad = WPAD_Data(0);}
|
GameMenu ()
|
||||||
while (WPAD_ButtonsHeld(0));
|
{
|
||||||
}
|
int gamemenuCount = 7;
|
||||||
else if (b & CLASSIC_CTRL_BUTTON_UP){
|
char gamemenu[][50] = {
|
||||||
do_UP = 1;
|
"Return to Game",
|
||||||
do{WPAD_ScanPads(); wpad = WPAD_Data(0);}
|
"Reset Game",
|
||||||
while (WPAD_ButtonsHeld(0));
|
"Load SRAM", "Save SRAM",
|
||||||
}
|
"Load Game Snapshot", "Save Game Snapshot",
|
||||||
else if (b & CLASSIC_CTRL_BUTTON_A){
|
"Back to Main Menu"
|
||||||
do_A = 1;
|
};
|
||||||
do{WPAD_ScanPads(); wpad = WPAD_Data(0);}
|
|
||||||
while (WPAD_ButtonsHeld(0));
|
int ret, retval = 0;
|
||||||
}
|
int quit = 0;
|
||||||
|
int oldmenu = menu;
|
||||||
|
menu = 0;
|
||||||
|
|
||||||
|
while (quit == 0)
|
||||||
|
{
|
||||||
|
// disable SRAM/SNAPSHOT saving/loading if AUTO is on
|
||||||
|
|
||||||
|
if (GCSettings.AutoLoad == 1) // Auto Load SRAM
|
||||||
|
gamemenu[2][0] = '\0';
|
||||||
|
else if (GCSettings.AutoLoad == 2) // Auto Load SNAPSHOT
|
||||||
|
gamemenu[4][0] = '\0';
|
||||||
|
|
||||||
|
if (GCSettings.AutoSave == 1) // Auto Save SRAM
|
||||||
|
gamemenu[3][0] = '\0';
|
||||||
|
else if (GCSettings.AutoSave == 2) // Auto Save SNAPSHOT
|
||||||
|
gamemenu[5][0] = '\0';
|
||||||
|
else if (GCSettings.AutoSave == 3) // Auto Save BOTH
|
||||||
|
{
|
||||||
|
gamemenu[3][0] = '\0';
|
||||||
|
gamemenu[5][0] = '\0';
|
||||||
}
|
}
|
||||||
if (isWiimoteAvailable){
|
|
||||||
if (b1 & WPAD_BUTTON_LEFT){
|
ret = RunMenu (gamemenu, gamemenuCount, (char*)"Game Menu");
|
||||||
do_DOWN = 1;
|
|
||||||
do{WPAD_ScanPads(); wpad = WPAD_Data(0);}
|
switch (ret)
|
||||||
while (WPAD_ButtonsHeld(0));
|
{
|
||||||
}
|
case 0: // Return to Game
|
||||||
else if (b1 & WPAD_BUTTON_RIGHT){
|
quit = retval = 1;
|
||||||
do_UP = 1;
|
break;
|
||||||
do{WPAD_ScanPads(); wpad = WPAD_Data(0);}
|
|
||||||
while (WPAD_ButtonsHeld(0));
|
case 1: // Reset Game
|
||||||
}
|
emulator.emuReset();
|
||||||
else if (b1 & WPAD_BUTTON_2){
|
quit = retval = 1;
|
||||||
do_A = 1;
|
break;
|
||||||
do{WPAD_ScanPads(); wpad = WPAD_Data(0);}
|
|
||||||
while (WPAD_ButtonsHeld(0));
|
case 2: // Load SRAM
|
||||||
}
|
//quit = retval = LoadSRAM(GCSettings.SaveMethod, NOTSILENT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // Save SRAM
|
||||||
|
//SaveSRAM(GCSettings.SaveMethod, NOTSILENT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // Load Freeze
|
||||||
|
//quit = retval = NGCUnfreezeGame (GCSettings.SaveMethod, NOTSILENT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: // Save Freeze
|
||||||
|
//NGCFreezeGame (GCSettings.SaveMethod, NOTSILENT);
|
||||||
|
//emulator.emuWriteState(statename);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case -1: // Button B
|
||||||
|
case 6: // Return to previous menu
|
||||||
|
retval = 0;
|
||||||
|
quit = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
menu = oldmenu;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Controller Configuration
|
||||||
|
*
|
||||||
|
* Snes9x 1.51 uses a cmd system to work out which button has been pressed.
|
||||||
|
* Here, I simply move the designated value to the gcpadmaps array, which
|
||||||
|
* saves on updating the cmd sequences.
|
||||||
|
***************************************************************************/
|
||||||
|
u32
|
||||||
|
GetInput (u16 ctrlr_type)
|
||||||
|
{
|
||||||
|
//u32 exp_type;
|
||||||
|
u32 pressed;
|
||||||
|
pressed=0;
|
||||||
|
s8 gc_px = 0;
|
||||||
|
|
||||||
|
while( PAD_ButtonsHeld(0)
|
||||||
|
#ifdef HW_RVL
|
||||||
|
| WPAD_ButtonsHeld(0)
|
||||||
#endif
|
#endif
|
||||||
buttons = PAD_ButtonsDown(0);
|
) VIDEO_WaitVSync(); // button 'debounce'
|
||||||
if(buttons & PAD_BUTTON_DOWN)
|
|
||||||
do_DOWN = 1;
|
while (pressed == 0)
|
||||||
else if(buttons & PAD_BUTTON_UP)
|
{
|
||||||
do_UP = 1;
|
VIDEO_WaitVSync();
|
||||||
else if(buttons & PAD_BUTTON_A)
|
// get input based on controller type
|
||||||
do_A = 1;
|
if (ctrlr_type == CTRLR_GCPAD)
|
||||||
if (do_DOWN)
|
|
||||||
{
|
{
|
||||||
do_DOWN=0;
|
pressed = PAD_ButtonsHeld (0);
|
||||||
current++;
|
gc_px = PAD_SubStickX (0);
|
||||||
if ( current == count )
|
|
||||||
current = 0;
|
|
||||||
|
|
||||||
if ( ( current % PAGE_SIZE ) == 0 )
|
|
||||||
offset = current;
|
|
||||||
|
|
||||||
redraw = 1;
|
|
||||||
}
|
}
|
||||||
|
#ifdef HW_RVL
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( do_UP )
|
// if ( WPAD_Probe( 0, &exp_type) == 0) // check wiimote and expansion status (first if wiimote is connected & no errors)
|
||||||
|
// {
|
||||||
|
pressed = WPAD_ButtonsHeld (0);
|
||||||
|
|
||||||
|
// if (ctrlr_type != CTRLR_WIIMOTE && exp_type != ctrlr_type+1) // if we need input from an expansion, and its not connected...
|
||||||
|
// pressed = 0;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*** check for exit sequence (c-stick left OR home button) ***/
|
||||||
|
if ( (gc_px < -70) || (pressed & WPAD_BUTTON_HOME) || (pressed & WPAD_CLASSIC_BUTTON_HOME) )
|
||||||
|
return 0;
|
||||||
|
} // end while
|
||||||
|
while( pressed == (PAD_ButtonsHeld(0)
|
||||||
|
#ifdef HW_RVL
|
||||||
|
| WPAD_ButtonsHeld(0)
|
||||||
|
#endif
|
||||||
|
) ) VIDEO_WaitVSync();
|
||||||
|
|
||||||
|
return pressed;
|
||||||
|
} // end GetInput()
|
||||||
|
|
||||||
|
int cfg_text_count = 7;
|
||||||
|
char cfg_text[][50] = {
|
||||||
|
"Remapping ",
|
||||||
|
"Press Any Button",
|
||||||
|
"on the",
|
||||||
|
" ", // identify controller
|
||||||
|
" ",
|
||||||
|
"Press C-Left or",
|
||||||
|
"Home to exit"
|
||||||
|
};
|
||||||
|
|
||||||
|
u32
|
||||||
|
GetButtonMap(u16 ctrlr_type, char* btn_name)
|
||||||
|
{
|
||||||
|
u32 pressed, previous;
|
||||||
|
char temp[50] = "";
|
||||||
|
uint k;
|
||||||
|
pressed = 0; previous = 1;
|
||||||
|
|
||||||
|
switch (ctrlr_type) {
|
||||||
|
case CTRLR_NUNCHUK:
|
||||||
|
strncpy (cfg_text[3], (char*)"NUNCHUK", 7);
|
||||||
|
break;
|
||||||
|
case CTRLR_CLASSIC:
|
||||||
|
strncpy (cfg_text[3], (char*)"CLASSIC", 7);
|
||||||
|
break;
|
||||||
|
case CTRLR_GCPAD:
|
||||||
|
strncpy (cfg_text[3], (char*)"GC PAD", 7);
|
||||||
|
break;
|
||||||
|
case CTRLR_WIIMOTE:
|
||||||
|
strncpy (cfg_text[3], (char*)"WIIMOTE", 7);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*** note which button we are remapping ***/
|
||||||
|
sprintf (temp, (char*)"Remapping ");
|
||||||
|
for (k=0; k<9-strlen(btn_name); k++) strcat(temp, " "); // add whitespace padding to align text
|
||||||
|
strncat (temp, btn_name, 9); // snes button we are remapping
|
||||||
|
strncpy (cfg_text[0], temp, 19); // copy this all back to the text we wish to display
|
||||||
|
|
||||||
|
DrawMenu(&cfg_text[0], NULL, cfg_text_count, 1); // display text
|
||||||
|
|
||||||
|
// while (previous != pressed && pressed == 0); // get two consecutive button presses (which are the same)
|
||||||
|
// {
|
||||||
|
// previous = pressed;
|
||||||
|
// VIDEO_WaitVSync(); // slow things down a bit so we don't overread the pads
|
||||||
|
pressed = GetInput(ctrlr_type);
|
||||||
|
// }
|
||||||
|
return pressed;
|
||||||
|
} // end getButtonMap()
|
||||||
|
|
||||||
|
int cfg_btns_count = 11;
|
||||||
|
char cfg_btns_menu[][50] = {
|
||||||
|
"A - ",
|
||||||
|
"B - ",
|
||||||
|
"L TRIG - ",
|
||||||
|
"R TRIG - ",
|
||||||
|
"SELECT - ",
|
||||||
|
"START - ",
|
||||||
|
"UP - ",
|
||||||
|
"DOWN - ",
|
||||||
|
"LEFT - ",
|
||||||
|
"RIGHT - ",
|
||||||
|
"Return to previous"
|
||||||
|
};
|
||||||
|
|
||||||
|
extern unsigned int gcpadmap[];
|
||||||
|
extern unsigned int wmpadmap[];
|
||||||
|
extern unsigned int ccpadmap[];
|
||||||
|
extern unsigned int ncpadmap[];
|
||||||
|
|
||||||
|
void
|
||||||
|
ConfigureButtons (u16 ctrlr_type)
|
||||||
|
{
|
||||||
|
int quit = 0;
|
||||||
|
int ret = 0;
|
||||||
|
int oldmenu = menu;
|
||||||
|
menu = 0;
|
||||||
|
char* menu_title = NULL;
|
||||||
|
u32 pressed;
|
||||||
|
|
||||||
|
unsigned int* currentpadmap = 0;
|
||||||
|
char temp[50] = "";
|
||||||
|
int i, j;
|
||||||
|
uint k;
|
||||||
|
|
||||||
|
/*** Update Menu Title (based on controller we're configuring) ***/
|
||||||
|
switch (ctrlr_type) {
|
||||||
|
case CTRLR_NUNCHUK:
|
||||||
|
menu_title = (char*)"VBA - NUNCHUK";
|
||||||
|
currentpadmap = ncpadmap;
|
||||||
|
break;
|
||||||
|
case CTRLR_CLASSIC:
|
||||||
|
menu_title = (char*)"VBA - CLASSIC";
|
||||||
|
currentpadmap = ccpadmap;
|
||||||
|
break;
|
||||||
|
case CTRLR_GCPAD:
|
||||||
|
menu_title = (char*)"VBA - GC PAD";
|
||||||
|
currentpadmap = gcpadmap;
|
||||||
|
break;
|
||||||
|
case CTRLR_WIIMOTE:
|
||||||
|
menu_title = (char*)"VBA - WIIMOTE";
|
||||||
|
currentpadmap = wmpadmap;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
while (quit == 0)
|
||||||
|
{
|
||||||
|
/*** Update Menu with Current ButtonMap ***/
|
||||||
|
for (i=0; i<10; i++) // vba pad has 10 buttons to config (go thru them)
|
||||||
|
{
|
||||||
|
// get current padmap button name to display
|
||||||
|
for ( j=0;
|
||||||
|
j < ctrlr_def[ctrlr_type].num_btns &&
|
||||||
|
currentpadmap[i] != ctrlr_def[ctrlr_type].map[j].btn // match padmap button press with button names
|
||||||
|
; j++ );
|
||||||
|
|
||||||
|
memset (temp, 0, sizeof(temp));
|
||||||
|
strncpy (temp, cfg_btns_menu[i], 12); // copy vba button information
|
||||||
|
if (currentpadmap[i] == ctrlr_def[ctrlr_type].map[j].btn) // check if a match was made
|
||||||
{
|
{
|
||||||
do_UP=0;
|
for (k=0; k<7-strlen(ctrlr_def[ctrlr_type].map[j].name) ;k++) strcat(temp, " "); // add whitespace padding to align text
|
||||||
current--;
|
strncat (temp, ctrlr_def[ctrlr_type].map[j].name, 6); // update button map display
|
||||||
if ( current < 0 ) current = count - 1;
|
|
||||||
offset = ( current / PAGE_SIZE ) * PAGE_SIZE;
|
|
||||||
redraw = 1;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
strcat (temp, (char*)"---"); // otherwise, button is 'unmapped'
|
||||||
if ( do_A )
|
strncpy (cfg_btns_menu[i], temp, 19); // move back updated information
|
||||||
{
|
|
||||||
do_A=0;
|
}
|
||||||
quit = 1;
|
|
||||||
p = (char*)direntries[current];
|
ret = RunMenu (cfg_btns_menu, cfg_btns_count, menu_title, 16);
|
||||||
}
|
|
||||||
}
|
switch (ret)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
case 6:
|
||||||
|
case 7:
|
||||||
|
case 8:
|
||||||
|
case 9:
|
||||||
|
case 10:
|
||||||
|
case 11:
|
||||||
|
/*** Change button map ***/
|
||||||
|
// wait for input
|
||||||
|
memset (temp, 0, sizeof(temp));
|
||||||
|
strncpy(temp, cfg_btns_menu[ret], 6); // get the name of the vba button we're changing
|
||||||
|
pressed = GetButtonMap(ctrlr_type, temp); // get a button selection from user
|
||||||
|
// FIX: check if input is valid for this controller
|
||||||
|
if (pressed != 0) // check if a the button was configured, or if the user exited.
|
||||||
|
currentpadmap[ret] = pressed; // update mapping
|
||||||
|
break;
|
||||||
|
|
||||||
|
case -1: /*** Button B ***/
|
||||||
|
case 12:
|
||||||
|
/*** Return ***/
|
||||||
|
quit = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
menu = oldmenu;
|
||||||
|
} // end configurebuttons()
|
||||||
|
|
||||||
|
int ctlrmenucount = 6;
|
||||||
|
char ctlrmenu[][50] = {
|
||||||
|
"Nunchuk",
|
||||||
|
"Classic Controller",
|
||||||
|
"Wiimote",
|
||||||
|
"Gamecube Pad",
|
||||||
|
"Save Preferences",
|
||||||
|
"Go Back"
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
ConfigureControllers ()
|
||||||
|
{
|
||||||
|
int quit = 0;
|
||||||
|
int ret = 0;
|
||||||
|
int oldmenu = menu;
|
||||||
|
menu = 0;
|
||||||
|
|
||||||
|
// disable unavailable controller options if in GC mode
|
||||||
|
#ifndef HW_RVL
|
||||||
|
ctlrmenu[4][0] = '\0';
|
||||||
|
ctlrmenu[5][0] = '\0';
|
||||||
|
ctlrmenu[6][0] = '\0';
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (quit == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*** Controller Config Menu ***/
|
||||||
|
ret = RunMenu (ctlrmenu, ctlrmenucount, (char*)"Configure Controllers");
|
||||||
|
|
||||||
|
switch (ret)
|
||||||
|
{
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
/*** Configure Nunchuk ***/
|
||||||
|
ConfigureButtons (CTRLR_NUNCHUK);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
/*** Configure Classic ***/
|
||||||
|
ConfigureButtons (CTRLR_CLASSIC);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
/*** Configure Wiimote ***/
|
||||||
|
ConfigureButtons (CTRLR_WIIMOTE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
/*** Configure GC Pad ***/
|
||||||
|
ConfigureButtons (CTRLR_GCPAD);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
/*** Save Preferences Now ***/
|
||||||
|
SavePrefs(GCSettings.SaveMethod, NOTSILENT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case -1: /*** Button B ***/
|
||||||
|
case 5:
|
||||||
|
/*** Return ***/
|
||||||
|
quit = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
whichfb ^= 1;
|
menu = oldmenu;
|
||||||
VIDEO_ClearFrameBuffer(vmode, xfb[whichfb], COLOR_BLACK);
|
|
||||||
forecolour = COLOR_WHITE;
|
|
||||||
backcolour = COLOR_BLACK;
|
|
||||||
MENU_DrawString(-1, 240, "Loading ... Wait", 1);
|
|
||||||
VIDEO_SetNextFramebuffer(xfb[whichfb]);
|
|
||||||
VIDEO_Flush();
|
|
||||||
VIDEO_WaitVSync();
|
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Main Menu
|
||||||
|
***************************************************************************/
|
||||||
|
int menucount = 7;
|
||||||
|
char menuitems[][50] = {
|
||||||
|
"Choose Game", "Controller Configuration", "Preferences",
|
||||||
|
"Game Menu",
|
||||||
|
"Credits", "Reset System", "Return to Loader"
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
mainmenu (int selectedMenu)
|
||||||
|
{
|
||||||
|
tb_t start,end;
|
||||||
|
mftb(&start);
|
||||||
|
StopAudio();
|
||||||
|
|
||||||
|
int quit = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
// disable game-specific menu items if a ROM isn't loaded
|
||||||
|
if (ROMSize == 0 )
|
||||||
|
menuitems[3][0] = '\0';
|
||||||
|
else
|
||||||
|
sprintf (menuitems[3], "Game Menu");
|
||||||
|
|
||||||
|
VIDEO_WaitVSync ();
|
||||||
|
|
||||||
|
while (quit == 0)
|
||||||
|
{
|
||||||
|
if(selectedMenu >= 0)
|
||||||
|
{
|
||||||
|
ret = selectedMenu;
|
||||||
|
selectedMenu = -1; // default back to main menu
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = RunMenu (menuitems, menucount, (char*)"Main Menu");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ret)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
// Load ROM Menu
|
||||||
|
quit = LoadManager ();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
// Configure Controllers
|
||||||
|
ConfigureControllers ();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
// Preferences
|
||||||
|
PreferencesMenu ();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
// Game Options
|
||||||
|
quit = GameMenu ();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
// Credits
|
||||||
|
Credits ();
|
||||||
|
WaitButtonA ();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
// Reset the Gamecube/Wii
|
||||||
|
Reboot();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
// Exit to Loader
|
||||||
|
#ifdef HW_RVL
|
||||||
|
#ifdef WII_DVD
|
||||||
|
DI_Close();
|
||||||
|
#endif
|
||||||
|
exit(0);
|
||||||
|
#else // gamecube
|
||||||
|
if (psoid[0] == PSOSDLOADID)
|
||||||
|
PSOReload ();
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case -1: // Button B
|
||||||
|
// Return to Game
|
||||||
|
quit = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Remove any still held buttons ***/
|
||||||
|
#ifdef HW_RVL
|
||||||
|
while( PAD_ButtonsHeld(0) || WPAD_ButtonsHeld(0) )
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
#else
|
||||||
|
while( PAD_ButtonsHeld(0) )
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
StartAudio();
|
||||||
|
mftb(&end);
|
||||||
|
loadtimeradjust += tb_diff_msec(&end, &start);
|
||||||
|
}
|
||||||
|
19
source/ngc/menu.h
Normal file
19
source/ngc/menu.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* crunchy2 May-June 2007
|
||||||
|
* Tantric August 2008
|
||||||
|
*
|
||||||
|
* menu.h
|
||||||
|
*
|
||||||
|
* Menu flow routines - handles all menu logic
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _NGCMENU_
|
||||||
|
|
||||||
|
#define _NGCMENU_
|
||||||
|
|
||||||
|
void mainmenu (int selectedMenu);
|
||||||
|
|
||||||
|
#endif
|
920
source/ngc/menudraw.cpp
Normal file
920
source/ngc/menudraw.cpp
Normal file
@ -0,0 +1,920 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* crunchy2 June 2007
|
||||||
|
* Tantric August 2008
|
||||||
|
*
|
||||||
|
* menudraw.cpp
|
||||||
|
*
|
||||||
|
* Menu drawing routines
|
||||||
|
*
|
||||||
|
* Uses libfreetype 2.2.1 compiled for GC with TTF support only.
|
||||||
|
* TTF only reduces the library by some 900k bytes!
|
||||||
|
*
|
||||||
|
* **WARNING***
|
||||||
|
*
|
||||||
|
* ONLY USE GUARANTEED PATENT FREE FONTS.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <wiiuse/wpad.h>
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
|
#include "video.h"
|
||||||
|
#include "menudraw.h"
|
||||||
|
#include "vba.h"
|
||||||
|
#include "filesel.h"
|
||||||
|
#include "dvd.h"
|
||||||
|
#include "input.h"
|
||||||
|
|
||||||
|
/*** Globals ***/
|
||||||
|
FT_Library ftlibrary;
|
||||||
|
FT_Face face;
|
||||||
|
FT_GlyphSlot slot;
|
||||||
|
FT_UInt glyph_index;
|
||||||
|
static unsigned int fonthi, fontlo;
|
||||||
|
|
||||||
|
extern char fontface[]; /*** From fontface.s ***/
|
||||||
|
extern int fontsize; /*** From fontface.s ***/
|
||||||
|
extern int screenheight;
|
||||||
|
extern unsigned int *xfb[2];
|
||||||
|
extern int whichfb;
|
||||||
|
|
||||||
|
/*** Permanent backdrop ***/
|
||||||
|
#ifdef HW_RVL
|
||||||
|
u32 *backdrop;
|
||||||
|
#else
|
||||||
|
static u32 *backdrop;
|
||||||
|
#endif
|
||||||
|
unsigned int getcolour (u8 r1, u8 g1, u8 b1);
|
||||||
|
void DrawLineFast( int startx, int endx, int y, u8 r, u8 g, u8 b );
|
||||||
|
u32 getrgb( u32 ycbr, u32 low );
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Initialisation of libfreetype
|
||||||
|
***************************************************************************/
|
||||||
|
int
|
||||||
|
FT_Init ()
|
||||||
|
{
|
||||||
|
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = FT_Init_FreeType (&ftlibrary);
|
||||||
|
if (err)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
err =
|
||||||
|
FT_New_Memory_Face (ftlibrary, (FT_Byte *) fontface, fontsize, 0, &face);
|
||||||
|
if (err)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
setfontsize (16);
|
||||||
|
setfontcolour (0xff, 0xff, 0xff);
|
||||||
|
|
||||||
|
slot = face->glyph;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* setfontsize
|
||||||
|
*
|
||||||
|
* Set the screen font size in pixels
|
||||||
|
***************************************************************************/
|
||||||
|
void
|
||||||
|
setfontsize (int pixelsize)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = FT_Set_Pixel_Sizes (face, 0, pixelsize);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
printf ("Error setting pixel sizes!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* DrawCharacter
|
||||||
|
* Draws a single character on the screen
|
||||||
|
***************************************************************************/
|
||||||
|
static void
|
||||||
|
DrawCharacter (FT_Bitmap * bmp, FT_Int x, FT_Int y)
|
||||||
|
{
|
||||||
|
FT_Int i, j, p, q;
|
||||||
|
FT_Int x_max = x + bmp->width;
|
||||||
|
FT_Int y_max = y + bmp->rows;
|
||||||
|
int spos;
|
||||||
|
unsigned int pixel;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
for (i = x, p = 0; i < x_max; i++, p++)
|
||||||
|
{
|
||||||
|
for (j = y, q = 0; j < y_max; j++, q++)
|
||||||
|
{
|
||||||
|
if (i < 0 || j < 0 || i >= 640 || j >= screenheight)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*** Convert pixel position to GC int sizes ***/
|
||||||
|
spos = (j * 320) + (i >> 1);
|
||||||
|
|
||||||
|
pixel = xfb[whichfb][spos];
|
||||||
|
c = bmp->buffer[q * bmp->width + p];
|
||||||
|
|
||||||
|
/*** Cool Anti-Aliasing doesn't work too well at hires on GC ***/
|
||||||
|
if (c > 128)
|
||||||
|
{
|
||||||
|
if (i & 1)
|
||||||
|
pixel = (pixel & 0xffff0000) | fontlo;
|
||||||
|
else
|
||||||
|
pixel = ((pixel & 0xffff) | fonthi);
|
||||||
|
|
||||||
|
xfb[whichfb][spos] = pixel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* DrawText
|
||||||
|
*
|
||||||
|
* Place the font bitmap on the screen
|
||||||
|
***************************************************************************/
|
||||||
|
void
|
||||||
|
DrawText (int x, int y, char *text)
|
||||||
|
{
|
||||||
|
int px, n;
|
||||||
|
int i;
|
||||||
|
int err;
|
||||||
|
int value, count;
|
||||||
|
|
||||||
|
n = strlen (text);
|
||||||
|
if (n == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
setfontcolour (0x00, 0x00, 0x00);
|
||||||
|
|
||||||
|
/*** x == -1, auto centre ***/
|
||||||
|
if (x == -1)
|
||||||
|
{
|
||||||
|
value = 0;
|
||||||
|
px = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = 1;
|
||||||
|
px = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (count = value; count < 2; count++)
|
||||||
|
{
|
||||||
|
/*** Draw the string ***/
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
err = FT_Load_Char (face, text[i], FT_LOAD_RENDER);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
printf ("Error %c %d\n", text[i], err);
|
||||||
|
continue; /*** Skip unprintable characters ***/
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count)
|
||||||
|
DrawCharacter (&slot->bitmap, px + slot->bitmap_left,
|
||||||
|
y - slot->bitmap_top);
|
||||||
|
|
||||||
|
px += slot->advance.x >> 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
px = (640 - px) >> 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* setfontcolour
|
||||||
|
*
|
||||||
|
* Uses RGB triple values.
|
||||||
|
***************************************************************************/
|
||||||
|
void
|
||||||
|
setfontcolour (u8 r, u8 g, u8 b)
|
||||||
|
{
|
||||||
|
u32 fontcolour;
|
||||||
|
|
||||||
|
fontcolour = getcolour (r, g, b);
|
||||||
|
fonthi = fontcolour & 0xffff0000;
|
||||||
|
fontlo = fontcolour & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Display credits, legal copyright and licence
|
||||||
|
*
|
||||||
|
* THIS MUST NOT BE REMOVED IN ANY DERIVATIVE WORK.
|
||||||
|
***************************************************************************/
|
||||||
|
void
|
||||||
|
Credits ()
|
||||||
|
{
|
||||||
|
clearscreen ();
|
||||||
|
|
||||||
|
setfontcolour (0x00, 0x00, 0x00);
|
||||||
|
|
||||||
|
setfontsize (28);
|
||||||
|
DrawText (-1, 60, (char*)"Credits");
|
||||||
|
|
||||||
|
int ypos = 25;
|
||||||
|
|
||||||
|
if (screenheight == 480)
|
||||||
|
ypos += 52;
|
||||||
|
else
|
||||||
|
ypos += 32;
|
||||||
|
|
||||||
|
setfontsize (18);
|
||||||
|
DrawText (-1, ypos += 30, (char*)"Technical");
|
||||||
|
|
||||||
|
setfontsize (14);
|
||||||
|
DrawText (-1, ypos += 22, (char*)"Snes9x v1.5.1 - Snes9x Team");
|
||||||
|
DrawText (-1, ypos += 18, (char*)"GameCube Port 2.0 WIP6 and earlier - SoftDev");
|
||||||
|
DrawText (-1, ypos += 18, (char*)"Additional improvements to 2.0 WIP6 - eke-eke");
|
||||||
|
DrawText (-1, ypos += 18, (char*)"GameCube 2.0.1bx enhancements - crunchy2");
|
||||||
|
DrawText (-1, ypos += 18, (char*)"v00x updates - michniewski & Tantric");
|
||||||
|
DrawText (-1, ypos += 18, (char*)"GX - http://www.gc-linux.org");
|
||||||
|
DrawText (-1, ypos += 18, (char*)"libogc - Shagkur & wintermute");
|
||||||
|
|
||||||
|
setfontsize (18);
|
||||||
|
DrawText (-1, ypos += 30, (char*)"Testing");
|
||||||
|
|
||||||
|
setfontsize (14);
|
||||||
|
DrawText (-1, ypos += 22, (char*)"crunchy2 / tehskeen users / others");
|
||||||
|
|
||||||
|
setfontsize (18);
|
||||||
|
DrawText (-1, ypos += 30, (char*)"Documentation");
|
||||||
|
|
||||||
|
setfontsize (14);
|
||||||
|
DrawText (-1, ypos += 22, (char*)"brakken, crunchy2, michniewski");
|
||||||
|
|
||||||
|
setfontsize (12);
|
||||||
|
DrawText (-1, ypos += 50, (char*)"Snes9x - Copyright (c) Snes9x Team 1996 - 2006");
|
||||||
|
DrawText (-1, ypos += 15, (char*)"This software is open source and may be copied, distributed, or modified");
|
||||||
|
DrawText (-1, ypos += 15, (char*)"under the terms of the GNU General Public License (GPL) Version 2.");
|
||||||
|
|
||||||
|
showscreen ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* getcolour
|
||||||
|
*
|
||||||
|
* Simply converts RGB to Y1CbY2Cr format
|
||||||
|
*
|
||||||
|
* I got this from a pastebin, so thanks to whoever originally wrote it!
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
getcolour (u8 r1, u8 g1, u8 b1)
|
||||||
|
{
|
||||||
|
int y1, cb1, cr1, y2, cb2, cr2, cb, cr;
|
||||||
|
u8 r2, g2, b2;
|
||||||
|
|
||||||
|
r2 = r1;
|
||||||
|
g2 = g1;
|
||||||
|
b2 = b1;
|
||||||
|
|
||||||
|
y1 = (299 * r1 + 587 * g1 + 114 * b1) / 1000;
|
||||||
|
cb1 = (-16874 * r1 - 33126 * g1 + 50000 * b1 + 12800000) / 100000;
|
||||||
|
cr1 = (50000 * r1 - 41869 * g1 - 8131 * b1 + 12800000) / 100000;
|
||||||
|
|
||||||
|
y2 = (299 * r2 + 587 * g2 + 114 * b2) / 1000;
|
||||||
|
cb2 = (-16874 * r2 - 33126 * g2 + 50000 * b2 + 12800000) / 100000;
|
||||||
|
cr2 = (50000 * r2 - 41869 * g2 - 8131 * b2 + 12800000) / 100000;
|
||||||
|
|
||||||
|
cb = (cb1 + cb2) >> 1;
|
||||||
|
cr = (cr1 + cr2) >> 1;
|
||||||
|
|
||||||
|
return ((y1 << 24) | (cb << 16) | (y2 << 8) | cr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Wait for user to press A
|
||||||
|
***************************************************************************/
|
||||||
|
void
|
||||||
|
WaitButtonA ()
|
||||||
|
{
|
||||||
|
#ifdef HW_RVL
|
||||||
|
while ( (PAD_ButtonsDown (0) & PAD_BUTTON_A) || (WPAD_ButtonsDown(0) & (WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A)) ) VIDEO_WaitVSync();
|
||||||
|
while (!(PAD_ButtonsDown (0) & PAD_BUTTON_A) && !(WPAD_ButtonsDown(0) & (WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A)) ) VIDEO_WaitVSync();
|
||||||
|
#else
|
||||||
|
while ( PAD_ButtonsDown (0) & PAD_BUTTON_A ) VIDEO_WaitVSync();
|
||||||
|
while (!(PAD_ButtonsDown (0) & PAD_BUTTON_A) ) VIDEO_WaitVSync();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Wait for user to press A or B. Returns 0 = B; 1 = A
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
int
|
||||||
|
WaitButtonAB ()
|
||||||
|
{
|
||||||
|
#ifdef HW_RVL
|
||||||
|
u32 gc_btns, wm_btns;
|
||||||
|
|
||||||
|
while ( (PAD_ButtonsDown (0) & (PAD_BUTTON_A | PAD_BUTTON_B))
|
||||||
|
|| (WPAD_ButtonsDown(0) & (WPAD_BUTTON_A | WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_A | WPAD_CLASSIC_BUTTON_B))
|
||||||
|
) VIDEO_WaitVSync();
|
||||||
|
|
||||||
|
while ( TRUE )
|
||||||
|
{
|
||||||
|
gc_btns = PAD_ButtonsDown (0);
|
||||||
|
wm_btns = WPAD_ButtonsDown (0);
|
||||||
|
if ( (gc_btns & PAD_BUTTON_A) || (wm_btns & (WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A)) )
|
||||||
|
return 1;
|
||||||
|
else if ( (gc_btns & PAD_BUTTON_B) || (wm_btns & (WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B)) )
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
u32 gc_btns;
|
||||||
|
|
||||||
|
while ( (PAD_ButtonsDown (0) & (PAD_BUTTON_A | PAD_BUTTON_B)) ) VIDEO_WaitVSync();
|
||||||
|
|
||||||
|
while ( TRUE )
|
||||||
|
{
|
||||||
|
gc_btns = PAD_ButtonsDown (0);
|
||||||
|
if ( gc_btns & PAD_BUTTON_A )
|
||||||
|
return 1;
|
||||||
|
else if ( gc_btns & PAD_BUTTON_B )
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Show a prompt
|
||||||
|
***************************************************************************/
|
||||||
|
void
|
||||||
|
WaitPrompt (char *msg)
|
||||||
|
{
|
||||||
|
int ypos = (screenheight - 64) >> 1;
|
||||||
|
|
||||||
|
if (screenheight == 480)
|
||||||
|
ypos += 52;
|
||||||
|
else
|
||||||
|
ypos += 32;
|
||||||
|
|
||||||
|
clearscreen ();
|
||||||
|
DrawText (-1, ypos, msg);
|
||||||
|
ypos += 30;
|
||||||
|
DrawText (-1, ypos, (char*)"Press A to continue");
|
||||||
|
showscreen ();
|
||||||
|
WaitButtonA ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Show a prompt with choice of two options. Returns 1 if A button was pressed
|
||||||
|
and 0 if B button was pressed.
|
||||||
|
***************************************************************************/
|
||||||
|
int
|
||||||
|
WaitPromptChoice (char *msg, char *bmsg, char *amsg)
|
||||||
|
{
|
||||||
|
int ypos = (screenheight - 64) >> 1;
|
||||||
|
|
||||||
|
if (screenheight == 480)
|
||||||
|
ypos += 37;
|
||||||
|
else
|
||||||
|
ypos += 17;
|
||||||
|
|
||||||
|
clearscreen ();
|
||||||
|
DrawText (-1, ypos, msg);
|
||||||
|
ypos += 60;
|
||||||
|
char txt[80];
|
||||||
|
sprintf (txt, "B = %s : A = %s", bmsg, amsg);
|
||||||
|
DrawText (-1, ypos, txt);
|
||||||
|
showscreen ();
|
||||||
|
return WaitButtonAB ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Show an action in progress
|
||||||
|
***************************************************************************/
|
||||||
|
void
|
||||||
|
ShowAction (char *msg)
|
||||||
|
{
|
||||||
|
int ypos = (screenheight - 30) >> 1;
|
||||||
|
|
||||||
|
if (screenheight == 480)
|
||||||
|
ypos += 52;
|
||||||
|
else
|
||||||
|
ypos += 32;
|
||||||
|
|
||||||
|
clearscreen ();
|
||||||
|
DrawText (-1, ypos, msg);
|
||||||
|
showscreen ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Generic Menu Routines
|
||||||
|
***************************************************************************/
|
||||||
|
void
|
||||||
|
DrawMenu (char items[][50], char *title, int maxitems, int selected, int fontsize, int x)
|
||||||
|
{
|
||||||
|
int i, w = 0;
|
||||||
|
int ypos = 0;
|
||||||
|
int n = 1;
|
||||||
|
int line_height;
|
||||||
|
|
||||||
|
ypos = 45;
|
||||||
|
|
||||||
|
if (screenheight == 480)
|
||||||
|
ypos += 52;
|
||||||
|
else
|
||||||
|
ypos += 32;
|
||||||
|
|
||||||
|
clearscreen ();
|
||||||
|
|
||||||
|
setfontcolour (0, 0, 0);
|
||||||
|
|
||||||
|
if (title != NULL)
|
||||||
|
{
|
||||||
|
setfontsize (28);
|
||||||
|
DrawText (-1, 60, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
setfontsize (12);
|
||||||
|
DrawText (510, screenheight - 20, VERSIONSTR);
|
||||||
|
|
||||||
|
// Draw menu items
|
||||||
|
|
||||||
|
setfontsize (fontsize); // set font size
|
||||||
|
|
||||||
|
line_height = (fontsize + 8);
|
||||||
|
|
||||||
|
for (i = 0; i < maxitems; i++)
|
||||||
|
{
|
||||||
|
if(strlen(items[i]) > 0)
|
||||||
|
{
|
||||||
|
if ( items[i] == NULL )
|
||||||
|
ypos -= line_height;
|
||||||
|
else if (i == selected)
|
||||||
|
{
|
||||||
|
for( w = 0; w < line_height; w++ )
|
||||||
|
DrawLineFast( 30, 610, n * line_height + (ypos-line_height+6) + w, 0x80, 0x80, 0x80 );
|
||||||
|
|
||||||
|
setfontcolour (0xff, 0xff, 0xff);
|
||||||
|
DrawText (x, n * line_height + ypos, items[i]);
|
||||||
|
setfontcolour (0x00, 0x00, 0x00);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawText (x, n * line_height + ypos, items[i]);
|
||||||
|
}
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showscreen ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* FindMenuItem
|
||||||
|
*
|
||||||
|
* Help function to find the next visible menu item on the list
|
||||||
|
* Supports menu wrap-around
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
int FindMenuItem(char items[][50], int maxitems, int currentItem, int direction)
|
||||||
|
{
|
||||||
|
int nextItem = currentItem + direction;
|
||||||
|
|
||||||
|
if(nextItem < 0)
|
||||||
|
nextItem = maxitems-1;
|
||||||
|
else if(nextItem >= maxitems)
|
||||||
|
nextItem = 0;
|
||||||
|
|
||||||
|
if(strlen(items[nextItem]) > 0)
|
||||||
|
return nextItem;
|
||||||
|
else
|
||||||
|
return FindMenuItem(&items[0], maxitems, nextItem, direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* RunMenu
|
||||||
|
*
|
||||||
|
* Call this with the menu array defined in menu.cpp
|
||||||
|
* It's here to keep all the font / interface stuff together.
|
||||||
|
***************************************************************************/
|
||||||
|
int menu = 0;
|
||||||
|
|
||||||
|
int
|
||||||
|
RunMenu (char items[][50], int maxitems, char *title, int fontsize, int x)
|
||||||
|
{
|
||||||
|
int redraw = 1;
|
||||||
|
int quit = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
u32 p = 0;
|
||||||
|
u32 wp = 0;
|
||||||
|
signed char gc_ay = 0;
|
||||||
|
signed char wm_ay = 0;
|
||||||
|
|
||||||
|
while (quit == 0)
|
||||||
|
{
|
||||||
|
if (redraw)
|
||||||
|
{
|
||||||
|
DrawMenu (&items[0], title, maxitems, menu, fontsize);
|
||||||
|
redraw = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gc_ay = PAD_StickY (0);
|
||||||
|
p = PAD_ButtonsDown (0);
|
||||||
|
#ifdef HW_RVL
|
||||||
|
wm_ay = WPAD_StickY (0,0);
|
||||||
|
wp = WPAD_ButtonsDown (0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
VIDEO_WaitVSync(); // slow things down a bit so we don't overread the pads
|
||||||
|
|
||||||
|
/*** Look for up ***/
|
||||||
|
if ( (p & PAD_BUTTON_UP) || (wp & (WPAD_BUTTON_UP | WPAD_CLASSIC_BUTTON_UP)) || (gc_ay > PADCAL) || (wm_ay > PADCAL) )
|
||||||
|
{
|
||||||
|
redraw = 1;
|
||||||
|
menu = FindMenuItem(&items[0], maxitems, menu, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Look for down ***/
|
||||||
|
if ( (p & PAD_BUTTON_DOWN) || (wp & (WPAD_BUTTON_DOWN | WPAD_CLASSIC_BUTTON_DOWN)) || (gc_ay < -PADCAL) || (wm_ay < -PADCAL) )
|
||||||
|
{
|
||||||
|
redraw = 1;
|
||||||
|
menu = FindMenuItem(&items[0], maxitems, menu, +1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((p & PAD_BUTTON_A) || (wp & (WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A)))
|
||||||
|
{
|
||||||
|
quit = 1;
|
||||||
|
ret = menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((p & PAD_BUTTON_B) || (wp & (WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B)))
|
||||||
|
{
|
||||||
|
quit = -1;
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Wait for B button to be released before proceeding ***/
|
||||||
|
while ( (PAD_ButtonsDown(0) & PAD_BUTTON_B)
|
||||||
|
#ifdef HW_RVL
|
||||||
|
|| (WPAD_ButtonsDown(0) & (WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B))
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ret = -1;
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Showfile screen
|
||||||
|
*
|
||||||
|
* Display the file selection to the user
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
void
|
||||||
|
ShowFiles (FILEENTRIES filelist[], int maxfiles, int offset, int selection)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
char text[MAXPATHLEN];
|
||||||
|
int ypos;
|
||||||
|
int w;
|
||||||
|
|
||||||
|
clearscreen ();
|
||||||
|
|
||||||
|
setfontsize (28);
|
||||||
|
DrawText (-1, 60, (char*)"Choose Game");
|
||||||
|
|
||||||
|
setfontsize(18);
|
||||||
|
|
||||||
|
ypos = (screenheight - ((PAGESIZE - 1) * 20)) >> 1;
|
||||||
|
|
||||||
|
if (screenheight == 480)
|
||||||
|
ypos += 24;
|
||||||
|
else
|
||||||
|
ypos += 10;
|
||||||
|
|
||||||
|
j = 0;
|
||||||
|
for (i = offset; i < (offset + PAGESIZE) && (i < maxfiles); i++)
|
||||||
|
{
|
||||||
|
if (filelist[i].flags) // if a dir
|
||||||
|
{
|
||||||
|
strcpy (text, "[");
|
||||||
|
strcat (text, filelist[i].displayname);
|
||||||
|
strcat (text, "]");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// hide file extension on listing (.7z, .fig, .smc)
|
||||||
|
StripExt(text, filelist[i].displayname);
|
||||||
|
}
|
||||||
|
if (j == (selection - offset))
|
||||||
|
{
|
||||||
|
/*** Highlighted text entry ***/
|
||||||
|
for ( w = 0; w < 20; w++ )
|
||||||
|
DrawLineFast( 30, 610, ( j * 20 ) + (ypos-16) + w, 0x80, 0x80, 0x80 );
|
||||||
|
|
||||||
|
setfontcolour (0x00, 0x00, 0xe0);
|
||||||
|
DrawText (50, (j * 20) + ypos, text);
|
||||||
|
setfontcolour (0x00, 0x00, 0x00);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*** Normal entry ***/
|
||||||
|
DrawText (50, (j * 20) + ypos, text);
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
showscreen ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Cheats screen
|
||||||
|
*
|
||||||
|
* Displays a scrollable list of cheats to the user
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
void
|
||||||
|
ShowCheats (char items[][50], char itemvalues[][50], int maxitems, int offset, int selection)
|
||||||
|
{
|
||||||
|
int i, j = 0;
|
||||||
|
int ypos;
|
||||||
|
int w;
|
||||||
|
|
||||||
|
clearscreen ();
|
||||||
|
|
||||||
|
setfontsize (28);
|
||||||
|
DrawText (-1, 60, (char*)"Cheats");
|
||||||
|
|
||||||
|
setfontsize(18);
|
||||||
|
|
||||||
|
ypos = (screenheight - ((PAGESIZE - 1) * 20)) >> 1;
|
||||||
|
|
||||||
|
if (screenheight == 480)
|
||||||
|
ypos += 24;
|
||||||
|
else
|
||||||
|
ypos += 10;
|
||||||
|
|
||||||
|
for (i = offset; i < (offset + PAGESIZE) && (i < maxitems); i++)
|
||||||
|
{
|
||||||
|
if (i == selection)
|
||||||
|
{
|
||||||
|
/*** Highlighted text entry ***/
|
||||||
|
for ( w = 0; w < 20; w++ )
|
||||||
|
DrawLineFast( 30, 610, ( j * 20 ) + (ypos-16) + w, 0x80, 0x80, 0x80 );
|
||||||
|
|
||||||
|
DrawText (150, (j * 20) + ypos, items[i]);
|
||||||
|
DrawText (400, (j * 20) + ypos, itemvalues[i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*** Normal entry ***/
|
||||||
|
DrawText (150, (j * 20) + ypos, items[i]);
|
||||||
|
DrawText (400, (j * 20) + ypos, itemvalues[i]);
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
showscreen ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* DrawLine
|
||||||
|
*
|
||||||
|
* Quick'n'Dirty Bresenham line drawing routine.
|
||||||
|
***************************************************************************/
|
||||||
|
#define SIGN(x) ((x<0)?-1:((x>0)?1:0))
|
||||||
|
|
||||||
|
void
|
||||||
|
DrawLine (int x1, int y1, int x2, int y2, u8 r, u8 g, u8 b)
|
||||||
|
{
|
||||||
|
u32 colour, pixel;
|
||||||
|
u32 colourhi, colourlo;
|
||||||
|
int i, dx, dy, sdx, sdy, dxabs, dyabs, x, y, px, py;
|
||||||
|
int sp;
|
||||||
|
|
||||||
|
colour = getcolour (r, g, b);
|
||||||
|
colourhi = colour & 0xffff0000;
|
||||||
|
colourlo = colour & 0xffff;
|
||||||
|
|
||||||
|
dx = x2 - x1; /*** Horizontal distance ***/
|
||||||
|
dy = y2 - y1; /*** Vertical distance ***/
|
||||||
|
|
||||||
|
dxabs = abs (dx);
|
||||||
|
dyabs = abs (dy);
|
||||||
|
sdx = SIGN (dx);
|
||||||
|
sdy = SIGN (dy);
|
||||||
|
x = dyabs >> 1;
|
||||||
|
y = dxabs >> 1;
|
||||||
|
px = x1;
|
||||||
|
py = y1;
|
||||||
|
|
||||||
|
sp = (py * 320) + (px >> 1);
|
||||||
|
pixel = xfb[whichfb][sp];
|
||||||
|
/*** Plot this pixel ***/
|
||||||
|
if (px & 1)
|
||||||
|
xfb[whichfb][sp] = (pixel & 0xffff0000) | colourlo;
|
||||||
|
else
|
||||||
|
xfb[whichfb][sp] = (pixel & 0xffff) | colourhi;
|
||||||
|
|
||||||
|
if (dxabs >= dyabs) /*** Mostly horizontal ***/
|
||||||
|
{
|
||||||
|
for (i = 0; i < dxabs; i++)
|
||||||
|
{
|
||||||
|
y += dyabs;
|
||||||
|
if (y >= dxabs)
|
||||||
|
{
|
||||||
|
y -= dxabs;
|
||||||
|
py += sdy;
|
||||||
|
}
|
||||||
|
|
||||||
|
px += sdx;
|
||||||
|
|
||||||
|
sp = (py * 320) + (px >> 1);
|
||||||
|
pixel = xfb[whichfb][sp];
|
||||||
|
|
||||||
|
if (px & 1)
|
||||||
|
xfb[whichfb][sp] = (pixel & 0xffff0000) | colourlo;
|
||||||
|
else
|
||||||
|
xfb[whichfb][sp] = (pixel & 0xffff) | colourhi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < dyabs; i++)
|
||||||
|
{
|
||||||
|
x += dxabs;
|
||||||
|
if (x >= dyabs)
|
||||||
|
{
|
||||||
|
x -= dyabs;
|
||||||
|
px += sdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
py += sdy;
|
||||||
|
|
||||||
|
sp = (py * 320) + (px >> 1);
|
||||||
|
pixel = xfb[whichfb][sp];
|
||||||
|
|
||||||
|
if (px & 1)
|
||||||
|
xfb[whichfb][sp] = (pixel & 0xffff0000) | colourlo;
|
||||||
|
else
|
||||||
|
xfb[whichfb][sp] = (pixel & 0xffff) | colourhi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Progress Bar
|
||||||
|
*
|
||||||
|
* Show the user what's happening
|
||||||
|
***************************************************************************/
|
||||||
|
void
|
||||||
|
ShowProgress (char *msg, int done, int total)
|
||||||
|
{
|
||||||
|
int ypos = (screenheight - 30) >> 1;
|
||||||
|
|
||||||
|
if (screenheight == 480)
|
||||||
|
ypos += 52;
|
||||||
|
else
|
||||||
|
ypos += 32;
|
||||||
|
|
||||||
|
int xpos;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
clearscreen ();
|
||||||
|
DrawText (-1, ypos, msg);
|
||||||
|
|
||||||
|
/*** Draw a white outline box ***/
|
||||||
|
for (i = 380; i < 401; i++)
|
||||||
|
DrawLine (100, i, 540, i, 0xff, 0xff, 0xff);
|
||||||
|
|
||||||
|
/*** Show progess ***/
|
||||||
|
xpos = (int) (((float) done / (float) total) * 438);
|
||||||
|
|
||||||
|
for (i = 381; i < 400; i++)
|
||||||
|
DrawLine (101, i, 101 + xpos, i, 0x00, 0x00, 0x80);
|
||||||
|
|
||||||
|
showscreen ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* DrawPolygon
|
||||||
|
***************************************************************************/
|
||||||
|
void
|
||||||
|
DrawPolygon (int vertices, int varray[], u8 r, u8 g, u8 b)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < vertices - 1; i++)
|
||||||
|
{
|
||||||
|
DrawLine (varray[(i << 1)], varray[(i << 1) + 1], varray[(i << 1) + 2],
|
||||||
|
varray[(i << 1) + 3], r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawLine (varray[0], varray[1], varray[(vertices << 1) - 2],
|
||||||
|
varray[(vertices << 1) - 1], r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Draw Line Fast
|
||||||
|
*
|
||||||
|
* This routine requires that start and endx are 32bit aligned.
|
||||||
|
* It tries to perform a semi-transparency over the existing image.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#define SRCWEIGHT 0.7f
|
||||||
|
#define DSTWEIGHT (1.0f - SRCWEIGHT)
|
||||||
|
|
||||||
|
static inline u8 c_adjust( u8 c , float weight )
|
||||||
|
{
|
||||||
|
return (u8)((float)c * weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawLineFast( int startx, int endx, int y, u8 r, u8 g, u8 b )
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
u32 offset;
|
||||||
|
int i;
|
||||||
|
u32 colour, clo, chi;
|
||||||
|
u32 lo,hi;
|
||||||
|
u8 *s, *d;
|
||||||
|
|
||||||
|
//colour = getcolour(r, g, b);
|
||||||
|
colour = ( r << 16 | g << 8 | b );
|
||||||
|
d = (u8 *)&colour;
|
||||||
|
d[1] = c_adjust(d[1], DSTWEIGHT);
|
||||||
|
d[2] = c_adjust(d[2], DSTWEIGHT);
|
||||||
|
d[3] = c_adjust(d[3], DSTWEIGHT);
|
||||||
|
|
||||||
|
width = ( endx - startx ) >> 1;
|
||||||
|
offset = ( y << 8 ) + ( y << 6 ) + ( startx >> 1 );
|
||||||
|
|
||||||
|
for ( i = 0; i < width; i++ )
|
||||||
|
{
|
||||||
|
lo = getrgb(xfb[whichfb][offset], 0);
|
||||||
|
hi = getrgb(xfb[whichfb][offset], 1);
|
||||||
|
|
||||||
|
s = (u8 *)&hi;
|
||||||
|
s[1] = ( ( c_adjust(s[1],SRCWEIGHT) ) + d[1] );
|
||||||
|
s[2] = ( ( c_adjust(s[2],SRCWEIGHT) ) + d[2] );
|
||||||
|
s[3] = ( ( c_adjust(s[3],SRCWEIGHT) ) + d[3] );
|
||||||
|
|
||||||
|
s = (u8 *)&lo;
|
||||||
|
s[1] = ( ( c_adjust(s[1],SRCWEIGHT) ) + d[1] );
|
||||||
|
s[2] = ( ( c_adjust(s[2],SRCWEIGHT) ) + d[2] );
|
||||||
|
s[3] = ( ( c_adjust(s[3],SRCWEIGHT) ) + d[3] );
|
||||||
|
|
||||||
|
clo = getcolour( s[1], s[2], s[3] );
|
||||||
|
s = (u8 *)&hi;
|
||||||
|
chi = getcolour( s[1], s[2], s[3] );
|
||||||
|
|
||||||
|
xfb[whichfb][offset++] = (chi & 0xffff0000 ) | ( clo & 0xffff) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Ok, I'm useless with Y1CBY2CR colour.
|
||||||
|
* So convert back to RGB so I can work with it -;)
|
||||||
|
***************************************************************************/
|
||||||
|
u32 getrgb( u32 ycbr, u32 low )
|
||||||
|
{
|
||||||
|
u8 r,g,b;
|
||||||
|
u32 y;
|
||||||
|
s8 cb,cr;
|
||||||
|
|
||||||
|
if ( low )
|
||||||
|
y = ( ycbr & 0xff00 ) >> 8;
|
||||||
|
else
|
||||||
|
y = ( ycbr & 0xff000000 ) >> 24;
|
||||||
|
|
||||||
|
cr = ycbr & 0xff;
|
||||||
|
cb = ( ycbr & 0xff0000 ) >> 16;
|
||||||
|
|
||||||
|
cr -= 128;
|
||||||
|
cb -= 128;
|
||||||
|
|
||||||
|
r = (u8)((float)y + 1.371 * (float)cr);
|
||||||
|
g = (u8)((float)y - 0.698 * (float)cr - 0.336 * (float)cb);
|
||||||
|
b = (u8)((float)y + 1.732 * (float)cb);
|
||||||
|
|
||||||
|
return (u32)( r << 16 | g << 8 | b );
|
||||||
|
|
||||||
|
}
|
46
source/ngc/menudraw.h
Normal file
46
source/ngc/menudraw.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* crunchy2 June 2007
|
||||||
|
* Tantric August 2008
|
||||||
|
*
|
||||||
|
* menudraw.h
|
||||||
|
*
|
||||||
|
* Menu drawing routines
|
||||||
|
*
|
||||||
|
* Uses libfreetype 2.2.1 compiled for GC with TTF support only.
|
||||||
|
* TTF only reduces the library by some 900k bytes!
|
||||||
|
*
|
||||||
|
* **WARNING***
|
||||||
|
*
|
||||||
|
* ONLY USE GUARANTEED PATENT FREE FONTS.
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef _NGCMENUDRAW_
|
||||||
|
#define _NGCMENUDRAW_
|
||||||
|
|
||||||
|
#include "filesel.h"
|
||||||
|
|
||||||
|
#define PAGESIZE 17 // max item listing on a screen
|
||||||
|
|
||||||
|
int FT_Init ();
|
||||||
|
void setfontsize (int pixelsize);
|
||||||
|
void setfontcolour (u8 r, u8 g, u8 b);
|
||||||
|
void DrawText (int x, int y, char *text);
|
||||||
|
void unpackbackdrop ();
|
||||||
|
void Credits ();
|
||||||
|
void RomInfo ();
|
||||||
|
void WaitButtonA ();
|
||||||
|
int RunMenu (char items[][50], int maxitems, char *title, int fontsize = 20, int x = -1);
|
||||||
|
void DrawMenu (char items[][50], char *title, int maxitems, int selected, int fontsize = 20, int x = -1);
|
||||||
|
void ShowCheats (char items[][50], char itemvalues[][50], int maxitems, int offset, int selection);
|
||||||
|
void ShowFiles (FILEENTRIES filelist[], int maxfiles, int offset, int selection);
|
||||||
|
|
||||||
|
void WaitPrompt (char *msg);
|
||||||
|
int WaitPromptChoice (char *msg, char* bmsg, char* amsg);
|
||||||
|
void ShowAction (char *msg);
|
||||||
|
void ShowProgress (char *msg, int done, int total);
|
||||||
|
void DrawPolygon (int vertices, int *varray, u8 r, u8 g, u8 b);
|
||||||
|
void DrawLineFast( int startx, int endx, int y, u8 r, u8 g, u8 b );
|
||||||
|
|
||||||
|
#endif
|
392
source/ngc/preferences.cpp
Normal file
392
source/ngc/preferences.cpp
Normal file
@ -0,0 +1,392 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* Tantric September 2008
|
||||||
|
*
|
||||||
|
* preferences.cpp
|
||||||
|
*
|
||||||
|
* Preferences save/load to XML file
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <mxml.h>
|
||||||
|
|
||||||
|
#include "vba.h"
|
||||||
|
#include "images/saveicon.h"
|
||||||
|
#include "menudraw.h"
|
||||||
|
#include "memcardop.h"
|
||||||
|
#include "fileop.h"
|
||||||
|
#include "smbop.h"
|
||||||
|
#include "filesel.h"
|
||||||
|
|
||||||
|
extern unsigned char savebuffer[];
|
||||||
|
extern int currconfig[4];
|
||||||
|
|
||||||
|
// button map configurations
|
||||||
|
extern unsigned int gcpadmap[];
|
||||||
|
extern unsigned int wmpadmap[];
|
||||||
|
extern unsigned int ccpadmap[];
|
||||||
|
extern unsigned int ncpadmap[];
|
||||||
|
|
||||||
|
#define PREFS_FILE_NAME "SNES9xGX.xml"
|
||||||
|
|
||||||
|
char prefscomment[2][32];
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Prepare Preferences Data
|
||||||
|
*
|
||||||
|
* This sets up the save buffer for saving.
|
||||||
|
***************************************************************************/
|
||||||
|
mxml_node_t *xml;
|
||||||
|
mxml_node_t *data;
|
||||||
|
mxml_node_t *section;
|
||||||
|
mxml_node_t *item;
|
||||||
|
mxml_node_t *elem;
|
||||||
|
|
||||||
|
char temp[200];
|
||||||
|
|
||||||
|
const char * toStr(int i)
|
||||||
|
{
|
||||||
|
sprintf(temp, "%d", i);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void createXMLSection(const char * name, const char * description)
|
||||||
|
{
|
||||||
|
section = mxmlNewElement(data, "section");
|
||||||
|
mxmlElementSetAttr(section, "name", name);
|
||||||
|
mxmlElementSetAttr(section, "description", description);
|
||||||
|
}
|
||||||
|
|
||||||
|
void createXMLSetting(const char * name, const char * description, const char * value)
|
||||||
|
{
|
||||||
|
item = mxmlNewElement(section, "setting");
|
||||||
|
mxmlElementSetAttr(item, "name", name);
|
||||||
|
mxmlElementSetAttr(item, "value", value);
|
||||||
|
mxmlElementSetAttr(item, "description", description);
|
||||||
|
}
|
||||||
|
|
||||||
|
void createXMLController(unsigned int controller[], const char * name, const char * description)
|
||||||
|
{
|
||||||
|
item = mxmlNewElement(section, "controller");
|
||||||
|
mxmlElementSetAttr(item, "name", name);
|
||||||
|
mxmlElementSetAttr(item, "description", description);
|
||||||
|
|
||||||
|
// create buttons
|
||||||
|
for(int i=0; i < 12; i++)
|
||||||
|
{
|
||||||
|
elem = mxmlNewElement(item, "button");
|
||||||
|
mxmlElementSetAttr(elem, "number", toStr(i));
|
||||||
|
mxmlElementSetAttr(elem, "assignment", toStr(controller[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * XMLSaveCallback(mxml_node_t *node, int where)
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
name = node->value.element.name;
|
||||||
|
|
||||||
|
if(where == MXML_WS_BEFORE_CLOSE)
|
||||||
|
{
|
||||||
|
if(!strcmp(name, "file") || !strcmp(name, "section"))
|
||||||
|
return ("\n");
|
||||||
|
else if(!strcmp(name, "controller"))
|
||||||
|
return ("\n\t");
|
||||||
|
}
|
||||||
|
if (where == MXML_WS_BEFORE_OPEN)
|
||||||
|
{
|
||||||
|
if(!strcmp(name, "file"))
|
||||||
|
return ("\n");
|
||||||
|
else if(!strcmp(name, "section"))
|
||||||
|
return ("\n\n");
|
||||||
|
else if(!strcmp(name, "setting") || !strcmp(name, "controller"))
|
||||||
|
return ("\n\t");
|
||||||
|
else if(!strcmp(name, "button"))
|
||||||
|
return ("\n\t\t");
|
||||||
|
}
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
preparePrefsData (int method)
|
||||||
|
{
|
||||||
|
int offset = 0;
|
||||||
|
memset (savebuffer, 0, SAVEBUFFERSIZE);
|
||||||
|
|
||||||
|
// add save icon and comments for Memory Card saves
|
||||||
|
if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB)
|
||||||
|
{
|
||||||
|
offset = sizeof (saveicon);
|
||||||
|
|
||||||
|
// Copy in save icon
|
||||||
|
memcpy (savebuffer, saveicon, offset);
|
||||||
|
|
||||||
|
// And the comments
|
||||||
|
sprintf (prefscomment[0], "%s Prefs", VERSIONSTR);
|
||||||
|
sprintf (prefscomment[1], "Preferences");
|
||||||
|
memcpy (savebuffer + offset, prefscomment, 64);
|
||||||
|
offset += 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
xml = mxmlNewXML("1.0");
|
||||||
|
mxmlSetWrapMargin(0); // disable line wrapping
|
||||||
|
|
||||||
|
data = mxmlNewElement(xml, "file");
|
||||||
|
mxmlElementSetAttr(data, "version",VERSIONSTR);
|
||||||
|
|
||||||
|
createXMLSection("File", "File Settings");
|
||||||
|
|
||||||
|
createXMLSetting("AutoLoad", "Auto Load", toStr(GCSettings.AutoLoad));
|
||||||
|
createXMLSetting("AutoSave", "Auto Save", toStr(GCSettings.AutoSave));
|
||||||
|
createXMLSetting("LoadMethod", "Load Method", toStr(GCSettings.LoadMethod));
|
||||||
|
createXMLSetting("SaveMethod", "Save Method", toStr(GCSettings.SaveMethod));
|
||||||
|
createXMLSetting("LoadFolder", "Load Folder", GCSettings.LoadFolder);
|
||||||
|
createXMLSetting("SaveFolder", "Save Folder", GCSettings.SaveFolder);
|
||||||
|
createXMLSetting("CheatFolder", "Cheats Folder", GCSettings.CheatFolder);
|
||||||
|
createXMLSetting("VerifySaves", "Verify Memory Card Saves", toStr(GCSettings.VerifySaves));
|
||||||
|
|
||||||
|
createXMLSection("Network", "Network Settings");
|
||||||
|
|
||||||
|
createXMLSetting("smbip", "Share Computer IP", GCSettings.smbip);
|
||||||
|
createXMLSetting("smbshare", "Share Name", GCSettings.smbshare);
|
||||||
|
createXMLSetting("smbuser", "Share Username", GCSettings.smbuser);
|
||||||
|
createXMLSetting("smbpwd", "Share Password", GCSettings.smbpwd);
|
||||||
|
|
||||||
|
createXMLSection("Emulation", "Emulation Settings");
|
||||||
|
|
||||||
|
createXMLSection("Controller", "Controller Settings");
|
||||||
|
|
||||||
|
createXMLController(gcpadmap, "gcpadmap", "GameCube Pad");
|
||||||
|
createXMLController(wmpadmap, "wmpadmap", "Wiimote");
|
||||||
|
createXMLController(ccpadmap, "ccpadmap", "Classic Controller");
|
||||||
|
createXMLController(ncpadmap, "ncpadmap", "Nunchuk");
|
||||||
|
|
||||||
|
int datasize = mxmlSaveString(xml, (char *)savebuffer, SAVEBUFFERSIZE, XMLSaveCallback);
|
||||||
|
|
||||||
|
mxmlDelete(xml);
|
||||||
|
|
||||||
|
return datasize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* loadXMLSetting
|
||||||
|
*
|
||||||
|
* Load XML elements into variables for an individual variable
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
void loadXMLSetting(char * var, const char * name)
|
||||||
|
{
|
||||||
|
item = mxmlFindElement(xml, xml, "setting", "name", name, MXML_DESCEND);
|
||||||
|
if(item)
|
||||||
|
sprintf(var, "%s", mxmlElementGetAttr(item, "value"));
|
||||||
|
}
|
||||||
|
void loadXMLSetting(int * var, const char * name)
|
||||||
|
{
|
||||||
|
item = mxmlFindElement(xml, xml, "setting", "name", name, MXML_DESCEND);
|
||||||
|
if(item)
|
||||||
|
*var = atoi(mxmlElementGetAttr(item, "value"));
|
||||||
|
}
|
||||||
|
void loadXMLSetting(bool * var, const char * name)
|
||||||
|
{
|
||||||
|
item = mxmlFindElement(xml, xml, "setting", "name", name, MXML_DESCEND);
|
||||||
|
if(item)
|
||||||
|
*var = atoi(mxmlElementGetAttr(item, "value"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* loadXMLController
|
||||||
|
*
|
||||||
|
* Load XML elements into variables for a controller mapping
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
void loadXMLController(unsigned int controller[], const char * name)
|
||||||
|
{
|
||||||
|
item = mxmlFindElement(xml, xml, "controller", "name", name, MXML_DESCEND);
|
||||||
|
|
||||||
|
if(item)
|
||||||
|
{
|
||||||
|
// populate buttons
|
||||||
|
for(int i=0; i < 12; i++)
|
||||||
|
{
|
||||||
|
elem = mxmlFindElement(item, xml, "button", "number", toStr(i), MXML_DESCEND);
|
||||||
|
if(elem)
|
||||||
|
controller[i] = atoi(mxmlElementGetAttr(elem, "assignment"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* decodePrefsData
|
||||||
|
*
|
||||||
|
* Decodes preferences - parses XML and loads preferences into the variables
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
bool
|
||||||
|
decodePrefsData (int method)
|
||||||
|
{
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
// skip save icon and comments for Memory Card saves
|
||||||
|
if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB)
|
||||||
|
{
|
||||||
|
offset = sizeof (saveicon);
|
||||||
|
offset += 64; // sizeof prefscomment
|
||||||
|
}
|
||||||
|
|
||||||
|
xml = mxmlLoadString(NULL, (char *)savebuffer+offset, MXML_TEXT_CALLBACK);
|
||||||
|
|
||||||
|
// check settings version
|
||||||
|
// we don't do anything with the version #, but we'll store it anyway
|
||||||
|
char * version;
|
||||||
|
item = mxmlFindElement(xml, xml, "file", "version", NULL, MXML_DESCEND);
|
||||||
|
if(item) // a version entry exists
|
||||||
|
version = (char *)mxmlElementGetAttr(item, "version");
|
||||||
|
else // version # not found, must be invalid
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// File Settings
|
||||||
|
|
||||||
|
loadXMLSetting(&GCSettings.AutoLoad, "AutoLoad");
|
||||||
|
loadXMLSetting(&GCSettings.AutoSave, "AutoSave");
|
||||||
|
loadXMLSetting(&GCSettings.LoadMethod, "LoadMethod");
|
||||||
|
loadXMLSetting(&GCSettings.SaveMethod, "SaveMethod");
|
||||||
|
loadXMLSetting(GCSettings.LoadFolder, "LoadFolder");
|
||||||
|
loadXMLSetting(GCSettings.SaveFolder, "SaveFolder");
|
||||||
|
loadXMLSetting(GCSettings.CheatFolder, "CheatFolder");
|
||||||
|
loadXMLSetting(&GCSettings.VerifySaves, "VerifySaves");
|
||||||
|
|
||||||
|
// Network Settings
|
||||||
|
|
||||||
|
loadXMLSetting(GCSettings.smbip, "smbip");
|
||||||
|
loadXMLSetting(GCSettings.smbshare, "smbshare");
|
||||||
|
loadXMLSetting(GCSettings.smbuser, "smbuser");
|
||||||
|
loadXMLSetting(GCSettings.smbpwd, "smbpwd");
|
||||||
|
|
||||||
|
// Emulation Settings
|
||||||
|
|
||||||
|
// Controller Settings
|
||||||
|
|
||||||
|
loadXMLController(gcpadmap, "gcpadmap");
|
||||||
|
loadXMLController(wmpadmap, "wmpadmap");
|
||||||
|
loadXMLController(ccpadmap, "ccpadmap");
|
||||||
|
loadXMLController(ncpadmap, "ncpadmap");
|
||||||
|
|
||||||
|
mxmlDelete(xml);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Save Preferences
|
||||||
|
***************************************************************************/
|
||||||
|
bool
|
||||||
|
SavePrefs (int method, bool silent)
|
||||||
|
{
|
||||||
|
if(method == METHOD_AUTO)
|
||||||
|
method = autoSaveMethod();
|
||||||
|
|
||||||
|
char filepath[1024];
|
||||||
|
int datasize;
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
datasize = preparePrefsData (method);
|
||||||
|
|
||||||
|
if (!silent)
|
||||||
|
ShowAction ((char*) "Saving preferences...");
|
||||||
|
|
||||||
|
if(method == METHOD_SD || method == METHOD_USB)
|
||||||
|
{
|
||||||
|
if(ChangeFATInterface(method, NOTSILENT))
|
||||||
|
{
|
||||||
|
sprintf (filepath, "%s/%s/%s", ROOTFATDIR, GCSettings.SaveFolder, PREFS_FILE_NAME);
|
||||||
|
offset = SaveBufferToFAT (filepath, datasize, silent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(method == METHOD_SMB)
|
||||||
|
{
|
||||||
|
sprintf (filepath, "%s/%s", GCSettings.SaveFolder, PREFS_FILE_NAME);
|
||||||
|
offset = SaveBufferToSMB (filepath, datasize, silent);
|
||||||
|
}
|
||||||
|
else if(method == METHOD_MC_SLOTA)
|
||||||
|
{
|
||||||
|
offset = SaveBufferToMC (savebuffer, CARD_SLOTA, (char *)PREFS_FILE_NAME, datasize, silent);
|
||||||
|
}
|
||||||
|
else if(method == METHOD_MC_SLOTB)
|
||||||
|
{
|
||||||
|
offset = SaveBufferToMC (savebuffer, CARD_SLOTB, (char *)PREFS_FILE_NAME, datasize, silent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset > 0)
|
||||||
|
{
|
||||||
|
if (!silent)
|
||||||
|
WaitPrompt ((char *)"Preferences saved");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Load Preferences from specified method
|
||||||
|
***************************************************************************/
|
||||||
|
bool
|
||||||
|
LoadPrefsFromMethod (int method)
|
||||||
|
{
|
||||||
|
bool retval = false;
|
||||||
|
char filepath[1024];
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
if(method == METHOD_SD || method == METHOD_USB)
|
||||||
|
{
|
||||||
|
if(ChangeFATInterface(method, NOTSILENT))
|
||||||
|
{
|
||||||
|
sprintf (filepath, "%s/%s/%s", ROOTFATDIR, GCSettings.SaveFolder, PREFS_FILE_NAME);
|
||||||
|
offset = LoadBufferFromFAT (filepath, SILENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(method == METHOD_SMB)
|
||||||
|
{
|
||||||
|
sprintf (filepath, "%s/%s", GCSettings.SaveFolder, PREFS_FILE_NAME);
|
||||||
|
offset = LoadBufferFromSMB (filepath, SILENT);
|
||||||
|
}
|
||||||
|
else if(method == METHOD_MC_SLOTA)
|
||||||
|
{
|
||||||
|
offset = LoadBufferFromMC (savebuffer, CARD_SLOTA, (char *)PREFS_FILE_NAME, SILENT);
|
||||||
|
}
|
||||||
|
else if(method == METHOD_MC_SLOTB)
|
||||||
|
{
|
||||||
|
offset = LoadBufferFromMC (savebuffer, CARD_SLOTB, (char *)PREFS_FILE_NAME, SILENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset > 0)
|
||||||
|
retval = decodePrefsData (method);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Load Preferences
|
||||||
|
* Checks sources consecutively until we find a preference file
|
||||||
|
***************************************************************************/
|
||||||
|
bool LoadPrefs()
|
||||||
|
{
|
||||||
|
ShowAction ((char*) "Loading preferences...");
|
||||||
|
bool prefFound = false;
|
||||||
|
if(ChangeFATInterface(METHOD_SD, SILENT))
|
||||||
|
prefFound = LoadPrefsFromMethod(METHOD_SD);
|
||||||
|
if(!prefFound && ChangeFATInterface(METHOD_USB, SILENT))
|
||||||
|
prefFound = LoadPrefsFromMethod(METHOD_USB);
|
||||||
|
if(!prefFound && TestCard(CARD_SLOTA, SILENT))
|
||||||
|
prefFound = LoadPrefsFromMethod(METHOD_MC_SLOTA);
|
||||||
|
if(!prefFound && TestCard(CARD_SLOTB, SILENT))
|
||||||
|
prefFound = LoadPrefsFromMethod(METHOD_MC_SLOTB);
|
||||||
|
if(!prefFound && ConnectShare (SILENT))
|
||||||
|
prefFound = LoadPrefsFromMethod(METHOD_SMB);
|
||||||
|
|
||||||
|
return prefFound;
|
||||||
|
}
|
12
source/ngc/preferences.h
Normal file
12
source/ngc/preferences.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* Tantric September 2008
|
||||||
|
*
|
||||||
|
* preferences.h
|
||||||
|
*
|
||||||
|
* Preferences save/load to XML file
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
bool SavePrefs (int method, bool silent);
|
||||||
|
bool LoadPrefs ();
|
339
source/ngc/smbop.cpp
Normal file
339
source/ngc/smbop.cpp
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* crunchy2 May 2007
|
||||||
|
* Tantric August 2008
|
||||||
|
*
|
||||||
|
* smbload.cpp
|
||||||
|
*
|
||||||
|
* SMB support routines
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <network.h>
|
||||||
|
#include <smb.h>
|
||||||
|
#include <zlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "vba.h"
|
||||||
|
#include "smbop.h"
|
||||||
|
#include "gcunzip.h"
|
||||||
|
#include "video.h"
|
||||||
|
#include "menudraw.h"
|
||||||
|
#include "filesel.h"
|
||||||
|
|
||||||
|
bool networkInit = false;
|
||||||
|
bool networkShareInit = false;
|
||||||
|
unsigned int SMBTimer = 0;
|
||||||
|
#define SMBTIMEOUT ( 3600 ) // Some implementations timeout in 10 minutes
|
||||||
|
|
||||||
|
SMBCONN smbconn;
|
||||||
|
#define ZIPCHUNK 16384
|
||||||
|
|
||||||
|
extern unsigned char savebuffer[];
|
||||||
|
extern char output[16384];
|
||||||
|
extern int offset;
|
||||||
|
extern int selection;
|
||||||
|
extern char currentdir[MAXPATHLEN];
|
||||||
|
extern FILEENTRIES filelist[MAXFILES];
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* InitializeNetwork
|
||||||
|
* Initializes the Wii/GameCube network interface
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
bool InitializeNetwork(bool silent)
|
||||||
|
{
|
||||||
|
ShowAction ((char*) "Initializing network...");
|
||||||
|
s32 result;
|
||||||
|
|
||||||
|
while ((result = net_init()) == -EAGAIN);
|
||||||
|
|
||||||
|
if (result >= 0)
|
||||||
|
{
|
||||||
|
char myIP[16];
|
||||||
|
|
||||||
|
if (if_config(myIP, NULL, NULL, true) < 0)
|
||||||
|
{
|
||||||
|
if(!silent)
|
||||||
|
WaitPrompt((char*) "Error reading IP address.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!silent)
|
||||||
|
WaitPrompt((char*) "Unable to initialize network.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Mount SMB Share
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
bool
|
||||||
|
ConnectShare (bool silent)
|
||||||
|
{
|
||||||
|
// Crashes or stalls system in GameCube mode - so disable
|
||||||
|
#ifndef HW_RVL
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// check that all parameter have been set
|
||||||
|
if(strlen(GCSettings.smbuser) == 0 ||
|
||||||
|
strlen(GCSettings.smbpwd) == 0 ||
|
||||||
|
strlen(GCSettings.smbshare) == 0 ||
|
||||||
|
strlen(GCSettings.smbip) == 0)
|
||||||
|
{
|
||||||
|
if(!silent)
|
||||||
|
WaitPrompt((char*) "Invalid network settings. Check SNES9xGX.xml.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!networkInit)
|
||||||
|
networkInit = InitializeNetwork(silent);
|
||||||
|
|
||||||
|
if(networkInit)
|
||||||
|
{
|
||||||
|
// connection may have expired
|
||||||
|
if (networkShareInit && SMBTimer > SMBTIMEOUT)
|
||||||
|
{
|
||||||
|
networkShareInit = false;
|
||||||
|
SMBTimer = 0;
|
||||||
|
SMB_Close(smbconn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!networkShareInit)
|
||||||
|
{
|
||||||
|
if(!silent)
|
||||||
|
ShowAction ((char*) "Connecting to network share...");
|
||||||
|
|
||||||
|
if(SMB_Connect(&smbconn, GCSettings.smbuser, GCSettings.smbpwd,
|
||||||
|
GCSettings.smbgcid, GCSettings.smbsvid, GCSettings.smbshare, GCSettings.smbip) == SMB_SUCCESS)
|
||||||
|
networkShareInit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!networkShareInit && !silent)
|
||||||
|
WaitPrompt ((char*) "Failed to connect to network share.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return networkShareInit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* SMBPath
|
||||||
|
*
|
||||||
|
* Returns a SMB-style path
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
char * SMBPath(char * path)
|
||||||
|
{
|
||||||
|
// fix path - replace all '/' with '\'
|
||||||
|
for(uint i=0; i < strlen(path); i++)
|
||||||
|
if(path[i] == '/')
|
||||||
|
path[i] = '\\';
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* parseSMBDirectory
|
||||||
|
*
|
||||||
|
* Load the directory and put in the filelist array
|
||||||
|
*****************************************************************************/
|
||||||
|
int
|
||||||
|
ParseSMBdirectory ()
|
||||||
|
{
|
||||||
|
if(!ConnectShare (NOTSILENT))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int filecount = 0;
|
||||||
|
char searchpath[1024];
|
||||||
|
SMBDIRENTRY smbdir;
|
||||||
|
|
||||||
|
// initialize selection
|
||||||
|
selection = offset = 0;
|
||||||
|
|
||||||
|
// Clear any existing values
|
||||||
|
memset (&filelist, 0, sizeof (FILEENTRIES) * MAXFILES);
|
||||||
|
|
||||||
|
if(strlen(currentdir) <= 1) // root
|
||||||
|
sprintf(searchpath, "*");
|
||||||
|
else
|
||||||
|
sprintf(searchpath, "%s/*", currentdir);
|
||||||
|
|
||||||
|
if (SMB_FindFirst
|
||||||
|
(SMBPath(searchpath), SMB_SRCH_READONLY | SMB_SRCH_DIRECTORY, &smbdir, smbconn) != SMB_SUCCESS)
|
||||||
|
{
|
||||||
|
char msg[200];
|
||||||
|
sprintf(msg, "Could not open %s", currentdir);
|
||||||
|
WaitPrompt (msg);
|
||||||
|
|
||||||
|
// if we can't open the dir, open root dir
|
||||||
|
sprintf(searchpath, "/");
|
||||||
|
sprintf(searchpath,"*");
|
||||||
|
|
||||||
|
if (SMB_FindFirst
|
||||||
|
(SMBPath(searchpath), SMB_SRCH_READONLY | SMB_SRCH_DIRECTORY, &smbdir, smbconn) != SMB_SUCCESS)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// index files/folders
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(strcmp(smbdir.name,".") != 0 &&
|
||||||
|
!(strlen(currentdir) <= 1 && strcmp(smbdir.name,"..") == 0))
|
||||||
|
{
|
||||||
|
memset (&filelist[filecount], 0, sizeof (FILEENTRIES));
|
||||||
|
filelist[filecount].length = smbdir.size_low;
|
||||||
|
smbdir.name[MAXJOLIET] = 0;
|
||||||
|
|
||||||
|
if(smbdir.attributes == SMB_SRCH_DIRECTORY)
|
||||||
|
filelist[filecount].flags = 1; // flag this as a dir
|
||||||
|
else
|
||||||
|
filelist[filecount].flags = 0;
|
||||||
|
|
||||||
|
// Update display name
|
||||||
|
memcpy (&filelist[filecount].displayname, smbdir.name, MAXDISPLAY);
|
||||||
|
filelist[filecount].displayname[MAXDISPLAY] = 0;
|
||||||
|
|
||||||
|
strcpy (filelist[filecount].filename, smbdir.name);
|
||||||
|
filecount++;
|
||||||
|
}
|
||||||
|
} while (SMB_FindNext (&smbdir, smbconn) == SMB_SUCCESS);
|
||||||
|
|
||||||
|
// close directory
|
||||||
|
SMB_FindClose (smbconn);
|
||||||
|
|
||||||
|
// Sort the file list
|
||||||
|
qsort(filelist, filecount, sizeof(FILEENTRIES), FileSortCallback);
|
||||||
|
|
||||||
|
return filecount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Load SMB file
|
||||||
|
****************************************************************************/
|
||||||
|
int
|
||||||
|
LoadSMBFile (char *filename, int length)
|
||||||
|
{
|
||||||
|
char filepath[MAXPATHLEN];
|
||||||
|
|
||||||
|
/* Check filename length */
|
||||||
|
if ((strlen(currentdir)+1+strlen(filelist[selection].filename)) < MAXPATHLEN)
|
||||||
|
sprintf(filepath, "%s/%s",currentdir,filelist[selection].filename);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WaitPrompt((char*) "Maximum filepath length reached!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
//return LoadBufferFromSMB((char *)Memory.ROM, SMBPath(filepath), NOTSILENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Write savebuffer to SMB file
|
||||||
|
****************************************************************************/
|
||||||
|
int
|
||||||
|
SaveBufferToSMB (char *filepath, int datasize, bool silent)
|
||||||
|
{
|
||||||
|
if(!ConnectShare (NOTSILENT))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
SMBFILE smbfile;
|
||||||
|
int dsize = datasize;
|
||||||
|
int wrote = 0;
|
||||||
|
int boffset = 0;
|
||||||
|
|
||||||
|
smbfile =
|
||||||
|
SMB_OpenFile (SMBPath(filepath), SMB_OPEN_WRITING | SMB_DENY_NONE,
|
||||||
|
SMB_OF_CREATE | SMB_OF_TRUNCATE, smbconn);
|
||||||
|
|
||||||
|
if (smbfile)
|
||||||
|
{
|
||||||
|
while (dsize > 0)
|
||||||
|
{
|
||||||
|
if (dsize > 1024)
|
||||||
|
wrote =
|
||||||
|
SMB_WriteFile ((char *) savebuffer + boffset, 1024, boffset, smbfile);
|
||||||
|
else
|
||||||
|
wrote =
|
||||||
|
SMB_WriteFile ((char *) savebuffer + boffset, dsize, boffset, smbfile);
|
||||||
|
|
||||||
|
boffset += wrote;
|
||||||
|
dsize -= wrote;
|
||||||
|
}
|
||||||
|
SMB_CloseFile (smbfile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char msg[100];
|
||||||
|
sprintf(msg, "Couldn't save SMB: %s", SMBPath(filepath));
|
||||||
|
WaitPrompt (msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearSaveBuffer ();
|
||||||
|
return boffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Load up a buffer from SMB file
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
// no buffer is specified - so use savebuffer
|
||||||
|
int
|
||||||
|
LoadBufferFromSMB (char *filepath, bool silent)
|
||||||
|
{
|
||||||
|
ClearSaveBuffer ();
|
||||||
|
return LoadBufferFromSMB((char *)savebuffer, filepath, silent);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
LoadBufferFromSMB (char * sbuffer, char *filepath, bool silent)
|
||||||
|
{
|
||||||
|
if(!ConnectShare (NOTSILENT))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
SMBFILE smbfile;
|
||||||
|
int ret;
|
||||||
|
int boffset = 0;
|
||||||
|
|
||||||
|
smbfile =
|
||||||
|
SMB_OpenFile (SMBPath(filepath), SMB_OPEN_READING, SMB_OF_OPEN, smbconn);
|
||||||
|
|
||||||
|
if (!smbfile)
|
||||||
|
{
|
||||||
|
if(!silent)
|
||||||
|
{
|
||||||
|
char msg[100];
|
||||||
|
sprintf(msg, "Couldn't open SMB: %s", SMBPath(filepath));
|
||||||
|
WaitPrompt (msg);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = SMB_ReadFile (sbuffer, 1024, boffset, smbfile);
|
||||||
|
|
||||||
|
if (IsZipFile (sbuffer))
|
||||||
|
{
|
||||||
|
boffset = UnZipFile ((unsigned char *)sbuffer, smbfile); // unzip from SMB
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Just load the file up
|
||||||
|
while ((ret = SMB_ReadFile (sbuffer + boffset, 1024, boffset, smbfile)) > 0)
|
||||||
|
boffset += ret;
|
||||||
|
}
|
||||||
|
SMB_CloseFile (smbfile);
|
||||||
|
|
||||||
|
return boffset;
|
||||||
|
}
|
27
source/ngc/smbop.h
Normal file
27
source/ngc/smbop.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* crunchy2 May 2007
|
||||||
|
* Tantric August 2008
|
||||||
|
*
|
||||||
|
* smbload.h
|
||||||
|
*
|
||||||
|
* SMB support routines
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _NGCSMB_
|
||||||
|
|
||||||
|
#define _NGCSMB_
|
||||||
|
|
||||||
|
bool InitializeNetwork(bool silent);
|
||||||
|
bool ConnectShare (bool silent);
|
||||||
|
char * SMBPath(char * path);
|
||||||
|
int UpdateSMBdirname();
|
||||||
|
int ParseSMBdirectory ();
|
||||||
|
int LoadSMBFile (char *filename, int length);
|
||||||
|
int LoadBufferFromSMB (char *filepath, bool silent);
|
||||||
|
int LoadBufferFromSMB (char * sbuffer, char *filepath, bool silent);
|
||||||
|
int SaveBufferToSMB (char *filepath, int datasize, bool silent);
|
||||||
|
|
||||||
|
#endif
|
@ -3,10 +3,9 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#ifndef __TMBINCTIMER__
|
#ifndef __TMBINCTIMER__
|
||||||
#define __TMBINCTIMER__
|
#define __TMBINCTIMER__
|
||||||
#ifdef WII_BUILD
|
#ifdef HW_RVL
|
||||||
#define TB_CLOCK 60750000 //WII
|
#define TB_CLOCK 60750000 //WII
|
||||||
#endif
|
#else
|
||||||
#ifdef GC_BUILD
|
|
||||||
#define TB_CLOCK 40500000
|
#define TB_CLOCK 40500000
|
||||||
#endif
|
#endif
|
||||||
#define mftb(rval) ({unsigned long u; do { \
|
#define mftb(rval) ({unsigned long u; do { \
|
||||||
|
107
source/ngc/vba.cpp
Normal file
107
source/ngc/vba.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* VisualBoyAdvance 1.7.2
|
||||||
|
* Nintendo GameCube Wrapper
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <wiiuse/wpad.h>
|
||||||
|
#include <sdcard/card_cmn.h>
|
||||||
|
#include <sdcard/wiisd_io.h>
|
||||||
|
#include <sdcard/card_io.h>
|
||||||
|
#include <fat.h>
|
||||||
|
|
||||||
|
#ifdef WII_DVD
|
||||||
|
extern "C" {
|
||||||
|
#include <di/di.h>
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "vbasupport.h"
|
||||||
|
#include "audio.h"
|
||||||
|
#include "dvd.h"
|
||||||
|
#include "smbop.h"
|
||||||
|
#include "menu.h"
|
||||||
|
#include "menudraw.h"
|
||||||
|
#include "input.h"
|
||||||
|
#include "video.h"
|
||||||
|
#include "vbaconfig.h"
|
||||||
|
|
||||||
|
extern int ROMSize;
|
||||||
|
extern int emulating;
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* main
|
||||||
|
*
|
||||||
|
* Program entry
|
||||||
|
****************************************************************************/
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
#ifdef WII_DVD
|
||||||
|
DI_Init(); // first
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int selectedMenu = -1;
|
||||||
|
|
||||||
|
PAD_Init (); /*** Initialise pads for input ***/
|
||||||
|
#ifdef HW_RVL
|
||||||
|
WPAD_Init();
|
||||||
|
// read wiimote accelerometer and IR data
|
||||||
|
WPAD_SetDataFormat(WPAD_CHAN_ALL,WPAD_FMT_BTNS_ACC_IR);
|
||||||
|
WPAD_SetVRes(WPAD_CHAN_ALL,640,480);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
InitialiseVideo();
|
||||||
|
|
||||||
|
// Initialise freetype font system
|
||||||
|
if (FT_Init ())
|
||||||
|
{
|
||||||
|
printf ("Cannot initialise font subsystem!\n");
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize libFAT for SD and USB
|
||||||
|
fatInitDefault();
|
||||||
|
|
||||||
|
// Initialize DVD subsystem (GameCube only)
|
||||||
|
#ifndef HW_RVL
|
||||||
|
DVD_Init ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Check if DVD drive belongs to a Wii
|
||||||
|
SetDVDDriveType();
|
||||||
|
|
||||||
|
InitialiseSound();
|
||||||
|
|
||||||
|
InitialisePalette();
|
||||||
|
|
||||||
|
// Set defaults
|
||||||
|
DefaultSettings ();
|
||||||
|
|
||||||
|
while (ROMSize == 0)
|
||||||
|
{
|
||||||
|
mainmenu (selectedMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Main loop
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
while (emulating)
|
||||||
|
{
|
||||||
|
emulator.emuMain(emulator.emuCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Never leaving here
|
||||||
|
while(1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
56
source/ngc/vba.h
Normal file
56
source/ngc/vba.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* crunchy2 May 2007-July 2007
|
||||||
|
* Tantric September 2008
|
||||||
|
*
|
||||||
|
* snes9xGX.h
|
||||||
|
*
|
||||||
|
* This file controls overall program flow. Most things start and end here!
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _VBA_H_
|
||||||
|
#define _VBA_H_
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
|
||||||
|
#define VERSIONNUM "1.0.0"
|
||||||
|
#define VERSIONSTR "VBA 1.0.0"
|
||||||
|
|
||||||
|
#define NOTSILENT 0
|
||||||
|
#define SILENT 1
|
||||||
|
|
||||||
|
enum {
|
||||||
|
METHOD_AUTO,
|
||||||
|
METHOD_SD,
|
||||||
|
METHOD_USB,
|
||||||
|
METHOD_DVD,
|
||||||
|
METHOD_SMB,
|
||||||
|
METHOD_MC_SLOTA,
|
||||||
|
METHOD_MC_SLOTB
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SGCSettings{
|
||||||
|
int AutoLoad;
|
||||||
|
int AutoSave;
|
||||||
|
int LoadMethod; // For ROMS: Auto, SD, DVD, USB, Network (SMB)
|
||||||
|
int SaveMethod; // For SRAM, Freeze, Prefs: Auto, SD, Memory Card Slot A, Memory Card Slot B, USB, SMB
|
||||||
|
char LoadFolder[200]; // Path to game files
|
||||||
|
char SaveFolder[200]; // Path to save files
|
||||||
|
char CheatFolder[200]; // Path to cheat files
|
||||||
|
char gcip[16];
|
||||||
|
char gwip[16];
|
||||||
|
char mask[16];
|
||||||
|
char smbip[16];
|
||||||
|
char smbuser[20];
|
||||||
|
char smbpwd[20];
|
||||||
|
char smbgcid[20];
|
||||||
|
char smbsvid[20];
|
||||||
|
char smbshare[20];
|
||||||
|
int VerifySaves;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct SGCSettings GCSettings;
|
||||||
|
|
||||||
|
#endif
|
@ -1,837 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* VisualBoyAdvance 1.7.2
|
|
||||||
* Nintendo GameCube Wrapper
|
|
||||||
****************************************************************************/
|
|
||||||
#include <gccore.h>
|
|
||||||
#include <ogcsys.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#ifdef WII_BUILD
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#include <ogc/conf.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <wiiuse/wpad.h>
|
|
||||||
extern s32 CONF_Init(void);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern int isClassicAvailable;
|
|
||||||
extern int isWiimoteAvailable;
|
|
||||||
|
|
||||||
void setup_controllers()
|
|
||||||
{ /* Doesn't work, either always returns
|
|
||||||
WiimoteAvailable only or apparently switches
|
|
||||||
REALLY fast between the two. WTF.
|
|
||||||
|
|
||||||
WPAD_ScanPads();
|
|
||||||
WPADData pad;
|
|
||||||
WPAD_ReadEvent(0, &pad);
|
|
||||||
// User can use just wiimote
|
|
||||||
if(pad.exp.type == WPAD_EXP_NONE)
|
|
||||||
{
|
|
||||||
isClassicAvailable = 0;
|
|
||||||
isWiimoteAvailable = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// User can use a Classic controller
|
|
||||||
else if(pad.exp.type == WPAD_EXP_CLASSIC)
|
|
||||||
{
|
|
||||||
isClassicAvailable = 1;
|
|
||||||
WPAD_SetDataFormat(0, WPAD_FMT_BTNS);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// User will have to use a GC controller
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isClassicAvailable = 0;
|
|
||||||
isWiimoteAvailable = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
isClassicAvailable = 1;
|
|
||||||
isWiimoteAvailable = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "mixer.h"
|
|
||||||
#include "gcpad.h"
|
|
||||||
#include "vmmem.h"
|
|
||||||
#include "pal60.h"
|
|
||||||
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#include "gx_supp.h"
|
|
||||||
#include "tbtime.h"
|
|
||||||
#include "sdfileio.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
/** VBA **/
|
|
||||||
#include "GBA.h"
|
|
||||||
#include "agbprint.h"
|
|
||||||
#include "Flash.h"
|
|
||||||
#include "Port.h"
|
|
||||||
#include "RTC.h"
|
|
||||||
#include "Sound.h"
|
|
||||||
#include "Text.h"
|
|
||||||
#include "unzip.h"
|
|
||||||
#include "Util.h"
|
|
||||||
#include "gb/GB.h"
|
|
||||||
#include "gb/gbGlobals.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Globals
|
|
||||||
*/
|
|
||||||
int RGB_LOW_BITS_MASK=0x821;
|
|
||||||
int systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
|
||||||
u16 systemGbPalette[24];
|
|
||||||
int systemDebug = 0;
|
|
||||||
int emulating = 0;
|
|
||||||
int systemFrameSkip = 0;
|
|
||||||
int systemRedShift = 0;
|
|
||||||
int systemBlueShift = 0;
|
|
||||||
int systemGreenShift = 0;
|
|
||||||
int systemColorDepth = 0;
|
|
||||||
int sensorX = 2047;
|
|
||||||
int sensorY = 2047;
|
|
||||||
u16 systemColorMap16[0x10000];
|
|
||||||
//u32 systemColorMap32[0x10000];
|
|
||||||
u32 *systemColorMap32 = (u32 *)&systemColorMap16;
|
|
||||||
bool systemSoundOn = false;
|
|
||||||
int systemVerbose = 0;
|
|
||||||
int cartridgeType = 0;
|
|
||||||
int srcWidth = 0;
|
|
||||||
int srcHeight = 0;
|
|
||||||
int destWidth = 0;
|
|
||||||
int destHeight = 0;
|
|
||||||
int srcPitch = 0;
|
|
||||||
int saveExists = 0;
|
|
||||||
extern int menuCalled;
|
|
||||||
#define WITHGX 1
|
|
||||||
#define DEBUGON 0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if DEBUGON
|
|
||||||
const char *dbg_local_ip = "192.168.1.32";
|
|
||||||
const char *dbg_netmask = "255.255.255.0";
|
|
||||||
const char *dbg_gw = "192.168.1.100";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*** 2D Video Globals ***/
|
|
||||||
GXRModeObj *vmode; /*** Graphics Mode Object ***/
|
|
||||||
u32 *xfb[2] = { NULL, NULL }; /*** Framebuffers ***/
|
|
||||||
int whichfb = 0; /*** Frame buffer toggle ***/
|
|
||||||
|
|
||||||
void debuggerOutput(char *, u32)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void (*dbgOutput)(char *, u32) = debuggerOutput;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Locals
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern char *MENU_GetLoadFile( char *whichdir );
|
|
||||||
extern void MENU_DrawString( int x, int y, char *msg, int style );
|
|
||||||
|
|
||||||
struct EmulatedSystem emulator =
|
|
||||||
{
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
false,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
static tb_t start, now;
|
|
||||||
static u8 soundbuffer[3200] ATTRIBUTE_ALIGN(32);
|
|
||||||
|
|
||||||
u32 loadtimeradjust;
|
|
||||||
|
|
||||||
void doScan(u32 blah)
|
|
||||||
{
|
|
||||||
PAD_ScanPads();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int throttle = 100;
|
|
||||||
u32 throttleLastTime = 0;
|
|
||||||
|
|
||||||
char filename[1024]; //rom file name
|
|
||||||
char batfilename[1024]; //battery save file name
|
|
||||||
char statename[1024]; //savestate file name
|
|
||||||
/****************************************************************************
|
|
||||||
* Initialise Video
|
|
||||||
*
|
|
||||||
* Before doing anything in libogc, it's recommended to configure a video
|
|
||||||
* output.
|
|
||||||
****************************************************************************/
|
|
||||||
static void
|
|
||||||
Initialise (void)
|
|
||||||
{
|
|
||||||
VIDEO_Init (); /*** ALWAYS CALL FIRST IN ANY LIBOGC PROJECT!
|
|
||||||
Not only does it initialise the video
|
|
||||||
subsystem, but also sets up the ogc os
|
|
||||||
***/
|
|
||||||
#if DEBUGON
|
|
||||||
DEBUG_Init(2424);
|
|
||||||
_break();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PAD_Init (); /*** Initialise pads for input ***/
|
|
||||||
#ifdef WII_BUILD
|
|
||||||
CONF_Init();
|
|
||||||
WPAD_Init();
|
|
||||||
setup_controllers();
|
|
||||||
#endif
|
|
||||||
vmode = VIDEO_GetPreferredMode(NULL);
|
|
||||||
|
|
||||||
/*** Now configure the framebuffer.
|
|
||||||
Really a framebuffer is just a chunk of memory
|
|
||||||
to hold the display line by line.
|
|
||||||
***/
|
|
||||||
|
|
||||||
xfb[0] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer (vmode));
|
|
||||||
/*** I prefer also to have a second buffer for double-buffering.
|
|
||||||
This is not needed for the console demo.
|
|
||||||
***/
|
|
||||||
xfb[1] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer (vmode));
|
|
||||||
|
|
||||||
/*** Define a console ***/
|
|
||||||
console_init (xfb[0], 20, 64, vmode->fbWidth, vmode->xfbHeight,
|
|
||||||
vmode->fbWidth * 2);
|
|
||||||
|
|
||||||
/*** Let libogc configure the mode ***/
|
|
||||||
VIDEO_Configure (vmode);
|
|
||||||
|
|
||||||
/*** Clear framebuffer to black ***/
|
|
||||||
VIDEO_ClearFrameBuffer (vmode, xfb[0], COLOR_BLACK);
|
|
||||||
VIDEO_ClearFrameBuffer (vmode, xfb[1], COLOR_BLACK);
|
|
||||||
|
|
||||||
/*** Set the framebuffer to be displayed at next VBlank ***/
|
|
||||||
VIDEO_SetNextFramebuffer (xfb[0]);
|
|
||||||
|
|
||||||
/*** Get the PAD status updated by libogc ***/
|
|
||||||
VIDEO_SetPreRetraceCallback (doScan);
|
|
||||||
VIDEO_SetBlack (0);
|
|
||||||
/*
|
|
||||||
int i;
|
|
||||||
u32 *vreg = (u32 *)0xCC002000;
|
|
||||||
for ( i = 0; i < 64; i++ )
|
|
||||||
vreg[i] = vpal60[i]; */
|
|
||||||
|
|
||||||
/*** Update the video for next vblank ***/
|
|
||||||
VIDEO_Flush ();
|
|
||||||
|
|
||||||
VIDEO_WaitVSync (); /*** Wait for VBL ***/
|
|
||||||
if (vmode->viTVMode & VI_NON_INTERLACE)
|
|
||||||
VIDEO_WaitVSync ();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void systemMessage(int num, const char *msg, ...)
|
|
||||||
{
|
|
||||||
/*** For now ... do nothing ***/
|
|
||||||
}
|
|
||||||
|
|
||||||
void GC_Sleep(u32 dwMiliseconds)
|
|
||||||
{
|
|
||||||
int nVBlanks = (dwMiliseconds / 16);
|
|
||||||
while (nVBlanks-- > 0)
|
|
||||||
{
|
|
||||||
VIDEO_WaitVSync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void systemFrame()
|
|
||||||
{}
|
|
||||||
|
|
||||||
void systemScreenCapture(int a)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void systemShowSpeed(int speed)
|
|
||||||
{}
|
|
||||||
static u32 autoFrameSkipLastTime = 0;
|
|
||||||
static int frameskipadjust = 0;
|
|
||||||
|
|
||||||
void write_save()
|
|
||||||
{
|
|
||||||
emulator.emuWriteBattery(batfilename);
|
|
||||||
}
|
|
||||||
|
|
||||||
void system10Frames(int rate)
|
|
||||||
{
|
|
||||||
if ( cartridgeType == 1 )
|
|
||||||
return;
|
|
||||||
|
|
||||||
u32 time = systemGetClock();
|
|
||||||
u32 diff = time - autoFrameSkipLastTime;
|
|
||||||
int speed = 100;
|
|
||||||
|
|
||||||
if(diff)
|
|
||||||
speed = (1000000/rate)/diff;
|
|
||||||
/* char temp[512];
|
|
||||||
sprintf(temp,"Speed: %i",speed);
|
|
||||||
MENU_DrawString( -1, 450,temp , 1 ); */
|
|
||||||
|
|
||||||
if(speed >= 98)
|
|
||||||
{
|
|
||||||
frameskipadjust++;
|
|
||||||
|
|
||||||
if(frameskipadjust >= 3)
|
|
||||||
{
|
|
||||||
frameskipadjust=0;
|
|
||||||
if(systemFrameSkip > 0)
|
|
||||||
systemFrameSkip--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(speed < 80)
|
|
||||||
frameskipadjust -= (90 - speed)/5;
|
|
||||||
else if(systemFrameSkip < 9)
|
|
||||||
frameskipadjust--;
|
|
||||||
|
|
||||||
if(frameskipadjust <= -2)
|
|
||||||
{
|
|
||||||
frameskipadjust += 2;
|
|
||||||
if(systemFrameSkip < 9)
|
|
||||||
systemFrameSkip++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( cartridgeType == 1 )
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
if(systemSaveUpdateCounter) {
|
|
||||||
char temp[512];
|
|
||||||
sprintf(temp,"Writing Save To Disk");
|
|
||||||
MENU_DrawString( -1, 450,temp , 1 );
|
|
||||||
} */
|
|
||||||
|
|
||||||
if(systemSaveUpdateCounter) {
|
|
||||||
if(--systemSaveUpdateCounter <= SYSTEM_SAVE_NOT_UPDATED) {
|
|
||||||
write_save();
|
|
||||||
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
autoFrameSkipLastTime = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void systemUpdateMotionSensor()
|
|
||||||
{}
|
|
||||||
|
|
||||||
void systemGbBorderOn()
|
|
||||||
{}
|
|
||||||
|
|
||||||
void systemWriteDataToSoundBuffer()
|
|
||||||
{
|
|
||||||
MIXER_AddSamples((u8 *)soundFinalWave, (cartridgeType == 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
void systemSoundPause()
|
|
||||||
{}
|
|
||||||
|
|
||||||
void systemSoundResume()
|
|
||||||
{}
|
|
||||||
|
|
||||||
void systemSoundReset()
|
|
||||||
{}
|
|
||||||
|
|
||||||
void systemGbPrint(u8 *data,int pages,int feed,int palette, int contrast)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void systemSoundShutdown()
|
|
||||||
{}
|
|
||||||
|
|
||||||
static void AudioPlayer( void )
|
|
||||||
{
|
|
||||||
AUDIO_StopDMA();
|
|
||||||
MIXER_GetSamples(soundbuffer, 3200);
|
|
||||||
DCFlushRange(soundbuffer,3200);
|
|
||||||
AUDIO_InitDMA((u32)soundbuffer,3200);
|
|
||||||
AUDIO_StartDMA();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool systemSoundInit()
|
|
||||||
{
|
|
||||||
AUDIO_Init(NULL);
|
|
||||||
AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
|
|
||||||
AUDIO_RegisterDMACallback(AudioPlayer);
|
|
||||||
memset(soundbuffer, 0, 3200);
|
|
||||||
|
|
||||||
//printf("Audio Inited\n");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void AudioDeInit()
|
|
||||||
{
|
|
||||||
AUDIO_StopDMA();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool systemPauseOnFrame()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int systemGetSensorX()
|
|
||||||
{
|
|
||||||
return sensorX;
|
|
||||||
}
|
|
||||||
|
|
||||||
int systemGetSensorY()
|
|
||||||
{
|
|
||||||
return sensorY;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool systemCanChangeSoundQuality()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* systemReadJoypads
|
|
||||||
****************************************************************************/
|
|
||||||
bool systemReadJoypads()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 systemReadJoypad(int which)
|
|
||||||
{
|
|
||||||
return NGCPad();
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* systemGetClock
|
|
||||||
*
|
|
||||||
* Returns number of milliseconds since program start
|
|
||||||
****************************************************************************/
|
|
||||||
u32 systemGetClock( void )
|
|
||||||
{
|
|
||||||
mftb(&now);
|
|
||||||
return tb_diff_msec(&now, &start) - loadtimeradjust;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* systemDrawScreen
|
|
||||||
****************************************************************************/
|
|
||||||
void systemDrawScreen()
|
|
||||||
{
|
|
||||||
/** GB / GBC Have oodles of time - so sync on VSync **/
|
|
||||||
#if WITHGX
|
|
||||||
GX_Render( srcWidth, srcHeight, pix, srcPitch );
|
|
||||||
#endif
|
|
||||||
#ifdef WII_BUILD
|
|
||||||
|
|
||||||
VIDEO_WaitVSync ();
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#ifdef GC_BUILD
|
|
||||||
if ( cartridgeType == 1 )
|
|
||||||
{
|
|
||||||
VIDEO_WaitVSync();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Showdir
|
|
||||||
****************************************************************************/
|
|
||||||
int ShowDir( char *whichdir )
|
|
||||||
{
|
|
||||||
int count;
|
|
||||||
int i;
|
|
||||||
count = gen_getdir( whichdir );
|
|
||||||
printf("Found %d files\n",count);
|
|
||||||
|
|
||||||
for ( i = 0; i < count; i++ )
|
|
||||||
printf("%s\n", direntries[i]);
|
|
||||||
while(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Asks user to select a ROM
|
|
||||||
*/
|
|
||||||
void chooseRom() {
|
|
||||||
//char *fname = "Sonic Advance 3.GBA";
|
|
||||||
char *fname = NULL;
|
|
||||||
memset(filename,0,1024);
|
|
||||||
memset(batfilename,0,1024);
|
|
||||||
fname = MENU_GetLoadFile( "/VBA/ROMS" );
|
|
||||||
sprintf(filename, "/VBA/ROMS/%s", fname);
|
|
||||||
|
|
||||||
// construct battery save file name
|
|
||||||
strcpy(batfilename, "/VBA/SAVES/");
|
|
||||||
strncat(batfilename,fname,strlen(fname)-4);
|
|
||||||
strcat(batfilename,".SAV");
|
|
||||||
|
|
||||||
// construct savestate name
|
|
||||||
strcpy(statename, "/VBA/SAVES/");
|
|
||||||
strncat(statename,fname,strlen(fname)-4);
|
|
||||||
strcat(statename,".SGM");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Checks to see if a previous SRAM/Flash save exists
|
|
||||||
If it does, it prompts the user to load it or not
|
|
||||||
*/
|
|
||||||
void checkSave() {
|
|
||||||
FILE* f = gen_fopen(statename, "rb");
|
|
||||||
if (f != NULL) {
|
|
||||||
gen_fclose(f);
|
|
||||||
whichfb^=1;
|
|
||||||
VIDEO_ClearFrameBuffer (vmode, xfb[whichfb], COLOR_BLACK);
|
|
||||||
MENU_DrawString( 140, 50,"Quick Save State Exists" , 1 );
|
|
||||||
MENU_DrawString( 140, 80,"Do you wish to load it?" , 1 );
|
|
||||||
MENU_DrawString( -1, 170,"(L) or (+) YES" , 1 );
|
|
||||||
MENU_DrawString( -1, 200,"(R) or (-) NO" , 1 );
|
|
||||||
VIDEO_WaitVSync ();
|
|
||||||
VIDEO_SetNextFramebuffer(xfb[whichfb]);
|
|
||||||
VIDEO_Flush();
|
|
||||||
VIDEO_WaitVSync();
|
|
||||||
while(1) {
|
|
||||||
WPADData *wpad;
|
|
||||||
WPAD_ScanPads();
|
|
||||||
wpad = WPAD_Data(0);
|
|
||||||
if (isWiimoteAvailable) {
|
|
||||||
unsigned short b = wpad->btns_h;
|
|
||||||
if(b & WPAD_BUTTON_PLUS) {
|
|
||||||
saveExists = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(b & WPAD_BUTTON_MINUS) break;
|
|
||||||
}
|
|
||||||
if (isClassicAvailable) {
|
|
||||||
unsigned short b = wpad->exp.classic.btns;
|
|
||||||
if(b & CLASSIC_CTRL_BUTTON_PLUS) {
|
|
||||||
saveExists = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(b & CLASSIC_CTRL_BUTTON_MINUS) break;
|
|
||||||
}
|
|
||||||
u16 buttons = PAD_ButtonsHeld(0);
|
|
||||||
if(buttons & PAD_TRIGGER_R){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(buttons & PAD_TRIGGER_L){
|
|
||||||
saveExists = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VIDEO_ClearFrameBuffer (vmode, xfb[whichfb], COLOR_BLACK);
|
|
||||||
VIDEO_WaitVSync ();
|
|
||||||
VIDEO_SetNextFramebuffer(xfb[whichfb]);
|
|
||||||
VIDEO_Flush();
|
|
||||||
VIDEO_WaitVSync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void askSound() {
|
|
||||||
soundOffFlag = false;
|
|
||||||
soundLowPass = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int ingameMenu() {
|
|
||||||
tb_t start,end;
|
|
||||||
mftb(&start);
|
|
||||||
char temp[512];
|
|
||||||
u16 buttons;
|
|
||||||
AudioDeInit();
|
|
||||||
whichfb^=1;
|
|
||||||
VIDEO_ClearFrameBuffer (vmode, xfb[whichfb], COLOR_BLACK);
|
|
||||||
MENU_DrawString( 140, 50,"VisualBoyAdvance 1.7.2" , 1 );
|
|
||||||
|
|
||||||
#ifdef GC_BUILD
|
|
||||||
MENU_DrawString( 140, 80,"Nintendo Gamecube Port" , 1 );
|
|
||||||
MENU_DrawString( -1, 170,"(B) - Resume play" , 1 );
|
|
||||||
MENU_DrawString( -1, 200,"(L) - Write Quicksave" , 1 );
|
|
||||||
MENU_DrawString( -1, 230,"(R) - Reset game" , 1 );
|
|
||||||
MENU_DrawString( -1, 320,"(Z) - Return to loader" , 1 );
|
|
||||||
#endif
|
|
||||||
#ifdef WII_BUILD
|
|
||||||
MENU_DrawString( 140, 80,"Nintendo Wii Port" , 1 );
|
|
||||||
MENU_DrawString( -1, 170,"(B) or (Home) - Resume play" , 1 );
|
|
||||||
MENU_DrawString( -1, 200,"(L) or (+) - Write Quicksave" , 1 );
|
|
||||||
MENU_DrawString( -1, 230,"(R) or (-) - Reset game" , 1 );
|
|
||||||
MENU_DrawString( -1, 320,"(Z) or (A+B) - Return to loader" , 1 );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sprintf(temp,"Frameskip: Auto (Currently %i)",systemFrameSkip);
|
|
||||||
MENU_DrawString( -1, 450,temp , 1 );
|
|
||||||
|
|
||||||
VIDEO_WaitVSync ();
|
|
||||||
VIDEO_SetNextFramebuffer(xfb[whichfb]);
|
|
||||||
VIDEO_Flush();
|
|
||||||
VIDEO_WaitVSync();
|
|
||||||
|
|
||||||
//wait for user to let go of menu calling button
|
|
||||||
do{buttons = PAD_ButtonsHeld(0);}
|
|
||||||
while((buttons & PAD_BUTTON_A)||(buttons & PAD_BUTTON_B));
|
|
||||||
//wait for user to let go of home button
|
|
||||||
#ifdef WII_BUILD
|
|
||||||
WPADData *wpad;
|
|
||||||
int btn;
|
|
||||||
if(isWiimoteAvailable)
|
|
||||||
do{WPAD_ScanPads(); wpad = WPAD_Data(0); btn = wpad->btns_h;}
|
|
||||||
while(btn & WPAD_BUTTON_HOME);
|
|
||||||
if(isClassicAvailable)
|
|
||||||
do{WPAD_ScanPads(); wpad = WPAD_Data(0); btn = wpad->exp.classic.btns;}
|
|
||||||
while(btn & CLASSIC_CTRL_BUTTON_HOME);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while(1){
|
|
||||||
|
|
||||||
#ifdef WII_BUILD
|
|
||||||
WPADData *wpad;
|
|
||||||
WPAD_ScanPads();
|
|
||||||
wpad = WPAD_Data(0);
|
|
||||||
if (isWiimoteAvailable)
|
|
||||||
{
|
|
||||||
unsigned short b = wpad->btns_h;
|
|
||||||
if(b & WPAD_BUTTON_MINUS){ //Reset game
|
|
||||||
emulator.emuReset();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(b & WPAD_BUTTON_PLUS) { //Write save
|
|
||||||
emulator.emuWriteState(statename);
|
|
||||||
GC_Sleep(1500);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if((b & WPAD_BUTTON_A) && (b & WPAD_BUTTON_B)) { //Return to loader
|
|
||||||
void (*reload)() = (void(*)())0x80001800;
|
|
||||||
reload();
|
|
||||||
}
|
|
||||||
if(b & WPAD_BUTTON_HOME) { //Resume play
|
|
||||||
do{WPAD_ScanPads(); wpad = WPAD_Data(0); b = wpad->btns_h;}
|
|
||||||
while(b & WPAD_BUTTON_HOME); //wait for home
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* if(b & WPAD_BUTTON_2) { //back to menu
|
|
||||||
INSERT BACK-TO-MENU HERE
|
|
||||||
} */
|
|
||||||
}
|
|
||||||
if (isClassicAvailable)
|
|
||||||
{
|
|
||||||
int b = wpad->exp.classic.btns;
|
|
||||||
if(b & CLASSIC_CTRL_BUTTON_MINUS){ //Reset game
|
|
||||||
emulator.emuReset();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(b & CLASSIC_CTRL_BUTTON_PLUS) { //Write save
|
|
||||||
emulator.emuWriteState(statename);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if((b & CLASSIC_CTRL_BUTTON_A) && (b & CLASSIC_CTRL_BUTTON_B)) { //Return to loader
|
|
||||||
void (*reload)() = (void(*)())0x80001800;
|
|
||||||
reload();
|
|
||||||
}
|
|
||||||
if(b & CLASSIC_CTRL_BUTTON_HOME) { //Resume play
|
|
||||||
do{WPAD_ScanPads(); wpad = WPAD_Data(0); b = wpad->exp.classic.btns;}
|
|
||||||
while(b & CLASSIC_CTRL_BUTTON_HOME); //wait for home button
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
u16 buttons = PAD_ButtonsHeld(0); //grab pad buttons
|
|
||||||
|
|
||||||
if(buttons & PAD_TRIGGER_R){ //Reset game
|
|
||||||
emulator.emuReset();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(buttons & PAD_TRIGGER_L) { //Write save
|
|
||||||
emulator.emuWriteState(statename);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(buttons & PAD_TRIGGER_Z) { //Return to loader
|
|
||||||
void (*reload)() = (void(*)())0x80001800;
|
|
||||||
reload();
|
|
||||||
}
|
|
||||||
if(buttons & PAD_BUTTON_B) { //Resume play
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AudioPlayer();
|
|
||||||
mftb(&end);
|
|
||||||
loadtimeradjust += tb_diff_msec(&end, &start);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* main
|
|
||||||
*
|
|
||||||
* Program entry
|
|
||||||
****************************************************************************/
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int vAspect = 0;
|
|
||||||
int hAspect = 0;
|
|
||||||
|
|
||||||
Initialise();
|
|
||||||
|
|
||||||
printf("\n\n\nVisualBoyAdvance 1.7.2\n");
|
|
||||||
printf("Nintendo Wii Port\n");
|
|
||||||
|
|
||||||
|
|
||||||
/** Kick off SD Lib **/
|
|
||||||
SDInit();
|
|
||||||
|
|
||||||
|
|
||||||
/** Build GBPalette **/
|
|
||||||
for( i = 0; i < 24; )
|
|
||||||
{
|
|
||||||
systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10);
|
|
||||||
systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10);
|
|
||||||
systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10);
|
|
||||||
systemGbPalette[i++] = 0;
|
|
||||||
}
|
|
||||||
/** Set palette etc - Fixed to RGB565 **/
|
|
||||||
systemColorDepth = 16;
|
|
||||||
systemRedShift = 11;
|
|
||||||
systemGreenShift = 6;
|
|
||||||
systemBlueShift = 0;
|
|
||||||
for(i = 0; i < 0x10000; i++)
|
|
||||||
{
|
|
||||||
systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
|
|
||||||
(((i & 0x3e0) >> 5) << systemGreenShift) |
|
|
||||||
(((i & 0x7c00) >> 10) << systemBlueShift);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Main loop
|
|
||||||
while(1) {
|
|
||||||
cartridgeType = 0;
|
|
||||||
srcWidth = 0;
|
|
||||||
srcHeight = 0;
|
|
||||||
destWidth = 0;
|
|
||||||
destHeight = 0;
|
|
||||||
srcPitch = 0;
|
|
||||||
|
|
||||||
chooseRom();
|
|
||||||
checkSave();
|
|
||||||
|
|
||||||
IMAGE_TYPE type = utilFindType(filename);
|
|
||||||
|
|
||||||
switch( type )
|
|
||||||
{
|
|
||||||
case IMAGE_GBA:
|
|
||||||
printf("GameBoy Advance Image\n");
|
|
||||||
cartridgeType = 2;
|
|
||||||
emulator = GBASystem;
|
|
||||||
srcWidth = 240;
|
|
||||||
srcHeight = 160;
|
|
||||||
VMCPULoadROM(filename);
|
|
||||||
/* Actual Visual Aspect is 1.57 */
|
|
||||||
hAspect = 70;
|
|
||||||
vAspect = 46;
|
|
||||||
srcPitch = 484;
|
|
||||||
soundQuality = 2;
|
|
||||||
soundBufferLen = 1470;
|
|
||||||
cpuSaveType = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IMAGE_GB:
|
|
||||||
printf("GameBoy Image\n");
|
|
||||||
cartridgeType = 1;
|
|
||||||
emulator = GBSystem;
|
|
||||||
srcWidth = 160;
|
|
||||||
srcHeight = 144;
|
|
||||||
gbLoadRom(filename);
|
|
||||||
/* Actual physical aspect is 1.0 */
|
|
||||||
hAspect = 60;
|
|
||||||
vAspect = 46;
|
|
||||||
srcPitch = 324;
|
|
||||||
soundQuality = 1;
|
|
||||||
soundBufferLen = 1470 * 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
printf("Unknown Image\n");
|
|
||||||
while(1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set defaults **/
|
|
||||||
flashSetSize(0x10000);
|
|
||||||
rtcEnable(true);
|
|
||||||
agbPrintEnable(false);
|
|
||||||
askSound();
|
|
||||||
|
|
||||||
#if WITHGX
|
|
||||||
/** Set GX **/
|
|
||||||
GX_Start( srcWidth, srcHeight, hAspect, vAspect );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ( cartridgeType == 1 )
|
|
||||||
{
|
|
||||||
gbSoundReset();
|
|
||||||
gbSoundSetQuality(soundQuality);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
soundSetQuality(soundQuality);
|
|
||||||
CPUInit("/VBA/BIOS/BIOS.GBA", 1);
|
|
||||||
CPUReset();
|
|
||||||
}
|
|
||||||
|
|
||||||
emulator.emuReadBattery(batfilename);
|
|
||||||
if (saveExists){
|
|
||||||
emulator.emuReadState(statename);
|
|
||||||
saveExists = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
soundVolume = 0;
|
|
||||||
systemSoundOn = true;
|
|
||||||
|
|
||||||
soundInit();
|
|
||||||
AudioPlayer();
|
|
||||||
|
|
||||||
emulating = 1;
|
|
||||||
/** Start system clock **/
|
|
||||||
mftb(&start);
|
|
||||||
|
|
||||||
while ( emulating )
|
|
||||||
{
|
|
||||||
emulator.emuMain(emulator.emuCount);
|
|
||||||
if(menuCalled) {
|
|
||||||
if(ingameMenu())
|
|
||||||
break;
|
|
||||||
menuCalled = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Never **/
|
|
||||||
while(1);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
53
source/ngc/vbaconfig.cpp
Normal file
53
source/ngc/vbaconfig.cpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* crunchy2 May 2007
|
||||||
|
* Tantric September 2008
|
||||||
|
*
|
||||||
|
* s9xconfig.cpp
|
||||||
|
*
|
||||||
|
* Configuration parameters are here for easy maintenance.
|
||||||
|
* Refer to Snes9x.h for all combinations.
|
||||||
|
* The defaults used here are taken directly from porting.html
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "vba.h"
|
||||||
|
#include "smbop.h"
|
||||||
|
|
||||||
|
struct SGCSettings GCSettings;
|
||||||
|
|
||||||
|
void
|
||||||
|
DefaultSettings ()
|
||||||
|
{
|
||||||
|
/************** GameCube/Wii Settings *********************/
|
||||||
|
GCSettings.LoadMethod = METHOD_AUTO; // Auto, SD, DVD, USB, Network (SMB)
|
||||||
|
GCSettings.SaveMethod = METHOD_AUTO; // Auto, SD, Memory Card Slot A, Memory Card Slot B, USB, Network (SMB)
|
||||||
|
sprintf (GCSettings.LoadFolder,"vba/roms"); // Path to game files
|
||||||
|
sprintf (GCSettings.SaveFolder,"vba/saves"); // Path to save files
|
||||||
|
sprintf (GCSettings.CheatFolder,"vba/cheats"); // Path to cheat files
|
||||||
|
GCSettings.AutoLoad = 1;
|
||||||
|
GCSettings.AutoSave = 1;
|
||||||
|
|
||||||
|
// custom SMB settings
|
||||||
|
strncpy (GCSettings.smbip, "", 15); // IP Address of share server
|
||||||
|
strncpy (GCSettings.smbuser, "", 19); // Your share user
|
||||||
|
strncpy (GCSettings.smbpwd, "", 19); // Your share user password
|
||||||
|
strncpy (GCSettings.smbshare, "", 19); // Share name on server
|
||||||
|
|
||||||
|
GCSettings.smbip[15] = 0;
|
||||||
|
GCSettings.smbuser[19] = 0;
|
||||||
|
GCSettings.smbpwd[19] = 0;
|
||||||
|
GCSettings.smbshare[19] = 0;
|
||||||
|
|
||||||
|
GCSettings.gcip[0] = 0;
|
||||||
|
GCSettings.gwip[0] = 0;
|
||||||
|
GCSettings.mask[0] = 0;
|
||||||
|
GCSettings.smbsvid[0] = 0;
|
||||||
|
GCSettings.smbgcid[0] = 0;
|
||||||
|
|
||||||
|
GCSettings.VerifySaves = 0;
|
||||||
|
}
|
21
source/ngc/vbaconfig.h
Normal file
21
source/ngc/vbaconfig.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Snes9x 1.51 Nintendo Wii/Gamecube Port
|
||||||
|
*
|
||||||
|
* softdev July 2006
|
||||||
|
* crunchy2 May 2007
|
||||||
|
* Tantric September 2008
|
||||||
|
*
|
||||||
|
* s9xconfig.h
|
||||||
|
*
|
||||||
|
* Configuration parameters are here for easy maintenance.
|
||||||
|
* Refer to Snes9x.h for all combinations.
|
||||||
|
* The defaults used here are taken directly from porting.html
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _VBACONFIG_
|
||||||
|
|
||||||
|
#define _VBACONFIG_
|
||||||
|
|
||||||
|
void DefaultSettings ();
|
||||||
|
|
||||||
|
#endif
|
474
source/ngc/vbasupport.cpp
Normal file
474
source/ngc/vbasupport.cpp
Normal file
@ -0,0 +1,474 @@
|
|||||||
|
|
||||||
|
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "GBA.h"
|
||||||
|
#include "agbprint.h"
|
||||||
|
#include "Flash.h"
|
||||||
|
#include "Port.h"
|
||||||
|
#include "RTC.h"
|
||||||
|
#include "Sound.h"
|
||||||
|
#include "Text.h"
|
||||||
|
#include "unzip.h"
|
||||||
|
#include "Util.h"
|
||||||
|
#include "gb/GB.h"
|
||||||
|
#include "gb/gbGlobals.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "audio.h"
|
||||||
|
#include "vmmem.h"
|
||||||
|
#include "pal60.h"
|
||||||
|
#include "input.h"
|
||||||
|
#include "video.h"
|
||||||
|
#include "menudraw.h"
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "tbtime.h"
|
||||||
|
#include "sdfileio.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Globals
|
||||||
|
*/
|
||||||
|
int RGB_LOW_BITS_MASK=0x821;
|
||||||
|
int systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
||||||
|
|
||||||
|
int systemDebug = 0;
|
||||||
|
int emulating = 0;
|
||||||
|
|
||||||
|
int sensorX = 2047;
|
||||||
|
int sensorY = 2047;
|
||||||
|
|
||||||
|
int systemFrameSkip = 0;
|
||||||
|
bool systemSoundOn = false;
|
||||||
|
int systemVerbose = 0;
|
||||||
|
int cartridgeType = 0;
|
||||||
|
int srcWidth = 0;
|
||||||
|
int srcHeight = 0;
|
||||||
|
int destWidth = 0;
|
||||||
|
int destHeight = 0;
|
||||||
|
int srcPitch = 0;
|
||||||
|
int saveExists = 0;
|
||||||
|
|
||||||
|
int systemRedShift = 0;
|
||||||
|
int systemBlueShift = 0;
|
||||||
|
int systemGreenShift = 0;
|
||||||
|
int systemColorDepth = 0;
|
||||||
|
u16 systemGbPalette[24];
|
||||||
|
u16 systemColorMap16[0x10000];
|
||||||
|
//u32 systemColorMap32[0x10000];
|
||||||
|
u32 *systemColorMap32 = (u32 *)&systemColorMap16;
|
||||||
|
|
||||||
|
/*** 2D Video Globals ***/
|
||||||
|
extern u32 whichfb;
|
||||||
|
extern u32 *xfb[2];
|
||||||
|
extern GXRModeObj *vmode;
|
||||||
|
|
||||||
|
struct EmulatedSystem emulator =
|
||||||
|
{
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
false,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
static tb_t start, now;
|
||||||
|
|
||||||
|
u32 loadtimeradjust;
|
||||||
|
|
||||||
|
int throttle = 100;
|
||||||
|
u32 throttleLastTime = 0;
|
||||||
|
|
||||||
|
int vAspect = 0;
|
||||||
|
int hAspect = 0;
|
||||||
|
|
||||||
|
//char filename[1024]; //rom file name
|
||||||
|
//char batfilename[1024]; //battery save file name
|
||||||
|
//char statename[1024]; //savestate file name
|
||||||
|
|
||||||
|
void debuggerOutput(char *, u32)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void (*dbgOutput)(char *, u32) = debuggerOutput;
|
||||||
|
|
||||||
|
void systemMessage(int num, const char *msg, ...)
|
||||||
|
{
|
||||||
|
/*** For now ... do nothing ***/
|
||||||
|
}
|
||||||
|
|
||||||
|
void GC_Sleep(u32 dwMiliseconds)
|
||||||
|
{
|
||||||
|
int nVBlanks = (dwMiliseconds / 16);
|
||||||
|
while (nVBlanks-- > 0)
|
||||||
|
{
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void systemFrame()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void systemScreenCapture(int a)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void systemShowSpeed(int speed)
|
||||||
|
{}
|
||||||
|
static u32 autoFrameSkipLastTime = 0;
|
||||||
|
static int frameskipadjust = 0;
|
||||||
|
|
||||||
|
void write_save()
|
||||||
|
{
|
||||||
|
//emulator.emuWriteBattery(batfilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void system10Frames(int rate)
|
||||||
|
{
|
||||||
|
if ( cartridgeType == 1 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
u32 time = systemGetClock();
|
||||||
|
u32 diff = time - autoFrameSkipLastTime;
|
||||||
|
int speed = 100;
|
||||||
|
|
||||||
|
if(diff)
|
||||||
|
speed = (1000000/rate)/diff;
|
||||||
|
/* char temp[512];
|
||||||
|
sprintf(temp,"Speed: %i",speed);
|
||||||
|
MENU_DrawString( -1, 450,temp , 1 ); */
|
||||||
|
|
||||||
|
if(speed >= 98)
|
||||||
|
{
|
||||||
|
frameskipadjust++;
|
||||||
|
|
||||||
|
if(frameskipadjust >= 3)
|
||||||
|
{
|
||||||
|
frameskipadjust=0;
|
||||||
|
if(systemFrameSkip > 0)
|
||||||
|
systemFrameSkip--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(speed < 80)
|
||||||
|
frameskipadjust -= (90 - speed)/5;
|
||||||
|
else if(systemFrameSkip < 9)
|
||||||
|
frameskipadjust--;
|
||||||
|
|
||||||
|
if(frameskipadjust <= -2)
|
||||||
|
{
|
||||||
|
frameskipadjust += 2;
|
||||||
|
if(systemFrameSkip < 9)
|
||||||
|
systemFrameSkip++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( cartridgeType == 1 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
if(systemSaveUpdateCounter) {
|
||||||
|
char temp[512];
|
||||||
|
sprintf(temp,"Writing Save To Disk");
|
||||||
|
MENU_DrawString( -1, 450,temp , 1 );
|
||||||
|
} */
|
||||||
|
|
||||||
|
if(systemSaveUpdateCounter) {
|
||||||
|
if(--systemSaveUpdateCounter <= SYSTEM_SAVE_NOT_UPDATED) {
|
||||||
|
write_save();
|
||||||
|
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
autoFrameSkipLastTime = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void systemUpdateMotionSensor()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void systemGbBorderOn()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void systemWriteDataToSoundBuffer()
|
||||||
|
{
|
||||||
|
MIXER_AddSamples((u8 *)soundFinalWave, (cartridgeType == 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void systemSoundPause()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void systemSoundResume()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void systemSoundReset()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void systemGbPrint(u8 *data,int pages,int feed,int palette, int contrast)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void systemSoundShutdown()
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool systemSoundInit()
|
||||||
|
{
|
||||||
|
//memset(soundbuffer, 0, 3200);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool systemPauseOnFrame()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int systemGetSensorX()
|
||||||
|
{
|
||||||
|
return sensorX;
|
||||||
|
}
|
||||||
|
|
||||||
|
int systemGetSensorY()
|
||||||
|
{
|
||||||
|
return sensorY;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool systemCanChangeSoundQuality()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* systemReadJoypads
|
||||||
|
****************************************************************************/
|
||||||
|
bool systemReadJoypads()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 systemReadJoypad(int which)
|
||||||
|
{
|
||||||
|
return GetJoy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* systemGetClock
|
||||||
|
*
|
||||||
|
* Returns number of milliseconds since program start
|
||||||
|
****************************************************************************/
|
||||||
|
u32 systemGetClock( void )
|
||||||
|
{
|
||||||
|
mftb(&now);
|
||||||
|
return tb_diff_msec(&now, &start) - loadtimeradjust;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* systemDrawScreen
|
||||||
|
****************************************************************************/
|
||||||
|
void systemDrawScreen()
|
||||||
|
{
|
||||||
|
/** GB / GBC Have oodles of time - so sync on VSync **/
|
||||||
|
GX_Render( srcWidth, srcHeight, pix, srcPitch );
|
||||||
|
|
||||||
|
#ifdef HW_RVL
|
||||||
|
VIDEO_WaitVSync ();
|
||||||
|
#else
|
||||||
|
if ( cartridgeType == 1 )
|
||||||
|
{
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Checks to see if a previous SRAM/Flash save exists
|
||||||
|
If it does, it prompts the user to load it or not
|
||||||
|
*/
|
||||||
|
void checkSave() {
|
||||||
|
/* FILE* f = gen_fopen(statename, "rb");
|
||||||
|
if (f != NULL) {
|
||||||
|
gen_fclose(f);
|
||||||
|
whichfb^=1;
|
||||||
|
VIDEO_ClearFrameBuffer (vmode, xfb[whichfb], COLOR_BLACK);
|
||||||
|
//MENU_DrawString( 140, 50,"Quick Save State Exists" , 1 );
|
||||||
|
//MENU_DrawString( 140, 80,"Do you wish to load it?" , 1 );
|
||||||
|
//MENU_DrawString( -1, 170,"(L) or (+) YES" , 1 );
|
||||||
|
//MENU_DrawString( -1, 200,"(R) or (-) NO" , 1 );
|
||||||
|
VIDEO_WaitVSync ();
|
||||||
|
VIDEO_SetNextFramebuffer(xfb[whichfb]);
|
||||||
|
VIDEO_Flush();
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
while(1) {
|
||||||
|
WPADData *wpad;
|
||||||
|
WPAD_ScanPads();
|
||||||
|
wpad = WPAD_Data(0);
|
||||||
|
if (isWiimoteAvailable) {
|
||||||
|
unsigned short b = wpad->btns_h;
|
||||||
|
if(b & WPAD_BUTTON_PLUS) {
|
||||||
|
saveExists = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(b & WPAD_BUTTON_MINUS) break;
|
||||||
|
}
|
||||||
|
if (isClassicAvailable) {
|
||||||
|
unsigned short b = wpad->exp.classic.btns;
|
||||||
|
if(b & CLASSIC_CTRL_BUTTON_PLUS) {
|
||||||
|
saveExists = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(b & CLASSIC_CTRL_BUTTON_MINUS) break;
|
||||||
|
}
|
||||||
|
u16 buttons = PAD_ButtonsHeld(0);
|
||||||
|
if(buttons & PAD_TRIGGER_R){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(buttons & PAD_TRIGGER_L){
|
||||||
|
saveExists = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VIDEO_ClearFrameBuffer (vmode, xfb[whichfb], COLOR_BLACK);
|
||||||
|
VIDEO_WaitVSync ();
|
||||||
|
VIDEO_SetNextFramebuffer(xfb[whichfb]);
|
||||||
|
VIDEO_Flush();
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void askSound() {
|
||||||
|
soundOffFlag = false;
|
||||||
|
soundLowPass = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int loadVBAROM(char filename[])
|
||||||
|
{
|
||||||
|
cartridgeType = 0;
|
||||||
|
srcWidth = 0;
|
||||||
|
srcHeight = 0;
|
||||||
|
destWidth = 0;
|
||||||
|
destHeight = 0;
|
||||||
|
srcPitch = 0;
|
||||||
|
|
||||||
|
IMAGE_TYPE type = utilFindType(filename);
|
||||||
|
|
||||||
|
switch( type )
|
||||||
|
{
|
||||||
|
case IMAGE_GBA:
|
||||||
|
//WaitPrompt("GameBoy Advance Image");
|
||||||
|
cartridgeType = 2;
|
||||||
|
emulator = GBASystem;
|
||||||
|
srcWidth = 240;
|
||||||
|
srcHeight = 160;
|
||||||
|
VMCPULoadROM(filename);
|
||||||
|
/* Actual Visual Aspect is 1.57 */
|
||||||
|
hAspect = 70;
|
||||||
|
vAspect = 46;
|
||||||
|
srcPitch = 484;
|
||||||
|
soundQuality = 2;
|
||||||
|
soundBufferLen = 1470;
|
||||||
|
cpuSaveType = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IMAGE_GB:
|
||||||
|
//WaitPrompt("GameBoy Image");
|
||||||
|
cartridgeType = 1;
|
||||||
|
emulator = GBSystem;
|
||||||
|
srcWidth = 160;
|
||||||
|
srcHeight = 144;
|
||||||
|
gbLoadRom(filename);
|
||||||
|
/* Actual physical aspect is 1.0 */
|
||||||
|
hAspect = 60;
|
||||||
|
vAspect = 46;
|
||||||
|
srcPitch = 324;
|
||||||
|
soundQuality = 1;
|
||||||
|
soundBufferLen = 1470 * 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
WaitPrompt((char *)"Unknown Image");
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set defaults **/
|
||||||
|
flashSetSize(0x10000);
|
||||||
|
rtcEnable(true);
|
||||||
|
agbPrintEnable(false);
|
||||||
|
askSound();
|
||||||
|
|
||||||
|
/** Setup GX **/
|
||||||
|
GX_Render_Init( srcWidth, srcHeight, hAspect, vAspect );
|
||||||
|
|
||||||
|
if ( cartridgeType == 1 )
|
||||||
|
{
|
||||||
|
gbSoundReset();
|
||||||
|
gbSoundSetQuality(soundQuality);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
soundSetQuality(soundQuality);
|
||||||
|
CPUInit("/VBA/BIOS/BIOS.GBA", 1);
|
||||||
|
CPUReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// emulator.emuReadBattery(batfilename);
|
||||||
|
if (saveExists)
|
||||||
|
{
|
||||||
|
//emulator.emuReadState(statename);
|
||||||
|
saveExists = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
soundVolume = 0;
|
||||||
|
systemSoundOn = true;
|
||||||
|
|
||||||
|
soundInit();
|
||||||
|
//AudioPlayer();
|
||||||
|
|
||||||
|
emulating = 1;
|
||||||
|
|
||||||
|
/** Start system clock **/
|
||||||
|
mftb(&start);
|
||||||
|
|
||||||
|
//emulator.emuReset();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitialisePalette()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
/** Build GBPalette **/
|
||||||
|
for( i = 0; i < 24; )
|
||||||
|
{
|
||||||
|
systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10);
|
||||||
|
systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10);
|
||||||
|
systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10);
|
||||||
|
systemGbPalette[i++] = 0;
|
||||||
|
}
|
||||||
|
/** Set palette etc - Fixed to RGB565 **/
|
||||||
|
systemColorDepth = 16;
|
||||||
|
systemRedShift = 11;
|
||||||
|
systemGreenShift = 6;
|
||||||
|
systemBlueShift = 0;
|
||||||
|
for(i = 0; i < 0x10000; i++)
|
||||||
|
{
|
||||||
|
systemColorMap16[i] =
|
||||||
|
((i & 0x1f) << systemRedShift) |
|
||||||
|
(((i & 0x3e0) >> 5) << systemGreenShift) |
|
||||||
|
(((i & 0x7c00) >> 10) << systemBlueShift);
|
||||||
|
}
|
||||||
|
}
|
6
source/ngc/vbasupport.h
Normal file
6
source/ngc/vbasupport.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "System.h"
|
||||||
|
|
||||||
|
extern struct EmulatedSystem emulator;
|
||||||
|
extern u32 loadtimeradjust;
|
||||||
|
int loadVBAROM(char filename[]);
|
||||||
|
void InitialisePalette();
|
342
source/ngc/video.cpp
Normal file
342
source/ngc/video.cpp
Normal file
@ -0,0 +1,342 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Generic GX Support for Emulators
|
||||||
|
* softdev 2007
|
||||||
|
*
|
||||||
|
* 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.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* NGC GX Video Functions
|
||||||
|
*
|
||||||
|
* These are pretty standard functions to setup and use GX scaling.
|
||||||
|
****************************************************************************/
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <wiiuse/wpad.h>
|
||||||
|
|
||||||
|
/*** External 2D Video ***/
|
||||||
|
/*** 2D Video Globals ***/
|
||||||
|
GXRModeObj *vmode; /*** Graphics Mode Object ***/
|
||||||
|
u32 *xfb[2] = { NULL, NULL }; /*** Framebuffers ***/
|
||||||
|
int whichfb = 0; /*** Frame buffer toggle ***/
|
||||||
|
|
||||||
|
int screenheight;
|
||||||
|
|
||||||
|
/*** 3D GX ***/
|
||||||
|
#define DEFAULT_FIFO_SIZE ( 256 * 1024 )
|
||||||
|
static u8 gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN(32);
|
||||||
|
|
||||||
|
/*** Texture memory ***/
|
||||||
|
static u8 *texturemem;
|
||||||
|
static int texturesize;
|
||||||
|
|
||||||
|
GXTexObj texobj;
|
||||||
|
static Mtx view;
|
||||||
|
static int vwidth, vheight, oldvwidth, oldvheight;
|
||||||
|
unsigned int copynow = GX_FALSE;
|
||||||
|
|
||||||
|
#define HASPECT 80
|
||||||
|
#define VASPECT 45
|
||||||
|
|
||||||
|
/* New texture based scaler */
|
||||||
|
typedef struct tagcamera
|
||||||
|
{
|
||||||
|
Vector pos;
|
||||||
|
Vector up;
|
||||||
|
Vector view;
|
||||||
|
}
|
||||||
|
camera;
|
||||||
|
|
||||||
|
/*** Square Matrix
|
||||||
|
This structure controls the size of the image on the screen.
|
||||||
|
Think of the output as a -80 x 80 by -60 x 60 graph.
|
||||||
|
***/
|
||||||
|
static s16 square[] ATTRIBUTE_ALIGN(32) = {
|
||||||
|
/*
|
||||||
|
* X, Y, Z
|
||||||
|
* Values set are for roughly 4:3 aspect
|
||||||
|
*/
|
||||||
|
-HASPECT, VASPECT, 0, // 0
|
||||||
|
HASPECT, VASPECT, 0, // 1
|
||||||
|
HASPECT, -VASPECT, 0, // 2
|
||||||
|
-HASPECT, -VASPECT, 0, // 3
|
||||||
|
};
|
||||||
|
|
||||||
|
static camera cam = { {0.0F, 0.0F, 0.0F},
|
||||||
|
{0.0F, 0.5F, 0.0F},
|
||||||
|
{0.0F, 0.0F, -0.5F}
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* StartGX
|
||||||
|
****************************************************************************/
|
||||||
|
void GX_Start()
|
||||||
|
{
|
||||||
|
Mtx p;
|
||||||
|
|
||||||
|
GXColor gxbackground = { 0, 0, 0, 0xff };
|
||||||
|
|
||||||
|
/*** Clear out FIFO area ***/
|
||||||
|
memset(&gp_fifo, 0, DEFAULT_FIFO_SIZE);
|
||||||
|
|
||||||
|
/*** Initialise GX ***/
|
||||||
|
GX_Init(&gp_fifo, DEFAULT_FIFO_SIZE);
|
||||||
|
GX_SetCopyClear(gxbackground, 0x00ffffff);
|
||||||
|
|
||||||
|
GX_SetViewport(0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1);
|
||||||
|
GX_SetDispCopyYScale((f32) vmode->xfbHeight / (f32) vmode->efbHeight);
|
||||||
|
GX_SetScissor(0, 0, vmode->fbWidth, vmode->efbHeight);
|
||||||
|
GX_SetDispCopySrc(0, 0, vmode->fbWidth, vmode->efbHeight);
|
||||||
|
GX_SetDispCopyDst(vmode->fbWidth, vmode->xfbHeight);
|
||||||
|
GX_SetCopyFilter(vmode->aa, vmode->sample_pattern, GX_TRUE,
|
||||||
|
vmode->vfilter);
|
||||||
|
GX_SetFieldMode(vmode->field_rendering,
|
||||||
|
((vmode->viHeight ==
|
||||||
|
2 * vmode->xfbHeight) ? GX_ENABLE : GX_DISABLE));
|
||||||
|
GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
|
||||||
|
GX_SetCullMode(GX_CULL_NONE);
|
||||||
|
GX_CopyDisp(xfb[whichfb ^ 1], GX_TRUE);
|
||||||
|
GX_SetDispCopyGamma(GX_GM_1_0);
|
||||||
|
|
||||||
|
guPerspective(p, 60, 1.33F, 10.0F, 1000.0F);
|
||||||
|
GX_LoadProjectionMtx(p, GX_PERSPECTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* UpdatePadsCB
|
||||||
|
*
|
||||||
|
* called by postRetraceCallback in InitGCVideo - scans gcpad and wpad
|
||||||
|
***************************************************************************/
|
||||||
|
void
|
||||||
|
UpdatePadsCB ()
|
||||||
|
{
|
||||||
|
#ifdef HW_RVL
|
||||||
|
WPAD_ScanPads();
|
||||||
|
#endif
|
||||||
|
PAD_ScanPads();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Initialise Video
|
||||||
|
*
|
||||||
|
* Before doing anything in libogc, it's recommended to configure a video
|
||||||
|
* output.
|
||||||
|
****************************************************************************/
|
||||||
|
void InitialiseVideo ()
|
||||||
|
{
|
||||||
|
/*** Start VIDEO Subsystem ***/
|
||||||
|
VIDEO_Init();
|
||||||
|
|
||||||
|
vmode = VIDEO_GetPreferredMode(NULL);
|
||||||
|
VIDEO_Configure(vmode);
|
||||||
|
|
||||||
|
screenheight = vmode->xfbHeight;
|
||||||
|
|
||||||
|
xfb[0] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer (vmode));
|
||||||
|
xfb[1] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer (vmode));
|
||||||
|
|
||||||
|
VIDEO_SetNextFramebuffer(xfb[0]);
|
||||||
|
VIDEO_SetBlack(FALSE);
|
||||||
|
VIDEO_Flush();
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
|
||||||
|
if(vmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||||
|
VIDEO_SetPostRetraceCallback((VIRetraceCallback)UpdatePadsCB);
|
||||||
|
VIDEO_SetNextFramebuffer(xfb[0]);
|
||||||
|
|
||||||
|
GX_Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Scaler Support Functions
|
||||||
|
****************************************************************************/
|
||||||
|
static void draw_init(void)
|
||||||
|
{
|
||||||
|
GX_ClearVtxDesc();
|
||||||
|
GX_SetVtxDesc(GX_VA_POS, GX_INDEX8);
|
||||||
|
GX_SetVtxDesc(GX_VA_CLR0, GX_INDEX8);
|
||||||
|
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||||||
|
|
||||||
|
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
|
||||||
|
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
|
||||||
|
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
||||||
|
|
||||||
|
GX_SetArray(GX_VA_POS, square, 3 * sizeof(s16));
|
||||||
|
|
||||||
|
GX_SetNumTexGens(1);
|
||||||
|
GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
|
||||||
|
|
||||||
|
GX_InvalidateTexAll();
|
||||||
|
|
||||||
|
GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565,
|
||||||
|
GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_vert(u8 pos, u8 c, f32 s, f32 t)
|
||||||
|
{
|
||||||
|
GX_Position1x8(pos);
|
||||||
|
GX_Color1x8(c);
|
||||||
|
GX_TexCoord2f32(s, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_square(Mtx v)
|
||||||
|
{
|
||||||
|
Mtx m; // model matrix.
|
||||||
|
Mtx mv; // modelview matrix.
|
||||||
|
|
||||||
|
guMtxIdentity(m);
|
||||||
|
guMtxTransApply(m, m, 0, 0, -100);
|
||||||
|
guMtxConcat(v, m, mv);
|
||||||
|
|
||||||
|
GX_LoadPosMtxImm(mv, GX_PNMTX0);
|
||||||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||||||
|
draw_vert(0, 0, 0.0, 0.0);
|
||||||
|
draw_vert(1, 0, 1.0, 0.0);
|
||||||
|
draw_vert(2, 0, 1.0, 1.0);
|
||||||
|
draw_vert(3, 0, 0.0, 1.0);
|
||||||
|
GX_End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GX_Render_Init(int width, int height, int haspect, int vaspect)
|
||||||
|
{
|
||||||
|
/*** Set new aspect (now with crap AR hack!) ***/
|
||||||
|
square[0] = square[9] = (-haspect - 7);
|
||||||
|
square[3] = square[6] = (haspect + 7);
|
||||||
|
square[1] = square[4] = (vaspect + 7);
|
||||||
|
square[7] = square[10] = (-vaspect - 7);
|
||||||
|
|
||||||
|
/*** Allocate 32byte aligned texture memory ***/
|
||||||
|
texturesize = (width * height) * 2;
|
||||||
|
texturemem = (u8 *) memalign(32, texturesize);
|
||||||
|
|
||||||
|
memset(texturemem, 0, texturesize);
|
||||||
|
|
||||||
|
/*** Setup for first call to scaler ***/
|
||||||
|
vwidth = vheight = -1;
|
||||||
|
}
|
||||||
|
/****************************************************************************
|
||||||
|
* GX_Render
|
||||||
|
*
|
||||||
|
* Pass in a buffer, width and height to update as a tiled RGB565 texture
|
||||||
|
****************************************************************************/
|
||||||
|
void GX_Render(int width, int height, u8 * buffer, int pitch)
|
||||||
|
{
|
||||||
|
int h, w;
|
||||||
|
long long int *dst = (long long int *) texturemem;
|
||||||
|
long long int *src1 = (long long int *) buffer;
|
||||||
|
long long int *src2 = (long long int *) (buffer + pitch);
|
||||||
|
long long int *src3 = (long long int *) (buffer + (pitch * 2));
|
||||||
|
long long int *src4 = (long long int *) (buffer + (pitch * 3));
|
||||||
|
int rowpitch = (pitch >> 3) * 3;
|
||||||
|
int rowadjust = ( pitch % 8 ) * 4;
|
||||||
|
char *ra = NULL;
|
||||||
|
|
||||||
|
vwidth = width;
|
||||||
|
vheight = height;
|
||||||
|
|
||||||
|
whichfb ^= 1;
|
||||||
|
|
||||||
|
if ((oldvheight != vheight) || (oldvwidth != vwidth))
|
||||||
|
{
|
||||||
|
/** Update scaling **/
|
||||||
|
oldvwidth = vwidth;
|
||||||
|
oldvheight = vheight;
|
||||||
|
draw_init();
|
||||||
|
memset(&view, 0, sizeof(Mtx));
|
||||||
|
guLookAt(view, &cam.pos, &cam.up, &cam.view);
|
||||||
|
GX_SetViewport(0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
GX_InvVtxCache();
|
||||||
|
GX_InvalidateTexAll();
|
||||||
|
GX_SetTevOp(GX_TEVSTAGE0, GX_DECAL);
|
||||||
|
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
|
||||||
|
|
||||||
|
for (h = 0; h < vheight; h += 4)
|
||||||
|
{
|
||||||
|
for (w = 0; w < (vwidth >> 2); w++)
|
||||||
|
{
|
||||||
|
*dst++ = *src1++;
|
||||||
|
*dst++ = *src2++;
|
||||||
|
*dst++ = *src3++;
|
||||||
|
*dst++ = *src4++;
|
||||||
|
}
|
||||||
|
|
||||||
|
src1 += rowpitch;
|
||||||
|
src2 += rowpitch;
|
||||||
|
src3 += rowpitch;
|
||||||
|
src4 += rowpitch;
|
||||||
|
|
||||||
|
if ( rowadjust )
|
||||||
|
{
|
||||||
|
ra = (char *)src1;
|
||||||
|
src1 = (long long int *)(ra + rowadjust);
|
||||||
|
ra = (char *)src2;
|
||||||
|
src2 = (long long int *)(ra + rowadjust);
|
||||||
|
ra = (char *)src3;
|
||||||
|
src3 = (long long int *)(ra + rowadjust);
|
||||||
|
ra = (char *)src4;
|
||||||
|
src4 = (long long int *)(ra + rowadjust);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DCFlushRange(texturemem, texturesize);
|
||||||
|
|
||||||
|
GX_SetNumChans(1);
|
||||||
|
GX_LoadTexObj(&texobj, GX_TEXMAP0);
|
||||||
|
|
||||||
|
draw_square(view);
|
||||||
|
|
||||||
|
GX_DrawDone();
|
||||||
|
|
||||||
|
GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
|
||||||
|
GX_SetColorUpdate(GX_TRUE);
|
||||||
|
GX_CopyDisp(xfb[whichfb], GX_TRUE);
|
||||||
|
GX_Flush();
|
||||||
|
|
||||||
|
VIDEO_SetNextFramebuffer(xfb[whichfb]);
|
||||||
|
VIDEO_Flush();
|
||||||
|
//VIDEO_WaitVSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Drawing screen
|
||||||
|
***************************************************************************/
|
||||||
|
void
|
||||||
|
clearscreen (int c)
|
||||||
|
{
|
||||||
|
int colour = COLOR_WHITE;
|
||||||
|
|
||||||
|
whichfb ^= 1;
|
||||||
|
VIDEO_ClearFrameBuffer (vmode, xfb[whichfb], colour);
|
||||||
|
#ifdef HW_RVL
|
||||||
|
// on wii copy from memory
|
||||||
|
//memcpy ((char *) xfb[whichfb], (char *) backdrop, 640 * screenheight * 2);
|
||||||
|
#else
|
||||||
|
// on gc copy from aram
|
||||||
|
//ARAMFetch ((char *) xfb[whichfb], (char *) AR_BACKDROP, 640 * screenheight * 2);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
showscreen ()
|
||||||
|
{
|
||||||
|
copynow = GX_FALSE;
|
||||||
|
VIDEO_SetNextFramebuffer (xfb[whichfb]);
|
||||||
|
VIDEO_Flush ();
|
||||||
|
VIDEO_WaitVSync ();
|
||||||
|
}
|
@ -23,7 +23,10 @@
|
|||||||
#ifndef __GXHDR__
|
#ifndef __GXHDR__
|
||||||
#define __GXHDR__
|
#define __GXHDR__
|
||||||
|
|
||||||
void GX_Start(int width, int height, int haspect, int vaspect);
|
void InitialiseVideo ();
|
||||||
|
void GX_Render_Init(int width, int height, int haspect, int vaspect);
|
||||||
void GX_Render(int width, int height, u8 * buffer, int pitch);
|
void GX_Render(int width, int height, u8 * buffer, int pitch);
|
||||||
|
void clearscreen (int colour = COLOR_BLACK);
|
||||||
|
void showscreen ();
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,4 +1,4 @@
|
|||||||
#ifdef WII_BUILD
|
#ifdef HW_RVL
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* VisualBoyAdvance 1.7.2
|
* VisualBoyAdvance 1.7.2
|
||||||
*
|
*
|
||||||
@ -17,6 +17,8 @@
|
|||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "Port.h"
|
#include "Port.h"
|
||||||
|
|
||||||
|
#include "menudraw.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "tbtime.h"
|
#include "tbtime.h"
|
||||||
}
|
}
|
||||||
@ -47,7 +49,7 @@ static char romfilename[1024];
|
|||||||
VRAM + OAM + PIX + IOMEM )
|
VRAM + OAM + PIX + IOMEM )
|
||||||
|
|
||||||
extern void CPUUpdateRenderBuffers(bool force);
|
extern void CPUUpdateRenderBuffers(bool force);
|
||||||
extern void MENU_DrawString( int x, int y, char *msg, int style );
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* VMAllocGBA
|
* VMAllocGBA
|
||||||
*
|
*
|
||||||
@ -103,14 +105,14 @@ int VMCPULoadROM( char *filename )
|
|||||||
|
|
||||||
GBAROMSize = 0;
|
GBAROMSize = 0;
|
||||||
|
|
||||||
/*sprintf(temp,"Filename %s\n", filename);
|
sprintf(temp,"Filename %s\n", filename);
|
||||||
MENU_DrawString( -1, 230,temp , 1 );
|
//WaitPrompt(temp);
|
||||||
*/
|
|
||||||
romfile = gen_fopen(filename, "rb");
|
romfile = gen_fopen(filename, "rb");
|
||||||
if ( romfile == NULL )
|
if ( romfile == NULL )
|
||||||
{
|
{
|
||||||
MENU_DrawString( -1, 400,"Error opening file!" , 1 );
|
WaitPrompt((char*) "Error opening file!");
|
||||||
while(1);
|
//while(1);
|
||||||
VMClose();
|
VMClose();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -120,7 +122,7 @@ int VMCPULoadROM( char *filename )
|
|||||||
fseek(romfile, 0, SEEK_SET);
|
fseek(romfile, 0, SEEK_SET);
|
||||||
|
|
||||||
sprintf(temp,"ROM Size %dMb (%dMBit)", GBAROMSize/1024/1024,(GBAROMSize*8)/1024/1024);
|
sprintf(temp,"ROM Size %dMb (%dMBit)", GBAROMSize/1024/1024,(GBAROMSize*8)/1024/1024);
|
||||||
MENU_DrawString( -1, 150,temp , 1 );
|
//WaitPrompt(temp);
|
||||||
|
|
||||||
rom = (u8 *)MEM2Storage;
|
rom = (u8 *)MEM2Storage;
|
||||||
|
|
||||||
@ -129,7 +131,7 @@ int VMCPULoadROM( char *filename )
|
|||||||
|
|
||||||
if ( (u32)res != GBAROMSize )
|
if ( (u32)res != GBAROMSize )
|
||||||
{
|
{
|
||||||
MENU_DrawString( -1, 400,"Error reading file!" , 1 );
|
WaitPrompt((char*) "Error reading file!");
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
strcpy( romfilename, filename );
|
strcpy( romfilename, filename );
|
||||||
@ -193,8 +195,7 @@ u8 VMRead8( u32 address )
|
|||||||
return (u8)rom[address];
|
return (u8)rom[address];
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#else
|
||||||
#ifdef GC_BUILD
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* VisualBoyAdvance 1.7.2
|
* VisualBoyAdvance 1.7.2
|
||||||
*
|
*
|
||||||
@ -211,6 +212,8 @@ u8 VMRead8( u32 address )
|
|||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "Port.h"
|
#include "Port.h"
|
||||||
|
|
||||||
|
#include "menudraw.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "tbtime.h"
|
#include "tbtime.h"
|
||||||
}
|
}
|
||||||
@ -376,6 +379,7 @@ static void VMClose( void )
|
|||||||
int VMCPULoadROM( char *filename )
|
int VMCPULoadROM( char *filename )
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
char msg[512];
|
||||||
|
|
||||||
/** Fix VM **/
|
/** Fix VM **/
|
||||||
VMClose();
|
VMClose();
|
||||||
@ -389,7 +393,7 @@ int VMCPULoadROM( char *filename )
|
|||||||
romfile = gen_fopen(filename, "rb");
|
romfile = gen_fopen(filename, "rb");
|
||||||
if ( romfile == NULL )
|
if ( romfile == NULL )
|
||||||
{
|
{
|
||||||
printf("Error opening file!\n");
|
WaitPrompt((char*) "Error opening file!");
|
||||||
while(1);
|
while(1);
|
||||||
VMClose();
|
VMClose();
|
||||||
return 0;
|
return 0;
|
||||||
@ -401,7 +405,8 @@ int VMCPULoadROM( char *filename )
|
|||||||
res = gen_fread(rom, 1, (1 << VMSHIFTBITS), romfile);
|
res = gen_fread(rom, 1, (1 << VMSHIFTBITS), romfile);
|
||||||
if ( res != (1 << VMSHIFTBITS ) )
|
if ( res != (1 << VMSHIFTBITS ) )
|
||||||
{
|
{
|
||||||
printf("Error reading file! %i \n",res);
|
sprintf(msg, "Error reading file! %i \n",res);
|
||||||
|
WaitPrompt(msg);
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,13 +436,15 @@ static void VMNewPage( int pageid )
|
|||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
tb_t start,end;
|
tb_t start,end;
|
||||||
|
char msg[512];
|
||||||
|
|
||||||
mftb(&start);
|
mftb(&start);
|
||||||
|
|
||||||
res = gen_fseek( romfile, pageid << VMSHIFTBITS, SEEK_SET );
|
res = gen_fseek( romfile, pageid << VMSHIFTBITS, SEEK_SET );
|
||||||
if ( ! res )
|
if ( ! res )
|
||||||
{
|
{
|
||||||
printf("Seek error! - Offset %08x %d\n", pageid << VMSHIFTBITS, res);
|
sprintf(msg, "Seek error! - Offset %08x %d\n", pageid << VMSHIFTBITS, res);
|
||||||
|
WaitPrompt(msg);
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,7 +453,8 @@ static void VMNewPage( int pageid )
|
|||||||
res = gen_fread( vmpage[pageid].pageptr, 1, 1 << VMSHIFTBITS, romfile );
|
res = gen_fread( vmpage[pageid].pageptr, 1, 1 << VMSHIFTBITS, romfile );
|
||||||
if ( res != ( 1 << VMSHIFTBITS ) )
|
if ( res != ( 1 << VMSHIFTBITS ) )
|
||||||
{
|
{
|
||||||
printf("Error reading! %d bytes only\n", res);
|
sprintf(msg, "Error reading! %d bytes only\n", res);
|
||||||
|
WaitPrompt(msg);
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,6 +489,7 @@ u32 VMRead32( u32 address )
|
|||||||
{
|
{
|
||||||
int pageid;
|
int pageid;
|
||||||
u32 badaddress;
|
u32 badaddress;
|
||||||
|
char msg[512];
|
||||||
//printf("VM32 : Request %08x\n", address);
|
//printf("VM32 : Request %08x\n", address);
|
||||||
|
|
||||||
if ( address >= GBAROMSize )
|
if ( address >= GBAROMSize )
|
||||||
@ -504,8 +513,9 @@ u32 VMRead32( u32 address )
|
|||||||
return READ32LE( vmpage[pageid].pageptr + ( address & VMSHIFTMASK ) );
|
return READ32LE( vmpage[pageid].pageptr + ( address & VMSHIFTMASK ) );
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("VM32 : Unknown page type! (%d) [%d]\n", vmpage[pageid].pagetype, pageid);
|
sprintf(msg, "VM32 : Unknown page type! (%d) [%d]", vmpage[pageid].pagetype, pageid);
|
||||||
while(1);
|
WaitPrompt(msg);
|
||||||
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Can never get here ... but stops gcc bitchin' */
|
/* Can never get here ... but stops gcc bitchin' */
|
||||||
@ -543,7 +553,7 @@ u16 VMRead16( u32 address )
|
|||||||
return READ16LE( vmpage[pageid].pageptr + ( address & VMSHIFTMASK ) );
|
return READ16LE( vmpage[pageid].pageptr + ( address & VMSHIFTMASK ) );
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("VM16 : Unknown page type!\n");
|
WaitPrompt((char*) "VM16 : Unknown page type!");
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,7 +592,7 @@ u8 VMRead8( u32 address )
|
|||||||
return (u8)vmpage[pageid].pageptr[ (address & VMSHIFTMASK) ];
|
return (u8)vmpage[pageid].pageptr[ (address & VMSHIFTMASK) ];
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("VM8 : Unknown page type!\n");
|
WaitPrompt((char*) "VM8 : Unknown page type!");
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user