structure/system overhaul - partially working

This commit is contained in:
dborth 2008-09-16 05:42:21 +00:00
parent e7dc70438e
commit fc4c229edc
41 changed files with 6439 additions and 1721 deletions

View File

@ -16,6 +16,8 @@ static int tail = 0;
static u8 mixerdata[MIXBUFFSIZE];
#define MIXERMASK ((MIXBUFFSIZE >> 2) - 1)
static u8 soundbuffer[3200] ATTRIBUTE_ALIGN(32);
/****************************************************************************
* MIXER_AddSamples
*
@ -71,3 +73,29 @@ int MIXER_GetSamples( u8 *dstbuffer, int maxlen )
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();
}

View File

@ -8,6 +8,8 @@
void MIXER_AddSamples( u8 *sampledata, int len );
int MIXER_GetSamples( u8 *dstbuffer, int maxlen );
void StopAudio();
void StartAudio();
void InitialiseSound();
#endif

117
source/ngc/button_mapping.c Normal file
View 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, ""}
}
}
};

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,12 @@
# Fonts
.rodata
.globl fontface
.balign 32
fontface:
.incbin "../source/ngc/ttf/font.ttf"
.globl fontsize
fontsize: .long 28736

View File

@ -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;
}

View File

@ -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
View 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
View 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

View File

@ -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
View 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
View 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

View File

@ -1 +0,0 @@

419
source/ngc/memcardop.cpp Normal file
View 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
View 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

View File

@ -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 <stdlib.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>
extern int isClassicAvailable;
extern int isWiimoteAvailable;
extern void setup_controllers();
#ifdef WII_DVD
extern "C" {
#include <di/di.h>
}
#endif
/****************************************************************************
* MENU_GetLoadFile
*
* Returns the filename of the selected file
***************************************************************************/
char *MENU_GetLoadFile( char *whichdir )
#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"
{
int count;
char *p = NULL;
int quit = 0;
int redraw = 1;
int current = 0;
int offset = 0;
u16 buttons;
int do_DOWN = 0;
int do_UP = 0;
int do_A = 0;
count = gen_getdir( whichdir );
if ( count == 0 )
{
printf("No ROM files in %s\n", whichdir);
while(1);
}
#ifdef WII_BUILD
setup_controllers();
#endif
if ( count == 1 )
return (char*)direntries[0];
/* Do menu */
while ( !quit )
{
if ( redraw )
{
whichfb ^= 1;
VIDEO_ClearFrameBuffer(vmode, xfb[whichfb], COLOR_BLACK);
MENU_Draw( count, current, offset );
VIDEO_SetNextFramebuffer(xfb[whichfb]);
VIDEO_Flush();
VIDEO_WaitVSync();
redraw = 0;
}
#ifdef WII_BUILD
WPAD_ScanPads();
WPADData *wpad;
wpad = WPAD_Data(0);
int b = wpad->exp.classic.btns;
unsigned short b1 = wpad->btns_d;
if (isClassicAvailable){
if (b & CLASSIC_CTRL_BUTTON_DOWN){
do_DOWN = 1;
do{WPAD_ScanPads(); wpad = WPAD_Data(0);}
while (WPAD_ButtonsHeld(0));
}
else if (b & CLASSIC_CTRL_BUTTON_UP){
do_UP = 1;
do{WPAD_ScanPads(); wpad = WPAD_Data(0);}
while (WPAD_ButtonsHeld(0));
}
else if (b & CLASSIC_CTRL_BUTTON_A){
do_A = 1;
do{WPAD_ScanPads(); wpad = WPAD_Data(0);}
while (WPAD_ButtonsHeld(0));
}
}
if (isWiimoteAvailable){
if (b1 & WPAD_BUTTON_LEFT){
do_DOWN = 1;
do{WPAD_ScanPads(); wpad = WPAD_Data(0);}
while (WPAD_ButtonsHeld(0));
}
else if (b1 & WPAD_BUTTON_RIGHT){
do_UP = 1;
do{WPAD_ScanPads(); wpad = WPAD_Data(0);}
while (WPAD_ButtonsHeld(0));
}
else if (b1 & WPAD_BUTTON_2){
do_A = 1;
do{WPAD_ScanPads(); wpad = WPAD_Data(0);}
while (WPAD_ButtonsHeld(0));
}
}
#endif
buttons = PAD_ButtonsDown(0);
if(buttons & PAD_BUTTON_DOWN)
do_DOWN = 1;
else if(buttons & PAD_BUTTON_UP)
do_UP = 1;
else if(buttons & PAD_BUTTON_A)
do_A = 1;
if (do_DOWN)
{
do_DOWN=0;
current++;
if ( current == count )
current = 0;
if ( ( current % PAGE_SIZE ) == 0 )
offset = current;
redraw = 1;
}
else
{
if ( do_UP )
{
do_UP=0;
current--;
if ( current < 0 ) current = count - 1;
offset = ( current / PAGE_SIZE ) * PAGE_SIZE;
redraw = 1;
}
else
{
if ( do_A )
{
do_A=0;
quit = 1;
p = (char*)direntries[current];
}
}
}
}
whichfb ^= 1;
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;
#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)
/****************************************************************************
* Reboot / Exit
***************************************************************************/
#ifndef HW_RVL
#define PSOSDLOADID 0x7c6000a6
int *psoid = (int *) 0x80001800;
void (*PSOReload) () = (void (*)()) 0x80001800;
#endif
void Reboot()
{
#ifdef HW_RVL
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
#else
#define SOFTRESET_ADR ((volatile u32*)0xCC003024)
*SOFTRESET_ADR = 0x00000000;
#endif
}
/****************************************************************************
* Load Manager
***************************************************************************/
int
LoadManager ()
{
int loadROM = OpenROM(GCSettings.LoadMethod);
/***
* check for autoloadsram / freeze
***/
if ( loadROM == 1 ) // if ROM was loaded, load the SRAM & settings
{
//if ( GCSettings.AutoLoad == 1 )
// LoadSRAM(GCSettings.SaveMethod, SILENT);
//else if ( GCSettings.AutoLoad == 2 )
// NGCUnfreezeGame (GCSettings.SaveMethod, SILENT);
// setup cheats
//SetupCheats();
}
return loadROM;
}
/****************************************************************************
* 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)
{
// 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)
{
case 0:
GCSettings.LoadMethod ++;
break;
case 1:
break;
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;
}
}
menu = oldmenu;
}
/****************************************************************************
* Game Options Menu
***************************************************************************/
int
GameMenu ()
{
int gamemenuCount = 7;
char gamemenu[][50] = {
"Return to Game",
"Reset Game",
"Load SRAM", "Save SRAM",
"Load Game Snapshot", "Save Game Snapshot",
"Back to Main Menu"
};
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';
}
ret = RunMenu (gamemenu, gamemenuCount, (char*)"Game Menu");
switch (ret)
{
case 0: // Return to Game
quit = retval = 1;
break;
case 1: // Reset Game
emulator.emuReset();
quit = retval = 1;
break;
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
) VIDEO_WaitVSync(); // button 'debounce'
while (pressed == 0)
{
VIDEO_WaitVSync();
// get input based on controller type
if (ctrlr_type == CTRLR_GCPAD)
{
pressed = PAD_ButtonsHeld (0);
gc_px = PAD_SubStickX (0);
}
#ifdef HW_RVL
else
{
// 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
{
for (k=0; k<7-strlen(ctrlr_def[ctrlr_type].map[j].name) ;k++) strcat(temp, " "); // add whitespace padding to align text
strncat (temp, ctrlr_def[ctrlr_type].map[j].name, 6); // update button map display
}
else
strcat (temp, (char*)"---"); // otherwise, button is 'unmapped'
strncpy (cfg_btns_menu[i], temp, 19); // move back updated information
}
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;
}
}
menu = oldmenu;
}
/****************************************************************************
* 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View File

@ -3,10 +3,9 @@
****************************************************************************/
#ifndef __TMBINCTIMER__
#define __TMBINCTIMER__
#ifdef WII_BUILD
#ifdef HW_RVL
#define TB_CLOCK 60750000 //WII
#endif
#ifdef GC_BUILD
#else
#define TB_CLOCK 40500000
#endif
#define mftb(rval) ({unsigned long u; do { \

107
source/ngc/vba.cpp Normal file
View 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
View 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

View File

@ -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
View 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
View 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
View 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
View 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
View 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 ();
}

View File

@ -23,7 +23,10 @@
#ifndef __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 clearscreen (int colour = COLOR_BLACK);
void showscreen ();
#endif

View File

@ -1,4 +1,4 @@
#ifdef WII_BUILD
#ifdef HW_RVL
/****************************************************************************
* VisualBoyAdvance 1.7.2
*
@ -17,6 +17,8 @@
#include "Util.h"
#include "Port.h"
#include "menudraw.h"
extern "C" {
#include "tbtime.h"
}
@ -47,7 +49,7 @@ static char romfilename[1024];
VRAM + OAM + PIX + IOMEM )
extern void CPUUpdateRenderBuffers(bool force);
extern void MENU_DrawString( int x, int y, char *msg, int style );
/****************************************************************************
* VMAllocGBA
*
@ -103,14 +105,14 @@ int VMCPULoadROM( char *filename )
GBAROMSize = 0;
/*sprintf(temp,"Filename %s\n", filename);
MENU_DrawString( -1, 230,temp , 1 );
*/
sprintf(temp,"Filename %s\n", filename);
//WaitPrompt(temp);
romfile = gen_fopen(filename, "rb");
if ( romfile == NULL )
{
MENU_DrawString( -1, 400,"Error opening file!" , 1 );
while(1);
WaitPrompt((char*) "Error opening file!");
//while(1);
VMClose();
return 0;
}
@ -120,7 +122,7 @@ int VMCPULoadROM( char *filename )
fseek(romfile, 0, SEEK_SET);
sprintf(temp,"ROM Size %dMb (%dMBit)", GBAROMSize/1024/1024,(GBAROMSize*8)/1024/1024);
MENU_DrawString( -1, 150,temp , 1 );
//WaitPrompt(temp);
rom = (u8 *)MEM2Storage;
@ -129,7 +131,7 @@ int VMCPULoadROM( char *filename )
if ( (u32)res != GBAROMSize )
{
MENU_DrawString( -1, 400,"Error reading file!" , 1 );
WaitPrompt((char*) "Error reading file!");
while(1);
}
strcpy( romfilename, filename );
@ -193,8 +195,7 @@ u8 VMRead8( u32 address )
return (u8)rom[address];
}
#endif
#ifdef GC_BUILD
#else
/****************************************************************************
* VisualBoyAdvance 1.7.2
*
@ -211,6 +212,8 @@ u8 VMRead8( u32 address )
#include "Util.h"
#include "Port.h"
#include "menudraw.h"
extern "C" {
#include "tbtime.h"
}
@ -376,6 +379,7 @@ static void VMClose( void )
int VMCPULoadROM( char *filename )
{
int res;
char msg[512];
/** Fix VM **/
VMClose();
@ -389,7 +393,7 @@ int VMCPULoadROM( char *filename )
romfile = gen_fopen(filename, "rb");
if ( romfile == NULL )
{
printf("Error opening file!\n");
WaitPrompt((char*) "Error opening file!");
while(1);
VMClose();
return 0;
@ -401,7 +405,8 @@ int VMCPULoadROM( char *filename )
res = gen_fread(rom, 1, (1 << VMSHIFTBITS), romfile);
if ( res != (1 << VMSHIFTBITS ) )
{
printf("Error reading file! %i \n",res);
sprintf(msg, "Error reading file! %i \n",res);
WaitPrompt(msg);
while(1);
}
@ -431,13 +436,15 @@ static void VMNewPage( int pageid )
{
int res;
tb_t start,end;
char msg[512];
mftb(&start);
res = gen_fseek( romfile, pageid << VMSHIFTBITS, SEEK_SET );
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);
}
@ -446,7 +453,8 @@ static void VMNewPage( int pageid )
res = gen_fread( vmpage[pageid].pageptr, 1, 1 << VMSHIFTBITS, romfile );
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);
}
@ -481,6 +489,7 @@ u32 VMRead32( u32 address )
{
int pageid;
u32 badaddress;
char msg[512];
//printf("VM32 : Request %08x\n", address);
if ( address >= GBAROMSize )
@ -504,7 +513,8 @@ u32 VMRead32( u32 address )
return READ32LE( vmpage[pageid].pageptr + ( address & VMSHIFTMASK ) );
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);
WaitPrompt(msg);
while(1);
}
@ -543,7 +553,7 @@ u16 VMRead16( u32 address )
return READ16LE( vmpage[pageid].pageptr + ( address & VMSHIFTMASK ) );
default:
printf("VM16 : Unknown page type!\n");
WaitPrompt((char*) "VM16 : Unknown page type!");
while(1);
}
@ -582,7 +592,7 @@ u8 VMRead8( u32 address )
return (u8)vmpage[pageid].pageptr[ (address & VMSHIFTMASK) ];
default:
printf("VM8 : Unknown page type!\n");
WaitPrompt((char*) "VM8 : Unknown page type!");
while(1);
}