This commit is contained in:
dborth 2008-09-02 01:57:21 +00:00
parent fb1190b4fd
commit 7c6d1b77a2
41 changed files with 45698 additions and 33 deletions

23
Makefile Normal file
View File

@ -0,0 +1,23 @@
.PHONY = all wii gc wii-clean gc-clean wii-run gc-run
all: wii gc
clean: wii-clean gc-clean
wii:
$(MAKE) -f Makefile.wii
wii-clean:
$(MAKE) -f Makefile.wii clean
wii-run:
$(MAKE) -f Makefile.wii run
gc:
$(MAKE) -f Makefile.gc
gc-clean:
$(MAKE) -f Makefile.gc clean
gc-run:
$(MAKE) -f Makefile.gc run

View File

@ -15,17 +15,17 @@ include $(DEVKITPPC)/gamecube_rules
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := fceu_gc
BUILD := build
#SOURCES := source source/sz source/boards source/linux source/linux/bits source/linux/gnu source/palettes source/fir source/input source/rom source/mappers source/mbshare source/drivers source/drivers/common source/drivers/gamecube source/iplfont
SOURCES := source source/boards source/mappers source/input \
source/mbshare source/drivers/common \
source/drivers/gamecube source/roms \
source/iplfont source/sz
TARGET := fceugx_gc
TARGETDIR := executables
BUILD := build_gc
SOURCES := source/fceultra \
source/fceultra/boards source/fceultra/mappers source/fceultra/input \
source/fceultra/mbshare source/fceultra/drivers/common source/fceultra/roms \
source/ngc
DATA := data
INCLUDES := source source/sz
INCLUDES := source/fceultra source/ngc
# Specify language in all capitals
# Supported languages: ENGLISH DUTCH
# Supported languages: ENGLISH
LANG := ENGLISH
#---------------------------------------------------------------------------------
@ -42,7 +42,7 @@ LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map -Wl,--cref
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -logc -lm -lz
LIBS := -lpng -lmxml -lbba -ltinysmb -lfat -lz -logc -lm -lfreetype
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
@ -57,7 +57,7 @@ LIBDIRS :=
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
@ -100,18 +100,20 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
-L$(LIBOGC_LIB)
export OUTPUT := $(CURDIR)/$(TARGET)
export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
@[ -d $(TARGETDIR) ] || mkdir -p $(TARGETDIR)
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.gc
@rm -fr $(OUTPUT).elf
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol source/tags
@rm -fr $(BUILD) $(OUTPUT).dol source/tags
#---------------------------------------------------------------------------------
run:

View File

@ -15,27 +15,25 @@ include $(DEVKITPPC)/wii_rules
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := fceu_wii
BUILD := build
#SOURCES := source source/sz source/boards source/linux source/linux/bits source/linux/gnu source/palettes source/fir source/input source/rom source/mappers source/mbshare source/drivers source/drivers/common source/drivers/gamecube source/iplfont
SOURCES := source source/boards source/mappers source/input \
source/mbshare source/drivers/common \
source/drivers/gamecube source/roms \
source/iplfont source/sz
TARGET := fceugx_wii
TARGETDIR := executables
BUILD := build_wii
SOURCES := source/fceultra \
source/fceultra/boards source/fceultra/mappers source/fceultra/input \
source/fceultra/mbshare source/fceultra/drivers/common source/fceultra/roms \
source/ngc
DATA := data
INCLUDES := source source/sz
INCLUDES := source/fceultra source/ngc
# Specify language in all capitals
# Supported languages: ENGLISH DUTCH
# Supported languages: ENGLISH
LANG := ENGLISH
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
#CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) -DFCEU_VERSION_NUMERIC=9812 -DNGC=1 -DZLIB -DBIG_ENDIAN -DHAVE_ASPRINTF=1 -DSTDC -D_SZ_ONE_DIRECTORY=1 -D_LZMA_IN_CB=1 -D_LZMA_OUT_READ
CFLAGS = -g -Os -Wall $(MACHDEP) $(INCLUDE) -DFCEU_VERSION_NUMERIC=9812 -DNGC=1 \
-DZLIB -DBIG_ENDIAN -DWORDS_BIGENDIAN -DHAVE_ASPRINTF=1 -DSTDC \
-D_SZ_ONE_DIRECTORY=1 -D_LZMA_IN_CB=1 -D_LZMA_OUT_READ \
-DWII_DVD -D_SZ_ONE_DIRECTORY=1 -D_LZMA_IN_CB=1 -D_LZMA_OUT_READ \
-DINTL_$(LANG)
CXXFLAGS = $(CFLAGS)
@ -44,7 +42,7 @@ LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map -Wl,--cref
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -ldb -lfat -logc -lm -lz
LIBS := -ldi -lpng -lmxml -lfat -lwiiuse -lz -lbte -logc -lm -lfreetype -ltinysmb
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
@ -59,7 +57,7 @@ LIBDIRS :=
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
@ -102,26 +100,28 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
-L$(LIBOGC_LIB)
export OUTPUT := $(CURDIR)/$(TARGET)
export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
@[ -d $(TARGETDIR) ] || mkdir -p $(TARGETDIR)
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.wii
@rm -fr $(OUTPUT).elf
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol source/tags
@rm -fr $(BUILD) $(OUTPUT).dol source/tags
#---------------------------------------------------------------------------------
run:
psoload $(TARGET).dol
wiiload $(TARGET).dol
#---------------------------------------------------------------------------------
reload:
psoload -r $(TARGET).dol
wiiload -r $(TARGET).dol
#---------------------------------------------------------------------------------

219
readme.txt Normal file
View File

@ -0,0 +1,219 @@
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
- FCE Ultra GX -
Version 2.0.0
(Under GPL License)
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
-=[ Explanation ]=-
FCE Ultra GX is a modified port of the FCE Ultra 0.98.12 Nintendo Entertainment
system for x86 (Windows/Linux) PC's. With it you can play NES games on your
Wii/GameCube. Version 2 is a complete rewrite based on code from the
SNES9x GX and Genesis Plus GX projects.
-=[ Features ]=-
* Wiimote, Nunchuk, Classic, and Gamecube controller support
* 1-2 Player Support
* Custom controller configurations
* SD, USB, DVD, SMB, GC Memory Card, and Zip support
* NES Compatibility Based on v0.98.12
* Sound Filters
* Graphics Filters (GX Chipset, Cheesy and 2x)
×—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬
|0O×øo· UPDATE HISTORY ·oø×O0|
`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨'
[What's New 2.0.0]
* Complete rewrite based on code from SNES9x GX and Genesis Plus GX
* Wiimote, Nunchuk, and Classic controller support
* Button mapping for all controller types
* Full support for SD, USB, DVD, GC Memory Card, and Zip files
* Game starts immediately after loading
* Load/save preference selector. ROMs, saves, and preferences are
saved/loaded according to these
* Preliminary Windows file share loading/saving (SMB) support on Wii:
You can input your network settings into FCEUGX.xml, or edit
fceuconfig.cpp from the source code and compile.
* 'Auto' settings for save/load - attempts to automatically determine
your load/save device(s) - SD, USB, Memory Card, DVD, SMB
* Preferences are now loaded and saved in XML format. You can open
FCEUGX.xml edit all settings, including some not available within
the program
* One makefile to make all versions
×—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬
|0O×øo· SETUP & INSTALLATION ·oø×O0|
`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨'
Unzip the archive. You will find the following folders inside:
apps Contains Homebrew Channel ready files
(see Homebrew Channel instructions below)
executables Contains Gamecube / Wii DOL files
(for loading from other methods)
fceu Contains the directory structure required for storing
roms and saves (see below)
----------------------------
Directory Structure Setup
----------------------------
By default, roms are loaded from "fceugx/roms/" and saves / preferences are
stored in "fceugx/saves/".
Therefore you should have the following folder structure at the root
of your load device (SD/USB/SMB):
fceugx/
roms/
saves/
cheats/
----------------------------
ROMS, Preferences, and Saves:
----------------------------
Wii
----------
On the Wii, you can load roms from SD card (Front SD or SD Gecko), USB, DVD,
or SMB share. Note that if you are using the Homebrew Channel, to load from
USB, DVD, or SMB you will first have to load FCEUGX from SD, and then set
your load method preference. To load roms from a Windows network share (SMB)
you will have to edit FCEUGX.xml on your SD card with your network settings,
or edit fceuconfig.cpp from the source code and compile. If you edit and compile
the source, you can use wiiload and the Homebrew Channel to load and play
FCEUGX completely over the network, without needing an SD card.
Gamecube
------------
You can load roms from DVD or SD card. If you create a bootable
DVD of FCEUGX you can put roms on the same DVD. You may save preferences and
game data to SD or Memory Card.
------------------------------
Loading / Running the Emulator:
------------------------------
Wii - Via Homebrew Channel:
--------------------
The most popular method of running homebrew on the Wii is through the Homebrew
Channel. If you already have the channel installed, just copy over the apps folder
included in the archive into the root of your SD card.
Remember to also create the fceugx directory structure required. See above.
If you haven't installed the Homebrew Channel yet, read about how to here:
http://hbc.hackmii.com/
Gamecube:
---------
You can load FCEUGX via sdload and an SD card in slot A, or by streaming
it to your Gamecube, or by booting a bootable DVD with FCEUGX on it.
This document doesn't cover how to do any of that. A good source for information
on these topics is the tehskeen forums: http://www.tehskeen.com/forums/
-=[ Supported Mappers ]=-
Mappers are the way the Nintendo handles switching from ROM/VROM so the more
that are supported the more games will work.
000 . 112 . 113 . 114 . 117 . 15 . 151 . 16 . 17 . 18 . 180 . 182 . 184 . 187
189 . 193 . 200 . 201 . 202 . 203 . 208 . 21 . 22 . 225 . 226 . 227 . 228 . 229
23 . 230 . 231 . 232 . 234 . 235 . 240 . 241 . 242 . 244 . 246 . 248 . 24 . 26
25 . 255 . 32 . 33 . 40 . 41 . 42 . 43 . 46 . 50 . 51 . 57 . 58 . 59
6 . 60 . 61 . 62 . 65 . 67 . 68 . 69 . 71 . 72 . 73 . 75 . 76 . 77
79 . 8 . 80 . 82 . 83 . 85 . 86 . 88 . 89 . 91 . 92 . 95 . 97 . 99
-[ Emulator Options ]-
Screen Scaler - How to scale the screen: GX, Cheesy or 2x
Palette - The colors used while viewing the game:
Default . loopy . quor . chris . matt
pasofami . crashman . mess . zaphod-cv
zaphod-smb . vs-drmar . vs-cv . vs-smb
Timing - NTSC or PAL (Depends if you're running a PAL or NTSC game)
×—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬
|0O×øo· UPDATE HISTORY (1.0.x) ·oø×O0|
`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨'
What's new [20080331]
+[Askot]
- Fixed/changed SDCARD slot selection for searching roms, at
start you will be prompted for this option.
- Code cleanup.
+[dsbomb]
- Added Wii mode support.
- Give a "Bad cartridge" error instead of locking up.
- Joystick fixes due to libogc r14's changed stick values
- Rearranged menu to make more sense, and consistent with Snes9x
- Add "Reboot" menu option
- Removed "." directory from SD card listing, it's pointless
- Expand DVD reading to DVD9 size (once DVDs are working again)
- Added option to go back a menu by pressing B.
What's new? Askot [20080326]
- Added saving state in SD Card (State files will be saved in root of SDCARD).
*Note: I can't make it work to save in root:\fceu\saves, so help needed.
- Added SDCARD slot selection for searching roms, meaning, you can search roms
from SDCARD SLOT A & SLOT B (Beta, meaning, buggy, but works).
- For standarization, you must create folders root:\fceu\roms to read NES
roms files from SDCARD.
- Added C-Left to call Menu.
- Reading files from SD Card it's faster, now they're called from cache
after first reading.
- Menu in saving STATE file changed to choose SLOT, DEVICE, Save STATE,
Load STATE, Return to previous.
- Added option PSO/SD Reload to menu, still works (START+B+X)
- Modified controls when going into the rom selection menu (DVD or
SDCARD):
+ Use B to quit selection list.
+ Use L/R triggrers or Pad Left/Right to go down/up one full page.
- Some menu rearrangment and a little of sourcecode cleanup:
+ Everytime you pressed B button on any option, playgame started, not anymore
until you select Play Game option.
What's new? asako [20070831]
- modify mmc3 code for Chinese pirated rom
- add some Chinese pirated rom mappers
What's new? _svpe_ [20070607]
- Wii support (PAL50 fix, 1.35GiB restriction removed)
- 7zip ROM loading support from the DVD (not from a SD card!!)
- dvd_read fix (the read data was always copied to readbuffer instead of *dst)
- slower file selection when using the D-Pad (I didn't like the selection to go
as fast as in the latest release)
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
-=[ Credits ]=-
GameCube/Wii Port v2.x Tantric
GameCube/Wii Port v1.0.9 askot & dsbomb
GameCube Port v1.0.8 SoftDev
FCE Ultra Xodnizel
Original FCE BERO
libogc Shagkur & wintermute
Testing tehskeen users
And many others who have contributed over the years!
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
FCEUGX Web Site
http://code.google.com/p/fceugc
TehSkeen Support Forums
http://www.tehskeen.net
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤

119
source/ngc/button_mapping.c Normal file
View File

@ -0,0 +1,119 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
* 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,40 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
* 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

38
source/ngc/common.h Normal file
View File

@ -0,0 +1,38 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* common.h
*
* Common module
****************************************************************************/
#include "driver.h"
#include "drivers/common/config.h"
/* Message logging(non-netplay messages, usually) for all. */
extern int NoWaiting;
extern FCEUGI *GI;
void DSMFix(unsigned int msg);
void StopSound(void);
extern int eoptions;
#define EO_BGRUN 1
#define EO_CPALETTE 4
#define EO_NOSPRLIM 8
#define EO_FSAFTERLOAD 32
#define EO_FOAFTERSTART 64
#define EO_NOTHROTTLE 128
#define EO_CLIPSIDES 256
#define EO_SNAPNAME 512
#define EO_HIDEMENU 2048
#define EO_HIGHPRIO 4096
#define EO_FORCEASPECT 8192
#define EO_FORCEISCALE 16384
#define EO_NOFOURSCORE 32768
extern unsigned char * nesromptr;

547
source/ngc/dvd.c Normal file
View File

@ -0,0 +1,547 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* dvd.c
*
* DVD loading routines
****************************************************************************/
#include <gccore.h>
#include <ogcsys.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WII_DVD
#include <di/di.h>
#endif
#include "menudraw.h"
#include "gcunzip.h"
extern bool isWii;
extern int offset;
extern int selection;
extern FILEENTRIES filelist[MAXFILES];
extern int maxfiles;
u64 dvddir = 0;
u64 dvdrootdir = 0;
int dvddirlength = 0;
#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);
if(offset < 0x57057C00 || (isWii == true && offset < 0x118244F00LL)) // don't read past the end of the DVD
{
#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])
{
int i;
for (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 DoSwitchDVDFolder(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 DoSwitchDVDFolder(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 DoSwitchDVDFolder(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 UnZipDVDFile (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);
}
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

22
source/ngc/dvd.h Normal file
View File

@ -0,0 +1,22 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* dvd.h
*
* DVD loading routines
****************************************************************************/
#ifndef _DVD_H_
#define _DVD_H_
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[]);
#endif

50
source/ngc/fceuconfig.c Normal file
View File

@ -0,0 +1,50 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* fceuconfig.c
*
* Configuration parameters
****************************************************************************/
#include <gccore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "fceuconfig.h"
struct SGCSettings GCSettings;
void
DefaultSettings ()
{
GCSettings.currpal = 0;
GCSettings.timing = 0;
GCSettings.FSDisable = 1;
GCSettings.slimit = 1;
GCSettings.screenscaler = 2;
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,"fceugx/roms"); // Path to game files
sprintf (GCSettings.SaveFolder,"fceugx/saves"); // Path to save files
sprintf (GCSettings.CheatFolder,"fceugx/cheats"); // Path to cheat files
GCSettings.AutoLoad = 0;
GCSettings.AutoSave = 0;
// default SMB settings
strncpy (GCSettings.smbip, "192.168.0.1", 15); // IP Address of share server
strncpy (GCSettings.smbuser, "Wiiuser", 19); // Your share user
strncpy (GCSettings.smbpwd, "password", 19); // Your share user password
strncpy (GCSettings.smbshare, "NES", 19); // Share name on server
GCSettings.gcip[0] = 0;
GCSettings.gwip[0] = 0;
GCSettings.mask[0] = 0;
GCSettings.smbsvid[0] = 0;
GCSettings.smbgcid[0] = 0;
}

61
source/ngc/fceuconfig.h Normal file
View File

@ -0,0 +1,61 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* fceuconfig.h
*
* Configuration parameters
****************************************************************************/
#ifndef _FCEUCONFIG_H_
#define _FCEUCONFIG_H_
void DefaultSettings ();
#define VERSIONNUM "001"
#define VERSIONSTR "FCEUGX 001"
#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;
int currpal;
int timing;
int FSDisable;
int slimit;
int screenscaler;
};
extern struct SGCSettings GCSettings;
#endif

193
source/ngc/fceugc.c Normal file
View File

@ -0,0 +1,193 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* fceugc.c
*
* This file controls overall program flow. Most things start and end here!
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <gctypes.h>
#include <ogc/system.h>
#include <fat.h>
#include <wiiuse/wpad.h>
#include "types.h"
#include "gcvideo.h"
#include "pad.h"
#include "fceuload.h"
#include "common.h"
#include "menudraw.h"
#include "menu.h"
#include "fceuconfig.h"
#include "preferences.h"
#ifdef WII_DVD
#include <di/di.h>
#endif
extern bool romLoaded;
bool isWii;
/* Some timing-related variables. */
static int fullscreen=0;
static int genie=0;
static int palyo=0;
static volatile int nofocus=0;
static volatile int userpause=0;
#define SO_FORCE8BIT 1
#define SO_SECONDARY 2
#define SO_GFOCUS 4
#define SO_D16VOL 8
#define GOO_DISABLESS 1 /* Disable screen saver when game is loaded. */
#define GOO_CONFIRMEXIT 2 /* Confirmation before exiting. */
#define GOO_POWERRESET 4 /* Confirm on power/reset. */
static int soundvolume=100;
static int soundquality=0;
static int soundo;
uint8 *xbsave=NULL;
int eoptions=EO_BGRUN | EO_FORCEISCALE;
extern int cleanSFMDATA();
extern void ResetNES(void);
extern void InitialiseSound();
extern void PlaySound( void *Buf, int samples );
long long basetime;
void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count);
int main(int argc, char *argv[])
{
#ifdef WII_DVD
DI_Init(); // first
#endif
int selectedMenu = -1;
#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
initDisplay();
/*** Initialise freetype ***/
if (FT_Init ())
{
printf ("Cannot initialise font subsystem!\n");
while (1);
}
InitialiseSound();
fatInitDefault();
#ifndef HW_RVL
DVD_Init();
#endif
/*** Minimal Emulation Loop ***/
if ( !FCEUI_Initialize() ) {
printf("Unable to initialize system\n");
return 1;
}
palyo=0;
FCEUI_SetVidSystem(palyo);
genie&=1;
FCEUI_SetGameGenie(genie);
fullscreen&=1;
soundo&=1;
FCEUI_SetSoundVolume(soundvolume);
FCEUI_SetSoundQuality(soundquality);
cleanSFMDATA();
GCMemROM();
romLoaded = false; // we start off with only the color test rom
// Set Defaults
DefaultSettings();
// Load preferences
if(!LoadPrefs(GCSettings.SaveMethod, SILENT))
{
WaitPrompt((char*) "Preferences reset - check settings!");
selectedMenu = 3; // change to preferences menu
}
// Go to main menu
MainMenu (selectedMenu);
while (1)
{
uint8 *gfx;
int32 *sound;
int32 ssize;
FCEUI_Emulate(&gfx, &sound, &ssize, 0);
xbsave = gfx;
FCEUD_Update(gfx, sound, ssize);
}
return 0;
}
/****************************************************************************
* FCEU Support Functions to be written
****************************************************************************/
/*** File Control ***/
FILE *FCEUD_UTF8fopen(const char *n, const char *m)
{
return(fopen(n,m));
}
/*** General Logging ***/
void FCEUD_PrintError(char *s)
{
}
void FCEUD_Message(char *text)
{
}
/*** VIDEO ***/
void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count)
{
PlaySound(Buffer, Count);
RenderFrame( (char *)XBuf, GCSettings.screenscaler );
GetJoy();
}
/*** Netplay ***/
int FCEUD_SendData(void *data, uint32 len)
{
return 1;
}
int FCEUD_RecvData(void *data, uint32 len)
{
return 0;
}
void FCEUD_NetworkClose(void)
{
}
void FCEUD_NetplayText(uint8 *text)
{
}

87
source/ngc/fceuload.c Normal file
View File

@ -0,0 +1,87 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* fceload.c
*
* NES Memory Load Game
*
* This performs the functions of LoadGame and iNESLoad from a single module
* Helper function for GameCube injected ROMS
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "types.h"
#include "git.h"
#include "driver.h"
#include "palette.h"
#include "fceu.h"
#include "sound.h"
#include "common.h"
#include "pad.h"
#include "menudraw.h"
unsigned char *nesromptr;
bool romLoaded = false;
extern FCEUGI *FCEUGameInfo;
extern int iNESMemLoad( char *rom );
extern unsigned char nesrom[];
#define SAMPLERATE 48000
int GCMemROM()
{
nesromptr = &nesrom[0];
ResetGameLoaded();
/*** Allocate and clear GameInfo ***/
FCEUGameInfo = malloc(sizeof(FCEUGI));
memset(FCEUGameInfo, 0, sizeof(FCEUGI));
/*** Set some default values ***/
FCEUGameInfo->soundchan = 1;
FCEUGameInfo->soundrate = SAMPLERATE;
FCEUGameInfo->name=0;
FCEUGameInfo->type=GIT_CART;
FCEUGameInfo->vidsys=GIV_USER;
FCEUGameInfo->input[0]=FCEUGameInfo->input[1]=-1;
FCEUGameInfo->inputfc=-1;
FCEUGameInfo->cspecial=0;
/*** Set internal sound information ***/
FCEUI_Sound(SAMPLERATE);
FCEUI_SetSoundQuality(0);
FCEUI_SetSoundVolume(100);
FCEUI_SetLowPass(0);
InitialisePads();
if ( iNESMemLoad( (char *)nesromptr ) )
{
FCEU_ResetVidSys();
PowerNES();
FCEU_ResetPalette();
FCEU_ResetMessages(); // Save state, status messages, etc.
SetSoundVariables();
romLoaded = true;
}
else
{
WaitPrompt("Invalid game file!");
romLoaded = false;
return 0;
}
return 1;
}

12
source/ngc/fceuload.h Normal file
View File

@ -0,0 +1,12 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* fceuload.h
*
* NES Memory Load Game
****************************************************************************/
int GCMemROM();

365
source/ngc/fceustate.c Normal file
View File

@ -0,0 +1,365 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* fceustate.c
*
* Memory Based Load/Save State Manager
*
* These are simply the state routines, brought together as GCxxxxx
* The original file I/O is replaced with Memory Read/Writes to the
* statebuffer below
****************************************************************************/
#include <gccore.h>
#include <string.h>
#include <malloc.h>
#include <fat.h>
#include "types.h"
#include "state.h"
#include "images/saveicon.h"
#include "fceuconfig.h"
#include "intl.h"
#include "menudraw.h"
#include "filesel.h"
#include "memcardop.h"
#include "fileop.h"
#include "smbop.h"
/*** External functions ***/
extern void FCEUPPU_SaveState(void);
extern void FCEUSND_SaveState(void);
extern void FlipByteOrder(uint8 *src, uint32 count);
extern void FCEUD_SetPalette(unsigned char index, unsigned char r, unsigned char g, unsigned char b);
extern void FCEU_ResetPalette(void);
extern void FCEUI_DisableSpriteLimitation( int a );
/*** External save structures ***/
extern SFORMAT SFCPU[];
extern SFORMAT SFCPUC[];
extern SFORMAT FCEUPPU_STATEINFO[];
extern SFORMAT FCEUCTRL_STATEINFO[];
extern SFORMAT FCEUSND_STATEINFO[];
extern SFORMAT SFMDATA[64];
extern u32 iNESGameCRC32;
#define RLSB 0x80000000
#define FILESIZEOFFSET 2116
int sboffset; /*** Used as a basic fileptr ***/
int mcversion = 0x981211;
extern unsigned char savebuffer[SAVEBUFFERSIZE];
extern char romFilename[];
/****************************************************************************
* Memory based file functions
****************************************************************************/
/*** Open a file ***/
void memopen() {
sboffset = 0;
memset(savebuffer, 0, sizeof(savebuffer));
}
/*** Close a file ***/
void memclose() {
sboffset = 0;
}
/*** Write to the file ***/
void memfwrite( void *buffer, int len ) {
if ( (sboffset + len ) > sizeof(savebuffer))
WaitPrompt("Buffer Exceeded");
if ( len > 0 ) {
memcpy(&savebuffer[sboffset], buffer, len );
sboffset += len;
}
}
/*** Read from a file ***/
void memfread( void *buffer, int len ) {
if ( ( sboffset + len ) > sizeof(savebuffer))
WaitPrompt("Buffer exceeded");
if ( len > 0 ) {
memcpy(buffer, &savebuffer[sboffset], len);
sboffset += len;
}
}
/****************************************************************************
* GCReadChunk
*
* Read the array of SFORMAT structures to memory
****************************************************************************/
int GCReadChunk( int chunkid, SFORMAT *sf ) {
int csize;
static char chunk[6];
int chunklength;
int thischunk;
char info[128];
memfread(&chunk, 4);
memfread(&thischunk, 4);
memfread(&chunklength, 4);
if (strcmp(chunk, "CHNK") == 0) {
if (chunkid == thischunk) {
/*** Now decode the array of chunks to this one ***/
while (sf->v) {
memfread(&chunk, 4);
if ( memcmp(&chunk, "CHKE", 4) == 0 )
return 1;
if (memcmp(&chunk, sf->desc, 4) == 0) {
memfread(&csize, 4);
if (csize == (sf->s & (~RLSB ))) {
memfread( sf->v, csize );
sprintf(info,"%s %d", chunk, csize);
} else {
WaitPrompt("Bad chunk link");
return 0;
}
} else {
sprintf(info, "No Sync %s %s", chunk, sf->desc);
WaitPrompt(info);
return 0;
}
sf++;
}
} else
return 0;
} else
return 0;
return 1;
}
/****************************************************************************
* GCFCEUSS_Load
*
* Reads the SFORMAT arrays
****************************************************************************/
int GCFCEUSS_Load() {
int totalsize = 0;
sboffset = 16 + sizeof(saveicon) + 64; /*** Reset memory file pointer ***/
memcpy(&totalsize, &savebuffer[FILESIZEOFFSET], 4);
/*** Now read the chunks back ***/
if (GCReadChunk(1, SFCPU)) {
if (GCReadChunk(2, SFCPUC)) {
if (GCReadChunk(3, FCEUPPU_STATEINFO)) {
if (GCReadChunk(4, FCEUCTRL_STATEINFO)) {
if (GCReadChunk(5, FCEUSND_STATEINFO)) {
if (GCReadChunk(0x10, SFMDATA))
return 1;
}
}
}
}
}
return 0;
}
/****************************************************************************
* GCSaveChunk
*
* Write the array of SFORMAT structures to the file
****************************************************************************/
int GCSaveChunk(int chunkid, SFORMAT *sf) {
int chnkstart;
int csize = 0;
int chsize = 0;
char chunk[] = "CHNK";
/*** Add chunk marker ***/
memfwrite(&chunk, 4);
memfwrite(&chunkid, 4);
chnkstart = sboffset; /*** Save ptr ***/
sboffset += 4; /*** Space for length ***/
csize += 12;
/*** Now run through this structure ***/
while (sf->v) {
/*** Check that there is a decription ***/
if ( sf->desc == NULL)
break;
/*** Write out the description ***/
memfwrite( sf->desc, 4);
/*** Write the length of this chunk ***/
chsize = ( sf->s & (~RLSB) );
memfwrite( &chsize, 4);
if ( chsize > 0 )
/*** Write the actual data ***/
memfwrite( sf->v, chsize );
csize += 8;
csize += chsize;
sf++;
}
/*** Update CHNK length ***/
memcpy(&savebuffer[chnkstart], &csize, 4);
return csize;
}
/****************************************************************************
* GCFCEUSS_Save
*
* This is a modified version of FCEUSS_Save
* It uses memory for it's I/O and has an added CHNK block.
* The file is terminated with CHNK length of 0.
****************************************************************************/
int GCFCEUSS_Save()
{
int totalsize = 0;
static unsigned char header[16] = "FCS\xff";
char chunk[] = "CHKE";
int zero = 0;
char Comment[2][100] = { { MENU_CREDITS_TITLE }, { "GAME" } };
memopen(); /*** Reset Memory File ***/
/*** Add version ID ***/
memcpy(&header[8], &mcversion, 4);
/*** Do internal Saving ***/
FCEUPPU_SaveState();
FCEUSND_SaveState();
/*** Write Icon ***/
memfwrite(&saveicon, sizeof(saveicon));
totalsize += sizeof(saveicon);
/*** And Comments ***/
strncpy (Comment[1],romFilename,31); // we only have 32 chars to work with!
memfwrite(&Comment[0], 64);
totalsize += 64;
/*** Write header ***/
memfwrite(&header, 16);
totalsize += 16;
totalsize += GCSaveChunk(1, SFCPU);
totalsize += GCSaveChunk(2, SFCPUC);
totalsize += GCSaveChunk(3, FCEUPPU_STATEINFO);
totalsize += GCSaveChunk(4, FCEUCTRL_STATEINFO);
totalsize += GCSaveChunk(5, FCEUSND_STATEINFO);
totalsize += GCSaveChunk(0x10, SFMDATA);
/*** Add terminating CHNK ***/
memfwrite(&chunk,4);
memfwrite(&zero,4);
totalsize += 8;
/*** Update size element ***/
memcpy(&savebuffer[FILESIZEOFFSET], &totalsize, 4);
return totalsize;
}
bool SaveState (int method, bool silent)
{
ShowAction ((char*) "Saving...");
if(method == METHOD_AUTO)
method = autoSaveMethod();
bool retval = false;
char filepath[1024];
int datasize;
int offset = 0;
datasize = GCFCEUSS_Save();
if ( datasize )
{
if(method == METHOD_SD || method == METHOD_USB)
{
if(ChangeFATInterface(method, NOTSILENT))
{
sprintf (filepath, "%s/%s/%s.fcs", ROOTFATDIR, GCSettings.SaveFolder, romFilename);
offset = SaveBufferToFAT (filepath, datasize, silent);
}
}
else if(method == METHOD_SMB)
{
sprintf (filepath, "%s/%s.fcs", GCSettings.SaveFolder, romFilename);
offset = SaveBufferToSMB (filepath, datasize, silent);
}
else if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB)
{
sprintf (filepath, "%08x.fcs", iNESGameCRC32);
if(method == METHOD_MC_SLOTA)
offset = SaveBufferToMC (savebuffer, CARD_SLOTA, filepath, datasize, silent);
else
offset = SaveBufferToMC (savebuffer, CARD_SLOTB, filepath, datasize, silent);
}
if (offset > 0)
{
if ( !silent )
WaitPrompt((char *)"Save successful");
retval = true;
}
}
return retval;
}
bool LoadState (int method, bool silent)
{
ShowAction ((char*) "Loading...");
if(method == METHOD_AUTO)
method = autoSaveMethod(); // we use 'Save' because SRAM needs R/W
char filepath[1024];
int offset = 0;
if(method == METHOD_SD || method == METHOD_USB)
{
ChangeFATInterface(method, NOTSILENT);
sprintf (filepath, "%s/%s/%s.fcs", ROOTFATDIR, GCSettings.SaveFolder, romFilename);
offset = LoadBufferFromFAT (filepath, silent);
}
else if(method == METHOD_SMB)
{
sprintf (filepath, "%s/%s.fcs", GCSettings.SaveFolder, romFilename);
offset = LoadSaveBufferFromSMB (filepath, silent);
}
else if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB)
{
sprintf (filepath, "%08x.fcs", iNESGameCRC32);
if(method == METHOD_MC_SLOTA)
offset = LoadBufferFromMC (savebuffer, CARD_SLOTA, filepath, silent);
else
offset = LoadBufferFromMC (savebuffer, CARD_SLOTB, filepath, silent);
}
if (offset > 0)
{
GCFCEUSS_Load();
return 1;
}
// if we reached here, nothing was done!
if(!silent)
WaitPrompt ((char*) "State file not found");
return 0;
}

13
source/ngc/fceustate.h Normal file
View File

@ -0,0 +1,13 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* fceustate.h
*
* Memory Based Load/Save State Manager
****************************************************************************/
bool SaveState (int method, bool silent);
bool LoadState (int method, bool silent);

281
source/ngc/fileop.c Normal file
View File

@ -0,0 +1,281 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* fileop.c
*
* File operations
****************************************************************************/
#include <gccore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ogcsys.h>
#include <zlib.h>
#include "common.h"
#include "fceuconfig.h"
#include "fileop.h"
#include "gcunzip.h"
#include "menudraw.h"
#include "filesel.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;
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;
}
handle = fopen (filepath, "rb");
if (handle > 0)
{
fread (zipbuffer, 1, 2048, handle);
if (IsZipFile (zipbuffer))
{
size = UnZipFATFile (nesromptr, 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 (nesromptr, zipbuffer, 2048); // copy what we already read
fread (nesromptr + 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;
}

33
source/ngc/fileop.h Normal file
View File

@ -0,0 +1,33 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* fatop.h
*
* FAT File operations
****************************************************************************/
#ifndef _FATOP_H_
#define _FATOP_H_
#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

580
source/ngc/filesel.c Normal file
View File

@ -0,0 +1,580 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* filesel.c
*
* 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
#include <di/di.h>
#endif
#include "common.h"
#include "fceuconfig.h"
#include "dvd.h"
#include "menudraw.h"
#include "filesel.h"
#include "smbop.h"
#include "fileop.h"
#include "memcardop.h"
#include "pad.h"
#include "fceuload.h"
int offset;
int selection;
char currentdir[MAXPATHLEN];
char romFilename[200];
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);
/****************************************************************************
* 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
}
}
/***************************************************************************
* Update curent directory name
***************************************************************************/
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 state saving
StripExt(romFilename, filelist[selection].filename);
ShowAction ((char *)"Loading...");
switch (method)
{
case METHOD_SD:
case METHOD_USB:
LoadFATFile (filelist[selection].filename,
filelist[selection].length);
break;
case METHOD_DVD:
dvddir = filelist[selection].offset;
dvddirlength = filelist[selection].length;
LoadDVDFile (nesromptr);
break;
case METHOD_SMB:
LoadSMBFile (filelist[selection].filename,
filelist[selection].length);
break;
}
if (GCMemROM() >= 0)
{
//hasloaded = 1; // indicator for memmap.cpp
//Memory.LoadROM ("BLANK.SMC");
//Memory.LoadSRAM ("BLANK");
//haverom = 1;
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;
}

38
source/ngc/filesel.h Normal file
View File

@ -0,0 +1,38 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 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

113
source/ngc/gcaudio.c Normal file
View File

@ -0,0 +1,113 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* audio.c
*
* Audio driver
****************************************************************************/
#include <gccore.h>
#define SAMPLERATE 48000
static unsigned char audiobuffer[2][64 * 1024] __attribute__((__aligned__(32)));
/*** Allow for up to 1 full second ***/
/****************************************************************************
* AudioSwitchBuffers
*
* Manages which buffer is played next
****************************************************************************/
static int isWriting = 0; /*** Bool for buffer writes ***/
static int buffSize[2]; /*** Hold size of current buffer ***/
static int whichab = 0; /*** Which Audio Buffer is in use ***/
static int isPlaying; /*** Is Playing ***/
static void AudioSwitchBuffers()
{
if ( buffSize[whichab] ) {
AUDIO_StopDMA();
AUDIO_InitDMA((u32)audiobuffer[whichab], buffSize[whichab]);
DCFlushRange(&audiobuffer[whichab], buffSize[whichab]);
AUDIO_StartDMA();
isPlaying = 0;
}
whichab ^= 1;
buffSize[whichab] = 0;
}
void InitialiseSound()
{
AUDIO_Init(NULL); /*** Start audio subsystem ***/
AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
AUDIO_RegisterDMACallback( AudioSwitchBuffers );
buffSize[0] = buffSize[1] = 0;
}
void StartAudio()
{
AUDIO_StartDMA();
}
void StopAudio()
{
AUDIO_StopDMA();
}
static inline unsigned short FLIP16(unsigned short b)
{
return((b<<8)|((b>>8)&0xFF));
}
static inline u32 FLIP32(u32 b)
{
return( (b<<24) | ((b>>8)&0xFF00) | ((b<<8)&0xFF0000) | ((b>>24)&0xFF) );
}
/****************************************************************************
* Audio incoming is monaural
*
* PlaySound will simply mix to get it right
****************************************************************************/
#define AUDIOBUFFER ((50 * SAMPLERATE) / 1000 ) << 4
static int isPlaying = 0;
static short MBuffer[ 8 * 96000 / 50 ];
void PlaySound( unsigned int *Buffer, int count )
{
int P;
unsigned short *s = (unsigned short *)&MBuffer[0];
unsigned int *d = (unsigned int *)&audiobuffer[whichab][buffSize[whichab]];
unsigned int c;
int ms;
isWriting = 1;
for ( P = 0; P < count; P++ ) {
MBuffer[P] = Buffer[P];
}
/*** Now do Mono - Stereo Conversion ***/
ms = count;
do
{
c = 0xffff & *s++;
*d++ = (c | (c<<16));
} while(--ms);
buffSize[whichab] += ( count << 2 );
/*** This is the kicker for the entire audio loop ***/
if ( isPlaying == 0 )
{
if ( buffSize[whichab] > AUDIOBUFFER )
{
isPlaying = 1;
AudioSwitchBuffers();
}
}
isWriting = 0;
}

227
source/ngc/gcunzip.c Normal file
View File

@ -0,0 +1,227 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* gcunzip.h
*
* Unzip routines
****************************************************************************/
#include <gccore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
#include "dvd.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
UnZipFATFile (unsigned char *outbuffer, FILE* infile)
{
fatfile = infile;
return UnZipBuffer(outbuffer, 0);
}
// Reading from DVD
int
UnZipDVDFile (unsigned char *outbuffer, u64 inoffset)
{
discoffset = inoffset;
return UnZipBuffer(outbuffer, 1);
}
// Reading from SMB
int
UnZipSMBFile (unsigned char *outbuffer, SMBFILE infile)
{
smbfile = infile;
return UnZipBuffer(outbuffer, 2);
}

45
source/ngc/gcunzip.h Normal file
View File

@ -0,0 +1,45 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* gcunzip.h
*
* Unzip routines
****************************************************************************/
#ifndef _GCUNZIP_H_
#define _GCUNZIP_H_
#include <smb.h>
extern int IsZipFile (char *buffer);
int UnZipFATFile (unsigned char *outbuffer, FILE* infile); // Reading from FAT
int UnZipDVDFile (unsigned char *outbuffer, u64 inoffset); // Reading from DVD
int UnZipSMBFile (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

634
source/ngc/gcvideo.c Normal file
View File

@ -0,0 +1,634 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* gcvideo.c
*
* Video rendering
****************************************************************************/
#include <gccore.h>
#include <ogcsys.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wiiuse/wpad.h>
#include "gcvideo.h"
#include "images/nesback.h"
extern unsigned int SMBTimer;
//#define FORCE_PAL50 1
#define TEX_WIDTH 256
#define TEX_HEIGHT 512
#define WIDTH 640
#define DEFAULT_FIFO_SIZE 256 * 1024
unsigned int *xfb[2]; /*** Framebuffer - used throughout ***/
GXRModeObj *vmode;
int screenheight;
/*** Need something to hold the PC palette ***/
struct pcpal {
unsigned char r;
unsigned char g;
unsigned char b;
} pcpalette[256];
unsigned int gcpalette[256]; /*** Much simpler GC palette ***/
unsigned short rgb565[256]; /*** Texture map palette ***/
static unsigned char gp_fifo[DEFAULT_FIFO_SIZE] __attribute__((__aligned__(32)));
static unsigned char texturemem[TEX_WIDTH * TEX_HEIGHT * 2] __attribute__((__aligned__(32)));
GXTexObj texobj;
GXColor background = {0, 0, 0, 0xff};
static Mtx projectionMatrix,modelViewMatrix;
void CheesyScale(unsigned char *XBuf);
int whichfb = 0;
int copynow = GX_FALSE;
/****************************************************************************
* GX Chip Copy to XFB
****************************************************************************/
static void copy_to_xfb() {
if (copynow == GX_TRUE) {
GX_CopyDisp(xfb[whichfb],GX_TRUE);
GX_Flush();
copynow = GX_FALSE;
}
SMBTimer++;
}
/****************************************************************************
* Initialise the GX
****************************************************************************/
void StartGX() {
/*** Clear out FIFO area ***/
memset(&gp_fifo, 0, DEFAULT_FIFO_SIZE);
/*** Initialise GX ***/
GX_Init(&gp_fifo, DEFAULT_FIFO_SIZE);
GX_SetCopyClear(background, 0x00ffffff);
/*** Additions from libogc ***/
GX_SetViewport(10,0,vmode->fbWidth,vmode->efbHeight,0,1);
GX_SetDispCopyYScale((f32)vmode->xfbHeight/(f32)vmode->efbHeight);
GX_SetDispCopySrc(0,0,vmode->fbWidth,vmode->efbHeight);
GX_SetDispCopyDst(vmode->fbWidth,vmode->xfbHeight);
GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
GX_SetCullMode(GX_CULL_NONE);
GX_SetZMode(GX_FALSE,GX_ALWAYS,GX_TRUE);
GX_SetColorUpdate(GX_TRUE);
GX_CopyDisp(xfb[whichfb],GX_TRUE);
/*** Additions from ogc spaceship ***/
GX_SetDispCopyGamma(GX_GM_1_0);
GX_ClearVtxDesc();
GX_SetVtxAttrFmt(GX_VTXFMT0,GX_VA_POS,GX_POS_XYZ,GX_F32,0);
GX_SetVtxAttrFmt(GX_VTXFMT0,GX_VA_TEX0,GX_TEX_ST,GX_F32,0);
GX_SetVtxDesc(GX_VA_POS,GX_DIRECT);
GX_SetVtxDesc(GX_VA_TEX0,GX_DIRECT);
GX_SetNumChans(0); /* default, color = vertex color */
GX_SetNumTexGens(1);
GX_SetTexCoordGen(GX_TEXCOORD0,GX_TG_MTX2x4,GX_TG_TEX0,GX_IDENTITY);
GX_SetTevOrder(GX_TEVSTAGE0,GX_TEXCOORD0,GX_TEXMAP0,GX_COLORNULL);
GX_SetTevOp(GX_TEVSTAGE0,GX_REPLACE);
GX_InitTexObj(&texobj,&texturemem,TEX_WIDTH,TEX_HEIGHT,
GX_TF_RGB565,GX_REPEAT,GX_REPEAT,GX_FALSE);
DCFlushRange(&texturemem, TEX_WIDTH * TEX_HEIGHT * 2);
GX_LoadTexObj(&texobj,GX_TEXMAP0);
GX_InvalidateTexAll();
/* load projection matrix */
/*** Setting Height to 648 get's it right ? ***/
guOrtho(projectionMatrix,10,610,640,0,-1,1);
GX_LoadProjectionMtx(projectionMatrix,GX_ORTHOGRAPHIC);
/* load model view matrix */
c_guMtxScale(modelViewMatrix,660,640,1);
GX_LoadPosMtxImm(modelViewMatrix,GX_PNMTX0);
}
/****************************************************************************
* GXDraw
*
* Using the texture map draw with quads
****************************************************************************/
void GXDraw(unsigned char *XBuf) {
float gs = 1.0;
float gt = 1.0;
int width, height,t,xb;
unsigned short *texture;
memset(&texturemem, 0, TEX_WIDTH * TEX_HEIGHT * 2);
texture = (unsigned short *)&texturemem[16 * TEX_WIDTH];
/*** Now draw the texture ***/
t = 0;
for(height = 0; height < 120; height++) {
xb = height * 512;
for(width = 256; width > 0; width -= 4) {
/*** Row one ***/
texture[t++] = rgb565[XBuf[xb + width-1]];
texture[t++] = rgb565[XBuf[xb + width-2]];
texture[t++] = rgb565[XBuf[xb + width-3]];
texture[t++] = rgb565[XBuf[xb + width-4]];
/*** Row three ***/
texture[t++] = rgb565[XBuf[xb + width-1]];
texture[t++] = rgb565[XBuf[xb + width-2]];
texture[t++] = rgb565[XBuf[xb + width-3]];
texture[t++] = rgb565[XBuf[xb + width-4]];
/*** Row one ***/
texture[t++] = rgb565[XBuf[xb + 256 + width-1]];
texture[t++] = rgb565[XBuf[xb + 256 + width-2]];
texture[t++] = rgb565[XBuf[xb + 256 + width-3]];
texture[t++] = rgb565[XBuf[xb + 256 + width-4]];
/*** Row three ***/
texture[t++] = rgb565[XBuf[xb + 256 + width-1]];
texture[t++] = rgb565[XBuf[xb + 256 + width-2]];
texture[t++] = rgb565[XBuf[xb + 256 + width-3]];
texture[t++] = rgb565[XBuf[xb + 256 + width-4]];
}
}
DCFlushRange(&texturemem, TEX_WIDTH * TEX_HEIGHT * 2);
/* setup GX */
GX_InvalidateTexAll();
// ok render the triangles now
GX_Begin(GX_QUADS,GX_VTXFMT0,4);
{
GX_Position3f32(0,0,0);
GX_TexCoord2f32(0,0);
GX_Position3f32(0,1,0);
GX_TexCoord2f32(0,gt);
GX_Position3f32(1,1,0);
GX_TexCoord2f32(gs,gt);
GX_Position3f32(1,0,0);
GX_TexCoord2f32(gs,0);
}
GX_End();
GX_DrawDone();
copynow = GX_TRUE;
}
/****************************************************************************
* UpdatePadsCB
*
* called by postRetraceCallback in InitGCVideo - scans gcpad and wpad
****************************************************************************/
void
UpdatePadsCB ()
{
#ifdef HW_RVL
WPAD_ScanPads();
#endif
PAD_ScanPads();
}
/****************************************************************************
* initDisplay
*
* It should be noted that this function forces the system to use a
* 640x480 viewport for either NTSC or PAL.
*
* Helps keep the rendering at 2x sweet
****************************************************************************/
void initDisplay() {
/*** 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);
/*** Setup a console - guard against spurious printf ***/
VIDEO_SetPreRetraceCallback((VIRetraceCallback)copy_to_xfb);
VIDEO_SetNextFramebuffer(xfb[0]);
PAD_Init();
StartGX();
}
/****************************************************************************
* RenderFrame
*
* Render a single frame at 2x zoom
****************************************************************************/
#define NESWIDTH 256
#define NESHEIGHT 240
void RenderFrame(char *XBuf, int style) {
int gcdispOffset = 32; /*** Offset to centre on screen ***/
int w,h;
int c,i;
whichfb ^= 1;
switch(style) {
case 0 :
VIDEO_ClearFrameBuffer(vmode, xfb[whichfb], COLOR_BLACK);
/*** Simply go through each row ***/
for(h = 0; h < NESHEIGHT; h++) {
for(w = 0; w < NESWIDTH; w++) {
c = (h << 8) + w;
i = gcdispOffset + w;
/*** Fast Zoom - Repeat each row, use 1 Xbuf == 2 GC
To speed up more, use indexed palette array ***/
xfb[whichfb][i] = gcpalette[(unsigned char)XBuf[c]];
xfb[whichfb][i + 320] = gcpalette[(unsigned char)XBuf[c]];
}
gcdispOffset += 640;
}
break;
case 1:
CheesyScale((unsigned char *)XBuf);
break;
case 2:
GXDraw((unsigned char *)XBuf);
break;
}
/*** Now resync with VSync ***/
VIDEO_SetNextFramebuffer(xfb[whichfb]);
VIDEO_Flush();
VIDEO_WaitVSync();
}
/****************************************************************************
* rgbcolor
*
* Support routine for gcpalette
****************************************************************************/
unsigned int rgbcolor(unsigned char r1, unsigned char g1, unsigned char b1,
unsigned char r2, unsigned char g2, unsigned char b2) {
int y1,cb1,cr1,y2,cb2,cr2,cb,cr;
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);
}
/****************************************************************************
* SetPalette
*
* A shadow copy of the palette is maintained, in case the NES Emu kernel
* requests a copy.
****************************************************************************/
void FCEUD_SetPalette(unsigned char index, unsigned char r, unsigned char g,
unsigned char b) {
/*** Make PC compatible copy ***/
pcpalette[index].r = r;
pcpalette[index].g = g;
pcpalette[index].b = b;
/*** Generate Gamecube palette ***/
gcpalette[index] = rgbcolor(r,g,b,r,g,b);
/*** Generate RGB565 texture palette ***/
rgb565[index] = ((r & 0xf8) << 8) |
((g & 0xfc) << 3) |
((b & 0xf8) >> 3);
}
/****************************************************************************
* GetPalette
****************************************************************************/
void FCEUD_GetPalette(unsigned char i, unsigned char *r, unsigned char *g,
unsigned char *b) {
*r = pcpalette[i].r;
*g = pcpalette[i].g;
*b = pcpalette[i].b;
}
/****************************************************************************
* NES Cheesy Scaler
*
* This scaler simply attempts to correct the 1.25 aspect by
* stretching the initial 256 pixels to 320.
* The standard 2x2 scaler can then be applied
****************************************************************************/
void CheesyScale(unsigned char *XBuf) {
static int newrow[320]; /*** New cheesy row ***/
unsigned int cheesypal[256]; /*** Enhanced Cheesy Palette ***/
int i,j,c,p = 0;
unsigned char p1,p2;
unsigned int ofs, gcdispOffset = 0;
int h, n, nw;
/*** Stretch ***/
for (h = 0; h < NESHEIGHT; h++) {
j = c = p = 0;
for (i = 0; i < NESWIDTH; i++) {
/*** Every fifth pixel is stretched by adding
the mid colour range ***/
n = (h << 8) + i;
newrow[j++] = XBuf[n];
c++;
if (c == 4) { /*** Done 4 pixels, so add the fifth ***/
p1 = XBuf[n];
p2 = XBuf[n+1];
cheesypal[p] = rgbcolor(pcpalette[p1].r, pcpalette[p1].g,
pcpalette[p1].b, pcpalette[p2].r, pcpalette[p2].g,
pcpalette[p2].b);
newrow[j++] = 0x8000 + p;
p++;
c = 0;
}
}
/*** Now update the screen display with the new colours ***/
ofs = gcdispOffset;
for (nw = 0; nw < 320; nw++) {
if (newrow[nw] & 0x8000) {
xfb[whichfb][ofs + nw] = cheesypal[newrow[nw] & 0xff ];
xfb[whichfb][ofs + 320 + nw] = cheesypal[newrow[nw] & 0xff];
} else {
xfb[whichfb][ofs + nw] = gcpalette[newrow[nw]];
xfb[whichfb][ofs + nw + 320] = gcpalette[newrow[nw]];
}
}
gcdispOffset += 640;
}
}
void
clearscreen ()
{
int colour = COLOR_BLACK;
whichfb ^= 1;
VIDEO_ClearFrameBuffer (vmode, xfb[whichfb], colour);
memcpy (xfb[whichfb], &bg, 1280 * 480);
}
void
showscreen ()
{
copynow = GX_FALSE;
VIDEO_SetNextFramebuffer (xfb[whichfb]);
VIDEO_Flush ();
VIDEO_WaitVSync ();
}
struct st_palettes palettes[] = {
/* The default NES palette must be the first entry in the array */
{ "loopy", "Loopy's NES palette",
{ 0x757575, 0x271b8f, 0x0000ab, 0x47009f,
0x8f0077, 0xab0013, 0xa70000, 0x7f0b00,
0x432f00, 0x004700, 0x005100, 0x003f17,
0x1b3f5f, 0x000000, 0x000000, 0x000000,
0xbcbcbc, 0x0073ef, 0x233bef, 0x8300f3,
0xbf00bf, 0xe7005b, 0xdb2b00, 0xcb4f0f,
0x8b7300, 0x009700, 0x00ab00, 0x00933b,
0x00838b, 0x000000, 0x000000, 0x000000,
0xffffff, 0x3fbfff, 0x5f97ff, 0xa78bfd,
0xf77bff, 0xff77b7, 0xff7763, 0xff9b3b,
0xf3bf3f, 0x83d313, 0x4fdf4b, 0x58f898,
0x00ebdb, 0x000000, 0x000000, 0x000000,
0xffffff, 0xabe7ff, 0xc7d7ff, 0xd7cbff,
0xffc7ff, 0xffc7db, 0xffbfb3, 0xffdbab,
0xffe7a3, 0xe3ffa3, 0xabf3bf, 0xb3ffcf,
0x9ffff3, 0x000000, 0x000000, 0x000000 }
},
{ "quor", "Quor's palette from Nestra 0.63",
{ 0x3f3f3f, 0x001f3f, 0x00003f, 0x1f003f,
0x3f003f, 0x3f0020, 0x3f0000, 0x3f2000,
0x3f3f00, 0x203f00, 0x003f00, 0x003f20,
0x003f3f, 0x000000, 0x000000, 0x000000,
0x7f7f7f, 0x405f7f, 0x40407f, 0x5f407f,
0x7f407f, 0x7f4060, 0x7f4040, 0x7f6040,
0x7f7f40, 0x607f40, 0x407f40, 0x407f60,
0x407f7f, 0x000000, 0x000000, 0x000000,
0xbfbfbf, 0x809fbf, 0x8080bf, 0x9f80bf,
0xbf80bf, 0xbf80a0, 0xbf8080, 0xbfa080,
0xbfbf80, 0xa0bf80, 0x80bf80, 0x80bfa0,
0x80bfbf, 0x000000, 0x000000, 0x000000,
0xffffff, 0xc0dfff, 0xc0c0ff, 0xdfc0ff,
0xffc0ff, 0xffc0e0, 0xffc0c0, 0xffe0c0,
0xffffc0, 0xe0ffc0, 0xc0ffc0, 0xc0ffe0,
0xc0ffff, 0x000000, 0x000000, 0x000000 }
},
{ "chris", "Chris Covell's NES palette",
{ 0x808080, 0x003DA6, 0x0012B0, 0x440096,
0xA1005E, 0xC70028, 0xBA0600, 0x8C1700,
0x5C2F00, 0x104500, 0x054A00, 0x00472E,
0x004166, 0x000000, 0x050505, 0x050505,
0xC7C7C7, 0x0077FF, 0x2155FF, 0x8237FA,
0xEB2FB5, 0xFF2950, 0xFF2200, 0xD63200,
0xC46200, 0x358000, 0x058F00, 0x008A55,
0x0099CC, 0x212121, 0x090909, 0x090909,
0xFFFFFF, 0x0FD7FF, 0x69A2FF, 0xD480FF,
0xFF45F3, 0xFF618B, 0xFF8833, 0xFF9C12,
0xFABC20, 0x9FE30E, 0x2BF035, 0x0CF0A4,
0x05FBFF, 0x5E5E5E, 0x0D0D0D, 0x0D0D0D,
0xFFFFFF, 0xA6FCFF, 0xB3ECFF, 0xDAABEB,
0xFFA8F9, 0xFFABB3, 0xFFD2B0, 0xFFEFA6,
0xFFF79C, 0xD7E895, 0xA6EDAF, 0xA2F2DA,
0x99FFFC, 0xDDDDDD, 0x111111, 0x111111 }
},
{ "matt", "Matthew Conte's NES palette",
{ 0x808080, 0x0000bb, 0x3700bf, 0x8400a6,
0xbb006a, 0xb7001e, 0xb30000, 0x912600,
0x7b2b00, 0x003e00, 0x00480d, 0x003c22,
0x002f66, 0x000000, 0x050505, 0x050505,
0xc8c8c8, 0x0059ff, 0x443cff, 0xb733cc,
0xff33aa, 0xff375e, 0xff371a, 0xd54b00,
0xc46200, 0x3c7b00, 0x1e8415, 0x009566,
0x0084c4, 0x111111, 0x090909, 0x090909,
0xffffff, 0x0095ff, 0x6f84ff, 0xd56fff,
0xff77cc, 0xff6f99, 0xff7b59, 0xff915f,
0xffa233, 0xa6bf00, 0x51d96a, 0x4dd5ae,
0x00d9ff, 0x666666, 0x0d0d0d, 0x0d0d0d,
0xffffff, 0x84bfff, 0xbbbbff, 0xd0bbff,
0xffbfea, 0xffbfcc, 0xffc4b7, 0xffccae,
0xffd9a2, 0xcce199, 0xaeeeb7, 0xaaf7ee,
0xb3eeff, 0xdddddd, 0x111111, 0x111111 }
},
{ "pasofami", "Palette from PasoFami/99",
{ 0x7f7f7f, 0x0000ff, 0x0000bf, 0x472bbf,
0x970087, 0xab0023, 0xab1300, 0x8b1700,
0x533000, 0x007800, 0x006b00, 0x005b00,
0x004358, 0x000000, 0x000000, 0x000000,
0xbfbfbf, 0x0078f8, 0x0058f8, 0x6b47ff,
0xdb00cd, 0xe7005b, 0xf83800, 0xe75f13,
0xaf7f00, 0x00b800, 0x00ab00, 0x00ab47,
0x008b8b, 0x000000, 0x000000, 0x000000,
0xf8f8f8, 0x3fbfff, 0x6b88ff, 0x9878f8,
0xf878f8, 0xf85898, 0xf87858, 0xffa347,
0xf8b800, 0xb8f818, 0x5bdb57, 0x58f898,
0x00ebdb, 0x787878, 0x000000, 0x000000,
0xffffff, 0xa7e7ff, 0xb8b8f8, 0xd8b8f8,
0xf8b8f8, 0xfba7c3, 0xf0d0b0, 0xffe3ab,
0xfbdb7b, 0xd8f878, 0xb8f8b8, 0xb8f8d8,
0x00ffff, 0xf8d8f8, 0x000000, 0x000000 }
},
{ "crashman", "CrashMan's NES palette",
{ 0x585858, 0x001173, 0x000062, 0x472bbf,
0x970087, 0x910009, 0x6f1100, 0x4c1008,
0x371e00, 0x002f00, 0x005500, 0x004d15,
0x002840, 0x000000, 0x000000, 0x000000,
0xa0a0a0, 0x004499, 0x2c2cc8, 0x590daa,
0xae006a, 0xb00040, 0xb83418, 0x983010,
0x704000, 0x308000, 0x207808, 0x007b33,
0x1c6888, 0x000000, 0x000000, 0x000000,
0xf8f8f8, 0x267be1, 0x5870f0, 0x9878f8,
0xff73c8, 0xf060a8, 0xd07b37, 0xe09040,
0xf8b300, 0x8cbc00, 0x40a858, 0x58f898,
0x00b7bf, 0x787878, 0x000000, 0x000000,
0xffffff, 0xa7e7ff, 0xb8b8f8, 0xd8b8f8,
0xe6a6ff, 0xf29dc4, 0xf0c0b0, 0xfce4b0,
0xe0e01e, 0xd8f878, 0xc0e890, 0x95f7c8,
0x98e0e8, 0xf8d8f8, 0x000000, 0x000000 }
},
{ "mess", "palette from the MESS NES driver",
{ 0x747474, 0x24188c, 0x0000a8, 0x44009c,
0x8c0074, 0xa80010, 0xa40000, 0x7c0800,
0x402c00, 0x004400, 0x005000, 0x003c14,
0x183c5c, 0x000000, 0x000000, 0x000000,
0xbcbcbc, 0x0070ec, 0x2038ec, 0x8000f0,
0xbc00bc, 0xe40058, 0xd82800, 0xc84c0c,
0x887000, 0x009400, 0x00a800, 0x009038,
0x008088, 0x000000, 0x000000, 0x000000,
0xfcfcfc, 0x3cbcfc, 0x5c94fc, 0x4088fc,
0xf478fc, 0xfc74b4, 0xfc7460, 0xfc9838,
0xf0bc3c, 0x80d010, 0x4cdc48, 0x58f898,
0x00e8d8, 0x000000, 0x000000, 0x000000,
0xfcfcfc, 0xa8e4fc, 0xc4d4fc, 0xd4c8fc,
0xfcc4fc, 0xfcc4d8, 0xfcbcb0, 0xfcd8a8,
0xfce4a0, 0xe0fca0, 0xa8f0bc, 0xb0fccc,
0x9cfcf0, 0x000000, 0x000000, 0x000000 }
},
{ "zaphod-cv", "Zaphod's VS Castlevania palette",
{ 0x7f7f7f, 0xffa347, 0x0000bf, 0x472bbf,
0x970087, 0xf85898, 0xab1300, 0xf8b8f8,
0xbf0000, 0x007800, 0x006b00, 0x005b00,
0xffffff, 0x9878f8, 0x000000, 0x000000,
0xbfbfbf, 0x0078f8, 0xab1300, 0x6b47ff,
0x00ae00, 0xe7005b, 0xf83800, 0x7777ff,
0xaf7f00, 0x00b800, 0x00ab00, 0x00ab47,
0x008b8b, 0x000000, 0x000000, 0x472bbf,
0xf8f8f8, 0xffe3ab, 0xf87858, 0x9878f8,
0x0078f8, 0xf85898, 0xbfbfbf, 0xffa347,
0xc800c8, 0xb8f818, 0x7f7f7f, 0x007800,
0x00ebdb, 0x000000, 0x000000, 0xffffff,
0xffffff, 0xa7e7ff, 0x5bdb57, 0xe75f13,
0x004358, 0x0000ff, 0xe7005b, 0x00b800,
0xfbdb7b, 0xd8f878, 0x8b1700, 0xffe3ab,
0x00ffff, 0xab0023, 0x000000, 0x000000 }
},
{ "zaphod-smb", "Zaphod's VS SMB palette",
{ 0x626a00, 0x0000ff, 0x006a77, 0x472bbf,
0x970087, 0xab0023, 0xab1300, 0xb74800,
0xa2a2a2, 0x007800, 0x006b00, 0x005b00,
0xffd599, 0xffff00, 0x009900, 0x000000,
0xff66ff, 0x0078f8, 0x0058f8, 0x6b47ff,
0x000000, 0xe7005b, 0xf83800, 0xe75f13,
0xaf7f00, 0x00b800, 0x5173ff, 0x00ab47,
0x008b8b, 0x000000, 0x91ff88, 0x000088,
0xf8f8f8, 0x3fbfff, 0x6b0000, 0x4855f8,
0xf878f8, 0xf85898, 0x595958, 0xff009d,
0x002f2f, 0xb8f818, 0x5bdb57, 0x58f898,
0x00ebdb, 0x787878, 0x000000, 0x000000,
0xffffff, 0xa7e7ff, 0x590400, 0xbb0000,
0xf8b8f8, 0xfba7c3, 0xffffff, 0x00e3e1,
0xfbdb7b, 0xffae00, 0xb8f8b8, 0xb8f8d8,
0x00ff00, 0xf8d8f8, 0xffaaaa, 0x004000 }
},
{ "vs-drmar", "VS Dr. Mario palette",
{ 0x5f97ff, 0x000000, 0x000000, 0x47009f,
0x00ab00, 0xffffff, 0xabe7ff, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0xe7005b, 0x000000, 0x000000, 0x000000,
0x5f97ff, 0x000000, 0x000000, 0x000000,
0x000000, 0x8b7300, 0xcb4f0f, 0x000000,
0xbcbcbc, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000,
0x00ebdb, 0x000000, 0x000000, 0x000000,
0x000000, 0xff9b3b, 0x000000, 0x000000,
0x83d313, 0x000000, 0x3fbfff, 0x000000,
0x0073ef, 0x000000, 0x000000, 0x000000,
0x00ebdb, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0xf3bf3f, 0x000000,
0x005100, 0x000000, 0xc7d7ff, 0xffdbab,
0x000000, 0x000000, 0x000000, 0x000000 }
},
{ "vs-cv", "VS Castlevania palette",
{ 0xaf7f00, 0xffa347, 0x008b8b, 0x472bbf,
0x970087, 0xf85898, 0xab1300, 0xf8b8f8,
0xf83800, 0x007800, 0x006b00, 0x005b00,
0xffffff, 0x9878f8, 0x00ab00, 0x000000,
0xbfbfbf, 0x0078f8, 0xab1300, 0x6b47ff,
0x000000, 0xe7005b, 0xf83800, 0x6b88ff,
0xaf7f00, 0x00b800, 0x6b88ff, 0x00ab47,
0x008b8b, 0x000000, 0x000000, 0x472bbf,
0xf8f8f8, 0xffe3ab, 0xf87858, 0x9878f8,
0x0078f8, 0xf85898, 0xbfbfbf, 0xffa347,
0x004358, 0xb8f818, 0x7f7f7f, 0x007800,
0x00ebdb, 0x000000, 0x000000, 0xffffff,
0xffffff, 0xa7e7ff, 0x5bdb57, 0x6b88ff,
0x004358, 0x0000ff, 0xe7005b, 0x00b800,
0xfbdb7b, 0xffa347, 0x8b1700, 0xffe3ab,
0xb8f818, 0xab0023, 0x000000, 0x007800 }
},
/* The default VS palette must be the last entry in the array */
{ "vs-smb", "VS SMB/VS Ice Climber palette",
{ 0xaf7f00, 0x0000ff, 0x008b8b, 0x472bbf,
0x970087, 0xab0023, 0x0000ff, 0xe75f13,
0xbfbfbf, 0x007800, 0x5bdb57, 0x005b00,
0xf0d0b0, 0xffe3ab, 0x00ab00, 0x000000,
0xbfbfbf, 0x0078f8, 0x0058f8, 0x6b47ff,
0x000000, 0xe7005b, 0xf83800, 0xf87858,
0xaf7f00, 0x00b800, 0x6b88ff, 0x00ab47,
0x008b8b, 0x000000, 0x000000, 0x3fbfff,
0xf8f8f8, 0x006b00, 0x8b1700, 0x9878f8,
0x6b47ff, 0xf85898, 0x7f7f7f, 0xe7005b,
0x004358, 0xb8f818, 0x0078f8, 0x58f898,
0x00ebdb, 0xfbdb7b, 0x000000, 0x000000,
0xffffff, 0xa7e7ff, 0xb8b8f8, 0xf83800,
0xf8b8f8, 0xfba7c3, 0xffffff, 0x00ffff,
0xfbdb7b, 0xffa347, 0xb8f8b8, 0xb8f8d8,
0xb8f818, 0xf8d8f8, 0x000000, 0x007800 }
}
};

30
source/ngc/gcvideo.h Normal file
View File

@ -0,0 +1,30 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* gcvideo.h
*
* Video rendering
****************************************************************************/
#ifndef _GCVIDEO_H_
#define _GCVIDEO_H_
void clearscreen ();
void showscreen ();
void initDisplay();
void RenderFrame(char *XBuf, int style);
// color palettes
#define MAXPAL 12
struct st_palettes {
char *name, *desc;
unsigned int data[64];
};
extern struct st_palettes palettes[];
#endif

38412
source/ngc/images/nesback.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,137 @@
#ifndef _IMGSAVEICON_
#define _IMGSAVEICON_
const unsigned short saveicon[1024] = {
0xDAD6, 0xEF7B, 0xE318, 0xCA52, 0xA94A, 0xCA52, 0xF7BD, 0xF7BD,
0x8C63, 0xA108, 0xCE73, 0xBDEF, 0x8421, 0x8C63, 0x9CE7, 0x8C63,
0xB5AD, 0xAD6B, 0xA94A, 0xCE71, 0xDEF7, 0xCE73, 0xF7BB, 0xFFFF,
0xA94A, 0xC20F, 0xEB58, 0xFBBB, 0x8421, 0xC1EE, 0xE2F5, 0xDED3,
0xDEF5, 0xDED4, 0xDEF4, 0xDED4, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
0xF7BA, 0xF7BA, 0xFBBA, 0xFBBA, 0xDAD4, 0xDED4, 0xDED4, 0xDED4,
0xDAB3, 0xDAB3, 0xDAB3, 0xD6B3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
0xFBBA, 0xFBBB, 0xFBBA, 0xFBBA, 0xDED4, 0xDEF4, 0xDED4, 0xCA0E,
0xD692, 0xD692, 0xD692, 0xD272, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
0xFFBB, 0xFFBB, 0xFBBA, 0xFBBA, 0xBD8A, 0xDAB2, 0xE2F4, 0xE2F4,
0xD292, 0xD692, 0xD692, 0xD292, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
0xFBBA, 0xF7BA, 0xF798, 0xF799, 0xE2F4, 0xE2F4, 0xDAB2, 0xDAD2,
0xD272, 0xCE71, 0xBDEE, 0xA529, 0xFFFF, 0xFFFF, 0xFFFF, 0xDAD4,
0xFBBA, 0xFBBA, 0xFB99, 0xD270, 0xDED4, 0xDED3, 0xDED3, 0xD670,
0x98C6, 0x8C63, 0x8421, 0x8000, 0x9CE7, 0x8842, 0x8000, 0x8000,
0x9CE5, 0x8000, 0x8000, 0x8000, 0xA0E5, 0x8000, 0x8000, 0x8000,
0x8421, 0x8842, 0x9084, 0x8421, 0x8000, 0x8421, 0x8C63, 0xB9CC,
0x8000, 0x8421, 0xB18B, 0xD6B3, 0x8000, 0x8421, 0xD6B3, 0xE717,
0xA528, 0xCE71, 0xDED4, 0xDAD3, 0xCE71, 0xE736, 0xE315, 0xE2F5,
0xE316, 0xDAD4, 0xDAD4, 0xDAD4, 0xB18B, 0xA528, 0xA528, 0xA128,
0xDAB3, 0xDED3, 0xDED4, 0xDED4, 0xE2F5, 0xE715, 0xE715, 0xE715,
0xDED4, 0xDED4, 0xDED4, 0xDED4, 0xA107, 0xA507, 0xA528, 0xA528,
0xDED4, 0xDED4, 0xDED4, 0xDEB3, 0xE715, 0xE716, 0xE715, 0xE716,
0xDED5, 0xDED4, 0xDED5, 0xDEF5, 0xA528, 0xA528, 0xA528, 0xA528,
0xDA92, 0xDED3, 0xDED3, 0xDAD3, 0xE716, 0xE716, 0xE715, 0xE2F5,
0xDEF5, 0xDEF5, 0xE2F5, 0xE2F5, 0xA528, 0xA528, 0xA528, 0xA528,
0xDED3, 0xDED3, 0xDAB2, 0xDAB3, 0xE715, 0xE715, 0xE2F4, 0xE2F5,
0xE2F5, 0xE2F5, 0xE315, 0xE315, 0xA528, 0xA528, 0xA528, 0xA528,
0xDED3, 0xDED3, 0xDEB2, 0xDA90, 0xE2F5, 0xE315, 0xE2F4, 0xDEB2,
0xE316, 0xE716, 0xEB36, 0xEF37, 0xA928, 0xA528, 0xA928, 0xB5AB,
0xA927, 0x8000, 0x8000, 0x8000, 0xB589, 0xB189, 0x8000, 0x8000,
0xD670, 0xB9AB, 0x98C4, 0x8000, 0xDED3, 0xD26F, 0xA927, 0x8000,
0x8000, 0xAD8B, 0xE738, 0xC210, 0x8000, 0xB9CD, 0xF39B, 0xA109,
0x8000, 0xBE0F, 0xEB5A, 0xA52A, 0x8000, 0xC20F, 0xE739, 0xAD6D,
0x94A4, 0x9084, 0x9084, 0x9084, 0x8442, 0x8842, 0x8842, 0x9083,
0x8843, 0x8C63, 0x8C62, 0x8841, 0x98E8, 0x94A6, 0x8862, 0x8842,
0x9083, 0x9083, 0x9083, 0x9084, 0x94A5, 0x94A5, 0x94A5, 0x94A4,
0x8862, 0x8862, 0x8842, 0x8842, 0x8842, 0x8841, 0x8421, 0x8421,
0x9484, 0x9484, 0x9084, 0x9084, 0x94A4, 0x94A5, 0x94A5, 0x94A5,
0x8862, 0x8862, 0x8C62, 0x8C62, 0x8421, 0x8421, 0x8421, 0x8421,
0x94A4, 0x9084, 0x94A4, 0x94A4, 0x94A5, 0x94A5, 0x94A5, 0x94A5,
0x8C62, 0x8C62, 0x8C62, 0x8C62, 0x8421, 0x8421, 0x8421, 0x8421,
0x94A4, 0x94A4, 0x94A4, 0x94A4, 0x94A5, 0x94A5, 0x94A5, 0x9083,
0x8C62, 0x8C63, 0x8C63, 0x9484, 0x8421, 0x8421, 0x8421, 0x8841,
0x94A4, 0x94A4, 0x94A4, 0x9CE6, 0x8C62, 0x8842, 0x8841, 0x8841,
0x9083, 0x8C62, 0x8C63, 0x8841, 0x8C62, 0x8C62, 0x8C62, 0x8421,
0xB58A, 0xDA91, 0xB58A, 0x8000, 0x94A4, 0xDA91, 0xBDCB, 0x8000,
0x9062, 0xD690, 0xBDCB, 0x8000, 0x8C62, 0xDA91, 0xC5ED, 0x8000,
0x8000, 0xBDEF, 0xEB5A, 0x98C7, 0x8000, 0xB9CD, 0xEB5A, 0x90A5,
0x8000, 0xA549, 0xD294, 0x98E7, 0x8000, 0x8421, 0xC651, 0xA128,
0xA96D, 0x9085, 0x8C63, 0x8C63, 0x94A6, 0x8421, 0x9CE7, 0x8C63,
0x8422, 0x8421, 0xA529, 0x94A4, 0x8421, 0x8421, 0x98C5, 0x9083,
0x8C63, 0x8C63, 0x8C63, 0x8C63, 0x8842, 0x8C62, 0x8C63, 0x9084,
0x8842, 0x8C62, 0x9084, 0x8C63, 0x8C42, 0x8C62, 0x8842, 0x8862,
0x8421, 0x8421, 0x8421, 0x8421, 0x8C63, 0x8421, 0x8421, 0x8421,
0x94A4, 0x8842, 0x8421, 0x8421, 0x9D07, 0x8862, 0x8421, 0x8421,
0x8421, 0x8421, 0x8421, 0x8C63, 0x8421, 0x8421, 0x8421, 0x94A4,
0x8421, 0x8421, 0x8421, 0xA108, 0x8421, 0x8421, 0x8421, 0xAD6B,
0x9084, 0x8421, 0x8421, 0x8441, 0x94A4, 0x8421, 0x8421, 0x8421,
0x94A4, 0x8821, 0x8841, 0x8841, 0x9484, 0x8421, 0x8842, 0x8842,
0x8841, 0x8421, 0x8841, 0x8420, 0x9084, 0x9084, 0x8C62, 0x8421,
0x94A4, 0x9CE7, 0x8842, 0x8421, 0x9084, 0x98C5, 0x8841, 0x8421,
0x8C62, 0xDA91, 0xC5ED, 0x8000, 0x9083, 0xDA92, 0xC1ED, 0x8000,
0x94A4, 0xC1ED, 0xAD69, 0x8000, 0x98A5, 0xB5AB, 0x8000, 0x8000,
0x8000, 0x8421, 0xC230, 0xA94A, 0x8000, 0x8421, 0xBE0F, 0xAD6B,
0x8000, 0x8421, 0xA98B, 0xB5CD, 0x8000, 0x8421, 0x8C63, 0xA149,
0x8421, 0x8421, 0x94A4, 0x90A4, 0x8020, 0x8421, 0x8841, 0x9484,
0x8862, 0x8421, 0x8420, 0x8821, 0xA128, 0xA129, 0xA549, 0x8883,
0x8842, 0x8842, 0x8841, 0x8C63, 0x8C42, 0x8842, 0x8841, 0x9084,
0x8842, 0x8842, 0x8842, 0x8C63, 0x8441, 0x8421, 0x8421, 0x8842,
0x9CE7, 0x8842, 0x8421, 0x8421, 0x9084, 0x8421, 0x8421, 0x8421,
0x8842, 0x8422, 0x8421, 0x8421, 0x8421, 0x8822, 0x8822, 0x8421,
0x8841, 0x8421, 0x8841, 0x98C5, 0x8441, 0x8421, 0x8441, 0x8C63,
0x8421, 0x8421, 0x8441, 0x8421, 0x8421, 0x8421, 0x8421, 0x8421,
0x94A4, 0x8000, 0x8421, 0x8842, 0x9084, 0x8842, 0x8421, 0x8842,
0x8C42, 0x8C62, 0x8822, 0x8842, 0x8421, 0x8821, 0x8821, 0x8841,
0x8842, 0x8C63, 0x8841, 0x8021, 0x8C63, 0x9084, 0x8421, 0x8000,
0x8842, 0x8C43, 0x8421, 0x8000, 0x9484, 0xA0E7, 0x9CC6, 0xB58B,
0x9CC5, 0xB5AB, 0x8000, 0x8000, 0xA527, 0xB18A, 0x8000, 0x8000,
0xB9AB, 0xB18A, 0x8000, 0x8000, 0xDAB3, 0xC1ED, 0xB58A, 0xA106,
0x8000, 0x8421, 0x8C63, 0x8421, 0x8000, 0x8421, 0x8C63, 0x8421,
0x8000, 0x8421, 0x8C63, 0x8421, 0x8000, 0x8421, 0x8C63, 0xAD8C,
0x8000, 0x8000, 0x8000, 0x90C5, 0x8000, 0x8000, 0x90A5, 0xA129,
0x98E7, 0xB5CE, 0xC652, 0xC210, 0xC651, 0xE318, 0xDEF7, 0xCE72,
0x94C6, 0xA529, 0xB9CE, 0xC632, 0xCA52, 0xDAD6, 0xDAD6, 0xD6B6,
0xD6B5, 0xD6B6, 0xD6B6, 0xD6B5, 0xC631, 0xD6B6, 0xD6B6, 0xD6B5,
0xC632, 0xB18D, 0xB16C, 0xA108, 0xEF7C, 0xE73A, 0xD6B6, 0xB5AD,
0xEB5A, 0xEF9C, 0xDEF7, 0xD693, 0xE73A, 0xF39D, 0xDAB5, 0xD271,
0x8401, 0xA108, 0xA528, 0xA508, 0x9083, 0xC20F, 0xCA30, 0xCA30,
0xC60F, 0xD272, 0xD271, 0xD250, 0xD671, 0xCE2F, 0xD270, 0xD670,
0xA929, 0xB16A, 0xBDED, 0xCA2F, 0xD250, 0xCA0E, 0xDA92, 0xDAB2,
0xD24F, 0xD24E, 0xD250, 0xCE2E, 0xD670, 0xD66F, 0xD64F, 0xCE2D,
0xD271, 0xDEB4, 0xDED4, 0xDED4, 0xD670, 0xD24F, 0xDA70, 0xD670,
0xD24E, 0xD24E, 0xD24E, 0xD24F, 0xD22E, 0xD24E, 0xD64E, 0xD64E,
0xDAB2, 0xCE50, 0xCA2E, 0xCA0D, 0xD670, 0xCE2E, 0xC5ED, 0xC5EC,
0xD24F, 0xCE0D, 0xC5EC, 0xC5EC, 0xD24E, 0xCE2D, 0xCA0C, 0xCA0D,
0x8000, 0x8421, 0xD2B4, 0xDAF7, 0x8000, 0x9D08, 0xE75A, 0xEB7B,
0x90C6, 0xB5CE, 0xEF7C, 0xF7BD, 0xBE0F, 0xEB39, 0xE739, 0xF39C,
0xE318, 0xDEF7, 0xDEF7, 0xDEF7, 0xDEF8, 0xE318, 0xDEF8, 0xE2F8,
0xE739, 0xE318, 0xE318, 0xE318, 0xF39C, 0xE739, 0xE739, 0xE739,
0xC630, 0xCA52, 0xDAB6, 0xD6B5, 0xDED6, 0xC20F, 0xD293, 0xD6B5,
0xE319, 0xDAD6, 0xC630, 0xDEF7, 0xE718, 0xE739, 0xDAB5, 0xD294,
0xE739, 0xF39D, 0xE2F7, 0xDAB3, 0xDEF8, 0xF39D, 0xE718, 0xDAD4,
0xDAD6, 0xF39D, 0xE739, 0xDED4, 0xD274, 0xE73A, 0xEB5A, 0xE2F5,
0xD270, 0xD670, 0xD671, 0xD691, 0xD670, 0xDA91, 0xDA91, 0xDA91,
0xDA91, 0xDEB1, 0xDEB2, 0xE2D2, 0xDEB2, 0xE2D3, 0xE2D3, 0xE2D3,
0xDA91, 0xDA91, 0xD66F, 0xD22D, 0xDEB2, 0xDE91, 0xCE2D, 0xD22E,
0xE6D3, 0xE2B2, 0xC9EC, 0xCA0D, 0xE6F3, 0xDA90, 0xCA0D, 0xCA0D,
0xD24E, 0xD24E, 0xD64E, 0xD66F, 0xD24E, 0xD64E, 0xD66F, 0xDA70,
0xD66F, 0xDA70, 0xDA91, 0xDA92, 0xDEB3, 0xDEB3, 0xE2D4, 0xE2D4,
0xD64F, 0xCE2E, 0xCE2E, 0xD24F, 0xD670, 0xCE2E, 0xD24F, 0xD670,
0xDAB2, 0xD250, 0xCE2E, 0xB148, 0xE2D4, 0xDA92, 0xD24F, 0xB969,
0xE739, 0xE317, 0xE318, 0xE739, 0xE318, 0xDEF7, 0xDAD6, 0xDAD6,
0xDEF7, 0xDAD6, 0xD6B5, 0xD6B4, 0xDEF7, 0xDAD6, 0xD6B4, 0xD294,
0xF7BD, 0xEB5A, 0xE739, 0xE738, 0xE318, 0xE739, 0xDAD6, 0xDAD6,
0xD294, 0xDAD6, 0xDAD6, 0xD294, 0xD294, 0xD294, 0xDAD6, 0xD294,
0xE738, 0xE739, 0xEB39, 0xD693, 0xDAD6, 0xDAD6, 0xDED6, 0xDAD5,
0xD294, 0xD294, 0xD294, 0xD694, 0xD273, 0xD293, 0xD273, 0xD273,
0xC630, 0xD6B5, 0xE738, 0xE2F5, 0xC630, 0xC631, 0xD6B5, 0xDAB3,
0xCE72, 0xC1EF, 0xCE72, 0xCA30, 0xD293, 0xC630, 0xC610, 0xD272,
0xDEB2, 0xE2D3, 0xE2D3, 0xDEB2, 0xD270, 0xD250, 0xCE2F, 0xD24F,
0xC60E, 0xCA2F, 0xCE50, 0xD271, 0xCE50, 0xCE51, 0xD251, 0xD271,
0xD670, 0xDEB2, 0xE2D3, 0xD691, 0xD691, 0xDAB2, 0xD692, 0xD693,
0xD271, 0xCE71, 0xD271, 0xD272, 0xD271, 0xD271, 0xD271, 0xD271,
0xE716, 0xE716, 0xE2F5, 0xE716, 0xDAB4, 0xE2F6, 0xDAB4, 0xDEB4,
0xD272, 0xDAB4, 0xDAB3, 0xD271, 0xD672, 0xD692, 0xDAB4, 0xD250,
0xE6F6, 0xDEB3, 0xD670, 0xD24F, 0xDEB3, 0xD691, 0xD670, 0xD670,
0xD270, 0xD270, 0xD250, 0xD671, 0xCE4F, 0xCE4F, 0xCE2F, 0xD24F,
};
#endif

24
source/ngc/intl.h Normal file
View File

@ -0,0 +1,24 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* intl.h
*
* This file holds collections of strings to make localization easier.
* Keep the max string length to 30 characters or bad things will happen
****************************************************************************/
#define MENU_STRING_LENGTH 30
#ifdef INTL_SPANISH
//#include "intl/spanish.h"
#elif defined INTL_GERMAN
//#include "intl/german.h"
#elif defined INTL_DUTCH
#include "intl/dutch.h"
#else
#include "intl/english.h"
#endif

420
source/ngc/memcardop.c Normal file
View File

@ -0,0 +1,420 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* memcardop.c
*
* Memory Card routines
****************************************************************************/
#include <gccore.h>
#include <ogcsys.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "common.h"
#include "menudraw.h"
#include "fceuconfig.h"
#include "menu.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;
}

22
source/ngc/memcardop.h Normal file
View File

@ -0,0 +1,22 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* memcardop.h
*
* Memory Card routines
****************************************************************************/
#ifndef _MEMCARDOP_H_
#define _MEMCARDOP_H_
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

799
source/ngc/menu.c Normal file
View File

@ -0,0 +1,799 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* menu.c
*
* Main menu flow control
****************************************************************************/
#include <gccore.h>
#include <ogcsys.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wiiuse/wpad.h>
#ifdef WII_DVD
#include <di/di.h>
#endif
#include "common.h"
#include "fceuconfig.h"
#include "pad.h"
#include "button_mapping.h"
#include "filesel.h"
#include "gcunzip.h"
#include "smbop.h"
#include "memcardop.h"
#include "fileop.h"
#include "dvd.h"
#include "menudraw.h"
#include "fceustate.h"
#include "gcvideo.h"
#include "preferences.h"
extern int GCMemROM();
extern void ResetNES(void);
extern void FCEU_ResetPalette(void);
extern int menu;
extern bool romLoaded;
#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);
if ( loadROM == 1 ) // if ROM was loaded
{
if(!GCMemROM()) // ROM was not valid
return 0;
// load the state
if (GCSettings.AutoLoad == 1)
LoadState(GCSettings.SaveMethod, SILENT);
}
return loadROM;
}
/****************************************************************************
* Emulator Menu
****************************************************************************/
static int emulatormenuCount = 7;
static char emulatormenu[][50] = {
"Screen Scaler",
"Palette",
"8 Sprite Limit",
"Timing",
"Four Score",
"Save Preferences",
"Back to Main Menu"
};
void
EmulatorMenu ()
{
int ret = 0;
int quit = 0;
int oldmenu = menu;
menu = 0;
while (quit == 0)
{
sprintf (emulatormenu[0], "Screen Scaler - %s",
(GCSettings.screenscaler == 0) ? "2x" : (GCSettings.screenscaler == 1) ? "Cheesy" : "GX");
sprintf (emulatormenu[1], "Palette - %s",
GCSettings.currpal ? palettes[GCSettings.currpal-1].name : "Default");
sprintf (emulatormenu[2], "8 Sprite Limit - %s",
GCSettings.slimit == true ? " ON" : "OFF");
sprintf (emulatormenu[3], "Timing - %s",
GCSettings.timing == true ? " PAL" : "NTSC");
sprintf (emulatormenu[4], "Four Score - %s",
GCSettings.FSDisable == true ? " ON" : "OFF");
ret = RunMenu (emulatormenu, emulatormenuCount, (char*)"Emulator Options", 16, -1);
switch (ret)
{
case 0: // screen scaler
if (++GCSettings.screenscaler > 2)
GCSettings.screenscaler = 0;
break;
case 1: // palette
if ( ++GCSettings.currpal > MAXPAL )
GCSettings.currpal = 0;
if ( GCSettings.currpal == 0 )
{
// Do palette reset
FCEU_ResetPalette();
}
else
{
// Now setup this palette
unsigned char i,r,g,b;
for ( i = 0; i < 64; i++ )
{
r = palettes[GCSettings.currpal-1].data[i] >> 16;
g = ( palettes[GCSettings.currpal-1].data[i] & 0xff00 ) >> 8;
b = ( palettes[GCSettings.currpal-1].data[i] & 0xff );
FCEUD_SetPalette( i, r, g, b);
FCEUD_SetPalette( i+64, r, g, b);
FCEUD_SetPalette( i+128, r, g, b);
FCEUD_SetPalette( i+192, r, g, b);
}
}
break;
case 2: // 8 sprite limit
GCSettings.slimit ^=1;
FCEUI_DisableSpriteLimitation(GCSettings.slimit);
break;
case 3: // timing
GCSettings.timing ^= 1;
FCEUI_SetVidSystem(GCSettings.timing);
break;
case 4: // four score
GCSettings.FSDisable ^= 1;
FCEUI_DisableFourScore(GCSettings.FSDisable);
break;
case 5:
SavePrefs(GCSettings.SaveMethod, NOTSILENT);
break;
case -1: // Button B
case 6:
quit = 1;
break;
}
}
menu = oldmenu;
}
/****************************************************************************
* 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 ON");
if (GCSettings.AutoSave == 0) sprintf (prefmenu[5],"Auto Save OFF");
else if (GCSettings.AutoSave == 1) sprintf (prefmenu[5],"Auto Save ON");
sprintf (prefmenu[6], "Verify MC Saves %s",
GCSettings.VerifySaves == true ? " ON" : "OFF");
ret = RunMenu (prefmenu, prefmenuCount, (char*)"Preferences", 16, -1);
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 > 1)
GCSettings.AutoLoad = 0;
break;
case 5:
GCSettings.AutoSave ++;
if (GCSettings.AutoSave > 1)
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 = 6;
char gamemenu[][50] = {
"Return to Game",
"Reset Game",
"ROM Information",
"Load State", "Save State",
"Back to Main Menu"
};
int ret, retval = 0;
int quit = 0;
int oldmenu = menu;
menu = 0;
while (quit == 0)
{
// disable state saving/loading if AUTO is on
if (GCSettings.AutoLoad == 1) // Auto Load SRAM
gamemenu[3][0] = '\0';
if (GCSettings.AutoSave == 1) // Auto Save SRAM
gamemenu[4][0] = '\0';
ret = RunMenu (gamemenu, gamemenuCount, (char*)"Game Menu", 20, -1);
switch (ret)
{
case 0: // Return to Game
quit = retval = 1;
break;
case 1: // Reset Game
ResetNES();
quit = retval = 1;
break;
case 2: // ROM Information
RomInfo();
WaitButtonA ();
break;
case 3: // Load State
quit = retval = LoadState(GCSettings.SaveMethod, NOTSILENT);
break;
case 4: // Save State
SaveState(GCSettings.SaveMethod, NOTSILENT);
break;
case -1: // Button B
case 5: // Return to previous menu
retval = 0;
quit = 1;
break;
}
}
menu = oldmenu;
return retval;
}
/****************************************************************************
* Controller Configuration
*
* Snes9x 1.50 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); // nes 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, 20, -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 = 9;
char cfg_btns_menu[][50] = {
"B - ",
"A - ",
"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*)"NES - NUNCHUK";
currentpadmap = ncpadmap;
break;
case CTRLR_CLASSIC:
menu_title = (char*)"NES - CLASSIC";
currentpadmap = ccpadmap;
break;
case CTRLR_GCPAD:
menu_title = (char*)"NES - GC PAD";
currentpadmap = gcpadmap;
break;
case CTRLR_WIIMOTE:
menu_title = (char*)"NES - WIIMOTE";
currentpadmap = wmpadmap;
break;
};
while (quit == 0)
{
/*** Update Menu with Current ButtonMap ***/
for (i=0; i<8; i++) // nes pad has 12 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 snes 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, -1);
switch (ret)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
/*** Change button map ***/
// wait for input
memset (temp, 0, sizeof(temp));
strncpy(temp, cfg_btns_menu[ret], 6); // get the name of the snes 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 8:
/*** 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", 20, -1);
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 = 8;
char menuitems[][50] = {
"Choose Game",
"Controller Configuration", "Emulator Options", "Preferences",
"Game Menu",
"Credits", "Reset System", "Exit"
};
void
MainMenu (int selectedMenu)
{
int quit = 0;
int ret;
VIDEO_WaitVSync ();
while (quit == 0)
{
// disable game-specific menu items if a ROM isn't loaded
if(!romLoaded)
menuitems[4][0] = '\0';
else
sprintf (menuitems[4], "Game Menu");
if(selectedMenu >= 0)
{
ret = selectedMenu;
selectedMenu = -1; // default back to main menu
}
else
{
ret = RunMenu (menuitems, menucount, (char*)"Main Menu", 20, -1);
}
switch (ret)
{
case 0:
// Load ROM Menu
quit = LoadManager ();
break;
case 1:
// Configure Controllers
ConfigureControllers ();
break;
case 2:
// Emulator Options
EmulatorMenu ();
break;
case 3:
// Preferences
PreferencesMenu ();
break;
case 4:
// Game Options
quit = GameMenu ();
break;
case 5:
// Credits
Credits ();
WaitButtonA ();
break;
case 6:
// Reset the Gamecube/Wii
Reboot();
break;
case 7:
// 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
if(romLoaded)
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
}

18
source/ngc/menu.h Normal file
View File

@ -0,0 +1,18 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* menu.h
*
* Main menu flow control
****************************************************************************/
#ifndef _NGCMENU_
#define _NGCMENU_
void MainMenu (int selectedMenu);
#endif

916
source/ngc/menudraw.c Normal file
View File

@ -0,0 +1,916 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* menudraw.c
*
* Menu drawing routines
****************************************************************************/
#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 "gcvideo.h"
#include "menudraw.h"
#include "filesel.h"
#include "dvd.h"
#include "pad.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;
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 (0xFF, 0xFF, 0xFF);
/*** 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 (0xFF, 0xFF, 0xFF);
setfontsize (28);
DrawText (-1, 145, (char*)"Credits");
int ypos = 140;
if (screenheight == 480)
ypos += 20;
setfontsize (14);
DrawText (125, ypos += 22, (char*)"GameCube/Wii Port v2.x");
DrawText (350, ypos, (char*)"Tantric");
DrawText (125, ypos += 18, (char*)"GameCube/Wii Port v1.0.9");
DrawText (350, ypos, (char*)"askot & dsbomb");
DrawText (125, ypos += 18, (char*)"GameCube Port v1.0.8");
DrawText (350, ypos, (char*)"SoftDev");
DrawText (125, ypos += 18, (char*)"FCE Ultra");
DrawText (350, ypos, (char*)"Xodnizel");
DrawText (125, ypos += 18, (char*)"Original FCE");
DrawText (350, ypos, (char*)"BERO");
DrawText (125, ypos += 18, (char*)"libogc");
DrawText (350, ypos, (char*)"Shagkur & wintermute");
DrawText (125, ypos += 18, (char*)"Testing");
DrawText (350, ypos, (char*)"tehskeen users");
DrawText (-1, ypos += 36, (char*)"And many others who have contributed over the years!");
setfontsize (12);
DrawText (-1, ypos += 50, (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 = 140;
if (screenheight == 480)
ypos += 20;
clearscreen ();
setfontcolour (0, 0, 0);
if (title != NULL)
{
setfontsize (26);
DrawText (-1, 145, title);
}
setfontsize (12);
DrawText (510, screenheight - 40, (char *)"FCEUGX 2.0.0");
// 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, 0x60, 0x60, 0x60 );
setfontcolour (0xff, 0xff, 0xff);
DrawText (x, n * line_height + ypos, items[i]);
setfontcolour (0xFF, 0xFF, 0xFF);
}
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, -1);
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, 145, (char*)"Choose Game");
setfontsize(18);
ypos = (screenheight - ((PAGESIZE - 1) * 20)) >> 1;
if (screenheight == 480)
ypos += 54;
else
ypos += 40;
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, 0x60, 0x60, 0x60 );
setfontcolour (0xFF, 0xFF, 0xFF);
DrawText (50, (j * 20) + ypos, text);
setfontcolour (0xFF, 0xFF, 0xFF);
}
else
{
/*** Normal entry ***/
DrawText (50, (j * 20) + ypos, text);
}
j++;
}
showscreen ();
}
/****************************************************************************
* ROM Information Screen
****************************************************************************/
typedef struct {
char ID[4]; /*NES^Z*/
u8 ROM_size;
u8 VROM_size;
u8 ROM_type;
u8 ROM_type2;
u8 reserve[8];
} iNES_HEADER;
extern int MapperNo;
extern iNES_HEADER head;
extern u32 ROM_size;
extern u32 VROM_size;
extern u32 iNESGameCRC32;
extern u8 iNESMirroring;
void RomInfo()
{
clearscreen ();
int ypos = 140;
if (screenheight == 480)
ypos += 20;
setfontsize (28);
DrawText (-1, 145, (char*)"Rom Information");
setfontsize (16);
setfontcolour (0xFF, 0xFF, 0xFF);
#define MENU_INFO_ROM "ROM Size"
#define MENU_INFO_VROM "VROM Size"
#define MENU_INFO_CRC "iNES CRC"
#define MENU_INFO_MAPPER "Mapper"
#define MENU_INFO_MIRROR "Mirroring"
char fmtString[1024];
ypos += 20;
DrawText (150, ypos, (char *)MENU_INFO_ROM);
sprintf(fmtString, "%d", head.ROM_size);
DrawText (300, ypos, fmtString);
ypos += 20;
DrawText (150, ypos, (char *)MENU_INFO_VROM);
sprintf(fmtString, "%d", head.VROM_size);
DrawText (300, ypos, fmtString);
ypos += 20;
DrawText (150, ypos, (char *)MENU_INFO_CRC);
sprintf(fmtString, "%08x", iNESGameCRC32);
DrawText (300, ypos, fmtString);
ypos += 20;
DrawText (150, ypos, (char *)MENU_INFO_MAPPER);
sprintf(fmtString, "%d", MapperNo);
DrawText (300, ypos, fmtString);
ypos += 20;
DrawText (150, ypos, (char *)MENU_INFO_MIRROR);
sprintf(fmtString, "%d", iNESMirroring);
DrawText (300, ypos, fmtString);
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 );
}

38
source/ngc/menudraw.h Normal file
View File

@ -0,0 +1,38 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* menudraw.h
*
* Menu drawing routines
****************************************************************************/
#ifndef _MENUDRAW_H_
#define _MENUDRAW_H_
#include "filesel.h"
#define PAGESIZE 13 // 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 Credits ();
void RomInfo ();
void WaitButtonA ();
int RunMenu (char items[][50], int maxitems, char *title, int fontsize, int x);
void DrawMenu (char items[][50], char *title, int maxitems, int selected, int fontsize, int x);
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

314
source/ngc/pad.c Normal file
View File

@ -0,0 +1,314 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* pad.c
*
* Controller input
****************************************************************************/
#include <gccore.h>
#include <wiiuse/wpad.h>
#include <math.h>
#include "driver.h"
#include "fceu.h"
#include "fceuconfig.h"
#include "pad.h"
#include "menu.h"
#include "fceustate.h"
// Original NES controller buttons
// All other pads are mapped to this
unsigned int nespadmap[] = {
JOY_B, JOY_A,
JOY_START, JOY_SELECT,
JOY_UP, JOY_DOWN,
JOY_LEFT, JOY_RIGHT
};
/*** Gamecube controller Padmap ***/
unsigned int gcpadmap[] = {
PAD_BUTTON_B, PAD_BUTTON_A,
PAD_TRIGGER_L, PAD_TRIGGER_R,
PAD_BUTTON_UP, PAD_BUTTON_DOWN,
PAD_BUTTON_LEFT, PAD_BUTTON_RIGHT
};
/*** 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
};
/*** Classic Controller Padmap ***/
unsigned int ccpadmap[] = {
WPAD_CLASSIC_BUTTON_Y, 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
};
/*** Nunchuk + wiimote Padmap ***/
unsigned int ncpadmap[] = {
WPAD_NUNCHUK_BUTTON_C, WPAD_NUNCHUK_BUTTON_Z,
WPAD_BUTTON_MINUS, WPAD_BUTTON_PLUS,
WPAD_BUTTON_UP, WPAD_BUTTON_DOWN,
WPAD_BUTTON_LEFT, WPAD_BUTTON_RIGHT
};
static uint32 JSReturn = 0;
/****************************************************************************
* Initialise Pads
****************************************************************************/
void InitialisePads()
{
int attrib = 0;
void *InputDPR;
FCEUI_DisableFourScore(1);
InputDPR = &JSReturn;
FCEUI_SetInput(0, SI_GAMEPAD, InputDPR, attrib);
FCEUI_SetInput(1, SI_GAMEPAD, InputDPR, attrib);
}
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);
}
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);
}
/****************************************************************************
* Convert GC Joystick Readings to JOY
****************************************************************************/
u8 PADTUR = 2;
unsigned char 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 |= JOY_RIGHT;
if (pad_x < 0 && pad_y == 0) J |= JOY_LEFT;
if (pad_x == 0 && pad_y > 0) J |= JOY_UP;
if (pad_x == 0 && pad_y < 0) J |= JOY_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 |= JOY_RIGHT;
else
J |= JOY_LEFT;
}
if ((float)pad_x / pad_y >= -2.41421356237 && (float)pad_x / pad_y < 2.41421356237)
{
if (pad_y >= 0)
J |= JOY_UP;
else
J |= JOY_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 |= JOY_RIGHT;
if (wm_ax < 0 && wm_ay == 0)
J |= JOY_LEFT;
if (wm_ax == 0 && wm_ay > 0)
J |= JOY_UP;
if (wm_ax == 0 && wm_ay < 0)
J |= JOY_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 |= JOY_RIGHT;
else
J |= JOY_LEFT;
}
/*** Recalc up / down ***/
t = (float) wm_ax / wm_ay;
if (t >= -2.41421356237 && t < 2.41421356237)
{
if (wm_ay >= 0)
J |= JOY_UP;
else
J |= JOY_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 |= nespadmap[i];
}
return J;
}
void GetJoy()
{
unsigned char pad[4];
short i;
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
)
{
AUDIO_StopDMA();
if (GCSettings.AutoLoad == 1)
SaveState(GCSettings.SaveMethod, SILENT);
MainMenu(4);
}
else
{
for (i = 0; i < 4; i++)
pad[i] = DecodeJoy(i);
JSReturn = pad[0] | pad[1] << 8 | pad[2] << 16 | pad[3] << 24;
}
}

33
source/ngc/pad.h Normal file
View File

@ -0,0 +1,33 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* pad.h
*
* Controller input
****************************************************************************/
#ifndef _PAD_H_
#define _PAD_H_
#include <gccore.h>
#define PI 3.14159265f
#define PADCAL 50
#define MAXJP 8
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);
void InitialisePads();
void GetJoy();
#endif

381
source/ngc/preferences.c Normal file
View File

@ -0,0 +1,381 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* preferences.c
*
* Preferences save/load preferences utilities
****************************************************************************/
#include <gccore.h>
#include <stdio.h>
#include <string.h>
#include <ogcsys.h>
#include <mxml.h>
#include "menudraw.h"
#include "memcardop.h"
#include "fileop.h"
#include "smbop.h"
#include "filesel.h"
#include "fceuconfig.h"
#include "pad.h"
extern const unsigned short saveicon[1024];
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 "FCEUGX.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
int i;
for(i=0; i < MAXJP; 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");
createXMLSetting("currpal", "Palette", toStr(GCSettings.currpal));
createXMLSetting("timing", "Timing", toStr(GCSettings.timing));
createXMLSetting("FSDisable", "Four Score", toStr(GCSettings.FSDisable));
createXMLSetting("slimit", "8 Sprite Limit", toStr(GCSettings.slimit));
createXMLSetting("screenscaler", "Screen Scaler", toStr(GCSettings.screenscaler));
createXMLSection("Controller", "Controller Settings");
createXMLController(gcpadmap, "gcpadmap", "GameCube Pad");
createXMLController(wmpadmap, "wmpadmap", "Wiimote");
createXMLController(ccpadmap, "ccpadmap", "Classic Controller");
createXMLController(ncpadmap, "ncpadmap", "Nunchuk");
memset (savebuffer + offset, 0, SAVEBUFFERSIZE);
int datasize = mxmlSaveString(xml, (char *)savebuffer, SAVEBUFFERSIZE, XMLSaveCallback);
mxmlDelete(xml);
return datasize;
}
/****************************************************************************
* Decode Preferences Data
****************************************************************************/
void loadXMLSettingStr(char * var, const char * name)
{
item = mxmlFindElement(xml, xml, "setting", "name", name, MXML_DESCEND);
if(item)
sprintf(var, "%s", mxmlElementGetAttr(item, "value"));
}
void loadXMLSettingInt(int * var, const char * name)
{
item = mxmlFindElement(xml, xml, "setting", "name", name, MXML_DESCEND);
if(item)
*var = atoi(mxmlElementGetAttr(item, "value"));
}
void loadXMLSettingBool(bool * var, const char * name)
{
item = mxmlFindElement(xml, xml, "setting", "name", name, MXML_DESCEND);
if(item)
*var = atoi(mxmlElementGetAttr(item, "value"));
}
void loadXMLController(unsigned int controller[], const char * name)
{
item = mxmlFindElement(xml, xml, "controller", "name", name, MXML_DESCEND);
if(item)
{
// populate buttons
int i;
for(i=0; i < MAXJP; i++)
{
elem = mxmlFindElement(item, xml, "button", "number", toStr(i), MXML_DESCEND);
if(elem)
controller[i] = atoi(mxmlElementGetAttr(elem, "assignment"));
}
}
}
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
loadXMLSettingInt(&GCSettings.AutoLoad, "AutoLoad");
loadXMLSettingInt(&GCSettings.AutoSave, "AutoSave");
loadXMLSettingInt(&GCSettings.LoadMethod, "LoadMethod");
loadXMLSettingInt(&GCSettings.SaveMethod, "SaveMethod");
loadXMLSettingStr(GCSettings.LoadFolder, "LoadFolder");
loadXMLSettingStr(GCSettings.SaveFolder, "SaveFolder");
loadXMLSettingStr(GCSettings.CheatFolder, "CheatFolder");
loadXMLSettingInt(&GCSettings.VerifySaves, "VerifySaves");
// Network Settings
loadXMLSettingStr(GCSettings.smbip, "smbip");
loadXMLSettingStr(GCSettings.smbshare, "smbshare");
loadXMLSettingStr(GCSettings.smbuser, "smbuser");
loadXMLSettingStr(GCSettings.smbpwd, "smbpwd");
// Emulation Settings
loadXMLSettingInt(&GCSettings.currpal, "currpal");
loadXMLSettingInt(&GCSettings.timing, "timing");
loadXMLSettingInt(&GCSettings.FSDisable, "FSDisable");
loadXMLSettingInt(&GCSettings.slimit, "slimit");
loadXMLSettingInt(&GCSettings.screenscaler, "screenscaler");
// 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
****************************************************************************/
bool
LoadPrefs (int method, bool silent)
{
if(method == METHOD_AUTO)
method = autoSaveMethod(); // we use 'Save' folder because preferences need R/W
bool retval = false;
char filepath[1024];
int offset = 0;
if ( !silent )
ShowAction ((char*) "Loading preferences...");
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 = LoadSaveBufferFromSMB (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);
if ( !silent )
WaitPrompt((char *)"Preferences loaded");
}
return retval;
}

13
source/ngc/preferences.h Normal file
View File

@ -0,0 +1,13 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* preferences.h
*
* Preferences save/load preferences utilities
****************************************************************************/
bool SavePrefs (int method, bool silent);
bool LoadPrefs (int method, bool silent);

328
source/ngc/smbop.c Normal file
View File

@ -0,0 +1,328 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* smbload.c
*
* 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 "common.h"
#include "fceuconfig.h"
#include "smbop.h"
#include "gcunzip.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
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 '\'
int i;
for(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 LoadBufferFromSMB((char *)nesromptr, 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
LoadSaveBufferFromSMB (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 = UnZipSMBFile ((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;
}

26
source/ngc/smbop.h Normal file
View File

@ -0,0 +1,26 @@
/****************************************************************************
* FCE Ultra 0.98.12
* Nintendo Wii/Gamecube Port
*
* Tantric September 2008
*
* smbop.h
*
* SMB support routines
****************************************************************************/
#ifndef _SMBOP_H_
#define _SMBOP_H_
bool InitializeNetwork(bool silent);
bool ConnectShare (bool silent);
char * SMBPath(char * path);
int UpdateSMBdirname();
int ParseSMBdirectory ();
int LoadSMBFile (char *filename, int length);
int LoadSaveBufferFromSMB (char *filepath, bool silent);
int LoadBufferFromSMB (char * sbuffer, char *filepath, bool silent);
int SaveBufferToSMB (char *filepath, int datasize, bool silent);
#endif