mirror of
https://github.com/dborth/fceugx.git
synced 2024-10-31 22:45:05 +01:00
2.0 beta
This commit is contained in:
parent
fb1190b4fd
commit
7c6d1b77a2
23
Makefile
Normal file
23
Makefile
Normal 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
|
30
Makefile.gc
30
Makefile.gc
@ -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:
|
||||
|
38
Makefile.wii
38
Makefile.wii
@ -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
219
readme.txt
Normal 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
119
source/ngc/button_mapping.c
Normal 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, ""}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
40
source/ngc/button_mapping.h
Normal file
40
source/ngc/button_mapping.h
Normal 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
38
source/ngc/common.h
Normal 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
547
source/ngc/dvd.c
Normal 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
22
source/ngc/dvd.h
Normal 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
50
source/ngc/fceuconfig.c
Normal 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
61
source/ngc/fceuconfig.h
Normal 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
193
source/ngc/fceugc.c
Normal 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
87
source/ngc/fceuload.c
Normal 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
12
source/ngc/fceuload.h
Normal 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
365
source/ngc/fceustate.c
Normal 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
13
source/ngc/fceustate.h
Normal 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
281
source/ngc/fileop.c
Normal 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
33
source/ngc/fileop.h
Normal 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
580
source/ngc/filesel.c
Normal 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
38
source/ngc/filesel.h
Normal 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
12
source/ngc/fontface.s
Normal file
@ -0,0 +1,12 @@
|
||||
# Fonts
|
||||
|
||||
.rodata
|
||||
.globl fontface
|
||||
.balign 32
|
||||
fontface:
|
||||
.incbin "../source/ngc/ttf/font.ttf"
|
||||
|
||||
|
||||
.globl fontsize
|
||||
fontsize: .long 28736
|
||||
|
113
source/ngc/gcaudio.c
Normal file
113
source/ngc/gcaudio.c
Normal 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
227
source/ngc/gcunzip.c
Normal 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
45
source/ngc/gcunzip.h
Normal 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
634
source/ngc/gcvideo.c
Normal 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
30
source/ngc/gcvideo.h
Normal 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
38412
source/ngc/images/nesback.h
Normal file
File diff suppressed because it is too large
Load Diff
137
source/ngc/images/saveicon.h
Normal file
137
source/ngc/images/saveicon.h
Normal 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
24
source/ngc/intl.h
Normal 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
420
source/ngc/memcardop.c
Normal 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
22
source/ngc/memcardop.h
Normal 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
799
source/ngc/menu.c
Normal 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
18
source/ngc/menu.h
Normal 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
916
source/ngc/menudraw.c
Normal 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
38
source/ngc/menudraw.h
Normal 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
314
source/ngc/pad.c
Normal 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
33
source/ngc/pad.h
Normal 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
381
source/ngc/preferences.c
Normal 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
13
source/ngc/preferences.h
Normal 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
328
source/ngc/smbop.c
Normal 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
26
source/ngc/smbop.h
Normal 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
|
Loading…
Reference in New Issue
Block a user