mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-12-24 18:21:50 +01:00
restored from bountysource
This commit is contained in:
parent
0f863ec61b
commit
fb15609c9e
126
Makefile.gc
Normal file
126
Makefile.gc
Normal file
@ -0,0 +1,126 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
# Clear the implicit built in rules
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(DEVKITPPC)),)
|
||||
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC)
|
||||
endif
|
||||
|
||||
include $(DEVKITPPC)/gamecube_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# INCLUDES is a list of directories containing extra header files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := genplus_cube
|
||||
BUILD := build_cube
|
||||
SOURCES := source source/m68k source/cpu source/sound source/cart_hw \
|
||||
source/cart_hw/svp source/ngc source/ngc/gui
|
||||
INCLUDES := source source/m68k source/cpu source/sound source/cart_hw \
|
||||
source/cart_hw/svp source/ngc source/ngc/gui
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
CFLAGS = -g -fno-strict-aliasing -O2 -Wall $(MACHDEP) $(INCLUDE) -DWORDS_BIGENDIAN -DNGC="1" -DHW_DOL
|
||||
CXXFLAGS = $(CFLAGS)
|
||||
|
||||
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -lfat -logc -lm -lz
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# automatically build a list of object files for our project
|
||||
#---------------------------------------------------------------------------------
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
export LD := $(CC)
|
||||
else
|
||||
export LD := $(CXX)
|
||||
endif
|
||||
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
|
||||
$(sFILES:.s=.o) $(SFILES:.S=.o)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of include paths
|
||||
#---------------------------------------------------------------------------------
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD) \
|
||||
-I$(LIBOGC_INC)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of library paths
|
||||
#---------------------------------------------------------------------------------
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
|
||||
-L$(LIBOGC_LIB)
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
.PHONY: $(BUILD) clean
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT).dol: $(OUTPUT).elf
|
||||
$(OUTPUT).elf: $(OFILES)
|
||||
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
@ -1,49 +1,46 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
# Generic makefile for Gamecube projects
|
||||
#
|
||||
# Tab stops set to 4
|
||||
# | | | |
|
||||
# 0 1 2 3
|
||||
#---------------------------------------------------------------------------------
|
||||
# Clear the implicit built in rules
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(DEVKITPPC)),)
|
||||
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC)
|
||||
endif
|
||||
|
||||
include $(DEVKITPPC)/wii_rules
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# INCLUDES is a list of directories containing extra header files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := genplus
|
||||
BUILD := build
|
||||
SOURCES := source source/m68k source/cpu source/sound \
|
||||
source/ngc source/ngc/gui source/ngc/vfat
|
||||
INCLUDES := source source/m68k source/cpu source/sound \
|
||||
source/ngc source/ngc/gui source/ngc/vfat
|
||||
TARGET := genplus_wii
|
||||
BUILD := build_wii
|
||||
SOURCES := source source/m68k source/cpu source/sound source/cart_hw\
|
||||
source/cart_hw/svp source/ngc source/ngc/gui
|
||||
INCLUDES := source source/m68k source/cpu source/sound source/cart_hw\
|
||||
source/cart_hw/svp source/ngc source/ngc/gui
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
MACHDEP = -DGEKKO -mcpu=750 -meabi -mhard-float
|
||||
CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) -DWORDS_BIGENDIAN \
|
||||
-DNGC="1" -DGENESIS_HACKS="1" \
|
||||
|
||||
LDFLAGS = $(MACHDEP) -mogc -Wl,-Map,$(notdir $@).map -Wl,--cref
|
||||
CFLAGS = -g -O2 -mrvl -Wall $(MACHDEP) -fno-strict-aliasing $(INCLUDE) -DWORDS_BIGENDIAN -DNGC="1" -DHW_RVL
|
||||
CXXFLAGS = $(CFLAGS)
|
||||
|
||||
PREFIX := powerpc-gekko-
|
||||
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
|
||||
|
||||
#export PATH:=/c/devkitPPC_r11/bin:/bin
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -lfat -lwiiuse -lbte -logc -lm -lz
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := /c/devkitPro/devkitPPC
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -logc -lm -lz -logcsys -lsdcard
|
||||
LIBDIRS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
@ -51,13 +48,14 @@ LIBS := -logc -lm -lz -logcsys -lsdcard
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))
|
||||
|
||||
export CC := $(PREFIX)gcc
|
||||
export CXX := $(PREFIX)g++
|
||||
export AR := $(PREFIX)ar
|
||||
export OBJCOPY := $(PREFIX)objcopy
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# automatically build a list of object files for our project
|
||||
#---------------------------------------------------------------------------------
|
||||
@ -65,6 +63,8 @@ CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
@ -74,32 +74,36 @@ else
|
||||
export LD := $(CXX)
|
||||
endif
|
||||
|
||||
export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(sFILES:.s=.o) $(SFILES:.S=.o)
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
|
||||
$(sFILES:.s=.o) $(SFILES:.S=.o)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of include paths
|
||||
#---------------------------------------------------------------------------------
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
-I$(CURDIR)/$(BUILD) \
|
||||
-I$(LIBOGC_INC)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of library paths
|
||||
#---------------------------------------------------------------------------------
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
|
||||
-L$(LIBOGC_LIB)
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
.PHONY: $(BUILD) clean
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir $@
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) *.elf
|
||||
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
run:
|
||||
@ -119,56 +123,19 @@ DEPENDS := $(OFILES:.o=.d)
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT).dol: $(OUTPUT).elf
|
||||
@echo output ... $(notdir $@)
|
||||
@$(OBJCOPY) -O binary $< $@
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT).elf: $(OFILES)
|
||||
@echo linking ... $(notdir $@)
|
||||
@$(LD) $^ $(LDFLAGS) $(LIBPATHS) $(LIBS) -o $@
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# Compile Targets for C/C++
|
||||
# This rule links in binary data with the .jpg extension
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
%.jpg.o : %.jpg
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o : %.cpp
|
||||
@echo Compiling ... $(notdir $<)
|
||||
@$(CXX) -MMD $(CFLAGS) -o $@ -c $<
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o : %.c
|
||||
@echo Compiling ... $(notdir $<)
|
||||
@$(CC) -MMD $(CFLAGS) -o $@ -c $<
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o : %.S
|
||||
@echo Compiling ... $(notdir $<)
|
||||
@$(CC) -MMD $(CFLAGS) -D_LANGUAGE_ASSEMBLY -c $< -o $@
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o : %.s
|
||||
@echo Compiling ... $(notdir $<)
|
||||
@$(CC) -MMD $(CFLAGS) -D_LANGUAGE_ASSEMBLY -c $< -o $@
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# canned command sequence for binary data
|
||||
#---------------------------------------------------------------------------------
|
||||
define bin2o
|
||||
cp $(<) $(*).tmp
|
||||
$(OBJCOPY) -I binary -O elf32-powerpc -B powerpc \
|
||||
--rename-section .data=.rodata,readonly,data,contents,alloc \
|
||||
--redefine-sym _binary_$*_tmp_start=$*\
|
||||
--redefine-sym _binary_$*_tmp_end=$*_end\
|
||||
--redefine-sym _binary_$*_tmp_size=$*_size\
|
||||
$(*).tmp $(@)
|
||||
echo "extern const u8" $(*)"[];" > $(*).h
|
||||
echo "extern const u32" $(*)_size[]";" >> $(*).h
|
||||
rm $(*).tmp
|
||||
endef
|
||||
@echo $(notdir $<)
|
||||
$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
6
compile_all.bat
Normal file
6
compile_all.bat
Normal file
@ -0,0 +1,6 @@
|
||||
cp Makefile.gc Makefile
|
||||
make
|
||||
cp Makefile.wii Makefile
|
||||
make
|
||||
rm Makefile
|
||||
cp genplus_wii.dol boot.dol
|
BIN
gen_eeprom.doc
BIN
gen_eeprom.doc
Binary file not shown.
BIN
genplus.doc
BIN
genplus.doc
Binary file not shown.
230
history.txt
230
history.txt
@ -1,32 +1,211 @@
|
||||
Genesis Plus for Gamecube
|
||||
------------------------------
|
||||
|
||||
CHANGELOG:
|
||||
current:
|
||||
---------
|
||||
[Genesis]
|
||||
- "cycle-accurate" HINT timings: every timing sensitive games/demos are now *finally* working fine
|
||||
- fixed CRAM/VSRAM DMA timings
|
||||
- fixed SAT address mask on VRAM writes
|
||||
- improved accuracy of 68k access to Z80: fix music in Pacman 2 when entering PAUSE menu
|
||||
- disabled "Address Error" emulation when UMK3 hack is loaded: fix game crashing after a round ends up
|
||||
- added support for some additional protected "pirate" games: Pocket Monster, King of Fighter 98, Soul Blade (credits to Haze)
|
||||
- improved overall Menacer emulation accuracy
|
||||
- fixed Menacer support in Terminator 2: Arcade Game
|
||||
- added Konami Justifier emulation: fix lightgun support in Lethal Enforcers 1 & 2
|
||||
- (YM2612) fixed LFO phase update for CH3 special mode in MAME core: fix some SFX in Warlock & Alladin (thanks to AamirM)
|
||||
- (YM2612) fixed enveloppe attenuation level on "KEY ON" in MAME core: fix Ecco 2's splash sound
|
||||
|
||||
[Wii]
|
||||
- added Wiimote IR pointing for LightGun control (Menacer/Justifier)
|
||||
|
||||
16/07/2008:
|
||||
-----------
|
||||
[Genesis]
|
||||
- adjusted (again) HINT timings: fix Double Dragon 2 (game freezed), hopefully does not break anything else
|
||||
- fixed broken EEPROM support for Codemaster games
|
||||
- modified input update timings: fix Dungeons & Dragons - Warriors of the Eternal Sun (thanks to Notaz)
|
||||
- added support for "Ultimate Mortal Kombat Trilogy" hack (max. size supported is 10MBytes)
|
||||
- added (VERY) preliminar support for PICO roms (credits to Notaz for his documentation)
|
||||
- improved YM2612 emulation (credits to Nemesis for his tests on real hardware):
|
||||
.implemented phase overflow emulation: improved fix for special music instrument used in Comix Zone, Flashback, Ariel, Shaq Fu...
|
||||
.improved SSG-EG emulation in MAME core (also based on additional code from Alone Coder)
|
||||
.improved Timers emulation accuracy
|
||||
.improved Enveloppe Generator accuracy
|
||||
.fixed Channel 3 CSM mode emulation
|
||||
.implemented sample interpolation in MAME core to emulate the chip at original frequency (HQ YM2612 mode, from gens)
|
||||
|
||||
[NGC/Wii]
|
||||
- added automatic alphabetical filesorting (Marty Disibio)
|
||||
- added ROM History for faster ROM access (Marty Disibio)
|
||||
- fixed a silly input bug in "ROM Infos" & "Game Genie" menus
|
||||
- modified "Hard Reset" option
|
||||
- improved display sharpness in original rendering mode (H40 cell mode only), filtering is now completely disabled
|
||||
- enabled overscan emulation in "STRETCH" aspect mode also
|
||||
- added support for horizontal wiimote handling in Menu (automatically used when the wiimote is not pointed towards the screen)
|
||||
- improved Controller options
|
||||
.prevented keys reconfiguration if device is not detected
|
||||
.added support for up to 8 players (ISS Pro Deluxe, ...)
|
||||
.each player can be affected to a custom device (GAMECUBE Pad, WIIMOTE/NUNCHUK or CLASSIC)
|
||||
.added the ability to use classic controller & wiimote pad from the same port separately
|
||||
.modified "soft-reset" key on the Wiimote to avoid "accidental" resets (now press Buttons + & - simultaneously)
|
||||
.added MODE button mapping: use "START+Z" on gamepad or "Button Minus" on wiimote/classic (not reconfigurable)
|
||||
.added automatic configuration save for controller options
|
||||
|
||||
|
||||
|
||||
01/06/2008:
|
||||
-----------
|
||||
[Genesis]
|
||||
- improved HCounter accuracy: fix graphic glitches in "Striker (Europe)"
|
||||
- improved HINT timing accuracy: fix flickering in "Zero The Kamikaze Squirrel (USA)"
|
||||
- improved rendering accuracy when backdrop color is modified during HBLANK (Road Rash I/II/III)
|
||||
- fixed broken Game Genie support
|
||||
|
||||
[NGC/Wii]
|
||||
- added full horizontal scaling (up to 720 pixels) when using "stretch" aspect mode (use Xscale to increase width)
|
||||
- added progressive mode support (480p) in menu also
|
||||
- added automatic SRAM/FreezeState support (OFF by default, check "system options")
|
||||
- added automatic configuration file support
|
||||
- /genplus/saves is now automatically created if it does not exist
|
||||
- use libfat automatic SDCARD detection: default slot is now always used when accessing SDCARD
|
||||
- assigned Reset Button to Genesis Soft-Reset
|
||||
|
||||
[Wii only]
|
||||
- added automatic TV mode detection (from SYSCONF), no more PAL60 version needed
|
||||
- added option to return to Wii System Menu
|
||||
- fixed "TP reload" option: now compatible with HB channel
|
||||
- removed SD-Gekko support (Wii slot becomes default slot)
|
||||
- added Wii SD slot support for SRAM & FreezeState files
|
||||
- added Wiimote, Nunchuk & Classic controllers support through libwiiuse (see User Manual for default keys)
|
||||
- added customizable key mapping (for each configurations: wiimote only, wiimote+nunchuk or classic)
|
||||
|
||||
|
||||
19/04/2008:
|
||||
-----------
|
||||
[Genesis]
|
||||
- modified VINT timings a little bit: fix lockup during Desert Strike's intro
|
||||
- corrected 68k interrupts handling: fix graphic glitches in Darius II/Sagaia
|
||||
|
||||
[NGC/Wii]
|
||||
- fixed 60Hz "Bilinear" rendering mode (was broken in last release)
|
||||
- fixed issue with the 1st file when browsing SDCARD through SD-Gekko
|
||||
- fixed GX initialization: fix "freeze" issue that occured sometime when starting a game
|
||||
- added "Wii Reboot" option
|
||||
- added PAL 50hz support in menu (black borders)
|
||||
- added progressive rendering mode support (480p) in Wii mode (not supported by the PAL60 version, use the other one !)
|
||||
- compiled with a modified libogc: should definitely fix the PAL "red screen" issue for RGB-cable users (still use the PAL60 version !)
|
||||
|
||||
|
||||
06/04/2008:
|
||||
-----------
|
||||
[Genesis]
|
||||
- updated SVP core: fix some perspective issues in Virtua Racing (thanks to Notaz)
|
||||
- added internal SAT update during VRAM Fill: fix unmasked sprites during Battletech's intro
|
||||
- fixed m68k core issues with gcc 4.2.3: fix Xperts, Lemmings 2, M1 Abrams Battle Tank
|
||||
- forced YM2612 Enveloppe update: fix intro music in Batman&Robin (thanks to Aamir)
|
||||
|
||||
[NGC/Wii]
|
||||
- removed not working DVD features (Wii mode only)
|
||||
- fixed Timers with PAL roms
|
||||
- added EURGB60 TV mode support: fix "red screen" issue with PAL Wii when using RGB cable
|
||||
- added PAL50 TV mode support (PAL and NTSC roms), see video options
|
||||
- added "TP reload" option, use "System Reboot" (Wii mode only)
|
||||
- added Front SD rom loading support with LFN & subdirectory browsing (Wii mode only)
|
||||
|
||||
|
||||
01/03/2008:
|
||||
-----------
|
||||
[Genesis]
|
||||
- added SVP emulation: Virtua Racing is now emulated (big thanks to Notaz and TascoDeluxe)
|
||||
- fixed VDP registers behaviour when VDP Mode 4 is enabled: fix Bass Masters Classic Pro, Captain Planet & The Planeeters
|
||||
- corrected a bug in DMA Fill operation: fix James Pond 3, Rockman World/Megaman Willy Wars (corrupted VRAM)
|
||||
- corrected typo errors in CPU cycle counters update: fix optiom screen music in "College Slam" and probably others games.
|
||||
- added preliminary support of undocumented YM2612 bug: fixes soundtracks of Shaq Fu, Spiderman, Comix Zone, Ariel and some others
|
||||
- added support for mappers & copy protection devices used in many unlicensed/pirate cartridges (see cart_hw.c for details)
|
||||
- rewrote memory handlers for better modularity and some (little) speedup
|
||||
- reduced Savestate size
|
||||
|
||||
[NGC]
|
||||
- compiled with last LibOGC (20080228): fix issues when unplugging controller, support for Wii mode (see release.txt)
|
||||
- added "hard-coded" IPL font (no more direct access to BOOTROM): fix font problem for Qoob users
|
||||
- added SDCARD Slot B support for loading Roms
|
||||
- removed unused MAME PSG Core
|
||||
- added 'Force DTACK' option for prototype games usually hanging on real hardware (example: Sonic Crackers)
|
||||
- added an option to underclock SVP core (with default cycle count, Virtua Racing actually does not run fullspeed in GC mode)
|
||||
- fixed frame timing in PAL mode
|
||||
- fixed analog stick sensitivity
|
||||
|
||||
|
||||
07/01/2008:
|
||||
-----------
|
||||
[Genesis]
|
||||
- fixed interleaved rom detection: roms with .smd extension should now work fine
|
||||
- fixed a recently introduced bug in VDP registers writes: fixes bad colors in Toy Story (intro)
|
||||
- updated list of games using EEPROM: added Sports Talk Baseball (internal memory check fixed) and Brian Lara Cricket
|
||||
- fixed VINT flag update when VINT is disabled: fixes NCAA College Football
|
||||
- adjusted DMA timings in H32 mode: fixes flickering in Out of this World, Kawasaki Superbike Challenge & Formula One
|
||||
- adjusted line rendering and HBLANK timings: fixes flickering in Nigel Mansell's World Championship Racing, Deadly Moves/Power Athlete
|
||||
- fixed unmapped ROM reads through Z80 Bank: fixes Zombie High (Proto)
|
||||
- added support for custom ROM/RAM mapping used by Game no Kanzume Otokuyou
|
||||
|
||||
[NGC]
|
||||
- fixed broken SDCARD support for SRAM and Savestate files
|
||||
|
||||
|
||||
30/12/2007:
|
||||
-----------
|
||||
- fixed ROM injector base address (DATA section 1)
|
||||
|
||||
|
||||
28/12/2007:
|
||||
-----------
|
||||
[Genesis]
|
||||
- many sourcecode cleanup and optimization
|
||||
- completely rewrote EEPROM emulation: now support all known EEPROM types (24C01-24C65) and mappers (Sega, Acclaim, EA, Codemasters)
|
||||
used in a few games (now use game database) as backup RAM. This should fix SRAM load/save support in the following games:
|
||||
|
||||
used in a few games (now use internal game database) as external RAM. This should at least fix save support in the following games:
|
||||
. NBA Jam (alternate Acclaim mapper)
|
||||
. College Slam, Frank Thomas Big Hurt Baseball (24C65 type)
|
||||
. NHLPA Hockey 93, Rings of Power (EA mapper)
|
||||
. Micromachines games (Codemasters mapper)
|
||||
. Micro Machines serie, Brian Lara Cricket 96/Shane Warne Cricket (Codemasters mapper)
|
||||
|
||||
- SRAM is now initialized with 0xFF data: fix Micromachines 2, Dino Dini Soccer
|
||||
- fixed SRAM word read/write handler: fix some Sega Sports and EA Sports games (NFL95, NBA Action 95, NL97, NHL98,...) which previously hang
|
||||
- modified WRITE_xxx & READ_xxx macros for portability
|
||||
- rewrote BIG ENDIAN support in render.c and vdp.c: it should be a little faster now (no more useless swapping)
|
||||
- fixed leftmost Window/PlaneA column render and implemented Window bug (as described in gen-vdp.txt)
|
||||
- improved Sprite Limit emulation and Sprite Collision detection
|
||||
- fixed test made before CRAM writes
|
||||
- removed redundant "color_update()" calls
|
||||
- added 9bits (RGB333) pixel color extrapolation to cover full color range (0-31;0-63) in 16-bit rendering mode (RGB565)
|
||||
- rewrote Interrupts handling: Sesame's Street Counting Cafe now works without any hacks, other timing sensitive games seems not to be affected
|
||||
- modified Hcounter tables: Road Rash games (I,II,III) don't need any timing hacks anymore
|
||||
- fixed VDP latency so it does not interfere with DMA timings anymore
|
||||
- external RAM is now initialized to 0xFF by default: fix Micromachines 2, Dino Dini Soccer
|
||||
- fixed SRAM 16-bits memory handlers: fix some Sega Sports and EA Sports games (NFL95, NBA Action 95, NHL97, NHL98,...)
|
||||
- modified WRITE_xxx & READ_xxx macros for better portability and faster memory access on BIG ENDIAN platform
|
||||
- completely rewrote BIG ENDIAN support in render.c and vdp.c: rendering should be a little faster
|
||||
- rewrote ROM bankswitch emulation (Super Street Fighter II): ROM access are faster, using memory pointers instead of reading ROM copy from ARAM
|
||||
- fixed leftmost Window/PlaneA column render and implemented Window bug (as described by Charles Mc Donald)
|
||||
- improved "Sprite Limit" and "Sprite Collision" detection accuracy
|
||||
- modified RGB565 Color Palette to use the full available color range (0-31;0-63)
|
||||
- implemented "cycle accurate" HV Interrupt timings: fix Sesame's Street Counting Cafe, Legend of Galahad (intro)
|
||||
- improved VDP access timings accuracy (added FIFO emulation): fix Double Clutch
|
||||
- improved DMA timings accuracy: fix Winter Olympics (E), Arch Rivals and probably more
|
||||
- fixed HCounter again: Road Rash serie (I,II,III) don't need timing hacks anymore
|
||||
- fixed VCounter in Interlaced 2 mode: fix Combat Cars "VS-Mode"
|
||||
- improved Interlaced 2 mode (double resolution) rendering: Sonic 2, Combat Cars ("VS-Modes") look far better
|
||||
- added TMSS BIOS support (optional)
|
||||
- rewrote part of the YM2162 MAME's core: fixed internal FM timers handling, removed non-YM2612 emulation code and unused multiple cpu support
|
||||
- implemented "cycle accurate" FM timers & sound samples rendering
|
||||
- improved Z80 Interrupt timing accuracy: fix Sonic 3 music slowdowns
|
||||
- updated Z80 & 68000 cores to last MAME versions
|
||||
- improved Soft Reset emulation: X-Men 2 and Eternal Champions (random character selection) now work more like on real hardware.
|
||||
- added full overscan emulation (vertical & horizontal borders) for "pixel perfect" aspect ratio (tested against a real genesis)
|
||||
|
||||
[NGC]
|
||||
- fixed rom checksum calculation (only used for rom information)
|
||||
- some modifications in GX rendering code.
|
||||
- added support for original Genesis/Megadrive NTSC & PAL video modes: this makes games looking exactly as on original hardware (progressive rendering with reduced resolution)
|
||||
- added "Aspect" option to switch between ORIGINAL (aspect ratio is fixed and borders are emulated) and MANUAL SET (horizontal and vertical scaling can be manually configured, borders are not emulated)
|
||||
- added "Overscan" option to disable the original borders color and always use black borders (only used when ORIGINAL Aspect mode is enabled)
|
||||
- added support for up to 720 pixels horizontal resolution (needed for proper aspect ratio emulation)
|
||||
- added "TV Mode" option to enable automatic switching to PAL(50Hz) TV mode when the Genesis runs in PAL mode
|
||||
- added "Xshift" & "Yshift" settings to let you adjust display area position while keeping the original aspect ratio
|
||||
- added option to disable/enable SSG-EG support in FM cores: this special mode is indeed not properly emulated and some games might sound wrong when enabled
|
||||
- removed "CPU Type" option, you can also now force Region (JAP/EUR/USA) without reseting the game, choose USA or JAP for 60hz, EUR for 50hz, this can be useful to bypass game region protection at startup.
|
||||
|
||||
|
||||
20/07/2007:
|
||||
-----------
|
||||
[Genesis]
|
||||
- corrected TeamPlayer support: fix multiplayer in Gauntlet 4 (Sept. version), Pengo and a lot of others
|
||||
- added J-Cart support: enable multiplayer in Codemasters games (Pete Sampras, Micromachines games, Super Skidmarks)
|
||||
@ -53,14 +232,18 @@ used in a few games (now use game database) as backup RAM. This should fix SRAM
|
||||
. use Left/Right buttons or Analog stick to scroll the selected entry's filename when it can't be full displayed
|
||||
- various menu rearrangment, minor bugfixes & sourcecode cleanup
|
||||
|
||||
|
||||
21/06/2007:
|
||||
-----------
|
||||
- added 4.7GB DVD support for WII drives (the maximal allowed size for Gamecube DVD is still 1.35GB)
|
||||
- removed MPAL video timings, always use 60Hz NTSC: fix display problems for PAL wii users (no more PAL50 version needed)
|
||||
- added Console Reboot option in main menu (IPL Reboot)
|
||||
- added Multitap support (EA 4-Way Play and Sega Teamplayer): allowed up to four players in games supporting those peripherals
|
||||
- added partial Sega Menacer lightgun support (use Analog Stick): automatically set when detecting the 6-in-1 Menacer game
|
||||
|
||||
|
||||
18/05/2007:
|
||||
-----------
|
||||
- you can now switch between FM cores without reseting the game. FM registers value are automatically restored when switching.
|
||||
- modified PAL framesync a little bit: the 20ms period is now applied between the start of 2 consecutive frames,
|
||||
no more between the end of the previous and the start of the next one, which seems more correct to me
|
||||
@ -69,13 +252,14 @@ no more between the end of the previous and the start of the next one, which see
|
||||
This means you can still modify some of these options afterwards but they are now automatically set/unset when loading a game which need
|
||||
special timing fixes. These fixes are also automatically desactivated when the current game doesn't need them.
|
||||
|
||||
For your information, games that are actually detected and need special timings to run properly are:
|
||||
For information, games that are actually detected and need special timings to run properly are:
|
||||
.Legend of Galahad & Road Rash series (single line not rendered properly)
|
||||
.Sesame Street Counting Cafe (don't boot)
|
||||
.Chaos Engine/Soldiers of Fortune (graphic glitches on scrolling)
|
||||
|
||||
|
||||
08/05/2007:
|
||||
-----------
|
||||
- corrected L & R buttons assignment: fixes Genesis X & Z buttons being inverted
|
||||
- VINT timings are now a little more accurate: fixes Sesame's Street Counting Cafe
|
||||
- SN76496 MAX_OUTPUT back to normal
|
||||
@ -87,26 +271,36 @@ For your information, games that are actually detected and need special timings
|
||||
- added configurable preamplification for each sound cores (see Emulator Options)
|
||||
- added some other configurable sound options (boost overall volume, FM improvment for Gens YM2612)
|
||||
|
||||
|
||||
11/04/2007:
|
||||
-----------
|
||||
- corrected MAX_OUTPUT value in SN76496 core: fix PSG sound (SFX) volume
|
||||
- removed unused sound buffer allocation
|
||||
|
||||
|
||||
26/03/2007:
|
||||
-----------
|
||||
- added DVD automount: automatically call libogc DVD_Mount function if ISO PVD reading failed (idea taken from softdev's last neocdredux release). This may be useful for loading roms from a DVD after booting from SDLOAD or after stopping DVD motor.
|
||||
- added "DVD motor off" feature, like in others emulators
|
||||
- corrected Memory Card mounting function: EXI_ProbeReset() function was never called if the first mounting attempt failed. Should fix some of the "Unable to mount memory card" errors.
|
||||
|
||||
|
||||
22/03/2007:
|
||||
-----------
|
||||
- added SDCARD subdirectory browsing and LFN (255 char. max) support
|
||||
|
||||
|
||||
17/03/2007:
|
||||
-----------
|
||||
- remove some rendering unused code (only used by DOS version of genesis plus) for little speedup
|
||||
- added an option to enable alternate line rendering timing (fix single line error in Road Rash series and Legend of Galahad's Intro)
|
||||
- Color RAM update now always reset color 0 to border color (fix color glitches in Mortal Kombat,...) (thanks to Noop's for the idea)
|
||||
- added last Softdev's modifications (normalised memory access and ASM GU functions used intead of 'C' ones) for some speedup
|
||||
- updated gcaram.c to be compatible with last libogc version
|
||||
|
||||
|
||||
09/03/2007:
|
||||
-----------
|
||||
- little rendering code speedups
|
||||
- modified HV counter tables (fix graphic glitches in Skitchin's sky, Lotus 2 Recs, Panorama Cotton, Dashin Desperados & maybe more)
|
||||
- completely rewrote DMA timings emulation so that it works for all games (no more cpu freezing)
|
||||
@ -122,7 +316,9 @@ For your information, games that are actually detected and need special timings
|
||||
- modified main frame synchro in PAL mode (fix sound glitch in this mode), thanks to Softdev for the solution
|
||||
- added savestates support (go to SRAM menu, memory card supports only)
|
||||
|
||||
|
||||
07/02/2007: (Eke-Eke)
|
||||
---------------------
|
||||
- fm timers fixed (fix missing music in Castle of Illusion, Quackshot, Undead Line, Wonderboy in Monster Lair, Cal 50, Turbo Outrun, Thundeforce 4 and maybe more)
|
||||
- added complete EEPROM emulation (save support now works fine in Wonderboy5, Megaman Willy Wars, NBA Jam...) (credits to Notaz, adapted from Picodrive code)
|
||||
- added preliminar dma timing emulation (fix bottom screen in Legend of Galahad) (credits to Notaz, adapted from Picodrive code)
|
||||
|
@ -43,7 +43,7 @@ unsigned int FLIP32(unsigned int b)
|
||||
return c;
|
||||
}
|
||||
|
||||
#define ROMOFFSET 0x80600000
|
||||
#define ROMOFFSET 0x80700000
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
|
600
source/cart_hw/cart_hw.c
Normal file
600
source/cart_hw/cart_hw.c
Normal file
@ -0,0 +1,600 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* Cartridge Hardware support
|
||||
*
|
||||
* code by Eke-Eke, GC/Wii port
|
||||
*
|
||||
* Lots of protection mechanism have been discovered by Haze
|
||||
* (http://haze.mameworld.info/)
|
||||
*
|
||||
* Realtec mapper has been figured out by TascoDeluxe
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#include "m68kcpu.h"
|
||||
|
||||
#define CART_CNT 26
|
||||
|
||||
/* Function prototypes */
|
||||
void default_time_w(unsigned int address, unsigned int value);
|
||||
void special_mapper_w(unsigned int address, unsigned int value);
|
||||
void realtec_mapper_w(unsigned int address, unsigned int value);
|
||||
void seganet_mapper_w(unsigned int address, unsigned int value);
|
||||
unsigned int radica_mapper_r(unsigned int address);
|
||||
void default_regs_w(unsigned int address, unsigned int value);
|
||||
unsigned int default_regs_r(unsigned int address);
|
||||
void special_regs_w(unsigned int address, unsigned int value);
|
||||
|
||||
/* Cart database entry */
|
||||
typedef struct
|
||||
{
|
||||
uint16 chk_1; /* header checksum */
|
||||
uint16 chk_2; /* real checksum */
|
||||
uint8 bank_start; /* first mapped bank in $400000-$7fffff region */
|
||||
uint8 bank_end; /* last mapped bank in $400000-$7fffff region */
|
||||
T_CART_HW cart_hw; /* hardware description */
|
||||
} T_CART_ENTRY;
|
||||
|
||||
/* Games that need extra hardware emulation:
|
||||
- copy protection device
|
||||
- custom ROM banking device
|
||||
*/
|
||||
T_CART_ENTRY rom_database[CART_CNT] =
|
||||
{
|
||||
/* Game no Kanzume Otokuyou */
|
||||
{0x0000,0xf9d1,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,seganet_mapper_w,0,0}},
|
||||
/* RADICA (Volume 1) (not byteswapped) */
|
||||
{0x0000,0x2326,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,radica_mapper_r,0,0,0}},
|
||||
/* RADICA (Volume 2) */
|
||||
{0x4f10,0x0836,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,radica_mapper_r,0,0,0}},
|
||||
/* RADICA (Volume 1) */
|
||||
{0xf424,0x9f82,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,radica_mapper_r,0,0,0}},
|
||||
/* Funny World & Balloon Boy */
|
||||
{0x0000,0x06ab,8,8,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,0,0,0,realtec_mapper_w}},
|
||||
/* Whac-a-Critter */
|
||||
{0xffff,0xf863,8,8,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,0,0,0,realtec_mapper_w}},
|
||||
/* Earth Defense */
|
||||
{0xffff,0x44fb,8,8,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,0,0,0,realtec_mapper_w}},
|
||||
/* Super Mario 2 1998 */
|
||||
{0xffff,0x0474,0,0,{{0x0a,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,default_regs_r,0,0,0}},
|
||||
/* Super Mario 2 1998 */
|
||||
{0x2020,0xb4eb,0,0,{{0x1c,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,default_regs_r,0,0,0}},
|
||||
/* Supper Bubble Bobble */
|
||||
{0x0000,0x16cd,8,8,{{0x55,0x0f,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x400002,0,0},0,0,0,default_regs_r,0}},
|
||||
/* Mahjong Lover */
|
||||
{0x0000,0x7037,8,8,{{0x90,0xd3,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x401000,0,0},0,0,0,default_regs_r,0}},
|
||||
/* Lion King 2 */
|
||||
{0xffff,0x1d9b,8,8,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,default_regs_r,default_regs_w}},
|
||||
/* Squirell King */
|
||||
{0x0000,0x8ec8,8,8,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,default_regs_r,default_regs_w}},
|
||||
/* Rockman X3 */
|
||||
{0x0000,0x9d0e,8,8,{{0x0c,0x88,0,0},{0xffffff,0xffffff,0,0},{0xa13000,0x400004,0,0},0,default_regs_r,0,default_regs_r,0}},
|
||||
/* A Bug's Life */
|
||||
{0x7f7f,0x2aad,0,0,{{0x28,0x1f,0x01,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,default_regs_r,0,0,0}},
|
||||
/* King of Fighter 99 */
|
||||
{0x0000,0x21e,0,0,{{0x00,0x01,0x1f,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,default_regs_r,0,0,0}},
|
||||
/* Pocket Monster */
|
||||
{0xd6fc,0x1eb1,0,0,{{0x00,0x01,0x1f,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,default_regs_r,0,0,0}},
|
||||
/* Lion King 3 */
|
||||
{0x0000,0x507c,12,15,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,0,0,default_regs_r,special_regs_w}},
|
||||
/* Super King Kong 99 */
|
||||
{0x0000,0x7d6e,12,15,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,0,0,default_regs_r,special_regs_w}},
|
||||
/* Pokemon Stadium */
|
||||
{0x0000,0x843c,14,15,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,0,0,special_regs_w}},
|
||||
/* Elf Wor */
|
||||
{0x0080,0x3dba,8,8,{{0x55,0x0f,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,default_regs_r,0}},
|
||||
/* Huan Le Tao Qi Shu - Smart Mouse */
|
||||
{0x0000,0x1a28,8,8,{{0x55,0x0f,0xaa,0xf0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,default_regs_r,0}},
|
||||
/* Ya-Se Chuanshuo */
|
||||
{0xffff,0xd472,8,8,{{0x63,0x98,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,default_regs_r,0}},
|
||||
/* Soul Blade */
|
||||
{0x0000,0x0c5b,8,8,{{0x00,0x98,0xc9,0xF0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,default_regs_r,0}},
|
||||
/* King of Fighter 98 */
|
||||
{0x0000,0xd0a0,9,9,{{0xaa,0xa0,0xf0,0xa0},{0xfc0000,0xffffff,0xffffff,0xffffff},{0x480000,0x4c82c0,0x4cdda0,0x4f8820},0,0,0,default_regs_r,0}},
|
||||
/* Lian Huan Pao - Barver Battle Saga */
|
||||
{0x30b9,0x1c2a,8,8,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,0,default_regs_r,0}}
|
||||
};
|
||||
|
||||
|
||||
/* current cart hardware */
|
||||
T_CART_HW cart_hw;
|
||||
uint8 j_cart;
|
||||
|
||||
static int old_system[2] = {-1,-1};
|
||||
|
||||
/************************************************************
|
||||
Cart Hardware initialization
|
||||
*************************************************************/
|
||||
|
||||
/* hardware that need to be reseted on power on */
|
||||
void cart_hw_reset()
|
||||
{
|
||||
/* Realtec mapper */
|
||||
if (cart_hw.realtec & 1)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* enable BOOTROM */
|
||||
for (i=0; i<8; i++) m68k_readmap_16[i] = REALTEC_ROM;
|
||||
cart_hw.realtec |= 2;
|
||||
}
|
||||
|
||||
/* SVP chip */
|
||||
if (svp) svp_reset();
|
||||
}
|
||||
|
||||
/* cart hardware detection */
|
||||
void cart_hw_init()
|
||||
{
|
||||
int i;
|
||||
|
||||
/**********************************************
|
||||
DEFAULT CART MAPPING
|
||||
***********************************************/
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = ROM;
|
||||
m68k_readmap_16[i] = ROM;
|
||||
m68k_writemap_8[i] = UNUSED;
|
||||
m68k_writemap_16[i] = UNUSED;
|
||||
}
|
||||
|
||||
for (i=8; i<16; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = UNUSED;
|
||||
m68k_readmap_16[i] = UNUSED;
|
||||
m68k_writemap_8[i] = UNUSED;
|
||||
m68k_writemap_16[i] = UNUSED;
|
||||
}
|
||||
|
||||
/* restore previous setting */
|
||||
if (old_system[0] != -1) input.system[0] = old_system[0];
|
||||
if (old_system[1] != -1) input.system[1] = old_system[1];
|
||||
|
||||
/**********************************************
|
||||
EXTERNAL RAM
|
||||
***********************************************/
|
||||
sram_init();
|
||||
eeprom_init();
|
||||
if (sram.on)
|
||||
{
|
||||
if (sram.custom)
|
||||
{
|
||||
/* serial EEPROM */
|
||||
m68k_readmap_8[eeprom.type.sda_out_adr >> 19] = EEPROM;
|
||||
m68k_readmap_16[eeprom.type.sda_out_adr >> 19] = EEPROM;
|
||||
m68k_writemap_8[eeprom.type.sda_in_adr >> 19] = EEPROM;
|
||||
m68k_writemap_16[eeprom.type.sda_in_adr >> 19] = EEPROM;
|
||||
m68k_writemap_8[eeprom.type.scl_adr >> 19] = EEPROM;
|
||||
m68k_writemap_16[eeprom.type.scl_adr >> 19] = EEPROM;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 64KB SRAM */
|
||||
m68k_readmap_8[sram.start >> 19] = SRAM;
|
||||
m68k_readmap_16[sram.start >> 19] = SRAM;
|
||||
if (sram.write)
|
||||
{
|
||||
m68k_writemap_8[sram.start >> 19] = SRAM;
|
||||
m68k_writemap_16[sram.start >> 19] = SRAM;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**********************************************
|
||||
SVP CHIP
|
||||
***********************************************/
|
||||
svp = NULL;
|
||||
if ((strstr(rominfo.product,"MK-1229") != NULL) ||
|
||||
(strstr(rominfo.product,"G-7001") != NULL))
|
||||
{
|
||||
svp_init();
|
||||
m68k_readmap_16[6] = SVP_DRAM;
|
||||
m68k_writemap_16[6] = SVP_DRAM;
|
||||
m68k_readmap_16[7] = SVP_CELL;
|
||||
m68k_writemap_16[7] = SVP_CELL;
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
SEGA MENACER
|
||||
***********************************************/
|
||||
input.x_offset = 0;
|
||||
input.y_offset = 0;
|
||||
|
||||
if (strstr(rominfo.product,"MK-1658") != NULL) /* Menacer 6-in-1 pack */
|
||||
{
|
||||
/* save current setting */
|
||||
if (old_system[0] == -1) old_system[0] = input.system[0];
|
||||
if (old_system[1] == -1) old_system[1] = input.system[1];
|
||||
|
||||
input.system[0] = NO_SYSTEM;
|
||||
input.system[1] = SYSTEM_MENACER;
|
||||
|
||||
/* specific game adjustment */
|
||||
input.x_offset = 0x52;
|
||||
}
|
||||
else if (strstr(rominfo.product,"T-081156") != NULL) /* T2: Arcade Game */
|
||||
{
|
||||
input.system[0] = SYSTEM_GAMEPAD;
|
||||
input.system[1] = SYSTEM_MENACER;
|
||||
|
||||
/* specific game adjustment */
|
||||
input.x_offset = 0x84;
|
||||
input.y_offset = 8;
|
||||
}
|
||||
else if (strstr(rominfo.product,"T-95136") != NULL) /* Lethal Enforcers II */
|
||||
{
|
||||
input.system[0] = SYSTEM_GAMEPAD;
|
||||
input.system[1] = SYSTEM_JUSTIFIER;
|
||||
|
||||
/* specific game adjustment */
|
||||
input.x_offset = 0x18;
|
||||
}
|
||||
else if ((strstr(rominfo.product,"T-95096") != NULL) || /* Lethal Enforcers (USA,Europe) */
|
||||
(strstr(rominfo.product,"T-95073") != NULL)) /* Lethal Enforcers (J)*/
|
||||
{
|
||||
input.system[0] = SYSTEM_GAMEPAD;
|
||||
input.system[1] = SYSTEM_JUSTIFIER;
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
J-CART
|
||||
***********************************************/
|
||||
j_cart = 0;
|
||||
if (((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0x168b)) || /* Super Skidmarks, Micro Machines Military*/
|
||||
((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0x165e)) || /* Pete Sampras Tennis (1991), Micro Machines 96 */
|
||||
((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0xcee0)) || /* Micro Machines Military (bad) */
|
||||
((strstr(rominfo.product,"00000000") != NULL) && (rominfo.checksum == 0x2c41)) || /* Micro Machines 96 (bad) */
|
||||
((strstr(rominfo.product,"XXXXXXXX") != NULL) && (rominfo.checksum == 0xdf39)) || /* Sampras Tennis 96 */
|
||||
((strstr(rominfo.product,"T-123456") != NULL) && (rominfo.checksum == 0x1eae)) || /* Sampras Tennis 96 */
|
||||
((strstr(rominfo.product,"T-120066") != NULL) && (rominfo.checksum == 0x16a4)) || /* Pete Sampras Tennis (1994)*/
|
||||
(strstr(rominfo.product,"T-120096") != NULL)) /* Micro Machines 2 */
|
||||
{
|
||||
if (genromsize <= 0x380000) /* just to be sure (checksum might not be enough) */
|
||||
{
|
||||
j_cart = 1;
|
||||
m68k_readmap_16[7] = J_CART;
|
||||
m68k_writemap_16[7] = J_CART;
|
||||
|
||||
/* save current setting */
|
||||
if (old_system[0] == -1) old_system[0] = input.system[0];
|
||||
if (old_system[1] == -1) old_system[1] = input.system[1];
|
||||
|
||||
/* PORT B by default */
|
||||
input.system[0] = SYSTEM_GAMEPAD;
|
||||
input.system[1] = SYSTEM_GAMEPAD;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
ULTIMATE MK3 HACK
|
||||
***********************************************/
|
||||
if (genromsize > 0x600000)
|
||||
{
|
||||
for (i=8; i<20; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = UMK3_HACK;
|
||||
m68k_readmap_16[i] = UMK3_HACK;
|
||||
}
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
/* this game does not work properly on real hardware */
|
||||
emulate_address_error = 0;
|
||||
#endif
|
||||
}
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
/* default behavior */
|
||||
else emulate_address_error = 1;
|
||||
#endif
|
||||
|
||||
/**********************************************
|
||||
Mappers & HW registers
|
||||
***********************************************/
|
||||
memset(&cart_hw, 0, sizeof(cart_hw));
|
||||
|
||||
/* default write handler for !TIME signal */
|
||||
cart_hw.time_w = default_time_w;
|
||||
|
||||
/* search for game into database */
|
||||
for (i=0; i < CART_CNT + 1; i++)
|
||||
{
|
||||
/* known cart found ! */
|
||||
if ((rominfo.checksum == rom_database[i].chk_1) &&
|
||||
(realchecksum == rom_database[i].chk_2))
|
||||
{
|
||||
/* retrieve hardware information */
|
||||
memcpy(&cart_hw, &(rom_database[i].cart_hw), sizeof(cart_hw));
|
||||
|
||||
/* initialize memory handlers for $400000-$7fffff region */
|
||||
int j = rom_database[i].bank_start;
|
||||
while (j <= rom_database[i].bank_end)
|
||||
{
|
||||
if (cart_hw.regs_r) m68k_readmap_8[j] = CART_HW;
|
||||
if (cart_hw.regs_w) m68k_writemap_8[j] = CART_HW;
|
||||
j++;
|
||||
}
|
||||
i = CART_CNT + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
MAPPER handlers
|
||||
*************************************************************/
|
||||
/*
|
||||
"official" ROM/RAM switch
|
||||
*/
|
||||
static inline void sega_mapper_w(unsigned int address, unsigned int value)
|
||||
{
|
||||
uint8 bank = (address >> 1) & 7;
|
||||
|
||||
switch (bank)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
/* ROM/RAM switch (Phantasy Star IV, Story of Thor/Beyond Oasis, Sonic 3 & Knuckles) */
|
||||
if (value & 1)
|
||||
{
|
||||
/* SRAM is mapped above 200000h */
|
||||
m68k_readmap_8[4] = SRAM;
|
||||
m68k_readmap_16[4] = SRAM;
|
||||
|
||||
if (value & 2)
|
||||
{
|
||||
/* SRAM write protected */
|
||||
m68k_writemap_8[4] = UNUSED;
|
||||
m68k_writemap_16[4] = UNUSED;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SRAM write enabled */
|
||||
m68k_writemap_8[4] = SRAM;
|
||||
m68k_writemap_16[4] = SRAM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ROM is mapped above 200000h */
|
||||
m68k_readmap_8[4] = ROM;
|
||||
m68k_readmap_16[4] = ROM;
|
||||
m68k_writemap_8[4] = UNUSED;
|
||||
m68k_writemap_16[4] = UNUSED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
/* ROM Bankswitch (Super Street Fighter 2)
|
||||
documented by Bart Trzynadlowski (http://www.trzy.org/files/ssf2.txt)
|
||||
*/
|
||||
rom_readmap[bank] = &cart_rom[value << 19];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
custom ROM Bankswitch used by pirate "Multi-in-1" carts
|
||||
(documented by Haze)
|
||||
*/
|
||||
static inline void multi_mapper_w(unsigned int address, unsigned int value)
|
||||
{
|
||||
int i;
|
||||
uint32 bank_addr = (address & 0x3F) << 16;
|
||||
|
||||
/* those games are generally not bigger than 1MB but it's safer to update all 512K banks */
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
if (bank_addr >= genromsize) return;
|
||||
rom_readmap[i] = &cart_rom[bank_addr];
|
||||
bank_addr += 0x80000;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Special ROM Bankswitch used for copy protection
|
||||
Used by unlicensed cartridges (Lion King III, Super King Kong 99)
|
||||
(documented by Haze)
|
||||
*/
|
||||
void special_mapper_w(unsigned int address, unsigned int value)
|
||||
{
|
||||
rom_readmap[0] = &cart_rom[value << 15];
|
||||
}
|
||||
|
||||
/*
|
||||
Realtec ROM Bankswitch (Earth Defend, Balloon Boy & Funny World, Whac-A-Critter)
|
||||
(documented by TascoDeluxe)
|
||||
*/
|
||||
void realtec_mapper_w(unsigned int address, unsigned int value)
|
||||
{
|
||||
uint32 base_addr;
|
||||
|
||||
if (cart_hw.realtec & 2)
|
||||
{
|
||||
int i;
|
||||
cart_hw.realtec &= ~2;
|
||||
|
||||
/* disable Realtec BOOTROM */
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = ROM;
|
||||
m68k_readmap_16[i] = ROM;
|
||||
}
|
||||
}
|
||||
|
||||
switch (address)
|
||||
{
|
||||
case 0x404000: /* three lower bits of ROM base address */
|
||||
cart_hw.regs[0] = value;
|
||||
base_addr = (value | ((cart_hw.regs[1] & 6) << 2)) << 17;
|
||||
rom_readmap[0] = &cart_rom[base_addr];
|
||||
return;
|
||||
|
||||
case 0x400000: /* two higher bits of ROM base address */
|
||||
cart_hw.regs[1] = value;
|
||||
base_addr = ((cart_hw.regs[0] & 7) | ((value & 6) << 2)) << 17;
|
||||
rom_readmap[0] = &cart_rom[base_addr];
|
||||
return;
|
||||
|
||||
case 0x402000: /* size of ROM range to map */
|
||||
cart_hw.regs[2] = value;
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Game no Kanzume Otokuyou ROM Mapper */
|
||||
void seganet_mapper_w(unsigned int address, unsigned int value)
|
||||
{
|
||||
int i;
|
||||
switch (address & 0xff)
|
||||
{
|
||||
case 0x01:
|
||||
if (value & 1)
|
||||
{
|
||||
/* ROM disabled */
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = UNUSED;
|
||||
m68k_readmap_16[i] = UNUSED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ROM enabled */
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = ROM;
|
||||
m68k_readmap_16[i] = ROM;
|
||||
}
|
||||
}
|
||||
break;;
|
||||
|
||||
case 0xf1:
|
||||
if (value & 1)
|
||||
{
|
||||
/* ROM Write protected*/
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
m68k_writemap_8[i] = UNUSED;
|
||||
m68k_writemap_16[i] = UNUSED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ROM Write enabled */
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
m68k_writemap_8[i] = ROM;
|
||||
m68k_writemap_16[i] = ROM;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
RADICA ROM Bankswitch
|
||||
(documented by Haze)
|
||||
*/
|
||||
unsigned int radica_mapper_r(unsigned int address)
|
||||
{
|
||||
/* 64KB ROM banks */
|
||||
uint8 bank = (address >> 1) & 0x3F;
|
||||
rom_readmap[0] = &cart_rom[bank * 0x10000];
|
||||
rom_readmap[1] = &cart_rom[bank * 0x10000 + 0x80000]; /* ROM is max. 1MB */
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************
|
||||
default !TIME signal handler
|
||||
*************************************************************/
|
||||
|
||||
/* default ROM bankswitch */
|
||||
void default_time_w(unsigned int address, unsigned int value)
|
||||
{
|
||||
if ((address & 0xf1) == 0xf1) sega_mapper_w(address, value);
|
||||
else if (address < 0xa13040) multi_mapper_w(address, value);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Internal register handlers
|
||||
*************************************************************/
|
||||
|
||||
unsigned int default_regs_r(unsigned int address)
|
||||
{
|
||||
uint8 i;
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if ((address & cart_hw.mask[i]) == cart_hw.addr[i])
|
||||
return cart_hw.regs[i];
|
||||
}
|
||||
|
||||
/* unused */
|
||||
return -1;
|
||||
}
|
||||
|
||||
void default_regs_w(unsigned int address, unsigned int value)
|
||||
{
|
||||
uint8 i;
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if ((address & cart_hw.mask[i]) == cart_hw.addr[i])
|
||||
{
|
||||
cart_hw.regs[i] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* special register behaviour (Lion King III, Super Donkey Kong 99) */
|
||||
void special_regs_w(unsigned int address, unsigned int value)
|
||||
{
|
||||
/* ROM bankswitch */
|
||||
if ((address >> 16) > 0x6f)
|
||||
{
|
||||
special_mapper_w(address, value);
|
||||
return;
|
||||
}
|
||||
|
||||
/* write regs */
|
||||
default_regs_w(address, value);
|
||||
|
||||
/* bitswapping (documented by Haze) */
|
||||
uint8 temp = cart_hw.regs[0];
|
||||
switch (cart_hw.regs[1])
|
||||
{
|
||||
case 1:
|
||||
cart_hw.regs[2] = (temp >> 1);
|
||||
return;
|
||||
|
||||
case 2:
|
||||
cart_hw.regs[2] = ((temp >> 4) | ((temp & 0x0F) << 4));
|
||||
return;
|
||||
|
||||
default:
|
||||
cart_hw.regs[2] = (((temp >> 7) & 0x01) | ((temp >> 5) & 0x02) |
|
||||
((temp >> 3) & 0x04) | ((temp >> 1) & 0x08) |
|
||||
((temp << 1) & 0x10) | ((temp << 3) & 0x20) |
|
||||
((temp << 5) & 0x40) | ((temp << 7) & 0x80));
|
||||
return;
|
||||
}
|
||||
}
|
53
source/cart_hw/cart_hw.h
Normal file
53
source/cart_hw/cart_hw.h
Normal file
@ -0,0 +1,53 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* Cartridge Hardware support
|
||||
*
|
||||
* code by Eke-Eke, GC/Wii port
|
||||
*
|
||||
* Lots of protection mechanism have been discovered by Haze
|
||||
* (http://haze.mameworld.info/)
|
||||
*
|
||||
* Realtec mapper has been figured out by TascoDeluxe
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _CART_HW_H_
|
||||
#define _CART_HW_H_
|
||||
|
||||
/* Hardware description */
|
||||
typedef struct
|
||||
{
|
||||
uint8 regs[4]; /* internal registers (R/W) */
|
||||
uint32 mask[4]; /* registers address mask */
|
||||
uint32 addr[4]; /* registers address */
|
||||
uint8 realtec; /* bit 0: realtec mapper detected, bit 1: bootrom enabled */
|
||||
unsigned int (*time_r)(unsigned int address); /* !TIME signal ($a130xx) read handler */
|
||||
void (*time_w)(unsigned int address, unsigned int data); /* !TIME signal ($a130xx) write handler */
|
||||
unsigned int (*regs_r)(unsigned int address); /* cart hardware region ($400000-$7fffff) read handler */
|
||||
void (*regs_w)(unsigned int address, unsigned int data); /* cart hardware region ($400000-$7fffff) write handler */
|
||||
} T_CART_HW;
|
||||
|
||||
/* global variables */
|
||||
extern T_CART_HW cart_hw;
|
||||
extern uint8 j_cart;
|
||||
|
||||
/* Function prototypes */
|
||||
extern void cart_hw_reset();
|
||||
extern void cart_hw_init();
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* Serial EEPROM support for Sega Genesis games
|
||||
* Genesis Plus 1.2a
|
||||
* Serial EEPROM support
|
||||
*
|
||||
* Copyright (C) 2007 EkeEke
|
||||
* code by Eke-Eke, GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -19,9 +20,6 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#include "rominfo.h"
|
||||
|
||||
#define GAME_COUNT 21
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -30,12 +28,13 @@ typedef struct
|
||||
T_EEPROM_TYPE type;
|
||||
} T_GAME_ENTRY;
|
||||
|
||||
T_GAME_ENTRY database[GAME_COUNT] =
|
||||
T_GAME_ENTRY database[24] =
|
||||
{
|
||||
/* ACCLAIM mappers */
|
||||
/* 24C02 (old mapper) */
|
||||
{{"T-081326" }, 0, {8, 0xFF, 0xFF, 0x200000, 0x200000, 0x200000, 0, 1, 1}}, /* NBA Jam (UE) */
|
||||
{{"T-81033" }, 0, {8, 0xFF, 0xFF, 0x200000, 0x200000, 0x200000, 0, 1, 1}}, /* NBA Jam (J) */
|
||||
{{"T-081326" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200001, 0, 1, 1}}, /* NBA Jam (UE) */
|
||||
{{"T-81033" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200001, 0, 1, 1}}, /* NBA Jam (J) */
|
||||
|
||||
/* 24C02 */
|
||||
{{"T-81406" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NBA Jam TE */
|
||||
{{"T-081276" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NFL Quarterback Club */
|
||||
@ -46,8 +45,8 @@ T_GAME_ENTRY database[GAME_COUNT] =
|
||||
{{"T-81476" }, 0, {16, 0x1FFF, 0x1FFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* Frank Thomas Big Hurt Baseball */
|
||||
|
||||
/* EA mapper (24C01 only) */
|
||||
{{"T-50396" }, 0, {7, 0x7F, 0x7F, 0x200000, 0x200000, 0x200000, 7, 7, 6}}, /* NHLPA Hockey 93 (UE) */
|
||||
{{"T-50176" }, 0, {7, 0x7F, 0x7F, 0x200000, 0x200000, 0x200000, 7, 7, 6}}, /* Rings of Power */
|
||||
{{"T-50396" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 7, 7, 6}}, /* NHLPA Hockey 93 (UE) */
|
||||
{{"T-50176" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 7, 7, 6}}, /* Rings of Power */
|
||||
|
||||
/* SEGA mapper (24C01 only) */
|
||||
{{"T-12046" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Megaman - The Wily Wars */
|
||||
@ -57,21 +56,26 @@ T_GAME_ENTRY database[GAME_COUNT] =
|
||||
{{"G-5538" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Greatest Heavyweights of the Ring (J) */
|
||||
{{"PR-1993" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Greatest Heavyweights of the Ring (E) */
|
||||
{{"G-4060" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Wonderboy in Monster World */
|
||||
{{"00001211-00"}, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Sports Talk Baseball */
|
||||
|
||||
/* CODEMASTERS mapper */
|
||||
/* 24C01 */
|
||||
{{"T-120106"}, 0, {7, 0x7F, 0x7F, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Brian Lara Cricket */
|
||||
/* 24C08 */
|
||||
{{"T-120096" }, 0, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines 2 - Turbo Tournament (E) */
|
||||
{{"00000000-00"}, 0x168B, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Military */
|
||||
{{"00000000-00"}, 0xCEE0, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Military (Bad)*/
|
||||
/* 24C16 */
|
||||
{{"00000000-00"}, 0x165E, {8, 0x7FF, 0x7FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Turbo Tournament 96 */
|
||||
{{"00000000-00"}, 0x2C41, {8, 0x7FF, 0x7FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}} /* Micro Machines Turbo Tournament 96 (Bad)*/
|
||||
{{"00000000-00"}, 0x2C41, {8, 0x7FF, 0x7FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Turbo Tournament 96 (Bad)*/
|
||||
/* 24C65 */
|
||||
{{"T-120146-50"}, 0, {16, 0x1FFF, 0x1FFF, 0x300000, 0x380001, 0x300000, 0, 7, 1}} /* Brian Lara Cricket 96, Shane Warne Cricket */
|
||||
};
|
||||
|
||||
|
||||
T_EEPROM eeprom;
|
||||
|
||||
void EEPROM_Init()
|
||||
void eeprom_init()
|
||||
{
|
||||
uint8 i = 0;
|
||||
|
||||
@ -84,7 +88,7 @@ void EEPROM_Init()
|
||||
sram.custom = 0;
|
||||
|
||||
/* look into game database */
|
||||
while ((i<GAME_COUNT) && (!sram.custom))
|
||||
while ((i<24) && (!sram.custom))
|
||||
{
|
||||
if (strstr(rominfo.product,database[i].game_id) != NULL)
|
||||
{
|
||||
@ -100,18 +104,11 @@ void EEPROM_Init()
|
||||
i++;
|
||||
}
|
||||
|
||||
if (sram.custom)
|
||||
/* Game not found in database but header seems to indicate it uses EEPROM */
|
||||
if (!sram.custom)
|
||||
{
|
||||
/* set SRAM start & end address */
|
||||
sram.start = sram.end = eeprom.type.sda_in_adr;
|
||||
if (sram.end < eeprom.type.sda_out_adr) sram.end = eeprom.type.sda_out_adr;
|
||||
if (sram.end < eeprom.type.scl_adr) sram.end = eeprom.type.scl_adr;
|
||||
if (sram.start > eeprom.type.sda_out_adr) sram.start = eeprom.type.sda_out_adr;
|
||||
if (sram.start > eeprom.type.scl_adr) sram.start = eeprom.type.scl_adr;
|
||||
}
|
||||
else if ((sram.end - sram.start) < 2)
|
||||
if ((sram.end - sram.start) < 2)
|
||||
{
|
||||
/* Game not found in database but header indicates it uses EEPROM */
|
||||
sram.custom = 1;
|
||||
sram.on = 1;
|
||||
sram.write = 1;
|
||||
@ -120,8 +117,9 @@ void EEPROM_Init()
|
||||
memcpy(&eeprom.type, &database[9].type, sizeof(T_EEPROM_TYPE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Detect_START()
|
||||
static inline void Detect_START()
|
||||
{
|
||||
if (eeprom.old_scl && eeprom.scl)
|
||||
{
|
||||
@ -139,7 +137,7 @@ static void Detect_START()
|
||||
}
|
||||
}
|
||||
|
||||
static void Detect_STOP()
|
||||
static inline void Detect_STOP()
|
||||
{
|
||||
if (eeprom.old_scl && eeprom.scl)
|
||||
{
|
||||
@ -150,15 +148,30 @@ static void Detect_STOP()
|
||||
}
|
||||
}
|
||||
|
||||
void EEPROM_Write(unsigned int address, unsigned int value)
|
||||
void eeprom_write(uint32 address, uint32 value, uint32 word_access)
|
||||
{
|
||||
uint16 sram_address = 0;
|
||||
error("eeprom write%d 0x%x = 0x%x (0x%x)\n", 8*(1+word_access), address, value, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
|
||||
/* decode SCL and SDA value */
|
||||
if (word_access)
|
||||
{
|
||||
/* 16-bits access */
|
||||
if (eeprom.type.sda_in_adr == address) eeprom.sda = (value >> (8 + eeprom.type.sda_in_bit)) & 1; /* MSB */
|
||||
else if (eeprom.type.sda_in_adr == (address | 1)) eeprom.sda = (value >> eeprom.type.sda_in_bit) & 1; /* LSB */
|
||||
else eeprom.sda = eeprom.old_sda;
|
||||
|
||||
if (eeprom.type.scl_adr == address) eeprom.scl = (value >> (8 + eeprom.type.scl_bit)) & 1; /* MSB */
|
||||
else if (eeprom.type.scl_adr == (address | 1)) eeprom.scl = (value >> eeprom.type.scl_bit) & 1; /* LSB */
|
||||
else eeprom.scl = eeprom.old_scl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (eeprom.type.sda_in_adr == address) eeprom.sda = (value >> eeprom.type.sda_in_bit) & 1;
|
||||
else eeprom.sda = eeprom.old_sda;
|
||||
|
||||
if (eeprom.type.scl_adr == address) eeprom.scl = (value >> eeprom.type.scl_bit) & 1;
|
||||
else eeprom.scl = eeprom.old_scl;
|
||||
}
|
||||
|
||||
/* EEPROM current state */
|
||||
switch (eeprom.state)
|
||||
@ -193,8 +206,14 @@ void EEPROM_Write(unsigned int address, unsigned int value)
|
||||
/* look for SCL HIGH to LOW transition */
|
||||
if (eeprom.old_scl && !eeprom.scl && (eeprom.cycles > 0))
|
||||
{
|
||||
if (eeprom.cycles < 8) eeprom.word_address |= (eeprom.old_sda << (7 - eeprom.cycles));
|
||||
else if (eeprom.cycles == 8) eeprom.rw = eeprom.old_sda;
|
||||
if (eeprom.cycles < 8)
|
||||
{
|
||||
eeprom.word_address |= (eeprom.old_sda << (7 - eeprom.cycles));
|
||||
}
|
||||
else if (eeprom.cycles == 8)
|
||||
{
|
||||
eeprom.rw = eeprom.old_sda;
|
||||
}
|
||||
else
|
||||
{ /* ACK CYCLE */
|
||||
eeprom.cycles = 0;
|
||||
@ -375,7 +394,7 @@ void EEPROM_Write(unsigned int address, unsigned int value)
|
||||
if (eeprom.cycles < 9)
|
||||
{
|
||||
/* Write DATA bits (max 64kBytes) */
|
||||
sram_address = (eeprom.slave_mask | eeprom.word_address) & 0xFFFF;
|
||||
uint16 sram_address = (eeprom.slave_mask | eeprom.word_address) & 0xFFFF;
|
||||
if (eeprom.old_sda) sram.sram[sram_address] |= (1 << (8 - eeprom.cycles));
|
||||
else sram.sram[sram_address] &= ~(1 << (8 - eeprom.cycles));
|
||||
|
||||
@ -397,10 +416,9 @@ void EEPROM_Write(unsigned int address, unsigned int value)
|
||||
eeprom.old_sda = eeprom.sda;
|
||||
}
|
||||
|
||||
|
||||
unsigned int EEPROM_Read(unsigned int address)
|
||||
uint32 eeprom_read(uint32 address, uint32 word_access)
|
||||
{
|
||||
uint16 sram_address;
|
||||
error("eeprom read%d 0x%x (0x%x)\n", 8*(1+word_access), address, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
uint8 sda_out = eeprom.sda;
|
||||
|
||||
/* EEPROM state */
|
||||
@ -410,7 +428,7 @@ unsigned int EEPROM_Read(unsigned int address)
|
||||
if (eeprom.cycles < 9)
|
||||
{
|
||||
/* Return DATA bits (max 64kBytes) */
|
||||
sram_address = (eeprom.slave_mask | eeprom.word_address) & 0xFFFF;
|
||||
uint16 sram_address = (eeprom.slave_mask | eeprom.word_address) & 0xffff;
|
||||
sda_out = (sram.sram[sram_address] >> (8 - eeprom.cycles)) & 1;
|
||||
|
||||
if (eeprom.cycles == 8)
|
||||
@ -434,6 +452,12 @@ unsigned int EEPROM_Read(unsigned int address)
|
||||
break;
|
||||
}
|
||||
|
||||
if (address == eeprom.type.sda_out_adr) return (sda_out << eeprom.type.sda_out_bit);
|
||||
else return 0;
|
||||
/* memory access */
|
||||
if (word_access)
|
||||
{
|
||||
/* 16-bits access */
|
||||
if (eeprom.type.sda_out_adr & 1) return (sda_out << eeprom.type.sda_out_bit); /* LSB */
|
||||
else return (sda_out << (eeprom.type.sda_out_bit + 8)); /* MSB */
|
||||
}
|
||||
else return (sda_out << eeprom.type.sda_out_bit);
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* Serial EEPROM support for Sega Genesis games
|
||||
* Genesis Plus 1.2a
|
||||
* Serial EEPROM support
|
||||
*
|
||||
* Copyright (C) 2007 EkeEKe
|
||||
* code by Eke-Eke, GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -18,6 +19,9 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef _EEPROM_H_
|
||||
#define _EEPROM_H_
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STAND_BY = 0,
|
||||
@ -81,7 +85,8 @@ typedef struct
|
||||
extern T_EEPROM eeprom;
|
||||
|
||||
/* Function prototypes */
|
||||
extern void EEPROM_Init();
|
||||
extern void EEPROM_Write(unsigned int address, unsigned int value);
|
||||
extern unsigned int EEPROM_Read(unsigned int address);
|
||||
extern void eeprom_init();
|
||||
extern void eeprom_write(uint32 address, uint32 value, uint32 word_access);
|
||||
extern uint32 eeprom_read(uint32 address, uint32 word_access);
|
||||
|
||||
#endif
|
98
source/cart_hw/sram.c
Normal file
98
source/cart_hw/sram.c
Normal file
@ -0,0 +1,98 @@
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* SRAM Hardware
|
||||
*
|
||||
* code by Eke-Eke, GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
T_SRAM sram;
|
||||
|
||||
/****************************************************************************
|
||||
* A quick guide to SRAM on the Genesis
|
||||
*
|
||||
* The SRAM definition is held at offset 0x1b0 of the ROM header.
|
||||
*
|
||||
* 1B0h: dc.b 'RA', %1x1yz000, %00100000
|
||||
* 1B4h: dc.l RAM start address
|
||||
* 1B8h: dc.l RAM end address
|
||||
* x 1 for BACKUP and 0 If not BACKUP
|
||||
* yz 10 if even address only
|
||||
* 11 if odd address only
|
||||
* 00 if both even and odd address
|
||||
*
|
||||
* Assuming max. 64k SRAM / Battery RAM throughout
|
||||
****************************************************************************/
|
||||
void sram_init()
|
||||
{
|
||||
memset (&sram, 0, sizeof (T_SRAM));
|
||||
memset (&sram.sram[0], 0xFF, 0x10000);
|
||||
sram.crc = crc32 (0, &sram.sram[0], 0x10000);
|
||||
|
||||
if ((cart_rom[0x1b0] == 0x52) && (cart_rom[0x1b1] == 0x41))
|
||||
{
|
||||
/* retrieve informations from headezr */
|
||||
sram.detected = 1;
|
||||
sram.start = READ_WORD_LONG(cart_rom, 0x1b4);
|
||||
sram.end = READ_WORD_LONG(cart_rom, 0x1b8);
|
||||
|
||||
/* fixe some bad header informations */
|
||||
if ((sram.start > sram.end) || ((sram.end - sram.start) >= 0x10000))
|
||||
sram.end = sram.start + 0xffff;
|
||||
sram.start &= 0xfffffffe;
|
||||
sram.end |= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* default SRAM region */
|
||||
sram.start = 0x200000;
|
||||
sram.end = 0x20ffff;
|
||||
}
|
||||
|
||||
/* set SRAM ON by default when ROM is not mapped */
|
||||
if (genromsize <= sram.start)
|
||||
{
|
||||
sram.on = 1;
|
||||
sram.write = 1;
|
||||
}
|
||||
|
||||
/* Some games with bad header or specific configuration */
|
||||
if (strstr(rominfo.product,"T-113016") != NULL)
|
||||
{
|
||||
/* Pugsy (try accessing unmapped area for copy protection) */
|
||||
sram.on = 0;
|
||||
sram.write = 0;
|
||||
}
|
||||
else if ((strstr(rominfo.product,"T-26013") != NULL) && (rominfo.checksum == 0xa837))
|
||||
{
|
||||
/* Psy-O-Blade (bad header) */
|
||||
sram.on = 1;
|
||||
sram.write = 1;
|
||||
sram.start = 0x200001;
|
||||
sram.end = 0x203fff;
|
||||
}
|
||||
else if (((realchecksum == 0xaeaa) || (realchecksum == 0x8dba)) && (rominfo.checksum == 0x8104))
|
||||
{
|
||||
/* Xin Qigai Wangzi, aka Beggar Prince (no header, use uncommon area) */
|
||||
sram.on = 1;
|
||||
sram.write = 1;
|
||||
sram.start = 0x400000;
|
||||
sram.end = 0x40ffff;
|
||||
}
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* SRAM Hardware
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
* code by Eke-Eke, GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -17,8 +18,10 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* NGC MANAGER
|
||||
***************************************************************************/
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef _SRAM_H_
|
||||
#define _SRAM_H_
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -28,13 +31,14 @@ typedef struct
|
||||
uint8 custom;
|
||||
uint32 start;
|
||||
uint32 end;
|
||||
int crc;
|
||||
uint32 crc;
|
||||
uint8 sram[0x10000];
|
||||
} T_SRAM;
|
||||
|
||||
/* Function prototypes */
|
||||
extern void SRAM_Init ();
|
||||
extern void sram_init ();
|
||||
|
||||
/* global variables */
|
||||
extern T_SRAM sram;
|
||||
|
||||
#endif
|
67
source/cart_hw/svp/imageformat.txt
Normal file
67
source/cart_hw/svp/imageformat.txt
Normal file
@ -0,0 +1,67 @@
|
||||
|
||||
vscroll: 1 (0); 209 (26) - alternates every 4 frames
|
||||
vram range for patterns: 0000-999f (low scr 0000-395f,72e0-999f; high 3980-999f)
|
||||
name table address: c000
|
||||
seen DMAs (in order): [300002-3026c3]->[0020-26e1] len 4961
|
||||
[3026c2-303943]->[26e0-3961] len 2369
|
||||
[303942-306003]->[72e0-99a1] len 4961
|
||||
---
|
||||
[306002-3086c3]->[3980-6041] len 4961
|
||||
[3086c2-309943]->[6040-72c1] len 2369
|
||||
[309942-30c003]->[72e0-99a2] len 4961
|
||||
tile arrangement:
|
||||
|
||||
000: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
|
||||
001: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
|
||||
002: 001 003 005 007 009 00b 00d 00f 011 013 015 017 019 01b 01d 01f 021 023 025 027 029 02b 02d 02f 031 033 035 037 039 03b 03d 03f
|
||||
003: 002 004 006 008 00a 00c 00e 010 012 014 016 018 01a 01c 01e 020 022 024 026 028 02a 02c 02e 030 032 034 036 038 03a 03c 03e 040
|
||||
004: 041 043 045 047 049 04b 04d 04f 051 053 055 057 059 05b 05d 05f 061 063 065 067 069 06b 06d 06f 071 073 075 077 079 07b 07d 07f
|
||||
005: 042 044 046 048 04a 04c 04e 050 052 054 056 058 05a 05c 05e 060 062 064 066 068 06a 06c 06e 070 072 074 076 078 07a 07c 07e 080
|
||||
006: 081 083 085 087 089 08b 08d 08f 091 093 095 097 099 09b 09d 09f 0a1 0a3 0a5 0a7 0a9 0ab 0ad 0af 0b1 0b3 0b5 0b7 0b9 0bb 0bd 0bf
|
||||
007: 082 084 086 088 08a 08c 08e 090 092 094 096 098 09a 09c 09e 0a0 0a2 0a4 0a6 0a8 0aa 0ac 0ae 0b0 0b2 0b4 0b6 0b8 0ba 0bc 0be 0c0
|
||||
008: 0c1 0c3 0c5 0c7 0c9 0cb 0cd 0cf 0d1 0d3 0d5 0d7 0d9 0db 0dd 0df 0e1 0e3 0e5 0e7 0e9 0eb 0ed 0ef 0f1 0f3 0f5 0f7 0f9 0fb 0fd 0ff
|
||||
009: 0c2 0c4 0c6 0c8 0ca 0cc 0ce 0d0 0d2 0d4 0d6 0d8 0da 0dc 0de 0e0 0e2 0e4 0e6 0e8 0ea 0ec 0ee 0f0 0f2 0f4 0f6 0f8 0fa 0fc 0fe 100
|
||||
010: 101 103 105 107 109 10b 10d 10f 111 113 115 117 119 11b 11d 11f 121 123 125 127 129 12b 12d 12f 131 133 135 137 139 13b 13d 13f
|
||||
011: 102 104 106 108 10a 10c 10e 110 112 114 116 118 11a 11c 11e 120 122 124 126 128 12a 12c 12e 130 132 134 136 138 13a 13c 13e 140
|
||||
012: 141 143 145 147 149 14b 14d 14f 151 153 155 157 159 15b 15d 15f 161 163 165 167 169 16b 16d 16f 171 173 175 177 179 17b 17d 17f
|
||||
013: 142 144 146 148 14a 14c 14e 150 152 154 156 158 15a 15c 15e 160 162 164 166 168 16a 16c 16e 170 172 174 176 178 17a 17c 17e 180
|
||||
014: 181 183 185 187 189 18b 18d 18f 191 193 195 197 199 19b 19d 19f 1a1 1a3 1a5 1a7 1a9 1ab 1ad 1af 1b1 1b3 1b5 1b7 1b9 1bb 1bd 1bf
|
||||
015: 182 184 186 188 18a 18c 18e 190 192 194 196 198 19a 19c 19e 1a0 1a2 1a4 1a6 1a8 1aa 1ac 1ae 1b0 1b2 1b4 1b6 1b8 1ba 1bc 1be 1c0
|
||||
016: 1c1 1c3 1c5 1c7 1c9 397 399 39b 39d 39f 3a1 3a3 3a5 3a7 3a9 3ab 3ad 3af 3b1 3b3 3b5 3b7 3b9 3bb 3bd 3bf 3c1 3c3 3c5 3c7 3c9 3cb
|
||||
017: 1c2 1c4 1c6 1c8 1ca 398 39a 39c 39e 3a0 3a2 3a4 3a6 3a8 3aa 3ac 3ae 3b0 3b2 3b4 3b6 3b8 3ba 3bc 3be 3c0 3c2 3c4 3c6 3c8 3ca 3cc
|
||||
018: 3cd 3cf 3d1 3d3 3d5 3d7 3d9 3db 3dd 3df 3e1 3e3 3e5 3e7 3e9 3eb 3ed 3ef 3f1 3f3 3f5 3f7 3f9 3fb 3fd 3ff 401 403 405 407 409 40b
|
||||
019: 3ce 3d0 3d2 3d4 3d6 3d8 3da 3dc 3de 3e0 3e2 3e4 3e6 3e8 3ea 3ec 3ee 3f0 3f2 3f4 3f6 3f8 3fa 3fc 3fe 400 402 404 406 408 40a 40c
|
||||
020: 40d 40f 411 413 415 417 419 41b 41d 41f 421 423 425 427 429 42b 42d 42f 431 433 435 437 439 43b 43d 43f 441 443 445 447 449 44b
|
||||
021: 40e 410 412 414 416 418 41a 41c 41e 420 422 424 426 428 42a 42c 42e 430 432 434 436 438 43a 43c 43e 440 442 444 446 448 44a 44c
|
||||
022: 44d 44f 451 453 455 457 459 45b 45d 45f 461 463 465 467 469 46b 46d 46f 471 473 475 477 479 47b 47d 47f 481 483 485 487 489 48b
|
||||
023: 44e 450 452 454 456 458 45a 45c 45e 460 462 464 466 468 46a 46c 46e 470 472 474 476 478 47a 47c 47e 480 482 484 486 488 48a 48c
|
||||
024: 48d 48f 491 493 495 497 499 49b 49d 49f 4a1 4a3 4a5 4a7 4a9 4ab 4ad 4af 4b1 4b3 4b5 4b7 4b9 4bb 4bd 4bf 4c1 4c3 4c5 4c7 4c9 4cb
|
||||
025: 48e 490 492 494 496 498 49a 49c 49e 4a0 4a2 4a4 4a6 4a8 4aa 4ac 4ae 4b0 4b2 4b4 4b6 4b8 4ba 4bc 4be 4c0 4c2 4c4 4c6 4c8 4ca 4cc
|
||||
026: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
|
||||
027: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
|
||||
028: 1cc 1ce 1d0 1d2 1d4 1d6 1d8 1da 1dc 1de 1e0 1e2 1e4 1e6 1e8 1ea 1ec 1ee 1f0 1f2 1f4 1f6 1f8 1fa 1fc 1fe 200 202 204 206 208 20a
|
||||
029: 1cd 1cf 1d1 1d3 1d5 1d7 1d9 1db 1dd 1df 1e1 1e3 1e5 1e7 1e9 1eb 1ed 1ef 1f1 1f3 1f5 1f7 1f9 1fb 1fd 1ff 201 203 205 207 209 20b
|
||||
030: 20c 20e 210 212 214 216 218 21a 21c 21e 220 222 224 226 228 22a 22c 22e 230 232 234 236 238 23a 23c 23e 240 242 244 246 248 24a
|
||||
031: 20d 20f 211 213 215 217 219 21b 21d 21f 221 223 225 227 229 22b 22d 22f 231 233 235 237 239 23b 23d 23f 241 243 245 247 249 24b
|
||||
032: 24c 24e 250 252 254 256 258 25a 25c 25e 260 262 264 266 268 26a 26c 26e 270 272 274 276 278 27a 27c 27e 280 282 284 286 288 28a
|
||||
033: 24d 24f 251 253 255 257 259 25b 25d 25f 261 263 265 267 269 26b 26d 26f 271 273 275 277 279 27b 27d 27f 281 283 285 287 289 28b
|
||||
034: 28c 28e 290 292 294 296 298 29a 29c 29e 2a0 2a2 2a4 2a6 2a8 2aa 2ac 2ae 2b0 2b2 2b4 2b6 2b8 2ba 2bc 2be 2c0 2c2 2c4 2c6 2c8 2ca
|
||||
035: 28d 28f 291 293 295 297 299 29b 29d 29f 2a1 2a3 2a5 2a7 2a9 2ab 2ad 2af 2b1 2b3 2b5 2b7 2b9 2bb 2bd 2bf 2c1 2c3 2c5 2c7 2c9 2cb
|
||||
036: 2cc 2ce 2d0 2d2 2d4 2d6 2d8 2da 2dc 2de 2e0 2e2 2e4 2e6 2e8 2ea 2ec 2ee 2f0 2f2 2f4 2f6 2f8 2fa 2fc 2fe 300 302 304 306 308 30a
|
||||
037: 2cd 2cf 2d1 2d3 2d5 2d7 2d9 2db 2dd 2df 2e1 2e3 2e5 2e7 2e9 2eb 2ed 2ef 2f1 2f3 2f5 2f7 2f9 2fb 2fd 2ff 301 303 305 307 309 30b
|
||||
038: 30c 30e 310 312 314 316 318 31a 31c 31e 320 322 324 326 328 32a 32c 32e 330 332 334 336 338 33a 33c 33e 340 342 344 346 348 34a
|
||||
039: 30d 30f 311 313 315 317 319 31b 31d 31f 321 323 325 327 329 32b 32d 32f 331 333 335 337 339 33b 33d 33f 341 343 345 347 349 34b
|
||||
040: 34c 34e 350 352 354 356 358 35a 35c 35e 360 362 364 366 368 36a 36c 36e 370 372 374 376 378 37a 37c 37e 380 382 384 386 388 38a
|
||||
041: 34d 34f 351 353 355 357 359 35b 35d 35f 361 363 365 367 369 36b 36d 36f 371 373 375 377 379 37b 37d 37f 381 383 385 387 389 38b
|
||||
042: 38c 38e 390 392 394 397 399 39b 39d 39f 3a1 3a3 3a5 3a7 3a9 3ab 3ad 3af 3b1 3b3 3b5 3b7 3b9 3bb 3bd 3bf 3c1 3c3 3c5 3c7 3c9 3cb
|
||||
043: 38d 38f 391 393 395 398 39a 39c 39e 3a0 3a2 3a4 3a6 3a8 3aa 3ac 3ae 3b0 3b2 3b4 3b6 3b8 3ba 3bc 3be 3c0 3c2 3c4 3c6 3c8 3ca 3cc
|
||||
044: 3cd 3cf 3d1 3d3 3d5 3d7 3d9 3db 3dd 3df 3e1 3e3 3e5 3e7 3e9 3eb 3ed 3ef 3f1 3f3 3f5 3f7 3f9 3fb 3fd 3ff 401 403 405 407 409 40b
|
||||
045: 3ce 3d0 3d2 3d4 3d6 3d8 3da 3dc 3de 3e0 3e2 3e4 3e6 3e8 3ea 3ec 3ee 3f0 3f2 3f4 3f6 3f8 3fa 3fc 3fe 400 402 404 406 408 40a 40c
|
||||
046: 40d 40f 411 413 415 417 419 41b 41d 41f 421 423 425 427 429 42b 42d 42f 431 433 435 437 439 43b 43d 43f 441 443 445 447 449 44b
|
||||
047: 40e 410 412 414 416 418 41a 41c 41e 420 422 424 426 428 42a 42c 42e 430 432 434 436 438 43a 43c 43e 440 442 444 446 448 44a 44c
|
||||
048: 44d 44f 451 453 455 457 459 45b 45d 45f 461 463 465 467 469 46b 46d 46f 471 473 475 477 479 47b 47d 47f 481 483 485 487 489 48b
|
||||
049: 44e 450 452 454 456 458 45a 45c 45e 460 462 464 466 468 46a 46c 46e 470 472 474 476 478 47a 47c 47e 480 482 484 486 488 48a 48c
|
||||
050: 48d 48f 491 493 495 497 499 49b 49d 49f 4a1 4a3 4a5 4a7 4a9 4ab 4ad 4af 4b1 4b3 4b5 4b7 4b9 4bb 4bd 4bf 4c1 4c3 4c5 4c7 4c9 4cb
|
||||
051: 48e 490 492 494 496 498 49a 49c 49e 4a0 4a2 4a4 4a6 4a8 4aa 4ac 4ae 4b0 4b2 4b4 4b6 4b8 4ba 4bc 4be 4c0 4c2 4c4 4c6 4c8 4ca 4cc
|
||||
052: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
|
||||
053: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
|
1330
source/cart_hw/svp/ssp16.c
Normal file
1330
source/cart_hw/svp/ssp16.c
Normal file
File diff suppressed because it is too large
Load Diff
82
source/cart_hw/svp/ssp16.h
Normal file
82
source/cart_hw/svp/ssp16.h
Normal file
@ -0,0 +1,82 @@
|
||||
/* The SVP chip emulator
|
||||
|
||||
(c) Copyright 2008, Grazvydas "notaz" Ignotas
|
||||
Free for non-commercial use.
|
||||
|
||||
For commercial use, separate licencing terms must be obtained.
|
||||
|
||||
*/
|
||||
|
||||
/* modified for Genesis Plus GCN port, added BIG ENDIAN support (EkeEke)*/
|
||||
|
||||
#ifndef _SSP16_H_
|
||||
#define _SSP16_H_
|
||||
|
||||
/* emulation event logging (from Picodrive) */
|
||||
#define EL_SVP 0x00004000 /* SVP stuff */
|
||||
#define EL_ANOMALY 0x80000000 /* some unexpected conditions (during emulation) */
|
||||
#ifdef LOG_SVP
|
||||
#define elprintf(w,f,...) error("%d(%d): " f "\n",frame_count,v_counter,##__VA_ARGS__);
|
||||
#else
|
||||
#define elprintf(w,f,...)
|
||||
#endif
|
||||
|
||||
/* register names */
|
||||
enum {
|
||||
SSP_GR0, SSP_X, SSP_Y, SSP_A,
|
||||
SSP_ST, SSP_STACK, SSP_PC, SSP_P,
|
||||
SSP_PM0, SSP_PM1, SSP_PM2, SSP_XST,
|
||||
SSP_PM4, SSP_gr13, SSP_PMC, SSP_AL
|
||||
};
|
||||
|
||||
typedef union
|
||||
{
|
||||
unsigned int v;
|
||||
struct {
|
||||
#ifdef LSB_FIRST
|
||||
unsigned short l;
|
||||
unsigned short h;
|
||||
#else
|
||||
unsigned short h;
|
||||
unsigned short l;
|
||||
#endif
|
||||
};
|
||||
} ssp_reg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union {
|
||||
unsigned short RAM[256*2]; // 2 internal RAM banks
|
||||
struct {
|
||||
unsigned short RAM0[256];
|
||||
unsigned short RAM1[256];
|
||||
};
|
||||
};
|
||||
ssp_reg_t gr[16]; // general registers
|
||||
union {
|
||||
unsigned char r[8]; // BANK pointers
|
||||
struct {
|
||||
unsigned char r0[4];
|
||||
unsigned char r1[4];
|
||||
};
|
||||
};
|
||||
unsigned short stack[6];
|
||||
unsigned int pmac_read[6]; // read modes/addrs for PM0-PM5
|
||||
unsigned int pmac_write[6]; // write ...
|
||||
//
|
||||
#define SSP_PMC_HAVE_ADDR 0x0001 // address written to PMAC, waiting for mode
|
||||
#define SSP_PMC_SET 0x0002 // PMAC is set
|
||||
#define SSP_HANG 0x1000 // 68000 hangs SVP
|
||||
#define SSP_WAIT_PM0 0x2000 // bit1 in PM0
|
||||
#define SSP_WAIT_30FE06 0x4000 // ssp tight loops on 30FE08 to become non-zero
|
||||
#define SSP_WAIT_30FE08 0x8000 // same for 30FE06
|
||||
#define SSP_WAIT_MASK 0xf000
|
||||
unsigned int emu_status;
|
||||
unsigned int pad[30];
|
||||
} ssp1601_t;
|
||||
|
||||
|
||||
void ssp1601_reset(ssp1601_t *ssp);
|
||||
void ssp1601_run(int cycles);
|
||||
|
||||
#endif
|
26
source/cart_hw/svp/svp.c
Normal file
26
source/cart_hw/svp/svp.c
Normal file
@ -0,0 +1,26 @@
|
||||
// The SVP chip emulator
|
||||
|
||||
// (c) Copyright 2008, Grazvydas "notaz" Ignotas
|
||||
// Free for non-commercial use.
|
||||
|
||||
// For commercial use, separate licencing terms must be obtained.
|
||||
|
||||
/* SVP Controller */
|
||||
/* modified for Genesis Plus GCN port (eke-eke) */
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
svp_t *svp = NULL;
|
||||
uint16 SVP_cycles = 850;
|
||||
|
||||
void svp_init(void)
|
||||
{
|
||||
svp = (void *) ((char *)cart_rom + 0x200000);
|
||||
memset(svp, 0, sizeof(*svp));
|
||||
}
|
||||
|
||||
void svp_reset(void)
|
||||
{
|
||||
memcpy(svp->iram_rom + 0x800, cart_rom + 0x800, 0x20000 - 0x800);
|
||||
ssp1601_reset(&svp->ssp1601);
|
||||
}
|
30
source/cart_hw/svp/svp.h
Normal file
30
source/cart_hw/svp/svp.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* The SVP chip emulator
|
||||
|
||||
(c) Copyright 2008, Grazvydas "notaz" Ignotas
|
||||
Free for non-commercial use.
|
||||
|
||||
For commercial use, separate licencing terms must be obtained.
|
||||
|
||||
*/
|
||||
/* SVP Controller */
|
||||
/* modified for Genesis Plus GCN port (eke-eke) */
|
||||
|
||||
#ifndef _SVP_H_
|
||||
#define _SVP_H_
|
||||
|
||||
#include "shared.h"
|
||||
#include "ssp16.h"
|
||||
|
||||
typedef struct {
|
||||
unsigned char iram_rom[0x20000]; // IRAM (0-0x7ff) and program ROM (0x800-0x1ffff)
|
||||
unsigned char dram[0x20000];
|
||||
ssp1601_t ssp1601;
|
||||
} svp_t;
|
||||
|
||||
extern svp_t *svp;
|
||||
extern uint16 SVP_cycles;
|
||||
|
||||
extern void svp_init(void);
|
||||
extern void svp_reset(void);
|
||||
|
||||
#endif
|
524
source/cart_hw/svp/svpdoc.txt
Normal file
524
source/cart_hw/svp/svpdoc.txt
Normal file
@ -0,0 +1,524 @@
|
||||
-------------------------------------------------------------------------------
|
||||
notaz's SVP doc
|
||||
$Id: svpdoc.txt 349 2008-02-04 23:13:59Z notaz $
|
||||
Copyright 2008, Grazvydas Ignotas (notaz)
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
If you use this, please credit me in your work or it's documentation.
|
||||
Tasco Deluxe should also be credited for his pioneering work on the subject.
|
||||
Thanks.
|
||||
|
||||
Use monospace font and disable word wrap when reading this document.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Table of Contents
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
0. Introduction
|
||||
1. Overview
|
||||
2. The SSP160x DSP
|
||||
2.1. General registers
|
||||
2.2. External registers
|
||||
2.3. Pointer registers
|
||||
2.4. The instruction set
|
||||
3. Memory map
|
||||
4. Other notes
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
0. Introduction
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
This document is an attempt to provide technical information needed to
|
||||
emulate Sega's SVP chip. It is based on reverse engineering Virtua Racing
|
||||
game and on various internet sources. None of information provided here
|
||||
was verified on the real hardware, so some things are likely to be
|
||||
inaccurate.
|
||||
|
||||
The following information sources were used while writing this document
|
||||
and emulator implementation:
|
||||
|
||||
[1] SVP Reference Guide (annotated) and SVP Register Guide (annotated)
|
||||
by Tasco Deluxe < tasco.deluxe @ gmail.com >
|
||||
http://www.sharemation.com/TascoDLX/SVP%20Reference%20Guide%202007.02.11.txt
|
||||
http://www.sharemation.com/TascoDLX/SVP%20Register%20Guide%202007.02.11.txt
|
||||
[2] SSP1610 disassembler
|
||||
written by Pierpaolo Prazzoli, MAME source code.
|
||||
http://mamedev.org/
|
||||
[3] SSP1601 DSP datasheet
|
||||
http://notaz.gp2x.de/docs/SSP1601.pdf
|
||||
[4] DSP page (with code samples) in Samsung Semiconductor website from 1997
|
||||
retrieved from Internet Archive: The Wayback Machine
|
||||
http://web.archive.org/web/19970607052826/www.sec.samsung.com/Products/dsp/dspcore.htm
|
||||
[5] Sega's SVP Chip: The Road not Taken?
|
||||
Ken Horowitz, Sega-16
|
||||
http://sega-16.com/feature_page.php?id=37&title=Sega's%20SVP%20Chip:%20The%20Road%20not%20Taken?
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
1. Overview
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The only game released with SVP chip was Virtua Racing. There are at least 4
|
||||
versions of the game: USA, Jap and 2 different Eur revisions. Three of them
|
||||
share identical SSP160x code, one of the Eur revisions has some differences.
|
||||
|
||||
From the software developer's point of view, the game cartridge contains
|
||||
at least:
|
||||
|
||||
* Samsung SSP160x 16-bit DSP core, which includes [3]:
|
||||
* Two independent high-speed RAM banks, accessed in single clock cycle,
|
||||
256 words each.
|
||||
* 16 x 16 bit multiply unit.
|
||||
* 32-bit ALU, status register.
|
||||
* Hardware stack of 6 levels.
|
||||
* 128KB of DRAM.
|
||||
* 2KB of IRAM (instruction RAM).
|
||||
* Memory controller with address mapping capability.
|
||||
* 2MB of game ROM.
|
||||
|
||||
[5] claims there is also "2 Channels PWM" in the cartridge, but it's either
|
||||
not used or not there at all.
|
||||
Various sources claim that SSP160x is SSP1601 which is likely to be true,
|
||||
because the code doesn't seem to use any SSP1605+ features.
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
2. The SSP160x DSP
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
SSP160x is 16-bit DSP, capable of performing multiplication + addition in
|
||||
single clock cycle [3]. It has 8 general, 8 external and 8 pointer registers.
|
||||
There is a status register which has operation control bits and condition
|
||||
flags. Condition flags are set/cleared during ALU (arithmetic, logic)
|
||||
operations. It also has 6-level hardware stack and 2 internal RAM banks
|
||||
RAM0 and RAM1, 256 words each.
|
||||
|
||||
The device is only capable of addressing 16-bit words, so all addresses refer
|
||||
to words (16bit value in ROM, accessed by 68k through address 0x84 would be
|
||||
accessed by SSP160x using address 0x42).
|
||||
|
||||
[3] mentions interrupt pins, but interrupts don't seem to be used by SVP code
|
||||
(actually there are functions which look like interrupt handler routines, but
|
||||
they don't seem to do anything important).
|
||||
|
||||
2.1. General registers
|
||||
----------------------
|
||||
|
||||
There are 8 general registers: -, X, Y, A, ST, STACK, PC and P ([2] [4]).
|
||||
Size is given in bits.
|
||||
|
||||
2.1.1. "-"
|
||||
Constant register with all bits set (0xffff). Also used for programming
|
||||
external registers (blind reads/writes, see 2.2).
|
||||
size: 16
|
||||
|
||||
2.1.2. "X"
|
||||
Generic register. Also acts as a multiplier 1 for P register.
|
||||
size: 16
|
||||
|
||||
2.1.3. "Y"
|
||||
Generic register. Also acts as a multiplier 2 for P register.
|
||||
size: 16
|
||||
|
||||
2.1.4. "A"
|
||||
Accumulator. Stores the result of all ALU (but not multiply) operations,
|
||||
status register is updated according to this. When directly accessed,
|
||||
only upper word is read/written. Low word can be accessed by using AL
|
||||
(see 2.2.8).
|
||||
size: 32
|
||||
|
||||
2.1.5. "ST"
|
||||
STatus register. Bits 0-9 are CONTROL, other are FLAG [2]. Only some of
|
||||
them are actually used by SVP.
|
||||
Bits: fedc ba98 7654 3210
|
||||
210 - RPL "Loop size". If non-zero, makes (rX+) and (rX-) respectively
|
||||
modulo-increment and modulo-decrement (see 2.3). The value
|
||||
shows which power of 2 to use, i.e. 4 means modulo by 16.
|
||||
43 - RB Unknown. Not used by SVP code.
|
||||
5 - ST5 Affects behavior of external registers. See 2.2.
|
||||
6 - ST6 Affects behavior of external registers. See 2.2.
|
||||
According to [3] (5,6) bits correspond to hardware pins.
|
||||
7 - IE Interrupt enable? Not used by SVP code.
|
||||
8 - OP Saturated value? Not used by SVP code.
|
||||
9 - MACS MAC shift? Not used by SVP code.
|
||||
a - GPI_0 Interrupt 0 enable/status? Not used by SVP code.
|
||||
b - GPI_1 Interrupt 1 enable/status? Not used by SVP code.
|
||||
c - L L flag. Similar to carry? Not used by SVP code.
|
||||
d - Z Zero flag. Set after ALU operations, when all 32 accumulator
|
||||
bits become zero.
|
||||
e - OV Overflow flag. Not used by SVP code.
|
||||
f - N Negative flag. Set after ALU operations, when bit31 in
|
||||
accumulator is 1.
|
||||
size: 16
|
||||
|
||||
2.1.6. "STACK"
|
||||
Hardware stack of 6 levels [3]. Values are "pushed" by directly writing to
|
||||
it, or by "call" instruction. "Pop" is performed by directly reading the
|
||||
register or by "ret" instruction.
|
||||
size: 16
|
||||
|
||||
2.1.7. "PC"
|
||||
Program Counter. Can be written directly to perform a jump. It is not clear
|
||||
if it is possible to read it (SVP code never does).
|
||||
size: 16
|
||||
|
||||
2.1.8. "P"
|
||||
multiply Product - multiplication result register.
|
||||
Always contains 32-bit multiplication result of X, Y and 2 (P = X * Y * 2).
|
||||
X and Y are sign-extended before performing the multiplication.
|
||||
size: 32
|
||||
|
||||
2.2. External registers
|
||||
-----------------------
|
||||
|
||||
The external registers, as the name says, are external to SSP160x, they are
|
||||
hooked to memory controller in SVP, so by accessing them we actually program
|
||||
the memory controller. They act as programmable memory access registers or
|
||||
external status registers [1]. Some of them can act as both, depending on how
|
||||
ST5 ans ST6 bits are set in status register. After a register is programmed,
|
||||
accessing it causes reads/writes from/to external memory (see section 3 for
|
||||
the memory map). The access may also cause some additional effects, like
|
||||
incremental of address, associated with accessed register.
|
||||
In this document and my emu, instead of using names EXT0-EXT7
|
||||
from [4] I used different names for these registers. Those names are from
|
||||
Tasco Deluxe's [1] doc.
|
||||
|
||||
All these registers can be blind-accessed (as said in [1]) by performing
|
||||
(ld -, PMx) or (ld PMx, -). This programs them to access memory (except PMC,
|
||||
where the effect is different).
|
||||
All registers are 16-bit.
|
||||
|
||||
2.2.1. "PM0"
|
||||
If ST5 or ST6 is set, acts as Programmable Memory access register
|
||||
(see 2.2.7). Else it acts as status of XST (2.2.4). It is also mapped
|
||||
to a15004 on 68k side:
|
||||
???????? ??????10
|
||||
0: set, when SSP160x has written something to XST
|
||||
(cleared when 015004 is read by 68k)
|
||||
1: set, when 68k has written something to a15000 or a15002
|
||||
(cleared on PM0 read by SSP160x)
|
||||
Note that this is likely to be incorrect, but such behavior is OK for
|
||||
emulation to work.
|
||||
|
||||
2.2.2. "PM1"
|
||||
Programmable Memory access register. Only accessed with ST bits set by
|
||||
SVP code.
|
||||
|
||||
2.2.3. "PM2"
|
||||
Same as PM1.
|
||||
|
||||
2.2.4. "XST"
|
||||
If ST5 or ST6 is set, acts as Programmable Memory access register
|
||||
(only used by memory test code). Else it acts as eXternal STatus
|
||||
register, which is also mapped to a15000 and a15002 on 68k side.
|
||||
Affects PM0 when written to.
|
||||
|
||||
2.2.5. "PM4"
|
||||
Programmable Memory access register. Not affected by ST5 and ST6 bits,
|
||||
always stays in PMAR mode.
|
||||
|
||||
2.2.6. "EXT5"
|
||||
Not used by SVP, so not covered by this document.
|
||||
|
||||
2.2.7. "PMC"
|
||||
Programmable Memory access Control. It is set using 2 16bit writes, first
|
||||
address, then mode word. After setting PMAC, PMx should be blind accessed
|
||||
using (ld -, PMx) or (ld PMx, -) to program it for reading or writing
|
||||
external memory respectively. Every PMx register can be programmed to
|
||||
access it's own memory location with it's own mode. Registers are programmed
|
||||
separately for reading and writing.
|
||||
|
||||
Reading PMC register also shifts it's state (from "waiting for address" to
|
||||
"waiting for mode" and back). Reads always return address word related to
|
||||
last PMx register accessed, or last address word written to PMC (whichever
|
||||
event happened last before PMC read).
|
||||
|
||||
The address word contains bits 0-15 of the memory word-address.
|
||||
The mode word format is as follows:
|
||||
dsnnnv?? ???aaaaa
|
||||
a: bits 16-20 of memory word-address.
|
||||
n: auto-increment value. If set, after every access of PMx, word-address
|
||||
value related to it will be incremented by (words):
|
||||
1 - 1 5 - 16
|
||||
2 - 2 6 - 32
|
||||
3 - 4 7 - 128
|
||||
4 - 8
|
||||
d: make auto-increment negative - decrement by count listed above.
|
||||
s: special-increment mode. If current address is even (when accessing
|
||||
programmed PMx), increment it by 1. Else, increment by 32. It is not
|
||||
clear what happens if d and n bits are also set (never done by SVP).
|
||||
v: over-write mode when writing, unknown when reading (not used).
|
||||
Over-write mode splits the word being written into 4 half-bytes and
|
||||
only writes those half-bytes, which are not zero.
|
||||
When auto-increment is performed, it affects all 21 address bits.
|
||||
|
||||
2.2.8. "AL"
|
||||
This register acts more like a general register.
|
||||
If this register is blind-accessed, it is "dummy programmed", i.e. nothing
|
||||
happens and PMC is reset to "waiting for address" state.
|
||||
In all other cases, it is Accumulator Low, 16 least significant bits of
|
||||
accumulator. Normally reading acc (ld X, A) you get 16 most significant
|
||||
bits, so this allows you access the low word of 32bit accumulator.
|
||||
|
||||
2.3. Pointer registers
|
||||
----------------------
|
||||
|
||||
There are 8 8-bit pointer registers rX, which are internal to SSP160x and are
|
||||
used to access internal RAM banks RAM0 and RAM1, or program memory indirectly.
|
||||
r0-r3 (ri) point to RAM0, r4-r7 (rj) point to RAM1. Each bank has 256 words of
|
||||
RAM, so 8bit registers can fully address them. The registers can be accessed
|
||||
directly, or 2 indirection levels can be used [ (rX), ((rX)) ]. They work
|
||||
similar to * and ** operators in C, only they use different types of memory
|
||||
and ((rX)) also performs post-increment. First indirection level (rX) accesses
|
||||
a word in RAMx, second accesses program memory at address read from (rX), and
|
||||
increments value in (rX).
|
||||
|
||||
Only r0,r1,r2,r4,r5,r6 can be directly modified (ldi r0, 5), or by using
|
||||
modifiers. 3 modifiers can be applied when using first indirection level
|
||||
(optional):
|
||||
+ : post-increment (ld a, (r0+) ). Increment register value after operation.
|
||||
Can be made modulo-increment by setting RPL bits in status register
|
||||
(see 2.1.5).
|
||||
- : post-decrement. Also can be made modulo-decrement by using RPL bits in ST.
|
||||
+!: post-increment, unaffected by RPL (probably).
|
||||
These are only used on 1st indirection level, so things like ( ld a, ((r0+)) )
|
||||
and (ld X, r6-) are probably invalid.
|
||||
|
||||
r3 and r7 are special and can not be changed (at least Samsung samples [4] and
|
||||
SVP code never do). They are fixed to the start of their RAM banks. (They are
|
||||
probably changeable for ssp1605+, Samsung's old DSP page claims that).
|
||||
1 of these 4 modifiers must be used on these registers (short form direct
|
||||
addressing? [2]):
|
||||
|00: RAMx[0] The very first word in the RAM bank.
|
||||
|01: RAMx[1] Second word
|
||||
|10: RAMx[2] ...
|
||||
|11: RAMx[3]
|
||||
|
||||
2.4. The instruction set
|
||||
------------------------
|
||||
|
||||
The Samsung SSP16 series assembler uses right-to-left notation ([2] [4]):
|
||||
ld X, Y
|
||||
means value from Y should be copied to X.
|
||||
|
||||
Size of every instruction is word, some have extension words for immediate
|
||||
values. When writing an interpreter, 7 most significant bits are usually
|
||||
enough to determine which opcode it is.
|
||||
|
||||
encoding bits are marked as:
|
||||
rrrr - general or external register, in order specified in 2.1 and 2.2
|
||||
(0 is '-', 1 'X', ..., 8 is 'PM0', ..., 0xf is 'AL')
|
||||
dddd - same as above, as destination operand
|
||||
ssss - same as above, as source operand
|
||||
jpp - pointer register index, 0-7
|
||||
j - specifies RAM bank, i.e. RAM0 or RAM1
|
||||
i* - immediate value bits
|
||||
a* - offset in internal RAM bank
|
||||
mm - modifier for pointer register, depending on register:
|
||||
r0-r2,r4-r6 r3,r7 examples
|
||||
0: (none) |00 ld a, (r0) cmp a, (r7|00)
|
||||
1: +! |01 ld (r0+!), a ld (r7|01), a
|
||||
2: - |10 add a, (r0-)
|
||||
3: + |11
|
||||
cccc - encodes condition, only 3 used by SVP, see check_cond() below
|
||||
ooo - operation to perform
|
||||
|
||||
Operation is written in C-style pseudo-code, where:
|
||||
program_memory[X] - access program memory at address X
|
||||
RAMj[X] - access internal RAM bank j=0,1 (RAM0 or RAM1), word
|
||||
offset X
|
||||
RIJ[X] - pointer register rX, X=0-7
|
||||
pr_modif_read(m,X) - read pointer register rX, applying modifier m:
|
||||
if register is r3 or r7, return value m
|
||||
else switch on value m:
|
||||
0: return rX;
|
||||
1: tmp = rX; rX++; return tmp; // rX+!
|
||||
2: tmp = rX; modulo_decrement(rX); return tmp; // rX-
|
||||
3: tmp = rX; modulo_increment(rX); return tmp; // rX+
|
||||
the modulo value used (if used at all) depends on ST
|
||||
RPL bits (see 2.1.5)
|
||||
check_cond(c,f) - checks if a flag matches f bit:
|
||||
switch (c) {
|
||||
case 0: return true;
|
||||
case 5: return (Z == f) ? true : false; // check Z flag
|
||||
case 7: return (N == f) ? true : false; // check N flag
|
||||
} // other conditions are possible, but they are not used
|
||||
update_flags() - update ST flags according to last ALU operation.
|
||||
sign_extend(X) - sign extend 16bit value X to 32bits.
|
||||
next_op_address() - address of instruction after current instruction.
|
||||
|
||||
2.4.1. ALU instructions
|
||||
|
||||
All of these instructions update flags, which are set according to full 32bit
|
||||
accumulator. The SVP code only checks N and Z flags, so it is not known when
|
||||
exactly OV and L flags are set. Operations are performed on full A, so
|
||||
(andi A, 0) would clear all 32 bits of A.
|
||||
|
||||
They share the same addressing modes. The exact arithmetic operation is
|
||||
determined by 3 most significant (ooo) bits:
|
||||
001 - sub - subtract (OP -=)
|
||||
011 - cmp - compare (OP -, flags are updated according to result)
|
||||
100 - add - add (OP +=)
|
||||
101 - and - binary AND (OP &=)
|
||||
110 - or - binary OR (OP |=)
|
||||
111 - eor - exclusive OR (OP ^=)
|
||||
|
||||
syntax encoding operation
|
||||
OP A, s ooo0 0000 0000 rrrr A OP r << 16;
|
||||
OP A, (ri) ooo0 001j 0000 mmpp A OP RAMj[pr_modif_read(m,jpp)] << 16;
|
||||
OP A, adr ooo0 011j aaaa aaaa A OP RAMj[a] << 16;
|
||||
OPi A, imm ooo0 1000 0000 0000 A OP i << 16;
|
||||
iiii iiii iiii iiii
|
||||
op A, ((ri)) ooo0 101j 0000 mmpp tmp = pr_modif_read(m,jpp);
|
||||
A OP program_memory[RAMj[tmp]] << 16;
|
||||
RAMj[tmp]++;
|
||||
op A, ri ooo1 001j 0000 00pp A OP RIJ[jpp] << 16;
|
||||
OPi simm ooo1 1000 iiii iiii A OP i << 16;
|
||||
|
||||
There is also "perform operation on accumulator" instruction:
|
||||
|
||||
syntax encoding operation
|
||||
mod cond, op 1001 000f cccc 0ooo if (check_cond(c,f)) switch(o) {
|
||||
case 2: A >>= 1; break; // arithmetic shift
|
||||
case 3: A <<= 1; break;
|
||||
case 6: A = -A; break; // negate A
|
||||
case 7: A = abs(A); break; // absolute val.
|
||||
} // other operations are possible, but
|
||||
// they are not used by SVP.
|
||||
|
||||
2.4.2. Load (move) instructions
|
||||
|
||||
These instructions never affect flags (even ld A).
|
||||
If destination is A, and source is 16bit, only upper word is transfered (same
|
||||
thing happens on opposite). If dest. is A, and source is P, whole 32bit value
|
||||
is transfered. It is not clear if P can be destination operand (probably not,
|
||||
no code ever does this).
|
||||
Writing to STACK pushes a value there, reading pops. It is not known what
|
||||
happens on overflow/underflow (never happens in SVP code).
|
||||
ld -, - is used as a nop.
|
||||
|
||||
syntax encoding operation
|
||||
ld d, s 0000 0000 dddd ssss d = s;
|
||||
ld d, (ri) 0000 001j dddd mmpp d = RAMj[pr_modif_read(m,jpp)];
|
||||
ld (ri), s 0000 010j ssss mmpp RAMj[pr_modif_read(m,jpp)] = s;
|
||||
ldi d, imm 0000 1000 dddd 0000 d = i;
|
||||
iiii iiii iiii iiii
|
||||
ld d, ((ri)) 0000 101j dddd mmpp tmp = pr_modif_read(m,jpp);
|
||||
d = program_memory[RAMj[tmp]];
|
||||
RAMj[tmp]++;
|
||||
ldi (ri), imm 0000 110l 0000 mmpp RAMj[pr_modif_read(m,jpp)] = i;
|
||||
iiii iiii iiii iiii
|
||||
ld adr, a 0000 111j aaaa aaaa RAMj[a] = A;
|
||||
ld d, ri 0001 001j dddd 00pp d = RIJ[jpp];
|
||||
ld ri, s 0001 010j ssss 00pp RIJ[jpp] = s;
|
||||
ldi ri, simm 0001 1jpp iiii iiii RIJ[jpp] = i;
|
||||
ld d, (a) 0100 1010 dddd 0000 d = program_memory[A[31:16]];
|
||||
// read a word from program memory. Offset
|
||||
// is the upper word in A.
|
||||
|
||||
2.4.3. Program control instructions
|
||||
|
||||
Only 3 instructions: call, ret (alias of ld PC, STACK) and branch. Indirect
|
||||
jumps can be performed by simply writing to PC.
|
||||
|
||||
syntax encoding operation
|
||||
call cond, addr 0100 100f cccc 0000 if (check_cond(c,f)) {
|
||||
aaaa aaaa aaaa aaaa STACK = next_op_address(); PC = a;
|
||||
}
|
||||
bra cond, addr 0100 110f cccc 0000 if (check_cond(c,f)) PC = a;
|
||||
aaaa aaaa aaaa aaaa
|
||||
ret 0000 0000 0110 0101 PC = STACK; // same as ld PC, STACK
|
||||
|
||||
2.4.4. Multiply-accumulate instructions
|
||||
|
||||
Not sure if (ri) and (rj) really get loaded into X and Y, but multiplication
|
||||
result surely is loaded into P. There is probably optional 3rd operand (1, 0;
|
||||
encoded by bit16, default 1), but it's not used by SVP code.
|
||||
|
||||
syntax encoding operation
|
||||
mld (rj), (ri) 1011 0111 nnjj mmii A = 0; update_flags();
|
||||
X = RAM0[pr_modif_read(m,0ii)];
|
||||
Y = RAM1[pr_modif_read(m,1jj)];
|
||||
P = sign_extend(X) * sign_extend(Y) * 2
|
||||
mpya (rj), (ri) 1001 0111 nnjj mmii A += P; update_flags();
|
||||
X = RAM0[pr_modif_read(m,0ii)];
|
||||
Y = RAM1[pr_modif_read(m,1jj)];
|
||||
P = sign_extend(X) * sign_extend(Y) * 2
|
||||
mpys (rj), (ri) 0011 0111 nnjj mmii A -= P; update_flags();
|
||||
X = RAM0[pr_modif_read(m,0ii)];
|
||||
Y = RAM1[pr_modif_read(m,1jj)];
|
||||
P = sign_extend(X) * sign_extend(Y) * 2
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
3. Memory map
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The SSp160x can access it's own program memory, and external memory through EXT
|
||||
registers (see 2.2). Program memory is read-execute-only, the size of this
|
||||
space is 64K words (this is how much 16bit PC can address):
|
||||
|
||||
byte address word address name
|
||||
0- 7ff 0- 3ff IRAM
|
||||
800-1ffff 400-ffff ROM
|
||||
|
||||
There were reports that SVP has internal ROM, but fortunately they were wrong.
|
||||
The location 800-1ffff is mapped from the same location in the 2MB game ROM.
|
||||
The IRAM is read-only (as SSP160x doesn't have any means of writing to it's
|
||||
program memory), but it can be changed through external memory space, as it's
|
||||
also mapped there.
|
||||
|
||||
The external memory space seems to match the one visible by 68k, with some
|
||||
differences:
|
||||
|
||||
68k space SVP space word address name
|
||||
0-1fffff 0-1fffff 0- fffff game ROM
|
||||
300000-31ffff 300000-31ffff 180000-18ffff DRAM
|
||||
? 390000-3907ff 1c8000-1c83ff IRAM
|
||||
390000-39ffff ? ? "cell arrange" 1
|
||||
3a0000-3affff ? ? "cell arrange" 2
|
||||
a15000-a15009 n/a n/a Status/control registers
|
||||
|
||||
The external memory can be read/written by SSP160x (except game ROM, which can
|
||||
only be read).
|
||||
|
||||
"cell arrange" 1 and 2 are similar to the one used in SegaCD, they map
|
||||
300000-30ffff location to 390000-39ffff and 3a0000-3affff, where linear image
|
||||
written to 300000 can be read as VDP patterns at 390000. Virtua Racing doesn't
|
||||
seem to use this feature, it is only used by memory test code.
|
||||
|
||||
Here is the list of status/control registers (16bit size):
|
||||
a15000 - w/r command/result register. Visible as XST for SSP160x (2.2.4).
|
||||
a15002 - mirror of the above.
|
||||
a15004 - status of command/result register (see 2.2.1).
|
||||
a15006 - possibly halts the SVP. Before doing DMA from DRAM, 68k code writes
|
||||
0xa, and after it's finished, writes 0. This is probably done to
|
||||
prevent SVP accessing DRAM and avoid bus clashes.
|
||||
a15008 - possibly causes an interrupt. There is (unused?) code which writes
|
||||
0, 1, and again 0 in sequence.
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
4. Other notes
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The game has arcade-style memory self-check mode, which can be accessed by
|
||||
pressing _all_ buttons (including directions) on 3-button controller. There was
|
||||
probably some loopback plug for this.
|
||||
|
||||
SVP seems to have DMA latency issue similar to one in Sega CD, as the code
|
||||
always sets DMA source address value larger by 2, then intended for copy.
|
||||
This is even true for DMAs from ROM, as it's probably hooked through SVP's
|
||||
memory controller.
|
||||
|
||||
The entry point for the code seems to be at address 0x800 (word 0x400) in ROM,
|
||||
but it is not clear where the address is fetched from when the system powers
|
||||
up. The memory test code also sets up "ld PC, .." opcodes at 0x7f4, 0x7f8 and
|
||||
0x7fc, which jump to some routines, possibly interrupt handlers. This means
|
||||
that mentioned addresses might be built-in interrupt vectors.
|
||||
|
||||
The SVP code doesn't seem to be timing sensitive, so it can be emulated without
|
||||
knowing timing of the instructions or even how fast the chip is clocked.
|
||||
Overclocking doesn't have any effect, underclocking causes slowdowns. Running
|
||||
10-12M instructions/sec (or possibly less) is sufficient.
|
||||
|
@ -4,12 +4,41 @@
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
#define CPU_16BIT_PORT 0x4000
|
||||
#define CPU_FLAGS_MASK 0xff00
|
||||
#define CLEAR_LINE 0
|
||||
#define ASSERT_LINE 1
|
||||
#define REG_PREVIOUSPC -1
|
||||
#define REG_SP_CONTENTS -2
|
||||
/* Interrupt line constants */
|
||||
enum
|
||||
{
|
||||
/* line states */
|
||||
CLEAR_LINE = 0, /* clear (a fired, held or pulsed) line */
|
||||
ASSERT_LINE, /* assert an interrupt immediately */
|
||||
HOLD_LINE, /* hold interrupt line until acknowledged */
|
||||
PULSE_LINE, /* pulse interrupt line for one instruction */
|
||||
|
||||
/* internal flags (not for use by drivers!) */
|
||||
INTERNAL_CLEAR_LINE = 100 + CLEAR_LINE,
|
||||
INTERNAL_ASSERT_LINE = 100 + ASSERT_LINE,
|
||||
|
||||
/* input lines */
|
||||
MAX_INPUT_LINES = 32+3,
|
||||
INPUT_LINE_IRQ0 = 0,
|
||||
INPUT_LINE_IRQ1 = 1,
|
||||
INPUT_LINE_IRQ2 = 2,
|
||||
INPUT_LINE_IRQ3 = 3,
|
||||
INPUT_LINE_IRQ4 = 4,
|
||||
INPUT_LINE_IRQ5 = 5,
|
||||
INPUT_LINE_IRQ6 = 6,
|
||||
INPUT_LINE_IRQ7 = 7,
|
||||
INPUT_LINE_IRQ8 = 8,
|
||||
INPUT_LINE_IRQ9 = 9,
|
||||
INPUT_LINE_NMI = MAX_INPUT_LINES - 3,
|
||||
|
||||
/* special input lines that are implemented in the core */
|
||||
INPUT_LINE_RESET = MAX_INPUT_LINES - 2,
|
||||
INPUT_LINE_HALT = MAX_INPUT_LINES - 1,
|
||||
|
||||
/* output lines */
|
||||
MAX_OUTPUT_LINES = 32
|
||||
};
|
||||
|
||||
|
||||
/* daisy-chain link */
|
||||
typedef struct {
|
||||
|
@ -25,14 +25,28 @@
|
||||
#ifndef OSD_CPU_H
|
||||
#define OSD_CPU_H
|
||||
|
||||
#ifndef NGC
|
||||
#ifndef DOS
|
||||
#include "basetsd.h"
|
||||
#endif
|
||||
#undef TRUE
|
||||
#undef FALSE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
typedef unsigned char UINT8;
|
||||
typedef unsigned short UINT16;
|
||||
//#ifdef DOS
|
||||
typedef unsigned int UINT32;
|
||||
__extension__ typedef unsigned long long UINT64;
|
||||
//#endif
|
||||
typedef signed char INT8;
|
||||
typedef signed short INT16;
|
||||
//#ifdef DOS
|
||||
typedef signed int INT32;
|
||||
__extension__ typedef signed long long INT64;
|
||||
//#endif
|
||||
|
||||
/* Combine two 32-bit integers into a 64-bit integer */
|
||||
#define COMBINE_64_32_32(A,B) ((((UINT64)(A))<<32) | (UINT32)(B))
|
||||
|
3900
source/cpu/z80.c
3900
source/cpu/z80.c
File diff suppressed because it is too large
Load Diff
@ -1,14 +1,15 @@
|
||||
#ifndef Z80_H
|
||||
#define Z80_H
|
||||
#ifndef Z80_H_
|
||||
#define Z80_H_
|
||||
|
||||
#include "cpuintrf.h"
|
||||
#include "osd_cpu.h"
|
||||
|
||||
enum {
|
||||
Z80_PC=1, Z80_SP, Z80_AF, Z80_BC, Z80_DE, Z80_HL,
|
||||
Z80_PC=1, Z80_SP, Z80_A, Z80_B,
|
||||
Z80_C, Z80_D, Z80_E, Z80_H, Z80_L,
|
||||
Z80_AF, Z80_BC, Z80_DE, Z80_HL,
|
||||
Z80_IX, Z80_IY, Z80_AF2, Z80_BC2, Z80_DE2, Z80_HL2,
|
||||
Z80_R, Z80_I, Z80_IM, Z80_IFF1, Z80_IFF2, Z80_HALT,
|
||||
Z80_NMI_STATE, Z80_IRQ_STATE, Z80_DC0, Z80_DC1, Z80_DC2, Z80_DC3
|
||||
Z80_DC0, Z80_DC1, Z80_DC2, Z80_DC3
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -20,38 +21,35 @@ enum {
|
||||
Z80_TABLE_ex /* cycles counts for taken jr/jp/call and interrupt latency (rst opcodes) */
|
||||
};
|
||||
|
||||
extern int z80_ICount; /* T-state count */
|
||||
/****************************************************************************/
|
||||
/* The Z80 registers. HALT is set to 1 when the CPU is halted, the refresh */
|
||||
/* register is calculated as follows: refresh=(Z80.r&127)|(Z80.r2&128) */
|
||||
/****************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
PAIR prvpc,pc,sp,af,bc,de,hl,ix,iy;
|
||||
PAIR af2,bc2,de2,hl2;
|
||||
UINT8 r,r2,iff1,iff2,halt,im,i;
|
||||
UINT8 nmi_state; /* nmi line state */
|
||||
UINT8 nmi_pending; /* nmi pending */
|
||||
UINT8 irq_state; /* irq line state */
|
||||
UINT8 after_ei; /* are we in the EI shadow? */
|
||||
const struct z80_irq_daisy_chain *daisy;
|
||||
int (*irq_callback)(int irqline);
|
||||
} Z80_Regs;
|
||||
|
||||
#define Z80_IGNORE_INT -1 /* Ignore interrupt */
|
||||
#define Z80_NMI_INT -2 /* Execute NMI */
|
||||
#define Z80_IRQ_INT -1000 /* Execute IRQ */
|
||||
|
||||
extern void z80_reset (void *param);
|
||||
extern void z80_exit (void);
|
||||
extern void z80_end_timeslice(void);
|
||||
extern int z80_execute(int cycles);
|
||||
extern void z80_burn(int cycles);
|
||||
extern unsigned z80_get_context (void *dst);
|
||||
extern void z80_set_context (void *src);
|
||||
extern void *z80_get_cycle_table (int which);
|
||||
extern void z80_set_cycle_table (int which, void *new_tbl);
|
||||
extern unsigned z80_get_pc (void);
|
||||
extern void z80_set_pc (unsigned val);
|
||||
extern unsigned z80_get_sp (void);
|
||||
extern void z80_set_sp (unsigned val);
|
||||
extern unsigned z80_get_reg (int regnum);
|
||||
extern void z80_set_reg (int regnum, unsigned val);
|
||||
extern void z80_set_nmi_line(int state);
|
||||
extern void z80_set_irq_line(int irqline, int state);
|
||||
extern void z80_set_irq_callback(int (*irq_callback)(int));
|
||||
extern void z80_state_save(void *file);
|
||||
extern void z80_state_load(void *file);
|
||||
extern const char *z80_info(void *context, int regnum);
|
||||
extern unsigned z80_dasm(char *buffer, unsigned pc);
|
||||
extern int z80_ICount;
|
||||
extern Z80_Regs Z80;
|
||||
|
||||
#ifdef MAME_DEBUG
|
||||
extern unsigned DasmZ80(char *buffer, unsigned pc);
|
||||
#endif
|
||||
void z80_init(int index, int clock, const void *config, int (*irqcallback)(int));
|
||||
void z80_reset (void);
|
||||
void z80_exit (void);
|
||||
int z80_execute(int cycles);
|
||||
void z80_burn(int cycles);
|
||||
void z80_get_context (void *dst);
|
||||
void z80_set_context (void *src);
|
||||
void z80_set_irq_line(int irqline, int state);
|
||||
|
||||
unsigned int cpu_readport16(unsigned int port);
|
||||
void cpu_writeport16(unsigned int port, unsigned int data);
|
||||
|
2051
source/cpu/z80daa.h
2051
source/cpu/z80daa.h
File diff suppressed because it is too large
Load Diff
238
source/genesis.c
238
source/genesis.c
@ -1,24 +1,30 @@
|
||||
/*
|
||||
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* Genesis internals & Bus arbitration
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
uint8 *cart_rom; /* cart_rom NEED to be previously dynamically allocated */
|
||||
uint8 bios_rom[0x800];
|
||||
uint8 work_ram[0x10000]; /* 68K work RAM */
|
||||
uint8 zram[0x2000]; /* Z80 work RAM */
|
||||
uint8 zbusreq; /* /BUSREQ from Z80 */
|
||||
@ -27,64 +33,119 @@ uint8 zbusack; /* /BUSACK to Z80 */
|
||||
uint8 zirq; /* /IRQ to Z80 */
|
||||
uint32 zbank; /* Address of Z80 bank window */
|
||||
uint8 gen_running;
|
||||
uint32 lastbusreqcnt;
|
||||
uint8 lastbusack;
|
||||
uint32 genromsize;
|
||||
|
||||
static int cpu_sync[512]; /* Z80-68K cycles synchronization table */
|
||||
|
||||
#ifdef LSB_FIRST
|
||||
void bswap(uint8 *mem, int length)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < length; i += 2)
|
||||
{
|
||||
uint8 temp = mem[i+0];
|
||||
mem[i+0] = mem[i+1];
|
||||
mem[i+1] = temp;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
uint32 rom_size;
|
||||
int32 resetline;
|
||||
uint8 *rom_readmap[8];
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Init, reset, shutdown functions */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void set_softreset(void)
|
||||
{
|
||||
resetline = (int) ((double) (lines_per_frame - 1) * rand() / (RAND_MAX + 1.0));
|
||||
}
|
||||
|
||||
void gen_init (void)
|
||||
{
|
||||
int i;
|
||||
#ifdef LSB_FIRST
|
||||
bswap(cart_rom, genromsize);
|
||||
#endif
|
||||
#ifdef NGC
|
||||
ShadowROM ();
|
||||
#else
|
||||
memcpy(shadow_rom,cart_rom,genromsize);
|
||||
#endif
|
||||
|
||||
/* initialize CPUs */
|
||||
m68k_set_cpu_type (M68K_CPU_TYPE_68000);
|
||||
m68k_pulse_reset ();
|
||||
gen_running = 1;
|
||||
for (i=0; i<512; i++) cpu_sync[i] = (int)(((double)i * 7.0) / 15.0);
|
||||
m68k_init();
|
||||
z80_init(0,0,0,z80_irq_callback);
|
||||
|
||||
/* default 68000 mapping */
|
||||
for (i=16; i<24; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = ILLEGAL;
|
||||
m68k_readmap_16[i] = ILLEGAL;
|
||||
m68k_writemap_8[i] = ILLEGAL;
|
||||
m68k_writemap_16[i] = ILLEGAL;
|
||||
}
|
||||
|
||||
/* Z80, I/O, CONTROL */
|
||||
m68k_readmap_8[20] = SYSTEM_IO;
|
||||
m68k_readmap_16[20] = SYSTEM_IO;
|
||||
m68k_writemap_8[20] = SYSTEM_IO;
|
||||
m68k_writemap_16[20] = SYSTEM_IO;
|
||||
|
||||
/* SEGA PICO */
|
||||
if (system_hw == SYSTEM_PICO)
|
||||
{
|
||||
m68k_readmap_8[16] = PICO_HW;
|
||||
m68k_readmap_16[16] = PICO_HW;
|
||||
m68k_writemap_8[16] = PICO_HW;
|
||||
m68k_writemap_16[16] = PICO_HW;
|
||||
|
||||
/* Notaz: there is no IO CONTROL area (Z80/YM2612/IO) */
|
||||
m68k_readmap_8[20] = UNUSED;
|
||||
m68k_readmap_16[20] = UNUSED;
|
||||
m68k_writemap_8[20] = UNUSED;
|
||||
m68k_writemap_16[20] = UNUSED;
|
||||
}
|
||||
|
||||
/* VDP */
|
||||
for (i=24; i<28; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = VDP;
|
||||
m68k_readmap_16[i] = VDP;
|
||||
m68k_writemap_8[i] = VDP;
|
||||
m68k_writemap_16[i] = VDP;
|
||||
}
|
||||
|
||||
/* WRAM */
|
||||
for (i=28; i<32; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = WRAM;
|
||||
m68k_readmap_16[i] = WRAM;
|
||||
m68k_writemap_8[i] = WRAM;
|
||||
m68k_writemap_16[i] = WRAM;
|
||||
}
|
||||
}
|
||||
|
||||
void gen_reset (void)
|
||||
void gen_reset (unsigned int hard_reset)
|
||||
{
|
||||
if (hard_reset)
|
||||
{
|
||||
/* Clear RAM */
|
||||
memset (work_ram, 0, sizeof (work_ram));
|
||||
memset (zram, 0, sizeof (zram));
|
||||
|
||||
/* Reset ROM mapping */
|
||||
if (config.bios_enabled == 3)
|
||||
{
|
||||
rom_readmap[0] = &bios_rom[0];
|
||||
rom_size = 0x800;
|
||||
}
|
||||
else
|
||||
{
|
||||
rom_readmap[0] = &cart_rom[0];
|
||||
rom_size = genromsize;
|
||||
}
|
||||
|
||||
uint8 i;
|
||||
for (i=1; i<8; i++) rom_readmap[i] = &cart_rom[i << 19];
|
||||
}
|
||||
|
||||
gen_running = 1;
|
||||
zreset = 0; /* Z80 is reset */
|
||||
zbusreq = 0; /* Z80 has control of the Z bus */
|
||||
zbusack = 1; /* Z80 is busy using the Z bus */
|
||||
zbank = 0; /* Assume default bank is 000000-007FFF */
|
||||
zirq = 0; /* No interrupts occuring */
|
||||
lastbusreqcnt = 0;
|
||||
lastbusack = 1;
|
||||
resetline = -1;
|
||||
|
||||
/* Reset the 68000 emulator */
|
||||
/* Reset CPUs */
|
||||
m68k_pulse_reset ();
|
||||
z80_reset (0);
|
||||
z80_set_irq_callback (z80_irq_callback);
|
||||
z80_reset ();
|
||||
_YM2612_Reset();
|
||||
|
||||
#ifdef NGC
|
||||
/* register SOFTRESET */
|
||||
SYS_SetResetCallback(set_softreset);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void gen_shutdown (void)
|
||||
@ -94,69 +155,84 @@ void gen_shutdown (void)
|
||||
/*-----------------------------------------------------------------------
|
||||
Bus controller chip functions
|
||||
-----------------------------------------------------------------------*/
|
||||
int gen_busack_r (void)
|
||||
unsigned int gen_busack_r (void)
|
||||
{
|
||||
if (zbusack == 0)
|
||||
{
|
||||
if ((count_m68k + m68k_cycles_run() - lastbusreqcnt) > 16)
|
||||
return 0; /* bus taken */
|
||||
else return (lastbusack&1);
|
||||
}
|
||||
else return 1;
|
||||
return zbusack;
|
||||
}
|
||||
|
||||
void gen_busreq_w (int state)
|
||||
void gen_busreq_w (unsigned int state)
|
||||
{
|
||||
int z80_cycles_to_run;
|
||||
|
||||
input_raz ();
|
||||
input_raz (); /* from Gens */
|
||||
|
||||
if (state == 1)
|
||||
if (state)
|
||||
{
|
||||
/* Bus Request */
|
||||
lastbusreqcnt = count_m68k + m68k_cycles_run();
|
||||
lastbusack = zbusack;
|
||||
if (zbusreq == 0)
|
||||
if (!zbusreq && zreset)
|
||||
{
|
||||
/* Z80 stopped */
|
||||
/* z80 was ON during the last 68k cycles */
|
||||
/* we execute the appropriate number of z80 cycles */
|
||||
z80_cycles_to_run = aim_z80 - cpu_sync[aim_m68k - count_m68k - m68k_cycles_run()];
|
||||
if (z80_cycles_to_run > 0) z80_run(z80_cycles_to_run);
|
||||
z80_cycles_to_run = line_z80 + ((count_m68k - line_m68k)*7)/15;
|
||||
z80_run(z80_cycles_to_run);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Bus released */
|
||||
if (zbusreq == 1)
|
||||
if (zbusreq && zreset)
|
||||
{
|
||||
/* Z80 started */
|
||||
/* z80 was OFF during the last 68k cycles */
|
||||
/* we burn the appropriate number of z80 cycles */
|
||||
z80_cycles_to_run = aim_z80 - cpu_sync[aim_m68k - count_m68k - m68k_cycles_run()];
|
||||
if (z80_cycles_to_run > 0) count_z80 = z80_cycles_to_run;
|
||||
z80_cycles_to_run = line_z80 + ((count_m68k - line_m68k)*7)/15;
|
||||
count_z80 = z80_cycles_to_run;
|
||||
}
|
||||
}
|
||||
zbusreq = (state & 1);
|
||||
|
||||
zbusreq = state;
|
||||
zbusack = 1 ^ (zbusreq & zreset);
|
||||
}
|
||||
|
||||
void gen_reset_w (int state)
|
||||
void gen_reset_w (unsigned int state)
|
||||
{
|
||||
zreset = (state & 1);
|
||||
zbusack = 1 ^ (zbusreq & zreset);
|
||||
int z80_cycles_to_run;
|
||||
|
||||
if (zreset == 0)
|
||||
if (state)
|
||||
{
|
||||
lastbusreqcnt = 0;
|
||||
lastbusack = 1;
|
||||
fm_reset();
|
||||
z80_reset (0);
|
||||
z80_set_irq_callback (z80_irq_callback);
|
||||
/* stop RESET process */
|
||||
if (!zbusreq && !zreset)
|
||||
{
|
||||
/* Z80 started */
|
||||
/* z80 was OFF during the last 68k cycles */
|
||||
/* we burn the appropriate number of z80 cycles */
|
||||
z80_cycles_to_run = line_z80 + ((count_m68k - line_m68k)*7)/15;
|
||||
count_z80 = z80_cycles_to_run;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* start RESET process */
|
||||
if (!zbusreq && zreset)
|
||||
{
|
||||
/* Z80 stopped */
|
||||
/* z80 was ON during the last 68k cycles */
|
||||
/* we execute the appropriate number of z80 cycles */
|
||||
z80_cycles_to_run = line_z80 + ((count_m68k - line_m68k)*7)/15;
|
||||
z80_run(z80_cycles_to_run);
|
||||
}
|
||||
|
||||
/* Reset Z80 & YM2612 */
|
||||
_YM2612_Reset();
|
||||
z80_reset ();
|
||||
}
|
||||
|
||||
zreset = state;
|
||||
zbusack = 1 ^ (zbusreq & zreset);
|
||||
}
|
||||
|
||||
void gen_bank_w (int state)
|
||||
void gen_bank_w (unsigned int state)
|
||||
{
|
||||
zbank = ((zbank >> 1) | ((state & 1) << 23)) & 0xFF8000;
|
||||
}
|
||||
|
@ -1,9 +1,32 @@
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* Genesis internals & Bus arbitration
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef _GENESIS_H_
|
||||
#define _GENESIS_H_
|
||||
|
||||
/* Global variables */
|
||||
extern uint8 *cart_rom;
|
||||
extern uint8 bios_rom[0x800];
|
||||
extern uint8 work_ram[0x10000];
|
||||
extern uint8 zram[0x2000];
|
||||
extern uint8 zbusreq;
|
||||
@ -12,21 +35,21 @@ extern uint8 zreset;
|
||||
extern uint8 zirq;
|
||||
extern uint32 zbank;
|
||||
extern uint8 gen_running;
|
||||
extern uint32 lastbusreqcnt;
|
||||
extern uint8 lastbusack;
|
||||
extern uint32 genromsize;
|
||||
extern uint32 rom_size;
|
||||
extern int32 resetline;
|
||||
extern uint8 *rom_readmap[8];
|
||||
|
||||
/* Function prototypes */
|
||||
void gen_init(void);
|
||||
void gen_reset(void);
|
||||
void gen_shutdown(void);
|
||||
int gen_busack_r(void);
|
||||
void gen_busreq_w(int state);
|
||||
void gen_reset_w(int state);
|
||||
void gen_bank_w(int state);
|
||||
void bswap(uint8 *mem, int length);
|
||||
int z80_irq_callback(int param);
|
||||
void m68k_irq_ack_callback(int int_level);
|
||||
extern void gen_init(void);
|
||||
extern void gen_reset(unsigned int hard_reset);
|
||||
extern void gen_shutdown(void);
|
||||
extern unsigned int gen_busack_r(void);
|
||||
extern void gen_busreq_w(unsigned int state);
|
||||
extern void gen_reset_w(unsigned int state);
|
||||
extern void gen_bank_w(unsigned int state);
|
||||
extern int z80_irq_callback(int param);
|
||||
extern void set_softreset(void);
|
||||
|
||||
#endif /* _GEN_H_ */
|
||||
|
||||
|
505
source/hvc.h
505
source/hvc.h
@ -1,4 +1,125 @@
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* HV Counters
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
/*
|
||||
NTSC, 256x192
|
||||
-------------
|
||||
|
||||
Lines Description
|
||||
|
||||
192 Active display
|
||||
24 Bottom border
|
||||
3 Bottom blanking
|
||||
3 Vertical blanking
|
||||
13 Top blanking
|
||||
27 Top border
|
||||
|
||||
V counter values
|
||||
00-DA, D5-FF
|
||||
|
||||
NTSC, 256x224
|
||||
-------------
|
||||
|
||||
Lines Description
|
||||
|
||||
224 Active display
|
||||
8 Bottom border
|
||||
3 Bottom blanking
|
||||
3 Vertical blanking
|
||||
13 Top blanking
|
||||
11 Top border
|
||||
|
||||
V counter values
|
||||
00-EA, E5-FF
|
||||
|
||||
NTSC, 256x240
|
||||
-------------
|
||||
|
||||
This mode does not work on NTSC machines. All 30 rows of the name table are
|
||||
displayed, there is no border, blanking, or retrace period, and the next
|
||||
frame starts after the 30th row. The display rolls continuously though it
|
||||
can be stabilized by adjusting the vertical hold.
|
||||
|
||||
V counter values
|
||||
00-FF, 00-06
|
||||
|
||||
PAL, 256x192
|
||||
------------
|
||||
|
||||
Lines Description
|
||||
|
||||
192 Active display
|
||||
48 Bottom border
|
||||
3 Bottom blanking
|
||||
3 Vertical blanking
|
||||
13 Top blanking
|
||||
54 Top border
|
||||
|
||||
V counter values
|
||||
00-F2, BA-FF
|
||||
|
||||
PAL, 256x224
|
||||
------------
|
||||
|
||||
Lines Description
|
||||
|
||||
224 Active display
|
||||
32 Bottom border
|
||||
3 Bottom blanking
|
||||
3 Vertical blanking
|
||||
13 Top blanking
|
||||
38 Top border
|
||||
|
||||
V counter values
|
||||
00-FF, 00-02, CA-FF
|
||||
|
||||
PAL, 256x240
|
||||
------------
|
||||
|
||||
Lines Description
|
||||
|
||||
240 Active display
|
||||
24 Bottom border
|
||||
3 Bottom blanking
|
||||
3 Vertical blanking
|
||||
13 Top blanking
|
||||
30 Top border
|
||||
|
||||
V counter values
|
||||
00-FF, 00-0A, D2-FF
|
||||
|
||||
Here are some details about what the different screen areas look like,
|
||||
useful if you are emulating overscan or if you want to have a 'virtual'
|
||||
vertical hold control in your emulator.
|
||||
|
||||
Active display - Where the display generated by the VDP goes.
|
||||
Bottom border - Filled with border color from VDP register #7.
|
||||
Bottom blanking - Filled with a light black color. (like display was blanked)
|
||||
Vertical sync - Filled with a pure black color. (like display was turned off)
|
||||
Top blanking - Filled with a light black color. (like display was blanked)
|
||||
Top border - Filled with the border color from VDP register #7.
|
||||
|
||||
*/
|
||||
#ifndef _HVC_H_
|
||||
#define _HVC_H_
|
||||
|
||||
@ -24,7 +145,7 @@ uint8 vc_ntsc_192[262] = {
|
||||
};
|
||||
|
||||
/* V counter values for NTSC 224-line display */
|
||||
uint16 vc_ntsc_224[262] = {
|
||||
uint8 vc_ntsc_224[262] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
@ -44,7 +165,7 @@ uint16 vc_ntsc_224[262] = {
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/* V counter values for NTSC 240-line display */
|
||||
/* V counter values for NTSC 240-line display (invalid mode) */
|
||||
uint8 vc_ntsc_240[262] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
@ -83,15 +204,15 @@ uint8 vc_pal_192[313] = {
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2,
|
||||
0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6,
|
||||
0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
|
||||
0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
|
||||
0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6,
|
||||
0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/* V counter values for PAL 224-line display */
|
||||
uint16 vc_pal_224[313] = {
|
||||
uint8 vc_pal_224[313] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
@ -108,15 +229,15 @@ uint16 vc_pal_224[313] = {
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
0x100, 0x101, 0x102,
|
||||
0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
0x00, 0x01, 0x02,
|
||||
0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
|
||||
0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
|
||||
0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6,
|
||||
0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/* V counter values for PAL 240-line display */
|
||||
uint16 vc_pal_240[313] = {
|
||||
uint8 vc_pal_240[313] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
@ -133,10 +254,11 @@ uint16 vc_pal_240[313] = {
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10A,
|
||||
0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
|
||||
0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
|
||||
0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
|
||||
0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6,
|
||||
0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/*
|
||||
@ -179,263 +301,114 @@ uint16 vc_pal_240[313] = {
|
||||
The V-blanking flag can also be forcibly set by disabling the display
|
||||
through bit 6 of register #1.
|
||||
|
||||
*/
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
H counter
|
||||
|
||||
Now for some additional information on the horizontal aspects of the
|
||||
display, taken from the TMS9918 manual and my tests on a NTSC Genesis.
|
||||
Be warned that a real SMS may have different results.
|
||||
|
||||
The H counter is 9 bits, and reading it returns the upper 8 bits. This is
|
||||
because a scanline consists of 342 pixels, which couldn't be represented
|
||||
with an 8-bit counter. Each scanline is divided up as follows:
|
||||
|
||||
Pixels H.Cnt Description
|
||||
256 : 00-7F : Active display
|
||||
15 : 80-87 : Right border
|
||||
8 : 87-8B : Right blanking
|
||||
26 : 8B-ED : Horizontal sync
|
||||
2 : ED-EE : Left blanking
|
||||
14 : EE-F5 : Color burst
|
||||
8 : F5-F9 : Left blanking
|
||||
13 : F9-FF : Left border
|
||||
|
||||
Here's a description of what these areas look like:
|
||||
|
||||
Active display - Where the display generated by the VDP goes.
|
||||
Right border - Filled with border color from VDP register $07.
|
||||
Right blanking - Filled with a light black color. (like display was blanked)
|
||||
Horizontal sync - Filled with a pure black color. (like display was turned off)
|
||||
Left blanking - Filled with the border color from VDP register $07.
|
||||
Color burst - Filled with a dark brown/orange color.
|
||||
Left blanking - Filled with a light black color. (like display was blanked)
|
||||
Left border - Filled with the border color from VDP register $07.
|
||||
|
||||
*/
|
||||
|
||||
uint8 cycle2hc32[488] = {
|
||||
0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05,
|
||||
0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0A,
|
||||
0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x10, 0x10,
|
||||
0x10, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15, 0x15, 0x16,
|
||||
0x16, 0x16, 0x17, 0x17, 0x17, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B,
|
||||
0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21,
|
||||
0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x26,
|
||||
0x27, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x29, 0x2A, 0x2A, 0x2A, 0x2B, 0x2B, 0x2B, 0x2C, 0x2C,
|
||||
0x2C, 0x2D, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x2F, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x32,
|
||||
0x32, 0x32, 0x33, 0x33, 0x33, 0x34, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, 0x36, 0x37, 0x37, 0x37,
|
||||
0x38, 0x38, 0x38, 0x39, 0x39, 0x39, 0x3A, 0x3A, 0x3A, 0x3B, 0x3B, 0x3B, 0x3C, 0x3C, 0x3D, 0x3D,
|
||||
0x3D, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F, 0x40, 0x40, 0x40, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42,
|
||||
0x43, 0x43, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x48, 0x48,
|
||||
0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4E,
|
||||
0x4E, 0x4E, 0x4F, 0x4F, 0x4F, 0x50, 0x50, 0x51, 0x51, 0x51, 0x52, 0x52, 0x52, 0x53, 0x53, 0x53,
|
||||
0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x58, 0x58, 0x58, 0x59, 0x59,
|
||||
0x59, 0x5A, 0x5A, 0x5A, 0x5B, 0x5B, 0x5B, 0x5C, 0x5C, 0x5C, 0x5D, 0x5D, 0x5E, 0x5E, 0x5E, 0x5F,
|
||||
0x5F, 0x5F, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x64, 0x64,
|
||||
0x65, 0x65, 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69, 0x6A,
|
||||
0x6A, 0x6A, 0x6B, 0x6B, 0x6C, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D, 0x6E, 0x6E, 0x6E, 0x6F, 0x6F, 0x6F,
|
||||
0x70, 0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75,
|
||||
0x75, 0x76, 0x76, 0x76, 0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79, 0x7A, 0x7A, 0x7A, 0x7B,
|
||||
0x7B, 0x7B, 0x7C, 0x7C, 0x7C, 0x7D, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7F, 0x7F, 0x80, 0x80, 0x80,
|
||||
0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x86,
|
||||
0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8A, 0x8A, 0x8A, 0x8B, 0x8B, 0x8B,
|
||||
0x8C, 0x8C, 0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8E, 0x8F, 0x8F, 0x8F, 0x90, 0x90, 0x90, 0x91, 0x91,
|
||||
0x91, 0x92, 0x92, 0x92, 0x93, 0x93,
|
||||
0xE9, 0xE9, 0xE9, 0xEA, 0xEA, 0xEA, 0xEB, 0xEB, 0xEB, 0xEC,
|
||||
0xEC, 0xEC, 0xED, 0xED, 0xED, 0xEE, 0xEE, 0xEE, 0xEF, 0xEF, 0xF0, 0xF0, 0xF0, 0xF1, 0xF1, 0xF1,
|
||||
0xF2, 0xF2, 0xF2, 0xF3, 0xF3, 0xF3, 0xF4, 0xF4, 0xF4, 0xF5, 0xF5, 0xF6, 0xF6, 0xF6, 0xF7, 0xF7,
|
||||
0xF7, 0xF8, 0xF8, 0xF8, 0xF9, 0xF9, 0xF9, 0xFA, 0xFA, 0xFA, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFD,
|
||||
0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF
|
||||
0x85, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8A, 0x8A,
|
||||
0x8A, 0x8B, 0x8B, 0x8B, 0x8C, 0x8C, 0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8E, 0x8F, 0x8F, 0x8F, 0x90,
|
||||
0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x93, 0x93,
|
||||
0xE9, 0xE9, 0xE9, 0xEA, 0xEA, 0xEA,
|
||||
0xEB, 0xEB, 0xEB, 0xEC, 0xEC, 0xEC, 0xED, 0xED, 0xED, 0xEE, 0xEE, 0xEE, 0xEF, 0xEF, 0xF0, 0xF0,
|
||||
0xF0, 0xF1, 0xF1, 0xF1, 0xF2, 0xF2, 0xF2, 0xF3, 0xF3, 0xF3, 0xF4, 0xF4, 0xF4, 0xF5, 0xF5, 0xF6,
|
||||
0xF6, 0xF6, 0xF7, 0xF7, 0xF7, 0xF8, 0xF8, 0xF8, 0xF9, 0xF9, 0xF9, 0xFA, 0xFA, 0xFA, 0xFB, 0xFB,
|
||||
0xFB, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
|
||||
0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06,
|
||||
0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0C,
|
||||
0x0C, 0x0C, 0x0D, 0x0D, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11,
|
||||
0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x17, 0x17,
|
||||
0x17, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C, 0x1C, 0x1C, 0x1D,
|
||||
0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x22,
|
||||
0x23, 0x23, 0x23, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x28,
|
||||
0x28, 0x29, 0x29, 0x29, 0x2A, 0x2A, 0x2A, 0x2B, 0x2B, 0x2B, 0x2C, 0x2C, 0x2C, 0x2D, 0x2D, 0x2D,
|
||||
0x2E, 0x2E, 0x2F, 0x2F, 0x2F, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x32, 0x32, 0x32, 0x33, 0x33,
|
||||
0x33, 0x34, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, 0x36, 0x37, 0x37, 0x37, 0x38, 0x38, 0x38, 0x39,
|
||||
0x39, 0x39, 0x3A, 0x3A, 0x3A, 0x3B, 0x3B, 0x3B, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D, 0x3E, 0x3E, 0x3E,
|
||||
0x3F, 0x3F, 0x3F, 0x40, 0x40, 0x40, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x43, 0x43, 0x44, 0x44,
|
||||
0x44, 0x45, 0x45, 0x45, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x48, 0x48, 0x48, 0x49, 0x49, 0x4A,
|
||||
0x4A, 0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4E, 0x4E, 0x4E, 0x4F, 0x4F,
|
||||
0x4F, 0x50, 0x50, 0x51, 0x51, 0x51, 0x52, 0x52, 0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x54, 0x55,
|
||||
0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x5A, 0x5A, 0x5A,
|
||||
0x5B, 0x5B, 0x5B, 0x5C, 0x5C, 0x5C, 0x5D, 0x5D, 0x5E, 0x5E, 0x5E, 0x5F, 0x5F, 0x5F, 0x60, 0x60,
|
||||
0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x64, 0x64, 0x65, 0x65, 0x65, 0x66,
|
||||
0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69, 0x6A, 0x6A, 0x6A, 0x6B, 0x6B,
|
||||
0x6C, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D, 0x6E, 0x6E, 0x6E, 0x6F, 0x6F, 0x6F, 0x70, 0x70, 0x70, 0x71,
|
||||
0x71, 0x72, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x76, 0x76, 0x76,
|
||||
0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79, 0x7A, 0x7A, 0x7A, 0x7B, 0x7B, 0x7B, 0x7C, 0x7C,
|
||||
0x7C, 0x7D, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7F, 0x7F, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82,
|
||||
0x82, 0x82, 0x83, 0x83, 0x83, 0x84, 0x84, 0x84
|
||||
};
|
||||
|
||||
|
||||
/*uint8 cycle2hc32[489] = {
|
||||
0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xed,
|
||||
0xed, 0xed, 0xee, 0xee, 0xee, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2,
|
||||
0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8, 0xf8,
|
||||
0xf8, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd,
|
||||
0xfe, 0xfe, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03,
|
||||
0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09,
|
||||
0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e,
|
||||
0x0f, 0x0f, 0x0f, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14,
|
||||
0x14, 0x14, 0x15, 0x15, 0x15, 0x16, 0x16, 0x17, 0x17, 0x17, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19,
|
||||
0x1a, 0x1a, 0x1a, 0x1b, 0x1b, 0x1b, 0x1c, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f,
|
||||
0x1f, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24, 0x24,
|
||||
0x25, 0x25, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x2a, 0x2a,
|
||||
0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30,
|
||||
0x30, 0x30, 0x31, 0x31, 0x31, 0x32, 0x32, 0x32, 0x33, 0x33, 0x33, 0x34, 0x34, 0x34, 0x35, 0x35,
|
||||
0x36, 0x36, 0x36, 0x37, 0x37, 0x37, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3b,
|
||||
0x3b, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f, 0x40, 0x40, 0x40,
|
||||
0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x43, 0x43, 0x43, 0x44, 0x44, 0x45, 0x45, 0x45, 0x46, 0x46,
|
||||
0x46, 0x47, 0x47, 0x47, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b,
|
||||
0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4e, 0x4e, 0x4e, 0x4f, 0x4f, 0x4f, 0x50, 0x50, 0x50, 0x51, 0x51,
|
||||
0x51, 0x52, 0x52, 0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57,
|
||||
0x57, 0x57, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c,
|
||||
0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, 0x62,
|
||||
0x62, 0x62, 0x63, 0x63, 0x64, 0x64, 0x64, 0x65, 0x65, 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67,
|
||||
0x68, 0x68, 0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d,
|
||||
0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x72, 0x72, 0x72,
|
||||
0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x76, 0x76, 0x76, 0x77, 0x77, 0x77, 0x78, 0x78,
|
||||
0x78, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7e,
|
||||
0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x83, 0x83, 0x83,
|
||||
0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88, 0x89,
|
||||
0x89, 0x89, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e,
|
||||
0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92
|
||||
};
|
||||
|
||||
*/
|
||||
/*
|
||||
uint8 cycle2hc32[489] = {
|
||||
0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed, 0xee,
|
||||
0xee, 0xee, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3,
|
||||
0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf9, 0xf9,
|
||||
0xf9, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe,
|
||||
0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04,
|
||||
0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a,
|
||||
0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f,
|
||||
0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0x15,
|
||||
0x15, 0x15, 0x16, 0x16, 0x16, 0x17, 0x17, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x1a, 0x1a, 0x1a,
|
||||
0x1b, 0x1b, 0x1b, 0x1c, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x20, 0x20,
|
||||
0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25,
|
||||
0x26, 0x26, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b,
|
||||
0x2b, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30, 0x30, 0x31,
|
||||
0x31, 0x31, 0x32, 0x32, 0x32, 0x33, 0x33, 0x33, 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x36, 0x36,
|
||||
0x37, 0x37, 0x37, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
|
||||
0x3c, 0x3c, 0x3d, 0x3d, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f, 0x40, 0x40, 0x40, 0x41, 0x41, 0x41,
|
||||
0x42, 0x42, 0x42, 0x43, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45, 0x45, 0x46, 0x46, 0x46, 0x47, 0x47,
|
||||
0x47, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c, 0x4c,
|
||||
0x4d, 0x4d, 0x4e, 0x4e, 0x4e, 0x4f, 0x4f, 0x4f, 0x50, 0x50, 0x50, 0x51, 0x51, 0x51, 0x52, 0x52,
|
||||
0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x57, 0x58,
|
||||
0x58, 0x58, 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, 0x5d, 0x5d, 0x5d,
|
||||
0x5e, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63,
|
||||
0x63, 0x63, 0x64, 0x64, 0x65, 0x65, 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68,
|
||||
0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e,
|
||||
0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x72, 0x72, 0x72, 0x73, 0x73, 0x73,
|
||||
0x74, 0x74, 0x75, 0x75, 0x75, 0x76, 0x76, 0x76, 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
|
||||
0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f,
|
||||
0x7f, 0x7f, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x83, 0x83, 0x84, 0x84, 0x84,
|
||||
0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a,
|
||||
0x8a, 0x8a, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f,
|
||||
0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92, 0x93
|
||||
};*/
|
||||
|
||||
|
||||
|
||||
uint8 cycle2hc40[488] = {
|
||||
0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06,
|
||||
0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0D,
|
||||
0x0D, 0x0E, 0x0E, 0x0F, 0x0F, 0x10, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14,
|
||||
0x14, 0x15, 0x15, 0x16, 0x16, 0x16, 0x17, 0x17, 0x18, 0x18, 0x19, 0x19, 0x19, 0x1A, 0x1A, 0x1B,
|
||||
0x1B, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22,
|
||||
0x22, 0x23, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29,
|
||||
0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30,
|
||||
0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, 0x36,
|
||||
0x37, 0x37, 0x38, 0x38, 0x39, 0x39, 0x39, 0x3A, 0x3A, 0x3B, 0x3B, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D,
|
||||
0x3E, 0x3E, 0x3F, 0x3F, 0x40, 0x40, 0x40, 0x41, 0x41, 0x42, 0x42, 0x43, 0x43, 0x43, 0x44, 0x44,
|
||||
0x45, 0x45, 0x46, 0x46, 0x46, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4A, 0x4B, 0x4B,
|
||||
0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4E, 0x4E, 0x4F, 0x4F, 0x50, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52,
|
||||
0x53, 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x58, 0x58, 0x59, 0x59,
|
||||
0x5A, 0x5A, 0x5A, 0x5B, 0x5B, 0x5C, 0x5C, 0x5D, 0x5D, 0x5D, 0x5E, 0x5E, 0x5F, 0x5F, 0x60, 0x60,
|
||||
0x60, 0x61, 0x61, 0x62, 0x62, 0x63, 0x63, 0x63, 0x64, 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67,
|
||||
0x67, 0x68, 0x68, 0x69, 0x69, 0x6A, 0x6A, 0x6A, 0x6B, 0x6B, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D, 0x6E,
|
||||
0x6E, 0x6F, 0x6F, 0x70, 0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x75,
|
||||
0x75, 0x76, 0x76, 0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x7A, 0x7A, 0x7A, 0x7B, 0x7B, 0x7C,
|
||||
0x7C, 0x7D, 0x7D, 0x7D, 0x7E, 0x7E, 0x7F, 0x7F, 0x80, 0x80, 0x80, 0x81, 0x81, 0x82, 0x82, 0x83,
|
||||
0x83, 0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x89, 0x89, 0x8A,
|
||||
0x8A, 0x8A, 0x8B, 0x8B, 0x8C, 0x8C, 0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8F, 0x8F, 0x90, 0x90, 0x90,
|
||||
0x91, 0x91, 0x92, 0x92, 0x93, 0x93, 0x94, 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x97, 0x97, 0x97,
|
||||
0x98, 0x98, 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9B, 0x9B, 0x9C, 0x9C, 0x9D, 0x9D, 0x9D, 0x9E, 0x9E,
|
||||
0x9F, 0x9F, 0xA0, 0xA0, 0xA1, 0xA1, 0xA1, 0xA2, 0xA2, 0xA3, 0xA3, 0xA4, 0xA4, 0xA4, 0xA5, 0xA5,
|
||||
0xA6, 0xA6, 0xA7, 0xA7, 0xA7, 0xA8, 0xA8, 0xA9, 0xA9, 0xAA, 0xAA, 0xAA, 0xAB, 0xAB, 0xAC, 0xAC,
|
||||
0xAD, 0xAD, 0xAD, 0xAE, 0xAE, 0xAF, 0xAF, 0xB0, 0xB0, 0xB1, 0xB1, 0xB1, 0xB2, 0xB2, 0xB3, 0xB3,
|
||||
0xB4, 0xB4, 0xB4, 0xB5, 0xB5, 0xB6, 0xB6,
|
||||
0xE4, 0xE4, 0xE4, 0xE5, 0xE5, 0xE6, 0xE6, 0xE7, 0xE7,
|
||||
0xE7, 0xE8, 0xE8, 0xE9, 0xE9, 0xEA, 0xEA, 0xEB, 0xEB, 0xEB, 0xEC, 0xEC, 0xED, 0xED, 0xEE, 0xEE,
|
||||
0xEE, 0xEF, 0xEF, 0xF0, 0xF0, 0xF1, 0xF1, 0xF1, 0xF2, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4, 0xF4, 0xF5,
|
||||
0xF5, 0xF6, 0xF6, 0xF7, 0xF7, 0xF7, 0xF8, 0xF8, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFB, 0xFC,
|
||||
0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF
|
||||
0xA5, 0xA5, 0xA6, 0xA6, 0xA7, 0xA7, 0xA7, 0xA8, 0xA8, 0xA9, 0xA9, 0xAA, 0xAA, 0xAA, 0xAB, 0xAB,
|
||||
0xAC, 0xAC, 0xAD, 0xAD, 0xAD, 0xAE, 0xAE, 0xAF, 0xAF, 0xB0, 0xB0, 0xB1, 0xB1, 0xB1, 0xB2, 0xB2,
|
||||
0xB3, 0xB3, 0xB4, 0xB4, 0xB4, 0xB5, 0xB5, 0xB6, 0xB6,
|
||||
0xE4, 0xE4, 0xE4, 0xE5, 0xE5, 0xE6, 0xE6,
|
||||
0xE7, 0xE7, 0xE7, 0xE8, 0xE8, 0xE9, 0xE9, 0xEA, 0xEA, 0xEB, 0xEB, 0xEB, 0xEC, 0xEC, 0xED, 0xED,
|
||||
0xEE, 0xEE, 0xEE, 0xEF, 0xEF, 0xF0, 0xF0, 0xF1, 0xF1, 0xF1, 0xF2, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4,
|
||||
0xF4, 0xF5, 0xF5, 0xF6, 0xF6, 0xF7, 0xF7, 0xF7, 0xF8, 0xF8, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB,
|
||||
0xFB, 0xFC, 0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
|
||||
0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09,
|
||||
0x09, 0x09, 0x0A, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0E, 0x0E, 0x0F, 0x0F, 0x10,
|
||||
0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15, 0x16, 0x16, 0x16,
|
||||
0x17, 0x17, 0x18, 0x18, 0x19, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D,
|
||||
0x1E, 0x1E, 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24,
|
||||
0x25, 0x25, 0x26, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
|
||||
0x2C, 0x2C, 0x2D, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32,
|
||||
0x33, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, 0x36, 0x37, 0x37, 0x38, 0x38, 0x39, 0x39,
|
||||
0x39, 0x3A, 0x3A, 0x3B, 0x3B, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D, 0x3E, 0x3E, 0x3F, 0x3F, 0x40, 0x40,
|
||||
0x40, 0x41, 0x41, 0x42, 0x42, 0x43, 0x43, 0x43, 0x44, 0x44, 0x45, 0x45, 0x46, 0x46, 0x46, 0x47,
|
||||
0x47, 0x48, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4A, 0x4B, 0x4B, 0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4E,
|
||||
0x4E, 0x4F, 0x4F, 0x50, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x55,
|
||||
0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x58, 0x58, 0x59, 0x59, 0x5A, 0x5A, 0x5A, 0x5B, 0x5B, 0x5C,
|
||||
0x5C, 0x5D, 0x5D, 0x5D, 0x5E, 0x5E, 0x5F, 0x5F, 0x60, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x63,
|
||||
0x63, 0x63, 0x64, 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69, 0x6A,
|
||||
0x6A, 0x6A, 0x6B, 0x6B, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D, 0x6E, 0x6E, 0x6F, 0x6F, 0x70, 0x70, 0x70,
|
||||
0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77, 0x77,
|
||||
0x78, 0x78, 0x79, 0x79, 0x7A, 0x7A, 0x7A, 0x7B, 0x7B, 0x7C, 0x7C, 0x7D, 0x7D, 0x7D, 0x7E, 0x7E,
|
||||
0x7F, 0x7F, 0x80, 0x80, 0x80, 0x81, 0x81, 0x82, 0x82, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85, 0x85,
|
||||
0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x89, 0x89, 0x8A, 0x8A, 0x8A, 0x8B, 0x8B, 0x8C, 0x8C,
|
||||
0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8F, 0x8F, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92, 0x93, 0x93,
|
||||
0x94, 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x97, 0x97, 0x97, 0x98, 0x98, 0x99, 0x99, 0x9A, 0x9A,
|
||||
0x9A, 0x9B, 0x9B, 0x9C, 0x9C, 0x9D, 0x9D, 0x9D, 0x9E, 0x9E, 0x9F, 0x9F, 0xA0, 0xA0, 0xA1, 0xA1,
|
||||
0xA1, 0xA2, 0xA2, 0xA3, 0xA3, 0xA4, 0xA4, 0xA4,
|
||||
};
|
||||
|
||||
/*
|
||||
uint8 cycle2hc40[489] = {
|
||||
0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe9, 0xe9, 0xea, 0xea,
|
||||
0xea, 0xeb, 0xeb, 0xec, 0xec, 0xed, 0xed, 0xed, 0xee, 0xee, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf1,
|
||||
0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8,
|
||||
0xf8, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfe, 0xfe, 0xff,
|
||||
0xff, 0xff, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x05,
|
||||
0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c,
|
||||
0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x12, 0x13, 0x13,
|
||||
0x14, 0x14, 0x15, 0x15, 0x15, 0x16, 0x16, 0x17, 0x17, 0x18, 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a,
|
||||
0x1b, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x21, 0x21,
|
||||
0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x27, 0x28,
|
||||
0x28, 0x29, 0x29, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2f,
|
||||
0x2f, 0x30, 0x30, 0x31, 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x34, 0x34, 0x35, 0x35, 0x36,
|
||||
0x36, 0x37, 0x37, 0x37, 0x38, 0x38, 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3c, 0x3d,
|
||||
0x3d, 0x3d, 0x3e, 0x3e, 0x3f, 0x3f, 0x40, 0x40, 0x40, 0x41, 0x41, 0x42, 0x42, 0x43, 0x43, 0x43,
|
||||
0x44, 0x44, 0x45, 0x45, 0x46, 0x46, 0x46, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49, 0x49, 0x4a, 0x4a,
|
||||
0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4e, 0x4e, 0x4f, 0x4f, 0x50, 0x50, 0x50, 0x51, 0x51,
|
||||
0x52, 0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x58, 0x58,
|
||||
0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f,
|
||||
0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, 0x64, 0x64, 0x65, 0x65, 0x65, 0x66,
|
||||
0x66, 0x67, 0x67, 0x68, 0x68, 0x68, 0x69, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, 0x6c, 0x6c, 0x6d,
|
||||
0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x72, 0x73, 0x73, 0x74,
|
||||
0x74, 0x75, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79, 0x7a, 0x7a, 0x7b,
|
||||
0x7b, 0x7b, 0x7c, 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x81,
|
||||
0x82, 0x82, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88,
|
||||
0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f,
|
||||
0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92, 0x93, 0x93, 0x94, 0x94, 0x94, 0x95, 0x95, 0x96, 0x96,
|
||||
0x97, 0x97, 0x97, 0x98, 0x98, 0x99, 0x99, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d,
|
||||
0x9d, 0x9e, 0x9e, 0x9f, 0x9f, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4,
|
||||
0xa4, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, 0xa7, 0xa7, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xab,
|
||||
0xab, 0xac, 0xac, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2,
|
||||
0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6
|
||||
};
|
||||
*/
|
||||
/*
|
||||
uint8 cycle2hc40[489] = {
|
||||
0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xea,
|
||||
0xea, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xed, 0xed, 0xee, 0xee, 0xee, 0xef, 0xef, 0xf0, 0xf0, 0xf1,
|
||||
0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
|
||||
0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfd, 0xfd, 0xfe, 0xfe,
|
||||
0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x05,
|
||||
0x05, 0x06, 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b,
|
||||
0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12,
|
||||
0x13, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15, 0x15, 0x16, 0x16, 0x17, 0x17, 0x18, 0x18, 0x18, 0x19,
|
||||
0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f, 0x20,
|
||||
0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x25, 0x26, 0x26,
|
||||
0x27, 0x27, 0x28, 0x28, 0x28, 0x29, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d,
|
||||
0x2d, 0x2e, 0x2e, 0x2f, 0x2f, 0x30, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x32, 0x33, 0x33, 0x34,
|
||||
0x34, 0x35, 0x35, 0x35, 0x36, 0x36, 0x37, 0x37, 0x38, 0x38, 0x38, 0x39, 0x39, 0x3a, 0x3a, 0x3a,
|
||||
0x3b, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f, 0x40, 0x40, 0x41, 0x41,
|
||||
0x42, 0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x45, 0x45, 0x45, 0x46, 0x46, 0x47, 0x47, 0x47, 0x48,
|
||||
0x48, 0x49, 0x49, 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4e, 0x4e, 0x4f,
|
||||
0x4f, 0x4f, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x55,
|
||||
0x56, 0x56, 0x57, 0x57, 0x57, 0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c,
|
||||
0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63,
|
||||
0x63, 0x64, 0x64, 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69, 0x6a,
|
||||
0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
|
||||
0x71, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77,
|
||||
0x77, 0x78, 0x78, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7e,
|
||||
0x7e, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x83, 0x83, 0x84, 0x84, 0x84,
|
||||
0x85, 0x85, 0x86, 0x86, 0x86, 0x87, 0x87, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8b, 0x8b,
|
||||
0x8c, 0x8c, 0x8c, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x90, 0x90, 0x91, 0x91, 0x91, 0x92,
|
||||
0x92, 0x93, 0x93, 0x94, 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x96, 0x97, 0x97, 0x98, 0x98, 0x99,
|
||||
0x99, 0x99, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f,
|
||||
0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa6, 0xa6,
|
||||
0xa6, 0xa7, 0xa7, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xab, 0xab, 0xab, 0xac, 0xac, 0xad,
|
||||
0xad, 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* H counter values for a 256-pixel wide display (342 pixel max.) */
|
||||
/*uint8 hc_256[171] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93,
|
||||
0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};*/
|
||||
|
||||
/* H counter values for a 320-pixel wide display (422 pixels max.) */
|
||||
/*uint8 hc_320[211] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
|
||||
0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};*/
|
||||
|
||||
/*uint8 *hc_table[2] = {
|
||||
hc_256,
|
||||
hc_320,
|
||||
};*/
|
||||
uint8 *vctab;
|
||||
uint8 *hctab;
|
||||
|
||||
#endif /* _HVC_H_ */
|
||||
|
||||
|
622
source/input.c
622
source/input.c
@ -1,220 +1,136 @@
|
||||
/*
|
||||
Copyright (C) 1999, 2000, 2001, 2002, 2003 Charles MacDonald
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
02/2007: fixed 6BUTTONS gamepad emulation (Eke-Eke)
|
||||
06/2007: Added TEAMPLAYER/4WAYPLAY/MENACER emulation (Eke-Eke)
|
||||
*/
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* Peripheral Input Support
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
t_input input;
|
||||
uint8 current_pad = 0;
|
||||
uint8 j_cart = 0;
|
||||
|
||||
void gamepad_reset(uint8 num);
|
||||
void gamepad_update(uint8 num);
|
||||
void gamepad_raz(uint8 num);
|
||||
void lightgun_update(void);
|
||||
void lightgun_reset(void);
|
||||
void teamplayer_reset(uint8 port);
|
||||
|
||||
/*****************************************************************************
|
||||
* Generic INPUTS Control
|
||||
*
|
||||
*****************************************************************************/
|
||||
void input_reset (int padtype)
|
||||
{
|
||||
uint8 i;
|
||||
|
||||
input.max = 0;
|
||||
for (i=0; i<MAX_DEVICES; i++)
|
||||
{
|
||||
input.dev[i] = NO_DEVICE;
|
||||
input.pad[i] = 0;
|
||||
}
|
||||
|
||||
switch (input.system[0])
|
||||
{
|
||||
case SYSTEM_GAMEPAD:
|
||||
if (input.max++ < MAX_INPUTS) input.dev[0] = padtype;
|
||||
gamepad_reset(0);
|
||||
break;
|
||||
|
||||
case SYSTEM_WAYPLAY:
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if (input.max++ < MAX_INPUTS) input.dev[i] = padtype;
|
||||
gamepad_reset(i);
|
||||
}
|
||||
current_pad = 0;
|
||||
break;
|
||||
|
||||
case SYSTEM_TEAMPLAYER:
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if (input.max++ < MAX_INPUTS) input.dev[i] = padtype;
|
||||
}
|
||||
teamplayer_reset(0);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (input.system[1])
|
||||
{
|
||||
case SYSTEM_GAMEPAD:
|
||||
if (input.max++ < MAX_INPUTS) input.dev[4] = padtype;
|
||||
gamepad_reset(4);
|
||||
break;
|
||||
|
||||
case SYSTEM_TEAMPLAYER:
|
||||
for (i=4; i<8; i++)
|
||||
{
|
||||
if (input.max++ < MAX_INPUTS) input.dev[i] = padtype;
|
||||
}
|
||||
teamplayer_reset(1);
|
||||
break;
|
||||
|
||||
case SYSTEM_MENACER:
|
||||
if (input.max++ < MAX_INPUTS) input.dev[4] = DEVICE_LIGHTGUN;
|
||||
lightgun_reset();
|
||||
break;
|
||||
}
|
||||
|
||||
if (input.max > MAX_INPUTS) input.max = MAX_INPUTS;
|
||||
|
||||
/* J-CART: add two gamepad inputs */
|
||||
if (j_cart)
|
||||
{
|
||||
input.dev[5] = padtype;
|
||||
input.dev[6] = padtype;
|
||||
gamepad_reset(5);
|
||||
gamepad_reset(6);
|
||||
input.max+=2;
|
||||
}
|
||||
}
|
||||
|
||||
void input_update()
|
||||
{
|
||||
uint8 i;
|
||||
switch (input.system[0])
|
||||
{
|
||||
case SYSTEM_GAMEPAD:
|
||||
if (input.dev[0] == DEVICE_6BUTTON) gamepad_update(0);
|
||||
break;
|
||||
|
||||
case SYSTEM_WAYPLAY:
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if (input.dev[i] == DEVICE_6BUTTON) gamepad_update(i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (input.system[1])
|
||||
{
|
||||
case SYSTEM_GAMEPAD:
|
||||
if (input.dev[4] == DEVICE_6BUTTON) gamepad_update(4);
|
||||
break;
|
||||
|
||||
case SYSTEM_MENACER:
|
||||
lightgun_update();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void input_raz()
|
||||
{
|
||||
uint8 i;
|
||||
switch (input.system[0])
|
||||
{
|
||||
case SYSTEM_GAMEPAD:
|
||||
if (input.dev[0] == DEVICE_6BUTTON) gamepad_raz(0);
|
||||
break;
|
||||
|
||||
case SYSTEM_WAYPLAY:
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if (input.dev[i] == DEVICE_6BUTTON) gamepad_raz(i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (input.system[1])
|
||||
{
|
||||
case SYSTEM_GAMEPAD:
|
||||
if (input.dev[4] == DEVICE_6BUTTON) gamepad_raz(4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* LIGHTGUN specific functions
|
||||
*
|
||||
*****************************************************************************/
|
||||
struct gun
|
||||
{
|
||||
int16 x;
|
||||
int16 y;
|
||||
} lightgun;
|
||||
/* H counter values for a 256-pixel wide display (342 pixel max.) */
|
||||
uint8 hc_256[171] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93,
|
||||
0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
void lightgun_reset(void)
|
||||
/* H counter values for a 320-pixel wide display (442 pixels max.) */
|
||||
uint8 hc_320[210] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
|
||||
0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
static inline void lightgun_reset(int num)
|
||||
{
|
||||
lightgun.x = bitmap.viewport.w >> 1;
|
||||
lightgun.y = bitmap.viewport.h >> 1;
|
||||
input.analog[num][0] = bitmap.viewport.w >> 1;
|
||||
input.analog[num][1] = bitmap.viewport.h >> 1;
|
||||
}
|
||||
|
||||
void lightgun_update(void)
|
||||
static inline void lightgun_update(int num)
|
||||
{
|
||||
if ((v_counter == lightgun.y))
|
||||
if ((input.analog[num][1] == v_counter + input.y_offset))
|
||||
{
|
||||
if (reg[0x0B] & 8) m68k_set_irq(2);
|
||||
if (reg[0x00] & 2)
|
||||
/* HL enabled ? */
|
||||
if (io_reg[5] & 0x80)
|
||||
{
|
||||
hc_latch = lightgun.x + 166;
|
||||
if (hc_latch >= bitmap.viewport.w + 52) hc_latch -= (bitmap.viewport.w + 52 + 48);
|
||||
hc_latch >>= 1;
|
||||
/* External Interrupt ? */
|
||||
if (reg[11] & 0x08) m68k_set_irq(2);
|
||||
|
||||
/* HVC Latch:
|
||||
1) some games does not set HVC latch but instead use bigger X offset
|
||||
2) for games using H40 mode, the gun routine scales up the Hcounter value,
|
||||
H-Counter range is approx. 292 pixel clocks
|
||||
*/
|
||||
if (reg[12] & 1)
|
||||
hc_latch = hc_320[((input.analog[num][0] * 290) / (2 * 320) + input.x_offset) % 210];
|
||||
else
|
||||
hc_latch = hc_256[(input.analog[num][0] / 2 + input.x_offset)%171];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void lightgun_set ()
|
||||
/* Sega Menacer specific */
|
||||
unsigned int menacer_read()
|
||||
{
|
||||
if ((input.pad[4] & INPUT_RIGHT)) lightgun.x ++;
|
||||
if ((input.pad[4] & INPUT_LEFT)) lightgun.x --;
|
||||
if ((input.pad[4] & INPUT_UP)) lightgun.y --;
|
||||
if ((input.pad[4] & INPUT_DOWN)) lightgun.y ++;
|
||||
|
||||
if (lightgun.x < 0) lightgun.x = 0;
|
||||
else if (lightgun.x > bitmap.viewport.w-34) lightgun.x = bitmap.viewport.w-34;
|
||||
|
||||
if (lightgun.y < 0) lightgun.y = 0;
|
||||
else if (lightgun.y > bitmap.viewport.h-8) lightgun.y = bitmap.viewport.h-8;
|
||||
}
|
||||
|
||||
uint8 lightgun_read (void)
|
||||
{
|
||||
uint8 retval = 0x00;
|
||||
int retval = 0x70;
|
||||
if ((input.pad[4] & INPUT_B)) retval |= 0x01;
|
||||
if ((input.pad[4] & INPUT_A)) retval |= 0x02;
|
||||
if ((input.pad[4] & INPUT_C)) retval |= 0x04;
|
||||
if ((input.pad[4] & INPUT_START)) retval |= 0x08;
|
||||
return (retval & 0x7F);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Konami Justifier specific */
|
||||
unsigned int justifier_read()
|
||||
{
|
||||
/* TL & TR pins should always return 1 (write only) */
|
||||
/* LEFT & RIGHT pins should always return 0 (needed during gun detection) */
|
||||
int retval = 0x73;
|
||||
|
||||
switch (io_reg[2])
|
||||
{
|
||||
case 0x40: /* gun detection */
|
||||
return 0x30;
|
||||
|
||||
case 0x00: /* gun #1 enabled */
|
||||
if ((input.pad[4] & INPUT_A)) retval &= ~0x01;
|
||||
if ((input.pad[4] & INPUT_START)) retval &= ~0x02;
|
||||
return retval;
|
||||
|
||||
case 0x20: /* gun #2 enabled */
|
||||
if ((input.pad[5] & INPUT_A)) retval &= ~0x01;
|
||||
if ((input.pad[5] & INPUT_START)) retval &= ~0x02;
|
||||
return retval;
|
||||
|
||||
default: /* guns disabled */
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* GAMEPAD specific functions (2PLAYERS/4WAYPLAY)
|
||||
@ -227,29 +143,27 @@ struct pad
|
||||
uint8 Delay;
|
||||
} gamepad[MAX_DEVICES];
|
||||
|
||||
void gamepad_reset(uint8 i)
|
||||
{
|
||||
gamepad[i].State = 0x40;
|
||||
if (input.dev[i] == DEVICE_6BUTTON) gamepad_raz(i);
|
||||
}
|
||||
|
||||
void gamepad_raz(uint8 i)
|
||||
static inline void gamepad_raz(unsigned int i)
|
||||
{
|
||||
gamepad[i].Counter = 0;
|
||||
gamepad[i].Delay = 0;
|
||||
}
|
||||
|
||||
void gamepad_update(uint8 i)
|
||||
static inline void gamepad_reset(unsigned int i)
|
||||
{
|
||||
gamepad[i].State = 0x40;
|
||||
if (input.dev[i] == DEVICE_6BUTTON) gamepad_raz(i);
|
||||
}
|
||||
|
||||
static inline void gamepad_update(unsigned int i)
|
||||
{
|
||||
if (gamepad[i].Delay++ > 25) gamepad_raz(i);
|
||||
}
|
||||
|
||||
uint8 gamepad_read (uint8 i)
|
||||
static inline unsigned int gamepad_read(unsigned int i)
|
||||
{
|
||||
int control;
|
||||
unsigned char retval = 0xFF;
|
||||
|
||||
if (input.dev[i] == NO_DEVICE) return 0x7F;
|
||||
int retval = 0x7F;
|
||||
|
||||
control = (gamepad[i].State & 0x40) >> 6; /* current TH state */
|
||||
|
||||
@ -327,11 +241,11 @@ uint8 gamepad_read (uint8 i)
|
||||
break;
|
||||
}
|
||||
|
||||
/* bit7 is latched*/
|
||||
return (retval&0x7f);
|
||||
/* bit7 is latched */
|
||||
return retval;
|
||||
}
|
||||
|
||||
void gamepad_write (uint8 i, uint8 data)
|
||||
static inline void gamepad_write(unsigned int i, unsigned int data)
|
||||
{
|
||||
if (input.dev[i] == DEVICE_6BUTTON)
|
||||
{
|
||||
@ -348,7 +262,7 @@ void gamepad_write (uint8 i, uint8 data)
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* TEAMPLAYER specific functions
|
||||
* TEAMPLAYER adapter
|
||||
*
|
||||
*****************************************************************************/
|
||||
struct teamplayer
|
||||
@ -358,11 +272,11 @@ struct teamplayer
|
||||
uint8 Table[12];
|
||||
} teamplayer[2];
|
||||
|
||||
void teamplayer_reset(uint8 port)
|
||||
static inline void teamplayer_reset(unsigned int port)
|
||||
{
|
||||
uint8 i;
|
||||
uint8 index = 0;
|
||||
uint8 pad_input = 0;
|
||||
int i;
|
||||
int index = 0;
|
||||
int pad_input = 0;
|
||||
|
||||
teamplayer[port].State = 0x60; /* TH = 1, TR = 1 */
|
||||
teamplayer[port].Counter = 0;
|
||||
@ -388,7 +302,6 @@ void teamplayer_reset(uint8 port)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* SEGA teamplayer returns successively:
|
||||
- PAD1 inputs
|
||||
- PAD2 inputs
|
||||
@ -400,11 +313,11 @@ void teamplayer_reset(uint8 port)
|
||||
2/ START,A,C,B buttons
|
||||
3/ MODE, X,Y,Z buttons (6Button only !)
|
||||
*/
|
||||
uint8 teamplayer_read(uint8 port, uint8 index)
|
||||
static inline unsigned int teamplayer_read_device(unsigned int port, unsigned int index)
|
||||
{
|
||||
uint8 retval = 0x7F;
|
||||
uint8 pad_input = teamplayer[port].Table[index] & 0x03;
|
||||
uint8 pad_num = (4 * port) + ((teamplayer[port].Table[index] >> 2) & 0x03);
|
||||
int retval = 0x7F;
|
||||
int pad_input = teamplayer[port].Table[index] & 0x03;
|
||||
int pad_num = (4 * port) + ((teamplayer[port].Table[index] >> 2) & 0x03);
|
||||
|
||||
switch (pad_input)
|
||||
{
|
||||
@ -436,42 +349,11 @@ uint8 teamplayer_read(uint8 port, uint8 index)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* MULTITAP generic functions (TEAMPLAYER/4WAYPLAY)
|
||||
*
|
||||
*****************************************************************************/
|
||||
void multitap_write (uint8 port, uint8 data)
|
||||
static inline unsigned int teamplayer_read(unsigned int port)
|
||||
{
|
||||
uint8 old_state;
|
||||
switch (input.system[port])
|
||||
{
|
||||
case SYSTEM_WAYPLAY:
|
||||
if (!port) gamepad_write(current_pad, data);
|
||||
else current_pad = (data >> 4) & 0x07;
|
||||
break;
|
||||
int retval = 0x7F;
|
||||
int padnum;
|
||||
|
||||
case SYSTEM_TEAMPLAYER:
|
||||
old_state = teamplayer[port].State;
|
||||
teamplayer[port].State = (data & io_reg[port+4]) | (teamplayer[port].State & ~io_reg[port+4]);
|
||||
if (old_state != teamplayer[port].State) teamplayer[port].Counter ++;
|
||||
if ((data&0x60) == 0x60) teamplayer[port].Counter = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 multitap_read (uint8 port)
|
||||
{
|
||||
uint8 retval = 0x7F;
|
||||
uint8 padnum;
|
||||
|
||||
switch (input.system[port])
|
||||
{
|
||||
case SYSTEM_WAYPLAY:
|
||||
if (port == 1) return 0x7F;
|
||||
if (current_pad >= 4) return 0x70; /* multitap detection (TH2 = 1) */
|
||||
return gamepad_read(current_pad); /* 0x0C = Pad1, 0x1C = Pad2, ... */
|
||||
|
||||
case SYSTEM_TEAMPLAYER:
|
||||
switch (teamplayer[port].Counter) /* acquisition sequence steps */
|
||||
{
|
||||
case 0: /* initial state: TH = 1, TR = 1 */
|
||||
@ -496,14 +378,250 @@ uint8 multitap_read (uint8 port)
|
||||
break;
|
||||
|
||||
default: /* gamepads inputs acquisition */
|
||||
retval = teamplayer_read(port, teamplayer[port].Counter - 8);
|
||||
retval = teamplayer_read_device(port, teamplayer[port].Counter - 8);
|
||||
break;
|
||||
}
|
||||
|
||||
/* TL must match TR state */
|
||||
retval &= ~0x10;
|
||||
if (teamplayer[port].State & 0x20) retval |= 0x10;
|
||||
return retval;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static inline void teamplayer_write(unsigned int port, unsigned int data)
|
||||
{
|
||||
int old_state = teamplayer[port].State;
|
||||
teamplayer[port].State = (data & io_reg[port+4]) | (teamplayer[port].State & ~io_reg[port+4]);
|
||||
if (old_state != teamplayer[port].State) teamplayer[port].Counter ++;
|
||||
if ((data&0x60) == 0x60) teamplayer[port].Counter = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* 4WAYPLAY adapter
|
||||
*
|
||||
*****************************************************************************/
|
||||
static inline void wayplay_write(unsigned int port, unsigned int data)
|
||||
{
|
||||
if (port == 0) gamepad_write(input.current, data);
|
||||
else input.current = (data >> 4) & 0x07;
|
||||
}
|
||||
|
||||
static inline unsigned int wayplay_read(unsigned int port)
|
||||
{
|
||||
if (port == 1) return 0x7F;
|
||||
if (input.current >= 4) return 0x70; /* multitap detection (TH2 = 1) */
|
||||
return gamepad_read(input.current); /* 0x0C = Pad1, 0x1C = Pad2, ... */
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* I/O wrappers
|
||||
*
|
||||
*****************************************************************************/
|
||||
unsigned int gamepad_1_read (void)
|
||||
{
|
||||
return gamepad_read(0);
|
||||
}
|
||||
|
||||
unsigned int gamepad_2_read (void)
|
||||
{
|
||||
return gamepad_read(4);
|
||||
}
|
||||
|
||||
void gamepad_1_write (unsigned int data)
|
||||
{
|
||||
gamepad_write(0, data);
|
||||
}
|
||||
|
||||
void gamepad_2_write (unsigned int data)
|
||||
{
|
||||
gamepad_write(4, data);
|
||||
}
|
||||
|
||||
unsigned int wayplay_1_read (void)
|
||||
{
|
||||
return wayplay_read(0);
|
||||
}
|
||||
|
||||
unsigned int wayplay_2_read (void)
|
||||
{
|
||||
return wayplay_read(1);
|
||||
}
|
||||
|
||||
void wayplay_1_write (unsigned int data)
|
||||
{
|
||||
wayplay_write(0, data);
|
||||
}
|
||||
|
||||
void wayplay_2_write (unsigned int data)
|
||||
{
|
||||
wayplay_write(1, data);
|
||||
}
|
||||
|
||||
unsigned int teamplayer_1_read (void)
|
||||
{
|
||||
return teamplayer_read(0);
|
||||
}
|
||||
|
||||
unsigned int teamplayer_2_read (void)
|
||||
{
|
||||
return teamplayer_read(1);
|
||||
}
|
||||
|
||||
void teamplayer_1_write (unsigned int data)
|
||||
{
|
||||
teamplayer_write(0, data);
|
||||
}
|
||||
|
||||
void teamplayer_2_write (unsigned int data)
|
||||
{
|
||||
teamplayer_write(1, data);
|
||||
}
|
||||
|
||||
unsigned int jcart_read(void)
|
||||
{
|
||||
return (gamepad_read(5) | (gamepad_read(6) << 8));
|
||||
}
|
||||
|
||||
void jcart_write(unsigned int data)
|
||||
{
|
||||
gamepad_write(5, (data&1) << 6);
|
||||
gamepad_write(6, (data&1) << 6);
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Generic INPUTS Control
|
||||
*
|
||||
*****************************************************************************/
|
||||
void input_reset ()
|
||||
{
|
||||
int i,j;
|
||||
|
||||
input.max = 0;
|
||||
input.current = 0;
|
||||
|
||||
for (i=0; i<MAX_DEVICES; i++)
|
||||
{
|
||||
input.dev[i] = NO_DEVICE;
|
||||
input.pad[i] = 0;
|
||||
}
|
||||
|
||||
for (i=0; i<2; i++)
|
||||
{
|
||||
switch (input.system[i])
|
||||
{
|
||||
case SYSTEM_GAMEPAD:
|
||||
if (input.max == MAX_INPUTS) return;
|
||||
input.dev[i*4] = input.padtype[input.max];
|
||||
input.max ++;
|
||||
gamepad_reset(i*4);
|
||||
break;
|
||||
|
||||
case SYSTEM_WAYPLAY:
|
||||
for (j=i*4; j< i*4+4; j++)
|
||||
{
|
||||
if (input.max == MAX_INPUTS) return;
|
||||
input.dev[j] = input.padtype[input.max];
|
||||
input.max ++;
|
||||
gamepad_reset(j);
|
||||
}
|
||||
break;
|
||||
|
||||
case SYSTEM_TEAMPLAYER:
|
||||
for (j=i*4; j< i*4+4; j++)
|
||||
{
|
||||
if (input.max == MAX_INPUTS) return;
|
||||
input.dev[j] = input.padtype[input.max];
|
||||
input.max ++;
|
||||
}
|
||||
teamplayer_reset(i);
|
||||
break;
|
||||
|
||||
case SYSTEM_MENACER:
|
||||
if (input.max == MAX_INPUTS) return;
|
||||
input.dev[i*4] = DEVICE_LIGHTGUN;
|
||||
lightgun_reset(0);
|
||||
break;
|
||||
|
||||
case SYSTEM_JUSTIFIER:
|
||||
for (j=i*4; j< i*4+2; j++)
|
||||
{
|
||||
if (input.max == MAX_INPUTS) return;
|
||||
input.dev[j] = DEVICE_LIGHTGUN;
|
||||
lightgun_reset(j - i*4);
|
||||
input.max ++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* J-CART: add two gamepad inputs */
|
||||
if (j_cart)
|
||||
{
|
||||
input.dev[5] = input.padtype[2];
|
||||
input.dev[6] = input.padtype[3];
|
||||
gamepad_reset(5);
|
||||
gamepad_reset(6);
|
||||
}
|
||||
}
|
||||
|
||||
void input_update()
|
||||
{
|
||||
int i;
|
||||
switch (input.system[0])
|
||||
{
|
||||
case SYSTEM_GAMEPAD:
|
||||
if (input.dev[0] == DEVICE_6BUTTON) gamepad_update(0);
|
||||
break;
|
||||
|
||||
case SYSTEM_WAYPLAY:
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if (input.dev[i] == DEVICE_6BUTTON) gamepad_update(i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (input.system[1])
|
||||
{
|
||||
case SYSTEM_GAMEPAD:
|
||||
if (input.dev[4] == DEVICE_6BUTTON) gamepad_update(4);
|
||||
break;
|
||||
|
||||
case SYSTEM_MENACER:
|
||||
lightgun_update(0);
|
||||
break;
|
||||
|
||||
case SYSTEM_JUSTIFIER:
|
||||
if ((io_reg[2] & 0x30) == 0x00) lightgun_update(0);
|
||||
if ((io_reg[2] & 0x30) == 0x20) lightgun_update(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void input_raz()
|
||||
{
|
||||
int i;
|
||||
switch (input.system[0])
|
||||
{
|
||||
case SYSTEM_GAMEPAD:
|
||||
if (input.dev[0] == DEVICE_6BUTTON) gamepad_raz(0);
|
||||
break;
|
||||
|
||||
case SYSTEM_WAYPLAY:
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if (input.dev[i] == DEVICE_6BUTTON) gamepad_raz(i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (input.system[1])
|
||||
{
|
||||
case SYSTEM_GAMEPAD:
|
||||
if (input.dev[4] == DEVICE_6BUTTON) gamepad_raz(4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
102
source/input.h
102
source/input.h
@ -1,18 +1,43 @@
|
||||
#ifndef _INPUT_H_
|
||||
#define _INPUT_H_
|
||||
#include "types.h"
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* Peripheral Input Support
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef _INPUT_HW_H_
|
||||
#define _INPUT_HW_H_
|
||||
|
||||
/* Available inputs */
|
||||
#ifdef HW_DOL
|
||||
#define MAX_INPUTS 4
|
||||
#else
|
||||
#define MAX_INPUTS 8
|
||||
#endif
|
||||
|
||||
/* Input devices */
|
||||
#ifdef NGC
|
||||
#define MAX_INPUTS (4)
|
||||
#else
|
||||
#define MAX_INPUTS (8)
|
||||
#endif
|
||||
#define MAX_DEVICES (8)
|
||||
|
||||
#define DEVICE_3BUTTON (0x00) /* 3-button gamepad */
|
||||
#define DEVICE_6BUTTON (0x01) /* 6-button gamepad */
|
||||
#define DEVICE_MOUSE (0x02) /* Sega Mouse (not supported) */
|
||||
#define DEVICE_LIGHTGUN (0x03) /* Sega Menacer */
|
||||
#define DEVICE_LIGHTGUN (0x02) /* Sega Menacer */
|
||||
#define DEVICE_MOUSE (0x03) /* Sega Mouse (not supported) */
|
||||
#define DEVICE_2BUTTON (0x04) /* 2-button gamepad (not supported) */
|
||||
#define NO_DEVICE (0x0F) /* unconnected */
|
||||
|
||||
@ -31,33 +56,60 @@
|
||||
#define INPUT_UP (0x00000001)
|
||||
|
||||
/* System bitmasks */
|
||||
#define SYSTEM_GAMEPAD (0) /* Single Gamepad */
|
||||
#define SYSTEM_TEAMPLAYER (1) /* Sega TeamPlayer (1~8 players) */
|
||||
#define SYSTEM_WAYPLAY (2) /* EA 4-Way Play (1~4 players) */
|
||||
#define SYSTEM_MENACER (3) /* SEGA Menacer Lightgun */
|
||||
#define NO_SYSTEM (4) /* Unconnected Port*/
|
||||
#define NO_SYSTEM (0) /* Unconnected Port*/
|
||||
#define SYSTEM_GAMEPAD (1) /* Single Gamepad */
|
||||
#define SYSTEM_MENACER (2) /* Sega Lightgun */
|
||||
#define SYSTEM_JUSTIFIER (3) /* Konami Lightgun */
|
||||
#define SYSTEM_TEAMPLAYER (4) /* Sega TeamPlayer */
|
||||
#define SYSTEM_WAYPLAY (5) /* EA 4-Way Play (use both ports) */
|
||||
|
||||
/* Players Inputs */
|
||||
#define PLAYER_1A (0)
|
||||
#define PLAYER_1B (1)
|
||||
#define PLAYER_1C (2)
|
||||
#define PLAYER_1D (3)
|
||||
#define PLAYER_2A (4)
|
||||
#define PLAYER_2B (5)
|
||||
#define PLAYER_2C (6)
|
||||
#define PLAYER_2D (7)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 dev[MAX_DEVICES]; /* Can be any of the DEVICE_* values */
|
||||
uint32 pad[MAX_DEVICES]; /* Can be any of the INPUT_* bitmasks */
|
||||
uint8 system[2]; /* Can be any of the SYSTEM_* bitmasks (PORTA & PORTB) */
|
||||
uint8 padtype[MAX_DEVICES]; /* 3BUTTONS or 6BUTTONS gamepad */
|
||||
uint8 system[2]; /* Can be any of the SYSTEM_* bitmasks */
|
||||
uint8 max; /* maximum number of connected devices */
|
||||
uint8 current; /* current PAD number (4WAYPLAY) */
|
||||
int analog[2][2]; /* analog device */
|
||||
int x_offset;
|
||||
int y_offset;
|
||||
} t_input;
|
||||
|
||||
/* global variables */
|
||||
/* Global variables */
|
||||
extern t_input input;
|
||||
extern uint8 j_cart;
|
||||
|
||||
/* Function prototypes */
|
||||
extern void input_reset (int padtype);
|
||||
extern void input_reset (void);
|
||||
extern void input_update(void);
|
||||
extern void input_raz(void);
|
||||
extern void lightgun_set (void);
|
||||
extern uint8 lightgun_read (void);
|
||||
extern uint8 gamepad_read (uint8 i);
|
||||
extern void gamepad_write (uint8 i, uint8 data);
|
||||
extern uint8 multitap_read (uint8 port);
|
||||
extern void multitap_write (uint8 port, uint8 data);
|
||||
|
||||
/* Peripherals specific */
|
||||
extern unsigned int menacer_read (void);
|
||||
extern unsigned int justifier_read (void);
|
||||
extern unsigned int gamepad_1_read (void);
|
||||
extern unsigned int gamepad_2_read (void);
|
||||
extern void gamepad_1_write (unsigned int data);
|
||||
extern void gamepad_2_write (unsigned int data);
|
||||
extern unsigned int wayplay_1_read (void);
|
||||
extern unsigned int wayplay_2_read (void);
|
||||
extern void wayplay_1_write (unsigned int data);
|
||||
extern void wayplay_2_write (unsigned int data);
|
||||
extern unsigned int teamplayer_1_read (void);
|
||||
extern unsigned int teamplayer_2_read (void);
|
||||
extern void teamplayer_1_write (unsigned int data);
|
||||
extern void teamplayer_2_write (unsigned int data);
|
||||
extern unsigned int jcart_read(void);
|
||||
extern void jcart_write(unsigned int data);
|
||||
|
||||
#endif
|
||||
|
174
source/io.c
174
source/io.c
@ -1,84 +1,39 @@
|
||||
/*
|
||||
Copyright (C) 1999, 2000, 2001, 2002, 2003 Charles MacDonald
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
I/O controller chip emulation
|
||||
*/
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* I/O Chip
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
uint8 io_reg[0x10];
|
||||
uint8 region_code = REGION_USA;
|
||||
uint8 pad_type = DEVICE_3BUTTON;
|
||||
|
||||
/*****************************************************************************
|
||||
* IO Read/Write wrappers
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
unsigned char Player1_Read (void)
|
||||
{
|
||||
return gamepad_read(0);
|
||||
}
|
||||
|
||||
unsigned char Player2_Read (void)
|
||||
{
|
||||
return gamepad_read(4);
|
||||
}
|
||||
|
||||
void Player1_Write (unsigned char data)
|
||||
{
|
||||
gamepad_write(0, data);
|
||||
}
|
||||
|
||||
void Player2_Write (unsigned char data)
|
||||
{
|
||||
gamepad_write(4, data);
|
||||
}
|
||||
|
||||
unsigned char MultiTap1_Read (void)
|
||||
{
|
||||
return multitap_read(0);
|
||||
}
|
||||
|
||||
unsigned char MultiTap2_Read (void)
|
||||
{
|
||||
return multitap_read(1);
|
||||
}
|
||||
|
||||
void MultiTap1_Write (unsigned char data)
|
||||
{
|
||||
multitap_write(0, data);
|
||||
}
|
||||
|
||||
void MultiTap2_Write (unsigned char data)
|
||||
{
|
||||
multitap_write(1, data);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* I/O chip functions *
|
||||
* *
|
||||
*****************************************************************************
|
||||
*/
|
||||
*****************************************************************************/
|
||||
struct port_t
|
||||
{
|
||||
void (*data_w)(uint8 data);
|
||||
uint8 (*data_r)(void);
|
||||
void (*data_w)(unsigned int data);
|
||||
unsigned int (*data_r)(void);
|
||||
} port[3];
|
||||
|
||||
void io_reset(void)
|
||||
@ -97,17 +52,22 @@ void io_reset(void)
|
||||
/* Initialize I/O registers */
|
||||
memcpy (io_reg, io_def, 0x10);
|
||||
|
||||
/* Initialize Port handlers */
|
||||
switch (input.system[0])
|
||||
{
|
||||
case SYSTEM_GAMEPAD:
|
||||
port[0].data_w = Player1_Write;
|
||||
port[0].data_r = Player1_Read;
|
||||
port[0].data_w = gamepad_1_write;
|
||||
port[0].data_r = gamepad_1_read;
|
||||
break;
|
||||
|
||||
case SYSTEM_WAYPLAY:
|
||||
port[0].data_w = wayplay_1_write;
|
||||
port[0].data_r = wayplay_1_read;
|
||||
break;
|
||||
|
||||
case SYSTEM_TEAMPLAYER:
|
||||
port[0].data_w = MultiTap1_Write;
|
||||
port[0].data_r = MultiTap1_Read;
|
||||
port[0].data_w = teamplayer_1_write;
|
||||
port[0].data_r = teamplayer_1_read;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -119,19 +79,28 @@ void io_reset(void)
|
||||
switch (input.system[1])
|
||||
{
|
||||
case SYSTEM_GAMEPAD:
|
||||
port[1].data_w = Player2_Write;
|
||||
port[1].data_r = Player2_Read;
|
||||
break;
|
||||
|
||||
case SYSTEM_WAYPLAY:
|
||||
case SYSTEM_TEAMPLAYER:
|
||||
port[1].data_w = MultiTap2_Write;
|
||||
port[1].data_r = MultiTap2_Read;
|
||||
port[1].data_w = gamepad_2_write;
|
||||
port[1].data_r = gamepad_2_read;
|
||||
break;
|
||||
|
||||
case SYSTEM_MENACER:
|
||||
port[1].data_w = NULL;
|
||||
port[1].data_r = lightgun_read;
|
||||
port[1].data_r = menacer_read;
|
||||
break;
|
||||
|
||||
case SYSTEM_JUSTIFIER:
|
||||
port[1].data_w = NULL;
|
||||
port[1].data_r = justifier_read;
|
||||
break;
|
||||
|
||||
case SYSTEM_WAYPLAY:
|
||||
port[1].data_w = wayplay_2_write;
|
||||
port[1].data_r = wayplay_2_read;
|
||||
break;
|
||||
|
||||
case SYSTEM_TEAMPLAYER:
|
||||
port[1].data_w = teamplayer_2_write;
|
||||
port[1].data_r = teamplayer_2_read;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -140,14 +109,15 @@ void io_reset(void)
|
||||
break;
|
||||
}
|
||||
|
||||
/* External Port (unconnected) */
|
||||
port[2].data_w = NULL;
|
||||
port[2].data_r = NULL;
|
||||
|
||||
j_cart = 0;
|
||||
input_reset(pad_type);
|
||||
/* Initialize Input Devices */
|
||||
input_reset();
|
||||
}
|
||||
|
||||
void io_write(int offset, int value)
|
||||
void io_write(unsigned int offset, unsigned int value)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
@ -166,50 +136,54 @@ void io_write(int offset, int value)
|
||||
/* autodetect 4-Way play ! */
|
||||
input.system[0] = SYSTEM_WAYPLAY;
|
||||
input.system[1] = SYSTEM_WAYPLAY;
|
||||
port[0].data_w = MultiTap1_Write;
|
||||
port[0].data_r = MultiTap1_Read;
|
||||
port[1].data_w = MultiTap2_Write;
|
||||
port[1].data_r = MultiTap2_Read;
|
||||
input_reset(pad_type);
|
||||
port[0].data_w = wayplay_1_write;
|
||||
port[0].data_r = wayplay_1_read;
|
||||
port[1].data_w = wayplay_2_write;
|
||||
port[1].data_r = wayplay_2_read;
|
||||
input_reset();
|
||||
}
|
||||
|
||||
case 0x04: /* Port A Ctrl */
|
||||
case 0x06: /* Port C Ctrl */
|
||||
io_reg[offset] = value & 0xFF;
|
||||
io_reg[offset-3] = ((io_reg[offset-3] & 0x80) | (io_reg[offset-3] & io_reg[offset]));
|
||||
break;
|
||||
return;
|
||||
|
||||
case 0x07: /* Port A TxData */
|
||||
case 0x0A: /* Port B TxData */
|
||||
case 0x0D: /* Port C TxData */
|
||||
io_reg[offset] = value;
|
||||
break;
|
||||
return;
|
||||
|
||||
case 0x09: /* Port A S-Ctrl */
|
||||
case 0x0C: /* Port B S-Ctrl */
|
||||
case 0x0F: /* Port C S-Ctrl */
|
||||
io_reg[offset] = (value & 0xF8);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int io_read(int offset)
|
||||
unsigned int io_read(unsigned int offset)
|
||||
{
|
||||
uint8 has_scd = 0x20; /* No Sega CD unit attached */
|
||||
uint8 gen_ver = 0x00; /* Version 0 hardware */
|
||||
uint8 input = 0x7F; /* default input state */
|
||||
|
||||
switch(offset)
|
||||
{
|
||||
case 0x00: /* Version */
|
||||
case 0x00: /* Version register */
|
||||
{
|
||||
uint8 has_scd = 0x20; /* No Sega CD unit attached */
|
||||
uint8 gen_ver = (config.bios_enabled == 3) ? 0x01 : 0x00; /* hardware version */
|
||||
return (region_code | has_scd | gen_ver);
|
||||
}
|
||||
|
||||
case 0x01: /* Port A Data */
|
||||
case 0x02: /* Port B Data */
|
||||
case 0x03: /* Port C Data */
|
||||
{
|
||||
uint8 input = 0x7F; /* default input state */
|
||||
if(port[offset-1].data_r) input = port[offset-1].data_r();
|
||||
return (io_reg[offset] | ((~io_reg[offset+3]) & input));
|
||||
}
|
||||
|
||||
default:
|
||||
return (io_reg[offset]);
|
||||
}
|
||||
}
|
||||
|
27
source/io.h
27
source/io.h
@ -1,3 +1,26 @@
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* I/O Chip
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef _IO_H_
|
||||
#define _IO_H_
|
||||
|
||||
@ -13,8 +36,8 @@ extern uint8 pad_type;
|
||||
|
||||
/* Function prototypes */
|
||||
extern void io_reset(void);
|
||||
extern void io_write(int offset, int value);
|
||||
extern int io_read(int offset);
|
||||
extern void io_write(unsigned int offset, unsigned int value);
|
||||
extern unsigned int io_read(unsigned int offset);
|
||||
|
||||
#endif /* _IO_H_ */
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
/****************************************************************************
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* ROM Loading Support
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -17,15 +19,10 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Information in this module was gleaned from
|
||||
* http://en.wikibooks.org/wiki/Genesis_Programming
|
||||
***************************************************************************/
|
||||
****************************************************************************************/
|
||||
|
||||
#include <ctype.h>
|
||||
#include "shared.h"
|
||||
#include "font.h"
|
||||
#include "rominfo.h"
|
||||
|
||||
#define MAXCOMPANY 64
|
||||
|
||||
/*** ROM Information ***/
|
||||
#define ROMCONSOLE 256
|
||||
@ -60,22 +57,9 @@
|
||||
#define PCDROM 4096
|
||||
#define PMOUSE 8192
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char companyid[6];
|
||||
char company[30];
|
||||
} COMPANYINFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char pID[2];
|
||||
char pName[21];
|
||||
} PERIPHERALINFO;
|
||||
|
||||
int peripherals;
|
||||
int checksumok;
|
||||
uint16 realchecksum;
|
||||
ROMINFO rominfo;
|
||||
uint16 GetRealChecksum ();
|
||||
|
||||
/***************************************************************************
|
||||
* Genesis ROM Manufacturers
|
||||
@ -173,6 +157,24 @@ PERIPHERALINFO peripheralinfo[14] = {
|
||||
{"M", "Mega Mouse"}
|
||||
};
|
||||
|
||||
/*
|
||||
* softdev - New Checksum Calculation
|
||||
eke-eke: fixed
|
||||
*/
|
||||
uint16 GetRealChecksum (uint8 *rom, int length)
|
||||
{
|
||||
int i;
|
||||
uint16 checksum = 0;
|
||||
|
||||
for (i = 0; i < length; i += 2)
|
||||
{
|
||||
checksum += ((rom[i] << 8) + rom[i + 1]);
|
||||
}
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* getcompany
|
||||
*
|
||||
@ -229,8 +231,31 @@ void getrominfo (char *romheader)
|
||||
|
||||
memcpy (&rominfo.consoletype, romheader + ROMCONSOLE, 16);
|
||||
memcpy (&rominfo.copyright, romheader + ROMCOPYRIGHT, 16);
|
||||
memcpy (&rominfo.domestic, romheader + ROMDOMESTIC, 48);
|
||||
memcpy (&rominfo.international, romheader + ROMWORLD, 48);
|
||||
|
||||
rominfo.domestic[0] = romheader[ROMDOMESTIC];
|
||||
j=1;
|
||||
for (i=1; i<48; i++)
|
||||
{
|
||||
if ((rominfo.domestic[j-1] != 32) || (romheader[ROMDOMESTIC + i] != 32))
|
||||
{
|
||||
rominfo.domestic[j] = romheader[ROMDOMESTIC + i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
rominfo.domestic[j] = 0;
|
||||
|
||||
rominfo.international[0] = romheader[ROMWORLD];
|
||||
j=1;
|
||||
for (i=1; i<48; i++)
|
||||
{
|
||||
if ((rominfo.international[j-1] != 32) || (romheader[ROMWORLD + i] != 32))
|
||||
{
|
||||
rominfo.international[j] = romheader[ROMWORLD + i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
rominfo.international[j] = 0;
|
||||
|
||||
memcpy (&rominfo.ROMType, romheader + ROMTYPE, 2);
|
||||
memcpy (&rominfo.product, romheader + ROMPRODUCT, 12);
|
||||
memcpy (&rominfo.checksum, romheader + ROMCHECKSUM, 2);
|
||||
@ -244,8 +269,10 @@ void getrominfo (char *romheader)
|
||||
memcpy (&rominfo.memo, romheader + ROMMEMO, 40);
|
||||
memcpy (&rominfo.country, romheader + ROMCOUNTRY, 16);
|
||||
|
||||
checksumok = (GetRealChecksum ((char *) cart_rom + 512, genromsize - 512)
|
||||
== rominfo.checksum);
|
||||
realchecksum = GetRealChecksum (((uint8 *) cart_rom) + 0x200, genromsize - 0x200);
|
||||
#ifdef LSB_FIRST
|
||||
rominfo.checksum = (rominfo.checksum >> 8) | ((rominfo.checksum & 0xff) << 8);
|
||||
#endif
|
||||
|
||||
peripherals = 0;
|
||||
|
||||
@ -253,157 +280,157 @@ void getrominfo (char *romheader)
|
||||
for (j=0; j < 14; j++)
|
||||
if (rominfo.io_support[i] == peripheralinfo[j].pID[0]) peripherals |= (1 << j);
|
||||
|
||||
if (peripherals & P6BUTTONS) pad_type = DEVICE_6BUTTON;
|
||||
else pad_type = DEVICE_3BUTTON;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
input.padtype[i] = (peripherals & P6BUTTONS) ? DEVICE_6BUTTON : DEVICE_3BUTTON;
|
||||
#ifdef HW_RVL
|
||||
if (config.input[i].device == 1) input.padtype[i] = DEVICE_3BUTTON;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Show rom info screen
|
||||
***************************************************************************/
|
||||
/* Automatically fixing the checksum is not a cool idea
|
||||
* This should be user switchable, or at least only applied
|
||||
* when genromsize == ( romend - romstart )
|
||||
if(realchecksum != (rominfo.checksum))
|
||||
{
|
||||
sprintf(msg, "WARNING: Possible hacked ROM loaded!");
|
||||
write_font( 10, 224, msg);
|
||||
cart_rom[0x18e] = realchecksum >> 8;
|
||||
cart_rom[0x18f] = realchecksum & 0xff;
|
||||
sprintf(msg, "Checksum corrected to %04x", realchecksum);
|
||||
write_font( 10, 248, msg);
|
||||
}
|
||||
*/
|
||||
void showrominfo ()
|
||||
/* 05/05/2006: new region detection routine (taken from GENS sourcecode) */
|
||||
void set_region ()
|
||||
{
|
||||
int ypos;
|
||||
u8 i,j,quit,redraw,max;
|
||||
char msg[128];
|
||||
short p;
|
||||
signed char a;
|
||||
char pName[14][21];
|
||||
uint16 realchecksum = GetRealChecksum (((uint8 *) cart_rom) + 0x200, genromsize - 0x200);
|
||||
/* country codes used to differentiate region */
|
||||
/* 0001 = japan ntsc (1) */
|
||||
/* 0010 = japan pal (2) */
|
||||
/* 0100 = usa (4) */
|
||||
/* 1000 = europe (8) */
|
||||
|
||||
quit = 0;
|
||||
j = 0;
|
||||
redraw = 1;
|
||||
int country = 0;
|
||||
int i = 0;
|
||||
char c;
|
||||
|
||||
/*** Remove any still held buttons ***/
|
||||
while(PAD_ButtonsHeld(0)) VIDEO_WaitVSync();
|
||||
/* reading header to find the country */
|
||||
if (!strnicmp(rominfo.country, "eur", 3)) country |= 8;
|
||||
else if (!strnicmp(rominfo.country, "usa", 3)) country |= 4;
|
||||
else if (!strnicmp(rominfo.country, "jap", 3)) country |= 1;
|
||||
|
||||
max = 14;
|
||||
for (i = 0; i < 14; i++)
|
||||
else for(i = 0; i < 4; i++)
|
||||
{
|
||||
if (peripherals & (1 << i))
|
||||
{
|
||||
sprintf(pName[max-14],"%s", peripheralinfo[i].pName);
|
||||
max ++;
|
||||
}
|
||||
c = toupper((int)rominfo.country[i]);
|
||||
if (c == 'U') country |= 4;
|
||||
else if (c == 'J') country |= 1;
|
||||
else if (c == 'E') country |= 8;
|
||||
else if (c < 16) country |= c;
|
||||
else if ((c >= '0') && (c <= '9')) country |= c - '0';
|
||||
else if ((c >= 'A') && (c <= 'F')) country |= c - 'A' + 10;
|
||||
}
|
||||
|
||||
while (quit == 0)
|
||||
{
|
||||
if (redraw)
|
||||
{
|
||||
ClearScreen ();
|
||||
/* automatic detection */
|
||||
/* setting region */
|
||||
/* this is used by IO register */
|
||||
if (country & 4) region_code = REGION_USA;
|
||||
else if (country & 1) region_code = REGION_JAPAN_NTSC;
|
||||
else if (country & 8) region_code = REGION_EUROPE;
|
||||
else if (country & 2) region_code = REGION_JAPAN_PAL;
|
||||
else region_code = REGION_USA;
|
||||
|
||||
ypos = 134;
|
||||
WriteCentre(ypos, "ROM Header Information");
|
||||
ypos += 2*fheight;
|
||||
|
||||
for (i=0; i<8; i++)
|
||||
/* some games need specific REGION setting */
|
||||
if (((strstr(rominfo.product,"T-45033") != NULL) && (rominfo.checksum == 0x0F81)) || /* Alisia Dragon (E) */
|
||||
(strstr(rominfo.product,"T-69046-50") != NULL)) /* On Dal Jang Goon (Korea) */
|
||||
{
|
||||
switch (i+j)
|
||||
/* need PAL settings */
|
||||
region_code = REGION_EUROPE;
|
||||
}
|
||||
else if ((realchecksum == 0x532e) && (strstr(rominfo.product,"1011-00") != NULL))
|
||||
{
|
||||
case 0:
|
||||
sprintf (msg, "Console type: %s", rominfo.consoletype);
|
||||
break;
|
||||
case 1:
|
||||
sprintf (msg, "Copyright: %s", rominfo.copyright);
|
||||
break;
|
||||
case 2:
|
||||
sprintf (msg, "Company: %s", companyinfo[getcompany ()].company);
|
||||
break;
|
||||
case 3:
|
||||
sprintf (msg, "Game Domestic Name:");
|
||||
break;
|
||||
case 4:
|
||||
sprintf(msg, " %s",rominfo.domestic);
|
||||
break;
|
||||
case 5:
|
||||
sprintf (msg, "Game International Name:");
|
||||
break;
|
||||
case 6:
|
||||
sprintf(msg, " %s",rominfo.international);
|
||||
break;
|
||||
case 7:
|
||||
sprintf (msg, "Type - %s : %s", rominfo.ROMType, strcmp (rominfo.ROMType, "AI") ? "Game" : "Educational");
|
||||
break;
|
||||
case 8:
|
||||
sprintf (msg, "Product - %s", rominfo.product);
|
||||
break;
|
||||
case 9:
|
||||
sprintf (msg, "Checksum - %04x (%04x) (%s)", rominfo.checksum, realchecksum, rominfo.checksum == realchecksum ? "Good" : "Bad");
|
||||
break;
|
||||
case 10:
|
||||
sprintf (msg, "ROM end: $%06X", rominfo.romend);
|
||||
break;
|
||||
case 11:
|
||||
if (sram.custom) sprintf (msg, "EEPROM(%dK) - $%06X", ((eeprom.type.size_mask+1)* 8) /1024, (unsigned int)sram.start);
|
||||
else if (sram.detected) sprintf (msg, "SRAM Start - $%06X", rominfo.ramstart);
|
||||
else sprintf (msg, "External RAM undetected");
|
||||
|
||||
break;
|
||||
case 12:
|
||||
if (sram.custom) sprintf (msg, "EEPROM(%dK) - $%06X", ((eeprom.type.size_mask+1)* 8) /1024, (unsigned int)sram.end);
|
||||
else if (sram.detected) sprintf (msg, "SRAM End - $%06X", rominfo.ramend);
|
||||
else if (sram.on) sprintf (msg, "Default SRAM activated ");
|
||||
else sprintf (msg, "SRAM is disactivated ");
|
||||
break;
|
||||
case 13:
|
||||
if (region_code == REGION_USA) sprintf (msg, "Region - %s (USA)", rominfo.country);
|
||||
else if (region_code == REGION_EUROPE) sprintf (msg, "Region - %s (EUR)", rominfo.country);
|
||||
else if (region_code == REGION_JAPAN_NTSC) sprintf (msg, "Region - %s (JAP)", rominfo.country);
|
||||
else if (region_code == REGION_JAPAN_PAL) sprintf (msg, "Region - %s (JPAL)", rominfo.country);
|
||||
break;
|
||||
default:
|
||||
sprintf (msg, "Supports - %s", pName[i+j-14]);
|
||||
break;
|
||||
/* On Dal Jang Goon (Korea) needs JAP region code */
|
||||
region_code = REGION_JAPAN_NTSC;
|
||||
}
|
||||
|
||||
write_font (100, ypos, msg);
|
||||
ypos += fheight;
|
||||
}
|
||||
/* Force region setting */
|
||||
if (config.region_detect == 1) region_code = REGION_USA;
|
||||
else if (config.region_detect == 2) region_code = REGION_EUROPE;
|
||||
else if (config.region_detect == 3) region_code = REGION_JAPAN_NTSC;
|
||||
else if (config.region_detect == 4) region_code = REGION_JAPAN_PAL;
|
||||
|
||||
ypos += fheight;
|
||||
WriteCentre (ypos, "Press A to Continue");
|
||||
SetScreen ();
|
||||
}
|
||||
|
||||
p = PAD_ButtonsDown (0);
|
||||
a = PAD_StickY (0);
|
||||
redraw = 0;
|
||||
|
||||
if ((j<(max-8)) && ((p & PAD_BUTTON_DOWN) || (a < -70))) {redraw = 1; j++;}
|
||||
if ((j>0) && ((p & PAD_BUTTON_UP) || (a > 70))) {redraw = 1; j--;}
|
||||
if (p & PAD_BUTTON_A) quit = 1;
|
||||
if (p & PAD_BUTTON_B) quit = 1;
|
||||
}
|
||||
/* set cpu/vdp speed: PAL or NTSC */
|
||||
if ((region_code == REGION_EUROPE) || (region_code == REGION_JAPAN_PAL)) vdp_pal = 1;
|
||||
else vdp_pal = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* softdev - New Checksum Calculation
|
||||
*/
|
||||
uint16 GetRealChecksum (uint8 * rom, int length)
|
||||
/* SMD (interleaved) rom support */
|
||||
static uint8 block[0x4000];
|
||||
|
||||
void deinterleave_block (uint8 * src)
|
||||
{
|
||||
int i;
|
||||
uint16 checksum = 0;
|
||||
|
||||
for (i = 0; i < length; i += 2)
|
||||
memcpy (block, src, 0x4000);
|
||||
for (i = 0; i < 0x2000; i += 1)
|
||||
{
|
||||
checksum += (uint16) rom[i];
|
||||
checksum += (uint16) rom[i + 1] << 8;
|
||||
src[i * 2 + 0] = block[0x2000 + (i)];
|
||||
src[i * 2 + 1] = block[0x0000 + (i)];
|
||||
}
|
||||
}
|
||||
|
||||
int load_rom(char *filename)
|
||||
{
|
||||
int i, size, offset = 0;
|
||||
|
||||
#ifdef NGC
|
||||
size = genromsize;
|
||||
#else
|
||||
uint8 *ptr;
|
||||
ptr = load_archive(filename, &size);
|
||||
if(!ptr) return (0);
|
||||
memcpy(cart_rom, ptr + offset, size);
|
||||
free(ptr);
|
||||
#endif
|
||||
|
||||
/* detect interleaved roms (.smd format) */
|
||||
if (strncmp((char *)(cart_rom + 0x100),"SEGA", 4) && ((size / 512) & 1))
|
||||
{
|
||||
size -= 512;
|
||||
offset += 512;
|
||||
|
||||
for (i = 0; i < (size / 0x4000); i += 1)
|
||||
{
|
||||
deinterleave_block (cart_rom + offset + (i * 0x4000));
|
||||
}
|
||||
|
||||
return checksum;
|
||||
memcpy(cart_rom, cart_rom + offset, size);
|
||||
}
|
||||
|
||||
/* max. 10 MBytes supported */
|
||||
if (size > 0xA00000) size = 0xA00000;
|
||||
genromsize = size;
|
||||
|
||||
/* clear unused ROM space */
|
||||
if (size < 0xA00000) memset (cart_rom + size, 0x00, 0xA00000 - size);
|
||||
|
||||
getrominfo((char *)cart_rom); /* get infos from ROM header */
|
||||
set_region(); /* set game region (PAL/NTSC, JAP/USA/EUR) */
|
||||
|
||||
#ifdef LSB_FIRST
|
||||
/* Byteswap ROM */
|
||||
uint8 temp;
|
||||
for(i = 0; i < genromsize; i += 2)
|
||||
{
|
||||
temp = cart_rom[i];
|
||||
cart_rom[i] = cart_rom[i+1];
|
||||
cart_rom[i+1] = temp;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* byteswapped RADICA dumps (from Haze) */
|
||||
if (((strstr(rominfo.product,"-K0101") != NULL) && (rominfo.checksum == 0xf424)) ||
|
||||
((strstr(rominfo.product,"-K0109") != NULL) && (rominfo.checksum == 0x4f10)))
|
||||
{
|
||||
uint8 temp;
|
||||
for(i = 0; i < genromsize; i += 2)
|
||||
{
|
||||
temp = cart_rom[i];
|
||||
cart_rom[i] = cart_rom[i+1];
|
||||
cart_rom[i+1] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
/* console hardware */
|
||||
if (strstr(rominfo.consoletype, "SEGA PICO") != NULL) system_hw = SYSTEM_PICO;
|
||||
else if (strstr(rominfo.consoletype, "SEGA MEGADRIVE") != NULL) system_hw = SYSTEM_MEGADRIVE;
|
||||
else system_hw = SYSTEM_GENESIS;
|
||||
|
||||
return(1);
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
/****************************************************************************
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* ROM Loading Support
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -17,11 +19,11 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Information in this module was gleaned from
|
||||
* http://en.wikibooks.org/wiki/Genesis_Programming
|
||||
***************************************************************************/
|
||||
#include "shared.h"
|
||||
****************************************************************************************/
|
||||
#ifndef _LOADROM_H_
|
||||
#define _LOADROM_H_
|
||||
|
||||
#define MAXCOMPANY 64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -43,7 +45,26 @@ typedef struct
|
||||
char country[18];
|
||||
} ROMINFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char companyid[6];
|
||||
char company[30];
|
||||
} COMPANYINFO;
|
||||
|
||||
extern void getrominfo (char *romheader);
|
||||
extern void showrominfo ();
|
||||
typedef struct
|
||||
{
|
||||
char pID[2];
|
||||
char pName[21];
|
||||
} PERIPHERALINFO;
|
||||
|
||||
/* Global variables */
|
||||
extern ROMINFO rominfo;
|
||||
extern COMPANYINFO companyinfo[MAXCOMPANY];
|
||||
extern PERIPHERALINFO peripheralinfo[14];
|
||||
extern uint16 realchecksum;
|
||||
|
||||
/* Function prototypes */
|
||||
extern int load_rom(char *filename);
|
||||
|
||||
#endif /* _LOADROM_H_ */
|
||||
|
@ -6,22 +6,28 @@
|
||||
/* ======================================================================== */
|
||||
/*
|
||||
* MUSASHI
|
||||
* Version 3.3
|
||||
* Version 3.32
|
||||
*
|
||||
* A portable Motorola M680x0 processor emulation engine.
|
||||
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
|
||||
* Copyright Karl Stenerud. All rights reserved.
|
||||
*
|
||||
* This code may be freely used for non-commercial purposes as long as this
|
||||
* copyright notice remains unaltered in the source code and any binary files
|
||||
* containing this code in compiled form.
|
||||
*
|
||||
* All other lisencing terms must be negotiated with the author
|
||||
* All other licensing terms must be negotiated with the author
|
||||
* (Karl Stenerud).
|
||||
*
|
||||
* The latest version of this code can be obtained at:
|
||||
* http://kstenerud.cjb.net
|
||||
*/
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================= CONFIGURATION ============================ */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Import the configuration for this build */
|
||||
#include "m68kconf.h"
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
@ -65,6 +71,7 @@ enum
|
||||
{
|
||||
M68K_CPU_TYPE_INVALID,
|
||||
M68K_CPU_TYPE_68000,
|
||||
M68K_CPU_TYPE_68008,
|
||||
M68K_CPU_TYPE_68010,
|
||||
M68K_CPU_TYPE_68EC020,
|
||||
M68K_CPU_TYPE_68020,
|
||||
@ -165,6 +172,15 @@ void m68k_write_memory_8(unsigned int address, unsigned int value);
|
||||
void m68k_write_memory_16(unsigned int address, unsigned int value);
|
||||
void m68k_write_memory_32(unsigned int address, unsigned int value);
|
||||
|
||||
/* Special call to simulate undocumented 68k behavior when move.l with a
|
||||
* predecrement destination mode is executed.
|
||||
* To simulate real 68k behavior, first write the high word to
|
||||
* [address+2], and then write the low word to [address].
|
||||
*
|
||||
* Enable this functionality with M68K_SIMULATE_PD_WRITES in m68kconf.h.
|
||||
*/
|
||||
void m68k_write_memory_32_pd(unsigned int address, unsigned int value);
|
||||
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
@ -209,6 +225,30 @@ void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data));
|
||||
void m68k_set_reset_instr_callback(void (*callback)(void));
|
||||
|
||||
|
||||
/* Set the callback for the CMPI.L #v, Dn instruction.
|
||||
* You must enable M68K_CMPILD_HAS_CALLBACK in m68kconf.h.
|
||||
* The CPU calls this callback every time it encounters a CMPI.L #v, Dn instruction.
|
||||
* Default behavior: do nothing.
|
||||
*/
|
||||
void m68k_set_cmpild_instr_callback(void (*callback)(unsigned int val, int reg));
|
||||
|
||||
|
||||
/* Set the callback for the RTE instruction.
|
||||
* You must enable M68K_RTE_HAS_CALLBACK in m68kconf.h.
|
||||
* The CPU calls this callback every time it encounters a RTE instruction.
|
||||
* Default behavior: do nothing.
|
||||
*/
|
||||
void m68k_set_rte_instr_callback(void (*callback)(void));
|
||||
|
||||
/* Set the callback for the TAS instruction.
|
||||
* You must enable M68K_TAS_HAS_CALLBACK in m68kconf.h.
|
||||
* The CPU calls this callback every time it encounters a TAS instruction.
|
||||
* Default behavior: return 1, allow writeback.
|
||||
*/
|
||||
void m68k_set_tas_instr_callback(int (*callback)(void));
|
||||
|
||||
|
||||
|
||||
/* Set the callback for informing of a large PC change.
|
||||
* You must enable M68K_MONITOR_PC in m68kconf.h.
|
||||
* The CPU calls this callback with the new PC value every time the PC changes
|
||||
@ -234,7 +274,7 @@ void m68k_set_fc_callback(void (*callback)(unsigned int new_fc));
|
||||
* instruction cycle.
|
||||
* Default behavior: do nothing.
|
||||
*/
|
||||
void m68k_set_instr_hook_callback(void (*callback)(void));
|
||||
void m68k_set_instr_hook_callback(void (*callback)(unsigned int pc));
|
||||
|
||||
|
||||
|
||||
@ -243,11 +283,16 @@ void m68k_set_instr_hook_callback(void (*callback)(void));
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Use this function to set the CPU type you want to emulate.
|
||||
* Currently supported types are: M68K_CPU_TYPE_68000, M68K_CPU_TYPE_68010,
|
||||
* M68K_CPU_TYPE_EC020, and M68K_CPU_TYPE_68020.
|
||||
* Currently supported types are: M68K_CPU_TYPE_68000, M68K_CPU_TYPE_68008,
|
||||
* M68K_CPU_TYPE_68010, M68K_CPU_TYPE_EC020, and M68K_CPU_TYPE_68020.
|
||||
*/
|
||||
void m68k_set_cpu_type(unsigned int cpu_type);
|
||||
|
||||
/* Do whatever initialisations the core requires. Should be called
|
||||
* at least once at init time.
|
||||
*/
|
||||
void m68k_init(void);
|
||||
|
||||
/* Pulse the RESET pin on the CPU.
|
||||
* You *MUST* reset the CPU at least once to initialize the emulation
|
||||
* Note: If you didn't call m68k_set_cpu_type() before resetting
|
||||
@ -291,18 +336,8 @@ unsigned int m68k_get_context(void* dst);
|
||||
/* set the current cpu context */
|
||||
void m68k_set_context(void* dst);
|
||||
|
||||
/* Save the current cpu context to disk.
|
||||
* You must provide a function pointer of the form:
|
||||
* void save_value(char* identifier, unsigned int value)
|
||||
*/
|
||||
void m68k_save_context( void (*save_value)(char* identifier, unsigned int value));
|
||||
|
||||
/* Load a cpu context from disk.
|
||||
* You must provide a function pointer of the form:
|
||||
* unsigned int load_value(char* identifier)
|
||||
*/
|
||||
void m68k_load_context(unsigned int (*load_value)(char* identifier));
|
||||
|
||||
/* Register the CPU state information */
|
||||
void m68k_state_register(const char *type, int index);
|
||||
|
||||
|
||||
/* Peek at the internals of a CPU context. This can either be a context
|
||||
@ -322,14 +357,21 @@ unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cp
|
||||
*/
|
||||
unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_type);
|
||||
|
||||
/* Same as above but accepts raw opcode data directly rather than fetching
|
||||
* via the read/write interfaces.
|
||||
*/
|
||||
unsigned int m68k_disassemble_raw(char* str_buff, unsigned int pc, const unsigned char* opdata, const unsigned char* argdata, unsigned int cpu_type);
|
||||
|
||||
/*** Not really required, but makes for clean compile under DevkitPPC ***/
|
||||
extern int vdp_int_ack_callback(int int_level);
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================= CONFIGURATION ============================ */
|
||||
/* ============================== MAME STUFF ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Import the configuration for this build */
|
||||
#include "m68kconf.h"
|
||||
|
||||
#if M68K_COMPILE_FOR_MAME == OPT_ON
|
||||
#include "m68kmame.h"
|
||||
#endif /* M68K_COMPILE_FOR_MAME */
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
@ -337,6 +379,3 @@ unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_
|
||||
/* ======================================================================== */
|
||||
|
||||
#endif /* M68K__HEADER */
|
||||
|
||||
/*** Not really required, but makes for clean compile under DevkitPPC ***/
|
||||
extern int vdp_int_ack_callback(int int_level);
|
@ -3,16 +3,16 @@
|
||||
/* ======================================================================== */
|
||||
/*
|
||||
* MUSASHI
|
||||
* Version 3.3
|
||||
* Version 3.32
|
||||
*
|
||||
* A portable Motorola M680x0 processor emulation engine.
|
||||
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
|
||||
* Copyright Karl Stenerud. All rights reserved.
|
||||
*
|
||||
* This code may be freely used for non-commercial purposes as long as this
|
||||
* copyright notice remains unaltered in the source code and any binary files
|
||||
* containing this code in compiled form.
|
||||
*
|
||||
* All other lisencing terms must be negotiated with the author
|
||||
* All other licensing terms must be negotiated with the author
|
||||
* (Karl Stenerud).
|
||||
*
|
||||
* The latest version of this code can be obtained at:
|
||||
@ -47,30 +47,36 @@
|
||||
#define M68K_COMPILE_FOR_MAME OPT_OFF
|
||||
#endif /* M68K_COMPILE_FOR_MAME */
|
||||
|
||||
#if M68K_COMPILE_FOR_MAME == OPT_ON
|
||||
#include "m68kmame.h"
|
||||
#else
|
||||
|
||||
#if M68K_COMPILE_FOR_MAME == OPT_OFF
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================= CONFIGURATION ============================ */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Turn on if you want to use the following M68K variants */
|
||||
#define M68K_EMULATE_010 OPT_ON
|
||||
#define M68K_EMULATE_EC020 OPT_ON
|
||||
#define M68K_EMULATE_020 OPT_ON
|
||||
/* Turn ON if you want to use the following M68K variants */
|
||||
#define M68K_EMULATE_008 OPT_OFF
|
||||
#define M68K_EMULATE_010 OPT_OFF
|
||||
#define M68K_EMULATE_EC020 OPT_OFF
|
||||
#define M68K_EMULATE_020 OPT_OFF
|
||||
#define M68K_EMULATE_040 OPT_OFF
|
||||
|
||||
|
||||
/* If on, the CPU will call m68k_read_immediate_xx() for immediate addressing
|
||||
/* If ON, the CPU will call m68k_read_immediate_xx() for immediate addressing
|
||||
* and m68k_read_pcrelative_xx() for PC-relative addressing.
|
||||
* If off, all read requests from the CPU will be redirected to m68k_read_xx()
|
||||
*/
|
||||
#define M68K_SEPARATE_READS OPT_OFF
|
||||
|
||||
/* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a
|
||||
* predecrement destination EA mode instead of m68k_write_32().
|
||||
* To simulate real 68k behavior, m68k_write_32_pd() must first write the high
|
||||
* word to [address+2], and then write the low word to [address].
|
||||
*/
|
||||
#define M68K_SIMULATE_PD_WRITES OPT_OFF
|
||||
|
||||
/* If on, CPU will call the interrupt acknowledge callback when it services an
|
||||
/* If ON, CPU will call the interrupt acknowledge callback when it services an
|
||||
* interrupt.
|
||||
* If off, all interrupts will be autovectored and all interrupt requests will
|
||||
* auto-clear when the interrupt is serviced.
|
||||
@ -79,26 +85,46 @@
|
||||
#define M68K_INT_ACK_CALLBACK(A) vdp_int_ack_callback(A)
|
||||
|
||||
|
||||
/* If on, CPU will call the breakpoint acknowledge callback when it encounters
|
||||
/* If ON, CPU will call the breakpoint acknowledge callback when it encounters
|
||||
* a breakpoint instruction and it is running a 68010+.
|
||||
*/
|
||||
#define M68K_EMULATE_BKPT_ACK OPT_OFF
|
||||
#define M68K_BKPT_ACK_CALLBACK() your_bkpt_ack_handler_function()
|
||||
|
||||
|
||||
/* If on, the CPU will monitor the trace flags and take trace exceptions
|
||||
/* If ON, the CPU will monitor the trace flags and take trace exceptions
|
||||
*/
|
||||
#define M68K_EMULATE_TRACE OPT_OFF
|
||||
|
||||
|
||||
/* If on, CPU will call the output reset callback when it encounters a reset
|
||||
/* If ON, CPU will call the output reset callback when it encounters a reset
|
||||
* instruction.
|
||||
*/
|
||||
#define M68K_EMULATE_RESET OPT_OFF
|
||||
#define M68K_RESET_CALLBACK() your_reset_handler_function()
|
||||
|
||||
|
||||
/* If on, CPU will call the set fc callback on every memory access to
|
||||
/* If ON, CPU will call the callback when it encounters a cmpi.l #v, dn
|
||||
* instruction.
|
||||
*/
|
||||
#define M68K_CMPILD_HAS_CALLBACK OPT_OFF
|
||||
#define M68K_CMPILD_CALLBACK(v,r) your_cmpild_handler_function(v,r)
|
||||
|
||||
|
||||
/* If ON, CPU will call the callback when it encounters a rte
|
||||
* instruction.
|
||||
*/
|
||||
#define M68K_RTE_HAS_CALLBACK OPT_OFF
|
||||
#define M68K_RTE_CALLBACK() your_rte_handler_function()
|
||||
|
||||
/* If ON, CPU will call the callback when it encounters a tas
|
||||
* instruction.
|
||||
*/
|
||||
#define M68K_TAS_HAS_CALLBACK OPT_OFF
|
||||
#define M68K_TAS_CALLBACK() your_tas_handler_function()
|
||||
|
||||
|
||||
/* If ON, CPU will call the set fc callback on every memory access to
|
||||
* differentiate between user/supervisor, program/data access like a real
|
||||
* 68000 would. This should be enabled and the callback should be set if you
|
||||
* want to properly emulate the m68010 or higher. (moves uses function codes
|
||||
@ -108,7 +134,7 @@
|
||||
#define M68K_SET_FC_CALLBACK(A) your_set_fc_handler_function(A)
|
||||
|
||||
|
||||
/* If on, CPU will call the pc changed callback when it changes the PC by a
|
||||
/* If ON, CPU will call the pc changed callback when it changes the PC by a
|
||||
* large value. This allows host programs to be nicer when it comes to
|
||||
* fetching immediate data and instructions on a banked memory system.
|
||||
*/
|
||||
@ -116,25 +142,25 @@
|
||||
#define M68K_SET_PC_CALLBACK(A) your_pc_changed_handler_function(A)
|
||||
|
||||
|
||||
/* If on, CPU will call the instruction hook callback before every
|
||||
/* If ON, CPU will call the instruction hook callback before every
|
||||
* instruction.
|
||||
*/
|
||||
#define M68K_INSTRUCTION_HOOK OPT_OFF
|
||||
#define M68K_INSTRUCTION_CALLBACK() your_instruction_hook_function()
|
||||
|
||||
|
||||
/* If on, the CPU will emulate the 4-byte prefetch queue of a real 68000 */
|
||||
/* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000 */
|
||||
#define M68K_EMULATE_PREFETCH OPT_OFF
|
||||
|
||||
|
||||
/* If on, the CPU will generate address error exceptions if it tries to
|
||||
/* If ON, the CPU will generate address error exceptions if it tries to
|
||||
* access a word or longword at an odd address.
|
||||
* NOTE: Do not enable this! It is not working!
|
||||
* NOTE: This is only emulated properly for 68000 mode.
|
||||
*/
|
||||
#define M68K_EMULATE_ADDRESS_ERROR OPT_OFF
|
||||
#define M68K_EMULATE_ADDRESS_ERROR OPT_ON
|
||||
|
||||
|
||||
/* Turn on to enable logging of illegal instruction calls.
|
||||
/* Turn ON to enable logging of illegal instruction calls.
|
||||
* M68K_LOG_FILEHANDLE must be #defined to a stdio file stream.
|
||||
* Turn on M68K_LOG_1010_1111 to log all 1010 and 1111 calls.
|
||||
*/
|
||||
@ -150,7 +176,7 @@
|
||||
*/
|
||||
|
||||
|
||||
/* If on, the enulation core will use 64-bit integers to speed up some
|
||||
/* If ON, the enulation core will use 64-bit integers to speed up some
|
||||
* operations.
|
||||
*/
|
||||
#define M68K_USE_64_BIT OPT_OFF
|
||||
@ -165,14 +191,6 @@
|
||||
#define INLINE static __inline__
|
||||
#endif /* INLINE */
|
||||
|
||||
|
||||
/* If your environment requires special prefixes for system callback functions
|
||||
* such as the argument to qsort(), then set them here or in the makefile.
|
||||
*/
|
||||
#ifndef DECL_SPEC
|
||||
#define DECL_SPEC
|
||||
#endif
|
||||
|
||||
#endif /* M68K_COMPILE_FOR_MAME */
|
||||
|
||||
|
@ -3,17 +3,17 @@
|
||||
/* ======================================================================== */
|
||||
|
||||
#if 0
|
||||
static const char* copyright_notice =
|
||||
static const char copyright_notice[] =
|
||||
"MUSASHI\n"
|
||||
"Version 3.3 (2001-01-29)\n"
|
||||
"Version 3.32 (2007-12-15)\n"
|
||||
"A portable Motorola M680x0 processor emulation engine.\n"
|
||||
"Copyright 1998-2001 Karl Stenerud. All rights reserved.\n"
|
||||
"Copyright Karl Stenerud. All rights reserved.\n"
|
||||
"\n"
|
||||
"This code may be freely used for non-commercial purpooses as long as this\n"
|
||||
"copyright notice remains unaltered in the source code and any binary files\n"
|
||||
"containing this code in compiled form.\n"
|
||||
"\n"
|
||||
"All other lisencing terms must be negotiated with the author\n"
|
||||
"All other licensing terms must be negotiated with the author\n"
|
||||
"(Karl Stenerud).\n"
|
||||
"\n"
|
||||
"The latest version of this code can be obtained at:\n"
|
||||
@ -32,8 +32,12 @@ static const char* copyright_notice =
|
||||
/* ================================ INCLUDES ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
extern void m68040_fpu_op0(void);
|
||||
extern void m68040_fpu_op1(void);
|
||||
|
||||
#include "m68kops.h"
|
||||
#include "m68kcpu.h"
|
||||
//#include "m68kfpu.c"
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================= DATA ================================= */
|
||||
@ -45,13 +49,21 @@ uint m68ki_tracing = 0;
|
||||
uint m68ki_address_space;
|
||||
|
||||
#ifdef M68K_LOG_ENABLE
|
||||
char* m68ki_cpu_names[9] =
|
||||
const char *const m68ki_cpu_names[] =
|
||||
{
|
||||
"Invalid CPU",
|
||||
"M68000",
|
||||
"M68008",
|
||||
"Invalid CPU",
|
||||
"M68010",
|
||||
"Invalid CPU",
|
||||
"M68EC020"
|
||||
"Invalid CPU",
|
||||
"Invalid CPU",
|
||||
"M68EC020",
|
||||
"Invalid CPU",
|
||||
"Invalid CPU",
|
||||
"Invalid CPU",
|
||||
"Invalid CPU",
|
||||
"Invalid CPU",
|
||||
"Invalid CPU",
|
||||
"Invalid CPU",
|
||||
@ -63,11 +75,15 @@ char* m68ki_cpu_names[9] =
|
||||
m68ki_cpu_core m68ki_cpu = {0};
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
jmp_buf m68ki_address_error_trap;
|
||||
jmp_buf m68ki_aerr_trap;
|
||||
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
||||
|
||||
uint m68ki_aerr_address;
|
||||
uint m68ki_aerr_write_mode;
|
||||
uint m68ki_aerr_fc;
|
||||
|
||||
/* Used by shift & rotate instructions */
|
||||
uint8 m68ki_shift_8_table[65] =
|
||||
const uint8 m68ki_shift_8_table[65] =
|
||||
{
|
||||
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
@ -76,7 +92,7 @@ uint8 m68ki_shift_8_table[65] =
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
uint16 m68ki_shift_16_table[65] =
|
||||
const uint16 m68ki_shift_16_table[65] =
|
||||
{
|
||||
0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
|
||||
0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff,
|
||||
@ -87,7 +103,7 @@ uint16 m68ki_shift_16_table[65] =
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff
|
||||
};
|
||||
uint m68ki_shift_32_table[65] =
|
||||
const uint m68ki_shift_32_table[65] =
|
||||
{
|
||||
0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000,
|
||||
0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
|
||||
@ -106,7 +122,7 @@ uint m68ki_shift_32_table[65] =
|
||||
/* Number of clock cycles to use for exception processing.
|
||||
* I used 4 for any vectors that are undocumented for processing times.
|
||||
*/
|
||||
uint8 m68ki_exception_cycle_table[3][256] =
|
||||
const uint8 m68ki_exception_cycle_table[4][256] =
|
||||
{
|
||||
{ /* 000 */
|
||||
4, /* 0: Reset - Initial Stack Pointer */
|
||||
@ -326,10 +342,83 @@ uint8 m68ki_exception_cycle_table[3][256] =
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
|
||||
},
|
||||
{ /* 040 */ // TODO: these values are not correct
|
||||
4, /* 0: Reset - Initial Stack Pointer */
|
||||
4, /* 1: Reset - Initial Program Counter */
|
||||
50, /* 2: Bus Error (unemulated) */
|
||||
50, /* 3: Address Error (unemulated) */
|
||||
20, /* 4: Illegal Instruction */
|
||||
38, /* 5: Divide by Zero */
|
||||
40, /* 6: CHK */
|
||||
20, /* 7: TRAPV */
|
||||
34, /* 8: Privilege Violation */
|
||||
25, /* 9: Trace */
|
||||
20, /* 10: 1010 */
|
||||
20, /* 11: 1111 */
|
||||
4, /* 12: RESERVED */
|
||||
4, /* 13: Coprocessor Protocol Violation (unemulated) */
|
||||
4, /* 14: Format Error */
|
||||
30, /* 15: Uninitialized Interrupt */
|
||||
4, /* 16: RESERVED */
|
||||
4, /* 17: RESERVED */
|
||||
4, /* 18: RESERVED */
|
||||
4, /* 19: RESERVED */
|
||||
4, /* 20: RESERVED */
|
||||
4, /* 21: RESERVED */
|
||||
4, /* 22: RESERVED */
|
||||
4, /* 23: RESERVED */
|
||||
30, /* 24: Spurious Interrupt */
|
||||
30, /* 25: Level 1 Interrupt Autovector */
|
||||
30, /* 26: Level 2 Interrupt Autovector */
|
||||
30, /* 27: Level 3 Interrupt Autovector */
|
||||
30, /* 28: Level 4 Interrupt Autovector */
|
||||
30, /* 29: Level 5 Interrupt Autovector */
|
||||
30, /* 30: Level 6 Interrupt Autovector */
|
||||
30, /* 31: Level 7 Interrupt Autovector */
|
||||
20, /* 32: TRAP #0 */
|
||||
20, /* 33: TRAP #1 */
|
||||
20, /* 34: TRAP #2 */
|
||||
20, /* 35: TRAP #3 */
|
||||
20, /* 36: TRAP #4 */
|
||||
20, /* 37: TRAP #5 */
|
||||
20, /* 38: TRAP #6 */
|
||||
20, /* 39: TRAP #7 */
|
||||
20, /* 40: TRAP #8 */
|
||||
20, /* 41: TRAP #9 */
|
||||
20, /* 42: TRAP #10 */
|
||||
20, /* 43: TRAP #11 */
|
||||
20, /* 44: TRAP #12 */
|
||||
20, /* 45: TRAP #13 */
|
||||
20, /* 46: TRAP #14 */
|
||||
20, /* 47: TRAP #15 */
|
||||
4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
|
||||
4, /* 49: FP Inexact Result (unemulated) */
|
||||
4, /* 50: FP Divide by Zero (unemulated) */
|
||||
4, /* 51: FP Underflow (unemulated) */
|
||||
4, /* 52: FP Operand Error (unemulated) */
|
||||
4, /* 53: FP Overflow (unemulated) */
|
||||
4, /* 54: FP Signaling NAN (unemulated) */
|
||||
4, /* 55: FP Unimplemented Data Type (unemulated) */
|
||||
4, /* 56: MMU Configuration Error (unemulated) */
|
||||
4, /* 57: MMU Illegal Operation Error (unemulated) */
|
||||
4, /* 58: MMU Access Level Violation Error (unemulated) */
|
||||
4, /* 59: RESERVED */
|
||||
4, /* 60: RESERVED */
|
||||
4, /* 61: RESERVED */
|
||||
4, /* 62: RESERVED */
|
||||
4, /* 63: RESERVED */
|
||||
/* 64-255: User Defined */
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
|
||||
}
|
||||
};
|
||||
|
||||
uint8 m68ki_ea_idx_cycle_table[64] =
|
||||
const uint8 m68ki_ea_idx_cycle_table[64] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, /* ..01.000 no memory indirect, base NULL */
|
||||
@ -380,6 +469,22 @@ static void default_reset_instr_callback(void)
|
||||
{
|
||||
}
|
||||
|
||||
/* Called when a cmpi.l #v, dn instruction is executed */
|
||||
static void default_cmpild_instr_callback(unsigned int val, int reg)
|
||||
{
|
||||
}
|
||||
|
||||
/* Called when a rte instruction is executed */
|
||||
static void default_rte_instr_callback(void)
|
||||
{
|
||||
}
|
||||
|
||||
/* Called when a tas instruction is executed */
|
||||
static int default_tas_instr_callback(void)
|
||||
{
|
||||
return 1; // allow writeback
|
||||
}
|
||||
|
||||
/* Called when the program counter changed by a large value */
|
||||
static unsigned int default_pc_changed_callback_data;
|
||||
static void default_pc_changed_callback(unsigned int new_pc)
|
||||
@ -395,11 +500,17 @@ static void default_set_fc_callback(unsigned int new_fc)
|
||||
}
|
||||
|
||||
/* Called every instruction cycle prior to execution */
|
||||
static void default_instr_hook_callback(void)
|
||||
static void default_instr_hook_callback(unsigned int pc)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
#include <setjmp.h>
|
||||
jmp_buf m68ki_aerr_trap;
|
||||
int emulate_address_error = 0;
|
||||
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================= API ================================== */
|
||||
@ -456,9 +567,11 @@ unsigned int m68k_get_reg(void* context, m68k_register_t regnum)
|
||||
switch(cpu->cpu_type)
|
||||
{
|
||||
case CPU_TYPE_000: return (unsigned int)M68K_CPU_TYPE_68000;
|
||||
case CPU_TYPE_008: return (unsigned int)M68K_CPU_TYPE_68008;
|
||||
case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010;
|
||||
case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020;
|
||||
case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020;
|
||||
case CPU_TYPE_040: return (unsigned int)M68K_CPU_TYPE_68040;
|
||||
}
|
||||
return M68K_CPU_TYPE_INVALID;
|
||||
default: return 0;
|
||||
@ -511,6 +624,7 @@ void m68k_set_reg(m68k_register_t regnum, unsigned int value)
|
||||
case M68K_REG_CAAR: REG_CAAR = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_PPC: REG_PPC = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return;
|
||||
case M68K_REG_PREF_ADDR: CPU_PREF_ADDR = MASK_OUT_ABOVE_32(value); return;
|
||||
case M68K_REG_CPU_TYPE: m68k_set_cpu_type(value); return;
|
||||
default: return;
|
||||
}
|
||||
@ -532,6 +646,21 @@ void m68k_set_reset_instr_callback(void (*callback)(void))
|
||||
CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback;
|
||||
}
|
||||
|
||||
void m68k_set_cmpild_instr_callback(void (*callback)(unsigned int, int))
|
||||
{
|
||||
CALLBACK_CMPILD_INSTR = callback ? callback : default_cmpild_instr_callback;
|
||||
}
|
||||
|
||||
void m68k_set_rte_instr_callback(void (*callback)(void))
|
||||
{
|
||||
CALLBACK_RTE_INSTR = callback ? callback : default_rte_instr_callback;
|
||||
}
|
||||
|
||||
void m68k_set_tas_instr_callback(int (*callback)(void))
|
||||
{
|
||||
CALLBACK_TAS_INSTR = callback ? callback : default_tas_instr_callback;
|
||||
}
|
||||
|
||||
void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc))
|
||||
{
|
||||
CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback;
|
||||
@ -542,7 +671,7 @@ void m68k_set_fc_callback(void (*callback)(unsigned int new_fc))
|
||||
CALLBACK_SET_FC = callback ? callback : default_set_fc_callback;
|
||||
}
|
||||
|
||||
void m68k_set_instr_hook_callback(void (*callback)(void))
|
||||
void m68k_set_instr_hook_callback(void (*callback)(unsigned int pc))
|
||||
{
|
||||
CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback;
|
||||
}
|
||||
@ -563,7 +692,23 @@ void m68k_set_cpu_type(unsigned int cpu_type)
|
||||
CYC_BCC_NOTAKE_W = 2;
|
||||
CYC_DBCC_F_NOEXP = -2;
|
||||
CYC_DBCC_F_EXP = 2;
|
||||
CYC_SCC_R_FALSE = 2;
|
||||
CYC_SCC_R_TRUE = 2;
|
||||
CYC_MOVEM_W = 2;
|
||||
CYC_MOVEM_L = 3;
|
||||
CYC_SHIFT = 1;
|
||||
CYC_RESET = 132;
|
||||
return;
|
||||
case M68K_CPU_TYPE_68008:
|
||||
CPU_TYPE = CPU_TYPE_008;
|
||||
CPU_ADDRESS_MASK = 0x003fffff;
|
||||
CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
|
||||
CYC_INSTRUCTION = m68ki_cycles[0];
|
||||
CYC_EXCEPTION = m68ki_exception_cycle_table[0];
|
||||
CYC_BCC_NOTAKE_B = -2;
|
||||
CYC_BCC_NOTAKE_W = 2;
|
||||
CYC_DBCC_F_NOEXP = -2;
|
||||
CYC_DBCC_F_EXP = 2;
|
||||
CYC_SCC_R_TRUE = 2;
|
||||
CYC_MOVEM_W = 2;
|
||||
CYC_MOVEM_L = 3;
|
||||
CYC_SHIFT = 1;
|
||||
@ -579,7 +724,7 @@ void m68k_set_cpu_type(unsigned int cpu_type)
|
||||
CYC_BCC_NOTAKE_W = 0;
|
||||
CYC_DBCC_F_NOEXP = 0;
|
||||
CYC_DBCC_F_EXP = 6;
|
||||
CYC_SCC_R_FALSE = 0;
|
||||
CYC_SCC_R_TRUE = 0;
|
||||
CYC_MOVEM_W = 2;
|
||||
CYC_MOVEM_L = 3;
|
||||
CYC_SHIFT = 1;
|
||||
@ -595,7 +740,7 @@ void m68k_set_cpu_type(unsigned int cpu_type)
|
||||
CYC_BCC_NOTAKE_W = 0;
|
||||
CYC_DBCC_F_NOEXP = 0;
|
||||
CYC_DBCC_F_EXP = 4;
|
||||
CYC_SCC_R_FALSE = 0;
|
||||
CYC_SCC_R_TRUE = 0;
|
||||
CYC_MOVEM_W = 2;
|
||||
CYC_MOVEM_L = 2;
|
||||
CYC_SHIFT = 0;
|
||||
@ -611,7 +756,23 @@ void m68k_set_cpu_type(unsigned int cpu_type)
|
||||
CYC_BCC_NOTAKE_W = 0;
|
||||
CYC_DBCC_F_NOEXP = 0;
|
||||
CYC_DBCC_F_EXP = 4;
|
||||
CYC_SCC_R_FALSE = 0;
|
||||
CYC_SCC_R_TRUE = 0;
|
||||
CYC_MOVEM_W = 2;
|
||||
CYC_MOVEM_L = 2;
|
||||
CYC_SHIFT = 0;
|
||||
CYC_RESET = 518;
|
||||
return;
|
||||
case M68K_CPU_TYPE_68040: // TODO: these values are not correct
|
||||
CPU_TYPE = CPU_TYPE_040;
|
||||
CPU_ADDRESS_MASK = 0xffffffff;
|
||||
CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
|
||||
CYC_INSTRUCTION = m68ki_cycles[2];
|
||||
CYC_EXCEPTION = m68ki_exception_cycle_table[2];
|
||||
CYC_BCC_NOTAKE_B = -2;
|
||||
CYC_BCC_NOTAKE_W = 0;
|
||||
CYC_DBCC_F_NOEXP = 0;
|
||||
CYC_DBCC_F_EXP = 4;
|
||||
CYC_SCC_R_TRUE = 0;
|
||||
CYC_MOVEM_W = 2;
|
||||
CYC_MOVEM_L = 2;
|
||||
CYC_SHIFT = 0;
|
||||
@ -648,7 +809,7 @@ int m68k_execute(int num_cycles)
|
||||
m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Call external hook to peek at CPU */
|
||||
m68ki_instr_hook(); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_instr_hook(REG_PC); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Record previous program counter */
|
||||
REG_PPC = REG_PC;
|
||||
@ -723,9 +884,7 @@ void m68k_set_irq(unsigned int int_level)
|
||||
m68ki_check_interrupts(); /* Level triggered (IRQ) */
|
||||
}
|
||||
|
||||
|
||||
/* Pulse the RESET line on the CPU */
|
||||
void m68k_pulse_reset(void)
|
||||
void m68k_init(void)
|
||||
{
|
||||
static uint emulation_initialized = 0;
|
||||
|
||||
@ -733,29 +892,35 @@ void m68k_pulse_reset(void)
|
||||
if(!emulation_initialized)
|
||||
{
|
||||
m68ki_build_opcode_table();
|
||||
m68k_set_int_ack_callback(NULL);
|
||||
m68k_set_bkpt_ack_callback(NULL);
|
||||
m68k_set_reset_instr_callback(NULL);
|
||||
m68k_set_pc_changed_callback(NULL);
|
||||
m68k_set_fc_callback(NULL);
|
||||
m68k_set_instr_hook_callback(NULL);
|
||||
|
||||
emulation_initialized = 1;
|
||||
}
|
||||
|
||||
m68k_set_int_ack_callback(NULL);
|
||||
m68k_set_bkpt_ack_callback(NULL);
|
||||
m68k_set_reset_instr_callback(NULL);
|
||||
m68k_set_cmpild_instr_callback(NULL);
|
||||
m68k_set_rte_instr_callback(NULL);
|
||||
m68k_set_tas_instr_callback(NULL);
|
||||
m68k_set_pc_changed_callback(NULL);
|
||||
m68k_set_fc_callback(NULL);
|
||||
m68k_set_instr_hook_callback(NULL);
|
||||
}
|
||||
|
||||
if(CPU_TYPE == 0) /* KW 990319 */
|
||||
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
|
||||
|
||||
/* Pulse the RESET line on the CPU */
|
||||
void m68k_pulse_reset(void)
|
||||
{
|
||||
/* Clear all stop levels and eat up all remaining cycles */
|
||||
CPU_STOPPED = 0;
|
||||
SET_CYCLES(0);
|
||||
|
||||
CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET;
|
||||
|
||||
/* Turn off tracing */
|
||||
FLAG_T1 = FLAG_T0 = 0;
|
||||
m68ki_clear_trace();
|
||||
/* Interrupt mask to level 7 */
|
||||
FLAG_INT_MASK = 0x0700;
|
||||
CPU_INT_LEVEL = 0;
|
||||
/* Reset VBR */
|
||||
REG_VBR = 0;
|
||||
/* Go to supervisor mode */
|
||||
@ -772,6 +937,8 @@ void m68k_pulse_reset(void)
|
||||
REG_SP = m68ki_read_imm_32();
|
||||
REG_PC = m68ki_read_imm_32();
|
||||
m68ki_jump(REG_PC);
|
||||
|
||||
CPU_RUN_MODE = RUN_MODE_NORMAL;
|
||||
}
|
||||
|
||||
/* Pulse the HALT line on the CPU */
|
||||
@ -799,95 +966,61 @@ void m68k_set_context(void* src)
|
||||
if(src) m68ki_cpu = *(m68ki_cpu_core*)src;
|
||||
}
|
||||
|
||||
void m68k_save_context( void (*save_value)(char*, unsigned int))
|
||||
{
|
||||
if(!save_value)
|
||||
return;
|
||||
|
||||
save_value("CPU_TYPE" , m68k_get_reg(NULL, M68K_REG_CPU_TYPE));
|
||||
save_value("D0" , REG_D[0]);
|
||||
save_value("D1" , REG_D[1]);
|
||||
save_value("D2" , REG_D[2]);
|
||||
save_value("D3" , REG_D[3]);
|
||||
save_value("D4" , REG_D[4]);
|
||||
save_value("D5" , REG_D[5]);
|
||||
save_value("D6" , REG_D[6]);
|
||||
save_value("D7" , REG_D[7]);
|
||||
save_value("A0" , REG_A[0]);
|
||||
save_value("A1" , REG_A[1]);
|
||||
save_value("A2" , REG_A[2]);
|
||||
save_value("A3" , REG_A[3]);
|
||||
save_value("A4" , REG_A[4]);
|
||||
save_value("A5" , REG_A[5]);
|
||||
save_value("A6" , REG_A[6]);
|
||||
save_value("A7" , REG_A[7]);
|
||||
save_value("PPC" , REG_PPC);
|
||||
save_value("PC" , REG_PC);
|
||||
save_value("USP" , REG_USP);
|
||||
save_value("ISP" , REG_ISP);
|
||||
save_value("MSP" , REG_MSP);
|
||||
save_value("VBR" , REG_VBR);
|
||||
save_value("SFC" , REG_SFC);
|
||||
save_value("DFC" , REG_DFC);
|
||||
save_value("CACR" , REG_CACR);
|
||||
save_value("CAAR" , REG_CAAR);
|
||||
save_value("SR" , m68ki_get_sr());
|
||||
save_value("INT_LEVEL" , CPU_INT_LEVEL);
|
||||
save_value("INT_CYCLES", CPU_INT_CYCLES);
|
||||
save_value("STOPPED" , (CPU_STOPPED & STOP_LEVEL_STOP) != 0);
|
||||
save_value("HALTED" , (CPU_STOPPED & STOP_LEVEL_HALT) != 0);
|
||||
save_value("PREF_ADDR" , CPU_PREF_ADDR);
|
||||
save_value("PREF_DATA" , CPU_PREF_DATA);
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== MAME STUFF ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
#if M68K_COMPILE_FOR_MAME == OPT_ON
|
||||
|
||||
static struct {
|
||||
uint16 sr;
|
||||
uint8 stopped;
|
||||
uint8 halted;
|
||||
} m68k_substate;
|
||||
|
||||
static void m68k_prepare_substate(void)
|
||||
{
|
||||
m68k_substate.sr = m68ki_get_sr();
|
||||
m68k_substate.stopped = (CPU_STOPPED & STOP_LEVEL_STOP) != 0;
|
||||
m68k_substate.halted = (CPU_STOPPED & STOP_LEVEL_HALT) != 0;
|
||||
}
|
||||
|
||||
void m68k_load_context(unsigned int (*load_value)(char*))
|
||||
static void m68k_post_load(void)
|
||||
{
|
||||
unsigned int temp;
|
||||
|
||||
m68k_set_cpu_type(load_value("CPU_TYPE"));
|
||||
REG_PPC = load_value("PPC");
|
||||
REG_PC = load_value("PC");
|
||||
m68ki_set_sr_noint_nosp(m68k_substate.sr);
|
||||
CPU_STOPPED = m68k_substate.stopped ? STOP_LEVEL_STOP : 0
|
||||
| m68k_substate.halted ? STOP_LEVEL_HALT : 0;
|
||||
m68ki_jump(REG_PC);
|
||||
CPU_INT_LEVEL = 0;
|
||||
m68ki_set_sr_noint(load_value("SR"));
|
||||
REG_D[0] = load_value("D0");
|
||||
REG_D[1] = load_value("D1");
|
||||
REG_D[2] = load_value("D2");
|
||||
REG_D[3] = load_value("D3");
|
||||
REG_D[4] = load_value("D4");
|
||||
REG_D[5] = load_value("D5");
|
||||
REG_D[6] = load_value("D6");
|
||||
REG_D[7] = load_value("D7");
|
||||
REG_A[0] = load_value("A0");
|
||||
REG_A[1] = load_value("A1");
|
||||
REG_A[2] = load_value("A2");
|
||||
REG_A[3] = load_value("A3");
|
||||
REG_A[4] = load_value("A4");
|
||||
REG_A[5] = load_value("A5");
|
||||
REG_A[6] = load_value("A6");
|
||||
REG_A[7] = load_value("A7");
|
||||
REG_USP = load_value("USP");
|
||||
REG_ISP = load_value("ISP");
|
||||
REG_MSP = load_value("MSP");
|
||||
REG_VBR = load_value("VBR");
|
||||
REG_SFC = load_value("SFC");
|
||||
REG_DFC = load_value("DFC");
|
||||
REG_CACR = load_value("CACR");
|
||||
REG_CAAR = load_value("CAAR");
|
||||
CPU_INT_LEVEL = load_value("INT_LEVEL");
|
||||
CPU_INT_CYCLES = load_value("INT_CYCLES");
|
||||
|
||||
CPU_STOPPED = 0;
|
||||
temp = load_value("STOPPED");
|
||||
if(temp) CPU_STOPPED |= STOP_LEVEL_STOP;
|
||||
temp = load_value("HALTED");
|
||||
if(temp) CPU_STOPPED |= STOP_LEVEL_HALT;
|
||||
|
||||
CPU_PREF_ADDR = load_value("PREF_ADDR");
|
||||
CPU_PREF_DATA = load_value("PREF_DATA");
|
||||
}
|
||||
|
||||
void m68k_state_register(const char *type, int index)
|
||||
{
|
||||
/* Note, D covers A because the dar array is common, REG_A=REG_D+8 */
|
||||
state_save_register_item_array(type, index, REG_D);
|
||||
state_save_register_item(type, index, REG_PPC);
|
||||
state_save_register_item(type, index, REG_PC);
|
||||
state_save_register_item(type, index, REG_USP);
|
||||
state_save_register_item(type, index, REG_ISP);
|
||||
state_save_register_item(type, index, REG_MSP);
|
||||
state_save_register_item(type, index, REG_VBR);
|
||||
state_save_register_item(type, index, REG_SFC);
|
||||
state_save_register_item(type, index, REG_DFC);
|
||||
state_save_register_item(type, index, REG_CACR);
|
||||
state_save_register_item(type, index, REG_CAAR);
|
||||
state_save_register_item(type, index, m68k_substate.sr);
|
||||
state_save_register_item(type, index, CPU_INT_LEVEL);
|
||||
state_save_register_item(type, index, CPU_INT_CYCLES);
|
||||
state_save_register_item(type, index, m68k_substate.stopped);
|
||||
state_save_register_item(type, index, m68k_substate.halted);
|
||||
state_save_register_item(type, index, CPU_PREF_ADDR);
|
||||
state_save_register_item(type, index, CPU_PREF_DATA);
|
||||
state_save_register_func_presave(m68k_prepare_substate);
|
||||
state_save_register_func_postload(m68k_post_load);
|
||||
}
|
||||
|
||||
#endif /* M68K_COMPILE_FOR_MAME */
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== END OF FILE ============================= */
|
||||
|
@ -4,16 +4,16 @@
|
||||
/* ======================================================================== */
|
||||
/*
|
||||
* MUSASHI
|
||||
* Version 3.3
|
||||
* Version 3.32
|
||||
*
|
||||
* A portable Motorola M680x0 processor emulation engine.
|
||||
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
|
||||
* Copyright Karl Stenerud. All rights reserved.
|
||||
*
|
||||
* This code may be freely used for non-commercial purposes as long as this
|
||||
* copyright notice remains unaltered in the source code and any binary files
|
||||
* containing this code in compiled form.
|
||||
*
|
||||
* All other lisencing terms must be negotiated with the author
|
||||
* All other licensing terms must be negotiated with the author
|
||||
* (Karl Stenerud).
|
||||
*
|
||||
* The latest version of this code can be obtained at:
|
||||
@ -40,6 +40,8 @@
|
||||
/* Check for > 32bit sizes */
|
||||
#if UINT_MAX > 0xffffffff
|
||||
#define M68K_INT_GT_32_BIT 1
|
||||
#else
|
||||
#define M68K_INT_GT_32_BIT 0
|
||||
#endif
|
||||
|
||||
/* Data types used in this emulation core */
|
||||
@ -56,10 +58,10 @@
|
||||
|
||||
#define sint8 signed char /* ASG: changed from char to signed char */
|
||||
#define sint16 signed short
|
||||
#define sint32 signed long
|
||||
#define sint32 signed int /* AWJ: changed from long to int */
|
||||
#define uint8 unsigned char
|
||||
#define uint16 unsigned short
|
||||
#define uint32 unsigned long
|
||||
#define uint32 unsigned int /* AWJ: changed from long to int */
|
||||
|
||||
/* signed and unsigned int must be at least 32 bits wide */
|
||||
#define sint signed int
|
||||
@ -107,7 +109,7 @@
|
||||
|
||||
|
||||
/* Allow for architectures that don't have 32-bit sizes */
|
||||
#if ULONG_MAX == 0xffffffff
|
||||
#if UINT_MAX == 0xffffffff
|
||||
#define MAKE_INT_32(A) (sint32)(A)
|
||||
#else
|
||||
#undef sint32
|
||||
@ -118,7 +120,7 @@
|
||||
{
|
||||
return (value & 0x80000000) ? value | ~0xffffffff : value & 0xffffffff;
|
||||
}
|
||||
#endif /* ULONG_MAX == 0xffffffff */
|
||||
#endif /* UINT_MAX == 0xffffffff */
|
||||
|
||||
|
||||
|
||||
@ -153,14 +155,25 @@
|
||||
|
||||
/* CPU types for deciding what to emulate */
|
||||
#define CPU_TYPE_000 1
|
||||
#define CPU_TYPE_010 2
|
||||
#define CPU_TYPE_EC020 4
|
||||
#define CPU_TYPE_020 8
|
||||
#define CPU_TYPE_008 2
|
||||
#define CPU_TYPE_010 4
|
||||
#define CPU_TYPE_EC020 8
|
||||
#define CPU_TYPE_020 16
|
||||
#define CPU_TYPE_040 32
|
||||
|
||||
/* Different ways to stop the CPU */
|
||||
#define STOP_LEVEL_STOP 1
|
||||
#define STOP_LEVEL_HALT 2
|
||||
|
||||
/* Used for 68000 address error processing */
|
||||
#define INSTRUCTION_YES 0
|
||||
#define INSTRUCTION_NO 0x08
|
||||
#define MODE_READ 0x10
|
||||
#define MODE_WRITE 0
|
||||
|
||||
#define RUN_MODE_NORMAL 0
|
||||
#define RUN_MODE_BERR_AERR_RESET 1
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void*)0)
|
||||
#endif
|
||||
@ -229,13 +242,13 @@
|
||||
#define MASK_OUT_BELOW_16(A) ((A) & ~0xffff)
|
||||
|
||||
/* No need to mask if we are 32 bit */
|
||||
#if M68K_INT_GT_32BIT || M68K_USE_64_BIT
|
||||
#if M68K_INT_GT_32_BIT || M68K_USE_64_BIT
|
||||
#define MASK_OUT_ABOVE_32(A) ((A) & 0xffffffff)
|
||||
#define MASK_OUT_BELOW_32(A) ((A) & ~0xffffffff)
|
||||
#else
|
||||
#define MASK_OUT_ABOVE_32(A) (A)
|
||||
#define MASK_OUT_BELOW_32(A) 0
|
||||
#endif /* M68K_INT_GT_32BIT || M68K_USE_64_BIT */
|
||||
#endif /* M68K_INT_GT_32_BIT || M68K_USE_64_BIT */
|
||||
|
||||
/* Simulate address lines of 68k family */
|
||||
#define ADDRESS_68K(A) ((A)&CPU_ADDRESS_MASK)
|
||||
@ -246,7 +259,7 @@
|
||||
#define LSR(A, C) ((A) >> (C))
|
||||
|
||||
/* Some > 32-bit optimizations */
|
||||
#if M68K_INT_GT_32BIT
|
||||
#if M68K_INT_GT_32_BIT
|
||||
/* Shift left and right */
|
||||
#define LSR_32(A, C) ((A) >> (C))
|
||||
#define LSL_32(A, C) ((A) << (C))
|
||||
@ -256,7 +269,7 @@
|
||||
*/
|
||||
#define LSR_32(A, C) ((C) < 32 ? (A) >> (C) : 0)
|
||||
#define LSL_32(A, C) ((C) < 32 ? (A) << (C) : 0)
|
||||
#endif /* M68K_INT_GT_32BIT */
|
||||
#endif /* M68K_INT_GT_32_BIT */
|
||||
|
||||
#if M68K_USE_64_BIT
|
||||
#define LSL_32_64(A, C) ((A) << (C))
|
||||
@ -303,6 +316,11 @@
|
||||
#define REG_CAAR m68ki_cpu.caar
|
||||
#define REG_IR m68ki_cpu.ir
|
||||
|
||||
#define REG_FP m68ki_cpu.fpr
|
||||
#define REG_FPCR m68ki_cpu.fpcr
|
||||
#define REG_FPSR m68ki_cpu.fpsr
|
||||
#define REG_FPIAR m68ki_cpu.fpiar
|
||||
|
||||
#define FLAG_T1 m68ki_cpu.t1_flag
|
||||
#define FLAG_T0 m68ki_cpu.t0_flag
|
||||
#define FLAG_S m68ki_cpu.s_flag
|
||||
@ -321,6 +339,8 @@
|
||||
#define CPU_PREF_DATA m68ki_cpu.pref_data
|
||||
#define CPU_ADDRESS_MASK m68ki_cpu.address_mask
|
||||
#define CPU_SR_MASK m68ki_cpu.sr_mask
|
||||
#define CPU_INSTR_MODE m68ki_cpu.instr_mode
|
||||
#define CPU_RUN_MODE m68ki_cpu.run_mode
|
||||
|
||||
#define CYC_INSTRUCTION m68ki_cpu.cyc_instruction
|
||||
#define CYC_EXCEPTION m68ki_cpu.cyc_exception
|
||||
@ -328,7 +348,7 @@
|
||||
#define CYC_BCC_NOTAKE_W m68ki_cpu.cyc_bcc_notake_w
|
||||
#define CYC_DBCC_F_NOEXP m68ki_cpu.cyc_dbcc_f_noexp
|
||||
#define CYC_DBCC_F_EXP m68ki_cpu.cyc_dbcc_f_exp
|
||||
#define CYC_SCC_R_FALSE m68ki_cpu.cyc_scc_r_false
|
||||
#define CYC_SCC_R_TRUE m68ki_cpu.cyc_scc_r_true
|
||||
#define CYC_MOVEM_W m68ki_cpu.cyc_movem_w
|
||||
#define CYC_MOVEM_L m68ki_cpu.cyc_movem_l
|
||||
#define CYC_SHIFT m68ki_cpu.cyc_shift
|
||||
@ -338,6 +358,9 @@
|
||||
#define CALLBACK_INT_ACK m68ki_cpu.int_ack_callback
|
||||
#define CALLBACK_BKPT_ACK m68ki_cpu.bkpt_ack_callback
|
||||
#define CALLBACK_RESET_INSTR m68ki_cpu.reset_instr_callback
|
||||
#define CALLBACK_CMPILD_INSTR m68ki_cpu.cmpild_instr_callback
|
||||
#define CALLBACK_RTE_INSTR m68ki_cpu.rte_instr_callback
|
||||
#define CALLBACK_TAS_INSTR m68ki_cpu.tas_instr_callback
|
||||
#define CALLBACK_PC_CHANGED m68ki_cpu.pc_changed_callback
|
||||
#define CALLBACK_SET_FC m68ki_cpu.set_fc_callback
|
||||
#define CALLBACK_INSTR_HOOK m68ki_cpu.instr_hook_callback
|
||||
@ -349,8 +372,16 @@
|
||||
/* These defines are dependant on the configuration defines in m68kconf.h */
|
||||
|
||||
/* Disable certain comparisons if we're not using all CPU types */
|
||||
#if M68K_EMULATE_040
|
||||
#define CPU_TYPE_IS_040_PLUS(A) ((A) & CPU_TYPE_040)
|
||||
#define CPU_TYPE_IS_040_LESS(A) 1
|
||||
#else
|
||||
#define CPU_TYPE_IS_040_PLUS(A) 0
|
||||
#define CPU_TYPE_IS_040_LESS(A) 1
|
||||
#endif
|
||||
|
||||
#if M68K_EMULATE_020
|
||||
#define CPU_TYPE_IS_020_PLUS(A) ((A) & CPU_TYPE_020)
|
||||
#define CPU_TYPE_IS_020_PLUS(A) ((A) & (CPU_TYPE_020 | CPU_TYPE_040))
|
||||
#define CPU_TYPE_IS_020_LESS(A) 1
|
||||
#else
|
||||
#define CPU_TYPE_IS_020_PLUS(A) 0
|
||||
@ -358,8 +389,8 @@
|
||||
#endif
|
||||
|
||||
#if M68K_EMULATE_EC020
|
||||
#define CPU_TYPE_IS_EC020_PLUS(A) ((A) & (CPU_TYPE_EC020 | CPU_TYPE_020))
|
||||
#define CPU_TYPE_IS_EC020_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_010 | CPU_TYPE_EC020))
|
||||
#define CPU_TYPE_IS_EC020_PLUS(A) ((A) & (CPU_TYPE_EC020 | CPU_TYPE_020 | CPU_TYPE_040))
|
||||
#define CPU_TYPE_IS_EC020_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_008 | CPU_TYPE_010 | CPU_TYPE_EC020))
|
||||
#else
|
||||
#define CPU_TYPE_IS_EC020_PLUS(A) CPU_TYPE_IS_020_PLUS(A)
|
||||
#define CPU_TYPE_IS_EC020_LESS(A) CPU_TYPE_IS_020_LESS(A)
|
||||
@ -367,8 +398,8 @@
|
||||
|
||||
#if M68K_EMULATE_010
|
||||
#define CPU_TYPE_IS_010(A) ((A) == CPU_TYPE_010)
|
||||
#define CPU_TYPE_IS_010_PLUS(A) ((A) & (CPU_TYPE_010 | CPU_TYPE_EC020 | CPU_TYPE_020))
|
||||
#define CPU_TYPE_IS_010_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_010))
|
||||
#define CPU_TYPE_IS_010_PLUS(A) ((A) & (CPU_TYPE_010 | CPU_TYPE_EC020 | CPU_TYPE_020 | CPU_TYPE_040))
|
||||
#define CPU_TYPE_IS_010_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_008 | CPU_TYPE_010))
|
||||
#else
|
||||
#define CPU_TYPE_IS_010(A) 0
|
||||
#define CPU_TYPE_IS_010_PLUS(A) CPU_TYPE_IS_EC020_PLUS(A)
|
||||
@ -381,8 +412,8 @@
|
||||
#define CPU_TYPE_IS_020_VARIANT(A) 0
|
||||
#endif
|
||||
|
||||
#if M68K_EMULATE_020 || M68K_EMULATE_EC020 || M68K_EMULATE_010
|
||||
#define CPU_TYPE_IS_000(A) ((A) == CPU_TYPE_000)
|
||||
#if M68K_EMULATE_040 || M68K_EMULATE_020 || M68K_EMULATE_EC020 || M68K_EMULATE_010
|
||||
#define CPU_TYPE_IS_000(A) ((A) == CPU_TYPE_000 || (A) == CPU_TYPE_008)
|
||||
#else
|
||||
#define CPU_TYPE_IS_000(A) 1
|
||||
#endif
|
||||
@ -430,14 +461,45 @@
|
||||
#define m68ki_output_reset()
|
||||
#endif /* M68K_EMULATE_RESET */
|
||||
|
||||
#if M68K_INSTRUCTION_HOOK
|
||||
#if M68K_INSTRUCTION_HOOK == OPT_SPECIFY_HANDLER
|
||||
#define m68ki_instr_hook() M68K_INSTRUCTION_CALLBACK()
|
||||
#if M68K_CMPILD_HAS_CALLBACK
|
||||
#if M68K_CMPILD_HAS_CALLBACK == OPT_SPECIFY_HANDLER
|
||||
#define m68ki_cmpild_callback(v,r) M68K_CMPILD_CALLBACK(v,r)
|
||||
#else
|
||||
#define m68ki_instr_hook() CALLBACK_INSTR_HOOK()
|
||||
#define m68ki_cmpild_callback(v,r) CALLBACK_CMPILD_INSTR(v,r)
|
||||
#endif
|
||||
#else
|
||||
#define m68ki_instr_hook()
|
||||
#define m68ki_cmpild_callback(v,r)
|
||||
#endif /* M68K_CMPILD_HAS_CALLBACK */
|
||||
|
||||
#if M68K_RTE_HAS_CALLBACK
|
||||
#if M68K_RTE_HAS_CALLBACK == OPT_SPECIFY_HANDLER
|
||||
#define m68ki_rte_callback() M68K_RTE_CALLBACK()
|
||||
#else
|
||||
#define m68ki_rte_callback() CALLBACK_RTE_INSTR()
|
||||
#endif
|
||||
#else
|
||||
#define m68ki_rte_callback()
|
||||
#endif /* M68K_RTE_HAS_CALLBACK */
|
||||
|
||||
#if M68K_TAS_HAS_CALLBACK
|
||||
#if M68K_TAS_HAS_CALLBACK == OPT_SPECIFY_HANDLER
|
||||
#define m68ki_tas_callback() M68K_TAS_CALLBACK()
|
||||
#else
|
||||
#define m68ki_tas_callback() CALLBACK_TAS_INSTR()
|
||||
#endif
|
||||
#else
|
||||
#define m68ki_tas_callback() 0
|
||||
#endif /* M68K_TAS_HAS_CALLBACK */
|
||||
|
||||
|
||||
#if M68K_INSTRUCTION_HOOK
|
||||
#if M68K_INSTRUCTION_HOOK == OPT_SPECIFY_HANDLER
|
||||
#define m68ki_instr_hook(pc) M68K_INSTRUCTION_CALLBACK(pc)
|
||||
#else
|
||||
#define m68ki_instr_hook(pc) CALLBACK_INSTR_HOOK(pc)
|
||||
#endif
|
||||
#else
|
||||
#define m68ki_instr_hook(pc)
|
||||
#endif /* M68K_INSTRUCTION_HOOK */
|
||||
|
||||
#if M68K_MONITOR_PC
|
||||
@ -490,19 +552,47 @@
|
||||
|
||||
/* Address error */
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
extern jmp_buf m68ki_address_error_trap;
|
||||
#define m68ki_set_address_error_trap() if(setjmp(m68ki_address_error_trap)) m68ki_exception_address_error();
|
||||
#define m68ki_check_address_error(A) if((A)&1) longjmp(m68ki_address_error_jump, 1);
|
||||
#include <setjmp.h>
|
||||
extern jmp_buf m68ki_aerr_trap;
|
||||
extern int emulate_address_error;
|
||||
|
||||
#define m68ki_set_address_error_trap() \
|
||||
if(setjmp(m68ki_aerr_trap) != 0) \
|
||||
{ \
|
||||
m68ki_exception_address_error(); \
|
||||
if(CPU_STOPPED) \
|
||||
{ \
|
||||
SET_CYCLES(0); \
|
||||
CPU_INT_CYCLES = 0; \
|
||||
return m68ki_initial_cycles; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define m68ki_check_address_error(ADDR, WRITE_MODE, FC) \
|
||||
if(((ADDR)&1) && emulate_address_error)\
|
||||
{ \
|
||||
m68ki_aerr_address = ADDR; \
|
||||
m68ki_aerr_write_mode = WRITE_MODE; \
|
||||
m68ki_aerr_fc = FC; \
|
||||
longjmp(m68ki_aerr_trap, 1); \
|
||||
}
|
||||
|
||||
#define m68ki_check_address_error_010_less(ADDR, WRITE_MODE, FC) \
|
||||
if (CPU_TYPE_IS_010_LESS(CPU_TYPE)) \
|
||||
{ \
|
||||
m68ki_check_address_error(ADDR, WRITE_MODE, FC) \
|
||||
}
|
||||
#else
|
||||
#define m68ki_set_address_error_trap()
|
||||
#define m68ki_check_address_error(A)
|
||||
#define m68ki_check_address_error(ADDR, WRITE_MODE, FC)
|
||||
#define m68ki_check_address_error_010_less(ADDR, WRITE_MODE, FC)
|
||||
#endif /* M68K_ADDRESS_ERROR */
|
||||
|
||||
/* Logging */
|
||||
#if M68K_LOG_ENABLE
|
||||
#include <stdio.h>
|
||||
extern FILE* M68K_LOG_FILEHANDLE
|
||||
extern char* m68ki_cpu_names[];
|
||||
extern const char *const m68ki_cpu_names[];
|
||||
|
||||
#define M68K_DO_LOG(A) if(M68K_LOG_FILEHANDLE) fprintf A
|
||||
#if M68K_LOG_1010_1111
|
||||
@ -721,6 +811,12 @@
|
||||
#define m68ki_write_16(A, V) m68ki_write_16_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA, V)
|
||||
#define m68ki_write_32(A, V) m68ki_write_32_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA, V)
|
||||
|
||||
#if M68K_SIMULATE_PD_WRITES
|
||||
#define m68ki_write_32_pd(A, V) m68ki_write_32_pd_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA, V)
|
||||
#else
|
||||
#define m68ki_write_32_pd(A, V) m68ki_write_32_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA, V)
|
||||
#endif
|
||||
|
||||
/* map read immediate 8 to read immediate 16 */
|
||||
#define m68ki_read_imm_8() MASK_OUT_ABOVE_8(m68ki_read_imm_16())
|
||||
|
||||
@ -745,9 +841,15 @@
|
||||
/* =============================== PROTOTYPES ============================= */
|
||||
/* ======================================================================== */
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint64 i;
|
||||
double f;
|
||||
} fp_reg;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint cpu_type; /* CPU Type: 68000, 68010, 68EC020, or 68020 */
|
||||
uint cpu_type; /* CPU Type: 68000, 68008, 68010, 68EC020, or 68020 */
|
||||
uint dar[16]; /* Data and Address Registers */
|
||||
uint ppc; /* Previous program counter */
|
||||
uint pc; /* Program Counter */
|
||||
@ -758,6 +860,10 @@ typedef struct
|
||||
uint cacr; /* Cache Control Register (m68020, unemulated) */
|
||||
uint caar; /* Cache Address Register (m68020, unemulated) */
|
||||
uint ir; /* Instruction Register */
|
||||
fp_reg fpr[8]; /* FPU Data Register (m68040) */
|
||||
uint fpiar; /* FPU Instruction Address Register (m68040) */
|
||||
uint fpsr; /* FPU Status Register (m68040) */
|
||||
uint fpcr; /* FPU Control Register (m68040) */
|
||||
uint t1_flag; /* Trace 1 */
|
||||
uint t0_flag; /* Trace 0 */
|
||||
uint s_flag; /* Supervisor */
|
||||
@ -775,27 +881,32 @@ typedef struct
|
||||
uint pref_data; /* Data in the prefetch queue */
|
||||
uint address_mask; /* Available address pins */
|
||||
uint sr_mask; /* Implemented status register bits */
|
||||
uint instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */
|
||||
uint run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */
|
||||
|
||||
/* Clocks required for instructions / exceptions */
|
||||
uint cyc_bcc_notake_b;
|
||||
uint cyc_bcc_notake_w;
|
||||
uint cyc_dbcc_f_noexp;
|
||||
uint cyc_dbcc_f_exp;
|
||||
uint cyc_scc_r_false;
|
||||
uint cyc_scc_r_true;
|
||||
uint cyc_movem_w;
|
||||
uint cyc_movem_l;
|
||||
uint cyc_shift;
|
||||
uint cyc_reset;
|
||||
uint8* cyc_instruction;
|
||||
uint8* cyc_exception;
|
||||
const uint8* cyc_instruction;
|
||||
const uint8* cyc_exception;
|
||||
|
||||
/* Callbacks to host */
|
||||
int (*int_ack_callback)(int int_line); /* Interrupt Acknowledge */
|
||||
void (*bkpt_ack_callback)(unsigned int data); /* Breakpoint Acknowledge */
|
||||
void (*reset_instr_callback)(void); /* Called when a RESET instruction is encountered */
|
||||
void (*cmpild_instr_callback)(unsigned int, int); /* Called when a CMPI.L #v, Dn instruction is encountered */
|
||||
void (*rte_instr_callback)(void); /* Called when a RTE instruction is encountered */
|
||||
int (*tas_instr_callback)(void); /* Called when a TAS instruction is encountered, allows / disallows writeback */
|
||||
void (*pc_changed_callback)(unsigned int new_pc); /* Called when the PC changes by a large amount */
|
||||
void (*set_fc_callback)(unsigned int new_fc); /* Called when the CPU function code changes */
|
||||
void (*instr_hook_callback)(void); /* Called every instruction cycle prior to execution */
|
||||
void (*instr_hook_callback)(unsigned int pc); /* Called every instruction cycle prior to execution */
|
||||
|
||||
} m68ki_cpu_core;
|
||||
|
||||
@ -803,13 +914,16 @@ typedef struct
|
||||
extern m68ki_cpu_core m68ki_cpu;
|
||||
extern sint m68ki_remaining_cycles;
|
||||
extern uint m68ki_tracing;
|
||||
extern uint8 m68ki_shift_8_table[];
|
||||
extern uint16 m68ki_shift_16_table[];
|
||||
extern uint m68ki_shift_32_table[];
|
||||
extern uint8 m68ki_exception_cycle_table[][256];
|
||||
extern const uint8 m68ki_shift_8_table[];
|
||||
extern const uint16 m68ki_shift_16_table[];
|
||||
extern const uint m68ki_shift_32_table[];
|
||||
extern const uint8 m68ki_exception_cycle_table[][256];
|
||||
extern uint m68ki_address_space;
|
||||
extern uint8 m68ki_ea_idx_cycle_table[];
|
||||
extern const uint8 m68ki_ea_idx_cycle_table[];
|
||||
|
||||
extern uint m68ki_aerr_address;
|
||||
extern uint m68ki_aerr_write_mode;
|
||||
extern uint m68ki_aerr_fc;
|
||||
|
||||
/* Read data immediately after the program counter */
|
||||
INLINE uint m68ki_read_imm_16(void);
|
||||
@ -824,6 +938,9 @@ INLINE uint m68ki_read_32_fc (uint address, uint fc);
|
||||
INLINE void m68ki_write_8_fc (uint address, uint fc, uint value);
|
||||
INLINE void m68ki_write_16_fc(uint address, uint fc, uint value);
|
||||
INLINE void m68ki_write_32_fc(uint address, uint fc, uint value);
|
||||
#if M68K_SIMULATE_PD_WRITES
|
||||
INLINE void m68ki_write_32_pd_fc(uint address, uint fc, uint value);
|
||||
#endif /* M68K_SIMULATE_PD_WRITES */
|
||||
|
||||
/* Indexed and PC-relative ea fetching */
|
||||
INLINE uint m68ki_get_ea_pcdi(void);
|
||||
@ -903,7 +1020,7 @@ INLINE void m68ki_set_sr_noint(uint value); /* set the status register
|
||||
INLINE uint m68ki_init_exception(void); /* Initial exception processing */
|
||||
|
||||
INLINE void m68ki_stack_frame_3word(uint pc, uint sr); /* Stack various frame types */
|
||||
INLINE void m68ki_stack_frame_buserr(uint pc, uint sr, uint address, uint write, uint instruction, uint fc);
|
||||
INLINE void m68ki_stack_frame_buserr(uint sr);
|
||||
|
||||
INLINE void m68ki_stack_frame_0000(uint pc, uint sr, uint vector);
|
||||
INLINE void m68ki_stack_frame_0001(uint pc, uint sr, uint vector);
|
||||
@ -941,7 +1058,7 @@ char* m68ki_disassemble_quick(unsigned int pc, unsigned int cpu_type);
|
||||
INLINE uint m68ki_read_imm_16(void)
|
||||
{
|
||||
m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error(REG_PC); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
|
||||
#if M68K_EMULATE_PREFETCH
|
||||
if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR)
|
||||
{
|
||||
@ -961,7 +1078,7 @@ INLINE uint m68ki_read_imm_32(void)
|
||||
uint temp_val;
|
||||
|
||||
m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error(REG_PC); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
|
||||
if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR)
|
||||
{
|
||||
CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC);
|
||||
@ -980,7 +1097,7 @@ INLINE uint m68ki_read_imm_32(void)
|
||||
return temp_val;
|
||||
#else
|
||||
m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error(REG_PC); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
|
||||
REG_PC += 4;
|
||||
return m68k_read_immediate_32(ADDRESS_68K(REG_PC-4));
|
||||
#endif /* M68K_EMULATE_PREFETCH */
|
||||
@ -1004,13 +1121,13 @@ INLINE uint m68ki_read_8_fc(uint address, uint fc)
|
||||
INLINE uint m68ki_read_16_fc(uint address, uint fc)
|
||||
{
|
||||
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error(address); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */
|
||||
return m68k_read_memory_16(ADDRESS_68K(address));
|
||||
}
|
||||
INLINE uint m68ki_read_32_fc(uint address, uint fc)
|
||||
{
|
||||
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error(address); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */
|
||||
return m68k_read_memory_32(ADDRESS_68K(address));
|
||||
}
|
||||
|
||||
@ -1022,16 +1139,24 @@ INLINE void m68ki_write_8_fc(uint address, uint fc, uint value)
|
||||
INLINE void m68ki_write_16_fc(uint address, uint fc, uint value)
|
||||
{
|
||||
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error(address); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */
|
||||
m68k_write_memory_16(ADDRESS_68K(address), value);
|
||||
}
|
||||
INLINE void m68ki_write_32_fc(uint address, uint fc, uint value)
|
||||
{
|
||||
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error(address); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */
|
||||
m68k_write_memory_32(ADDRESS_68K(address), value);
|
||||
}
|
||||
|
||||
#if M68K_SIMULATE_PD_WRITES
|
||||
INLINE void m68ki_write_32_pd_fc(uint address, uint fc, uint value)
|
||||
{
|
||||
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */
|
||||
m68k_write_memory_32_pd(ADDRESS_68K(address), value);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------- Effective Address Calculation -------------------- */
|
||||
@ -1342,6 +1467,14 @@ INLINE void m68ki_set_sm_flag(uint value)
|
||||
REG_SP = REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)];
|
||||
}
|
||||
|
||||
/* Set the S and M flags. Don't touch the stack pointer. */
|
||||
INLINE void m68ki_set_sm_flag_nosp(uint value)
|
||||
{
|
||||
/* Set the S and M flags */
|
||||
FLAG_S = value & SFLAG_SET;
|
||||
FLAG_M = value & MFLAG_SET;
|
||||
}
|
||||
|
||||
|
||||
/* Set the condition code register */
|
||||
INLINE void m68ki_set_ccr(uint value)
|
||||
@ -1367,6 +1500,22 @@ INLINE void m68ki_set_sr_noint(uint value)
|
||||
m68ki_set_sm_flag((value >> 11) & 6);
|
||||
}
|
||||
|
||||
/* Set the status register but don't check for interrupts nor
|
||||
* change the stack pointer
|
||||
*/
|
||||
INLINE void m68ki_set_sr_noint_nosp(uint value)
|
||||
{
|
||||
/* Mask out the "unimplemented" bits */
|
||||
value &= CPU_SR_MASK;
|
||||
|
||||
/* Now set the status register */
|
||||
FLAG_T1 = BIT_F(value);
|
||||
FLAG_T0 = BIT_E(value);
|
||||
FLAG_INT_MASK = value & 0x0700;
|
||||
m68ki_set_ccr(value);
|
||||
m68ki_set_sm_flag_nosp((value >> 11) & 6);
|
||||
}
|
||||
|
||||
/* Set the status register and check for interrupts */
|
||||
INLINE void m68ki_set_sr(uint value)
|
||||
{
|
||||
@ -1405,7 +1554,7 @@ INLINE void m68ki_stack_frame_3word(uint pc, uint sr)
|
||||
INLINE void m68ki_stack_frame_0000(uint pc, uint sr, uint vector)
|
||||
{
|
||||
/* Stack a 3-word frame if we are 68000 */
|
||||
if(CPU_TYPE == CPU_TYPE_000)
|
||||
if(CPU_TYPE == CPU_TYPE_000 || CPU_TYPE == CPU_TYPE_008)
|
||||
{
|
||||
m68ki_stack_frame_3word(pc, sr);
|
||||
return;
|
||||
@ -1439,18 +1588,18 @@ INLINE void m68ki_stack_frame_0010(uint sr, uint vector)
|
||||
|
||||
/* Bus error stack frame (68000 only).
|
||||
*/
|
||||
INLINE void m68ki_stack_frame_buserr(uint pc, uint sr, uint address, uint write, uint instruction, uint fc)
|
||||
INLINE void m68ki_stack_frame_buserr(uint sr)
|
||||
{
|
||||
m68ki_push_32(pc);
|
||||
m68ki_push_32(REG_PC);
|
||||
m68ki_push_16(sr);
|
||||
m68ki_push_16(REG_IR);
|
||||
m68ki_push_32(address); /* access address */
|
||||
m68ki_push_32(m68ki_aerr_address); /* access address */
|
||||
/* 0 0 0 0 0 0 0 0 0 0 0 R/W I/N FC
|
||||
* R/W 0 = write, 1 = read
|
||||
* I/N 0 = instruction, 1 = not
|
||||
* FC 3-bit function code
|
||||
*/
|
||||
m68ki_push_16(((!write)<<4) | ((!instruction)<<3) | fc);
|
||||
m68ki_push_16(m68ki_aerr_write_mode | CPU_INSTR_MODE | m68ki_aerr_fc);
|
||||
}
|
||||
|
||||
/* Format 8 stack frame (68010).
|
||||
@ -1660,7 +1809,15 @@ INLINE void m68ki_exception_trace(void)
|
||||
uint sr = m68ki_init_exception();
|
||||
|
||||
if(CPU_TYPE_IS_010_LESS(CPU_TYPE))
|
||||
{
|
||||
#if M68K_EMULATE_ADDRESS_ERROR == OPT_ON
|
||||
if(CPU_TYPE_IS_000(CPU_TYPE))
|
||||
{
|
||||
CPU_INSTR_MODE = INSTRUCTION_NO;
|
||||
}
|
||||
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
||||
m68ki_stack_frame_0000(REG_PC, sr, EXCEPTION_TRACE);
|
||||
}
|
||||
else
|
||||
m68ki_stack_frame_0010(sr, EXCEPTION_TRACE);
|
||||
|
||||
@ -1677,7 +1834,15 @@ INLINE void m68ki_exception_trace(void)
|
||||
INLINE void m68ki_exception_privilege_violation(void)
|
||||
{
|
||||
uint sr = m68ki_init_exception();
|
||||
m68ki_stack_frame_0000(REG_PC, sr, EXCEPTION_PRIVILEGE_VIOLATION);
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR == OPT_ON
|
||||
if(CPU_TYPE_IS_000(CPU_TYPE))
|
||||
{
|
||||
CPU_INSTR_MODE = INSTRUCTION_NO;
|
||||
}
|
||||
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
||||
|
||||
m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_PRIVILEGE_VIOLATION);
|
||||
m68ki_jump_vector(EXCEPTION_PRIVILEGE_VIOLATION);
|
||||
|
||||
/* Use up some clock cycles and undo the instruction's cycles */
|
||||
@ -1695,7 +1860,7 @@ INLINE void m68ki_exception_1010(void)
|
||||
#endif
|
||||
|
||||
sr = m68ki_init_exception();
|
||||
m68ki_stack_frame_0000(REG_PC-2, sr, EXCEPTION_1010);
|
||||
m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_1010);
|
||||
m68ki_jump_vector(EXCEPTION_1010);
|
||||
|
||||
/* Use up some clock cycles and undo the instruction's cycles */
|
||||
@ -1714,7 +1879,7 @@ INLINE void m68ki_exception_1111(void)
|
||||
#endif
|
||||
|
||||
sr = m68ki_init_exception();
|
||||
m68ki_stack_frame_0000(REG_PC-2, sr, EXCEPTION_1111);
|
||||
m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_1111);
|
||||
m68ki_jump_vector(EXCEPTION_1111);
|
||||
|
||||
/* Use up some clock cycles and undo the instruction's cycles */
|
||||
@ -1731,7 +1896,15 @@ INLINE void m68ki_exception_illegal(void)
|
||||
m68ki_disassemble_quick(ADDRESS_68K(REG_PPC))));
|
||||
|
||||
sr = m68ki_init_exception();
|
||||
m68ki_stack_frame_0000(REG_PC, sr, EXCEPTION_ILLEGAL_INSTRUCTION);
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR == OPT_ON
|
||||
if(CPU_TYPE_IS_000(CPU_TYPE))
|
||||
{
|
||||
CPU_INSTR_MODE = INSTRUCTION_NO;
|
||||
}
|
||||
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
||||
|
||||
m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_ILLEGAL_INSTRUCTION);
|
||||
m68ki_jump_vector(EXCEPTION_ILLEGAL_INSTRUCTION);
|
||||
|
||||
/* Use up some clock cycles and undo the instruction's cycles */
|
||||
@ -1752,7 +1925,27 @@ INLINE void m68ki_exception_format_error(void)
|
||||
/* Exception for address error */
|
||||
INLINE void m68ki_exception_address_error(void)
|
||||
{
|
||||
/* Not emulated yet */
|
||||
uint sr = m68ki_init_exception();
|
||||
|
||||
/* If we were processing a bus error, address error, or reset,
|
||||
* this is a catastrophic failure.
|
||||
* Halt the CPU
|
||||
*/
|
||||
if(CPU_RUN_MODE == RUN_MODE_BERR_AERR_RESET)
|
||||
{
|
||||
m68k_read_memory_8(0x00ffff01);
|
||||
CPU_STOPPED = STOP_LEVEL_HALT;
|
||||
return;
|
||||
}
|
||||
CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET;
|
||||
|
||||
/* Note: This is implemented for 68000 only! */
|
||||
m68ki_stack_frame_buserr(sr);
|
||||
|
||||
m68ki_jump_vector(EXCEPTION_ADDRESS_ERROR);
|
||||
|
||||
/* Use up some clock cycles and undo the instruction's cycles */
|
||||
USE_CYCLES(CYC_EXCEPTION[EXCEPTION_ADDRESS_ERROR] - CYC_INSTRUCTION[REG_IR]);
|
||||
}
|
||||
|
||||
|
||||
@ -1763,11 +1956,19 @@ void m68ki_exception_interrupt(uint int_level)
|
||||
uint sr;
|
||||
uint new_pc;
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR == OPT_ON
|
||||
if(CPU_TYPE_IS_000(CPU_TYPE))
|
||||
{
|
||||
CPU_INSTR_MODE = INSTRUCTION_NO;
|
||||
}
|
||||
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
||||
|
||||
/* Turn off the stopped state */
|
||||
CPU_STOPPED &= ~STOP_LEVEL_STOP;
|
||||
|
||||
/* If we are halted, don't do anything */
|
||||
if(CPU_STOPPED) return;
|
||||
if(CPU_STOPPED)
|
||||
return;
|
||||
|
||||
/* Acknowledge the interrupt */
|
||||
vector = m68ki_int_ack(int_level);
|
||||
|
11948
source/m68k/m68kopac.c
11948
source/m68k/m68kopac.c
File diff suppressed because it is too large
Load Diff
13286
source/m68k/m68kopdm.c
13286
source/m68k/m68kopdm.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
38527
source/m68k/m68kops.c
38527
source/m68k/m68kops.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,3 @@
|
||||
|
||||
#ifndef _MACROS_H_
|
||||
#define _MACROS_H_
|
||||
|
||||
|
1207
source/mem68k.c
1207
source/mem68k.c
File diff suppressed because it is too large
Load Diff
@ -1,14 +1,51 @@
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* 68k memory handlers
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef _MEM68K_H_
|
||||
#define _MEM68K_H_
|
||||
|
||||
/* Function prototypes */
|
||||
unsigned int m68k_read_bus_8 (unsigned int address);
|
||||
unsigned int m68k_read_bus_16 (unsigned int address);
|
||||
void m68k_unused_w (unsigned int address, unsigned int value);
|
||||
void m68k_lockup_w_8 (unsigned int address, unsigned int value);
|
||||
void m68k_lockup_w_16 (unsigned int address, unsigned int value);
|
||||
unsigned int m68k_lockup_r_8 (unsigned int address);
|
||||
unsigned int m68k_lockup_r_16 (unsigned int address);
|
||||
enum {
|
||||
SRAM,
|
||||
EEPROM,
|
||||
J_CART,
|
||||
SVP_DRAM,
|
||||
SVP_CELL,
|
||||
CART_HW,
|
||||
REALTEC_ROM,
|
||||
VDP,
|
||||
SYSTEM_IO,
|
||||
UNUSED,
|
||||
ILLEGAL,
|
||||
WRAM,
|
||||
UMK3_HACK,
|
||||
PICO_HW,
|
||||
ROM
|
||||
};
|
||||
|
||||
extern uint8 m68k_readmap_8[32];
|
||||
extern uint8 m68k_readmap_16[32];
|
||||
extern uint8 m68k_writemap_8[32];
|
||||
extern uint8 m68k_writemap_16[32];
|
||||
|
||||
|
||||
#endif /* _MEM68K_H_ */
|
||||
|
550
source/membnk.c
550
source/membnk.c
@ -1,139 +1,77 @@
|
||||
/*
|
||||
membnk.c --
|
||||
Memory handlers Z80 access to the banked V-bus address space.
|
||||
*/
|
||||
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* M68k Bank access from Z80
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
#include "shared.h"
|
||||
|
||||
|
||||
void z80_write_banked_memory(unsigned int address, unsigned int data)
|
||||
/*
|
||||
Handlers for access to unused addresses and those which make the
|
||||
machine lock up.
|
||||
*/
|
||||
static inline void z80bank_unused_w(unsigned int address, unsigned int data)
|
||||
{
|
||||
switch((address >> 21) & 7)
|
||||
{
|
||||
case 0: /* Cartridge ROM */
|
||||
case 1:
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 2: /* Unused */
|
||||
case 3:
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 4: /* Unused (lockup) */
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
|
||||
case 5: /* Z80, I/O chip, etc. */
|
||||
if(address <= 0xA0FFFF)
|
||||
{
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch((address >> 8) & 0xFF)
|
||||
{
|
||||
case 0x00: /* I/O chip */
|
||||
if(address <= 0xA1001F) io_write((address >> 1) & 0x0F, data);
|
||||
else z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x11: /* /BUSREQ */
|
||||
if (address & 1) z80bank_unused_w (address, data);
|
||||
else gen_busreq_w (data & 1);
|
||||
return;
|
||||
|
||||
case 0x12: /* /RESET (w) */
|
||||
if (address & 1) z80bank_unused_w (address, data);
|
||||
else gen_reset_w (data & 1);
|
||||
return;
|
||||
|
||||
case 0x10: /* MEMORY MODE */
|
||||
case 0x13: /* TIME */
|
||||
case 0x20: /* ? */
|
||||
case 0x30: /* ? */
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
default: /* Invalid */
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
case 6: /* VDP */
|
||||
z80bank_vdp_w(address, data);
|
||||
return;
|
||||
|
||||
case 7: /* Work RAM */
|
||||
WRITE_BYTE(work_ram, address & 0xFFFF, data);
|
||||
return;
|
||||
}
|
||||
#ifdef LOGERROR
|
||||
error("Z80 bank unused write %06X = %02X\n", address, data);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int z80_read_banked_memory(unsigned int address)
|
||||
static inline unsigned int z80bank_unused_r(unsigned int address)
|
||||
{
|
||||
switch((address >> 21) & 7)
|
||||
{
|
||||
case 0: /* Cartridge ROM */
|
||||
case 1:
|
||||
return READ_BYTE(cart_rom, address);
|
||||
|
||||
case 2: /* Unused */
|
||||
case 3:
|
||||
return z80bank_unused_r(address);
|
||||
|
||||
case 4: /* Unused (lockup) */
|
||||
return z80bank_lockup_r(address);
|
||||
|
||||
case 5: /* Z80, I/O chip, etc.*/
|
||||
if (address <= 0xA0FFFF) return z80bank_lockup_r (address);
|
||||
else
|
||||
{
|
||||
switch((address >> 8) & 0xFF)
|
||||
{
|
||||
case 0x00: /* I/O chip */
|
||||
if (address <= 0xA1001F) return io_read((address >> 1) & 0x0F);
|
||||
else return z80bank_unused_r (address);
|
||||
break;
|
||||
|
||||
case 0x11: /* /BUSACK from Z80 */
|
||||
/* The Z80 can't read this bit (it would be halted
|
||||
when the bit was zero) so we always return '1'. */
|
||||
return 0xFF;
|
||||
|
||||
case 0x10: /* Unused */
|
||||
case 0x12: /* Unused */
|
||||
case 0x13: /* /TIME region */
|
||||
case 0x20: /* Unused */
|
||||
case 0x30: /* Unused */
|
||||
return z80bank_unused_r(address);
|
||||
|
||||
default: /* Lockup */
|
||||
return z80bank_lockup_r(address);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 6: /* VDP */
|
||||
return z80bank_vdp_r(address);
|
||||
|
||||
case 7: /* Work RAM - can't be read on some Genesis models (!) */
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
return (-1);
|
||||
#ifdef LOGERROR
|
||||
error("Z80 bank unused read %06X\n", address);
|
||||
#endif
|
||||
return (address & 1) ? 0x00 : 0xFF;
|
||||
}
|
||||
|
||||
|
||||
void z80bank_vdp_w(int address, int data)
|
||||
static inline void z80bank_lockup_w(unsigned int address, unsigned int data)
|
||||
{
|
||||
if((address & 0xE700E0) == 0xC00000)
|
||||
#ifdef LOGERROR
|
||||
error("Z80 bank lockup write %06X = %02X\n", address, data);
|
||||
#endif
|
||||
gen_running = config.force_dtack;
|
||||
}
|
||||
|
||||
static inline unsigned int z80bank_lockup_r(unsigned int address)
|
||||
{
|
||||
#ifdef LOGERROR
|
||||
error("Z80 bank lockup read %06X\n", address);
|
||||
#endif
|
||||
gen_running = config.force_dtack;
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
/*
|
||||
Z80 memory handlers
|
||||
*/
|
||||
void z80_write_banked_memory (unsigned int address, unsigned int data)
|
||||
{
|
||||
int offset = address >> 19;
|
||||
|
||||
switch (m68k_writemap_8[offset])
|
||||
{
|
||||
switch(address & 0x1F)
|
||||
case VDP:
|
||||
/* Valid VDP addresses */
|
||||
if (((address >> 16) & 0x07) == 0)
|
||||
{
|
||||
switch (address & 0xff)
|
||||
{
|
||||
case 0x00: /* Data port */
|
||||
case 0x01:
|
||||
@ -149,17 +87,6 @@ void z80bank_vdp_w(int address, int data)
|
||||
vdp_ctrl_w(data << 8 | data);
|
||||
return;
|
||||
|
||||
case 0x08: /* Lockup (HVC) */
|
||||
case 0x09:
|
||||
case 0x0A:
|
||||
case 0x0B:
|
||||
case 0x0C:
|
||||
case 0x0D:
|
||||
case 0x0E:
|
||||
case 0x0F:
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x10: /* Unused */
|
||||
case 0x12:
|
||||
case 0x14:
|
||||
@ -171,126 +98,269 @@ void z80bank_vdp_w(int address, int data)
|
||||
case 0x13:
|
||||
case 0x15:
|
||||
case 0x17:
|
||||
psg_write(1, data);
|
||||
psg_write(0, data);
|
||||
return;
|
||||
|
||||
case 0x18: /* Unused */
|
||||
case 0x19:
|
||||
case 0x1A:
|
||||
case 0x1B:
|
||||
case 0x1a:
|
||||
case 0x1b:
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x1C: /* Test register */
|
||||
case 0x1D:
|
||||
case 0x1E:
|
||||
case 0x1F:
|
||||
case 0x1c: /* Test register */
|
||||
case 0x1d:
|
||||
case 0x1e:
|
||||
case 0x1f:
|
||||
vdp_test_w(data << 8 | data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid VDP address */
|
||||
|
||||
default: /* Invalid address */
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int z80bank_vdp_r(int address)
|
||||
{
|
||||
if((address & 0xE700E0) == 0xC00000)
|
||||
{
|
||||
switch(address & 0x1F)
|
||||
{
|
||||
case 0x00: /* Data */
|
||||
case 0x02:
|
||||
return (vdp_data_r() >> 8) & 0xFF;
|
||||
|
||||
case 0x01: /* Data */
|
||||
case 0x03:
|
||||
return vdp_data_r() & 0xFF;
|
||||
|
||||
case 0x04: /* Control */
|
||||
case 0x06:
|
||||
return (0xFC | (vdp_ctrl_r() >> 8)) & 0xFF;
|
||||
|
||||
case 0x05: /* Control */
|
||||
case 0x07:
|
||||
return vdp_ctrl_r() & 0xFF;
|
||||
|
||||
case 0x08: /* HVC */
|
||||
case 0x0A:
|
||||
case 0x0C:
|
||||
case 0x0E:
|
||||
return (vdp_hvc_r() >> 8) & 0xFF;
|
||||
|
||||
case 0x09: /* HVC */
|
||||
case 0x0B:
|
||||
case 0x0D:
|
||||
case 0x0F:
|
||||
return vdp_hvc_r() & 0xFF;
|
||||
|
||||
case 0x10: /* Lockup */
|
||||
case 0x11:
|
||||
case 0x12:
|
||||
case 0x13:
|
||||
case 0x14:
|
||||
case 0x15:
|
||||
case 0x16:
|
||||
case 0x17:
|
||||
return z80bank_lockup_r(address);
|
||||
|
||||
case 0x18: /* Unused */
|
||||
case 0x19:
|
||||
case 0x1A:
|
||||
case 0x1B:
|
||||
case 0x1C:
|
||||
case 0x1D:
|
||||
case 0x1E:
|
||||
case 0x1F:
|
||||
return (z80bank_unused_r(address) | 0xFF);
|
||||
}
|
||||
|
||||
/* Invalid address */
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
|
||||
|
||||
case SYSTEM_IO:
|
||||
{
|
||||
unsigned int base = address >> 8;
|
||||
|
||||
/* Z80 (access prohibited) */
|
||||
if (base <= 0xa0ff)
|
||||
{
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* CONTROL registers */
|
||||
if (base <= 0xa1ff)
|
||||
{
|
||||
switch (base & 0xff)
|
||||
{
|
||||
case 0x00: /* I/O chip (only gets /LWR) */
|
||||
if ((address & 0xe1) == 0x01) io_write((address >> 1) & 0x0f, data);
|
||||
else z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x11: /* BUSREQ */
|
||||
if (address & 1) z80bank_unused_w(address, data);
|
||||
else gen_busreq_w(data & 1);
|
||||
return;
|
||||
|
||||
case 0x12: /* RESET */
|
||||
if (address & 1) z80bank_unused_w(address, data);
|
||||
else gen_reset_w(data & 1);
|
||||
return;
|
||||
|
||||
case 0x30: /* TIME */
|
||||
if (cart_hw.time_w) return cart_hw.time_w(address, data);
|
||||
else z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x41: /* BOOTROM */
|
||||
if (address & 1)
|
||||
{
|
||||
if (data & 1)
|
||||
{
|
||||
rom_readmap[0] = &cart_rom[0];
|
||||
rom_size = genromsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid VDP address */
|
||||
rom_readmap[0] = &bios_rom[0];
|
||||
rom_size = 0x800;
|
||||
}
|
||||
|
||||
if (!(config.bios_enabled & 2))
|
||||
{
|
||||
config.bios_enabled |= 2;
|
||||
memcpy(bios_rom, cart_rom, 0x800);
|
||||
memset(cart_rom, 0, 0x500000);
|
||||
}
|
||||
}
|
||||
else z80bank_unused_w (address, data);
|
||||
return;
|
||||
|
||||
case 0x10: /* MEMORY MODE */
|
||||
case 0x20: /* MEGA-CD */
|
||||
case 0x40: /* TMSS */
|
||||
case 0x44: /* RADICA */
|
||||
case 0x50: /* SVP REGISTERS */
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
default: /* Invalid address */
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalid address */
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
}
|
||||
|
||||
case ROM:
|
||||
WRITE_BYTE(rom_readmap[offset], address & 0x7ffff, data);
|
||||
return;
|
||||
|
||||
case SRAM:
|
||||
if (address <= sram.end) WRITE_BYTE(sram.sram, address - sram.start, data);
|
||||
else z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case EEPROM:
|
||||
if ((address == eeprom.type.sda_in_adr) || (address == eeprom.type.scl_adr)) eeprom_write(address, data);
|
||||
else z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case CART_HW:
|
||||
cart_hw.regs_w(address, data);
|
||||
return;
|
||||
|
||||
case UNUSED:
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case ILLEGAL:
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
|
||||
default: /* WRAM */
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int z80_read_banked_memory(unsigned int address)
|
||||
{
|
||||
int offset = address >> 19;
|
||||
|
||||
switch (m68k_readmap_8[offset])
|
||||
{
|
||||
case WRAM: /* NOTE: can't be read on some Genesis models (!)*/
|
||||
return z80bank_unused_r(address) | 0xff;
|
||||
|
||||
case SYSTEM_IO:
|
||||
{
|
||||
unsigned int base = address >> 8;
|
||||
|
||||
/* Z80 (access prohibited) */
|
||||
if (base <= 0xa0ff) return z80bank_lockup_r(address);
|
||||
|
||||
/* I/O & CONTROL registers */
|
||||
if (base <= 0xa1ff)
|
||||
{
|
||||
switch (base & 0xff)
|
||||
{
|
||||
case 0x00: /* I/O chip */
|
||||
if (address & 0xe0) return z80bank_unused_r(address);
|
||||
return (io_read((address >> 1) & 0x0f));
|
||||
|
||||
case 0x11: /* BUSACK */
|
||||
if (address & 0x01) return 0xff;
|
||||
else return (zbusack | 0xfe);
|
||||
|
||||
case 0x30: /* TIME */
|
||||
if (cart_hw.time_r) return cart_hw.time_r(address);
|
||||
else z80bank_unused_r(address);
|
||||
|
||||
case 0x10: /* MEMORY MODE */
|
||||
case 0x12: /* RESET */
|
||||
case 0x20: /* MEGA-CD */
|
||||
case 0x40: /* TMSS */
|
||||
case 0x41: /* BOOTROM */
|
||||
case 0x44: /* RADICA */
|
||||
case 0x50: /* SVP REGISTERS */
|
||||
return z80bank_unused_r(address);
|
||||
|
||||
default: /* Invalid address */
|
||||
return z80bank_lockup_r(address);
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalid address */
|
||||
return z80bank_lockup_r(address);
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Handlers for access to unused addresses and those which make the
|
||||
machine lock up.
|
||||
*/
|
||||
void z80bank_unused_w(int address, int data)
|
||||
{
|
||||
error("Z80 bank unused write %06X = %02X (%04X)\n", address, data, z80_get_reg(Z80_PC));
|
||||
}
|
||||
|
||||
int z80bank_unused_r(int address)
|
||||
{
|
||||
error("Z80 bank unused read %06X (%04X)\n", address, z80_get_reg(Z80_PC));
|
||||
return (address & 1) ? 0x00 : 0xFF;
|
||||
}
|
||||
|
||||
void z80bank_lockup_w(int address, int data)
|
||||
{
|
||||
error("Z80 bank lockup write %06X = %02X (%04X)\n", address, data, z80_get_reg(Z80_PC));
|
||||
gen_running = 0;
|
||||
z80_end_timeslice();
|
||||
}
|
||||
|
||||
int z80bank_lockup_r(int address)
|
||||
{
|
||||
error("Z80 bank lockup read %06X (%04X)\n", address, z80_get_reg(Z80_PC));
|
||||
gen_running = 0;
|
||||
z80_end_timeslice();
|
||||
return 0xFF;
|
||||
case VDP:
|
||||
/* Valid VDP addresses */
|
||||
if (((address >> 16) & 0x07) == 0)
|
||||
{
|
||||
switch (address & 0xff)
|
||||
{
|
||||
case 0x00: /* DATA */
|
||||
case 0x02:
|
||||
return (vdp_data_r() >> 8);
|
||||
|
||||
case 0x01: /* DATA */
|
||||
case 0x03:
|
||||
return (vdp_data_r() & 0xff);
|
||||
|
||||
case 0x04: /* CTRL */
|
||||
case 0x06:
|
||||
return (0xfc | ((vdp_ctrl_r() >> 8) & 3));
|
||||
|
||||
case 0x05: /* CTRL */
|
||||
case 0x07:
|
||||
return (vdp_ctrl_r() & 0xff);
|
||||
|
||||
case 0x08: /* HVC */
|
||||
case 0x0a:
|
||||
case 0x0c:
|
||||
case 0x0e:
|
||||
return (vdp_hvc_r() >> 8);
|
||||
|
||||
case 0x09: /* HVC */
|
||||
case 0x0b:
|
||||
case 0x0d:
|
||||
case 0x0f:
|
||||
return (vdp_hvc_r() & 0xff);
|
||||
|
||||
case 0x18: /* Unused */
|
||||
case 0x19:
|
||||
case 0x1a:
|
||||
case 0x1b:
|
||||
case 0x1c:
|
||||
case 0x1d:
|
||||
case 0x1e:
|
||||
case 0x1f:
|
||||
return (z80bank_unused_r(address) | 0xff);
|
||||
|
||||
default: /* Invalid address */
|
||||
return z80bank_lockup_r(address);
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalid address */
|
||||
return (z80bank_lockup_r (address));
|
||||
|
||||
case SRAM:
|
||||
if (address <= sram.end) return READ_BYTE(sram.sram, address - sram.start);
|
||||
return READ_BYTE(rom_readmap[offset], address & 0x7ffff);
|
||||
|
||||
case EEPROM:
|
||||
if (address == eeprom.type.sda_out_adr) return eeprom_read(address);
|
||||
return READ_BYTE(rom_readmap[offset], address & 0x7ffff);
|
||||
|
||||
case CART_HW:
|
||||
return cart_hw.regs_r(address);
|
||||
|
||||
case UNUSED:
|
||||
return z80bank_unused_r(address);
|
||||
|
||||
case ILLEGAL:
|
||||
return z80bank_lockup_r(address);
|
||||
|
||||
case UMK3_HACK:
|
||||
return READ_BYTE(&cart_rom[offset<<19], address & 0x7ffff);
|
||||
|
||||
default: /* ROM */
|
||||
return READ_BYTE(rom_readmap[offset], address & 0x7ffff);
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,30 @@
|
||||
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* M68k Bank access from Z80
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
#ifndef _MEMBNK_H_
|
||||
#define _MEMBNK_H_
|
||||
|
||||
/* Function prototypes */
|
||||
void z80_write_banked_memory (unsigned int address, unsigned int data);
|
||||
int z80_read_banked_memory (unsigned int address);
|
||||
void z80bank_vdp_w (int address, int data);
|
||||
int z80bank_vdp_r (int address);
|
||||
void z80bank_unused_w (int address, int data);
|
||||
int z80bank_unused_r (int address);
|
||||
void z80bank_lockup_w (int address, int data);
|
||||
int z80bank_lockup_r (int address);
|
||||
extern void z80_write_banked_memory(unsigned int address, unsigned int data);
|
||||
extern unsigned int z80_read_banked_memory(unsigned int address);
|
||||
|
||||
#endif /* _MEMBNK_H_ */
|
||||
|
@ -1,48 +1,94 @@
|
||||
/*
|
||||
memvdp.c --
|
||||
Memory handlers for when the VDP reads the V-bus during DMA.
|
||||
*/
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* 68k memory from VDP handler
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
unsigned int vdp_dma_r(unsigned int address)
|
||||
{
|
||||
switch((address >> 21) & 7)
|
||||
int offset = address >> 19;
|
||||
|
||||
switch (m68k_readmap_16[offset])
|
||||
{
|
||||
case 0: /* Cartridge ROM */
|
||||
case 1:
|
||||
return *(uint16 *)(cart_rom + address);
|
||||
case ROM:
|
||||
if (svp) address -= 2;
|
||||
return *(uint16 *)(rom_readmap[offset] + (address & 0x7ffff));
|
||||
|
||||
case 2: /* Unused */
|
||||
case 3:
|
||||
return 0xFF00;
|
||||
case UMK3_HACK:
|
||||
return *(uint16 *)(&cart_rom[offset << 19] + (address & 0x7ffff));
|
||||
|
||||
case 4: /* Work RAM */
|
||||
case 6:
|
||||
case 7:
|
||||
return *(uint16 *)(work_ram + (address & 0xffff));
|
||||
case SVP_DRAM:
|
||||
address -= 2;
|
||||
return *(uint16 *)(svp->dram + (address & 0x1fffe));
|
||||
|
||||
case 5: /* Z80 area and I/O chip */
|
||||
/* Z80 area always returns $FFFF */
|
||||
if(address <= 0xA0FFFF)
|
||||
case SVP_CELL:
|
||||
address -= 2;
|
||||
switch (address >> 16)
|
||||
{
|
||||
case 0x39:
|
||||
address >>= 1;
|
||||
address = (address & 0x7001) | ((address & 0x3e) << 6) | ((address & 0xfc0) >> 5);
|
||||
return ((uint16 *)svp->dram)[address];
|
||||
|
||||
case 0x3A:
|
||||
address >>= 1;
|
||||
address = (address & 0x7801) | ((address & 0x1e) << 6) | ((address & 0x7e0) >> 4);
|
||||
return ((uint16 *)svp->dram)[address];
|
||||
|
||||
default:
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
case SYSTEM_IO:
|
||||
/* Z80 area */
|
||||
/* Return $FFFF only when the Z80 isn't hogging the Z-bus.
|
||||
(e.g. Z80 isn't reset and 68000 has the bus) */
|
||||
return (zbusack == 0) ? 0xFFFF : *(uint16 *)(work_ram + (address & 0xffff));
|
||||
}
|
||||
if (address <= 0xa0ffff) return (zbusack ? *(uint16 *)(work_ram + (address & 0xffff)) : 0xffff);
|
||||
|
||||
/* The I/O chip and work RAM try to drive the data bus which
|
||||
results in both values being combined in random ways when read.
|
||||
We return the I/O chip values which seem to have precedence, */
|
||||
else if (address <= 0xA1001F)
|
||||
if (address <= 0xa1001f)
|
||||
{
|
||||
uint8 temp = io_read((address >> 1) & 0x0F);
|
||||
int temp = io_read((address >> 1) & 0x0f);
|
||||
return (temp << 8 | temp);
|
||||
}
|
||||
|
||||
/* All remaining locations access work RAM */
|
||||
else return *(uint16 *)(work_ram + (address & 0xffff));
|
||||
return *(uint16 *)(work_ram + (address & 0xffff));
|
||||
|
||||
case SRAM:
|
||||
if (address <= sram.end) return *(uint16 *)(sram.sram + (address - sram.start));
|
||||
return *(uint16 *)(rom_readmap[address >> 19] + (address & 0x7ffff));
|
||||
|
||||
case EEPROM:
|
||||
if (address == eeprom.type.sda_out_adr) return eeprom_read(address);
|
||||
return *(uint16 *)(rom_readmap[address >> 19] + (address & 0x7ffff));
|
||||
|
||||
case J_CART:
|
||||
if (address == eeprom.type.sda_out_adr) return eeprom_read(address); /* some games also have EEPROM mapped here */
|
||||
else return jcart_read();
|
||||
|
||||
default:
|
||||
return *(uint16 *)(work_ram + (address & 0xffff));
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,29 @@
|
||||
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* 68k memory from VDP handler
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
#ifndef _MEMVDP_H_
|
||||
#define _MEMVDP_H_
|
||||
|
||||
/* Function prototypes */
|
||||
unsigned int vdp_dma_r (unsigned int address);
|
||||
extern unsigned int vdp_dma_r(unsigned int address);
|
||||
|
||||
#endif /* _MEMVDP_H_ */
|
||||
|
285
source/memz80.c
285
source/memz80.c
@ -1,105 +1,97 @@
|
||||
/*
|
||||
memz80.c --
|
||||
Memory handlers for Z80 memory and port access, and the Z80 to
|
||||
VDP interface.
|
||||
*/
|
||||
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* Z80 memory handler
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
#include "shared.h"
|
||||
#define LOG_PORT 0 /* 1= Log Z80 I/O port accesses */
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
|
||||
unsigned int cpu_readmem16(unsigned int address)
|
||||
/*
|
||||
Handlers for access to unused addresses and those which make the
|
||||
machine lock up.
|
||||
*/
|
||||
static inline void z80_unused_w(unsigned int address, unsigned int data)
|
||||
{
|
||||
switch((address >> 13) & 7)
|
||||
{
|
||||
case 0: /* Work RAM */
|
||||
case 1:
|
||||
return zram[address & 0x1FFF];
|
||||
|
||||
case 2: /* YM2612 */
|
||||
return fm_read(address & 3);
|
||||
|
||||
case 3: /* VDP */
|
||||
if ((address & 0xFF00) == 0x7F00) return z80_vdp_r (address);
|
||||
return 0xFF;
|
||||
|
||||
default: /* V-bus bank */
|
||||
return z80_read_banked_memory(zbank | (address & 0x7FFF));
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
#ifdef LOGERROR
|
||||
error("Z80 unused write %04X = %02X\n", address, data);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void cpu_writemem16(unsigned int address, unsigned int data)
|
||||
static inline unsigned int z80_unused_r(unsigned int address)
|
||||
{
|
||||
switch((address >> 13) & 7)
|
||||
{
|
||||
case 0: /* Work RAM */
|
||||
case 1:
|
||||
zram[address & 0x1FFF] = data;
|
||||
return;
|
||||
|
||||
case 2: /* YM2612 */
|
||||
fm_write(1, address & 3, data);
|
||||
return;
|
||||
|
||||
case 3: /* Bank register and VDP */
|
||||
switch(address & 0xFF00)
|
||||
{
|
||||
case 0x6000:
|
||||
gen_bank_w(data & 1);
|
||||
return;
|
||||
|
||||
case 0x7F00:
|
||||
z80_vdp_w(address, data);
|
||||
return;
|
||||
|
||||
default:
|
||||
z80_unused_w(address, data);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
default: /* V-bus bank */
|
||||
z80_write_banked_memory(zbank | (address & 0x7FFF), data);
|
||||
return;
|
||||
}
|
||||
#ifdef LOGERROR
|
||||
error("Z80 unused read %04X\n", address);
|
||||
#endif
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
|
||||
int z80_vdp_r(int address)
|
||||
static inline void z80_lockup_w(unsigned int address, unsigned int data)
|
||||
{
|
||||
switch(address & 0xFF)
|
||||
#ifdef LOGERROR
|
||||
error("Z80 lockup write %04X = %02X\n", address, data);
|
||||
#endif
|
||||
gen_running = config.force_dtack;
|
||||
}
|
||||
|
||||
static inline unsigned int z80_lockup_r(unsigned int address)
|
||||
{
|
||||
#ifdef LOGERROR
|
||||
error("Z80 lockup read %04X\n", address);
|
||||
#endif
|
||||
gen_running = config.force_dtack;
|
||||
return 0xff;
|
||||
}
|
||||
/*
|
||||
VDP access
|
||||
*/
|
||||
static inline unsigned int z80_vdp_r(unsigned int address)
|
||||
{
|
||||
switch (address & 0xff)
|
||||
{
|
||||
case 0x00: /* VDP data port */
|
||||
case 0x02:
|
||||
return (vdp_data_r() >> 8) & 0xFF;
|
||||
return (vdp_data_r() >> 8) & 0xff;
|
||||
|
||||
case 0x01: /* VDP data port */
|
||||
case 0x03:
|
||||
return (vdp_data_r() & 0xFF);
|
||||
return (vdp_data_r() & 0xff);
|
||||
|
||||
case 0x04: /* VDP control port */
|
||||
case 0x06:
|
||||
return (0xFF | ((vdp_ctrl_r() >> 8) & 3));
|
||||
return (0xfc | ((vdp_ctrl_r() >> 8) & 3));
|
||||
|
||||
case 0x05: /* VDP control port */
|
||||
case 0x07:
|
||||
return (vdp_ctrl_r() & 0xFF);
|
||||
return (vdp_ctrl_r() & 0xff);
|
||||
|
||||
case 0x08: /* HV counter */
|
||||
case 0x0A:
|
||||
case 0x0C:
|
||||
case 0x0E:
|
||||
return (vdp_hvc_r() >> 8) & 0xFF;
|
||||
case 0x0a:
|
||||
case 0x0c:
|
||||
case 0x0e:
|
||||
return (vdp_hvc_r() >> 8) & 0xff;
|
||||
|
||||
case 0x09: /* HV counter */
|
||||
case 0x0B:
|
||||
case 0x0D:
|
||||
case 0x0F:
|
||||
return (vdp_hvc_r() & 0xFF);
|
||||
case 0x0b:
|
||||
case 0x0d:
|
||||
case 0x0f:
|
||||
return (vdp_hvc_r() & 0xff);
|
||||
|
||||
case 0x10: /* Unused (PSG) */
|
||||
case 0x11:
|
||||
@ -109,31 +101,28 @@ int z80_vdp_r(int address)
|
||||
case 0x15:
|
||||
case 0x16:
|
||||
case 0x17:
|
||||
return z80_lockup_r(address);
|
||||
return z80_lockup_r (address);
|
||||
|
||||
case 0x18: /* Unused */
|
||||
case 0x19:
|
||||
case 0x1A:
|
||||
case 0x1B:
|
||||
case 0x1a:
|
||||
case 0x1b:
|
||||
return z80_unused_r(address);
|
||||
|
||||
case 0x1C: /* Unused (test register) */
|
||||
case 0x1D:
|
||||
case 0x1E:
|
||||
case 0x1F:
|
||||
case 0x1c: /* Unused (test register) */
|
||||
case 0x1d:
|
||||
case 0x1e:
|
||||
case 0x1f:
|
||||
return z80_unused_r(address);
|
||||
|
||||
default: /* Invalid VDP addresses */
|
||||
return z80_lockup_r(address);
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
|
||||
void z80_vdp_w(int address, int data)
|
||||
static inline void z80_vdp_w(unsigned int address, unsigned int data)
|
||||
{
|
||||
switch(address & 0xFF)
|
||||
switch (address & 0xff)
|
||||
{
|
||||
case 0x00: /* VDP data port */
|
||||
case 0x01:
|
||||
@ -151,12 +140,12 @@ void z80_vdp_w(int address, int data)
|
||||
|
||||
case 0x08: /* Unused (HV counter) */
|
||||
case 0x09:
|
||||
case 0x0A:
|
||||
case 0x0B:
|
||||
case 0x0C:
|
||||
case 0x0D:
|
||||
case 0x0E:
|
||||
case 0x0F:
|
||||
case 0x0a:
|
||||
case 0x0b:
|
||||
case 0x0c:
|
||||
case 0x0d:
|
||||
case 0x0e:
|
||||
case 0x0f:
|
||||
z80_lockup_w(address, data);
|
||||
return;
|
||||
|
||||
@ -173,15 +162,15 @@ void z80_vdp_w(int address, int data)
|
||||
case 0x16:
|
||||
case 0x18:
|
||||
case 0x19:
|
||||
case 0x1A:
|
||||
case 0x1B:
|
||||
case 0x1a:
|
||||
case 0x1b:
|
||||
z80_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x1C: /* Test register */
|
||||
case 0x1D:
|
||||
case 0x1E:
|
||||
case 0x1F:
|
||||
case 0x1c: /* Test register */
|
||||
case 0x1d:
|
||||
case 0x1e:
|
||||
case 0x1f:
|
||||
vdp_test_w(data << 8 | data);
|
||||
return;
|
||||
|
||||
@ -191,6 +180,65 @@ void z80_vdp_w(int address, int data)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Z80 memory handlers
|
||||
*/
|
||||
unsigned int cpu_readmem16(unsigned int address)
|
||||
{
|
||||
switch((address >> 13) & 7)
|
||||
{
|
||||
case 0: /* Work RAM */
|
||||
case 1:
|
||||
return zram[address & 0x1fff];
|
||||
|
||||
case 2: /* YM2612 */
|
||||
return fm_read(1, address & 3);
|
||||
|
||||
case 3: /* VDP */
|
||||
if ((address & 0xff00) == 0x7f00) return z80_vdp_r (address);
|
||||
return (z80_unused_r(address) | 0xff);
|
||||
|
||||
default: /* V-bus bank */
|
||||
return z80_read_banked_memory(zbank | (address & 0x7fff));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cpu_writemem16(unsigned int address, unsigned int data)
|
||||
{
|
||||
switch((address >> 13) & 7)
|
||||
{
|
||||
case 0: /* Work RAM */
|
||||
case 1:
|
||||
zram[address & 0x1fff] = data;
|
||||
return;
|
||||
|
||||
case 2: /* YM2612 */
|
||||
fm_write(1, address & 3, data);
|
||||
return;
|
||||
|
||||
case 3: /* Bank register and VDP */
|
||||
switch(address & 0xff00)
|
||||
{
|
||||
case 0x6000:
|
||||
gen_bank_w(data & 1);
|
||||
return;
|
||||
|
||||
case 0x7f00:
|
||||
z80_vdp_w(address, data);
|
||||
return;
|
||||
|
||||
default:
|
||||
z80_unused_w(address, data);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
default: /* V-bus bank */
|
||||
z80_write_banked_memory(zbank | (address & 0x7fff), data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Port handlers. Ports are unused when not in Mark III compatability mode.
|
||||
@ -202,7 +250,7 @@ void z80_vdp_w(int address, int data)
|
||||
unsigned int cpu_readport16(unsigned int port)
|
||||
{
|
||||
#if LOG_PORT
|
||||
error("Z80 read port %04X (%04X)\n", port, z80_get_reg(Z80_PC));
|
||||
error("Z80 read port %04X\n", port);
|
||||
#endif
|
||||
return 0xFF;
|
||||
}
|
||||
@ -210,37 +258,6 @@ unsigned int cpu_readport16(unsigned int port)
|
||||
void cpu_writeport16(unsigned int port, unsigned int data)
|
||||
{
|
||||
#if LOG_PORT
|
||||
error("Z80 write %02X to port %04X (%04X)\n", data, port, z80_get_reg(Z80_PC));
|
||||
error("Z80 write %02X to port %04X\n", data, port);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Handlers for access to unused addresses and those which make the
|
||||
machine lock up.
|
||||
*/
|
||||
void z80_unused_w(int address, int data)
|
||||
{
|
||||
error("Z80 unused write %04X = %02X (%04X)\n", address, data, z80_get_reg(Z80_PC));
|
||||
}
|
||||
|
||||
int z80_unused_r(int address)
|
||||
{
|
||||
error("Z80 unused read %04X (%04X)\n", address, z80_get_reg(Z80_PC));
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void z80_lockup_w(int address, int data)
|
||||
{
|
||||
error("Z80 lockup write %04X = %02X (%04X)\n", address, data, z80_get_reg(Z80_PC));
|
||||
gen_running = 0;
|
||||
z80_end_timeslice();
|
||||
}
|
||||
|
||||
int z80_lockup_r(int address)
|
||||
{
|
||||
error("Z80 lockup read %04X (%04X)\n", address, z80_get_reg(Z80_PC));
|
||||
gen_running = 0;
|
||||
z80_end_timeslice();
|
||||
return 0xFF;
|
||||
}
|
||||
|
@ -1,17 +1,26 @@
|
||||
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* Z80 memory handler
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
#ifndef _MEMZ80_H_
|
||||
#define _MEMZ80_H_
|
||||
|
||||
/* Function prototypes */
|
||||
unsigned int cpu_readmem16 (unsigned int address);
|
||||
void cpu_writemem16 (unsigned int address, unsigned int data);
|
||||
unsigned int cpu_readport16 (unsigned int port);
|
||||
void cpu_writeport16 (unsigned int port, unsigned int data);
|
||||
void z80_unused_w (int address, int data);
|
||||
int z80_unused_r (int address);
|
||||
void z80_lockup_w (int address, int data);
|
||||
int z80_lockup_r (int address);
|
||||
int z80_vdp_r (int address);
|
||||
void z80_vdp_w (int address, int data);
|
||||
|
||||
#endif /* _MEMZ80_H_ */
|
||||
|
68
source/ngc/config.c
Normal file
68
source/ngc/config.c
Normal file
@ -0,0 +1,68 @@
|
||||
#include "shared.h"
|
||||
#include "font.h"
|
||||
|
||||
#include <fat.h>
|
||||
#include <sys/dir.h>
|
||||
|
||||
t_config config;
|
||||
|
||||
void config_save()
|
||||
{
|
||||
/* first check if directory exist */
|
||||
DIR_ITER *dir = diropen("/genplus");
|
||||
if (dir == NULL) mkdir("/genplus",S_IRWXU);
|
||||
else dirclose(dir);
|
||||
|
||||
/* open file for writing */
|
||||
FILE *fp = fopen("/genplus/genplus.ini", "wb");
|
||||
if (fp == NULL) return;
|
||||
|
||||
/* save options */
|
||||
fwrite(&config, sizeof(config), 1, fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void config_load()
|
||||
{
|
||||
/* open file for writing */
|
||||
FILE *fp = fopen("/genplus/genplus.ini", "rb");
|
||||
if (fp == NULL) return;
|
||||
|
||||
/* read file */
|
||||
fread(&config, sizeof(config), 1, fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void set_config_defaults(void)
|
||||
{
|
||||
/* sound options */
|
||||
config.psg_preamp = 1.5;
|
||||
config.fm_preamp = 1.0;
|
||||
config.boost = 1;
|
||||
config.hq_fm = 1;
|
||||
config.fm_core = 0;
|
||||
config.ssg_enabled = 0;
|
||||
|
||||
/* system options */
|
||||
config.freeze_auto = -1;
|
||||
config.sram_auto = -1;
|
||||
config.region_detect = 0;
|
||||
config.force_dtack = 0;
|
||||
config.bios_enabled = 0;
|
||||
|
||||
/* display options */
|
||||
config.xshift = 0;
|
||||
config.yshift = 0;
|
||||
config.xscale = 0;
|
||||
config.yscale = 0;
|
||||
config.aspect = 1;
|
||||
config.overscan = 1;
|
||||
config.render = (vmode->viTVMode == VI_TVMODE_NTSC_PROG) ? 2 : 0;
|
||||
|
||||
/* controllers options */
|
||||
ogc_input__set_defaults();
|
||||
config.crosshair = 0;
|
||||
}
|
||||
|
42
source/ngc/config.h
Normal file
42
source/ngc/config.h
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
/****************************************************************************
|
||||
* Config Option
|
||||
*
|
||||
****************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
double psg_preamp;
|
||||
double fm_preamp;
|
||||
uint8 boost;
|
||||
uint8 hq_fm;
|
||||
uint8 fm_core;
|
||||
uint8 ssg_enabled;
|
||||
int8 sram_auto;
|
||||
int8 freeze_auto;
|
||||
uint8 region_detect;
|
||||
uint8 force_dtack;
|
||||
uint8 bios_enabled;
|
||||
int16 xshift;
|
||||
int16 yshift;
|
||||
int16 xscale;
|
||||
int16 yscale;
|
||||
uint8 tv_mode;
|
||||
uint8 aspect;
|
||||
uint8 overscan;
|
||||
uint8 render;
|
||||
uint16 pad_keymap[4][MAX_KEYS];
|
||||
uint32 wpad_keymap[4*3][MAX_KEYS];
|
||||
t_input_config input[MAX_DEVICES];
|
||||
uint8 crosshair;
|
||||
} t_config;
|
||||
|
||||
extern t_config config;
|
||||
extern void config_save();
|
||||
extern void config_load();
|
||||
extern void set_config_defaults(void);
|
||||
|
||||
#endif /* _CONFIG_H_ */
|
||||
|
@ -1,26 +1,3 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
#include "shared.h"
|
||||
|
||||
#define ARAMSTART 0x8000
|
||||
|
||||
/**
|
||||
* Nintendo GameCube ARAM Wrapper for libOGC aram.c
|
||||
*
|
||||
@ -29,6 +6,10 @@
|
||||
* Actually, only SSF2TNC needs shadowing, but it's always
|
||||
* Good to know :)
|
||||
*/
|
||||
#include "shared.h"
|
||||
|
||||
#define ARAMSTART 0x8000
|
||||
|
||||
|
||||
#define ARAM_READ 1
|
||||
#define ARAM_WRITE 0
|
||||
@ -81,5 +62,5 @@ ARAMFetch (char *dst, char *src, int len)
|
||||
void
|
||||
ShadowROM ()
|
||||
{
|
||||
ARAMPut (cart_rom, (void *) ARAMSTART, genromsize);
|
||||
ARAMPut ((char *)cart_rom, (void *) ARAMSTART, genromsize);
|
||||
}
|
||||
|
@ -1,22 +1,11 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
/**
|
||||
* Nintendo GameCube ARAM Wrapper for libOGC aram.c
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
* This is an often overlooked area of ~16Mb extra RAM
|
||||
* It's use in Genesis Plus is to shadow the ROM.
|
||||
* Actually, only SSF2TNC needs shadowing, but it's always
|
||||
* Good to know :)
|
||||
*/
|
||||
|
||||
extern void StartARAM ();
|
||||
void ShadowROM ();
|
||||
|
@ -1,208 +0,0 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* NGC - Joypad Configuration
|
||||
***************************************************************************/
|
||||
#include <shared.h>
|
||||
|
||||
extern int domenu (char items[][20], int maxitems);
|
||||
extern unsigned short gcpadmap[];
|
||||
extern int menu;
|
||||
extern char menutitle[];
|
||||
extern int padcal;
|
||||
extern void reloadrom();
|
||||
|
||||
int configpadcount = 11;
|
||||
char padmenu[11][20] = {
|
||||
{"Genesis A - B"},
|
||||
{"Genesis B - A"},
|
||||
{"Genesis C - X"},
|
||||
{"Genesis X - TL"},
|
||||
{"Genesis Y - Y"},
|
||||
{"Genesis Z - TR"},
|
||||
{"Analog - 70"},
|
||||
{"Type - 3BUTTONS"},
|
||||
{"PortA - GAMEPAD"},
|
||||
{"PortB - GAMEPAD"},
|
||||
{" Exit Config "}
|
||||
};
|
||||
|
||||
uint8 mpads[6] = {0, 1, 2, 3, 4, 5 }; /*** Default Mapping ***/
|
||||
uint8 sys_type[2] = {0,0};
|
||||
uint8 old_sys_type[2] = {0,0};
|
||||
|
||||
/****************************************************************************
|
||||
* UpdatePadMaps
|
||||
****************************************************************************/
|
||||
void UpdatePadMaps (uint8 padvalue, int padnum)
|
||||
{
|
||||
padmenu[padnum][15] = ' ';
|
||||
padmenu[padnum][16] = ' ';
|
||||
switch (padvalue)
|
||||
{
|
||||
case 0:
|
||||
gcpadmap[padnum] = PAD_BUTTON_B;
|
||||
padmenu[padnum][16] = 'B';
|
||||
break;
|
||||
|
||||
case 1:
|
||||
gcpadmap[padnum] = PAD_BUTTON_A;
|
||||
padmenu[padnum][16] = 'A';
|
||||
break;
|
||||
|
||||
case 2:
|
||||
gcpadmap[padnum] = PAD_BUTTON_X;
|
||||
padmenu[padnum][16] = 'X';
|
||||
break;
|
||||
|
||||
case 3:
|
||||
gcpadmap[padnum] = PAD_TRIGGER_R;
|
||||
padmenu[padnum][15] = 'T';
|
||||
padmenu[padnum][16] = 'R';
|
||||
break;
|
||||
|
||||
case 4:
|
||||
gcpadmap[padnum] = PAD_BUTTON_Y;
|
||||
padmenu[padnum][16] = 'Y';
|
||||
break;
|
||||
|
||||
case 5:
|
||||
gcpadmap[padnum] = PAD_TRIGGER_L;
|
||||
padmenu[padnum][15] = 'T';
|
||||
padmenu[padnum][16] = 'L';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* ConfigureJoypads
|
||||
****************************************************************************/
|
||||
void ConfigureJoypads ()
|
||||
{
|
||||
int ret;
|
||||
int quit = 0;
|
||||
int prevmenu = menu;
|
||||
|
||||
strcpy (menutitle, "");
|
||||
|
||||
if (pad_type) sprintf (padmenu[7], "Type - 6BUTTONS");
|
||||
else sprintf (padmenu[7], "Type - 3BUTTONS");
|
||||
|
||||
if (input.system[1] == SYSTEM_MENACER) sprintf (padmenu[8], "PortA - NONE");
|
||||
else if (sys_type[0] == 0) sprintf (padmenu[8], "PortA - GAMEPAD");
|
||||
else if (sys_type[0] == 1) sprintf (padmenu[8], "PortA - MULTITAP");
|
||||
else if (sys_type[0] == 2) sprintf (padmenu[8], "PortA - NONE");
|
||||
|
||||
if (input.system[1] == SYSTEM_MENACER) sprintf (padmenu[9], "PortB - MENACER");
|
||||
else if (sys_type[1] == 0) sprintf (padmenu[9], "PortB - GAMEPAD");
|
||||
else if (sys_type[1] == 1) sprintf (padmenu[9], "PortB - MULTITAP");
|
||||
else if (sys_type[1] == 2) sprintf (padmenu[9], "PortB - NONE");
|
||||
|
||||
menu = 0;
|
||||
while (quit == 0)
|
||||
{
|
||||
ret = domenu (&padmenu[0], configpadcount);
|
||||
switch (ret)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
mpads[ret]++;
|
||||
if (mpads[ret] > 5) mpads[ret] = 0;
|
||||
UpdatePadMaps (mpads[ret], ret);
|
||||
break;
|
||||
|
||||
case 6: /*** Pad calibrate analog ***/
|
||||
case -8:
|
||||
if (ret>0) padcal += 2;
|
||||
else padcal -= 2;
|
||||
if (padcal > 90) padcal = 0;
|
||||
if (padcal < 0) padcal = 90;
|
||||
sprintf (padmenu[6], "Analog - %02d", padcal);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
pad_type ^= 1;
|
||||
if (pad_type) sprintf (padmenu[7], "Type - 6BUTTONS");
|
||||
else sprintf (padmenu[7], "Type - 3BUTTONS");
|
||||
system_reset();
|
||||
break;
|
||||
|
||||
case 8:
|
||||
if (input.system[1] == SYSTEM_MENACER) break;
|
||||
sys_type[0] ++;
|
||||
if (sys_type[0] > 2) sys_type[0] = 0;
|
||||
|
||||
if (sys_type[0] == 0)
|
||||
{
|
||||
input.system[0] = SYSTEM_GAMEPAD;
|
||||
sprintf (padmenu[8], "PortA - GAMEPAD");
|
||||
}
|
||||
else if (sys_type[0] == 1)
|
||||
{
|
||||
input.system[0] = SYSTEM_TEAMPLAYER;
|
||||
sprintf (padmenu[8], "PortA - MULTITAP");
|
||||
}
|
||||
else if (sys_type[0] == 2)
|
||||
{
|
||||
input.system[0] = NO_SYSTEM;
|
||||
sprintf (padmenu[8], "PortA - NONE");
|
||||
}
|
||||
break;
|
||||
|
||||
case 9:
|
||||
if (input.system[1] == SYSTEM_MENACER) break;
|
||||
sys_type[1] ++;
|
||||
if (sys_type[1] > 2) sys_type[1] = 0;
|
||||
|
||||
if (sys_type[1] == 0)
|
||||
{
|
||||
input.system[1] = SYSTEM_GAMEPAD;
|
||||
sprintf (padmenu[9], "PortB - GAMEPAD");
|
||||
}
|
||||
else if (sys_type[1] == 1)
|
||||
{
|
||||
input.system[1] = SYSTEM_TEAMPLAYER;
|
||||
sprintf (padmenu[9], "PortB - MULTITAP");
|
||||
}
|
||||
else if (sys_type[1] == 2)
|
||||
{
|
||||
input.system[1] = NO_SYSTEM;
|
||||
sprintf (padmenu[9], "PortB - NONE");
|
||||
}
|
||||
break;
|
||||
|
||||
case 10:
|
||||
case -1:
|
||||
if ((old_sys_type[0] != sys_type[0]) || (old_sys_type[1] != sys_type[1]))
|
||||
{
|
||||
old_sys_type[0] = sys_type[0];
|
||||
old_sys_type[1] = sys_type[1];
|
||||
system_reset();
|
||||
}
|
||||
quit = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
menu = prevmenu;
|
||||
}
|
@ -1,22 +1,4 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Nintendo Gamecube DVD Reading Library
|
||||
*
|
||||
* This is NOT a complete DVD library, in that it works for reading
|
||||
@ -33,46 +15,64 @@
|
||||
* To keep libOGC stable, make sure you call DVD_Init before using
|
||||
* these functions.
|
||||
***************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#ifdef WII_DVD
|
||||
#include "wdvd.h"
|
||||
#endif
|
||||
#include "dvd.h"
|
||||
|
||||
/** DVD I/O Address base **/
|
||||
volatile unsigned long *dvd = (volatile unsigned long *) 0xCC006000;
|
||||
#ifndef HW_RVL
|
||||
static vu32* const dvd = (u32*)0xCC006000;
|
||||
static unsigned char *inquiry=(unsigned char *)0x80000004;
|
||||
#endif
|
||||
|
||||
/** Due to lack of memory, we'll use this little 2k keyhole for all DVD operations **/
|
||||
unsigned char DVDreadbuffer[2048] ATTRIBUTE_ALIGN (32);
|
||||
|
||||
#ifdef HW_RVL
|
||||
u64 DvdMaxOffset = 0x118244F00LL;
|
||||
#else
|
||||
u64 DvdMaxOffset = 0x57057C00; // default
|
||||
#endif
|
||||
|
||||
/***************************************************************************
|
||||
* dvd_read
|
||||
*
|
||||
* Read DVD disc sectors
|
||||
***************************************************************************/
|
||||
extern u8 isWII;
|
||||
|
||||
int dvd_read (void *dst, unsigned int len, u64 offset)
|
||||
{
|
||||
unsigned char *buffer = (unsigned char *) (unsigned int) DVDreadbuffer;
|
||||
#ifndef HW_RVL
|
||||
//unsigned char *buffer = (unsigned char *) (unsigned int) DVDreadbuffer;
|
||||
|
||||
if (len > 2048) return 1; /*** We only allow 2k reads **/
|
||||
DCInvalidateRange((void *)buffer, len);
|
||||
// if (len > 2048) return 1; /*** We only allow 2k reads **/
|
||||
/* DCInvalidateRange((void *)buffer, len);
|
||||
|
||||
if(offset < 0x57057C00 || (isWII == 1 && offset < 0x118244F00LL)) // don't read past the end of the DVD
|
||||
if(offset < DvdMaxOffset)
|
||||
{
|
||||
offset >>= 2;
|
||||
dvd[0] = 0x2E;
|
||||
dvd[1] = 0;
|
||||
dvd[2] = 0xA8000000;
|
||||
dvd[3] = (u32)offset;
|
||||
dvd[3] = (u32)(offset >> 2);
|
||||
dvd[4] = len;
|
||||
dvd[5] = (unsigned long) buffer;
|
||||
dvd[5] = (u32) buffer;
|
||||
dvd[6] = len;
|
||||
dvd[7] = 3; /*** Enable reading with DMA ***/
|
||||
while (dvd[7] & 1);
|
||||
memcpy (dst, buffer, len);
|
||||
}
|
||||
else return 0; // Let's not read past end of DVD
|
||||
dvd[7] = 3; *//*** Enable reading with DMA ***/
|
||||
// while (dvd[7] & 1);
|
||||
// memcpy (dst, buffer, len);
|
||||
// }
|
||||
// else return 1; // Let's not read past end of DVD
|
||||
|
||||
if (dvd[0] & 0x4) return 0; /* Ensure it has completed */
|
||||
// if (dvd[0] & 0x4) return 0; /* Ensure it has completed */
|
||||
if (DVD_LowRead(dst,len,offset,NULL) == 1)
|
||||
return 0;
|
||||
#elif WII_DVD
|
||||
|
||||
if (WDVD_LowUnencryptedRead((unsigned char **)&dst, len, (u32)(offset >> 2)) == 1)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -86,9 +86,14 @@ int dvd_read (void *dst, unsigned int len, u64 offset)
|
||||
*
|
||||
* libOGC tends to foul up if you don't, and sometimes does if you do!
|
||||
****************************************************************************/
|
||||
#ifndef HW_RVL
|
||||
void uselessinquiry ()
|
||||
{
|
||||
dvddrvinfo drive_info;
|
||||
|
||||
DVD_LowInquiry(&drive_info,NULL);
|
||||
|
||||
/*
|
||||
dvd[0] = 0;
|
||||
dvd[1] = 0;
|
||||
dvd[2] = 0x12000000;
|
||||
@ -98,8 +103,9 @@ void uselessinquiry ()
|
||||
dvd[6] = 0x20;
|
||||
dvd[7] = 1;
|
||||
|
||||
while (dvd[7] & 1);
|
||||
while (dvd[7] & 1);*/
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* dvd_motor_off
|
||||
@ -108,8 +114,13 @@ void uselessinquiry ()
|
||||
*
|
||||
* This can be used to prevent the Disc from spinning during playtime
|
||||
****************************************************************************/
|
||||
#ifndef HW_RVL
|
||||
void dvd_motor_off( )
|
||||
{
|
||||
|
||||
DVD_LowStopMotor(NULL);
|
||||
|
||||
/*
|
||||
dvd[0] = 0x2e;
|
||||
dvd[1] = 0;
|
||||
dvd[2] = 0xe3000000;
|
||||
@ -118,23 +129,24 @@ void dvd_motor_off( )
|
||||
dvd[5] = 0;
|
||||
dvd[6] = 0;
|
||||
dvd[7] = 1; // Do immediate
|
||||
while (dvd[7] & 1);
|
||||
while (dvd[7] & 1);*/
|
||||
|
||||
/*** PSO Stops blackscreen at reload ***/
|
||||
dvd[0] = 0x14;
|
||||
dvd[1] = 0;
|
||||
/* dvd[0] = 0x14;
|
||||
dvd[1] = 0;*/
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* dvd_inquiry
|
||||
* dvd_drive_detect()
|
||||
*
|
||||
* Return the Current DVD Drive ID
|
||||
* Detect the DVD Drive Type
|
||||
*
|
||||
* This can be used to determine whereas the console is a Gamecube or a Wii
|
||||
****************************************************************************/
|
||||
int dvd_inquiry()
|
||||
#ifndef HW_RVL
|
||||
void dvd_drive_detect()
|
||||
{
|
||||
dvd[0] = 0x2e;
|
||||
/*dvd[0] = 0x2e;
|
||||
dvd[1] = 0;
|
||||
dvd[2] = 0x12000000;
|
||||
dvd[3] = 0;
|
||||
@ -143,6 +155,24 @@ int dvd_inquiry()
|
||||
dvd[6] = 0x20;
|
||||
dvd[7] = 3;
|
||||
while( dvd[7] & 1 );
|
||||
DCFlushRange((void *)0x80000000, 32);
|
||||
return (int)inquiry[2];
|
||||
DCFlushRange((void *)0x80000000, 32);*/
|
||||
|
||||
dvddrvinfo drive_info;
|
||||
|
||||
DVD_LowInquiry(&drive_info,NULL);
|
||||
|
||||
//int driveid = (int)inquiry[2];
|
||||
int driveid = drive_info.dev_code;
|
||||
|
||||
if ((driveid == 4) || (driveid == 6) || (driveid == 8))
|
||||
{
|
||||
/* Gamecube DVD Drive (1.4 GB)*/
|
||||
DvdMaxOffset = 0x57057C00;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wii DVD Drive (4.7GB) */
|
||||
DvdMaxOffset = 0x118244F00LL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1,24 +1,23 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* Nintendo Gamecube DVD Reading Library
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
* This is NOT a complete DVD library, in that it works for reading
|
||||
* ISO9660 discs only.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* If you need softmod drivecodes etc, look elsewhere.
|
||||
* There are known issues with libogc dvd handling, so these work
|
||||
* outside of it ,if you will.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* This is ideal for using with a gc-linux self booting DVD only.
|
||||
* Go http://www.gc-linux.org for further information and the tools
|
||||
* for your platform.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* To keep libOGC stable, make sure you call DVD_Init before using
|
||||
* these functions.
|
||||
***************************************************************************/
|
||||
|
||||
extern int dvd_read (void *dst, unsigned int len, u64 offset);
|
||||
extern void uselessinquiry ();
|
||||
extern void dvd_motor_off ();
|
||||
extern int dvd_inquiry();
|
||||
extern void dvd_drive_detect();
|
||||
|
||||
|
@ -1,49 +1,71 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* ROM Selection Interface
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
* The following features are implemented:
|
||||
* . SDCARD access with LFN support (through softdev's VFAT library)
|
||||
* . DVD access
|
||||
* . easy subdirectory browsing
|
||||
* . ROM browser
|
||||
* . alphabetical file sorting (Marty Disibio)
|
||||
* . load from history list (Marty Disibio)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* File Selection
|
||||
***************************************************************************/
|
||||
#include "shared.h"
|
||||
#include "dvd.h"
|
||||
#include "iso9660.h"
|
||||
#include "font.h"
|
||||
#include "unzip.h"
|
||||
#include "history.h"
|
||||
|
||||
#define PAGESIZE 12
|
||||
#define PADCAL 70
|
||||
|
||||
static int maxfiles;
|
||||
u8 havedir = 0;
|
||||
u8 haveSDdir = 0;
|
||||
u8 UseSDCARD = 0;
|
||||
sd_file *filehandle;
|
||||
char rootSDdir[SDCARD_MAX_PATH_LEN];
|
||||
int LoadFile (unsigned char *buffer);
|
||||
int offset = 0;
|
||||
int selection = 0;
|
||||
int old_selection = 0;
|
||||
int old_offset = 0;
|
||||
static int offset = 0;
|
||||
static int selection = 0;
|
||||
static int old_selection = 0;
|
||||
static int old_offset = 0;
|
||||
static char rootSDdir[256];
|
||||
static u8 haveDVDdir = 0;
|
||||
static u8 haveSDdir = 0;
|
||||
static u8 UseSDCARD = 0;
|
||||
static u8 UseHistory = 0;
|
||||
static int LoadFile (unsigned char *buffer);
|
||||
|
||||
/* globals */
|
||||
FILE *sdfile;
|
||||
|
||||
extern void reloadrom ();
|
||||
|
||||
/***************************************************************************
|
||||
* Showfile screen
|
||||
* FileSortCallback
|
||||
*
|
||||
* Quick sort callback to sort file entries with the following order:
|
||||
* .
|
||||
* ..
|
||||
* <dirs>
|
||||
* <files>
|
||||
***************************************************************************/
|
||||
static 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 == 1 && ((FILEENTRIES *)f2)->flags == 0) return -1;
|
||||
if(((FILEENTRIES *)f1)->flags == 0 && ((FILEENTRIES *)f2)->flags == 1) return 1;
|
||||
|
||||
return stricmp(((FILEENTRIES *)f1)->filename, ((FILEENTRIES *)f2)->filename);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* ShowFiles
|
||||
*
|
||||
* Show filenames list in current directory
|
||||
***************************************************************************/
|
||||
static void ShowFiles (int offset, int selection)
|
||||
{
|
||||
@ -58,7 +80,6 @@ static void ShowFiles (int offset, int selection)
|
||||
memset(text,0,MAXJOLIET+2);
|
||||
if (filelist[i].flags) sprintf(text, "[%s]", filelist[i].filename + filelist[i].filename_offset);
|
||||
else sprintf (text, "%s", filelist[i].filename + filelist[i].filename_offset);
|
||||
|
||||
if (j == (selection - offset)) WriteCentre_HL ((j * fheight) + 120, text);
|
||||
else WriteCentre ((j * fheight) + 120, text);
|
||||
j++;
|
||||
@ -67,9 +88,11 @@ static void ShowFiles (int offset, int selection)
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Update SDCARD curent directory name
|
||||
* updateSDdirname
|
||||
*
|
||||
* Update ROOT directory while browsing SDCARD
|
||||
***************************************************************************/
|
||||
int updateSDdirname()
|
||||
static int updateSDdirname()
|
||||
{
|
||||
int size=0;
|
||||
char *test;
|
||||
@ -83,84 +106,110 @@ int updateSDdirname()
|
||||
{
|
||||
/* determine last subdirectory namelength */
|
||||
sprintf(temp,"%s",rootSDdir);
|
||||
test= strtok(temp,"\\");
|
||||
test= strtok(temp,"/");
|
||||
while (test != NULL)
|
||||
{
|
||||
size = strlen(test);
|
||||
test = strtok(NULL,"\\");
|
||||
test = strtok(NULL,"/");
|
||||
}
|
||||
|
||||
/* remove last subdirectory name */
|
||||
size = strlen(rootSDdir) - size - 1;
|
||||
rootSDdir[size] = 0;
|
||||
|
||||
/* handles root name */
|
||||
if (strcmp(rootSDdir,"dev0:") == 0) sprintf(rootSDdir,"dev0:\\genplus\\..");
|
||||
|
||||
return 1;
|
||||
size = strlen(rootSDdir) - size;
|
||||
rootSDdir[size-1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* test new directory namelength */
|
||||
if ((strlen(rootSDdir)+1+strlen(filelist[selection].filename)) < SDCARD_MAX_PATH_LEN)
|
||||
{
|
||||
/* handles root name */
|
||||
if (strcmp(rootSDdir,"dev0:\\genplus\\..") == 0) sprintf(rootSDdir,"dev0:");
|
||||
sprintf(rootSDdir, "%s%s/",rootSDdir, filelist[selection].filename);
|
||||
}
|
||||
|
||||
/* update current directory name */
|
||||
sprintf(rootSDdir, "%s\\%s",rootSDdir, filelist[selection].filename);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
WaitPrompt ("Dirname is too long !");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Browse SDCARD subdirectories
|
||||
* parseSDdirectory
|
||||
*
|
||||
* List files into one SDCARD directory
|
||||
***************************************************************************/
|
||||
int parseSDdirectory()
|
||||
static int parseSDdirectory()
|
||||
{
|
||||
int entries = 0;
|
||||
int nbfiles = 0;
|
||||
DIR *sddir = NULL;
|
||||
char filename[MAXPATHLEN];
|
||||
struct stat filestat;
|
||||
|
||||
/* Get a list of files from the actual root directory */
|
||||
entries = SDCARD_ReadDir (rootSDdir, &sddir);
|
||||
|
||||
if (entries < 0) entries = 0;
|
||||
if (entries > MAXFILES) entries = MAXFILES;
|
||||
|
||||
/* Move to DVD structure - this is required for the file selector */
|
||||
while (entries)
|
||||
/* open directory */
|
||||
DIR_ITER *dir = diropen (rootSDdir);
|
||||
if (dir == NULL)
|
||||
{
|
||||
memset (&filelist[nbfiles], 0, sizeof (FILEENTRIES));
|
||||
strncpy(filelist[nbfiles].filename,sddir[nbfiles].fname,MAXJOLIET);
|
||||
filelist[nbfiles].filename[MAXJOLIET-1] = 0;
|
||||
filelist[nbfiles].length = sddir[nbfiles].fsize;
|
||||
filelist[nbfiles].flags = (char)(sddir[nbfiles].fattr & SDCARD_ATTR_DIR);
|
||||
nbfiles++;
|
||||
entries--;
|
||||
sprintf(filename, "Error opening %s", rootSDdir);
|
||||
WaitPrompt (filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*** Release memory ***/
|
||||
free(sddir);
|
||||
while (dirnext(dir, filename, &filestat) == 0)
|
||||
{
|
||||
if (strcmp(filename,".") != 0)
|
||||
{
|
||||
memset(&filelist[nbfiles], 0, sizeof (FILEENTRIES));
|
||||
sprintf(filelist[nbfiles].filename,"%s",filename);
|
||||
filelist[nbfiles].length = filestat.st_size;
|
||||
filelist[nbfiles].flags = (filestat.st_mode & S_IFDIR) ? 1 : 0;
|
||||
nbfiles++;
|
||||
}
|
||||
}
|
||||
|
||||
dirclose(dir);
|
||||
|
||||
/* Sort the file list */
|
||||
qsort(filelist, nbfiles, sizeof(FILEENTRIES), FileSortCallback);
|
||||
|
||||
return nbfiles;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* FileSelected
|
||||
*
|
||||
* Called when a file is selected by the user inside the FileSelector loop.
|
||||
****************************************************************************/
|
||||
static void FileSelected()
|
||||
{
|
||||
/* If loading from history then we need to setup a few more things. */
|
||||
if(UseHistory)
|
||||
{
|
||||
/* Get the parent folder for the file. */
|
||||
strncpy(rootSDdir, history.entries[selection].filepath, MAXJOLIET-1);
|
||||
rootSDdir[MAXJOLIET-1] = '\0';
|
||||
|
||||
/* Get the length of the file. This has to be done
|
||||
* before calling LoadFile(). */
|
||||
char filepath[MAXJOLIET];
|
||||
struct stat filestat;
|
||||
snprintf(filepath, MAXJOLIET-1, "%s%s", history.entries[selection].filepath, history.entries[selection].filename);
|
||||
filepath[MAXJOLIET-1] = '\0';
|
||||
if(stat(filepath, &filestat) == 0)
|
||||
{
|
||||
filelist[selection].length = filestat.st_size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add/move the file to the top of the history. */
|
||||
history_add_file(rootSDdir, filelist[selection].filename);
|
||||
|
||||
rootdir = filelist[selection].offset;
|
||||
rootdirlength = filelist[selection].length;
|
||||
memfile_autosave();
|
||||
genromsize = LoadFile(cart_rom);
|
||||
reloadrom();
|
||||
memfile_autoload();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* FileSelector
|
||||
*
|
||||
* Let user select a file from the File listing
|
||||
****************************************************************************/
|
||||
void FileSelector ()
|
||||
static void FileSelector ()
|
||||
{
|
||||
short p;
|
||||
signed char a,b;
|
||||
int haverom = 0;
|
||||
int redraw = 1;
|
||||
int go_up = 0;
|
||||
@ -170,16 +219,10 @@ void FileSelector ()
|
||||
{
|
||||
if (redraw) ShowFiles (offset, selection);
|
||||
redraw = 0;
|
||||
p = PAD_ButtonsDown (0);
|
||||
a = PAD_StickY (0);
|
||||
b = PAD_StickX (0);
|
||||
|
||||
/*
|
||||
* check selection screen changes
|
||||
*/
|
||||
p = ogc_input__getMenuButtons();
|
||||
|
||||
/* scroll displayed filename */
|
||||
if ((p & PAD_BUTTON_LEFT) || (b < -PADCAL))
|
||||
if (p & PAD_BUTTON_LEFT)
|
||||
{
|
||||
if (filelist[selection].filename_offset > 0)
|
||||
{
|
||||
@ -187,7 +230,7 @@ void FileSelector ()
|
||||
redraw = 1;
|
||||
}
|
||||
}
|
||||
else if ((p & PAD_BUTTON_RIGHT) || (b > PADCAL))
|
||||
else if (p & PAD_BUTTON_RIGHT)
|
||||
{
|
||||
size = 0;
|
||||
for (i=filelist[selection].filename_offset; i<strlen(filelist[selection].filename); i++)
|
||||
@ -201,7 +244,7 @@ void FileSelector ()
|
||||
}
|
||||
|
||||
/* highlight next item */
|
||||
else if ((p & PAD_BUTTON_DOWN) || (a < -PADCAL))
|
||||
else if (p & PAD_BUTTON_DOWN)
|
||||
{
|
||||
filelist[selection].filename_offset = 0;
|
||||
selection++;
|
||||
@ -211,7 +254,7 @@ void FileSelector ()
|
||||
}
|
||||
|
||||
/* highlight previous item */
|
||||
else if ((p & PAD_BUTTON_UP) || (a > PADCAL))
|
||||
else if (p & PAD_BUTTON_UP)
|
||||
{
|
||||
filelist[selection].filename_offset = 0;
|
||||
selection--;
|
||||
@ -250,16 +293,18 @@ void FileSelector ()
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check pressed key
|
||||
*/
|
||||
|
||||
/* go up one directory or quit */
|
||||
if (p & PAD_BUTTON_B)
|
||||
{
|
||||
filelist[selection].filename_offset = 0;
|
||||
if (((!UseSDCARD) && (basedir == rootdir)) ||
|
||||
(UseSDCARD && strcmp(rootSDdir,"dev0:\\genplus\\..") == 0)) return;
|
||||
if (UseSDCARD)
|
||||
{
|
||||
if (strcmp(filelist[0].filename,"..") != 0) return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (basedir == rootdir) return;
|
||||
}
|
||||
go_up = 1;
|
||||
}
|
||||
|
||||
@ -276,23 +321,22 @@ void FileSelector ()
|
||||
filelist[selection].filename_offset = 0;
|
||||
if (go_up)
|
||||
{
|
||||
/* select item #1 */
|
||||
go_up = 0;
|
||||
selection = 1;
|
||||
selection = UseSDCARD ? 0 : 1;
|
||||
}
|
||||
|
||||
/*** This is directory ***/
|
||||
if (filelist[selection].flags)
|
||||
{
|
||||
if (UseSDCARD) /* SDCARD directory handler */
|
||||
/* SDCARD directory handler */
|
||||
if (UseSDCARD)
|
||||
{
|
||||
/* update current directory */
|
||||
int status = updateSDdirname();
|
||||
|
||||
/* move to new directory */
|
||||
if (status == 1)
|
||||
if (updateSDdirname())
|
||||
{
|
||||
/* reinit selector (previous value is saved for one level) */
|
||||
if (selection == 1)
|
||||
if (selection == 0)
|
||||
{
|
||||
selection = old_selection;
|
||||
offset = old_offset;
|
||||
@ -308,23 +352,16 @@ void FileSelector ()
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
|
||||
/* set new entry list */
|
||||
maxfiles = parseSDdirectory();
|
||||
if (!maxfiles)
|
||||
{
|
||||
/* quit */
|
||||
WaitPrompt ("Error reading directory !");
|
||||
WaitPrompt ("No files found !");
|
||||
haverom = 1;
|
||||
haveSDdir = 0;
|
||||
}
|
||||
}
|
||||
else if (status == -1)
|
||||
{
|
||||
/* quit */
|
||||
haverom = 1;
|
||||
haveSDdir = 0;
|
||||
}
|
||||
}
|
||||
else /* DVD directory handler */
|
||||
{
|
||||
@ -353,16 +390,13 @@ void FileSelector ()
|
||||
}
|
||||
|
||||
/* get new entry list */
|
||||
maxfiles = parsedirectory ();
|
||||
maxfiles = parseDVDdirectory ();
|
||||
}
|
||||
}
|
||||
}
|
||||
else /*** This is a file ***/
|
||||
{
|
||||
rootdir = filelist[selection].offset;
|
||||
rootdirlength = filelist[selection].length;
|
||||
genromsize = LoadFile (cart_rom);
|
||||
reloadrom ();
|
||||
FileSelected();
|
||||
haverom = 1;
|
||||
}
|
||||
redraw = 1;
|
||||
@ -378,11 +412,15 @@ void FileSelector ()
|
||||
void OpenDVD ()
|
||||
{
|
||||
UseSDCARD = 0;
|
||||
UseHistory = 0;
|
||||
|
||||
if (!getpvd())
|
||||
{
|
||||
ShowAction("Mounting DVD ... Wait");
|
||||
#ifndef HW_RVL
|
||||
DVD_Mount();
|
||||
havedir = 0;
|
||||
#endif
|
||||
haveDVDdir = 0;
|
||||
if (!getpvd())
|
||||
{
|
||||
WaitPrompt ("Failed to mount DVD");
|
||||
@ -390,7 +428,7 @@ void OpenDVD ()
|
||||
}
|
||||
}
|
||||
|
||||
if (havedir == 0)
|
||||
if (haveDVDdir == 0)
|
||||
{
|
||||
/* don't mess with SD entries */
|
||||
haveSDdir = 0;
|
||||
@ -399,37 +437,43 @@ void OpenDVD ()
|
||||
rootdir = basedir;
|
||||
old_selection = selection = offset = old_offset = 0;
|
||||
|
||||
if ((maxfiles = parsedirectory ()))
|
||||
if ((maxfiles = parseDVDdirectory ()))
|
||||
{
|
||||
FileSelector ();
|
||||
havedir = 1;
|
||||
haveDVDdir = 1;
|
||||
}
|
||||
}
|
||||
else FileSelector ();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* OpenSD updated to use the new libogc. Written by softdev and pasted
|
||||
* into this code by Drack.
|
||||
* Modified for subdirectory browing & quick filelist recovery
|
||||
* Enjoy!
|
||||
*****************************************************************************/
|
||||
* OpenSD
|
||||
*
|
||||
* Function to load a SDCARD directory and display to user.
|
||||
****************************************************************************/
|
||||
int OpenSD ()
|
||||
{
|
||||
UseSDCARD = 1;
|
||||
UseHistory = 0;
|
||||
|
||||
if (haveSDdir == 0)
|
||||
{
|
||||
/* don't mess with DVD entries */
|
||||
havedir = 0;
|
||||
haveDVDdir = 0;
|
||||
|
||||
/* reinit selector */
|
||||
old_selection = selection = offset = old_offset = 0;
|
||||
|
||||
/* Reset SDCARD root directory */
|
||||
sprintf(rootSDdir,"dev0:\\genplus\\roms");
|
||||
sprintf (rootSDdir, "/genplus/roms/");
|
||||
|
||||
/* Parse initial root directory and get entries list */
|
||||
/* if directory doesn't exist, use root */
|
||||
DIR_ITER *dir = diropen(rootSDdir);
|
||||
if (dir == NULL) sprintf (rootSDdir, "fat:/");
|
||||
else dirclose(dir);
|
||||
}
|
||||
|
||||
/* Parse root directory and get entries list */
|
||||
ShowAction("Reading Directory ...");
|
||||
if ((maxfiles = parseSDdirectory ()))
|
||||
{
|
||||
@ -442,43 +486,67 @@ int OpenSD ()
|
||||
else
|
||||
{
|
||||
/* no entries found */
|
||||
WaitPrompt ("Error reading dev0:\\genplus\\roms");
|
||||
WaitPrompt ("no files found !");
|
||||
haveSDdir = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Retrieve previous entries list and made a new selection */
|
||||
else FileSelector ();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* SDCard Get Info
|
||||
****************************************************************************/
|
||||
void GetSDInfo ()
|
||||
void OpenHistory()
|
||||
{
|
||||
char fname[SDCARD_MAX_PATH_LEN];
|
||||
rootdirlength = 0;
|
||||
int i;
|
||||
|
||||
/* Check filename length */
|
||||
if ((strlen(rootSDdir)+1+strlen(filelist[selection].filename)) < SDCARD_MAX_PATH_LEN)
|
||||
sprintf(fname, "%s\\%s",rootSDdir,filelist[selection].filename);
|
||||
UseSDCARD = 1;
|
||||
UseHistory = 1;
|
||||
|
||||
/* don't mess with SD entries */
|
||||
haveSDdir = 0;
|
||||
|
||||
/* reinit selector */
|
||||
old_selection = selection = offset = old_offset = 0;
|
||||
|
||||
/* Reset SDCARD root directory */
|
||||
/* Make this empty because the history */
|
||||
/* entry will contain the entire path. */
|
||||
/*sprintf (rootSDdir, "");*/
|
||||
|
||||
/* Recreate the file listing from the history
|
||||
* as if all of the roms were in the same directory. */
|
||||
ShowAction("Reading Files ...");
|
||||
|
||||
maxfiles = 0;
|
||||
for(i=0; i < NUM_HISTORY_ENTRIES; i++)
|
||||
{
|
||||
if(history.entries[i].filepath[0] > 0)
|
||||
{
|
||||
filelist[i].offset = 0;
|
||||
filelist[i].length = 0;
|
||||
filelist[i].flags = 0;
|
||||
filelist[i].filename_offset = 0;
|
||||
strncpy(filelist[i].filename, history.entries[i].filename, MAXJOLIET-1);
|
||||
filelist[i].filename[MAXJOLIET-1] = '\0';
|
||||
|
||||
maxfiles++;
|
||||
}
|
||||
else
|
||||
{
|
||||
WaitPrompt ("Maximum Filename Length reached !");
|
||||
haveSDdir = 0; // reset everything before next access
|
||||
/* Found the end of the list. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
filehandle = SDCARD_OpenFile (fname, "rb");
|
||||
if (filehandle == NULL)
|
||||
if(!maxfiles)
|
||||
{
|
||||
WaitPrompt ("Unable to open file!");
|
||||
WaitPrompt ("No recent files");
|
||||
return;
|
||||
}
|
||||
rootdirlength = SDCARD_GetFileSize (filehandle);
|
||||
|
||||
FileSelector();
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* LoadFile
|
||||
*
|
||||
@ -488,53 +556,90 @@ void GetSDInfo ()
|
||||
*
|
||||
* The buffer parameter should re-use the initial ROM buffer.
|
||||
****************************************************************************/
|
||||
int LoadFile (unsigned char *buffer)
|
||||
static int LoadFile (unsigned char *buffer)
|
||||
{
|
||||
int offset;
|
||||
int readoffset;
|
||||
int blocks;
|
||||
int i;
|
||||
u64 discoffset;
|
||||
u64 discoffset = 0;
|
||||
char readbuffer[2048];
|
||||
char fname[MAXPATHLEN];
|
||||
|
||||
/* SDCard Addition */
|
||||
if (UseSDCARD) GetSDInfo ();
|
||||
/* SDCard access */
|
||||
if (UseSDCARD)
|
||||
{
|
||||
/* open file */
|
||||
sprintf(fname, "%s%s",rootSDdir,filelist[selection].filename);
|
||||
sdfile = fopen(fname, "rb");
|
||||
if (sdfile == NULL)
|
||||
{
|
||||
WaitPrompt ("Unable to open file!");
|
||||
haveSDdir = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* How many 2k blocks to read */
|
||||
if (rootdirlength == 0) return 0;
|
||||
blocks = rootdirlength / 2048;
|
||||
readoffset = 0;
|
||||
|
||||
offset = 0;
|
||||
discoffset = rootdir;
|
||||
ShowAction ("Loading ... Wait");
|
||||
|
||||
if (UseSDCARD) SDCARD_ReadFile (filehandle, &readbuffer, 2048);
|
||||
else dvd_read (&readbuffer, 2048, discoffset);
|
||||
/* Read first data chunk */
|
||||
if (UseSDCARD)
|
||||
{
|
||||
fread(readbuffer, 1, 2048, sdfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
discoffset = rootdir;
|
||||
dvd_read (&readbuffer, 2048, discoffset);
|
||||
}
|
||||
|
||||
/* determine file type */
|
||||
if (!IsZipFile ((char *) readbuffer))
|
||||
{
|
||||
if (UseSDCARD) SDCARD_SeekFile (filehandle, 0, SDCARD_SEEK_SET);
|
||||
/* go back to file start */
|
||||
if (UseSDCARD)
|
||||
{
|
||||
fseek(sdfile, 0, SEEK_SET);
|
||||
}
|
||||
|
||||
/* read data chunks */
|
||||
for (i = 0; i < blocks; i++)
|
||||
{
|
||||
if (UseSDCARD) SDCARD_ReadFile (filehandle, &readbuffer, 2048);
|
||||
else dvd_read(readbuffer, 2048, discoffset);
|
||||
memcpy (buffer + offset, readbuffer, 2048);
|
||||
offset += 2048;
|
||||
if (UseSDCARD)
|
||||
{
|
||||
fread(readbuffer, 1, 2048, sdfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
dvd_read(readbuffer, 2048, discoffset);
|
||||
discoffset += 2048;
|
||||
}
|
||||
|
||||
/* And final cleanup */
|
||||
if (rootdirlength % 2048)
|
||||
{
|
||||
i = rootdirlength % 2048;
|
||||
if (UseSDCARD) SDCARD_ReadFile (filehandle, &readbuffer, i);
|
||||
else dvd_read (readbuffer, 2048, discoffset);
|
||||
memcpy (buffer + offset, readbuffer, i);
|
||||
memcpy (buffer + readoffset, readbuffer, 2048);
|
||||
readoffset += 2048;
|
||||
}
|
||||
}
|
||||
else return UnZipBuffer (buffer, discoffset, rootdirlength);
|
||||
|
||||
if (UseSDCARD) SDCARD_CloseFile (filehandle);
|
||||
/* final read */
|
||||
i = rootdirlength % 2048;
|
||||
if (i)
|
||||
{
|
||||
if (UseSDCARD) fread(readbuffer, 1, i, sdfile);
|
||||
else dvd_read (readbuffer, 2048, discoffset);
|
||||
memcpy (buffer + readoffset, readbuffer, i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unzip file */
|
||||
return UnZipBuffer (buffer, discoffset, rootdirlength, UseSDCARD);
|
||||
}
|
||||
|
||||
/* close SD file */
|
||||
if (UseSDCARD) fclose(sdfile);
|
||||
|
||||
return rootdirlength;
|
||||
}
|
||||
|
@ -1,526 +0,0 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* File Selection
|
||||
***************************************************************************/
|
||||
#include "shared.h"
|
||||
#include "dvd.h"
|
||||
#include "iso9660.h"
|
||||
#include "font.h"
|
||||
#include "unzip.h"
|
||||
#include "diskio.h"
|
||||
#include "vfat.h"
|
||||
|
||||
|
||||
#define PAGESIZE 12
|
||||
#define PADCAL 70
|
||||
|
||||
static int maxfiles;
|
||||
u8 havedir = 0;
|
||||
u8 haveSDdir = 0;
|
||||
u8 UseSDCARD = 0;
|
||||
char rootSDdir[SDCARD_MAX_PATH_LEN];
|
||||
int LoadFile (unsigned char *buffer);
|
||||
int offset = 0;
|
||||
int selection = 0;
|
||||
int old_selection = 0;
|
||||
int old_offset = 0;
|
||||
VFATFS fs;
|
||||
FSDIRENTRY f;
|
||||
|
||||
|
||||
extern void reloadrom ();
|
||||
|
||||
/***************************************************************************
|
||||
* Showfile screen
|
||||
***************************************************************************/
|
||||
static void ShowFiles (int offset, int selection)
|
||||
{
|
||||
int i, j;
|
||||
char text[MAX_LONG_NAME+2];
|
||||
|
||||
ClearScreen ();
|
||||
j = 0;
|
||||
|
||||
for (i = offset; i < (offset + PAGESIZE) && (i < maxfiles); i++)
|
||||
{
|
||||
memset(text,0,MAX_LONG_NAME+2);
|
||||
if (filelist[i].flags) sprintf(text, "[%s]", filelist[i].displayname + filelist[i].filename_offset);
|
||||
else sprintf (text, "%s", filelist[i].displayname + filelist[i].filename_offset);
|
||||
|
||||
if (j == (selection - offset)) WriteCentre_HL ((j * fheight) + 120, text);
|
||||
else WriteCentre ((j * fheight) + 120, text);
|
||||
j++;
|
||||
}
|
||||
SetScreen ();
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Update SDCARD curent directory name
|
||||
***************************************************************************/
|
||||
int updateSDdirname()
|
||||
{
|
||||
int size=0;
|
||||
char *test;
|
||||
char temp[1024];
|
||||
|
||||
|
||||
/* go up to parent directory */
|
||||
if (strcmp(filelist[selection].filename,"..") == 0)
|
||||
{
|
||||
/* determine last subdirectory namelength */
|
||||
sprintf(temp,"%s",rootSDdir);
|
||||
test= strtok(temp,"/");
|
||||
while (test != NULL)
|
||||
{
|
||||
size = strlen(test);
|
||||
test = strtok(NULL,"/");
|
||||
}
|
||||
|
||||
/* remove last subdirectory name */
|
||||
size = strlen(rootSDdir) - size - 1;
|
||||
rootSDdir[size] = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update current directory name */
|
||||
sprintf(rootSDdir, "%s/%s",rootSDdir, filelist[selection].filename);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Browse SDCARD subdirectories
|
||||
***************************************************************************/
|
||||
int parseSDdirectory()
|
||||
{
|
||||
int nbfiles = 0;
|
||||
FSDIRENTRY fsdir;
|
||||
|
||||
/* Get a list of files from the actual root directory */
|
||||
int res = VFAT_opendir(0, &fsdir, rootSDdir);
|
||||
|
||||
if (res == FS_SUCCESS)
|
||||
{
|
||||
while ( VFAT_readdir(&fsdir) == FS_SUCCESS )
|
||||
{
|
||||
memset (&filelist[nbfiles], 0, sizeof (FILEENTRIES));
|
||||
strcpy(filelist[nbfiles].displayname, fsdir.longname);
|
||||
strcpy(filelist[nbfiles].filename, fsdir.shortname);
|
||||
filelist[nbfiles].length = fsdir.fsize;
|
||||
filelist[nbfiles].flags = fsdir.dirent.attribute & ATTR_DIRECTORY;
|
||||
nbfiles++;
|
||||
}
|
||||
|
||||
VFAT_closedir(&fsdir);
|
||||
}
|
||||
|
||||
return nbfiles;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* FileSelector
|
||||
*
|
||||
* Let user select a file from the File listing
|
||||
****************************************************************************/
|
||||
void FileSelector ()
|
||||
{
|
||||
short p;
|
||||
signed char a,b;
|
||||
int haverom = 0;
|
||||
int redraw = 1;
|
||||
int go_up = 0;
|
||||
int i,size;
|
||||
|
||||
while (haverom == 0)
|
||||
{
|
||||
if (redraw) ShowFiles (offset, selection);
|
||||
redraw = 0;
|
||||
p = PAD_ButtonsDown (0);
|
||||
a = PAD_StickY (0);
|
||||
b = PAD_StickX (0);
|
||||
|
||||
/*
|
||||
* check selection screen changes
|
||||
*/
|
||||
|
||||
/* scroll displayed filename */
|
||||
if ((p & PAD_BUTTON_LEFT) || (b < -PADCAL))
|
||||
{
|
||||
if (filelist[selection].filename_offset > 0)
|
||||
{
|
||||
filelist[selection].filename_offset --;
|
||||
redraw = 1;
|
||||
}
|
||||
}
|
||||
else if ((p & PAD_BUTTON_RIGHT) || (b > PADCAL))
|
||||
{
|
||||
size = 0;
|
||||
for (i=filelist[selection].filename_offset; i<strlen(filelist[selection].filename); i++)
|
||||
size += font_size[(int)filelist[selection].filename[i]];
|
||||
|
||||
if (size > back_framewidth)
|
||||
{
|
||||
filelist[selection].filename_offset ++;
|
||||
redraw = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* highlight next item */
|
||||
else if ((p & PAD_BUTTON_DOWN) || (a < -PADCAL))
|
||||
{
|
||||
filelist[selection].filename_offset = 0;
|
||||
selection++;
|
||||
if (selection == maxfiles) selection = offset = 0;
|
||||
if ((selection - offset) >= PAGESIZE) offset += PAGESIZE;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
/* highlight previous item */
|
||||
else if ((p & PAD_BUTTON_UP) || (a > PADCAL))
|
||||
{
|
||||
filelist[selection].filename_offset = 0;
|
||||
selection--;
|
||||
if (selection < 0)
|
||||
{
|
||||
selection = maxfiles - 1;
|
||||
offset = selection - PAGESIZE + 1;
|
||||
}
|
||||
if (selection < offset) offset -= PAGESIZE;
|
||||
if (offset < 0) offset = 0;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
/* go back one page */
|
||||
else if (p & PAD_TRIGGER_L)
|
||||
{
|
||||
filelist[selection].filename_offset = 0;
|
||||
selection -= PAGESIZE;
|
||||
if (selection < 0)
|
||||
{
|
||||
selection = maxfiles - 1;
|
||||
offset = selection - PAGESIZE + 1;
|
||||
}
|
||||
if (selection < offset) offset -= PAGESIZE;
|
||||
if (offset < 0) offset = 0;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
/* go forward one page */
|
||||
else if (p & PAD_TRIGGER_R)
|
||||
{
|
||||
filelist[selection].filename_offset = 0;
|
||||
selection += PAGESIZE;
|
||||
if (selection > maxfiles - 1) selection = offset = 0;
|
||||
if ((selection - offset) >= PAGESIZE) offset += PAGESIZE;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check pressed key
|
||||
*/
|
||||
|
||||
/* go up one directory or quit */
|
||||
if (p & PAD_BUTTON_B)
|
||||
{
|
||||
filelist[selection].filename_offset = 0;
|
||||
if (((!UseSDCARD) && (basedir == rootdir)) ||
|
||||
(UseSDCARD && strcmp(rootSDdir,"/") == 0)) return;
|
||||
go_up = 1;
|
||||
}
|
||||
|
||||
/* quit */
|
||||
if (p & PAD_TRIGGER_Z)
|
||||
{
|
||||
filelist[selection].filename_offset = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* open selected file or directory */
|
||||
if ((p & PAD_BUTTON_A) || go_up)
|
||||
{
|
||||
filelist[selection].filename_offset = 0;
|
||||
if (go_up)
|
||||
{
|
||||
go_up = 0;
|
||||
selection = UseSDCARD ? 0 : 1;
|
||||
}
|
||||
|
||||
/*** This is directory ***/
|
||||
if (filelist[selection].flags)
|
||||
{
|
||||
/* SDCARD directory handler */
|
||||
if (UseSDCARD)
|
||||
{
|
||||
/* update current directory */
|
||||
int status = updateSDdirname();
|
||||
|
||||
/* move to new directory */
|
||||
if (status == 1)
|
||||
{
|
||||
/* reinit selector (previous value is saved for one level) */
|
||||
if (selection == 1)
|
||||
{
|
||||
selection = old_selection;
|
||||
offset = old_offset;
|
||||
old_selection = 0;
|
||||
old_offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* save current selector value */
|
||||
old_selection = selection;
|
||||
old_offset = offset;
|
||||
selection = 0;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
/* set new entry list */
|
||||
maxfiles = parseSDdirectory();
|
||||
if (!maxfiles)
|
||||
{
|
||||
/* quit */
|
||||
WaitPrompt ("Error reading directory !");
|
||||
haverom = 1;
|
||||
haveSDdir = 0;
|
||||
}
|
||||
}
|
||||
else if (status == -1)
|
||||
{
|
||||
/* quit */
|
||||
haverom = 1;
|
||||
haveSDdir = 0;
|
||||
}
|
||||
}
|
||||
/* DVD directory handler */
|
||||
else
|
||||
{
|
||||
/* move to a new directory */
|
||||
if (selection != 0)
|
||||
{
|
||||
/* update current directory */
|
||||
rootdir = filelist[selection].offset;
|
||||
rootdirlength = filelist[selection].length;
|
||||
|
||||
/* reinit selector (previous value is saved for one level) */
|
||||
if (selection == 1)
|
||||
{
|
||||
selection = old_selection;
|
||||
offset = old_offset;
|
||||
old_selection = 0;
|
||||
old_offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* save current selector value */
|
||||
old_selection = selection;
|
||||
old_offset = offset;
|
||||
selection = 0;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
/* get new entry list */
|
||||
maxfiles = parsedirectory ();
|
||||
}
|
||||
}
|
||||
}
|
||||
else /*** This is a file ***/
|
||||
{
|
||||
rootdir = filelist[selection].offset;
|
||||
rootdirlength = filelist[selection].length;
|
||||
genromsize = LoadFile (cart_rom);
|
||||
reloadrom ();
|
||||
haverom = 1;
|
||||
}
|
||||
redraw = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* OpenDVD
|
||||
*
|
||||
* Function to load a DVD directory and display to user.
|
||||
****************************************************************************/
|
||||
void OpenDVD ()
|
||||
{
|
||||
UseSDCARD = 0;
|
||||
if (!getpvd())
|
||||
{
|
||||
ShowAction("Mounting DVD ... Wait");
|
||||
DVD_Mount();
|
||||
havedir = 0;
|
||||
if (!getpvd())
|
||||
{
|
||||
WaitPrompt ("Failed to mount DVD");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (havedir == 0)
|
||||
{
|
||||
/* don't mess with SD entries */
|
||||
haveSDdir = 0;
|
||||
|
||||
/* reinit selector */
|
||||
rootdir = basedir;
|
||||
old_selection = selection = offset = old_offset = 0;
|
||||
|
||||
if ((maxfiles = parsedirectory ()))
|
||||
{
|
||||
FileSelector ();
|
||||
havedir = 1;
|
||||
}
|
||||
}
|
||||
else FileSelector ();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* OpenSD updated to use the new libogc. Written by softdev and pasted
|
||||
* into this code by Drack.
|
||||
* Modified for subdirectory browing & quick filelist recovery
|
||||
* Enjoy!
|
||||
*****************************************************************************/
|
||||
int OpenSD ()
|
||||
{
|
||||
UseSDCARD = 1;
|
||||
char msg[20];
|
||||
|
||||
if (haveSDdir == 0)
|
||||
{
|
||||
/* don't mess with DVD entries */
|
||||
havedir = 0;
|
||||
|
||||
/* reinit selector */
|
||||
old_selection = selection = offset = old_offset = 0;
|
||||
|
||||
/* Reset SDCARD root directory */
|
||||
sprintf(rootSDdir,"/genplus/roms");
|
||||
|
||||
/* Parse initial root directory and get entries list */
|
||||
ShowAction("Reading Directory ...");
|
||||
int res = VFAT_mount(FS_SLOTA, &fs);
|
||||
if ( res != FS_TYPE_FAT16 )
|
||||
{
|
||||
sprintf(msg,"Error mounting SDCARD: %d", res);
|
||||
WaitPrompt (msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((maxfiles = parseSDdirectory ()))
|
||||
{
|
||||
/* Select an entry */
|
||||
FileSelector ();
|
||||
|
||||
/* memorize last entries list, actual root directory and selection for next access */
|
||||
haveSDdir = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no entries found */
|
||||
WaitPrompt ("Error reading /genplus/roms");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Retrieve previous entries list and made a new selection */
|
||||
else FileSelector ();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* SDCard Get Info
|
||||
****************************************************************************/
|
||||
void GetSDInfo ()
|
||||
{
|
||||
char fname[SDCARD_MAX_PATH_LEN];
|
||||
rootdirlength = 0;
|
||||
|
||||
/* Check filename length */
|
||||
sprintf(fname, "%s/%s",rootSDdir,filelist[selection].filename);
|
||||
|
||||
int res = VFAT_fopen(0, &f, fname, FS_READ);
|
||||
if (res != FS_SUCCESS )
|
||||
{
|
||||
WaitPrompt ("Unable to open file!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* LoadFile
|
||||
*
|
||||
* This function will load a file from DVD or SDCARD, in BIN, SMD or ZIP format.
|
||||
* The values for offset and length are inherited from rootdir and
|
||||
* rootdirlength.
|
||||
*
|
||||
* The buffer parameter should re-use the initial ROM buffer.
|
||||
****************************************************************************/
|
||||
int LoadFile (unsigned char *buffer)
|
||||
{
|
||||
int offset;
|
||||
int blocks;
|
||||
int i;
|
||||
u64 discoffset;
|
||||
char readbuffer[2048];
|
||||
|
||||
/* SDCard Addition */
|
||||
if (UseSDCARD) GetSDInfo ();
|
||||
|
||||
/* How many 2k blocks to read */
|
||||
if (rootdirlength == 0) return 0;
|
||||
blocks = rootdirlength / 2048;
|
||||
|
||||
offset = 0;
|
||||
discoffset = rootdir;
|
||||
ShowAction ("Loading ... Wait");
|
||||
|
||||
if (UseSDCARD) VFAT_fread(&f, readbuffer, 2048);
|
||||
else dvd_read (&readbuffer, 2048, discoffset);
|
||||
|
||||
if (!IsZipFile ((char *) readbuffer))
|
||||
{
|
||||
if (UseSDCARD) VFAT_fseek(&f, 0, SEEK_SET);
|
||||
|
||||
for (i = 0; i < blocks; i++)
|
||||
{
|
||||
if (UseSDCARD) VFAT_fread (&f, readbuffer, 2048);
|
||||
else dvd_read(readbuffer, 2048, discoffset);
|
||||
memcpy (buffer + offset, readbuffer, 2048);
|
||||
offset += 2048;
|
||||
discoffset += 2048;
|
||||
}
|
||||
|
||||
/* And final cleanup */
|
||||
if (rootdirlength % 2048)
|
||||
{
|
||||
i = rootdirlength % 2048;
|
||||
if (UseSDCARD) VFAT_fread (&f, readbuffer, i);
|
||||
else dvd_read (readbuffer, 2048, discoffset);
|
||||
memcpy (buffer + offset, readbuffer, i);
|
||||
}
|
||||
}
|
||||
else return UnZipBuffer (buffer, discoffset, rootdirlength);
|
||||
|
||||
if (UseSDCARD) VFAT_fclose(&f);
|
||||
|
||||
return rootdirlength;
|
||||
}
|
@ -1,540 +0,0 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* File Selection
|
||||
***************************************************************************/
|
||||
#include "shared.h"
|
||||
#include "dvd.h"
|
||||
#include "iso9660.h"
|
||||
#include "font.h"
|
||||
#include "unzip.h"
|
||||
|
||||
#define PAGESIZE 12
|
||||
#define PADCAL 70
|
||||
|
||||
static int maxfiles;
|
||||
u8 havedir = 0;
|
||||
u8 haveSDdir = 0;
|
||||
u8 UseSDCARD = 0;
|
||||
sd_file *filehandle;
|
||||
char rootSDdir[SDCARD_MAX_PATH_LEN];
|
||||
int LoadFile (unsigned char *buffer);
|
||||
int offset = 0;
|
||||
int selection = 0;
|
||||
int old_selection = 0;
|
||||
int old_offset = 0;
|
||||
|
||||
extern void reloadrom ();
|
||||
|
||||
/***************************************************************************
|
||||
* Showfile screen
|
||||
***************************************************************************/
|
||||
static void ShowFiles (int offset, int selection)
|
||||
{
|
||||
int i, j;
|
||||
char text[MAXJOLIET+2];
|
||||
|
||||
ClearScreen ();
|
||||
j = 0;
|
||||
|
||||
for (i = offset; i < (offset + PAGESIZE) && (i < maxfiles); i++)
|
||||
{
|
||||
memset(text,0,MAXJOLIET+2);
|
||||
if (filelist[i].flags) sprintf(text, "[%s]", filelist[i].filename + filelist[i].filename_offset);
|
||||
else sprintf (text, "%s", filelist[i].filename + filelist[i].filename_offset);
|
||||
|
||||
if (j == (selection - offset)) WriteCentre_HL ((j * fheight) + 120, text);
|
||||
else WriteCentre ((j * fheight) + 120, text);
|
||||
j++;
|
||||
}
|
||||
SetScreen ();
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Update SDCARD curent directory name
|
||||
***************************************************************************/
|
||||
int updateSDdirname()
|
||||
{
|
||||
int size=0;
|
||||
char *test;
|
||||
char temp[1024];
|
||||
|
||||
/* 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",rootSDdir);
|
||||
test= strtok(temp,"\\");
|
||||
while (test != NULL)
|
||||
{
|
||||
size = strlen(test);
|
||||
test = strtok(NULL,"\\");
|
||||
}
|
||||
|
||||
/* remove last subdirectory name */
|
||||
size = strlen(rootSDdir) - size - 1;
|
||||
rootSDdir[size] = 0;
|
||||
|
||||
/* handles root name */
|
||||
if (strcmp(rootSDdir,"dev0:") == 0) sprintf(rootSDdir,"dev0:\\genplus\\..");
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* test new directory namelength */
|
||||
if ((strlen(rootSDdir)+1+strlen(filelist[selection].filename)) < SDCARD_MAX_PATH_LEN)
|
||||
{
|
||||
/* handles root name */
|
||||
if (strcmp(rootSDdir,"dev0:\\genplus\\..") == 0) sprintf(rootSDdir,"dev0:");
|
||||
|
||||
/* update current directory name */
|
||||
sprintf(rootSDdir, "%s\\%s",rootSDdir, filelist[selection].filename);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
WaitPrompt ("Dirname is too long !");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Browse SDCARD subdirectories
|
||||
***************************************************************************/
|
||||
int parseSDdirectory()
|
||||
{
|
||||
int entries = 0;
|
||||
int nbfiles = 0;
|
||||
DIR *sddir = NULL;
|
||||
|
||||
/* Get a list of files from the actual root directory */
|
||||
entries = SDCARD_ReadDir (rootSDdir, &sddir);
|
||||
|
||||
if (entries < 0) entries = 0;
|
||||
if (entries > MAXFILES) entries = MAXFILES;
|
||||
|
||||
/* Move to DVD structure - this is required for the file selector */
|
||||
while (entries)
|
||||
{
|
||||
memset (&filelist[nbfiles], 0, sizeof (FILEENTRIES));
|
||||
strncpy(filelist[nbfiles].filename,sddir[nbfiles].fname,MAXJOLIET);
|
||||
filelist[nbfiles].filename[MAXJOLIET-1] = 0;
|
||||
filelist[nbfiles].length = sddir[nbfiles].fsize;
|
||||
filelist[nbfiles].flags = (char)(sddir[nbfiles].fattr & SDCARD_ATTR_DIR);
|
||||
nbfiles++;
|
||||
entries--;
|
||||
}
|
||||
|
||||
/*** Release memory ***/
|
||||
free(sddir);
|
||||
|
||||
return nbfiles;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* FileSelector
|
||||
*
|
||||
* Let user select a file from the File listing
|
||||
****************************************************************************/
|
||||
void FileSelector ()
|
||||
{
|
||||
short p;
|
||||
signed char a,b;
|
||||
int haverom = 0;
|
||||
int redraw = 1;
|
||||
int go_up = 0;
|
||||
int i,size;
|
||||
|
||||
while (haverom == 0)
|
||||
{
|
||||
if (redraw) ShowFiles (offset, selection);
|
||||
redraw = 0;
|
||||
p = PAD_ButtonsDown (0);
|
||||
a = PAD_StickY (0);
|
||||
b = PAD_StickX (0);
|
||||
|
||||
/*
|
||||
* check selection screen changes
|
||||
*/
|
||||
|
||||
/* scroll displayed filename */
|
||||
if ((p & PAD_BUTTON_LEFT) || (b < -PADCAL))
|
||||
{
|
||||
if (filelist[selection].filename_offset > 0)
|
||||
{
|
||||
filelist[selection].filename_offset --;
|
||||
redraw = 1;
|
||||
}
|
||||
}
|
||||
else if ((p & PAD_BUTTON_RIGHT) || (b > PADCAL))
|
||||
{
|
||||
size = 0;
|
||||
for (i=filelist[selection].filename_offset; i<strlen(filelist[selection].filename); i++)
|
||||
size += font_size[(int)filelist[selection].filename[i]];
|
||||
|
||||
if (size > back_framewidth)
|
||||
{
|
||||
filelist[selection].filename_offset ++;
|
||||
redraw = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* highlight next item */
|
||||
else if ((p & PAD_BUTTON_DOWN) || (a < -PADCAL))
|
||||
{
|
||||
filelist[selection].filename_offset = 0;
|
||||
selection++;
|
||||
if (selection == maxfiles) selection = offset = 0;
|
||||
if ((selection - offset) >= PAGESIZE) offset += PAGESIZE;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
/* highlight previous item */
|
||||
else if ((p & PAD_BUTTON_UP) || (a > PADCAL))
|
||||
{
|
||||
filelist[selection].filename_offset = 0;
|
||||
selection--;
|
||||
if (selection < 0)
|
||||
{
|
||||
selection = maxfiles - 1;
|
||||
offset = selection - PAGESIZE + 1;
|
||||
}
|
||||
if (selection < offset) offset -= PAGESIZE;
|
||||
if (offset < 0) offset = 0;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
/* go back one page */
|
||||
else if (p & PAD_TRIGGER_L)
|
||||
{
|
||||
filelist[selection].filename_offset = 0;
|
||||
selection -= PAGESIZE;
|
||||
if (selection < 0)
|
||||
{
|
||||
selection = maxfiles - 1;
|
||||
offset = selection - PAGESIZE + 1;
|
||||
}
|
||||
if (selection < offset) offset -= PAGESIZE;
|
||||
if (offset < 0) offset = 0;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
/* go forward one page */
|
||||
else if (p & PAD_TRIGGER_R)
|
||||
{
|
||||
filelist[selection].filename_offset = 0;
|
||||
selection += PAGESIZE;
|
||||
if (selection > maxfiles - 1) selection = offset = 0;
|
||||
if ((selection - offset) >= PAGESIZE) offset += PAGESIZE;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check pressed key
|
||||
*/
|
||||
|
||||
/* go up one directory or quit */
|
||||
if (p & PAD_BUTTON_B)
|
||||
{
|
||||
filelist[selection].filename_offset = 0;
|
||||
if (((!UseSDCARD) && (basedir == rootdir)) ||
|
||||
(UseSDCARD && strcmp(rootSDdir,"dev0:\\genplus\\..") == 0)) return;
|
||||
go_up = 1;
|
||||
}
|
||||
|
||||
/* quit */
|
||||
if (p & PAD_TRIGGER_Z)
|
||||
{
|
||||
filelist[selection].filename_offset = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* open selected file or directory */
|
||||
if ((p & PAD_BUTTON_A) || go_up)
|
||||
{
|
||||
filelist[selection].filename_offset = 0;
|
||||
if (go_up)
|
||||
{
|
||||
go_up = 0;
|
||||
selection = 1;
|
||||
}
|
||||
|
||||
/*** This is directory ***/
|
||||
if (filelist[selection].flags)
|
||||
{
|
||||
if (UseSDCARD) /* SDCARD directory handler */
|
||||
{
|
||||
/* update current directory */
|
||||
int status = updateSDdirname();
|
||||
|
||||
/* move to new directory */
|
||||
if (status == 1)
|
||||
{
|
||||
/* reinit selector (previous value is saved for one level) */
|
||||
if (selection == 1)
|
||||
{
|
||||
selection = old_selection;
|
||||
offset = old_offset;
|
||||
old_selection = 0;
|
||||
old_offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* save current selector value */
|
||||
old_selection = selection;
|
||||
old_offset = offset;
|
||||
selection = 0;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
|
||||
/* set new entry list */
|
||||
maxfiles = parseSDdirectory();
|
||||
if (!maxfiles)
|
||||
{
|
||||
/* quit */
|
||||
WaitPrompt ("Error reading directory !");
|
||||
haverom = 1;
|
||||
haveSDdir = 0;
|
||||
}
|
||||
}
|
||||
else if (status == -1)
|
||||
{
|
||||
/* quit */
|
||||
haverom = 1;
|
||||
haveSDdir = 0;
|
||||
}
|
||||
}
|
||||
else /* DVD directory handler */
|
||||
{
|
||||
/* move to a new directory */
|
||||
if (selection != 0)
|
||||
{
|
||||
/* update current directory */
|
||||
rootdir = filelist[selection].offset;
|
||||
rootdirlength = filelist[selection].length;
|
||||
|
||||
/* reinit selector (previous value is saved for one level) */
|
||||
if (selection == 1)
|
||||
{
|
||||
selection = old_selection;
|
||||
offset = old_offset;
|
||||
old_selection = 0;
|
||||
old_offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* save current selector value */
|
||||
old_selection = selection;
|
||||
old_offset = offset;
|
||||
selection = 0;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
/* get new entry list */
|
||||
maxfiles = parsedirectory ();
|
||||
}
|
||||
}
|
||||
}
|
||||
else /*** This is a file ***/
|
||||
{
|
||||
rootdir = filelist[selection].offset;
|
||||
rootdirlength = filelist[selection].length;
|
||||
genromsize = LoadFile (cart_rom);
|
||||
reloadrom ();
|
||||
haverom = 1;
|
||||
}
|
||||
redraw = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* OpenDVD
|
||||
*
|
||||
* Function to load a DVD directory and display to user.
|
||||
****************************************************************************/
|
||||
void OpenDVD ()
|
||||
{
|
||||
UseSDCARD = 0;
|
||||
if (!getpvd())
|
||||
{
|
||||
ShowAction("Mounting DVD ... Wait");
|
||||
DVD_Mount();
|
||||
havedir = 0;
|
||||
if (!getpvd())
|
||||
{
|
||||
WaitPrompt ("Failed to mount DVD");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (havedir == 0)
|
||||
{
|
||||
/* don't mess with SD entries */
|
||||
haveSDdir = 0;
|
||||
|
||||
/* reinit selector */
|
||||
rootdir = basedir;
|
||||
old_selection = selection = offset = old_offset = 0;
|
||||
|
||||
if ((maxfiles = parsedirectory ()))
|
||||
{
|
||||
FileSelector ();
|
||||
havedir = 1;
|
||||
}
|
||||
}
|
||||
else FileSelector ();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* OpenSD updated to use the new libogc. Written by softdev and pasted
|
||||
* into this code by Drack.
|
||||
* Modified for subdirectory browing & quick filelist recovery
|
||||
* Enjoy!
|
||||
*****************************************************************************/
|
||||
int OpenSD ()
|
||||
{
|
||||
UseSDCARD = 1;
|
||||
|
||||
if (haveSDdir == 0)
|
||||
{
|
||||
/* don't mess with DVD entries */
|
||||
havedir = 0;
|
||||
|
||||
/* reinit selector */
|
||||
old_selection = selection = offset = old_offset = 0;
|
||||
|
||||
/* Reset SDCARD root directory */
|
||||
sprintf(rootSDdir,"dev0:\\genplus\\roms");
|
||||
|
||||
/* Parse initial root directory and get entries list */
|
||||
ShowAction("Reading Directory ...");
|
||||
if ((maxfiles = parseSDdirectory ()))
|
||||
{
|
||||
/* Select an entry */
|
||||
FileSelector ();
|
||||
|
||||
/* memorize last entries list, actual root directory and selection for next access */
|
||||
haveSDdir = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no entries found */
|
||||
WaitPrompt ("Error reading dev0:\\genplus\\roms");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Retrieve previous entries list and made a new selection */
|
||||
else FileSelector ();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* SDCard Get Info
|
||||
****************************************************************************/
|
||||
void GetSDInfo ()
|
||||
{
|
||||
char fname[SDCARD_MAX_PATH_LEN];
|
||||
rootdirlength = 0;
|
||||
|
||||
/* Check filename length */
|
||||
if ((strlen(rootSDdir)+1+strlen(filelist[selection].filename)) < SDCARD_MAX_PATH_LEN)
|
||||
sprintf(fname, "%s\\%s",rootSDdir,filelist[selection].filename);
|
||||
|
||||
else
|
||||
{
|
||||
WaitPrompt ("Maximum Filename Length reached !");
|
||||
haveSDdir = 0; // reset everything before next access
|
||||
}
|
||||
|
||||
filehandle = SDCARD_OpenFile (fname, "rb");
|
||||
if (filehandle == NULL)
|
||||
{
|
||||
WaitPrompt ("Unable to open file!");
|
||||
return;
|
||||
}
|
||||
rootdirlength = SDCARD_GetFileSize (filehandle);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* LoadFile
|
||||
*
|
||||
* This function will load a file from DVD or SDCARD, in BIN, SMD or ZIP format.
|
||||
* The values for offset and length are inherited from rootdir and
|
||||
* rootdirlength.
|
||||
*
|
||||
* The buffer parameter should re-use the initial ROM buffer.
|
||||
****************************************************************************/
|
||||
int LoadFile (unsigned char *buffer)
|
||||
{
|
||||
int offset;
|
||||
int blocks;
|
||||
int i;
|
||||
u64 discoffset;
|
||||
char readbuffer[2048];
|
||||
|
||||
/* SDCard Addition */
|
||||
if (UseSDCARD) GetSDInfo ();
|
||||
|
||||
/* How many 2k blocks to read */
|
||||
if (rootdirlength == 0) return 0;
|
||||
blocks = rootdirlength / 2048;
|
||||
|
||||
offset = 0;
|
||||
discoffset = rootdir;
|
||||
ShowAction ("Loading ... Wait");
|
||||
|
||||
if (UseSDCARD) SDCARD_ReadFile (filehandle, &readbuffer, 2048);
|
||||
else dvd_read (&readbuffer, 2048, discoffset);
|
||||
|
||||
if (!IsZipFile ((char *) readbuffer))
|
||||
{
|
||||
if (UseSDCARD) SDCARD_SeekFile (filehandle, 0, SDCARD_SEEK_SET);
|
||||
|
||||
for (i = 0; i < blocks; i++)
|
||||
{
|
||||
if (UseSDCARD) SDCARD_ReadFile (filehandle, &readbuffer, 2048);
|
||||
else dvd_read(readbuffer, 2048, discoffset);
|
||||
memcpy (buffer + offset, readbuffer, 2048);
|
||||
offset += 2048;
|
||||
discoffset += 2048;
|
||||
}
|
||||
|
||||
/* And final cleanup */
|
||||
if (rootdirlength % 2048)
|
||||
{
|
||||
i = rootdirlength % 2048;
|
||||
if (UseSDCARD) SDCARD_ReadFile (filehandle, &readbuffer, i);
|
||||
else dvd_read (readbuffer, 2048, discoffset);
|
||||
memcpy (buffer + offset, readbuffer, i);
|
||||
}
|
||||
}
|
||||
else return UnZipBuffer (buffer, discoffset, rootdirlength);
|
||||
|
||||
if (UseSDCARD) SDCARD_CloseFile (filehandle);
|
||||
|
||||
return rootdirlength;
|
||||
}
|
@ -1,24 +1,3 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* IPL FONT Engine
|
||||
*
|
||||
@ -26,9 +5,613 @@
|
||||
* Added IPL font extraction
|
||||
*****************************************************************************/
|
||||
#include "shared.h"
|
||||
#include "font.h"
|
||||
#include "gpback.h"
|
||||
|
||||
/*** IPL Font (ripped from original BOOTROM) ***/
|
||||
static unsigned char iplfont[]=
|
||||
{
|
||||
0x59,0x61,0x79,0x30,0x00,0x01,0x01,0x10,0x00,0x00,0x03,0x08,0x00,0x00,0x13,0x94,
|
||||
0xfd,0x77,0x7e,0xfb,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xfb,0xff,0xff,
|
||||
0xfe,0xff,0x7f,0x9f,0xff,0xff,0xfd,0xed,0xdb,0xb3,0x3f,0x73,0x27,0xdf,0xbe,0xfb,
|
||||
0xe7,0x3e,0xe9,0xfd,0xf9,0x51,0xfd,0xf7,0xdf,0x7d,0x5f,0x77,0xee,0x7d,0xdf,0xff,
|
||||
0xfb,0xff,0x7f,0xfb,0xbf,0xb7,0xef,0xff,0xeb,0xff,0xdf,0xaf,0x7d,0xf1,0xdd,0x7f,
|
||||
0xff,0xbf,0xb3,0xff,0x7e,0x9f,0xbf,0x7f,0xfe,0xbf,0xdf,0xf4,0xfe,0x7d,0xff,0xff,
|
||||
0xba,0x6f,0xe5,0xff,0xfe,0xd4,0xbf,0xf7,0xbe,0x7e,0xbf,0xcf,0xbf,0xf5,0x6b,0xfd,
|
||||
0xff,0xd7,0xd5,0x7f,0x7a,0xd0,0xbe,0xd3,0xf5,0xfe,0xff,0xe5,0xbf,0x7e,0xf9,0xfc,
|
||||
0x79,0x67,0xe8,0x35,0xbe,0x9b,0xbf,0x72,0xf0,0xcf,0x49,0xf7,0xd5,0x72,0xb6,0x7c,
|
||||
0xff,0xf5,0xa3,0xfc,0xfa,0xba,0xa9,0x97,0xb5,0xb9,0xfb,0x1f,0xff,0xc0,0xb2,0x2f,
|
||||
0xf4,0xe7,0x3f,0xff,0xfe,0xff,0x43,0xff,0x6f,0x69,0xaf,0xdc,0xe7,0x8c,0x48,0xaa,
|
||||
0x3f,0x00,0x0f,0x70,0x73,0x28,0x3b,0x1f,0x1a,0x7f,0xa4,0xff,0x42,0x7a,0x7f,0x6b,
|
||||
0x74,0x8f,0xaa,0xbc,0xaf,0xa3,0xcd,0x5e,0x02,0x16,0x3e,0xaa,0xfc,0x55,0xce,0x2d,
|
||||
0x7b,0x3c,0xa9,0x57,0xd2,0x72,0x7f,0x7f,0x7f,0xaf,0xb4,0x3f,0xec,0xab,0xff,0xff,
|
||||
0xff,0xfd,0xff,0xfe,0xff,0xea,0x6a,0x93,0xa0,0x49,0x4f,0xc6,0x9e,0x04,0xb6,0x7f,
|
||||
0xfd,0xff,0xfa,0x54,0xf4,0xcb,0xa9,0x3d,0x0a,0x14,0xa7,0xe3,0x77,0xd2,0xdf,0xfd,
|
||||
0xff,0xe2,0xff,0x8e,0x07,0xff,0x89,0x8e,0x80,0x88,0x73,0x7a,0x71,0x04,0x6f,0xbf,
|
||||
0x52,0x9f,0x3f,0xd2,0x9f,0x1c,0x18,0xf7,0xff,0x82,0x95,0x7f,0xae,0x64,0x3d,0xd7,
|
||||
0x9e,0x0b,0xa3,0xfc,0x81,0x17,0xa8,0x7f,0x9f,0xd3,0xf9,0x6a,0xb2,0x88,0xb4,0xf1,
|
||||
0x2d,0xef,0xaf,0xd7,0xc7,0xc0,0x50,0xb6,0xe4,0xce,0xff,0xf7,0xe8,0x50,0xfe,0xd4,
|
||||
0x80,0x31,0x3e,0x32,0x1a,0x27,0x9f,0xb9,0xfe,0x3f,0x11,0xb9,0xdd,0xcf,0xe0,0x9b,
|
||||
0xe5,0xff,0xef,0xfc,0x9f,0x54,0x5f,0x53,0xa4,0xff,0xc4,0x4d,0xfe,0xff,0x53,0xff,
|
||||
0x7f,0xdf,0x87,0xfd,0xff,0x7e,0x57,0xea,0xa6,0x4f,0xca,0xc8,0xfd,0x7f,0xfb,0xf2,
|
||||
0xed,0x78,0xfb,0x57,0xff,0xc9,0xfc,0x9f,0xf4,0x75,0xff,0x5b,0xf3,0xfb,0xfa,0xa8,
|
||||
0x7d,0xef,0xdd,0x3a,0x3e,0xfd,0x5b,0xe9,0xe3,0xf9,0x27,0xfd,0xef,0x3f,0xf7,0x44,
|
||||
0xde,0xff,0x7e,0xbf,0x9d,0xab,0xfd,0xea,0xad,0xf1,0x63,0xfc,0xf9,0x98,0x3c,0xca,
|
||||
0x9b,0x7c,0xdf,0xea,0xfd,0x57,0x42,0xfc,0xff,0xfa,0xff,0x7f,0xef,0xf9,0xf9,0x7d,
|
||||
0xaa,0x0b,0xf9,0x74,0xcd,0xff,0x74,0xff,0xcf,0xfb,0xff,0x56,0xaa,0x56,0x6f,0xf5,
|
||||
0x3d,0xf5,0x1a,0xad,0x2d,0xff,0x57,0xbd,0xd5,0x00,0x7f,0xf9,0x57,0xfe,0xd6,0x95,
|
||||
0xdf,0xd8,0xa9,0xff,0xfb,0xf3,0x7f,0xfe,0xaf,0xf7,0xfe,0x5f,0xff,0xbf,0x13,0xf7,
|
||||
0xd2,0xff,0xdf,0xf7,0xde,0xff,0xfd,0x7f,0xff,0xc7,0xd0,0xb6,0xff,0xff,0xc7,0xd5,
|
||||
0xff,0x7c,0xfe,0x28,0x57,0xab,0xf9,0x7b,0xf3,0xdf,0xee,0x9f,0xab,0xdd,0x55,0xe9,
|
||||
0xef,0x93,0xd4,0xac,0x97,0x09,0x6f,0xf1,0xfe,0xfa,0xbf,0xef,0xfd,0x7f,0x9d,0x3d,
|
||||
0xf2,0xa4,0x3a,0x25,0x55,0xef,0xfa,0x92,0xa5,0x50,0xcd,0xfd,0x63,0xab,0xec,0x69,
|
||||
0x3f,0x1e,0xee,0x4d,0xff,0xff,0xef,0x9f,0xfe,0xbf,0xfa,0x57,0xc2,0xff,0x5f,0xe2,
|
||||
0xaa,0xaa,0xb7,0x58,0xa7,0xc4,0xd9,0xed,0xfa,0xa0,0x6f,0x97,0xfa,0x9d,0xbf,0xc9,
|
||||
0xac,0xa7,0x7a,0x57,0xbd,0xff,0x7c,0xf5,0x16,0xaa,0xbc,0x7a,0xbd,0x27,0xd6,0xaf,
|
||||
0xf3,0x98,0xbe,0x97,0xd5,0xd2,0x7f,0x5e,0x5f,0xed,0x96,0xff,0x3f,0x42,0xe9,0x52,
|
||||
0x55,0xc4,0x52,0x58,0x8e,0x57,0x55,0x52,0xca,0x65,0x7b,0xdc,0x5d,0x41,0xff,0x5b,
|
||||
0x2f,0xff,0xf9,0xf7,0xaf,0xea,0x7c,0x89,0x09,0xea,0x7c,0xf4,0xdf,0xff,0xa3,0x07,
|
||||
0xbe,0x22,0x5f,0x4c,0xff,0xf2,0xbf,0xe1,0x7f,0xaa,0x32,0xaf,0xd5,0xfe,0xd1,0xcc,
|
||||
0xf7,0xaa,0x54,0xc5,0x80,0xf4,0x5f,0xde,0xc3,0xba,0xc0,0x81,0x31,0x5c,0xb2,0x7f,
|
||||
0xc9,0xac,0xbd,0xfe,0x39,0xff,0xf2,0x8a,0xd5,0x34,0x2d,0xe4,0x83,0xff,0x7f,0xf4,
|
||||
0xff,0x0b,0xff,0xf5,0xaa,0xa2,0x49,0xd1,0x0b,0xe3,0x73,0x7f,0x97,0xf0,0xaa,0x0a,
|
||||
0x8d,0xf3,0xe5,0xca,0x3f,0x6f,0xdf,0xfd,0x6e,0xa9,0xb5,0x51,0x13,0x7f,0x47,0x56,
|
||||
0xfe,0xb1,0x51,0x54,0xa6,0x0c,0x16,0xef,0x55,0xa9,0xc5,0x52,0x8f,0xcf,0xcd,0xf7,
|
||||
0x7d,0x22,0x0a,0x88,0xca,0x4f,0xf2,0xe2,0x80,0x65,0x41,0x6b,0x68,0x5f,0xfd,0x85,
|
||||
0xfd,0xca,0x58,0xfe,0xb3,0xfb,0x52,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x03,0x10,0x09,0x10,0x07,0x10,0x15,
|
||||
0x20,0x0a,0x30,0x13,0x10,0x0e,0x10,0x0a,0x10,0x06,0x10,0x17,0x10,0x1e,0x10,0x6b,
|
||||
0x10,0x00,0x10,0x58,0x10,0x00,0x20,0x12,0x10,0x85,0x50,0x00,0x20,0x00,0x20,0x1f,
|
||||
0x40,0x10,0x10,0x88,0x00,0x00,0x10,0x01,0x00,0x3f,0x20,0x01,0x80,0x6f,0x30,0x01,
|
||||
0x00,0x7f,0x80,0x9f,0x00,0x2d,0x80,0xcf,0x00,0x60,0x90,0x5f,0x12,0x05,0xc0,0x9f,
|
||||
0xb1,0x1d,0xa0,0x5f,0x01,0x3e,0x30,0x01,0x01,0x5f,0x01,0x8f,0x00,0x2f,0x51,0xe7,
|
||||
0x01,0xef,0xa2,0x1f,0x10,0xf1,0x00,0x00,0x70,0xcf,0xa2,0xfe,0x83,0x0f,0x01,0x8f,
|
||||
0x03,0x3f,0x83,0x6f,0x10,0x5f,0x01,0xef,0xb0,0x8f,0x03,0xaf,0x01,0xb0,0xb0,0x01,
|
||||
0x04,0x3f,0x94,0x65,0x04,0x72,0x10,0x00,0xe4,0xaf,0x14,0x2f,0x45,0xcc,0xf4,0x2f,
|
||||
0x20,0x01,0x23,0xf3,0x92,0xe0,0x12,0x1d,0x11,0x8d,0x12,0x35,0x20,0xc7,0xf3,0x10,
|
||||
0x05,0x54,0x10,0xdb,0x60,0x01,0x05,0x8f,0x10,0x82,0x30,0x01,0x05,0xbf,0x13,0xd2,
|
||||
0x12,0xe1,0x03,0xf1,0x30,0x01,0x40,0x01,0x83,0xff,0x01,0xc9,0x06,0x5a,0x86,0x7d,
|
||||
0x04,0x5e,0x15,0xb1,0xd6,0x73,0x50,0x01,0x36,0xdc,0x10,0x07,0xd7,0x20,0x80,0x01,
|
||||
0x07,0x40,0x42,0xf2,0x03,0x0b,0x23,0x20,0x30,0x90,0x26,0x94,0x10,0x2f,0x20,0x9b,
|
||||
0x05,0xa1,0x17,0x25,0x50,0x01,0xc7,0xdf,0x05,0xbf,0x21,0xbb,0x37,0xf9,0x06,0x0b,
|
||||
0x31,0x07,0x13,0x71,0x07,0x36,0x18,0x55,0x18,0x2d,0x13,0x4f,0x08,0xd8,0x22,0x0f,
|
||||
0x40,0x5f,0x20,0x3d,0x13,0x56,0x10,0x1e,0x61,0x9b,0x12,0x3e,0x2a,0x25,0x97,0x1b,
|
||||
0x03,0x0b,0x27,0xc7,0x17,0xff,0x09,0x8d,0x13,0xff,0x07,0xcc,0x13,0x01,0x72,0xef,
|
||||
0x00,0xad,0x70,0x01,0x54,0x6e,0x64,0x01,0x04,0x60,0x20,0x01,0x08,0x1d,0x20,0x01,
|
||||
0x01,0x50,0x13,0xca,0x3b,0xe2,0x06,0x6f,0x61,0xff,0x0b,0x1a,0x83,0xfb,0x0b,0x3b,
|
||||
0x24,0x01,0x8b,0x6b,0x03,0x01,0x62,0x6f,0x1a,0x62,0x00,0x8f,0x35,0xa5,0x9b,0xc4,
|
||||
0x43,0xfd,0x43,0x3f,0x03,0xf3,0x17,0x79,0x94,0x2f,0x0c,0x1f,0xc8,0xcf,0x38,0x9f,
|
||||
0x0a,0x20,0x56,0x51,0xb5,0xf1,0x08,0xff,0xb9,0x2f,0x08,0xff,0x8c,0xcf,0x09,0x5f,
|
||||
0x0a,0xcb,0x0b,0x40,0x09,0xdf,0xab,0xcd,0x09,0x8c,0x16,0xaf,0x9b,0xf0,0x46,0x93,
|
||||
0xa4,0xf7,0xcd,0x3f,0xad,0xaf,0x06,0xae,0x9c,0x8a,0x98,0x01,0x20,0x8f,0x0e,0x10,
|
||||
0x19,0x83,0x9b,0x6f,0x02,0x3f,0x98,0x61,0x2b,0xd1,0x00,0x2f,0xa8,0x91,0xb3,0x5a,
|
||||
0x02,0xcf,0x98,0xc1,0x11,0x4f,0x03,0x2f,0x25,0x59,0x9f,0x9f,0x00,0x2f,0x06,0x7f,
|
||||
0x5b,0x9a,0x1c,0xf9,0x19,0x09,0x19,0x09,0xe6,0xaf,0x24,0xcd,0x10,0x09,0x10,0x91,
|
||||
0x58,0x9d,0x0e,0x49,0x19,0x8b,0x2d,0x77,0x1d,0x79,0x1b,0x61,0x06,0x4d,0x47,0x6f,
|
||||
0x12,0xad,0x2a,0x80,0x19,0x2f,0x18,0xff,0x0f,0x70,0x29,0xa8,0x16,0x23,0x1a,0xe3,
|
||||
0x11,0x23,0x25,0x33,0xff,0xa0,0x06,0x4b,0x00,0x2f,0x3e,0x5a,0x0f,0xd4,0x2b,0x6b,
|
||||
0x46,0x1d,0x18,0xfd,0x2b,0x0b,0x1b,0x6b,0x36,0x2d,0x6b,0x6b,0x6d,0x3d,0x1b,0xb4,
|
||||
0x1e,0xa9,0x9f,0x97,0x1e,0xc5,0x03,0x3f,0x1c,0x28,0x73,0x9d,0x16,0xef,0x17,0xaf,
|
||||
0xfb,0x09,0x5b,0x0f,0x1a,0x4f,0x1c,0x37,0x70,0x01,0x1c,0x3e,0x10,0x53,0x1e,0x14,
|
||||
0x1e,0x21,0x31,0xc3,0xfe,0xaf,0x50,0x01,0x13,0xfd,0x20,0x0b,0x10,0x01,0x10,0x8f,
|
||||
0x07,0x3f,0x30,0x01,0x13,0x0f,0x0e,0x9f,0xc0,0x01,0x12,0x13,0x1b,0x45,0x13,0x3d,
|
||||
0xfd,0xaf,0x60,0x2f,0x14,0x2b,0x2b,0xf2,0x6f,0xff,0x04,0xbb,0x7c,0x29,0x23,0xfd,
|
||||
0x85,0x0e,0x1c,0x36,0x0b,0xff,0x80,0x8d,0x33,0x2f,0x2f,0xff,0x02,0xcf,0x49,0x4d,
|
||||
0x19,0x53,0x21,0x1f,0x19,0x59,0x30,0xb7,0x13,0xf7,0x28,0x31,0x03,0xff,0x70,0x2f,
|
||||
0x50,0x37,0x0f,0xef,0x1f,0x0d,0x48,0xff,0x38,0x6f,0x1c,0x6f,0x08,0x6f,0x19,0xef,
|
||||
0x16,0x3a,0x69,0x2f,0x08,0x9f,0x1f,0x10,0x5d,0x5c,0x68,0x8f,0x0b,0x2d,0x53,0xcb,
|
||||
0x7b,0x6f,0x1d,0x8b,0x00,0x5f,0x1a,0x1f,0x8b,0x9f,0x24,0x2d,0x16,0x4f,0x03,0xcf,
|
||||
0x44,0x2f,0x0a,0xdd,0x1e,0x71,0x9f,0xff,0x1c,0xc0,0x0c,0xef,0xbf,0xf3,0xd0,0x0f,
|
||||
0xfd,0xb1,0x50,0x4e,0x00,0xe7,0x9a,0x4e,0x27,0x39,0x2e,0xe0,0xac,0xad,0x0f,0xbb,
|
||||
0x1a,0x3b,0x10,0xc7,0x3c,0xdf,0x1c,0xf0,0x6c,0xe9,0x9f,0xf9,0x26,0x41,0x5e,0x0f,
|
||||
0x15,0xaf,0x1d,0x3e,0x0e,0x20,0x83,0xfd,0x4b,0x0f,0x1e,0xdd,0x0f,0x3f,0x12,0x6d,
|
||||
0x12,0x9d,0x74,0xf3,0x0b,0x0f,0x3f,0xb6,0x23,0xcd,0x3b,0x5f,0x10,0x5d,0x04,0x2f,
|
||||
0x30,0x2f,0xab,0x9f,0x03,0xff,0x0e,0xff,0x10,0xc1,0x1e,0x3d,0x51,0x7f,0x02,0xcf,
|
||||
0x83,0xcf,0x4c,0xef,0x63,0xff,0x64,0x37,0x00,0x2f,0x0f,0xe0,0x19,0xbd,0x99,0xbf,
|
||||
0x26,0x75,0x09,0x8e,0xba,0x0e,0x27,0xd9,0x00,0x2f,0x0f,0x30,0xaa,0xdf,0x1f,0xa3,
|
||||
0x00,0x9f,0x17,0x6f,0x9c,0x1f,0x0a,0x4f,0x0c,0xbf,0xa9,0xef,0x13,0xd9,0x09,0xef,
|
||||
0xcd,0x1f,0x0b,0x0f,0x19,0x85,0x0c,0xef,0x1d,0x1f,0x9c,0xef,0x1b,0xcf,0x0d,0x7f,
|
||||
0x9d,0xdf,0x04,0x3c,0xa7,0x0f,0x1b,0xde,0x0d,0x4f,0x14,0x64,0xba,0xaf,0x18,0x13,
|
||||
0x00,0x5f,0xac,0x4e,0x18,0xd8,0xb0,0x7f,0xb9,0xee,0xa1,0xdf,0x13,0xdb,0x0c,0xff,
|
||||
0x26,0xa9,0xad,0x1f,0x00,0xbf,0xee,0x9f,0x1b,0x05,0x0f,0x3c,0x0e,0x5e,0x0e,0x8f,
|
||||
0x0f,0xbc,0x1f,0x8b,0xaa,0x17,0x0e,0x6e,0xc0,0x01,0x23,0xf3,0xa0,0x03,0xfb,0x6f,
|
||||
0x1c,0xfd,0x1b,0xf4,0x6a,0x47,0x1b,0xcd,0x05,0x2f,0x03,0xff,0xe0,0x9f,0x23,0xf3,
|
||||
0xfa,0x7f,0x12,0x33,0x5a,0x4f,0x1a,0x8b,0x2c,0xb3,0x79,0xd6,0xef,0xff,0x70,0x01,
|
||||
0x39,0xf1,0x1c,0x67,0x3a,0xb1,0x1b,0x43,0x0d,0x4f,0x1c,0xdf,0x1a,0xab,0x20,0x2f,
|
||||
0x39,0x2b,0x1d,0x45,0x37,0x0d,0x2c,0xa6,0x0d,0x4f,0x79,0xef,0x1f,0x0d,0x22,0xb1,
|
||||
0x23,0x65,0x0d,0x4e,0x2b,0xbd,0x17,0x13,0x57,0x11,0x5c,0xcb,0x23,0xfd,0x01,0xdf,
|
||||
0xeb,0x3f,0x23,0xf3,0xa0,0x03,0x07,0x9f,0x1b,0x61,0x1b,0x61,0x37,0xf7,0x13,0x63,
|
||||
0x10,0xbf,0x4a,0xf7,0x0a,0x3f,0x17,0x69,0x1e,0x19,0x1e,0x1b,0x4e,0x1d,0x2e,0x5f,
|
||||
0x17,0x3b,0x1c,0xbd,0x2c,0xbf,0x5e,0x3d,0x1e,0x43,0x0e,0x6e,0x1b,0xe3,0x2e,0x87,
|
||||
0x1c,0xed,0x21,0xed,0x11,0x78,0x5e,0x71,0x0f,0xff,0x1e,0x99,0x2c,0xc7,0x3e,0x9b,
|
||||
0xb8,0xe3,0xb9,0x1f,0xd0,0x01,0x0f,0x6f,0x30,0xbb,0xa7,0x57,0x23,0x27,0x10,0x16,
|
||||
0x14,0xcf,0x0f,0xff,0xd0,0x01,0x0f,0xd0,0xdf,0xf0,0x0c,0x00,0x27,0xf3,0x3b,0x30,
|
||||
0x43,0xff,0x0b,0x9f,0xc8,0xff,0x28,0xe3,0x0d,0x2f,0x1d,0x2b,0x99,0x5f,0x16,0xa9,
|
||||
0x09,0x5f,0x3f,0xea,0x80,0x9f,0x80,0xa3,0x7e,0x4f,0x4f,0xd3,0x00,0x8f,0x9a,0x4f,
|
||||
0x4f,0xd4,0x0c,0xef,0x83,0xff,0x09,0xef,0x11,0x09,0xa9,0xed,0x1d,0xef,0x09,0xef,
|
||||
0x3c,0xfd,0x2e,0xb3,0x0e,0x4e,0x2c,0xed,0x4d,0xaf,0x3d,0x1f,0x1f,0x99,0x2b,0x3f,
|
||||
0x05,0xdf,0x01,0x3f,0x0d,0x7f,0x8d,0x4f,0x23,0xcb,0x10,0x5f,0x1f,0x9f,0x05,0xb0,
|
||||
0x2f,0xee,0x1d,0xe5,0x4c,0x2f,0x27,0xb3,0x43,0xc1,0x00,0x2f,0x15,0xd1,0x19,0x38,
|
||||
0x31,0xe0,0x37,0xf8,0x8e,0x1f,0xb2,0x7f,0x27,0xe7,0xa1,0x1f,0x14,0x71,0x15,0x57,
|
||||
0x01,0x1f,0x1d,0x7d,0x60,0x01,0x3c,0xbf,0x70,0x01,0x0e,0x73,0x26,0x0f,0xfb,0xff,
|
||||
0x03,0xff,0x0b,0x72,0x1f,0x0f,0x7c,0xcb,0x57,0xa7,0x16,0x1a,0x1e,0x65,0x83,0xff,
|
||||
0x00,0x5f,0x00,0x32,0x00,0xa1,0x37,0x7b,0x01,0x01,0x1a,0xbd,0x0c,0xf0,0x0d,0x5f,
|
||||
0x01,0xc1,0xeb,0x9f,0x00,0xdf,0x10,0x01,0x0e,0x3e,0x2f,0xdb,0x0e,0x84,0x2c,0x2f,
|
||||
0x02,0xe1,0x00,0x99,0x4b,0xff,0x03,0xf5,0x3f,0x6f,0x24,0xef,0x2b,0x16,0x20,0x01,
|
||||
0x0b,0x6f,0x18,0x8d,0x10,0x67,0x53,0xff,0x1c,0xc5,0x1b,0x3a,0x02,0x2f,0x5e,0xaf,
|
||||
0x1a,0x88,0x0d,0x5a,0x20,0x2f,0x4b,0xa5,0x2b,0x7f,0x15,0xed,0x1b,0xd7,0x30,0x01,
|
||||
0x0d,0xea,0x3c,0x35,0x40,0x5f,0x29,0xbd,0xff,0x6f,0x27,0x8f,0x27,0x97,0x27,0x9b,
|
||||
0x0d,0xea,0x30,0x8f,0x2c,0x93,0x4f,0x3f,0x1c,0x9f,0x10,0x01,0x03,0x4f,0x1f,0x93,
|
||||
0x7f,0x9f,0x26,0x3f,0x1f,0x2d,0x20,0x01,0x00,0xbc,0xa9,0x23,0x03,0x9f,0x28,0x75,
|
||||
0x90,0x01,0x0e,0xe1,0x59,0x7f,0x1d,0x7d,0x31,0xdf,0x1e,0x77,0x0b,0x3f,0x2d,0x77,
|
||||
0xa0,0x03,0x0f,0x0a,0x20,0x01,0x1f,0xff,0x39,0xe4,0x6b,0x53,0x9e,0xaf,0x60,0xef,
|
||||
0x41,0xaf,0x0e,0x7f,0x22,0x3f,0x62,0x3f,0x1f,0x35,0x1c,0x72,0x02,0x0f,0x1b,0x2d,
|
||||
0xc2,0x9f,0x32,0x9f,0x21,0xc1,0x02,0x9f,0x12,0x6f,0x2d,0x0f,0x45,0x1f,0x02,0x6f,
|
||||
0x2f,0x5d,0x0f,0x2f,0x2b,0x4e,0x2e,0xcb,0x39,0xb5,0x53,0x5f,0x3c,0x69,0x06,0x7e,
|
||||
0x1b,0xa3,0x93,0xb4,0xa0,0x0f,0x04,0x2f,0x1e,0xfa,0x3a,0xcf,0x1e,0x24,0x5b,0xaf,
|
||||
0x0f,0x6f,0x1f,0x9b,0x52,0x2f,0x2b,0xa2,0x1e,0x13,0x0a,0xaf,0x2f,0x65,0x3a,0xaf,
|
||||
0x7b,0xa0,0x13,0xff,0x02,0x7f,0x2c,0xad,0x90,0x2f,0x2f,0x4f,0x19,0xed,0x00,0x8f,
|
||||
0x10,0x2d,0x1a,0xa3,0x3f,0x68,0x1e,0x2c,0x13,0xf9,0x0a,0x4f,0x53,0xf7,0x09,0x1b,
|
||||
0x10,0x09,0x1c,0xd3,0x1f,0xcf,0x08,0x3c,0x8f,0x9f,0x4d,0x1f,0x70,0x01,0x03,0x9f,
|
||||
0x7d,0x1f,0x0e,0xb0,0x43,0xfb,0x0e,0xde,0x13,0xf9,0x8d,0x7f,0x3e,0xdd,0x25,0xaf,
|
||||
0x03,0xff,0x00,0x8f,0x43,0xf5,0x23,0xfb,0x4e,0x6f,0x23,0xf3,0x40,0x03,0x0e,0x0f,
|
||||
0x6e,0xad,0x02,0x6f,0xe2,0x3f,0x25,0x87,0x02,0x6f,0x16,0xff,0x64,0x4d,0x02,0x9b,
|
||||
0x5e,0x0f,0x92,0x9b,0x22,0x6b,0x56,0x6b,0x06,0x6d,0x00,0xaf,0xff,0xde,0x26,0xc5,
|
||||
0x12,0x45,0x3f,0x5f,0x26,0x09,0x1f,0x95,0x0a,0x78,0x09,0x8f,0x0d,0x82,0x0c,0x4f,
|
||||
0x30,0x01,0x0e,0x51,0x0e,0x21,0x15,0x1a,0x8f,0xf4,0xaf,0xff,0x2e,0xe9,0x0e,0xa2,
|
||||
0x1f,0x69,0x7c,0xcc,0x15,0xe3,0x0c,0x6f,0x30,0x01,0x00,0x2f,0x18,0xc5,0x6f,0xff,
|
||||
0x3b,0x67,0x01,0xb2,0x20,0x07,0x20,0x0b,0x0f,0xff,0x86,0x83,0x4e,0x7f,0x90,0x01,
|
||||
0x0a,0x23,0x17,0x43,0x65,0x63,0x2b,0xad,0x00,0x9f,0x34,0xd3,0x2c,0x10,0x1a,0x5b,
|
||||
0x75,0xef,0x37,0x43,0x17,0xa1,0x49,0xe0,0x1b,0x0d,0x1c,0x65,0x20,0x27,0x0f,0xff,
|
||||
0x48,0x03,0x4b,0x53,0x1c,0x63,0x30,0x31,0x0c,0xf3,0x12,0x49,0x30,0x58,0x35,0x63,
|
||||
0x10,0x2d,0x0a,0xe1,0x19,0x8f,0x10,0x09,0x0f,0xff,0xd0,0x01,0x0f,0xff,0x10,0xa6,
|
||||
0x20,0x01,0x2b,0xf2,0x03,0x50,0x72,0x1d,0x4f,0xff,0x1a,0x2f,0x00,0xfd,0x0c,0x00,
|
||||
0x22,0x47,0x1f,0xd9,0x05,0x02,0x0f,0xff,0x21,0xa7,0x10,0x01,0x32,0x2b,0x0f,0xff,
|
||||
0x53,0xfb,0x14,0x01,0x1e,0x9b,0x0f,0xff,0x80,0x2f,0x1e,0xcb,0x0f,0xff,0xdf,0xff,
|
||||
0x05,0xb2,0x33,0xf7,0x1a,0xdf,0x99,0xb0,0x08,0xd1,0x2f,0x63,0x3e,0x29,0x33,0xfb,
|
||||
0x1f,0x0f,0x0a,0x7f,0x10,0x1e,0x23,0x97,0x4b,0x3f,0x63,0x67,0x07,0x18,0x10,0x8f,
|
||||
0x40,0x5f,0x0f,0xd2,0x1d,0x5d,0x4c,0x4f,0x5a,0x7d,0x0e,0xeb,0x1b,0xc9,0x1c,0x92,
|
||||
0x16,0x8e,0xc4,0x49,0x06,0xd2,0x21,0xc3,0x8f,0xeb,0x1c,0xc3,0x07,0x02,0x0f,0xfd,
|
||||
0x03,0xfd,0x23,0xfb,0x14,0xaa,0x09,0xad,0x25,0x73,0x87,0x67,0x1c,0x01,0x4f,0xff,
|
||||
0x05,0x2b,0x00,0x60,0x20,0x01,0x09,0x1d,0x10,0x8d,0x2c,0x8f,0x00,0x7b,0x20,0x01,
|
||||
0xac,0x51,0x0d,0xbe,0x7e,0x90,0x7f,0xfb,0x36,0x21,0x4f,0xff,0x90,0x01,0x04,0x2f,
|
||||
0x10,0x2f,0x04,0x2f,0x0b,0xaf,0xa4,0x4e,0x0a,0xbf,0x13,0x79,0x2f,0xff,0x1f,0xa1,
|
||||
0x27,0x6f,0x09,0x8d,0x16,0x2b,0x98,0xff,0x0b,0x1a,0x8f,0xf4,0x8f,0xff,0x1f,0xe3,
|
||||
0x0a,0x18,0x10,0xbf,0xc0,0xbf,0x0a,0x1f,0x11,0x1e,0x0a,0x9f,0x4f,0x49,0x07,0x16,
|
||||
0x6f,0xff,0x49,0x19,0x03,0x17,0xab,0xbd,0x07,0xcb,0x0b,0xf8,0x7c,0x98,0x07,0x77,
|
||||
0x29,0xb5,0x69,0xaf,0x02,0xd0,0x8f,0xf8,0x1a,0x57,0x0b,0x6f,0x2f,0xa5,0x10,0x31,
|
||||
0x0f,0x5f,0x20,0x01,0x1d,0x2b,0x3a,0xdd,0x8f,0xff,0x17,0xe5,0x2b,0x3f,0x15,0xe4,
|
||||
0x18,0x38,0x42,0x54,0x18,0x05,0x0e,0xef,0x1b,0xf1,0x0f,0xff,0x10,0x29,0x18,0xd5,
|
||||
0x11,0x2f,0x18,0xdd,0x1c,0x3d,0x10,0x01,0x10,0x09,0x6f,0xff,0x0e,0x4b,0x33,0xf3,
|
||||
0x14,0xc2,0x1a,0xb9,0x0b,0xcf,0x0f,0x5f,0x0e,0x95,0x11,0x03,0x0f,0xf4,0x26,0xdd,
|
||||
0xc3,0xc5,0x0f,0x04,0x87,0x07,0x6f,0xb3,0x0f,0x32,0x60,0x01,0x0f,0xe0,0x51,0x89,
|
||||
0x5f,0xff,0x15,0xdd,0x95,0xdd,0x19,0xc5,0xaa,0xf7,0xc0,0x2f,0xc0,0x2f,0x06,0x0e,
|
||||
0x43,0xf5,0x6f,0xff,0x09,0x7f,0x3b,0x29,0x13,0x07,0x3e,0x63,0x1f,0x69,0x1d,0x5d,
|
||||
0x0e,0x0f,0x1e,0x5e,0x13,0xfe,0x1d,0x29,0xaf,0xff,0x0a,0x75,0x1f,0xc9,0x13,0x8b,
|
||||
0x1f,0xff,0xa5,0x8d,0x0d,0x5b,0x5e,0x1b,0x48,0xcf,0x68,0xcf,0x14,0x1f,0x17,0xfd,
|
||||
0x2f,0xcb,0x1e,0xe9,0x0b,0x9e,0x30,0xff,0x1c,0xa8,0x19,0x38,0x0c,0x63,0x25,0x23,
|
||||
0x17,0x9d,0x2b,0xa5,0x30,0x5f,0x16,0xe5,0x9b,0x7f,0x2f,0x81,0x0e,0x57,0x2b,0xcf,
|
||||
0xcb,0xcf,0x1e,0xb1,0x0b,0x4d,0x00,0x82,0x01,0x35,0x4f,0x2f,0x1f,0x13,0x1b,0xf1,
|
||||
0x0f,0x31,0x1c,0x27,0x0f,0x9c,0x5f,0x5f,0x83,0x60,0x06,0xa9,0x13,0x6b,0x8f,0xf6,
|
||||
0x14,0xb6,0x0f,0x19,0x4f,0x02,0xba,0x8b,0x11,0x10,0x0e,0x91,0x0e,0xe0,0xac,0xce,
|
||||
0x0d,0xc6,0x75,0x4f,0x01,0x21,0xcf,0xf3,0x19,0x2a,0x0a,0x53,0xa0,0x4f,0x0f,0xe2,
|
||||
0x19,0x77,0xe0,0x5f,0x07,0x40,0x1d,0x1d,0x79,0x4f,0x32,0x89,0x0f,0xa4,0x20,0x01,
|
||||
0x6f,0xff,0x30,0x01,0x0f,0x93,0x1f,0xd7,0x59,0x64,0x9f,0xc6,0x1d,0xf1,0x4e,0x0f,
|
||||
0x19,0xac,0x0f,0xe6,0x1a,0x68,0x82,0x7d,0x1a,0x79,0x0c,0x5f,0x00,0xef,0xaf,0xff,
|
||||
0x80,0xef,0x7a,0x45,0x7f,0xf1,0xc8,0xbb,0x10,0x0f,0xb8,0x8b,0x67,0xfb,0x27,0xbd,
|
||||
0x0a,0x71,0xc0,0x81,0x0a,0xf3,0x0f,0xff,0x18,0xd1,0x29,0x8d,0x1f,0xa1,0x4b,0x05,
|
||||
0x2f,0x5b,0x0b,0x11,0x12,0xd3,0x44,0xf6,0x18,0x01,0x15,0x07,0x2b,0x45,0x03,0xf1,
|
||||
0x1f,0xff,0x3b,0xff,0x02,0xcf,0xb3,0xc5,0x2c,0x85,0x1c,0xc3,0x0c,0x6e,0x19,0x8f,
|
||||
0x3d,0xf3,0x1c,0xdd,0x0f,0xfc,0x5a,0x27,0x30,0x01,0x0d,0xcf,0x41,0x1b,0x16,0x23,
|
||||
0x0c,0xb3,0x43,0xf5,0x46,0x19,0x03,0xff,0x19,0x1b,0x1c,0xbe,0x33,0xf9,0x21,0x97,
|
||||
0x10,0x8d,0x0c,0xc2,0x10,0x01,0x4d,0x76,0x13,0xa7,0x40,0x01,0xa9,0xd7,0x0a,0x9b,
|
||||
0x1d,0xc9,0x8a,0xc7,0x0d,0x81,0xeb,0xfb,0x1f,0x4e,0x20,0x01,0x0f,0xd3,0xec,0x4f,
|
||||
0x0c,0xf7,0x10,0xef,0x50,0x01,0xe0,0xef,0x04,0x56,0x09,0x1f,0x1e,0xa5,0x20,0x09,
|
||||
0x15,0x80,0x0e,0xf3,0x71,0x7b,0x0f,0x12,0xcb,0x0f,0x2d,0x7d,0x0b,0x5f,0x70,0x01,
|
||||
0x6f,0x87,0x40,0x99,0x0f,0x3d,0x43,0xf7,0x30,0x01,0x0f,0xe1,0x1c,0x8b,0x1c,0x5f,
|
||||
0x29,0x60,0x0d,0x89,0x5f,0xdc,0x16,0xd5,0xa2,0x1b,0x0f,0xfe,0x19,0x7c,0x7f,0xff,
|
||||
0x0f,0xff,0x25,0x49,0x10,0x01,0x31,0x1f,0x01,0x1f,0x70,0x01,0x0f,0xd5,0x14,0x7f,
|
||||
0x3d,0x81,0x1a,0x7f,0x1e,0x58,0x1a,0x83,0x0c,0xc0,0x17,0xf5,0x1e,0xab,0x3d,0xad,
|
||||
0x18,0x36,0x21,0x21,0x27,0xa5,0x17,0xf9,0x0e,0x79,0x15,0x71,0x19,0x39,0x18,0x03,
|
||||
0x1f,0x3d,0x18,0x04,0x1e,0xe9,0x78,0x9e,0x0f,0xc6,0x0d,0xa5,0x10,0xef,0xa0,0xef,
|
||||
0x21,0x88,0x00,0xef,0x0e,0xa0,0x1d,0x53,0x88,0x5f,0x29,0x80,0x13,0xff,0x0e,0x9d,
|
||||
0x1f,0xd5,0xb5,0x2f,0x0f,0x12,0x0f,0x30,0x9b,0x9f,0x1b,0xac,0x0f,0xa2,0x02,0xf6,
|
||||
0xaf,0xff,0x0d,0xb7,0xc0,0x2f,0x03,0x65,0xaa,0x10,0x24,0xdb,0x00,0x2f,0xa6,0xf0,
|
||||
0x00,0x9d,0xd7,0x20,0x0a,0xd5,0x1a,0x39,0x56,0x4d,0x3c,0x8d,0x1d,0x88,0x25,0x63,
|
||||
0x0e,0x6f,0x20,0x31,0x60,0x2f,0x1e,0x7e,0x4d,0xa8,0x0e,0x9f,0x18,0x19,0x25,0x10,
|
||||
0x40,0x5f,0x30,0x5d,0x19,0xab,0x0e,0xcf,0x1d,0x49,0x70,0xbf,0x0e,0xff,0x30,0x01,
|
||||
0x43,0xad,0x17,0x83,0x20,0x01,0x2d,0x1b,0x00,0xef,0x1c,0xed,0x1b,0x5f,0x11,0xdf,
|
||||
0x1e,0x74,0x19,0x3f,0x15,0xb1,0x0c,0x95,0xd8,0xd5,0xcf,0xf8,0xda,0x7e,0x5c,0x5f,
|
||||
0x51,0xc0,0x0a,0x0f,0x8d,0xd5,0x04,0xeb,0x1b,0x99,0x60,0x01,0x1b,0x2f,0x70,0x01,
|
||||
0x0e,0xa9,0x20,0x01,0x1b,0x9d,0x1e,0x56,0xb0,0x01,0x0f,0xff,0x20,0x01,0x08,0x84,
|
||||
0xab,0xcf,0x40,0x01,0x0f,0x98,0x8b,0x0f,0x6f,0x63,0x0b,0x0f,0x1f,0x48,0x13,0x00,
|
||||
0x67,0x1a,0x2b,0x65,0x1f,0x22,0xf1,0x4d,0x70,0x01,0x00,0x2f,0xcf,0xcf,0x1d,0xbf,
|
||||
0x1e,0xc3,0x19,0x2f,0x95,0x80,0x1e,0x1f,0x1d,0x3a,0x33,0xf3,0x1e,0x3b,0x2e,0xd5,
|
||||
0x62,0x45,0x0e,0xdd,0x23,0xfb,0x1e,0x3b,0x18,0xb7,0x1f,0x7a,0x00,0x2f,0x1e,0x5e,
|
||||
0x40,0x2f,0x60,0x2f,0x00,0x2f,0x00,0x2f,0x20,0x5f,0x50,0x5f,0x40,0x5f,0x00,0x8f,
|
||||
0x30,0xe9,0x14,0x8f,0x10,0x33,0x1e,0x6f,0x10,0x2b,0x1f,0x17,0x00,0x2f,0x40,0xf1,
|
||||
0x70,0x2f,0x40,0x2f,0x00,0x2f,0xd0,0x8f,0x1f,0x8d,0x1d,0xe3,0x10,0x00,0x1e,0xd1,
|
||||
0xcf,0x93,0x1e,0x61,0x3f,0x2f,0x1e,0x11,0xab,0x8a,0x00,0x00,0x44,0x01,0x1e,0x9d,
|
||||
0x1a,0xa7,0x1e,0xe9,0x0c,0x00,0x4f,0xfe,0x15,0xf1,0xa3,0xff,0x08,0x6f,0x1f,0xcb,
|
||||
0x00,0x85,0x08,0x67,0x10,0x8d,0x19,0x50,0x1b,0x0d,0xf1,0xe5,0xb2,0xdf,0x13,0x39,
|
||||
0x3f,0xeb,0x1b,0x17,0x7b,0x19,0xac,0xfd,0xd0,0x2f,0x1c,0x2e,0x11,0x01,0x3f,0xaf,
|
||||
0x6b,0xc9,0x62,0x2a,0x1d,0xe1,0x20,0x63,0x3d,0xdf,0x20,0x2b,0x4d,0xef,0x23,0xf3,
|
||||
0x10,0x01,0x5d,0x61,0x25,0xd7,0x66,0x7d,0x04,0xef,0x22,0xb1,0x27,0x3e,0x12,0xde,
|
||||
0x1c,0xc4,0x50,0x10,0x00,0x2f,0x10,0x61,0x70,0x2f,0x00,0x2f,0x00,0x2f,0x10,0x5f,
|
||||
0x80,0x5f,0x1d,0x54,0x00,0x8f,0x15,0x71,0x12,0x3f,0x4c,0xad,0x34,0x30,0xcc,0xbe,
|
||||
0x80,0x2f,0xc0,0x2f,0x00,0x2f,0x60,0x8f,0x53,0x23,0x43,0xfb,0x9f,0x9f,0x7f,0x6f,
|
||||
0x1e,0x07,0x1e,0x6f,0x1e,0x06,0x32,0x41,0x0d,0xa1,0x1e,0x4b,0x39,0x91,0x86,0x0b,
|
||||
0x2f,0x41,0x08,0x3f,0x19,0xbd,0x60,0x2f,0x59,0x8d,0x00,0x2f,0x10,0x2d,0x80,0x2f,
|
||||
0x19,0xf1,0x00,0x5f,0x20,0x01,0x70,0x2f,0x44,0xff,0x22,0x2d,0x00,0xbe,0x1a,0x6c,
|
||||
0x04,0x93,0x3f,0x2d,0x00,0x2f,0x10,0x5d,0x00,0x5f,0x20,0x01,0x00,0x8f,0x9f,0xf8,
|
||||
0xcf,0xff,0x0d,0xab,0x21,0xaf,0x4f,0x86,0x1c,0x00,0x07,0x3f,0x39,0x1c,0x5f,0xcd,
|
||||
0x5a,0x1f,0x1b,0x67,0x1a,0x1f,0x0a,0x15,0x1b,0xa1,0x1b,0xf1,0x22,0x1e,0x1a,0xa9,
|
||||
0x2e,0x87,0x11,0x67,0x0b,0xcf,0x1f,0x43,0x20,0x2f,0x1a,0xd7,0x17,0x0f,0x00,0x2f,
|
||||
0x4b,0x6f,0x1e,0xe8,0x30,0x5f,0x1e,0x6b,0x4b,0x6f,0x00,0x5f,0x8b,0x6f,0x1f,0xa5,
|
||||
0x27,0xe2,0x20,0x01,0x00,0x8f,0x9f,0xff,0xfe,0xa1,0x0f,0x06,0x40,0x8f,0x6f,0xea,
|
||||
0x04,0xc2,0x21,0x4f,0x4b,0x99,0x3f,0x20,0x1c,0x91,0x2f,0xbc,0x0f,0xd3,0x1b,0x99,
|
||||
0x40,0x2f,0x1f,0xd3,0x5d,0xd9,0x00,0x2f,0x20,0x2d,0x27,0xc7,0x20,0x5f,0x3c,0xef,
|
||||
0x1b,0x45,0x00,0x5f,0x20,0x01,0x23,0x20,0xec,0x9e,0x0f,0xff,0x50,0x01,0x9c,0x31,
|
||||
0x00,0x2f,0x67,0xa0,0x20,0x2f,0x00,0x2f,0x00,0x5f,0x00,0x2f,0xd0,0x01,0x0f,0xff,
|
||||
0x00,0x2f,0x13,0xf1,0x4e,0x4d,0x14,0x03,0x1f,0x17,0x11,0xd6,0x45,0x5d,0x2b,0x99,
|
||||
0x1f,0x1d,0x1b,0xff,0x60,0x01,0xfb,0x3f,0x26,0xdd,0x3d,0x75,0x26,0xe1,0x1d,0x7c,
|
||||
0x1a,0xf5,0xef,0x9c,0x17,0x71,0x17,0xd5,0x1d,0xb7,0x1a,0x4f,0x27,0x0d,0x62,0x24,
|
||||
0x00,0x2f,0x40,0x2f,0x12,0xab,0x00,0x2f,0x30,0x8f,0x38,0x65,0x1e,0x3f,0x1f,0xdb,
|
||||
0x00,0x8f,0x3d,0x6b,0x10,0xb3,0x15,0x49,0x2c,0x67,0x18,0xa1,0x1b,0x41,0x21,0x3f,
|
||||
0x00,0xbf,0x11,0x68,0xf0,0xef,0x20,0xe5,0xa0,0x03,0xc0,0x01,0x00,0x2f,0xd0,0x01,
|
||||
0x00,0x8f,0x00,0x3f,0x98,0x5f,0x0b,0x9e,0x00,0x2f,0x83,0xff,0x0f,0xfa,0x00,0x2f,
|
||||
0x56,0xdb,0x17,0xf9,0x4b,0x10,0x1f,0xf8,0x49,0xee,0x1f,0x65,0xa9,0xc9,0x6d,0x20,
|
||||
0x4b,0x3f,0x04,0xef,0x33,0x11,0x1a,0x25,0x45,0x76,0x0c,0x5e,0x1f,0x55,0x13,0x3f,
|
||||
0x24,0x85,0x55,0x60,0x00,0x2f,0xa0,0x2f,0x30,0x2f,0x00,0x2f,0x1c,0x29,0xf0,0x2f,
|
||||
0x20,0x2f,0x00,0x8f,0x20,0x8f,0x10,0x8f,0x07,0x6a,0x86,0xdf,0x14,0xef,0x0f,0x07,
|
||||
0x1c,0x97,0x1f,0x5a,0x60,0xbf,0x00,0xef,0x25,0x13,0x71,0x4f,0x23,0xff,0x01,0x4f,
|
||||
0x30,0x2f,0xc0,0x2f,0x00,0x5f,0xf0,0x2f,0x20,0x2f,0x00,0x2f,0x24,0xf1,0xa0,0x5f,
|
||||
0x50,0x2f,0x0f,0xfa,0x38,0x71,0x21,0x5c,0x08,0x9f,0x9f,0xff,0x0f,0x91,0xcf,0xf8,
|
||||
0x00,0xa3,0x1b,0xd6,0x1c,0xd9,0xb6,0x6f,0x2c,0x95,0x0b,0xd6,0xad,0x81,0x0f,0xdf,
|
||||
0x5c,0x95,0xc0,0x5d,0x0a,0x1a,0x9e,0x09,0x0f,0xff,0x20,0x01,0x8f,0xff,0x4d,0xc9,
|
||||
0x0f,0xd6,0x1f,0x93,0x6f,0xf6,0x17,0xf1,0x09,0xbe,0x00,0x1f,0x4e,0x15,0x01,0x7f,
|
||||
0x4e,0x15,0x9c,0x50,0x01,0x7f,0x6e,0x15,0x01,0x4f,0x7e,0x15,0x0d,0x80,0x2e,0x15,
|
||||
0x0d,0xaf,0x4e,0x15,0x0d,0xe0,0x4e,0x15,0x0e,0x10,0x1d,0xab,0x89,0x6f,0x1d,0xe1,
|
||||
0x02,0x9f,0x02,0x9f,0x0f,0x0b,0x15,0xef,0x2a,0x11,0x2c,0x62,0x15,0xc4,0x39,0x31,
|
||||
0x08,0x2f,0x18,0x2b,0x8a,0x0e,0x1e,0x45,0x14,0xe3,0x10,0x01,0xfe,0x1f,0x3b,0xa3,
|
||||
0x1e,0x82,0x1a,0x29,0x19,0xc2,0x19,0xcf,0x0e,0x4d,0x23,0xc3,0x2d,0x01,0x1d,0x61,
|
||||
0x0a,0xae,0x1f,0x0d,0xc0,0x2f,0xb0,0x2f,0x03,0x95,0x30,0x5f,0x50,0x5f,0x1e,0xdf,
|
||||
0x70,0x2d,0x00,0x5f,0xc0,0x8f,0x1f,0x35,0x4d,0x91,0x00,0x8f,0x1e,0x11,0x10,0xbf,
|
||||
0x10,0xbf,0x34,0xe5,0x2b,0x6e,0x00,0xbf,0x1f,0x91,0xa0,0x8f,0x40,0xef,0x20,0xed,
|
||||
0x00,0x2f,0x2e,0x20,0x3d,0x1e,0x7d,0x2e,0x1f,0xe5,0x20,0x01,0x4d,0xe5,0x2e,0x43,
|
||||
0x11,0x77,0x7f,0x17,0x0f,0xcd,0x50,0xbf,0x1f,0x7a,0x04,0xef,0x25,0x64,0x40,0x2f,
|
||||
0x10,0x2f,0x90,0x2f,0x00,0x2f,0x21,0x7f,0x20,0x2f,0x50,0x2f,0x61,0x7f,0x1e,0x55,
|
||||
0x00,0x2f,0x31,0x4f,0x20,0x2f,0x10,0x8f,0x51,0x4f,0x00,0x2f,0x20,0x8f,0x5e,0xa1,
|
||||
0x2e,0xa9,0x0e,0xff,0x27,0x25,0x0e,0x3f,0x00,0x2f,0x1f,0x95,0x00,0x2f,0x1f,0xf7,
|
||||
0x16,0x9b,0x1c,0xb7,0x2c,0xc8,0x19,0x99,0xf6,0xd2,0x19,0xa5,0x3f,0x97,0x42,0x9f,
|
||||
0x4d,0xb2,0x0e,0x7f,0x70,0x01,0x2f,0xf9,0x70,0x01,0x0c,0x2f,0x1f,0xf5,0x4e,0x0a,
|
||||
0x30,0x2e,0x13,0xfb,0x0f,0x6f,0x23,0xfb,0x47,0x15,0x34,0x25,0x00,0x35,0x24,0x2b,
|
||||
0x3a,0xa0,0x43,0x37,0x0c,0xbf,0x30,0x2f,0x00,0x2f,0x2e,0xcc,0xf0,0x5f,0x00,0x2f,
|
||||
0x00,0x2f,0x21,0x87,0xc0,0xbf,0x00,0x2f,0x1c,0x01,0x3b,0xc0,0x7b,0xd0,0x9c,0x31,
|
||||
0x1a,0x79,0x1f,0xbf,0x21,0xaa,0x15,0xad,0x01,0xdb,0x3b,0x5e,0x17,0x09,0x6a,0xaf,
|
||||
0x14,0x23,0x35,0xad,0x00,0x2f,0x00,0x5f,0x2c,0xc1,0x00,0x2f,0x02,0x9f,0x83,0xf9,
|
||||
0x0e,0x0f,0x00,0x2f,0x4c,0x2f,0x6d,0xaf,0x14,0x07,0x00,0xef,0x00,0x9f,0xbe,0x89,
|
||||
0xaf,0xf4,0x0a,0x7f,0x1e,0xa7,0x09,0xef,0xab,0x9d,0x08,0xcf,0xcb,0x6f,0x17,0xbb,
|
||||
0x0b,0x6f,0x1c,0xf9,0x9c,0xaf,0x30,0x01,0x0c,0x90,0xcf,0xff,0x0b,0x6f,0x01,0x4f,
|
||||
0x01,0x4f,0x03,0xa7,0x1f,0xcd,0x11,0x4f,0xc1,0x4f,0x0a,0xbf,0x20,0x01,0x8f,0xf4,
|
||||
0x09,0x1f,0x01,0xdf,0x0c,0xa9,0x20,0x01,0x0b,0xcf,0x00,0x18,0x0e,0x19,0x29,0xef,
|
||||
0x19,0xef,0x1b,0xf5,0x89,0xef,0x0b,0x9f,0xc0,0x2f,0xb0,0x2f,0x0b,0xff,0x30,0x5f,
|
||||
0x50,0x5f,0x1a,0x73,0x00,0x2f,0xb0,0x2f,0x68,0xcf,0x20,0x8f,0x00,0x5f,0x2a,0x10,
|
||||
0x1f,0xc9,0x4a,0xe3,0x4b,0x6f,0x2d,0x3c,0x2c,0x91,0x09,0x60,0x43,0xf3,0x2f,0x95,
|
||||
0x4d,0x92,0xce,0xed,0x79,0x01,0x20,0x5f,0x2d,0x69,0x2a,0xdb,0x0f,0xff,0x1e,0x4b,
|
||||
0x60,0x01,0xd0,0x0f,0x01,0x4f,0xe0,0x1f,0x2d,0x21,0x50,0x01,0xf3,0xc5,0x11,0x4f,
|
||||
0xa0,0x5f,0x1b,0xc3,0x5d,0x8b,0x8e,0x2e,0xb1,0x1f,0xa0,0x8f,0x40,0x5f,0x00,0x2f,
|
||||
0x22,0x00,0x1d,0xcd,0x4e,0x15,0x30,0xcf,0x1b,0x7b,0x1d,0x7b,0x05,0x1f,0x50,0xab,
|
||||
0x5f,0xf2,0x1d,0xe5,0x1e,0x57,0x0d,0x1f,0x10,0x5f,0x6e,0x75,0x2d,0x1f,0x32,0x17,
|
||||
0x00,0x5f,0x04,0x10,0x05,0x21,0x1b,0x0b,0x23,0x29,0x79,0xef,0x23,0xc3,0x09,0x8f,
|
||||
0x20,0x2f,0xb0,0x2f,0x00,0x2f,0x00,0x2f,0x09,0xef,0x2d,0x89,0x14,0x79,0x2a,0x7f,
|
||||
0x50,0x5f,0x09,0xef,0x34,0x17,0x6a,0xaf,0x10,0xbf,0x0a,0xaf,0xa4,0x03,0x64,0xd0,
|
||||
0x26,0x79,0x07,0xc4,0x2b,0x10,0x01,0x1f,0x33,0xf9,0x10,0x8f,0x1f,0x99,0x60,0x0f,
|
||||
0x00,0x2f,0x50,0x2f,0x23,0xf9,0x00,0x2f,0x70,0x2f,0x1f,0xd7,0x1f,0x97,0x00,0x2f,
|
||||
0x1f,0xe8,0x11,0xb0,0x19,0x0e,0x18,0x85,0x06,0x06,0x7e,0x0f,0x64,0xad,0x2d,0xdd,
|
||||
0x0f,0x77,0x2e,0xd0,0xa0,0x5f,0x1e,0x73,0x07,0xf7,0x09,0x08,0x0a,0x19,0x0b,0x2a,
|
||||
0x0c,0x3b,0x0d,0x4c,0x0e,0x5d,0x0f,0x6e,0x0c,0x7f,0x0d,0x90,0x0e,0xa1,0x0f,0xb2,
|
||||
0x0c,0xcb,0x0d,0xdc,0x0e,0xed,0x0f,0xfe,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,
|
||||
0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,
|
||||
0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,
|
||||
0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,
|
||||
0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,
|
||||
0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,
|
||||
0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,
|
||||
0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,
|
||||
0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,
|
||||
0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,
|
||||
0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,
|
||||
0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,
|
||||
0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,0x0f,0xff,
|
||||
0x0f,0xff,0x0f,0xff,0x00,0x00,0x00,0x20,0x00,0xff,0x18,0x18,0x00,0x1c,0x18,0x00,
|
||||
0x02,0x00,0x00,0x15,0x00,0x0b,0x02,0x30,0x00,0x00,0x01,0x10,0x55,0xaa,0xff,0x0c,
|
||||
0x06,0x0b,0x12,0x10,0x16,0x13,0x06,0x0a,0x0a,0x0f,0x13,0x07,0x11,0x07,0x17,0x12,
|
||||
0x0a,0x11,0x11,0x13,0x12,0x12,0x11,0x11,0x11,0x07,0x07,0x11,0x13,0x11,0x0f,0x14,
|
||||
0x12,0x10,0x11,0x11,0x0e,0x0e,0x0b,0x10,0x0e,0x13,0x10,0x12,0x0f,0x12,0x11,0x10,
|
||||
0x10,0x10,0x11,0x16,0x11,0x11,0x0f,0x0a,0x17,0x09,0x0d,0x18,0x07,0x0f,0x0f,0x0e,
|
||||
0x0f,0x0f,0x0a,0x0f,0x0e,0x07,0x09,0x0e,0x07,0x13,0x0f,0x0a,0x0d,0x0b,0x0e,0x0f,
|
||||
0x13,0x0f,0x0e,0x0d,0x0a,0x05,0x0a,0x15,0x18,0x14,0x18,0x06,0x0f,0x0b,0x15,0x0e,
|
||||
0x0e,0x0d,0x17,0x18,0x0f,0x18,0x18,0x07,0x07,0x0b,0x0b,0x0f,0x12,0x0e,0x0b,0x13,
|
||||
0x18,0x0d,0x11,0x06,0x0f,0x0c,0x17,0x0b,0x0e,0x12,0x0a,0x17,0x18,0x0b,0x12,0x0a,
|
||||
0x0b,0x0a,0x0e,0x0e,0x08,0x08,0x07,0x0b,0x0e,0x14,0x14,0x15,0x10,0x12,0x13,0x13,
|
||||
0x14,0x10,0x0f,0x06,0x14,0x10,0x11,0x11,0x12,0x10,0x11,0x0f,0x13,0x0e,0x10,0x0e,
|
||||
0x0e,0x0e,0x0f,0x10,0x0e,0x00,0x27,0x29,0x00,0x3e,0x18,0x3e,0x0b,0x80,0x09,0x06,
|
||||
0x00,0x0b,0x00,0x0f,0x41,0x90,0x42,0xe0,0x42,0xd0,0x09,0x1b,0x02,0xff,0x0f,0xeb,
|
||||
0x90,0x00,0xfd,0x00,0xbf,0x09,0x06,0xf8,0x1f,0xfe,0x2e,0x0b,0x40,0x2e,0x6f,0x01,
|
||||
0xff,0x03,0xe0,0xf4,0x00,0xbc,0x09,0x3f,0x17,0x18,0x00,0x7d,0x00,0xf8,0x02,0xe0,
|
||||
0x16,0x09,0x00,0x0f,0x40,0x07,0xc0,0x18,0x0a,0x1d,0x01,0xa0,0xad,0x06,0x00,0x1f,
|
||||
0x80,0x7e,0x00,0xf8,0x1b,0x00,0xbf,0x03,0xfd,0xf9,0x00,0xff,0x80,0x6f,0x0a,0x29,
|
||||
0x00,0xbe,0x07,0xfe,0x19,0x2b,0x01,0xff,0x07,0xf9,0xe9,0x5f,0x0a,0x6b,0x02,0xff,
|
||||
0x0b,0xf5,0xd0,0x5b,0xf0,0x18,0x06,0x80,0x1f,0xd0,0x7f,0xd0,0x3e,0x3e,0x00,0x2e,
|
||||
0x0e,0x0e,0x03,0x0d,0x03,0x38,0x80,0x00,0x40,0x0c,0x0f,0x0b,0xff,0x0b,0xff,0x01,
|
||||
0x7d,0x00,0x3c,0x00,0x78,0x15,0xb9,0x2f,0xff,0x03,0xc0,0xff,0x5b,0x95,0x0f,0x40,
|
||||
0x0f,0x00,0x5e,0x54,0xff,0xf8,0x2f,0x4b,0x2e,0x0b,0x2f,0x4b,0x1f,0xeb,0x07,0xff,
|
||||
0x00,0x6f,0x0b,0x0b,0xc0,0xe4,0x00,0xff,0x40,0x6f,0xc0,0x07,0x3d,0x0b,0x2f,0x6f,
|
||||
0x0b,0xfe,0x01,0xa4,0x80,0x7c,0x81,0xf4,0x82,0xe0,0x4b,0x80,0x1f,0x00,0x7d,0x1f,
|
||||
0xb8,0x7e,0xe0,0xe0,0x7d,0x00,0x03,0xd0,0x03,0xd0,0x02,0xf1,0x00,0xfb,0x00,0xbf,
|
||||
0xdb,0x0f,0x42,0x7c,0x00,0x7c,0xe0,0xb4,0xd0,0xb4,0xf4,0x0f,0x00,0x0e,0x00,0x38,
|
||||
0x19,0x03,0xd0,0x07,0x80,0x0b,0x0f,0xf4,0x00,0xb8,0x3c,0x00,0x2d,0x3c,0x0f,0x1f,
|
||||
0x04,0x0f,0x2e,0x0f,0x3f,0xdf,0x06,0xff,0x00,0x7f,0x06,0xff,0x2f,0xdf,0x40,0x0b,
|
||||
0x80,0x7f,0xc0,0xf9,0x00,0xd0,0xbf,0xc0,0x01,0x1a,0xaa,0x2f,0xff,0x1a,0xaa,0x00,
|
||||
0x01,0xf4,0x00,0xfa,0xaa,0xff,0xff,0xfa,0xaa,0x40,0x10,0x0b,0x2a,0xaa,0x7f,0xff,
|
||||
0x6a,0xaa,0xaa,0xa8,0xff,0xfc,0xaa,0xa8,0x3f,0x02,0x00,0x07,0x00,0x1f,0x00,0x7e,
|
||||
0x01,0xf4,0x07,0xd0,0x2f,0x40,0xbd,0xe0,0x0b,0xe0,0x0f,0xc0,0x2f,0x40,0x2f,0x00,
|
||||
0x40,0x02,0xf8,0x00,0xfc,0x00,0xbd,0x00,0x7e,0x3e,0x7f,0xfe,0x3e,0x7e,0x10,0x7e,
|
||||
0x00,0x0d,0x0f,0xd0,0x1f,0x80,0x06,0x06,0x00,0x7f,0x01,0xfe,0x02,0xf4,0x02,0xf8,
|
||||
0x02,0xf4,0x07,0xf0,0x6f,0xe0,0xff,0x40,0xf4,0x01,0x0f,0x80,0x01,0x15,0xf4,0x01,
|
||||
0x5f,0xe0,0xff,0x80,0xff,0xe0,0x07,0x00,0x07,0x2e,0x00,0xb8,0x02,0xf0,0x0b,0xd0,
|
||||
0x1f,0xaa,0xfb,0xd0,0xe7,0xd0,0x87,0xd0,0x07,0xab,0xea,0x80,0x2f,0x29,0x15,0x43,
|
||||
0x2f,0xff,0x00,0xf0,0x01,0xe0,0x02,0xe0,0x02,0xd0,0x00,0xff,0xf8,0x3c,0x78,0x00,
|
||||
0xb4,0x00,0x50,0x04,0x2f,0xeb,0x0b,0xff,0x00,0xbf,0x06,0xe0,0x03,0xe0,0x1b,0xd0,
|
||||
0xff,0x80,0xf9,0x06,0x3d,0x00,0xb8,0x01,0xf0,0xc1,0xf0,0x41,0xf0,0x00,0xf0,0x00,
|
||||
0xbe,0x00,0x7f,0x00,0x2e,0xbc,0x00,0x1f,0x0f,0x80,0x0b,0xfa,0x02,0xff,0x00,0x1a,
|
||||
0xbe,0xf0,0x2f,0xe0,0x1f,0xf8,0xbf,0xff,0xf8,0x2f,0x40,0x40,0x27,0x0b,0x40,0x0b,
|
||||
0x80,0x03,0xf4,0x1d,0x11,0x3c,0xf4,0x02,0xf0,0x07,0xd0,0x0f,0x40,0x12,0x2e,0x0f,
|
||||
0x04,0x0f,0x1a,0x80,0x01,0x0c,0x01,0x07,0x80,0x07,0x80,0x03,0x40,0x0e,0x45,0x2f,
|
||||
0x80,0x05,0x15,0xbd,0x02,0xf4,0x0b,0x80,0x2e,0xd0,0x0d,0x1f,0x80,0x0f,0xd0,0x07,
|
||||
0xf4,0x02,0xfe,0x00,0xbd,0x01,0xfc,0x07,0xf4,0xbf,0xd0,0xff,0x40,0xa4,0x04,0x14,
|
||||
0x12,0x07,0xf4,0x2f,0xff,0x2f,0xff,0x05,0x55,0xff,0xf8,0xff,0xf8,0x55,0x54,0x05,
|
||||
0x00,0x2f,0x90,0x0b,0xfe,0xfc,0x02,0xf8,0xaf,0xf4,0xff,0x90,0x04,0xff,0xff,0xab,
|
||||
0xea,0xc0,0x17,0x06,0xaa,0xaa,0xa0,0xff,0xf0,0xaa,0xa0,0x09,0x1b,0x09,0xab,0xf8,
|
||||
0x0d,0xe4,0xd0,0x1b,0x0a,0x6f,0x07,0xff,0x1f,0xe5,0xe8,0x0e,0x60,0xb4,0x07,0x3b,
|
||||
0x2d,0x00,0x2f,0x19,0x01,0xaf,0x0b,0xff,0x2f,0xd5,0xfe,0x00,0xbf,0x0a,0x02,0xbe,
|
||||
0x90,0xaa,0xfd,0xa0,0x00,0x02,0xaa,0x1f,0xff,0x1f,0x90,0x0a,0x1a,0xfa,0x40,0xff,
|
||||
0xe0,0x5b,0x09,0x2a,0xaa,0x3f,0xff,0x3f,0x50,0x40,0x0c,0x3e,0x00,0xff,0x00,0x01,
|
||||
0x2f,0xa9,0xa9,0x00,0x38,0x0a,0x40,0xa4,0x01,0xf8,0x01,0xf8,0x19,0x14,0xc0,0x0f,
|
||||
0x80,0x0f,0x85,0x1f,0xbf,0x1f,0xfe,0x2f,0xd0,0x05,0xa4,0xaf,0xf0,0xbc,0x00,0x2e,
|
||||
0x2f,0x3e,0xbf,0x3f,0xe4,0x3f,0x50,0x40,0x00,0xfe,0x40,0xbd,0x09,0x03,0x0b,0x0b,
|
||||
0xe0,0xbd,0xf0,0xd0,0x02,0x40,0xd0,0x3f,0xaf,0xbf,0xe0,0x06,0xf8,0x00,0x2f,0x40,
|
||||
0x3f,0x0f,0xf5,0x6a,0x02,0xf0,0xfc,0x6f,0xfc,0xfe,0xbc,0xa4,0x1a,0x40,0x19,0x21,
|
||||
0x2f,0x02,0xfe,0x1f,0xe4,0x2f,0x80,0x1f,0xe0,0x02,0xfe,0x7f,0xe0,0xfe,0x00,0x0e,
|
||||
0x55,0xff,0xff,0x0b,0x80,0xbf,0x80,0x1f,0xf0,0x02,0xf4,0x1b,0xf4,0x00,0x3e,0x1f,
|
||||
0x00,0x2f,0x7f,0x40,0xfd,0x81,0x0f,0x0b,0x2e,0x2f,0x2c,0x3e,0x3c,0x7c,0x3c,0xbc,
|
||||
0x3c,0xbc,0x2d,0x7e,0xa4,0x07,0xfe,0xe2,0xaf,0xe1,0xc0,0x0b,0xc1,0x0b,0x82,0x5f,
|
||||
0xd7,0xc0,0xe0,0x7d,0x00,0xfc,0x01,0xf4,0x02,0xfa,0x03,0xff,0xbd,0x2f,0x00,0xc0,
|
||||
0xab,0xe0,0xff,0x1f,0x40,0xff,0xc0,0x0b,0x6f,0xff,0x80,0x1b,0xd0,0x03,0xe0,0x04,
|
||||
0x1f,0x40,0x2f,0xb8,0x00,0x20,0x0c,0x2f,0xd0,0x07,0xe0,0xf4,0x02,0xff,0xfc,0x05,
|
||||
0x55,0xa8,0x54,0x05,0x2f,0x6a,0xa8,0xbf,0xfc,0xaa,0xfc,0x00,0x02,0x20,0x1b,0x40,
|
||||
0x2f,0xd0,0xff,0x00,0x16,0x05,0x0b,0xe0,0x03,0x00,0xbc,0x0a,0x1f,0x15,0x0a,0xbd,
|
||||
0x02,0xfc,0x09,0x00,0x0a,0x0b,0xe0,0xbf,0xd0,0xfe,0x32,0x07,0x40,0x17,0x6f,0xe0,
|
||||
0x00,0xfd,0x00,0xbf,0xd0,0x0b,0xf4,0x10,0x05,0xff,0x0b,0x00,0xbf,0x07,0xfd,0x2f,
|
||||
0xd0,0x2e,0xf8,0x05,0x05,0x06,0x1e,0x2f,0x0f,0x4a,0xf9,0xff,0xff,0xe5,0xa9,0x00,
|
||||
0x07,0x55,0x69,0x40,0xc0,0x07,0xea,0x2f,0x40,0x3f,0xab,0x7d,0x06,0x02,0xf0,0x03,
|
||||
0xf0,0x1b,0xfe,0x06,0xc0,0xf8,0x6f,0x74,0x01,0xfc,0xef,0x07,0x01,0x15,0x03,0xf0,
|
||||
0x0b,0xe0,0x7f,0xe4,0x0b,0x40,0xff,0x40,0x55,0x0c,0x15,0x2f,0x40,0xf4,0x7f,0xbc,
|
||||
0x00,0xbc,0x01,0x09,0x0e,0x29,0x0a,0x0c,0x2f,0x06,0x90,0x18,0x0e,0x2a,0x40,0x3f,
|
||||
0xc0,0x3f,0x2a,0xbf,0x08,0x0a,0x1f,0x01,0xa0,0x02,0xf0,0x02,0xf0,0x18,0x12,0x90,
|
||||
0xff,0x0d,0x03,0x80,0x5b,0xe0,0x18,0x40,0xbf,0xc0,0x0a,0xe4,0x7f,0x80,0x0d,0xaf,
|
||||
0x90,0xff,0xe0,0xea,0x09,0x29,0x00,0x90,0x03,0xe0,0x03,0x09,0x40,0x68,0xf8,0x0c,
|
||||
0x69,0xbf,0x7d,0x0a,0x40,0x0b,0xd0,0x03,0xa4,0x09,0x1a,0xa4,0x02,0xf4,0x0b,0x40,
|
||||
0x07,0x05,0x54,0x1f,0xfe,0x1f,0xa9,0x1e,0x17,0x18,0x00,0x2e,0x00,0x0b,0x80,0x02,
|
||||
0x17,0x15,0x54,0x2f,0xfc,0x1a,0xbc,0x00,0x3c,0x15,0x69,0xff,0x0b,0xeb,0x2f,0x82,
|
||||
0xe0,0x00,0x11,0x0f,0x02,0x2f,0x0b,0x2f,0x2f,0x2f,0xbe,0x2f,0xfe,0x8b,0x2f,0x80,
|
||||
0xf4,0x09,0x2f,0x13,0x3f,0xe0,0x3e,0xf0,0x3e,0xf4,0x3e,0xb8,0x3e,0x7c,0x3e,0x3e,
|
||||
0x3e,0x2f,0x3e,0x1f,0x00,0xff,0x01,0xff,0x02,0xfb,0x03,0xeb,0x07,0xcb,0x0b,0x8b,
|
||||
0x0f,0x4b,0x5f,0x0b,0x1f,0xf8,0x1f,0xbd,0x1f,0xbe,0x1f,0x6f,0x1f,0x4f,0x1f,0x4b,
|
||||
0x1f,0x43,0x1f,0x41,0x02,0xf0,0x42,0xf0,0xc2,0xf0,0xe2,0xf0,0xf2,0xf0,0xfa,0x07,
|
||||
0x0f,0x80,0x01,0x3e,0x3f,0x2e,0xaa,0x1f,0x80,0xbf,0xa0,0x00,0xfc,0x7e,0x00,0x95,
|
||||
0xea,0x0b,0xd0,0xaf,0xc0,0xff,0x40,0x02,0xf9,0x02,0x0b,0xbf,0x80,0x0f,0xd0,0x2e,
|
||||
0x01,0x03,0x7e,0xf0,0x07,0x0f,0xc0,0x01,0x41,0x0f,0x82,0x0f,0x82,0x0b,0xc3,0x07,
|
||||
0xd3,0x03,0xe7,0x03,0xeb,0x80,0xfb,0xc1,0xe7,0xc1,0xe7,0xd2,0xd3,0xe3,0xc2,0xe3,
|
||||
0x81,0xf7,0xbc,0xf4,0xd0,0xbd,0x2f,0x3f,0x1f,0x80,0x3f,0xf0,0x00,0x03,0xe0,0x3f,
|
||||
0x0b,0x00,0x07,0x2f,0xbc,0x03,0x02,0xbe,0x01,0xf8,0x7f,0xe0,0x0f,0xbd,0x02,0x01,
|
||||
0x00,0x3c,0x0d,0x1d,0xb4,0x1e,0x1f,0x2e,0xbf,0x2f,0xfe,0x06,0x08,0x2f,0x01,0xfc,
|
||||
0x00,0xbe,0xd0,0x07,0xf0,0x01,0x50,0x07,0x55,0x55,0xfe,0x00,0x04,0x3e,0x0f,0x3e,
|
||||
0x0b,0x3e,0x07,0x3e,0x03,0x3e,0x02,0x14,0xbe,0x0b,0xfd,0x0b,0xfc,0x0b,0xf8,0x0b,
|
||||
0xf4,0x0b,0x50,0x05,0x40,0xbe,0xf0,0x7f,0xf0,0x2f,0xf0,0x0f,0xf0,0x0b,0x05,0x7e,
|
||||
0x00,0xfd,0x0a,0x14,0x07,0xf4,0xbf,0xd0,0xff,0x80,0x9b,0xf4,0x02,0xfd,0x00,0x64,
|
||||
0x10,0xf4,0x03,0x40,0x1f,0xd0,0x1f,0xc0,0x90,0x0e,0x03,0x04,0x50,0x05,0x0b,0x04,
|
||||
0x02,0xfb,0x01,0xbe,0x00,0x81,0xfb,0x40,0xff,0x7f,0xbd,0x01,0xf8,0xf0,0x03,0xe0,
|
||||
0x04,0x2f,0x80,0x80,0xff,0x80,0x55,0x40,0x0a,0x1f,0xa9,0x1f,0xfe,0x05,0x54,0x21,
|
||||
0x7d,0x07,0xf8,0x1f,0x1a,0xbc,0x2f,0xfc,0x15,0x22,0x55,0x01,0x00,0x0b,0x40,0x1c,
|
||||
0x00,0x1c,0x40,0x48,0x19,0x58,0x0a,0x1f,0x0a,0x1e,0xad,0x02,0xfe,0x07,0xe4,0x48,
|
||||
0x3f,0x64,0x00,0xb8,0x19,0x18,0x2f,0x40,0x88,0xff,0x80,0x2f,0x80,0x1a,0x1c,0x55,
|
||||
0x0b,0xff,0x2f,0xeb,0x1d,0x00,0x04,0x01,0x00,0x6f,0x0b,0x01,0x05,0xfb,0x40,0xfc,
|
||||
0x2f,0x06,0x15,0x01,0xff,0x0b,0xfa,0x1f,0x90,0x2f,0x40,0xfd,0x00,0x1c,0x09,0x0f,
|
||||
0xd0,0xef,0x02,0x00,0xbf,0x02,0xfa,0x5a,0x1f,0xff,0xfe,0x80,0xbf,0x80,0xfe,0x3f,
|
||||
0xfd,0x3f,0xfd,0x12,0x00,0xeb,0x40,0xff,0x0f,0x00,0x15,0x3e,0xff,0x3f,0xfb,0x3f,
|
||||
0x40,0x3e,0xbd,0x00,0x11,0xb8,0x0d,0x42,0x6f,0x1f,0xfd,0x1f,0xbd,0xd0,0x05,0x12,
|
||||
0x2e,0xff,0x2f,0xef,0x2f,0x42,0x2e,0x02,0x50,0xdb,0xfe,0xff,0xbf,0xf8,0x1f,0x0b,
|
||||
0x05,0x1f,0x7f,0x1f,0xfa,0x1f,0xd0,0x7f,0x08,0x15,0x02,0x80,0x00,0xfd,0x1f,0x40,
|
||||
0x06,0xfa,0xfd,0x04,0x07,0xeb,0x0c,0x04,0x2e,0x80,0x14,0x07,0xff,0x0f,0xeb,0x74,
|
||||
0x18,0x15,0x1a,0xaa,0x55,0xff,0xff,0xaa,0x50,0xff,0xf8,0xaa,0xa4,0x21,0x90,0x01,
|
||||
0x3f,0xaf,0x1f,0xff,0x01,0xbc,0xfc,0x00,0xfe,0x40,0x6f,0x02,0xfa,0x2e,0xbf,0x14,
|
||||
0x05,0x06,0x1c,0xf8,0x06,0x2f,0xeb,0x80,0x04,0x1f,0xa5,0xd0,0x03,0xfa,0x40,0x40,
|
||||
0xf9,0x06,0x07,0xd0,0x01,0x13,0x0b,0xe5,0x07,0xff,0x00,0x6a,0x00,0x00,0x09,0x00,
|
||||
0x0b,0xff,0x00,0xbf,0x40,0xef,0x40,0x4f,0x7f,0x02,0x7d,0x14,0x0a,0x0f,0xf8,0x05,
|
||||
0xf8,0x3f,0xf4,0x2f,0x90,0x10,0x1f,0xef,0x42,0x80,0x15,0x0d,0x14,0x14,0x2f,0x00,
|
||||
0x04,0x7f,0x09,0xfa,0x2f,0xbf,0x2f,0x05,0x0a,0xfa,0x01,0xef,0x02,0x0e,0x16,0x08,
|
||||
0xeb,0xbd,0x22,0x01,0xa0,0x02,0xf0,0xff,0x26,0x68,0x02,0xfd,0x03,0xd4,0x03,0x17,
|
||||
0x28,0x00,0x38,0x16,0x09,0x40,0x1f,0xe0,0x05,0xf0,0x00,0xb0,0x7b,0x2b,0xe9,0xff,
|
||||
0xff,0xf9,0x6f,0x5b,0x03,0xc0,0xd0,0x68,0x28,0x00,0x3d,0x44,0x69,0x01,0xff,0xeb,
|
||||
0x1f,0x82,0x40,0x00,0xc0,0x0f,0xf0,0x02,0xf0,0x1f,0xff,0x1f,0xff,0x12,0x7e,0x04,
|
||||
0x0f,0xc0,0xe0,0x02,0xf0,0x01,0xf4,0x7c,0x05,0x3e,0x01,0x2f,0x02,0x1f,0x43,0x0f,
|
||||
0x83,0x0b,0xc7,0x07,0xcb,0x07,0xfc,0x0b,0xfd,0x0f,0xfe,0x0f,0xee,0x1f,0x9f,0xc0,
|
||||
0xc0,0x07,0xe0,0x01,0xf9,0x3f,0x2f,0xf8,0x02,0x7d,0xd1,0x03,0xe2,0x02,0xf7,0xb8,
|
||||
0xf0,0x03,0xff,0x2f,0xff,0x0b,0xf8,0x04,0x03,0xc0,0x02,0xc0,0x02,0xd0,0x02,0xd0,
|
||||
0x0b,0xc0,0x0e,0x38,0x0f,0x01,0xf8,0x01,0x16,0x6a,0x07,0xff,0x1f,0xea,0x2d,0x00,
|
||||
0x04,0xe4,0x00,0xff,0x96,0x2f,0xff,0x01,0xa9,0x10,0xf4,0x05,0x0e,0x00,0x2f,0x0a,
|
||||
0xbf,0x1f,0xff,0x05,0xbe,0x00,0xbd,0xd0,0x02,0x40,0x00,0xaa,0x80,0xff,0xd0,0x55,
|
||||
0xff,0xd0,0xff,0xd0,0xe0,0x00,0x17,0x34,0x0a,0xaf,0x0f,0xff,0x0a,0xaf,0x00,0x0f,
|
||||
0xc0,0x80,0x00,0xea,0x40,0xff,0x80,0xaa,0x40,0x80,0x5f,0x15,0x7d,0x3f,0xff,0x3f,
|
||||
0xff,0x54,0xfd,0x09,0x2a,0xbe,0x3f,0xff,0x2a,0xbe,0xa9,0xa8,0x09,0x1e,0xb4,0x1e,
|
||||
0x01,0xfe,0x40,0x07,0x3f,0x41,0x2f,0xeb,0x0b,0xff,0xbe,0xbe,0x05,0x00,0xf9,0x1f,
|
||||
0x06,0x03,0xdf,0x02,0xff,0x02,0xfe,0xfd,0x4f,0x7d,0x0b,0xbc,0x07,0xf8,0x07,0xf4,
|
||||
0x03,0xf4,0x01,0x50,0x03,0x7f,0x00,0xfa,0x02,0xf4,0x0b,0xe0,0x2f,0x80,0x05,0x03,
|
||||
0x01,0xfb,0x7f,0xbd,0x2f,0xf8,0x1f,0x01,0xf8,0x07,0xe0,0x1f,0x80,0x15,0x55,0xfc,
|
||||
0x54,0x04,0xd0,0x02,0xc0,0x03,0xc0,0x03,0x80,0x03,0xd0,0x02,0xfd,0x00,0x68,0x10,
|
||||
0x1d,0x00,0xb0,0x01,0xf0,0x1f,0xe0,0x0a,0x40,0x71,0x0f,0x01,0xe4,0x07,0xff,0xbf,
|
||||
0xbf,0xff,0x06,0x94,0xd0,0x07,0x16,0x0b,0x00,0x0e,0x14,0x0f,0x1f,0x04,0x1f,0x1f,
|
||||
0xbe,0x0b,0xfd,0x00,0x60,0x40,0x0d,0x3e,0x0f,0x0e,0x03,0x0d,0x03,0x34,0x0e,0x08,
|
||||
0x06,0x00,0x1f,0xc0,0x1f,0xc0,0x06,0x18,0x00,0x7e,0x01,0x7f,0x01,0x19,0x60,0x64,
|
||||
0x3d,0x28,0x1d,0x0e,0x38,0x06,0xe4,0x0b,0xbc,0x1d,0x90,0x02,0xd0,0x07,0x03,0x01,
|
||||
0x00,0x07,0xe0,0x02,0xfa,0x1a,0x00,0xaf,0x04,0x40,0x00,0xa4,0x0a,0x0b,0x0f,0x6f,
|
||||
0x01,0xff,0x03,0xf5,0x96,0xaa,0xff,0xff,0xff,0xaa,0xa4,0xa4,0x25,0x07,0xd0,0xbf,
|
||||
0x00,0x1a,0x1a,0xaa,0xaa,0x67,0x40,0x1c,0x00,0x2c,0x19,0x17,0x01,0x1c,0x07,0x3c,
|
||||
0x0f,0x39,0x0e,0x40,0x0f,0x80,0x5e,0x26,0x90,0x0f,0xf8,0x2f,0xbf,0x38,0x1b,0x20,
|
||||
0x02,0x40,0x4b,0x80,0xff,0x09,0x1a,0xa9,0x2f,0xfe,0xa0,0x19,0xf8,0x2e,0xfc,0x7e,
|
||||
0xfe,0xfe,0xef,0xea,0x0b,0x80,0x07,0xf6,0x14,0x08,0x0f,0x7e,0x1d,0x1e,0x0b,0xbd,
|
||||
0x06,0xf6,0x1e,0x00,0x2d,0x0f,0x00,0x2d,0x00,0x78,0x85,0x00,0x7f,0x81,0xb6,0xd3,
|
||||
0x64,0xdb,0x40,0x07,0xff,0x0f,0x90,0x2f,0x00,0x6f,0x00,0x6f,0x40,0xa0,0xbf,0x00,
|
||||
0xb8,0x01,0xf4,0x02,0xe0,0x07,0xc0,0x0f,0x0f,0x40,0x0b,0xc0,0x0e,0x0b,0x1f,0x2e,
|
||||
0x1e,0x3f,0x40,0x40,0x0b,0x40,0x0b,0xff,0xe0,0x25,0x2f,0xff,0x3f,0x00,0xbd,0xff,
|
||||
0x80,0xbf,0x80,0xbe,0x09,0x4e,0x2f,0x80,0x2f,0x80,0x1a,0x19,0x00,0x39,0x19,0x29,
|
||||
0x0a,0x0a,0x10,0x15,0x54,0x2f,0xfd,0x16,0x1a,0xaa,0xaa,0xaa,0xa8,0x05,0x55,0x55,
|
||||
0x55,0x55,0x54,0xff,0xf8,0xaa,0x21,0x01,0x90,0xeb,0xda,0xe2,0x8a,0xe0,0x0a,0x90,
|
||||
0x0a,0x07,0xff,0xaa,0x80,0x0f,0x90,0x07,0xfe,0xe0,0x90,0x7c,0x90,0x00,0xd0,0x01,
|
||||
0xf0,0x7d,0x07,0x54,0xef,0x1f,0x43,0x2e,0x01,0x2d,0x50,0x4b,0xfd,0xdf,0xaf,0xfd,
|
||||
0x0b,0xf8,0x03,0xf9,0xaf,0xff,0xfe,0xc0,0x32,0xb4,0x01,0xe1,0x03,0xc0,0x0b,0x40,
|
||||
0x1e,0xe1,0xe7,0xd1,0xeb,0xe1,0xe7,0xf6,0xd3,0x7f,0xc2,0x87,0x80,0x47,0x80,0x87,
|
||||
0x80,0xdb,0x40,0xfe,0x2f,0x40,0x1f,0xfa,0x02,0xff,0xc0,0xc0,0xbf,0x40,0xfd,0x00,
|
||||
0x04,0x03,0xe0,0x3d,0x0b,0x00,0x0e,0x1f,0x7f,0x40,0xff,0xff,0xeb,0xff,0x45,0x54,
|
||||
0x23,0x02,0xf8,0x0b,0xaa,0x80,0x55,0x72,0x9f,0x1a,0xa8,0xdd,0xaf,0x00,0x01,0x0a,
|
||||
0x00,0x1f,0xea,0x06,0xff,0xf8,0x00,0xbd,0xfd,0x05,0xb8,0x01,0xf0,0x03,0xd0,0x0b,
|
||||
0x80,0x0f,0x40,0x2e,0x10,0x2d,0x00,0x2e,0x01,0x1f,0x43,0x0b,0xef,0x02,0xfa,0x50,
|
||||
0xf8,0x01,0xfd,0x07,0xdf,0xaf,0x4b,0xfe,0x80,0x43,0x04,0x0b,0xd7,0x10,0xf4,0x06,
|
||||
0xfc,0x1a,0xa4,0x3c,0x3e,0x2b,0x05,0x00,0x01,0x7f,0x00,0x00,0x00,0xa9,0x00,0xff,
|
||||
0x80,0x5b,0xd0,0x0c,0x2d,0x10,0x08,0x40,0x0f,0x80,0x0b,0x68,0x01,0xf8,0x03,0xf0,
|
||||
0x06,0x18,0x2d,0x0b,0xfa,0x07,0x40,0x2e,0x06,0x0b,0x15,0x05,0xd0,0x0b,0x06,0xb8,
|
||||
0x02,0x15,0x40,0xff,0xf9,0x95,0x6f,0x00,0x02,0x05,0x80,0xb8,0x50,0x0f,0xf8,0x09,
|
||||
0x01,0xfe,0x07,0x5e,0x17,0x08,0x00,0x2c,0xb0,0x0e,0x38,0x68,0x03,0x01,0xa4,0x1f,
|
||||
0xff,0x3d,0x0b,0x3c,0x03,0x3d,0x07,0x1f,0xbf,0xc0,0x0e,0x01,0x90,0x07,0x06,0xa4,
|
||||
0x1f,0xbd,0x3c,0x1e,0x14,0x1e,0x01,0xfd,0x1e,0x07,0xff,0x15,0x05,0x57,0x2f,0xf4,
|
||||
0x03,0x1f,0x03,0xf0,0x01,0x1f,0x00,0x0b,0x02,0xf4,0x03,0xe0,0x40,0x3e,0x30,0x2a,
|
||||
0x29,0x2e,0x07,0xbf,0x02,0xfe,0x0b,0xe0,0x0f,0x80,0x1f,0x40,0x1f,0x41,0x1f,0x42,
|
||||
0xad,0x40,0xbb,0xc0,0xf2,0xc0,0xe0,0x00,0x01,0xf4,0xf4,0x00,0xb8,0x05,0xbd,0x1f,
|
||||
0xff,0x0a,0xbe,0x00,0x2e,0x02,0xe0,0x01,0x55,0xa9,0x01,0x1f,0x46,0x07,0xef,0x01,
|
||||
0xf9,0x01,0xe0,0xf0,0x91,0xf4,0xff,0xd0,0x6f,0x40,0x0b,0x80,0x03,0x00,0x02,0x3f,
|
||||
0x05,0x6f,0x0f,0xff,0x0a,0xab,0x00,0x03,0x0b,0xd0,0x1f,0x80,0x2f,0xf9,0x50,0xff,
|
||||
0xf8,0xea,0xa4,0x00,0x14,0x11,0xf9,0x06,0xff,0x0f,0x96,0x1f,0x0f,0xd0,0x07,0xfe,
|
||||
0x04,0xff,0xbf,0x2f,0x07,0x80,0x0b,0x02,0x0e,0x0b,0x1d,0x0b,0x1d,0x0f,0x0b,0x0e,
|
||||
0x07,0xbf,0xf8,0xe5,0x7d,0x80,0x08,0x40,0x00,0xc0,0x09,0x2d,0x0b,0x00,0x07,0x40,
|
||||
0x0b,0x00,0x2d,0x0e,0x1d,0x3f,0x0b,0xe6,0x00,0x00,0x2a,0xaa,0x2a,0xaa,0x80,0x05,
|
||||
0x01,0xe0,0x03,0xc0,0x07,0x42,0x0e,0x07,0x2d,0x0f,0x38,0x1d,0x2c,0x0e,0x0e,0x07,
|
||||
0xb4,0x04,0x15,0x55,0x7f,0xff,0x6a,0xaf,0x05,0x40,0x05,0x07,0x81,0x02,0x1d,0x0e,
|
||||
0x02,0xaa,0x90,0xea,0xf4,0xc0,0x38,0xc0,0x38,0xea,0xf4,0xeb,0xd0,0xc1,0xe0,0xc0,
|
||||
0xf4,0x1f,0x1e,0x02,0x00,0x02,0x1a,0xab,0xab,0x00,0xe0,0x00,0xea,0xa8,0xff,0xfd,
|
||||
0xfa,0xa9,0xe0,0x03,0x0b,0x90,0x2e,0x00,0x3e,0x21,0xbd,0x02,0xf4,0x0b,0xd0,0x2f,
|
||||
0xea,0x05,0x07,0x01,0x34,0x3e,0x2a,0x11,0x0f,0xc3,0x0b,0xe7,0xbf,0x2c,0x81,0xc0,
|
||||
0x47,0xc0,0xaf,0x80,0xfe,0x01,0x3d,0xf9,0x0f,0xff,0x0b,0x24,0xfa,0xfc,0xff,0xf4,
|
||||
0x15,0x03,0xef,0x1f,0x46,0x1d,0x6f,0x40,0xfb,0xd0,0x91,0xf4,0x00,0x74,0x06,0x0a,
|
||||
0xab,0x0f,0x03,0xea,0xa4,0xff,0xf8,0xe5,0x50,0x08,0x2d,0x29,0x14,0x6f,0x00,0x01,
|
||||
0x01,0x07,0xe5,0x01,0xf9,0x2f,0xbe,0x90,0x31,0x0b,0x02,0x07,0x80,0xb8,0xf9,0xbd,
|
||||
0xbf,0xf4,0x02,0x95,0x6f,0xff,0xf9,0xb8,0x26,0x0b,0x42,0x03,0x81,0xf0,0x2c,0xe0,
|
||||
0x38,0x0e,0x00,0x0a,0x0a,0x3c,0x81,0xc0,0x78,0x80,0x37,0x20,0xaa,0xaa,0xaa,0xa9,
|
||||
0x4a,0x01,0xa9,0x0b,0xef,0x0a,0x07,0x00,0x5b,0x05,0x10,0x01,0xf8,0x0b,0xfd,0x2f,
|
||||
0xd0,0x09,0x4b,0x01,0xbf,0x0b,0xff,0x2f,0xfe,0x1e,0x65,0x01,0x40,0x1b,0x80,0x3f,
|
||||
0x80,0x12,0x80,0x02,0x15,0x01,0x50,0x0b,0xfd,0x1e,0x0b,0x2c,0x07,0x2c,0x07,0x40,
|
||||
0x09,0x04,0x08,0x2c,0x0e,0x1e,0x0b,0x0b,0x03,0x0c,0x02,0xe0,0x1f,0x14,0x39,0x50,
|
||||
0x0b,0xfe,0x1e,0x01,0x00,0x0b,0x40,0x1f,0x0d,0xc0,0x04,0x0b,0x01,0xf8,0x05,0x3f,
|
||||
0x00,0x19,0xf4,0x03,0x06,0xf4,0xa0,0x2f,0x01,0x04,0x14,0xff,0x07,0x41,0x02,0x40,
|
||||
0x20,0xe0,0xb4,0xff,0xf0,0x6f,0xd0,0x05,0x06,0x7e,0x15,0xc0,0xfc,0x06,0x2e,0x2e,
|
||||
0x90,0x0b,0x5f,0xfc,0x10,0x05,0x00,0x00,0xff,0x10,0x07,0x19,0x03,0x1f,0xaf,0x06,
|
||||
0xfa,0xc0,0x3d,0x05,0x00,0x14,0x00,0x7d,0xbd,0x00,0xfe,0x2f,0xfe,0x0b,0xfe,0x01,
|
||||
0x00,0x2e,0x06,0x1f,0xd0,0x05,0x34,0x80,0x16,0x2d,0x0b,0x0f,0xae,0x02,0xa4,0x06,
|
||||
0x03,0x81,0x02,0xd0,0x74,0x00,0x3c,0x2c,0x00,0x74,0x0e,0xe0,0x01,0x00,0x92,0x00,
|
||||
0x07,0x02,0xe0,0x07,0xd0,0x0b,0x40,0x2e,0x00,0x7c,0x00,0xf4,0x1a,0xe0,0x7e,0xc0,
|
||||
0xfa,0x19,0xbf,0xe2,0xe6,0xc2,0x80,0x0b,0x01,0xae,0x01,0xaf,0x00,0x07,0x2d,0x07,
|
||||
0x1f,0xaf,0x01,0x40,0x41,0xf0,0x83,0xd0,0x8b,0x80,0x6e,0x02,0x7d,0x0b,0xb4,0x90,
|
||||
0x0b,0x06,0x0f,0x00,0x6f,0x02,0xfe,0x03,0x2f,0x7d,0x00,0xfc,0x01,0xf4,0x02,0xfa,
|
||||
0xf8,0x7e,0x1f,0x40,0x0f,0xc0,0x0b,0xd0,0xab,0xe0,0x07,0xfc,0x80,0x03,0x0f,0x25,
|
||||
0xbc,0x03,0x3f,0xc0,0x01,0x07,0x1f,0x7d,0xfe,0xfd,0xaf,0x00,0x4f,0x07,0xab,0xf4,
|
||||
0x05,0x5f,0xe0,0x01,0xff,0xff,0xf9,0x55,0xf8,0xf8,0x07,0xfe,0x40,0x2f,0x80,0xaf,
|
||||
0xe0,0x02,0xa0,0x00,0x6d,0x1f,0xeb,0x1f,0xff,0x1f,0xa9,0x1a,0xfd,0x7d,0x0d,0x33,
|
||||
0x40,0x02,0x03,0xc0,0x1f,0x80,0x2e,0x0a,0x58,0xf0,0x81,0x0b,0x43,0x0e,0x07,0x2c,
|
||||
0x0e,0x14,0x78,0xd0,0x2e,0x00,0xb8,0xd0,0x06,0x42,0xda,0x0b,0x4a,0x1e,0xaf,0x1a,
|
||||
0xaf,0x90,0x40,0x02,0xb8,0xea,0x02,0xa0,0x02,0x7c,0x00,0x64,0x79,0xc1,0xe1,0x43,
|
||||
0x01,0xe8,0xd0,0x0b,0xe0,0x1f,0x80,0x0f,0xe0,0x07,0xff,0x02,0x90,0x07,0xd0,0x2f,
|
||||
0xc0,0xff,0x40,0xf8,0x02,0xff,0x0b,0xd5,0x0f,0xc0,0x00,0x00,0xff,0xf0,0xfc,0x3e,
|
||||
0x02,0x3f,0x56,0xf4,0x0a,0x07,0x23,0x2f,0x14,0xf8,0x7e,0x04,0x02,0xff,0x03,0xf5,
|
||||
0xff,0xf8,0x55,0xbc,0x2f,0x40,0xe5,0x07,0xd0,0x0f,0x7d,0x08,0x3e,0xfe,0xaa,0xff,
|
||||
0xff,0x55,0x90,0x07,0xf5,0x1b,0x07,0x2e,0x00,0x00,0x17,0xf0,0xff,0xd0,0xf9,0x17,
|
||||
0x10,0x00,0x7d,0x2f,0xff,0x03,0x01,0xbf,0x02,0xfd,0x01,0x90,0x80,0x05,0x2a,0xff,
|
||||
0x0b,0xe2,0x0b,0x40,0xe0,0x78,0x06,0x00,0x0b,0xd2,0x05,0x50,0x03,0xb9,0x00,0xff,
|
||||
0x80,0x2f,0xe0,0x01,0x3e,0x14,0x40,0xbf,0xc0,0xf9,0x12,0x6a,0xff,0xe0,0xd2,0xf8,
|
||||
0x40,0xb8,0x00,0x10,0x14,0xc2,0xf4,0x40,0x50,0x16,0x7f,0xff,0xe4,0x01,0x90,0x0b,
|
||||
0xfd,0x1f,0xbf,0x2d,0x0b,0x14,0x80,0x42,0xc0,0xff,0x80,0xfe,0x02,0x00,0x80,0xfd,
|
||||
0x00,0x28,0xfe,0x07,0x0a,0x6f,0xb8,0x54,0x07,0x7e,0x11,0xa4,0xff,0x40,0x5f,0x05,
|
||||
0x81,0x24,0x95,0x04,0x01,0xc0,0x05,0x40,0x05,0x60,0x0c,0x54,0x7e,0xff,0x02,0x3f,
|
||||
0x2f,0x80,0x00,0xe4,0x68,0xf0,0x05,0x2f,0x38,0x40,0xf4,0x03,0x06,0x01,0xf8,0x90,
|
||||
0x7e,0x06,0x02,0xf8,0x2f,0xf0,0x0e,0x2f,0xff,0x2f,0x00,0xff,0x2f,0xaa,0x2f,0xfd,
|
||||
0x00,0xa9,0x03,0x2e,0x29,0xfc,0x00,0xa8,0x12,0x00,0x0c,0x3e,0x0e,0x7e,0x7e,0x0a,
|
||||
0xbe,0x1f,0xff,0x0a,0xbe,0xff,0xfe,0x0b,0x02,0xa4,0xa4,0x02,0xf0,0xf0,0x00,0x2f,
|
||||
0xd0,0x2f,0xf0,0x2f,0xf8,0x2e,0xbd,0x2e,0x3f,0x2e,0x2f,0x2e,0x0f,0x2e,0x82,0xe0,
|
||||
0xd2,0xe0,0xe2,0x07,0xfe,0x0f,0xd0,0x7e,0x7e,0x00,0xbf,0xd0,0x0b,0xe0,0x02,0xbc,
|
||||
0xbd,0xff,0x03,0xf4,0x0b,0xd0,0x2f,0x3e,0x00,0x07,0x44,0xc0,0xaf,0xf4,0x02,0xfc,
|
||||
0x3f,0x00,0x40,0xd0,0x07,0xf4,0x01,0xfd,0xbe,0x01,0xf8,0x07,0x7e,0xbe,0x00,0x0b,
|
||||
0x42,0x1f,0x4b,0xaf,0xf4,0x07,0xf8,0x0f,0xfd,0x2f,0x7e,0x7d,0x2f,0xf8,0xd0,0x02,
|
||||
0xf0,0x5f,0x0e,0x05,0xaa,0x2f,0xff,0x15,0xaa,0x40,0xff,0x80,0x55,0x09,0x78,0x15,
|
||||
0x13,0x7e,0x7f,0x03,0x6f,0xab,0xfe,0xff,0xe4,0xe0,0x2e,0x02,0xf6,0xe0,0xfe,0xe0,
|
||||
0x7f,0xe0,0x2f,0xe0,0x0f,0xe0,0x05,0x50,0x04,0xfa,0x1a,0x02,0xf8,0x07,0xf0,0xaf,
|
||||
0xd0,0xfe,0x40,0xa4,0x04,0x06,0xbe,0x01,0xfc,0xaf,0xf4,0xff,0x90,0xa5,0x09,0x02,
|
||||
0xbd,0x80,0x04,0x02,0xf8,0x15,0x3f,0xab,0xa9,0x04,0xf8,0x0b,0xe0,0x2f,0x80,0x1d,
|
||||
0x80,0xf8,0x08,0x0f,0x9f,0x0b,0xfe,0x07,0xfd,0x02,0xfe,0xc6,0x0a,0x80,0x05,0x0f,
|
||||
0xd0,0x0b,0x07,0xe0,0x08,0xc0,0x0b,0xfa,0x02,0xc0,0xfe,0x40,0x94,0x05,0x2f,0x0b,
|
||||
0x00,0x05,0x80,0x03,0x90,0x18,0x00,0x34,0x11,0x1a,0x1d,0x01,0xaa,0x09,0x0a,0x00,
|
||||
0xbf,0x03,0xfd,0xd0,0x0a,0xf8,0x08,0x40,0x0b,0xf8,0x2f,0xfe,0x78,0x1f,0x40,0x07,
|
||||
0x80,0xff,0x09,0x0b,0xe1,0x05,0x19,0x01,0xff,0xc0,0x02,0xe5,0xd0,0xb4,0x00,0x0f,
|
||||
0x4a,0x16,0x80,0x3b,0x15,0x18,0xfd,0x17,0xe2,0xf8,0x18,0x17,0xb8,0x1f,0x06,0x00,
|
||||
0xaf,0x0a,0x1f,0x00,0x40,0xff,0x10,0x03,0x2f,0x00,0x0f,0x07,0xe0,0x0b,0xc0,0x1f,
|
||||
0x40,0xd0,0x02,0x2f,0x55,0xa4,0x6f,0x80,0x6f,0x0b,0xff,0x2f,0x95,0x01,0x3e,0x2f,
|
||||
0x3e,0x1a,0x3e,0x00,0xf9,0xf8,0x00,0xbe,0x01,0x00,0x02,0xbf,0x1f,0xff,0x2e,0x41,
|
||||
0x08,0x00,0x00,0x5b,0x07,0xff,0xf8,0xfc,0x00,0x00,0xfc,0x00,0x40,0x01,0x1e,0x78,
|
||||
0x90,0x00,0x20,0x02,0xfd,0x05,0x01,0x1f,0x40,0x1b,0x06,0xff,0x54,0xbc,0x03,0x05,
|
||||
0x05,0xff,0x1f,0xff,0x0e,0x02,0x04,0x02,0x00,0x02,0x06,0x5b,0xf8,0xff,0xfe,0xf8,
|
||||
0x1f,0xf0,0x0b,0xe5,0xab,0xff,0x40,0x00,0x05,0x01,0xbf,0x07,0xfa,0x1f,0x80,0x04,
|
||||
0x02,0x00,0x00,0xaf,0x07,0xff,0x0f,0x90,0x2f,0x00,0x2e,0x16,0x3f,0xff,0x90,0xbe,
|
||||
0xaf,0x00,0x00,0x01,0xbf,0x3e,0x00,0xbf,0x01,0x1f,0xbd,0x02,0x05,0x2e,0x00,0x3d,
|
||||
0x50,0x06,0x2a,0x0e,0x2a,0x19,0x40,0xb8,0x00,0x10,0x29,0x1a,0x1a,0x02,0xfe,0x00,
|
||||
0x00,0x6f,0x1f,0x40,0x2f,0x40,0xef,0x80,0xff,0xc0,0x2f,0xc0,0x20,0x19,0x6a,0x2e,
|
||||
0xff,0x2f,0xd5,0x2f,0x13,0x0b,0x05,0xc0,0x40,0x04,0xa4,0x10,0x05,0x29,0x08,0x1f,
|
||||
0xe4,0x2f,0xab,0x1f,0xff,0x01,0xfe,0x40,0xbf,0x40,0x06,0x04,0x3f,0x17,0x1f,0xe4,
|
||||
0x2e,0xaf,0x0a,0x01,0x1a,0xbc,0x00,0xfe,0x80,0xaf,0x80,0x34,0x0f,0xff,0x02,0x2f,
|
||||
0x5f,0x1f,0xff,0x06,0xfa,0x94,0xe0,0x01,0xf4,0x07,0xfe,0xaf,0x6f,0xfe,0x06,0x80,
|
||||
0x0b,0xe4,0x6f,0x00,0x0f,0xbd,0x6e,0x90,0x05,0xa9,0x2e,0x0b,0xea,0x50,0x1e,0x40,
|
||||
0x49,0xfe,0x09,0x00,0xf4,0x05,0x4e,0x14,0x43,0x07,0xf9,0x07,0xd0,0x0b,0xd0,0x1f,
|
||||
0xc0,0xbf,0x50,0x13,0x1e,0xbf,0x00,0x1b,0xd0,0x0a,0x01,0x7f,0x01,0x18,0x1a,0x00,
|
||||
0xbf,0x01,0xff,0x07,0xe5,0xf4,0x0c,0xf4,0x3f,0x0a,0x03,0x03,0xbd,0x0e,0xf4,0x3a,
|
||||
0x2e,0x00,0xf4,0x1b,0xe0,0x09,0x7f,0xf5,0x0a,0x07,0xe0,0x04,0x27,0x1f,0x0b,0xe0,
|
||||
0x16,0xff,0x36,0x6a,0xe5,0x2f,0x3e,0x00,0xa0,0x40,0x0f,0x80,0x0b,0x00,0xa0,0x00,
|
||||
0x0f,0x00,0x80,0x01,0x1f,0x7d,0x0a,0x20,0x07,0x00,0x1f,0x01,0x01,0x6a,0xe5,0xfd,
|
||||
0x80,0x00,0x05,0x55,0x2f,0xff,0x1a,0xaa,0x55,0x55,0xff,0xff,0xaa,0xaa,0x6a,0x06,
|
||||
0x81,0x2f,0x02,0x2e,0x0b,0x9f,0x40,0xfe,0x80,0xef,0x80,0xcb,0xc0,0x02,0x0a,0xa0,
|
||||
0x02,0x1a,0x6d,0x1a,0x2f,0x54,0x07,0x1a,0x00,0xf9,0x40,0xf8,0x01,0x5b,0x2f,0xbf,
|
||||
0x2f,0xf4,0x2f,0xe0,0x2f,0x40,0xd0,0x02,0xd0,0x02,0xf9,0x0a,0x04,0xff,0x3d,0x2f,
|
||||
0x40,0x08,0x2f,0x1f,0x0d,0x3f,0x00,0x09,0x5a,0x40,0x2f,0x09,0x2f,0x0b,0xfa,0x0b,
|
||||
0xc0,0x80,0x08,0x60,0x06,0x1f,0x2f,0x7e,0x1f,0xf8,0x0b,0xfa,0x03,0xff,0x0b,0x9a,
|
||||
0x4b,0xc0,0x0c,0x69,0x3f,0x40,0xff,0x40,0xef,0x40,0x05,0x09,0x0f,0xfa,0x07,0x7f,
|
||||
0x10,0xea,0x7f,0xef,0x00,0x34,0x00,0x1f,0x00,0x7f,0x0f,0xfd,0x0f,0xf0,0xd0,0x00,
|
||||
0x00,0xf0,0x2f,0xfe,0x2f,0x6f,0x2f,0x45,0x07,0xd0,0x90,0x08,0xbe,0xd0,0x80,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xa2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
};
|
||||
|
||||
/*** Backdrop ***/
|
||||
char backdrop[(640 * 480 * 2) + 32];
|
||||
|
||||
@ -46,8 +629,6 @@ typedef struct
|
||||
|
||||
static unsigned char fontWork[ 0x20000 ] __attribute__((aligned(32)));
|
||||
static unsigned char fontFont[ 0x40000 ] __attribute__((aligned(32)));
|
||||
extern unsigned int *xfb[2];
|
||||
extern int whichfb;
|
||||
|
||||
/****************************************************************************
|
||||
* YAY0 Decoding
|
||||
@ -144,13 +725,14 @@ void untile(unsigned char *dst, unsigned char *src, int xres, int yres)
|
||||
}
|
||||
|
||||
int font_offset[256], font_size[256], fheight;
|
||||
extern void __SYS_ReadROM(void *buf,u32 len,u32 offset);
|
||||
//extern void __SYS_ReadROM(void *buf,u32 len,u32 offset);
|
||||
|
||||
void init_font(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
__SYS_ReadROM((unsigned char *)&fontFont,0x3000,0x1FCF00);
|
||||
//__SYS_ReadROM((unsigned char *)&fontFont,0x3000,0x1FCF00);
|
||||
memcpy(&fontFont, &iplfont, sizeof(iplfont));
|
||||
yay0_decode((unsigned char *)&fontFont, (unsigned char *)&fontWork);
|
||||
FONT_HEADER *fnt;
|
||||
|
||||
@ -177,8 +759,8 @@ void init_font(void)
|
||||
|
||||
#define TRANSPARENCY (COLOR_BLACK)
|
||||
|
||||
unsigned int blit_lookup[4] = {COLOR_BLACK, 0x6d896d77, 0xb584b57b, 0xff80ff80};
|
||||
unsigned int blit_lookup_inv[4] = {COLOR_WHITE, 0xb584b57b, 0x6d896d77, 0x258e2573};
|
||||
unsigned int blit_lookup[4]={COLOR_BLACK, 0x6d896d77, 0xb584b57b, COLOR_WHITE};
|
||||
unsigned int blit_lookup_inv[4]={COLOR_WHITE, 0xb584b57b, 0x6d896d77, 0x258e2573};
|
||||
|
||||
void setfontcolour (int fcolour)
|
||||
{
|
||||
@ -186,7 +768,7 @@ void setfontcolour (int fcolour)
|
||||
{
|
||||
blit_lookup[1] = 0x6d896d77;
|
||||
blit_lookup[2] = 0xb584b57b;
|
||||
blit_lookup[3] = 0xff80ff80;
|
||||
blit_lookup[3] = COLOR_WHITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -235,24 +817,24 @@ void blit_char(int x, int y, unsigned char c, unsigned int *lookup)
|
||||
}
|
||||
}
|
||||
|
||||
void write_font(int x, int y, const unsigned char *string)
|
||||
void write_font(int x, int y, char *string)
|
||||
{
|
||||
int ox = x;
|
||||
while (*string && (x < (ox + back_framewidth)))
|
||||
{
|
||||
blit_char(x, y, *string, blit_lookup);
|
||||
x += font_size[*string];
|
||||
x += font_size[(u8)*string];
|
||||
string++;
|
||||
}
|
||||
}
|
||||
|
||||
void writex(int x, int y, int sx, int sy, const unsigned char *string, unsigned int *lookup)
|
||||
void writex(int x, int y, int sx, int sy, char *string, unsigned int *lookup)
|
||||
{
|
||||
int ox = x;
|
||||
while ((*string) && ((x) < (ox + sx)))
|
||||
{
|
||||
blit_char(x, y, *string, lookup);
|
||||
x += font_size[*string];
|
||||
x += font_size[(u8)*string];
|
||||
string++;
|
||||
}
|
||||
|
||||
@ -264,19 +846,19 @@ void writex(int x, int y, int sx, int sy, const unsigned char *string, unsigned
|
||||
}
|
||||
}
|
||||
|
||||
void WriteCentre( int y, const unsigned char *string)
|
||||
void WriteCentre( int y, char *string)
|
||||
{
|
||||
int x, t;
|
||||
for (x=t=0; t<strlen(string); t++) x += font_size[string[t]];
|
||||
for (x=t=0; t<strlen(string); t++) x += font_size[(u8)string[t]];
|
||||
if (x>back_framewidth) x=back_framewidth;
|
||||
x = (640 - x) >> 1;
|
||||
write_font(x, y, string);
|
||||
}
|
||||
|
||||
void WriteCentre_HL( int y, const unsigned char *string)
|
||||
void WriteCentre_HL( int y, char *string)
|
||||
{
|
||||
int x,t,h;
|
||||
for (x=t=0; t<strlen(string); t++) x += font_size[string[t]];
|
||||
for (x=t=0; t<strlen(string); t++) x += font_size[(u8)string[t]];
|
||||
if (x>back_framewidth) x = back_framewidth;
|
||||
h = x;
|
||||
x = (640 - x) >> 1;
|
||||
@ -326,6 +908,7 @@ u8 SILENT = 0;
|
||||
|
||||
void SetScreen ()
|
||||
{
|
||||
|
||||
VIDEO_SetNextFramebuffer (xfb[whichfb]);
|
||||
VIDEO_Flush ();
|
||||
VIDEO_WaitVSync ();
|
||||
@ -338,21 +921,31 @@ void ClearScreen ()
|
||||
back_framewidth = 440;
|
||||
}
|
||||
|
||||
void WaitButtonA ()
|
||||
{
|
||||
s16 p = ogc_input__getMenuButtons();
|
||||
|
||||
while (p & PAD_BUTTON_A)
|
||||
{
|
||||
VIDEO_WaitVSync();
|
||||
p = ogc_input__getMenuButtons();
|
||||
}
|
||||
|
||||
while (!(p & PAD_BUTTON_A))
|
||||
{
|
||||
VIDEO_WaitVSync();
|
||||
p = ogc_input__getMenuButtons();
|
||||
}
|
||||
}
|
||||
|
||||
void WaitPrompt (char *msg)
|
||||
{
|
||||
int quit = 0;
|
||||
|
||||
if (SILENT) return;
|
||||
|
||||
while (PAD_ButtonsDown(0) & PAD_BUTTON_A) {};
|
||||
while (!(PAD_ButtonsDown(0) & PAD_BUTTON_A) && (quit == 0))
|
||||
{
|
||||
ClearScreen();
|
||||
WriteCentre(254, msg);
|
||||
WriteCentre(254 + fheight, "Press A to Continue");
|
||||
SetScreen();
|
||||
while (!(PAD_ButtonsDown(0) & PAD_BUTTON_A));
|
||||
}
|
||||
WaitButtonA ();
|
||||
}
|
||||
|
||||
void ShowAction (char *msg)
|
||||
@ -364,12 +957,6 @@ void ShowAction (char *msg)
|
||||
SetScreen();
|
||||
}
|
||||
|
||||
void WaitButtonA ()
|
||||
{
|
||||
while (PAD_ButtonsDown(0) & PAD_BUTTON_A) {};
|
||||
while (!(PAD_ButtonsDown(0) & PAD_BUTTON_A));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Unpack Backdrop
|
||||
*
|
||||
@ -382,7 +969,7 @@ void unpackBackdrop ()
|
||||
|
||||
inbytes = gpback_COMPRESSED;
|
||||
outbytes = gpback_RAW;
|
||||
res = uncompress ((char *) &backdrop[0], &outbytes, (char *) &gpback[0], inbytes);
|
||||
res = uncompress ((Bytef *) &backdrop[0], &outbytes, (Bytef *) &gpback[0], inbytes);
|
||||
if (res != Z_OK) while (1);
|
||||
}
|
||||
|
||||
|
@ -1,23 +1,3 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
***************************************************************************/
|
||||
/*****************************************************************************
|
||||
* IPL FONT Engine
|
||||
*
|
||||
@ -26,9 +6,9 @@
|
||||
*****************************************************************************/
|
||||
|
||||
extern void init_font(void);
|
||||
extern void WriteCentre_HL( int y, const unsigned char *string);
|
||||
extern void WriteCentre (int y, const unsigned char *text);
|
||||
extern void write_font (int x, int y, const unsigned char *text);
|
||||
extern void WriteCentre_HL( int y, char *string);
|
||||
extern void WriteCentre (int y, char *text);
|
||||
extern void write_font (int x, int y, char *text);
|
||||
extern void WaitPrompt (char *msg);
|
||||
extern void ShowAction (char *msg);
|
||||
extern void WaitButtonA ();
|
||||
@ -40,3 +20,4 @@ extern void setfontcolour (int fcolour);
|
||||
extern int fheight;
|
||||
extern int font_size[256];
|
||||
extern u16 back_framewidth;
|
||||
extern u8 SILENT;
|
||||
|
@ -22,10 +22,11 @@
|
||||
|
||||
#include "shared.h"
|
||||
#include "font.h"
|
||||
#include "rominfo.h"
|
||||
|
||||
#define MAXCODES 8
|
||||
|
||||
extern char menutitle[60];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int address;
|
||||
@ -39,7 +40,6 @@ int ggrow = 0;
|
||||
int editing = 0;
|
||||
char ggvalidchars[] = "ABCDEFGHJKLMNPRSTVWXYZ0123456789*";
|
||||
GGPATCH ggpatch[8];
|
||||
extern char menutitle[];
|
||||
|
||||
/****************************************************************************
|
||||
* Decode Game Genie entries to memory patches
|
||||
@ -112,7 +112,7 @@ void decode_ggcodes ()
|
||||
j = 0;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
if (strcmp (ggcodes[i], "AAAA-AAAA"))
|
||||
if (strcmp ((char *)ggcodes[i], "AAAA-AAAA"))
|
||||
{
|
||||
/*** Move the code into thiscode ***/
|
||||
memcpy (&thiscode, &ggcodes[i], 4);
|
||||
@ -128,19 +128,12 @@ void decode_ggcodes ()
|
||||
{
|
||||
for (i = 0; i < j; i++)
|
||||
{
|
||||
if (ggpatch[i].address < rominfo.romend)
|
||||
if (ggpatch[i].address < 0x400000)
|
||||
{
|
||||
/*** Patching ROM space ***/
|
||||
cart_rom[ggpatch[i].address] = ggpatch[i].data & 0x0ff;
|
||||
cart_rom[ggpatch[i].address + 1] = (ggpatch[i].data & 0xff00) >> 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*** Patching 68K memory ***/
|
||||
m68k_write_memory_16 (ggpatch[i].address, ggpatch[i].data);
|
||||
/*** Patching ROM space ONLY (Game Genie does NOT have access to other memory areas) ***/
|
||||
if (cart_rom) *(uint16 *)(cart_rom + ggpatch[i].address) = ggpatch[i].data & 0xffff;
|
||||
}
|
||||
}
|
||||
/* TODO : Fix Checksum */
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,7 +148,7 @@ void ClearGGCodes ()
|
||||
|
||||
for (i = 0; i < MAXCODES; i++)
|
||||
{
|
||||
strcpy (ggcodes[i], "AAAA-AAAA");
|
||||
strcpy ((char *)ggcodes[i], "AAAA-AAAA");
|
||||
gghpos[i] = 0;
|
||||
}
|
||||
ggrow = 0;
|
||||
@ -179,14 +172,14 @@ void DrawGGCodes ()
|
||||
if (i == ggrow)
|
||||
{
|
||||
/*** Highlight selected ***/
|
||||
WriteCentre_HL (i * fheight + 224, ggcodes[i]);
|
||||
WriteCentre_HL (i * fheight + 224, (char *)ggcodes[i]);
|
||||
|
||||
/*** If editing, highlight the current character ***/
|
||||
if (editing)
|
||||
{
|
||||
int hpos = 0;
|
||||
|
||||
for (j=0; j<strlen (ggcodes[i]); j++) hpos += font_size[ggcodes[i][j]];
|
||||
for (j=0; j<strlen ((char *)ggcodes[i]); j++) hpos += font_size[ggcodes[i][j]];
|
||||
hpos = ((640 - hpos) >> 1);
|
||||
for (j=0; j<gghpos[i]; j++) hpos += font_size[ggcodes[i][j]];
|
||||
|
||||
@ -194,11 +187,11 @@ void DrawGGCodes ()
|
||||
fntDrawBoxFilled (hpos, (i * fheight) + 224, hpos + font_size[c[0]],
|
||||
((i + 1) * fheight) + 224, COLOR_YELLOW);
|
||||
setfontcolour (COLOR_BLUE);
|
||||
write_font (hpos, (i * fheight) + 224, c);
|
||||
write_font (hpos, (i * fheight) + 224, (char *)c);
|
||||
setfontcolour (COLOR_WHITE);
|
||||
}
|
||||
}
|
||||
else WriteCentre ((i * fheight) + 224, ggcodes[i]);
|
||||
else WriteCentre ((i * fheight) + 224, (char *)ggcodes[i]);
|
||||
}
|
||||
SetScreen ();
|
||||
}
|
||||
@ -216,14 +209,11 @@ void GGEditLine ()
|
||||
char c[2] = { 0, 0 };
|
||||
char *v;
|
||||
int redraw = 1;
|
||||
signed char x, y;
|
||||
|
||||
/** Lose any previous A press **/
|
||||
while (PAD_ButtonsDown (0) & PAD_BUTTON_A);
|
||||
int quit = 0;
|
||||
|
||||
editing = 1;
|
||||
|
||||
while (!(PAD_ButtonsDown (0) & PAD_BUTTON_A))
|
||||
while (quit == 0)
|
||||
{
|
||||
if (redraw)
|
||||
{
|
||||
@ -231,11 +221,9 @@ void GGEditLine ()
|
||||
redraw = 0;
|
||||
}
|
||||
|
||||
p = PAD_ButtonsDown (0);
|
||||
x = PAD_StickX (0);
|
||||
y = PAD_StickY (0);
|
||||
p = ogc_input__getMenuButtons();
|
||||
|
||||
if ((p & PAD_BUTTON_UP) || (y > 70))
|
||||
if (p & PAD_BUTTON_UP)
|
||||
{
|
||||
/*** Increment the entry ***/
|
||||
redraw = 1;
|
||||
@ -246,7 +234,7 @@ void GGEditLine ()
|
||||
else ggcodes[ggrow][gghpos[ggrow]] = *v;
|
||||
}
|
||||
|
||||
if ((p & PAD_BUTTON_DOWN) || (y < -70))
|
||||
if (p & PAD_BUTTON_DOWN)
|
||||
{
|
||||
/*** Decrement entry ***/
|
||||
redraw = 1;
|
||||
@ -260,14 +248,14 @@ void GGEditLine ()
|
||||
}
|
||||
}
|
||||
|
||||
if ((p & PAD_BUTTON_LEFT) || (x < -70))
|
||||
if (p & PAD_BUTTON_LEFT)
|
||||
{
|
||||
redraw = 1;
|
||||
gghpos[ggrow]--;
|
||||
if (gghpos[ggrow] == 4) gghpos[ggrow]--;
|
||||
}
|
||||
|
||||
if ((p & PAD_BUTTON_RIGHT) || (x > 70))
|
||||
if (p & PAD_BUTTON_RIGHT)
|
||||
{
|
||||
redraw = 1;
|
||||
gghpos[ggrow]++;
|
||||
@ -276,10 +264,9 @@ void GGEditLine ()
|
||||
|
||||
if (gghpos[ggrow] < 0) gghpos[ggrow] = 8;
|
||||
if (gghpos[ggrow] > 8) gghpos[ggrow] = 0;
|
||||
}
|
||||
|
||||
/** Lose any previous A press **/
|
||||
while (PAD_ButtonsDown (0) & PAD_BUTTON_A);
|
||||
if (p & PAD_BUTTON_A) quit = 1;
|
||||
}
|
||||
|
||||
editing = 0;
|
||||
}
|
||||
@ -294,13 +281,12 @@ void GGSelectLine ()
|
||||
int redraw = 1;
|
||||
int quit = 0;
|
||||
short j;
|
||||
signed char y;
|
||||
|
||||
/*** To select a line, just move up or down.
|
||||
Pressing A will enter edit mode.
|
||||
Pressing B will exit to caller. ***/
|
||||
|
||||
while (!(PAD_ButtonsDown (0) & PAD_BUTTON_B) && (quit == 0))
|
||||
while (quit == 0)
|
||||
{
|
||||
if (redraw)
|
||||
{
|
||||
@ -308,16 +294,15 @@ void GGSelectLine ()
|
||||
redraw = 0;
|
||||
}
|
||||
|
||||
j = PAD_ButtonsDown (0);
|
||||
y = PAD_StickY (0);
|
||||
j = ogc_input__getMenuButtons();
|
||||
|
||||
if ((j & PAD_BUTTON_UP) || (y > 70))
|
||||
if (j & PAD_BUTTON_UP)
|
||||
{
|
||||
ggrow--;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
if ((j & PAD_BUTTON_DOWN) || (y < -70))
|
||||
if (j & PAD_BUTTON_DOWN)
|
||||
{
|
||||
ggrow++;
|
||||
redraw = 1;
|
||||
@ -333,6 +318,14 @@ void GGSelectLine ()
|
||||
GGEditLine ();
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
if (j & PAD_TRIGGER_Z)
|
||||
{
|
||||
/* reset code */
|
||||
strcpy ((char *)ggcodes[ggrow], "AAAA-AAAA");
|
||||
gghpos[ggrow] = 0;
|
||||
redraw = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,4 +341,7 @@ void GetGGEntries ()
|
||||
editing = 0;
|
||||
strcpy (menutitle, "Game Genie Entry");
|
||||
GGSelectLine ();
|
||||
|
||||
/* Apply Game Genie patches */
|
||||
decode_ggcodes ();
|
||||
}
|
||||
|
@ -1,22 +1,4 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* DVD ISO9660/Joliet Parsing
|
||||
*
|
||||
* This is not intended as a complete guide to ISO9660.
|
||||
@ -197,7 +179,7 @@ static int getentry (int entrycount)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* parsedirectory
|
||||
* parseDVDdirectory
|
||||
*
|
||||
* This function will parse the directory tree.
|
||||
* It relies on rootdir and rootdirlength being pre-populated by a call to
|
||||
@ -205,7 +187,7 @@ static int getentry (int entrycount)
|
||||
*
|
||||
* The return value is number of files collected, or 0 on failure.
|
||||
****************************************************************************/
|
||||
int parsedirectory ()
|
||||
int parseDVDdirectory ()
|
||||
{
|
||||
int pdlength;
|
||||
u64 pdoffset;
|
||||
|
@ -1,27 +1,12 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* DVD ISO9660/Joliet Parsing
|
||||
*
|
||||
* This is not intended as a complete guide to ISO9660.
|
||||
* Here I use the bare minimum!
|
||||
***************************************************************************/
|
||||
#ifndef _ISO9660_H
|
||||
#define _ISO9660_H
|
||||
|
||||
#define MAXJOLIET 256
|
||||
#define MAXFILES 1000 /** Restrict to 1000 files per dir **/
|
||||
@ -40,5 +25,7 @@ extern u64 rootdir;
|
||||
extern int rootdirlength;
|
||||
|
||||
extern int getpvd ();
|
||||
extern int parsedirectory ();
|
||||
extern int parseDVDdirectory ();
|
||||
extern FILEENTRIES filelist[MAXFILES];
|
||||
|
||||
#endif
|
||||
|
@ -1,45 +0,0 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* DVD ISO9660/Joliet Parsing
|
||||
*
|
||||
* This is not intended as a complete guide to ISO9660.
|
||||
* Here I use the bare minimum!
|
||||
***************************************************************************/
|
||||
#include "vfat.h"
|
||||
#define MAXFILES 1000 /** Restrict to 1000 files per dir **/
|
||||
#define MAXJOLIET 256
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u64 offset;
|
||||
unsigned int length;
|
||||
char flags;
|
||||
char filename[13];
|
||||
char displayname[MAX_LONG_NAME];
|
||||
u16 filename_offset;
|
||||
} FILEENTRIES;
|
||||
|
||||
extern u64 basedir;
|
||||
extern u64 rootdir;
|
||||
extern int rootdirlength;
|
||||
|
||||
extern int getpvd ();
|
||||
extern int parsedirectory ();
|
||||
extern FILEENTRIES filelist[MAXFILES];
|
@ -1,44 +0,0 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* DVD ISO9660/Joliet Parsing
|
||||
*
|
||||
* This is not intended as a complete guide to ISO9660.
|
||||
* Here I use the bare minimum!
|
||||
***************************************************************************/
|
||||
|
||||
#define MAXJOLIET 256
|
||||
#define MAXFILES 1000 /** Restrict to 1000 files per dir **/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u64 offset;
|
||||
unsigned int length;
|
||||
char flags;
|
||||
char filename[MAXJOLIET];
|
||||
u16 filename_offset;
|
||||
} FILEENTRIES;
|
||||
|
||||
extern u64 basedir;
|
||||
extern u64 rootdir;
|
||||
extern int rootdirlength;
|
||||
|
||||
extern int getpvd ();
|
||||
extern int parsedirectory ();
|
||||
extern FILEENTRIES filelist[MAXFILES];
|
@ -22,9 +22,6 @@
|
||||
#include "font.h"
|
||||
#include "dkpro.h"
|
||||
|
||||
extern u32 *xfb[2];
|
||||
extern int whichfb;
|
||||
|
||||
/*
|
||||
* Unpack the devkit pro logo
|
||||
*/
|
||||
@ -37,7 +34,7 @@ int dkunpack ()
|
||||
inbytes = dkpro_COMPRESSED;
|
||||
outbytes = dkpro_RAW;
|
||||
dkproraw = malloc (dkpro_RAW + 16);
|
||||
res = uncompress ((char *) dkproraw, &outbytes, (char *) &dkpro[0], inbytes);
|
||||
res = uncompress ((Bytef *) dkproraw, &outbytes, (Bytef *) &dkpro[0], inbytes);
|
||||
if (res == Z_OK) return 1;
|
||||
free (dkproraw);
|
||||
return 0;
|
||||
@ -93,7 +90,10 @@ void legal ()
|
||||
free (dkproraw);
|
||||
}
|
||||
else WriteCentre (ypos, "Developed with DevkitPPC and libOGC");
|
||||
|
||||
#ifdef HW_RVL
|
||||
SetScreen ();
|
||||
sleep(1);
|
||||
#endif
|
||||
WriteCentre (ypos, "Press A to continue");
|
||||
SetScreen ();
|
||||
WaitButtonA ();
|
||||
|
@ -1,108 +1,102 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
/***************************************************************************
|
||||
* SDCARD/MEMCARD File support
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
#include "shared.h"
|
||||
#include "dvd.h"
|
||||
#include "font.h"
|
||||
#include "rominfo.h"
|
||||
#include "saveicon.h" /*** Nice little icon - thanks brakken! ***/
|
||||
|
||||
#include <fat.h>
|
||||
#include <sys/dir.h>
|
||||
|
||||
/* Support for MemCards */
|
||||
/**
|
||||
* libOGC System Work Area
|
||||
*/
|
||||
static u8 SysArea[CARD_WORKAREA] ATTRIBUTE_ALIGN (32);
|
||||
static card_dir CardDir;
|
||||
static card_file CardFile;
|
||||
static card_stat CardStatus;
|
||||
|
||||
/**
|
||||
* DMA Transfer Area.
|
||||
* Must be 32-byte aligned.
|
||||
* 64k SRAM + 2k Icon
|
||||
*/
|
||||
unsigned char savebuffer[0x24000] ATTRIBUTE_ALIGN (32);
|
||||
static u8 savebuffer[0x26000] ATTRIBUTE_ALIGN (32);
|
||||
|
||||
card_dir CardDir;
|
||||
card_file CardFile;
|
||||
card_stat CardStatus;
|
||||
extern int CARDSLOT;
|
||||
extern int use_SDCARD;
|
||||
|
||||
int ManageSRAM (int direction);
|
||||
int ManageState (int direction);
|
||||
int ManageSRAM (u8 direction, u8 device);
|
||||
int ManageState (u8 direction, u8 device);
|
||||
|
||||
/****************************************************************************
|
||||
* SRAM autoload
|
||||
* FILE autoload (SRAM/FreezeState or Config File)
|
||||
*
|
||||
* the detection order is the following:
|
||||
* MCARD (SLOTA) > MCARD (SLOTB) > SDCARD (SLOTA) > SDCARD (SLOTB)
|
||||
*
|
||||
*****************************************************************************/
|
||||
extern u8 SILENT;
|
||||
|
||||
void sram_autoload()
|
||||
void memfile_autoload()
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
int old_cardslot = CARDSLOT;
|
||||
int old_sdcard = use_SDCARD;
|
||||
/* this should be transparent to the user */
|
||||
SILENT = 1;
|
||||
|
||||
/* SRAM */
|
||||
if (config.sram_auto != -1)
|
||||
ManageSRAM(1,config.sram_auto);
|
||||
|
||||
/* STATE */
|
||||
if (config.freeze_auto != -1)
|
||||
ManageState(1,config.freeze_auto);
|
||||
|
||||
SILENT = 1; /* this should be transparent to the user */
|
||||
while ((i < 4) && (!ret))
|
||||
{
|
||||
use_SDCARD = (i&2) ? 1 : 0;
|
||||
CARDSLOT = (i&1) ? CARD_SLOTB : CARD_SLOTA;
|
||||
ret = ManageSRAM(1);
|
||||
i++;
|
||||
}
|
||||
if (!ret)
|
||||
{
|
||||
/* restore old settings if not found */
|
||||
CARDSLOT = old_cardslot;
|
||||
use_SDCARD = old_sdcard;
|
||||
}
|
||||
SILENT = 0;
|
||||
}
|
||||
|
||||
void memfile_autosave()
|
||||
{
|
||||
int crccheck = crc32 (0, sram.sram, 0x10000);
|
||||
|
||||
/* this should be transparent to the user */
|
||||
SILENT = 1;
|
||||
|
||||
/* SRAM */
|
||||
if ((config.sram_auto != -1) && (crccheck != sram.crc))
|
||||
ManageSRAM(0, config.sram_auto);
|
||||
|
||||
/* STATE */
|
||||
if (config.freeze_auto != -1)
|
||||
ManageState(0,config.freeze_auto);
|
||||
|
||||
SILENT = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* SDCARD Access functions
|
||||
*
|
||||
* We use the same buffer as for Memory Card manager
|
||||
* Function returns TRUE on success.
|
||||
*****************************************************************************/
|
||||
int SD_ManageFile(char *filename, int direction, int filetype)
|
||||
static int SD_ManageFile(char *filename, int direction, int filetype)
|
||||
{
|
||||
char name[1024];
|
||||
sd_file *handle;
|
||||
int len = 0;
|
||||
int offset = 0;
|
||||
char pathname[MAXPATHLEN];
|
||||
int done = 0;
|
||||
int filesize;
|
||||
unsigned long inbytes,outbytes;
|
||||
|
||||
/* first check if directory exist */
|
||||
DIR_ITER *dir = diropen("/genplus/saves");
|
||||
if (dir == NULL) mkdir("/genplus/saves",S_IRWXU);
|
||||
else dirclose(dir);
|
||||
|
||||
/* build complete SDCARD filename */
|
||||
sprintf (name, "dev%d:\\genplus\\saves\\%s", CARDSLOT, filename);
|
||||
sprintf (pathname, "/genplus/saves/%s", filename);
|
||||
|
||||
/* open file */
|
||||
handle = direction ? SDCARD_OpenFile (name, "rb") :
|
||||
SDCARD_OpenFile (name, "wb");
|
||||
|
||||
if (handle == NULL)
|
||||
FILE *fp = fopen(pathname, direction ? "rb" : "wb");
|
||||
if (fp == NULL)
|
||||
{
|
||||
sprintf (filename, "Error opening %s", name);
|
||||
sprintf (filename, "Error opening %s", pathname);
|
||||
WaitPrompt(filename);
|
||||
return 0;
|
||||
}
|
||||
@ -114,43 +108,56 @@ int SD_ManageFile(char *filename, int direction, int filetype)
|
||||
if (filetype) /* SRAM */
|
||||
{
|
||||
inbytes = 0x10000;
|
||||
outbytes = 0x12000;
|
||||
compress2 ((char *) &savebuffer[sizeof(outbytes)], &outbytes, (char *) &sram.sram, inbytes, 9);
|
||||
memcpy(&savebuffer[0], &outbytes, sizeof(outbytes));
|
||||
filesize = outbytes + sizeof(outbytes);
|
||||
outbytes = 0x24000;
|
||||
compress2 ((Bytef *)(savebuffer + 4), &outbytes, (Bytef *)(sram.sram), inbytes, 9);
|
||||
memcpy(savebuffer, &outbytes, 4);
|
||||
filesize = outbytes + 4;
|
||||
sram.crc = crc32 (0, sram.sram, 0x10000);
|
||||
}
|
||||
else filesize = state_save(&savebuffer[0]); /* STATE */
|
||||
else filesize = state_save(savebuffer); /* STATE */
|
||||
|
||||
len = SDCARD_WriteFile (handle, savebuffer, filesize);
|
||||
SDCARD_CloseFile (handle);
|
||||
|
||||
if (len != filesize)
|
||||
/* write buffer */
|
||||
done = fwrite(savebuffer, 1, filesize, fp);
|
||||
if (done < filesize)
|
||||
{
|
||||
sprintf (filename, "Error writing %s", name);
|
||||
WaitPrompt (filename);
|
||||
sprintf (filename, "Error writing %s", pathname);
|
||||
WaitPrompt(filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (filetype) sram.crc = crc32 (0, &sram.sram[0], 0x10000);
|
||||
sprintf (filename, "Saved %d bytes successfully", filesize);
|
||||
fclose(fp);
|
||||
sprintf (filename, "Saved %d bytes successfully", done);
|
||||
WaitPrompt (filename);
|
||||
return 1;
|
||||
|
||||
case 1: /* LOADING */
|
||||
|
||||
while ((len = SDCARD_ReadFile (handle, &savebuffer[offset], 2048)) > 0) offset += len;
|
||||
/* read size */
|
||||
fseek(fp , 0 , SEEK_END);
|
||||
filesize = ftell (fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
/* read into buffer (32k blocks) */
|
||||
done = fread(savebuffer, 1, filesize, fp);
|
||||
if (done < filesize)
|
||||
{
|
||||
sprintf (filename, "Error reading %s", pathname);
|
||||
WaitPrompt(filename);
|
||||
return 0;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
if (filetype) /* SRAM */
|
||||
{
|
||||
memcpy(&inbytes,&savebuffer[0],sizeof(inbytes));
|
||||
memcpy(&inbytes, savebuffer, 4);
|
||||
outbytes = 0x10000;
|
||||
uncompress ((char *) &sram.sram, &outbytes, (char *) &savebuffer[sizeof(inbytes)], inbytes);
|
||||
sram.crc = crc32 (0, &sram.sram[0], outbytes);
|
||||
uncompress ((Bytef *)(sram.sram), &outbytes, (Bytef *)(savebuffer + 4), inbytes);
|
||||
sram.crc = crc32 (0, sram.sram, 0x10000);
|
||||
system_reset ();
|
||||
}
|
||||
else state_load(&savebuffer[0]); /* STATE */
|
||||
SDCARD_CloseFile (handle);
|
||||
else state_load(savebuffer); /* STATE */
|
||||
|
||||
sprintf (filename, "Loaded %d bytes successfully", offset);
|
||||
sprintf (filename, "Loaded %d bytes successfully", done);
|
||||
WaitPrompt (filename);
|
||||
return 1;
|
||||
}
|
||||
@ -167,16 +174,18 @@ int SD_ManageFile(char *filename, int direction, int filetype)
|
||||
*
|
||||
* Function returns TRUE on success.
|
||||
*****************************************************************************/
|
||||
int MountTheCard ()
|
||||
int MountTheCard (u8 slot)
|
||||
{
|
||||
int tries = 0;
|
||||
int CardError;
|
||||
*(unsigned long *) (0xcc006800) |= 1 << 13; /*** Disable Encryption ***/
|
||||
#ifndef HW_RVL
|
||||
uselessinquiry ();
|
||||
#endif
|
||||
while (tries < 10)
|
||||
{
|
||||
*(unsigned long *) (0xcc006800) |= 1 << 13; /*** Disable Encryption ***/
|
||||
uselessinquiry ();
|
||||
VIDEO_WaitVSync ();
|
||||
CardError = CARD_Mount (CARDSLOT, SysArea, NULL); /*** Don't need or want a callback ***/
|
||||
CardError = CARD_Mount (slot, SysArea, NULL); /*** Don't need or want a callback ***/
|
||||
if (CardError == 0) return 1;
|
||||
else EXI_ProbeReset ();
|
||||
tries++;
|
||||
@ -190,9 +199,9 @@ int MountTheCard ()
|
||||
* Wrapper to search through the files on the card.
|
||||
* Returns TRUE if found.
|
||||
****************************************************************************/
|
||||
int CardFileExists (char *filename)
|
||||
int CardFileExists (char *filename, u8 slot)
|
||||
{
|
||||
int CardError = CARD_FindFirst (CARDSLOT, &CardDir, TRUE);
|
||||
int CardError = CARD_FindFirst (slot, &CardDir, TRUE);
|
||||
while (CardError != CARD_ERROR_NOFILE)
|
||||
{
|
||||
CardError = CARD_FindNext (&CardDir);
|
||||
@ -212,7 +221,7 @@ int CardFileExists (char *filename)
|
||||
*
|
||||
* direction == 0 save, 1 load.
|
||||
****************************************************************************/
|
||||
int ManageSRAM (int direction)
|
||||
int ManageSRAM (u8 direction, u8 device)
|
||||
{
|
||||
char filename[128];
|
||||
char action[80];
|
||||
@ -222,31 +231,25 @@ int ManageSRAM (int direction)
|
||||
char comment[2][32] = { {"Genesis Plus 1.2a"}, {"SRAM Save"} };
|
||||
int outbytes = 0;
|
||||
int sbo;
|
||||
int i;
|
||||
unsigned long inzipped,outzipped;
|
||||
|
||||
if (!genromsize) return 0;
|
||||
|
||||
/* clean buffer */
|
||||
memset(savebuffer, 0, 0x24000);
|
||||
|
||||
if (direction) ShowAction ("Loading SRAM ...");
|
||||
else ShowAction ("Saving SRAM ...");
|
||||
|
||||
/* First, build a filename based on the information retrieved for this ROM */
|
||||
if (strlen (rominfo.domestic)) strcpy (filename, rominfo.domestic);
|
||||
else strcpy (filename, rominfo.international);
|
||||
|
||||
/* As these names tend to be bulked with spaces, let's strip them */
|
||||
/* Name should be in 16 character blocks, so take first 16 */
|
||||
filename[16] = 0;
|
||||
for (i = strlen (filename) - 1; i > 0; i--)
|
||||
if (filename[i] != 32) break;
|
||||
filename[i + 1] = 0;
|
||||
|
||||
/* Now add the 16bit checksum, to ensure it's the same ROM */
|
||||
sprintf (filename, "%s%02X.srm", filename, rominfo.checksum);
|
||||
/* First, build a filename */
|
||||
sprintf (filename, "MD-%04X.srm", realchecksum);
|
||||
strcpy (comment[1], filename);
|
||||
|
||||
/* device is SDCARD, let's go */
|
||||
if (use_SDCARD) return SD_ManageFile(filename,direction,1);
|
||||
if (device == 0) return SD_ManageFile(filename,direction,1);
|
||||
|
||||
/* set MCARD slot nr. */
|
||||
u8 CARDSLOT = device - 1;
|
||||
|
||||
/* device is MCARD, we continue */
|
||||
if (direction == 0) /*** Saving ***/
|
||||
@ -257,7 +260,7 @@ int ManageSRAM (int direction)
|
||||
|
||||
inzipped = 0x10000;
|
||||
outzipped = 0x12000;
|
||||
compress2 ((char *) &savebuffer[2112+sizeof(outzipped)], &outzipped, (char *) &sram.sram, inzipped, 9);
|
||||
compress2 ((Bytef *) &savebuffer[2112+sizeof(outzipped)], &outzipped, (Bytef *) &sram.sram, inzipped, 9);
|
||||
memcpy(&savebuffer[2112], &outzipped, sizeof(outzipped));
|
||||
}
|
||||
|
||||
@ -268,7 +271,7 @@ int ManageSRAM (int direction)
|
||||
CARD_Init ("GENP", "00");
|
||||
|
||||
/*** Attempt to mount the card ***/
|
||||
CardError = MountTheCard ();
|
||||
CardError = MountTheCard (CARDSLOT);
|
||||
|
||||
if (CardError)
|
||||
{
|
||||
@ -283,7 +286,7 @@ int ManageSRAM (int direction)
|
||||
if (outbytes % SectorSize) blocks += SectorSize;
|
||||
|
||||
/*** Check if a previous save exists ***/
|
||||
if (CardFileExists (filename))
|
||||
if (CardFileExists (filename,CARDSLOT))
|
||||
{
|
||||
CardError = CARD_Open (CARDSLOT, filename, &CardFile);
|
||||
if (CardError)
|
||||
@ -351,7 +354,7 @@ int ManageSRAM (int direction)
|
||||
return 1;
|
||||
|
||||
default: /*** Loading ***/
|
||||
if (!CardFileExists (filename))
|
||||
if (!CardFileExists (filename,CARDSLOT))
|
||||
{
|
||||
WaitPrompt ("No SRAM File Found");
|
||||
CARD_Unmount (CARDSLOT);
|
||||
@ -387,7 +390,7 @@ int ManageSRAM (int direction)
|
||||
/* Copy to SRAM */
|
||||
memcpy(&inzipped,&savebuffer[2112],sizeof(inzipped));
|
||||
outzipped = 0x10000;
|
||||
uncompress ((char *) &sram.sram, &outzipped, (char *) &savebuffer[2112+sizeof(inzipped)], inzipped);
|
||||
uncompress ((Bytef *) &sram.sram, &outzipped, (Bytef *) &savebuffer[2112+sizeof(inzipped)], inzipped);
|
||||
sram.crc = crc32 (0, &sram.sram[0], 0x10000);
|
||||
system_reset ();
|
||||
|
||||
@ -402,14 +405,14 @@ int ManageSRAM (int direction)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* ManageSTATE
|
||||
* ManageState
|
||||
*
|
||||
* Here is the main Freeze File Management stuff.
|
||||
* The output file contains an icon (2K), 64 bytes comment and the STATE (~128k)
|
||||
*
|
||||
* direction == 0 save, 1 load.
|
||||
****************************************************************************/
|
||||
int ManageState (int direction)
|
||||
int ManageState (u8 direction, u8 device)
|
||||
{
|
||||
char filename[128];
|
||||
char action[80];
|
||||
@ -417,32 +420,27 @@ int ManageState (int direction)
|
||||
unsigned int SectorSize;
|
||||
int blocks;
|
||||
char comment[2][32] = { {"Genesis Plus 1.2a [FRZ]"}, {"Freeze State"} };
|
||||
int outbytes;
|
||||
int outbytes = 0;
|
||||
int sbo;
|
||||
int i;
|
||||
int state_size = 0;
|
||||
|
||||
if (!genromsize) return 0;
|
||||
|
||||
/* clean buffer */
|
||||
memset(savebuffer, 0, 0x24000);
|
||||
|
||||
if (direction) ShowAction ("Loading State ...");
|
||||
else ShowAction ("Saving State ...");
|
||||
|
||||
/* First, build a filename based on the information retrieved for this ROM */
|
||||
if (strlen (rominfo.domestic)) strcpy (filename, rominfo.domestic);
|
||||
else strcpy (filename, rominfo.international);
|
||||
|
||||
/* As these names tend to be bulked with spaces, let's strip them */
|
||||
/* Name should be in 16 character blocks, so take first 16 */
|
||||
filename[16] = 0;
|
||||
for (i = strlen (filename) - 1; i > 0; i--) if (filename[i] != 32) break;
|
||||
filename[i + 1] = 0;
|
||||
|
||||
/* Now add the 16bit checksum, to ensure it's the same ROM */
|
||||
sprintf (filename, "%s%02X.gpz", filename, rominfo.checksum);
|
||||
/* First, build a filename */
|
||||
sprintf (filename, "MD-%04X.gpz", realchecksum);
|
||||
strcpy (comment[1], filename);
|
||||
|
||||
/* device is SDCARD, let's go */
|
||||
if (use_SDCARD) return SD_ManageFile(filename,direction,0);
|
||||
if (device == 0) return SD_ManageFile(filename,direction,0);
|
||||
|
||||
/* set MCARD slot nr. */
|
||||
u8 CARDSLOT = device - 1;
|
||||
|
||||
/* device is MCARD, we continue */
|
||||
if (direction == 0) /* Saving */
|
||||
@ -460,7 +458,7 @@ int ManageState (int direction)
|
||||
CARD_Init ("GENP", "00");
|
||||
|
||||
/*** Attempt to mount the card ***/
|
||||
CardError = MountTheCard ();
|
||||
CardError = MountTheCard (CARDSLOT);
|
||||
|
||||
if (CardError)
|
||||
{
|
||||
@ -475,7 +473,7 @@ int ManageState (int direction)
|
||||
if (outbytes % SectorSize) blocks += SectorSize;
|
||||
|
||||
/*** Check if a previous save exists ***/
|
||||
if (CardFileExists (filename))
|
||||
if (CardFileExists (filename, CARDSLOT))
|
||||
{
|
||||
CardError = CARD_Open (CARDSLOT, filename, &CardFile);
|
||||
if (CardError)
|
||||
@ -542,7 +540,7 @@ int ManageState (int direction)
|
||||
return 1;
|
||||
|
||||
default: /*** Loading ***/
|
||||
if (!CardFileExists (filename))
|
||||
if (!CardFileExists (filename, CARDSLOT))
|
||||
{
|
||||
WaitPrompt ("No Savestate Found");
|
||||
CARD_Unmount (CARDSLOT);
|
||||
@ -575,6 +573,7 @@ int ManageState (int direction)
|
||||
CARD_Close (&CardFile);
|
||||
CARD_Unmount (CARDSLOT);
|
||||
|
||||
/*** Load State ***/
|
||||
state_load(&savebuffer[2112]);
|
||||
|
||||
/*** Inform user ***/
|
File diff suppressed because it is too large
Load Diff
101
source/ngc/history.c
Normal file
101
source/ngc/history.c
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* history.c
|
||||
* genplusgx-mdisibio
|
||||
*
|
||||
* Created by Martin Disibio on 6/17/08.
|
||||
* Copyright 2008 __MyCompanyName__. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shared.h"
|
||||
#include "font.h"
|
||||
#include "history.h"
|
||||
|
||||
t_history history;
|
||||
|
||||
void history_save()
|
||||
{
|
||||
/* first check if directory exist */
|
||||
DIR_ITER *dir = diropen("/genplus");
|
||||
if (dir == NULL) mkdir("/genplus",S_IRWXU);
|
||||
else dirclose(dir);
|
||||
|
||||
/* open file for writing */
|
||||
FILE *fp = fopen("/genplus/romhistory.ini", "wb");
|
||||
if (fp == NULL) return;
|
||||
|
||||
/* save options */
|
||||
fwrite(&history, sizeof(history), 1, fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* history_add_file
|
||||
*
|
||||
* Adds the given file path to the top of the history list, shifting each
|
||||
* existing entry in the history down one place. If given file path is
|
||||
* already in the list then the existing entry is (in effect) moved to the
|
||||
* top instead.
|
||||
****************************************************************************/
|
||||
void history_add_file(char *filepath, char *filename)
|
||||
{
|
||||
/* Create the new entry for this path. */
|
||||
t_history_entry newentry;
|
||||
strncpy(newentry.filepath, filepath, MAXJOLIET - 1);
|
||||
strncpy(newentry.filename, filename, MAXJOLIET - 1);
|
||||
newentry.filepath[MAXJOLIET - 1] = '\0';
|
||||
newentry.filename[MAXJOLIET - 1] = '\0';
|
||||
|
||||
t_history_entry oldentry; /* Old entry is the one being shuffled down a spot. */
|
||||
t_history_entry currentry; /* Curr entry is the one that just replaced old path. */
|
||||
|
||||
/* Initially set curr entry to the new value. */
|
||||
memcpy(¤try, &newentry, sizeof(t_history_entry));
|
||||
|
||||
int i;
|
||||
for(i=0; i < NUM_HISTORY_ENTRIES; i++)
|
||||
{
|
||||
/* Save off the next entry. */
|
||||
memcpy(&oldentry, &history.entries[i], sizeof(t_history_entry));
|
||||
|
||||
/* Overwrite with the previous entry. */
|
||||
memcpy(&history.entries[i], ¤try, sizeof(t_history_entry));
|
||||
|
||||
/* Switch the old entry to the curr entry now. */
|
||||
memcpy(¤try, &oldentry, sizeof(t_history_entry));
|
||||
|
||||
/* If the entry in the list at this spot matches
|
||||
the new entry then do nothing and let this
|
||||
entry get deleted. */
|
||||
if(strcmp(newentry.filepath, currentry.filepath) == 0 && strcmp(newentry.filename, currentry.filename) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* now save to disk */
|
||||
history_save();
|
||||
}
|
||||
|
||||
void history_load()
|
||||
{
|
||||
/* open file for reading */
|
||||
FILE *fp = fopen("/genplus/romhistory.ini", "rb");
|
||||
if (fp == NULL) return;
|
||||
|
||||
/* read file */
|
||||
fread(&history, sizeof(history), 1, fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void set_history_defaults(void)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i < NUM_HISTORY_ENTRIES; i++)
|
||||
{
|
||||
memset(&history.entries[i], 0, sizeof(t_history_entry));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
40
source/ngc/history.h
Normal file
40
source/ngc/history.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* history.h
|
||||
* genplusgx-mdisibio
|
||||
*
|
||||
* Created by Martin Disibio on 6/17/08.
|
||||
*
|
||||
*/
|
||||
#ifndef _HISTORY_H
|
||||
#define _HISTORY_H
|
||||
|
||||
#include "types.h"
|
||||
#include "iso9660.h"
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* ROM Play History
|
||||
*
|
||||
****************************************************************************/
|
||||
#define NUM_HISTORY_ENTRIES (10)
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char filepath[MAXJOLIET];
|
||||
char filename[MAXJOLIET];
|
||||
} t_history_entry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
t_history_entry entries[NUM_HISTORY_ENTRIES];
|
||||
} t_history;
|
||||
|
||||
extern t_history history;
|
||||
extern void history_add_file(char *filepath, char *filename);
|
||||
extern void history_load();
|
||||
extern void set_history_defaults();
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,196 +0,0 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#include "rominfo.h"
|
||||
#include <ctype.h>
|
||||
|
||||
/* 05/05/2006: new region detection routine (taken from GENS sourcecode) */
|
||||
extern uint8 region_detect;
|
||||
extern uint8 cpu_detect;
|
||||
|
||||
void genesis_set_region ()
|
||||
{
|
||||
/* country codes used to differentiate region */
|
||||
/* 0001 = japan ntsc (1) */
|
||||
/* 0010 = japan pal (2) */
|
||||
/* 0100 = usa (4) */
|
||||
/* 1000 = europe (8) */
|
||||
|
||||
int country = 0;
|
||||
int i = 0;
|
||||
char c;
|
||||
|
||||
/* reading header to find the country */
|
||||
if (!strnicmp(rominfo.country, "eur", 3)) country |= 8;
|
||||
else if (!strnicmp(rominfo.country, "usa", 3)) country |= 4;
|
||||
else if (!strnicmp(rominfo.country, "jap", 3)) country |= 1;
|
||||
|
||||
else for(i = 0; i < 4; i++)
|
||||
{
|
||||
c = toupper((int)rominfo.country[i]);
|
||||
if (c == 'U') country |= 4;
|
||||
else if (c == 'J') country |= 1;
|
||||
else if (c == 'E') country |= 8;
|
||||
else if (c < 16) country |= c;
|
||||
else if ((c >= '0') && (c <= '9')) country |= c - '0';
|
||||
else if ((c >= 'A') && (c <= 'F')) country |= c - 'A' + 10;
|
||||
}
|
||||
|
||||
/* automatic detection */
|
||||
/* setting region */
|
||||
/* this is used by IO register */
|
||||
if (country & 4) region_code = REGION_USA;
|
||||
else if (country & 8) region_code = REGION_EUROPE;
|
||||
else if (country & 1) region_code = REGION_JAPAN_NTSC;
|
||||
else if (country & 2) region_code = REGION_JAPAN_PAL;
|
||||
else region_code = REGION_USA;
|
||||
|
||||
/* cpu mode: PAL or NTSC */
|
||||
if ((region_code == REGION_EUROPE) || (region_code == REGION_JAPAN_PAL)) vdp_pal = 1;
|
||||
else vdp_pal = 0;
|
||||
|
||||
/* Force region setting */
|
||||
if (region_detect == 1) region_code = REGION_USA;
|
||||
else if (region_detect == 2) region_code = REGION_EUROPE;
|
||||
else if (region_detect == 3) region_code = REGION_JAPAN_NTSC;
|
||||
else if (region_detect == 4) region_code = REGION_JAPAN_PAL;
|
||||
|
||||
/* Force CPU mode */
|
||||
if (cpu_detect == 1) vdp_pal = 0;
|
||||
else if (cpu_detect == 2) vdp_pal = 1;
|
||||
}
|
||||
|
||||
|
||||
/* patch_game
|
||||
* set specific timings for some games
|
||||
*/
|
||||
extern uint8 alttiming;
|
||||
extern uint8 vdptiming;
|
||||
extern uint8 sys_type[2];
|
||||
|
||||
void detect_game()
|
||||
{
|
||||
/* Lotus 2 RECS */
|
||||
if (strstr(rominfo.product,"T-50746") != NULL) alttiming = 1;
|
||||
else alttiming = 0;
|
||||
|
||||
/* Chaos Engine / Soldier of Fortune */
|
||||
if ((strstr(rominfo.product,"T-104066") != NULL) ||
|
||||
(strstr(rominfo.product,"T-124016") != NULL)) vdptiming = 1;
|
||||
else vdptiming = 0;
|
||||
|
||||
/* Menacer 6-in-1 Pack */
|
||||
if (strstr(rominfo.product,"MK-1658") != NULL)
|
||||
{
|
||||
input.system[0] = NO_SYSTEM;
|
||||
input.system[1] = SYSTEM_MENACER;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sys_type[0] == 0) input.system[0] = SYSTEM_GAMEPAD;
|
||||
else if (sys_type[0] == 1) input.system[0] = SYSTEM_TEAMPLAYER;
|
||||
else if (sys_type[0] == 2) input.system[0] = NO_SYSTEM;
|
||||
|
||||
if (sys_type[1] == 0) input.system[1] = SYSTEM_GAMEPAD;
|
||||
else if (sys_type[1] == 1) input.system[1] = SYSTEM_TEAMPLAYER;
|
||||
else if (sys_type[1] == 2) input.system[1] = NO_SYSTEM;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* SMD -interleaved) rom support */
|
||||
static uint8 block[0x4000];
|
||||
|
||||
void deinterleave_block (uint8 * src)
|
||||
{
|
||||
int i;
|
||||
memcpy (block, src, 0x4000);
|
||||
for (i = 0; i < 0x2000; i += 1)
|
||||
{
|
||||
src[i * 2 + 0] = block[0x2000 + (i)];
|
||||
src[i * 2 + 1] = block[0x0000 + (i)];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* load_memrom
|
||||
* softdev 12 March 2006
|
||||
* Changed from using ROM buffer to a single copy in cart_rom
|
||||
*
|
||||
* Saving ROM size in bytes :)
|
||||
* Required for remote loading.
|
||||
*
|
||||
* WIP3 - Removed 5Mb SSF2TNC from main memory to Audio ROM
|
||||
*/
|
||||
void load_memrom (int size)
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
SSF2TNC = 0;
|
||||
|
||||
/* Support for interleaved roms */
|
||||
if ((size / 512) & 1)
|
||||
{
|
||||
int i;
|
||||
size -= 512;
|
||||
offset += 512;
|
||||
|
||||
for (i = 0; i < (size / 0x4000); i += 1)
|
||||
{
|
||||
deinterleave_block (cart_rom + offset + (i * 0x4000));
|
||||
}
|
||||
}
|
||||
|
||||
if (size > 0x500000) size = 0x500000;
|
||||
if (offset) memcpy (cart_rom, cart_rom + offset, size);
|
||||
if (size > 0x400000) SSF2TNC = 1; /*** Assume SSF2TNC (mapped ROM) ***/
|
||||
|
||||
genromsize = size;
|
||||
|
||||
/*** Clear out space ***/
|
||||
if (size < 0x500000) memset (cart_rom + size, 0, 0x500000 - size);
|
||||
return;
|
||||
}
|
||||
|
||||
/*** Reloadrom
|
||||
performs some initialization before running the new rom
|
||||
***/
|
||||
extern void decode_ggcodes ();
|
||||
extern void ClearGGCodes ();
|
||||
extern void sram_autoload();
|
||||
extern uint8 autoload;
|
||||
|
||||
void reloadrom ()
|
||||
{
|
||||
load_memrom (genromsize);
|
||||
getrominfo (cart_rom); /* Other Infos from ROM Header */
|
||||
genesis_set_region (); /* Region Detection */
|
||||
detect_game(); /* game special patches */
|
||||
SRAM_Init (); /* SRAM Infos from ROM header */
|
||||
|
||||
system_init ();
|
||||
audio_init(48000);
|
||||
ClearGGCodes (); /* Game Genie */
|
||||
decode_ggcodes ();
|
||||
|
||||
system_reset ();
|
||||
if (autoload) sram_autoload();
|
||||
}
|
670
source/ngc/ngc.c
670
source/ngc/ngc.c
@ -21,619 +21,217 @@
|
||||
#include "gcaram.h"
|
||||
#include "dvd.h"
|
||||
#include "font.h"
|
||||
#include "history.h"
|
||||
|
||||
#define ROMOFFSET 0x80600000
|
||||
|
||||
unsigned char *gen_bmp; /*** Work bitmap ***/
|
||||
int frameticker = 0;
|
||||
int ConfigRequested = 0;
|
||||
int padcal = 70;
|
||||
int RenderedFrameCount = 0;
|
||||
int FrameCount = 0;
|
||||
int FramesPerSecond = 0;
|
||||
u8 isWII = 0;
|
||||
#ifdef WII_DVD
|
||||
#include "wdvd.h"
|
||||
#endif
|
||||
|
||||
/***************************************************************************
|
||||
* Nintendo Gamecube Hardware Specific Functions
|
||||
*
|
||||
* T I M E R
|
||||
***************************************************************************/
|
||||
#define TB_CLOCK 40500000
|
||||
#define mftb(rval) ({unsigned long u; do { \
|
||||
asm volatile ("mftbu %0" : "=r" (u)); \
|
||||
asm volatile ("mftb %0" : "=r" ((rval)->l)); \
|
||||
asm volatile ("mftbu %0" : "=r" ((rval)->u)); \
|
||||
} while(u != ((rval)->u)); })
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned long l, u;
|
||||
} tb_t;
|
||||
|
||||
unsigned long tb_diff_msec(tb_t *end, tb_t *start)
|
||||
{
|
||||
unsigned long upper, lower;
|
||||
upper = end->u - start->u;
|
||||
if (start->l > end->l) upper--;
|
||||
lower = end->l - start->l;
|
||||
return ((upper*((unsigned long)0x80000000/(TB_CLOCK/2000))) + (lower/(TB_CLOCK/1000)));
|
||||
}
|
||||
|
||||
int msBetweenFrames = 20;
|
||||
tb_t now, prev;
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Nintendo Gamecube Hardware Specific Functions
|
||||
*
|
||||
* V I D E O
|
||||
***************************************************************************/
|
||||
/*** 2D Video ***/
|
||||
unsigned int *xfb[2]; /*** Double buffered ***/
|
||||
int whichfb = 0; /*** Switch ***/
|
||||
GXRModeObj *vmode; /*** General video mode ***/
|
||||
|
||||
/*** GX ***/
|
||||
#define TEX_WIDTH 320
|
||||
#define TEX_HEIGHT 256
|
||||
#define DEFAULT_FIFO_SIZE 256 * 1024
|
||||
|
||||
static u8 gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN (32);
|
||||
static u8 texturemem[TEX_WIDTH * (TEX_HEIGHT + 8) * 2] ATTRIBUTE_ALIGN (32);
|
||||
GXTexObj texobj;
|
||||
static Mtx view;
|
||||
int vwidth, vheight, oldvwidth, oldvheight;
|
||||
|
||||
/* New texture based scaler */
|
||||
#define HASPECT 76
|
||||
#define VASPECT 54
|
||||
|
||||
typedef struct tagcamera
|
||||
{
|
||||
Vector pos;
|
||||
Vector up;
|
||||
Vector view;
|
||||
} camera;
|
||||
|
||||
/*** Square Matrix
|
||||
This structure controls the size of the image on the screen.
|
||||
Think of the output as a -80 x 80 by -60 x 60 graph.
|
||||
***/
|
||||
s16 square[] ATTRIBUTE_ALIGN (32) =
|
||||
{
|
||||
/*
|
||||
* X, Y, Z
|
||||
* Values set are for roughly 4:3 aspect
|
||||
*/
|
||||
-HASPECT, VASPECT, 0, // 0
|
||||
HASPECT, VASPECT, 0, // 1
|
||||
HASPECT, -VASPECT, 0, // 2
|
||||
-HASPECT, -VASPECT, 0, // 3
|
||||
};
|
||||
|
||||
static camera cam = { {0.0F, 0.0F, 0.0F},
|
||||
{0.0F, 0.5F, 0.0F},
|
||||
{0.0F, 0.0F, -0.5F}
|
||||
};
|
||||
|
||||
/*** Framestart function
|
||||
Simply increment the tick counter
|
||||
***/
|
||||
static void framestart()
|
||||
{
|
||||
frameticker++;
|
||||
}
|
||||
|
||||
/*** WIP3 - Scaler Support Functions
|
||||
***/
|
||||
static void draw_init (void)
|
||||
{
|
||||
GX_ClearVtxDesc ();
|
||||
GX_SetVtxDesc (GX_VA_POS, GX_INDEX8);
|
||||
GX_SetVtxDesc (GX_VA_CLR0, GX_INDEX8);
|
||||
GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT);
|
||||
GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
|
||||
GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
|
||||
GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
||||
GX_SetArray (GX_VA_POS, square, 3 * sizeof (s16));
|
||||
GX_SetNumTexGens (1);
|
||||
GX_SetTexCoordGen (GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
|
||||
GX_InvalidateTexAll ();
|
||||
GX_InitTexObj (&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||||
}
|
||||
|
||||
static void draw_vert (u8 pos, u8 c, f32 s, f32 t)
|
||||
{
|
||||
GX_Position1x8 (pos);
|
||||
GX_Color1x8 (c);
|
||||
GX_TexCoord2f32 (s, t);
|
||||
}
|
||||
|
||||
static void draw_square (Mtx v)
|
||||
{
|
||||
Mtx m; // model matrix.
|
||||
Mtx mv; // modelview matrix.
|
||||
|
||||
guMtxIdentity (m);
|
||||
guMtxTransApply (m, m, 0, 0, -100);
|
||||
guMtxConcat (v, m, mv);
|
||||
GX_LoadPosMtxImm (mv, GX_PNMTX0);
|
||||
GX_Begin (GX_QUADS, GX_VTXFMT0, 4);
|
||||
draw_vert (0, 0, 0.0, 0.0);
|
||||
draw_vert (1, 0, 1.0, 0.0);
|
||||
draw_vert (2, 0, 1.0, 1.0);
|
||||
draw_vert (3, 0, 0.0, 1.0);
|
||||
GX_End ();
|
||||
}
|
||||
|
||||
/*** StartGX
|
||||
This function initialises the GX.
|
||||
WIP3 - Based on texturetest from libOGC examples.
|
||||
***/
|
||||
static void StartGX (void)
|
||||
{
|
||||
Mtx p;
|
||||
GXColor gxbackground = { 0, 0, 0, 0xff };
|
||||
|
||||
/*** Clear out FIFO area ***/
|
||||
memset (&gp_fifo, 0, DEFAULT_FIFO_SIZE);
|
||||
|
||||
/*** Initialise GX ***/
|
||||
GX_Init (&gp_fifo, DEFAULT_FIFO_SIZE);
|
||||
GX_SetCopyClear (gxbackground, 0x00ffffff);
|
||||
GX_SetViewport (0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1);
|
||||
GX_SetDispCopyYScale ((f32) vmode->xfbHeight / (f32) vmode->efbHeight);
|
||||
GX_SetScissor (0, 0, vmode->fbWidth, vmode->efbHeight);
|
||||
GX_SetDispCopySrc (0, 0, vmode->fbWidth, vmode->efbHeight);
|
||||
GX_SetDispCopyDst (vmode->fbWidth, vmode->xfbHeight);
|
||||
GX_SetCopyFilter (vmode->aa, vmode->sample_pattern, GX_TRUE, vmode->vfilter);
|
||||
GX_SetFieldMode (vmode->field_rendering, ((vmode->viHeight == 2 * vmode->xfbHeight) ? GX_ENABLE : GX_DISABLE));
|
||||
GX_SetPixelFmt (GX_PF_RGB8_Z24, GX_ZC_LINEAR);
|
||||
GX_SetCullMode (GX_CULL_NONE);
|
||||
GX_CopyDisp (xfb[whichfb ^ 1], GX_TRUE);
|
||||
GX_SetDispCopyGamma (GX_GM_1_0);
|
||||
guPerspective (p, 60, 1.33F, 10.0F, 1000.0F);
|
||||
GX_LoadProjectionMtx (p, GX_PERSPECTIVE);
|
||||
memset (texturemem, 0, TEX_WIDTH * TEX_HEIGHT * 2);
|
||||
vwidth = 100;
|
||||
vheight = 100;
|
||||
}
|
||||
|
||||
/*** InitGCVideo
|
||||
This function MUST be called at startup.
|
||||
***/
|
||||
static void InitGCVideo ()
|
||||
{
|
||||
int *romptr = (int *)ROMOFFSET;
|
||||
|
||||
/*
|
||||
* Before doing anything else under libogc,
|
||||
* Call VIDEO_Init
|
||||
*/
|
||||
VIDEO_Init ();
|
||||
|
||||
/*
|
||||
* Before any memory is allocated etc.
|
||||
* Rescue any tagged ROM in data 2
|
||||
*/
|
||||
StartARAM();
|
||||
if ( memcmp((char *)romptr,"GENPLUSR",8) == 0 )
|
||||
{
|
||||
genromsize = romptr[2];
|
||||
ARAMPut ((char *) 0x80600020, (char *) 0x8000, genromsize);
|
||||
}
|
||||
else genromsize = 0;
|
||||
|
||||
/* Init Gamepads */
|
||||
PAD_Init ();
|
||||
|
||||
/*
|
||||
* Reset the video mode
|
||||
* This is always set to 60hz
|
||||
* Whether your running PAL or NTSC
|
||||
*/
|
||||
vmode = &TVNtsc480IntDf;
|
||||
VIDEO_Configure (vmode);
|
||||
|
||||
/*** Now configure the framebuffer.
|
||||
Really a framebuffer is just a chunk of memory
|
||||
to hold the display line by line.
|
||||
**/
|
||||
xfb[0] = (u32 *) MEM_K0_TO_K1((u32 *) SYS_AllocateFramebuffer(vmode));
|
||||
|
||||
/*** I prefer also to have a second buffer for double-buffering.
|
||||
This is not needed for the console demo.
|
||||
***/
|
||||
xfb[1] = (u32 *) MEM_K0_TO_K1((u32 *) SYS_AllocateFramebuffer(vmode));
|
||||
|
||||
/*** Define a console ***/
|
||||
console_init(xfb[0], 20, 64, vmode->fbWidth, vmode->xfbHeight, vmode->fbWidth * 2);
|
||||
|
||||
/*** Clear framebuffer to black ***/
|
||||
VIDEO_ClearFrameBuffer(vmode, xfb[0], COLOR_BLACK);
|
||||
VIDEO_ClearFrameBuffer(vmode, xfb[1], COLOR_BLACK);
|
||||
|
||||
/*** Set the framebuffer to be displayed at next VBlank ***/
|
||||
VIDEO_SetNextFramebuffer(xfb[0]);
|
||||
|
||||
/*** Increment frameticker and timer ***/
|
||||
VIDEO_SetPreRetraceCallback(framestart);
|
||||
|
||||
/*** Get the PAD status updated by libogc ***/
|
||||
VIDEO_SetPostRetraceCallback(PAD_ScanPads);
|
||||
VIDEO_SetBlack (FALSE);
|
||||
|
||||
/*** Update the video for next vblank ***/
|
||||
VIDEO_Flush();
|
||||
|
||||
/*** Wait for VBL ***/
|
||||
VIDEO_WaitVSync();
|
||||
if (vmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||
|
||||
DVD_Init ();
|
||||
SDCARD_Init ();
|
||||
unpackBackdrop ();
|
||||
init_font();
|
||||
StartGX ();
|
||||
|
||||
/* Wii drive detection for 4.7Gb support */
|
||||
int driveid = dvd_inquiry();
|
||||
if ((driveid == 4) || (driveid == 6) || (driveid == 8)) isWII = 0;
|
||||
else isWII = 1;
|
||||
}
|
||||
|
||||
/*** Video Update
|
||||
called after each emulation frame
|
||||
***/
|
||||
static void update_video ()
|
||||
{
|
||||
int h, w;
|
||||
vwidth = (reg[12] & 1) ? 320 : 256;
|
||||
vheight = (reg[1] & 8) ? 240 : 224;
|
||||
|
||||
long long int *dst = (long long int *)texturemem;
|
||||
long long int *src1 = (long long int *)(bitmap.data + 64);
|
||||
long long int *src2 = src1 + 256;
|
||||
long long int *src3 = src2 + 256;
|
||||
long long int *src4 = src3 + 256;
|
||||
long long int stride = 1024 - ( vwidth >> 2 );
|
||||
|
||||
whichfb ^= 1;
|
||||
|
||||
if ((oldvheight != vheight) || (oldvwidth != vwidth))
|
||||
{
|
||||
/** Update scaling **/
|
||||
oldvwidth = vwidth;
|
||||
oldvheight = vheight;
|
||||
draw_init ();
|
||||
memset (&view, 0, sizeof (Mtx));
|
||||
guLookAt(view, &cam.pos, &cam.up, &cam.view);
|
||||
GX_SetViewport (0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1);
|
||||
}
|
||||
|
||||
GX_InvVtxCache ();
|
||||
GX_InvalidateTexAll ();
|
||||
GX_SetTevOp (GX_TEVSTAGE0, GX_DECAL);
|
||||
GX_SetTevOrder (GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
|
||||
|
||||
for (h = 0; h < vheight; h += 4)
|
||||
{
|
||||
for (w = 0; w < (vwidth >> 2); w++ )
|
||||
{
|
||||
*dst++ = *src1++;
|
||||
*dst++ = *src2++;
|
||||
*dst++ = *src3++;
|
||||
*dst++ = *src4++;
|
||||
}
|
||||
|
||||
src1 += stride;
|
||||
src2 += stride;
|
||||
src3 += stride;
|
||||
src4 += stride;
|
||||
}
|
||||
|
||||
DCFlushRange (texturemem, TEX_WIDTH * TEX_HEIGHT * 2);
|
||||
GX_SetNumChans (1);
|
||||
GX_LoadTexObj (&texobj, GX_TEXMAP0);
|
||||
draw_square (view);
|
||||
GX_DrawDone ();
|
||||
GX_SetZMode (GX_TRUE, GX_LEQUAL, GX_TRUE);
|
||||
GX_SetColorUpdate (GX_TRUE);
|
||||
GX_CopyDisp (xfb[whichfb], GX_TRUE);
|
||||
GX_Flush ();
|
||||
VIDEO_SetNextFramebuffer (xfb[whichfb]);
|
||||
VIDEO_Flush ();
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Nintendo Gamecube Hardware Specific Functions
|
||||
*
|
||||
* A U D I O
|
||||
***************************************************************************/
|
||||
unsigned char soundbuffer[16][3840] ATTRIBUTE_ALIGN(32);
|
||||
int mixbuffer = 0;
|
||||
int playbuffer = 0;
|
||||
int IsPlaying = 0;
|
||||
|
||||
/*** AudioSwitchBuffers
|
||||
Genesis Plus only provides sound data on completion of each frame.
|
||||
To try to make the audio less choppy, this function is called from both the
|
||||
DMA completion and update_audio.
|
||||
Testing for data in the buffer ensures that there are no clashes.
|
||||
***/
|
||||
static void AudioSwitchBuffers()
|
||||
{
|
||||
u32 dma_len = (vdp_pal) ? 3840 : 3200;
|
||||
|
||||
if ( !ConfigRequested )
|
||||
{
|
||||
AUDIO_InitDMA((u32) soundbuffer[playbuffer], dma_len);
|
||||
DCFlushRange(soundbuffer[playbuffer], dma_len);
|
||||
AUDIO_StartDMA();
|
||||
playbuffer++;
|
||||
playbuffer &= 0xf;
|
||||
if ( playbuffer == mixbuffer ) playbuffer--;
|
||||
if ( playbuffer < 0 ) playbuffer = 15;
|
||||
IsPlaying = 1;
|
||||
}
|
||||
else IsPlaying = 0;
|
||||
}
|
||||
|
||||
/*** InitGCAudio
|
||||
Stock code to set the DSP at 48Khz
|
||||
***/
|
||||
static void InitGCAudio ()
|
||||
{
|
||||
AUDIO_Init (NULL);
|
||||
AUDIO_SetDSPSampleRate (AI_SAMPLERATE_48KHZ);
|
||||
AUDIO_RegisterDMACallback (AudioSwitchBuffers);
|
||||
memset(soundbuffer, 0, 16 * 3840);
|
||||
}
|
||||
|
||||
/*** Audio Update
|
||||
called after each emulation frame
|
||||
***/
|
||||
static void update_audio ()
|
||||
{
|
||||
if (IsPlaying == 0) AudioSwitchBuffers ();
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Nintendo Gamecube Hardware Specific Functions
|
||||
*
|
||||
* I N P U T
|
||||
***************************************************************************/
|
||||
/**
|
||||
* IMPORTANT
|
||||
* If you change the padmap here, be sure to update confjoy to
|
||||
* reflect the changes - or confusion will ensue!
|
||||
*
|
||||
* DEFAULT MAPPING IS:
|
||||
* Genesis Gamecube
|
||||
* A B
|
||||
* B A
|
||||
* C X
|
||||
* X LT
|
||||
* Y Y
|
||||
* Z RT
|
||||
*
|
||||
* Mode is unused, as it's our menu hotkey for now :)
|
||||
* Also note that libOGC has LT/RT reversed - it's not a typo!
|
||||
*/
|
||||
unsigned int gppadmap[] = { INPUT_A, INPUT_B, INPUT_C,
|
||||
INPUT_X, INPUT_Y, INPUT_Z,
|
||||
INPUT_UP, INPUT_DOWN,
|
||||
INPUT_LEFT, INPUT_RIGHT,
|
||||
INPUT_START, INPUT_MODE
|
||||
};
|
||||
|
||||
unsigned short gcpadmap[] = { PAD_BUTTON_B, PAD_BUTTON_A, PAD_BUTTON_X,
|
||||
PAD_TRIGGER_L, PAD_BUTTON_Y, PAD_TRIGGER_R,
|
||||
PAD_BUTTON_UP, PAD_BUTTON_DOWN,
|
||||
PAD_BUTTON_LEFT, PAD_BUTTON_RIGHT,
|
||||
PAD_BUTTON_START, PAD_TRIGGER_Z
|
||||
};
|
||||
|
||||
static unsigned int DecodeJoy (unsigned short p)
|
||||
{
|
||||
unsigned int J = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 12; i++) if (p & gcpadmap[i]) J |= gppadmap[i];
|
||||
return J;
|
||||
}
|
||||
|
||||
static unsigned int GetAnalog (int Joy)
|
||||
{
|
||||
signed char x, y;
|
||||
unsigned int i = 0;
|
||||
|
||||
x = PAD_StickX (Joy);
|
||||
y = PAD_StickY (Joy);
|
||||
if (x > padcal) i |= INPUT_RIGHT;
|
||||
if (x < -padcal) i |= INPUT_LEFT;
|
||||
if (y > padcal) i |= INPUT_UP;
|
||||
if (y < -padcal) i |= INPUT_DOWN;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*** Inputs Update
|
||||
called before each emulation frame
|
||||
***/
|
||||
static void update_inputs()
|
||||
{
|
||||
int i = 0;
|
||||
int joynum = 0;
|
||||
|
||||
/*** Check for SOFT-RESET combo ***/
|
||||
if ((PAD_ButtonsHeld (0) & PAD_TRIGGER_Z) &&
|
||||
(PAD_ButtonsHeld (0) & PAD_TRIGGER_L))
|
||||
{
|
||||
m68k_pulse_reset ();
|
||||
return;
|
||||
}
|
||||
|
||||
/*** Check for menu combo ***/
|
||||
if (PAD_ButtonsHeld (0) & PAD_TRIGGER_Z)
|
||||
{
|
||||
ConfigRequested = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i=0; i<MAX_DEVICES; i++)
|
||||
{
|
||||
input.pad[i] = 0;
|
||||
if (input.dev[i] != NO_DEVICE)
|
||||
{
|
||||
input.pad[i] = DecodeJoy(PAD_ButtonsHeld (joynum));
|
||||
input.pad[i] |= GetAnalog (joynum);
|
||||
joynum ++;
|
||||
if (input.dev[i] == DEVICE_LIGHTGUN) lightgun_set();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* General Genesis Plus Support
|
||||
* Genesis Virtual Machine
|
||||
*
|
||||
***************************************************************************/
|
||||
void error (char *format, ...)
|
||||
static void load_bios()
|
||||
{
|
||||
/* Function does nothing, but must exist! */
|
||||
return;
|
||||
/* reset BIOS found flag */
|
||||
config.bios_enabled &= ~2;
|
||||
|
||||
/* open file */
|
||||
FILE *fp = fopen("/genplus/BIOS.bin", "rb");
|
||||
if (fp == NULL) return;
|
||||
|
||||
/* read file */
|
||||
fread(bios_rom, 1, 0x800, fp);
|
||||
fclose(fp);
|
||||
|
||||
/* update BIOS flags */
|
||||
config.bios_enabled |= 2;
|
||||
}
|
||||
|
||||
/*** init_machine
|
||||
Initialise the Genesis VM
|
||||
***/
|
||||
static void init_machine ()
|
||||
static void init_machine()
|
||||
{
|
||||
/*** Allocate cart_rom here ***/
|
||||
cart_rom = malloc(0x500000 + 32);
|
||||
if ((u32)cart_rom & 0x1f) cart_rom += 32 - ((u32)cart_rom & 0x1f);
|
||||
memset(cart_rom, 0, 0x500000);
|
||||
/* Allocate cart_rom here */
|
||||
cart_rom = memalign(32, 0xA00000);
|
||||
|
||||
/*** Fetch from ARAM any linked rom ***/
|
||||
if (genromsize) ARAMFetch(cart_rom, (void *)0x8000, genromsize);
|
||||
/* BIOS support */
|
||||
load_bios();
|
||||
|
||||
/*** Allocate global work bitmap ***/
|
||||
/* allocate global work bitmap */
|
||||
memset (&bitmap, 0, sizeof (bitmap));
|
||||
bitmap.data = malloc (1024 * 512 * 2);
|
||||
bitmap.width = 1024;
|
||||
bitmap.height = 512;
|
||||
bitmap.width = 360;
|
||||
bitmap.height = 576;
|
||||
bitmap.depth = 16;
|
||||
bitmap.granularity = 2;
|
||||
bitmap.pitch = (bitmap.width * bitmap.granularity);
|
||||
bitmap.pitch = bitmap.width * bitmap.granularity;
|
||||
bitmap.viewport.w = 256;
|
||||
bitmap.viewport.h = 224;
|
||||
bitmap.viewport.x = 0x20;
|
||||
bitmap.viewport.x = 0;
|
||||
bitmap.viewport.y = 0;
|
||||
bitmap.remap = 1;
|
||||
bitmap.data = malloc (bitmap.width * bitmap.height * bitmap.granularity);
|
||||
|
||||
/* default inputs */
|
||||
/* default system */
|
||||
input.system[0] = SYSTEM_GAMEPAD;
|
||||
input.system[1] = SYSTEM_GAMEPAD;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
Load a new rom and performs some initialization
|
||||
***************************************************/
|
||||
void reloadrom ()
|
||||
{
|
||||
load_rom(""); /* Load ROM */
|
||||
system_init (); /* Initialize System */
|
||||
audio_init(48000); /* Audio System initialization */
|
||||
ClearGGCodes (); /* Clear Game Genie patches */
|
||||
system_reset (); /* System Power ON */
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* M A I N
|
||||
*
|
||||
***************************************************************************/
|
||||
extern void legal ();
|
||||
extern void MainMenu ();
|
||||
extern void reloadrom ();
|
||||
int FramesPerSecond = 0;
|
||||
int frameticker = 0;
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
genromsize = 0;
|
||||
u16 usBetweenFrames;
|
||||
long long now, prev;
|
||||
int RenderedFrameCount = 0;
|
||||
int FrameCount = 0;
|
||||
|
||||
/* Initialize GC System */
|
||||
InitGCVideo ();
|
||||
InitGCAudio ();
|
||||
/* load hacked IOS with full access to DVD interface (WIP) */
|
||||
#ifdef WII_DVD
|
||||
IOS_ReloadIOS(5);
|
||||
#endif
|
||||
|
||||
/* Initialize OGC subsystems */
|
||||
ogc_video__init();
|
||||
ogc_input__init();
|
||||
ogc_audio__init();
|
||||
|
||||
/* Initialize DVD interface */
|
||||
#ifndef HW_RVL
|
||||
DVD_Init ();
|
||||
dvd_drive_detect();
|
||||
|
||||
#elif WII_DVD
|
||||
if (WDVD_Init())
|
||||
{
|
||||
if (WDVD_Reset())
|
||||
{
|
||||
u64 id;
|
||||
WDVD_LowReadDiskId(&id);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize SDCARD Interface (LibFAT) */
|
||||
fatInitDefault();
|
||||
|
||||
/* Restore User Configuration */
|
||||
set_config_defaults();
|
||||
config_load();
|
||||
|
||||
/* Restore Recent Files list */
|
||||
set_history_defaults();
|
||||
history_load();
|
||||
|
||||
/* Initialize Genesis Virtual Machine */
|
||||
init_machine ();
|
||||
legal();
|
||||
|
||||
/* Load any injected rom */
|
||||
if (genromsize)
|
||||
{
|
||||
ARAMFetch((char *)cart_rom, (void *)0x8000, genromsize);
|
||||
reloadrom ();
|
||||
MainMenu();
|
||||
}
|
||||
else while (!genromsize) MainMenu();
|
||||
|
||||
/* Main emulation loop */
|
||||
/* Show Menu */
|
||||
legal();
|
||||
MainMenu();
|
||||
ConfigRequested = 0;
|
||||
|
||||
/* Initialize Frame timings */
|
||||
frameticker = 0;
|
||||
mftb(&prev);
|
||||
prev = gettime();
|
||||
|
||||
/* Emulation Loop */
|
||||
while (1)
|
||||
{
|
||||
/* Update all inputs */
|
||||
update_inputs();
|
||||
|
||||
FrameCount++;
|
||||
|
||||
if (vdp_pal) /* PAL 50Hz (use timer) */
|
||||
/* Frame synchronization */
|
||||
if (gc_pal != vdp_pal)
|
||||
{
|
||||
mftb(&now);
|
||||
if (tb_diff_msec(&now, &prev) > msBetweenFrames)
|
||||
/* use timers */
|
||||
usBetweenFrames = vdp_pal ? 20000 : 16666;
|
||||
now = gettime();
|
||||
if (diff_usec(prev, now) > usBetweenFrames)
|
||||
{
|
||||
memcpy(&prev, &now, sizeof(tb_t));
|
||||
/* Frame skipping */
|
||||
prev = now;
|
||||
system_frame(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*** Delay ***/
|
||||
while (tb_diff_msec(&now, &prev) < msBetweenFrames) mftb(&now);
|
||||
memcpy(&prev, &now, sizeof(tb_t) );
|
||||
/* Delay */
|
||||
while (diff_usec(prev, now) < usBetweenFrames) now = gettime();
|
||||
|
||||
/* Render Frame */
|
||||
prev = now;
|
||||
system_frame(0);
|
||||
RenderedFrameCount++;
|
||||
}
|
||||
}
|
||||
else /* NTSC 60Hz (use vsync) */
|
||||
else
|
||||
{
|
||||
while ( frameticker < 1 ) usleep(10);
|
||||
|
||||
/** Simulate a frame **/
|
||||
/* use VSync */
|
||||
if (frameticker > 1)
|
||||
{
|
||||
/* Frame skipping */
|
||||
frameticker--;
|
||||
if (frameticker > 5)
|
||||
{
|
||||
system_frame (0);
|
||||
RenderedFrameCount++;
|
||||
frameticker = 1;
|
||||
}
|
||||
else system_frame (1);
|
||||
system_frame (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Delay */
|
||||
while (!frameticker) usleep(10);
|
||||
|
||||
system_frame (0);
|
||||
RenderedFrameCount++;
|
||||
}
|
||||
}
|
||||
|
||||
frameticker--;
|
||||
}
|
||||
|
||||
/** Draw the frame **/
|
||||
update_video ();
|
||||
/* update video & audio */
|
||||
ogc_video__update();
|
||||
ogc_audio__update();
|
||||
|
||||
/** add the audio **/
|
||||
update_audio ();
|
||||
|
||||
/** Check render frames **/
|
||||
if ((FrameCount == vdp_rate))
|
||||
/* Check rendered frames (FPS) */
|
||||
FrameCount++;
|
||||
if (FrameCount == vdp_rate)
|
||||
{
|
||||
FramesPerSecond = RenderedFrameCount;
|
||||
RenderedFrameCount = 0;
|
||||
FrameCount = 0;
|
||||
}
|
||||
|
||||
/* Check for Menu request */
|
||||
if (ConfigRequested)
|
||||
{
|
||||
AUDIO_StopDMA ();
|
||||
IsPlaying = mixbuffer = playbuffer = 0;
|
||||
/* reset AUDIO */
|
||||
ogc_audio__reset();
|
||||
|
||||
/* go to menu */
|
||||
MainMenu ();
|
||||
ConfigRequested = 0;
|
||||
|
||||
/* reset frame timings */
|
||||
frameticker = 0;
|
||||
prev = gettime();
|
||||
FrameCount = 0;
|
||||
RenderedFrameCount = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
86
source/ngc/ogc_audio.c
Normal file
86
source/ngc/ogc_audio.c
Normal file
@ -0,0 +1,86 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Genesis Plus - Sega Megadrive / Genesis Emulator
|
||||
*
|
||||
* NGC/Wii Audio support
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#include "ogc_input.h"
|
||||
|
||||
/* global datas */
|
||||
unsigned char soundbuffer[16][3840] ATTRIBUTE_ALIGN(32);
|
||||
int mixbuffer = 0;
|
||||
|
||||
static int playbuffer = 0;
|
||||
static int IsPlaying = 0;
|
||||
|
||||
/*** AudioSwitchBuffers
|
||||
Genesis Plus only provides sound data on completion of each frame.
|
||||
To try to make the audio less choppy, this function is called from both the
|
||||
DMA completion and update_audio.
|
||||
Testing for data in the buffer ensures that there are no clashes.
|
||||
***/
|
||||
static void AudioSwitchBuffers()
|
||||
{
|
||||
if (ConfigRequested)
|
||||
{
|
||||
IsPlaying = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
u32 dma_len = (vdp_pal) ? 3840 : 3200;
|
||||
|
||||
/* restart audio DMA with current soundbuffer */
|
||||
AUDIO_InitDMA((u32) soundbuffer[playbuffer], dma_len);
|
||||
DCFlushRange(soundbuffer[playbuffer], dma_len);
|
||||
AUDIO_StartDMA();
|
||||
|
||||
/* increment soundbuffers index */
|
||||
playbuffer++;
|
||||
playbuffer &= 0xf;
|
||||
if (playbuffer == mixbuffer)
|
||||
{
|
||||
playbuffer--;
|
||||
if ( playbuffer < 0 ) playbuffer = 15;
|
||||
}
|
||||
|
||||
IsPlaying = 1;
|
||||
}
|
||||
|
||||
|
||||
void ogc_audio__init(void)
|
||||
{
|
||||
AUDIO_Init (NULL);
|
||||
AUDIO_SetDSPSampleRate (AI_SAMPLERATE_48KHZ);
|
||||
AUDIO_RegisterDMACallback (AudioSwitchBuffers);
|
||||
memset(soundbuffer, 0, 16 * 3840);
|
||||
}
|
||||
|
||||
void ogc_audio__reset(void)
|
||||
{
|
||||
AUDIO_StopDMA ();
|
||||
IsPlaying = 0;
|
||||
mixbuffer = 0;
|
||||
playbuffer = 0;
|
||||
}
|
||||
|
||||
void ogc_audio__update(void)
|
||||
{
|
||||
/* restart Audio DMA if needed */
|
||||
if (!IsPlaying) AudioSwitchBuffers();
|
||||
}
|
31
source/ngc/ogc_audio.h
Normal file
31
source/ngc/ogc_audio.h
Normal file
@ -0,0 +1,31 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* SMS Plus - Sega Master System / GameGear Emulator
|
||||
*
|
||||
* NGC/Wii Audio support
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
#ifndef _GC_AUDIO_H_
|
||||
#define _GC_AUDIO_H_
|
||||
|
||||
extern u8 soundbuffer[16][3840];
|
||||
extern int mixbuffer;
|
||||
|
||||
extern void ogc_audio__init(void);
|
||||
extern void ogc_audio__reset(void);
|
||||
extern void ogc_audio__update(void);
|
||||
|
||||
#endif
|
671
source/ngc/ogc_input.c
Normal file
671
source/ngc/ogc_input.c
Normal file
@ -0,0 +1,671 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* SMS Plus GX - Sega Master System / GameGear Emulator
|
||||
*
|
||||
* SMS Plus - Sega Master System / GameGear Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#include "font.h"
|
||||
|
||||
#ifdef HW_RVL
|
||||
#include <wiiuse/wpad.h>
|
||||
#endif
|
||||
|
||||
/* configurable keys */
|
||||
#define KEY_BUTTONA 0
|
||||
#define KEY_BUTTONB 1
|
||||
#define KEY_BUTTONC 2
|
||||
#define KEY_START 3
|
||||
#define KEY_MENU 4
|
||||
#define KEY_BUTTONX 5 // 6-buttons only
|
||||
#define KEY_BUTTONY 6 // 6-buttons only
|
||||
#define KEY_BUTTONZ 7 // 6-buttons only
|
||||
|
||||
int ConfigRequested = 1;
|
||||
|
||||
static const char *keys_name[MAX_KEYS] =
|
||||
{
|
||||
"Button A",
|
||||
"Button B",
|
||||
"Button C",
|
||||
"Button START ",
|
||||
"Menu",
|
||||
"Button X",
|
||||
"Button Y",
|
||||
"Button Z",
|
||||
};
|
||||
|
||||
/* gamepad available buttons */
|
||||
static const u16 pad_keys[8] =
|
||||
{
|
||||
PAD_TRIGGER_Z,
|
||||
PAD_TRIGGER_R,
|
||||
PAD_TRIGGER_L,
|
||||
PAD_BUTTON_A,
|
||||
PAD_BUTTON_B,
|
||||
PAD_BUTTON_X,
|
||||
PAD_BUTTON_Y,
|
||||
PAD_BUTTON_START,
|
||||
};
|
||||
|
||||
#ifdef HW_RVL
|
||||
|
||||
/* directional buttons mapping */
|
||||
#define PAD_UP 0
|
||||
#define PAD_DOWN 1
|
||||
#define PAD_LEFT 2
|
||||
#define PAD_RIGHT 3
|
||||
|
||||
static u32 wpad_dirmap[3][4] =
|
||||
{
|
||||
{WPAD_BUTTON_RIGHT, WPAD_BUTTON_LEFT, WPAD_BUTTON_UP, WPAD_BUTTON_DOWN}, // WIIMOTE only
|
||||
{WPAD_BUTTON_UP, WPAD_BUTTON_DOWN, WPAD_BUTTON_LEFT, WPAD_BUTTON_RIGHT}, // WIIMOTE + NUNCHUK
|
||||
{WPAD_CLASSIC_BUTTON_UP, WPAD_CLASSIC_BUTTON_DOWN, WPAD_CLASSIC_BUTTON_LEFT, WPAD_CLASSIC_BUTTON_RIGHT} // CLASSIC
|
||||
};
|
||||
|
||||
/* wiimote/expansion available buttons */
|
||||
static u32 wpad_keys[20] =
|
||||
{
|
||||
WPAD_BUTTON_2,
|
||||
WPAD_BUTTON_1,
|
||||
WPAD_BUTTON_B,
|
||||
WPAD_BUTTON_A,
|
||||
/* WPAD_BUTTON_MINUS, used for mode */
|
||||
WPAD_BUTTON_HOME,
|
||||
WPAD_BUTTON_PLUS,
|
||||
WPAD_NUNCHUK_BUTTON_Z,
|
||||
WPAD_NUNCHUK_BUTTON_C,
|
||||
WPAD_CLASSIC_BUTTON_ZR,
|
||||
WPAD_CLASSIC_BUTTON_X,
|
||||
WPAD_CLASSIC_BUTTON_A,
|
||||
WPAD_CLASSIC_BUTTON_Y,
|
||||
WPAD_CLASSIC_BUTTON_B,
|
||||
WPAD_CLASSIC_BUTTON_ZL,
|
||||
WPAD_CLASSIC_BUTTON_FULL_R,
|
||||
WPAD_CLASSIC_BUTTON_PLUS,
|
||||
WPAD_CLASSIC_BUTTON_HOME,
|
||||
WPAD_CLASSIC_BUTTON_MINUS,
|
||||
WPAD_CLASSIC_BUTTON_FULL_L,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/*******************************
|
||||
gamepad support
|
||||
*******************************/
|
||||
static void pad_config(int num, int padtype)
|
||||
{
|
||||
int i,j,max;
|
||||
u16 p;
|
||||
u8 quit;
|
||||
char msg[30];
|
||||
|
||||
u32 pad = PAD_ScanPads() & (1<<num);
|
||||
if (!pad)
|
||||
{
|
||||
sprintf(msg, "PAD #%d is not connected !", num+1);
|
||||
WaitPrompt(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
/* configure keys */
|
||||
max = (padtype == DEVICE_6BUTTON) ? MAX_KEYS : (MAX_KEYS - 3);
|
||||
for (i=0; i<max; i++)
|
||||
{
|
||||
/* remove any pending keys */
|
||||
while (PAD_ButtonsHeld(num))
|
||||
{
|
||||
VIDEO_WaitVSync();
|
||||
PAD_ScanPads();
|
||||
}
|
||||
|
||||
ClearScreen();
|
||||
sprintf(msg,"Press key for %s",keys_name[i]);
|
||||
WriteCentre(254, msg);
|
||||
SetScreen();
|
||||
|
||||
/* check buttons state */
|
||||
quit = 0;
|
||||
while (quit == 0)
|
||||
{
|
||||
VIDEO_WaitVSync();
|
||||
PAD_ScanPads();
|
||||
p = PAD_ButtonsDown(num);
|
||||
|
||||
for (j=0; j<8; j++)
|
||||
{
|
||||
if (p & pad_keys[j])
|
||||
{
|
||||
config.pad_keymap[num][i] = pad_keys[j];
|
||||
quit = 1;
|
||||
j = 9; /* exit loop */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pad_update(s8 num, u8 i)
|
||||
{
|
||||
/* get PAD status */
|
||||
s8 x = PAD_StickX (num);
|
||||
s8 y = PAD_StickY (num);
|
||||
u16 p = PAD_ButtonsHeld(num);
|
||||
|
||||
/* update keys */
|
||||
if ((p & PAD_BUTTON_UP) || (y > 70)) input.pad[i] |= INPUT_UP;
|
||||
else if ((p & PAD_BUTTON_DOWN) || (y < -70)) input.pad[i] |= INPUT_DOWN;
|
||||
if ((p & PAD_BUTTON_LEFT) || (x < -60)) input.pad[i] |= INPUT_LEFT;
|
||||
else if ((p & PAD_BUTTON_RIGHT) || (x > 60)) input.pad[i] |= INPUT_RIGHT;
|
||||
|
||||
/* get current key config */
|
||||
u16 pad_keymap[MAX_KEYS];
|
||||
memcpy(pad_keymap, config.pad_keymap[num], MAX_KEYS * sizeof(u16));
|
||||
|
||||
/* SOFTRESET */
|
||||
if ((p & PAD_TRIGGER_L) && (p & PAD_TRIGGER_Z))
|
||||
{
|
||||
set_softreset();
|
||||
}
|
||||
|
||||
/* BUTTONS */
|
||||
if (p & pad_keymap[KEY_BUTTONA]) input.pad[i] |= INPUT_A;
|
||||
if (p & pad_keymap[KEY_BUTTONB]) input.pad[i] |= INPUT_B;
|
||||
if (p & pad_keymap[KEY_BUTTONC]) input.pad[i] |= INPUT_C;
|
||||
if (p & pad_keymap[KEY_BUTTONX]) input.pad[i] |= INPUT_X;
|
||||
if (p & pad_keymap[KEY_BUTTONY]) input.pad[i] |= INPUT_Y;
|
||||
if (p & pad_keymap[KEY_BUTTONZ]) input.pad[i] |= INPUT_Z;
|
||||
|
||||
/* MODE/START */
|
||||
if ((p & PAD_BUTTON_START) && (p & PAD_TRIGGER_Z)) input.pad[i] |= INPUT_MODE;
|
||||
else if (p & pad_keymap[KEY_START]) input.pad[i] |= INPUT_START;
|
||||
|
||||
/* MENU */
|
||||
if (p & pad_keymap[KEY_MENU])
|
||||
{
|
||||
ConfigRequested = 1;
|
||||
}
|
||||
|
||||
int temp;
|
||||
if (input.dev[i] == DEVICE_LIGHTGUN)
|
||||
{
|
||||
temp = input.analog[i-4][0];
|
||||
if ((input.pad[i] & INPUT_RIGHT)) temp ++;
|
||||
else if ((input.pad[i] & INPUT_LEFT)) temp --;
|
||||
if (temp < 0) temp = 0;
|
||||
else if (temp > bitmap.viewport.w) temp = bitmap.viewport.w;
|
||||
input.analog[i-4][0] = temp;
|
||||
|
||||
temp = input.analog[i-4][1];
|
||||
if ((input.pad[i] & INPUT_UP)) temp --;
|
||||
if ((input.pad[i] & INPUT_DOWN)) temp ++;
|
||||
if (temp < 0) temp = 0;
|
||||
else if (temp > bitmap.viewport.h) temp = bitmap.viewport.h;
|
||||
input.analog[i-4][1] = temp;
|
||||
}
|
||||
else if ((system_hw == SYSTEM_PICO) && (i == 0))
|
||||
{
|
||||
temp = input.analog[0][0];
|
||||
if ((input.pad[i] & INPUT_RIGHT)) temp ++;
|
||||
else if ((input.pad[i] & INPUT_LEFT)) temp --;
|
||||
if (temp < 0x17c) temp = 0x17c;
|
||||
else if (temp > 0x3c) temp = 0x3c;
|
||||
input.analog[0][0] = temp;
|
||||
|
||||
temp = input.analog[0][1];
|
||||
if ((input.pad[i] & INPUT_UP)) temp --;
|
||||
if ((input.pad[i] & INPUT_DOWN)) temp ++;
|
||||
if (temp < 0x1fc) temp = 0x1fc;
|
||||
else if (temp > 0x3f3) temp = 0x3f3;
|
||||
input.analog[0][1] = temp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*******************************
|
||||
wiimote support
|
||||
*******************************/
|
||||
#ifdef HW_RVL
|
||||
|
||||
#define PI 3.14159265f
|
||||
|
||||
static 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);
|
||||
}
|
||||
|
||||
|
||||
static 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);
|
||||
}
|
||||
|
||||
static void wpad_config(u8 num, u8 exp, u8 padtype)
|
||||
{
|
||||
int i,j,max;
|
||||
u8 quit;
|
||||
char msg[30];
|
||||
u32 current = 255;
|
||||
|
||||
/* check wiimote status */
|
||||
WPAD_Probe(num, ¤t);
|
||||
if (((exp > WPAD_EXP_NONE) && (current != exp)) || (current == 255))
|
||||
{
|
||||
if (exp == WPAD_EXP_NONE) sprintf(msg, "WIIMOTE #%d is not connected !", num+1);
|
||||
if (exp == WPAD_EXP_NUNCHUK) sprintf(msg, "NUNCHUK #%d is not connected !", num+1);
|
||||
if (exp == WPAD_EXP_CLASSIC) sprintf(msg, "CLASSIC #%d is not connected !", num+1);
|
||||
WaitPrompt(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
/* index for wpad_keymap */
|
||||
u8 index = exp + (num * 3);
|
||||
|
||||
/* loop on each mapped keys */
|
||||
max = (padtype == DEVICE_6BUTTON) ? MAX_KEYS : (MAX_KEYS - 3);
|
||||
for (i=0; i<max; i++)
|
||||
{
|
||||
/* remove any pending buttons */
|
||||
while (WPAD_ButtonsHeld(num))
|
||||
{
|
||||
WPAD_ScanPads();
|
||||
VIDEO_WaitVSync();
|
||||
}
|
||||
|
||||
/* user information */
|
||||
ClearScreen();
|
||||
sprintf(msg,"Press key for %s",keys_name[i]);
|
||||
WriteCentre(254, msg);
|
||||
SetScreen();
|
||||
|
||||
/* wait for input */
|
||||
quit = 0;
|
||||
while (quit == 0)
|
||||
{
|
||||
WPAD_ScanPads();
|
||||
|
||||
/* get buttons */
|
||||
for (j=0; j<20; j++)
|
||||
{
|
||||
if (WPAD_ButtonsDown(num) & wpad_keys[j])
|
||||
{
|
||||
config.wpad_keymap[index][i] = wpad_keys[j];
|
||||
quit = 1;
|
||||
j = 20; /* leave loop */
|
||||
}
|
||||
}
|
||||
} /* wait for input */
|
||||
} /* loop for all keys */
|
||||
|
||||
/* removed any pending buttons */
|
||||
while (WPAD_ButtonsHeld(num))
|
||||
{
|
||||
WPAD_ScanPads();
|
||||
VIDEO_WaitVSync();
|
||||
}
|
||||
}
|
||||
|
||||
static void wpad_update(s8 num, u8 i, u32 exp)
|
||||
{
|
||||
/* get buttons status */
|
||||
u32 p = WPAD_ButtonsHeld(num);
|
||||
|
||||
/* get analog sticks values */
|
||||
s8 x = 0;
|
||||
s8 y = 0;
|
||||
if (exp != WPAD_EXP_NONE)
|
||||
{
|
||||
x = WPAD_StickX(num,0);
|
||||
y = WPAD_StickY(num,0);
|
||||
}
|
||||
|
||||
/* update directional key input */
|
||||
if ((p & wpad_dirmap[exp][PAD_UP]) || (y > 70)) input.pad[i] |= INPUT_UP;
|
||||
else if ((p & wpad_dirmap[exp][PAD_DOWN]) || (y < -70)) input.pad[i] |= INPUT_DOWN;
|
||||
if ((p & wpad_dirmap[exp][PAD_LEFT]) || (x < -60)) input.pad[i] |= INPUT_LEFT;
|
||||
else if ((p & wpad_dirmap[exp][PAD_RIGHT]) || (x > 60)) input.pad[i] |= INPUT_RIGHT;
|
||||
|
||||
/* retrieve current key mapping */
|
||||
u32 *wpad_keymap = config.wpad_keymap[exp + (3 * num)];
|
||||
|
||||
/* BUTTONS */
|
||||
if (p & wpad_keymap[KEY_BUTTONA]) input.pad[i] |= INPUT_A;
|
||||
if (p & wpad_keymap[KEY_BUTTONB]) input.pad[i] |= INPUT_B;
|
||||
if (p & wpad_keymap[KEY_BUTTONC]) input.pad[i] |= INPUT_C;
|
||||
if (p & wpad_keymap[KEY_BUTTONX]) input.pad[i] |= INPUT_X;
|
||||
if (p & wpad_keymap[KEY_BUTTONY]) input.pad[i] |= INPUT_Y;
|
||||
if (p & wpad_keymap[KEY_BUTTONZ]) input.pad[i] |= INPUT_Z;
|
||||
if (p & wpad_keymap[KEY_START]) input.pad[i] |= INPUT_START;
|
||||
|
||||
/* MODE Button */
|
||||
if ((p & WPAD_CLASSIC_BUTTON_MINUS) || (p & WPAD_BUTTON_MINUS)) input.pad[i] |= INPUT_MODE;
|
||||
|
||||
/* ANALOG Device (use IR pointing by default) */
|
||||
if (input.dev[i] == DEVICE_LIGHTGUN)
|
||||
{
|
||||
struct ir_t ir;
|
||||
WPAD_IR(num, &ir);
|
||||
if (ir.valid)
|
||||
{
|
||||
input.analog[i-4][0] = (ir.x * bitmap.viewport.w) / 640;
|
||||
input.analog[i-4][1] = (ir.y * bitmap.viewport.h) / 480;
|
||||
}
|
||||
}
|
||||
else if ((system_hw == SYSTEM_PICO) && (i == 0))
|
||||
{
|
||||
struct ir_t ir;
|
||||
WPAD_IR(num, &ir);
|
||||
if (ir.valid)
|
||||
{
|
||||
input.analog[0][0] = 0x3c + (ir.x * (0x17c - 0x3c + 1)) / 640;
|
||||
input.analog[0][1] = 0x1fc + (ir.y * (0x3f3 - 0x1fc + 1)) / 480;
|
||||
}
|
||||
}
|
||||
|
||||
/* SOFTRESET */
|
||||
if (((p & WPAD_CLASSIC_BUTTON_PLUS) && (p & WPAD_CLASSIC_BUTTON_MINUS)) ||
|
||||
((p & WPAD_BUTTON_PLUS) && (p & WPAD_BUTTON_MINUS)))
|
||||
{
|
||||
set_softreset();
|
||||
}
|
||||
|
||||
/* MENU */
|
||||
if (p & wpad_keymap[KEY_MENU])
|
||||
{
|
||||
ConfigRequested = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************
|
||||
Generic input handlers
|
||||
******************************************************************/
|
||||
|
||||
void ogc_input__init(void)
|
||||
{
|
||||
PAD_Init ();
|
||||
|
||||
#ifdef HW_RVL
|
||||
WPAD_Init();
|
||||
WPAD_SetIdleTimeout(60);
|
||||
WPAD_SetDataFormat(WPAD_CHAN_ALL,WPAD_FMT_BTNS_ACC_IR);
|
||||
WPAD_SetVRes(WPAD_CHAN_ALL,640,480);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ogc_input__set_defaults(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* set default key mapping for each type of devices */
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
config.pad_keymap[i][KEY_BUTTONA] = PAD_BUTTON_B;
|
||||
config.pad_keymap[i][KEY_BUTTONB] = PAD_BUTTON_A;
|
||||
config.pad_keymap[i][KEY_BUTTONC] = PAD_BUTTON_X;
|
||||
config.pad_keymap[i][KEY_START] = PAD_BUTTON_START;
|
||||
config.pad_keymap[i][KEY_MENU] = PAD_TRIGGER_Z;
|
||||
config.pad_keymap[i][KEY_BUTTONX] = PAD_TRIGGER_L;
|
||||
config.pad_keymap[i][KEY_BUTTONY] = PAD_BUTTON_Y;
|
||||
config.pad_keymap[i][KEY_BUTTONZ] = PAD_TRIGGER_R;
|
||||
}
|
||||
|
||||
#ifdef HW_RVL
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
/* WIIMOTE */
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_BUTTONA] = WPAD_BUTTON_A;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_BUTTONB] = WPAD_BUTTON_2;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_BUTTONC] = WPAD_BUTTON_1;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_START] = WPAD_BUTTON_PLUS;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_MENU] = WPAD_BUTTON_HOME;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_BUTTONX] = 0;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_BUTTONY] = 0;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_NONE][KEY_BUTTONZ] = 0;
|
||||
|
||||
/* WIIMOTE + NUNCHUK */
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_BUTTONA] = WPAD_NUNCHUK_BUTTON_Z;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_BUTTONB] = WPAD_BUTTON_A;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_BUTTONC] = WPAD_BUTTON_B;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_START] = WPAD_BUTTON_PLUS;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_MENU] = WPAD_BUTTON_HOME;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_BUTTONX] = WPAD_NUNCHUK_BUTTON_C;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_BUTTONY] = WPAD_BUTTON_1;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_NUNCHUK][KEY_BUTTONZ] = WPAD_BUTTON_2;
|
||||
|
||||
/* CLASSIC CONTROLLER */
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_BUTTONA] = WPAD_CLASSIC_BUTTON_Y;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_BUTTONB] = WPAD_CLASSIC_BUTTON_B;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_BUTTONC] = WPAD_CLASSIC_BUTTON_A;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_START] = WPAD_CLASSIC_BUTTON_PLUS;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_MENU] = WPAD_CLASSIC_BUTTON_HOME;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_BUTTONX] = WPAD_CLASSIC_BUTTON_ZL;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_BUTTONY] = WPAD_CLASSIC_BUTTON_X;
|
||||
config.wpad_keymap[i*3 + WPAD_EXP_CLASSIC][KEY_BUTTONZ] = WPAD_CLASSIC_BUTTON_ZR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* set default device assigantion */
|
||||
for (i=0; i<MAX_DEVICES; i++)
|
||||
{
|
||||
#ifdef HW_RVL
|
||||
config.input[i].device = (i < 4) ? 1 : 0;
|
||||
#else
|
||||
config.input[i].device = (i < 4) ? 0 : -1;
|
||||
#endif
|
||||
config.input[i].port = i % 4;
|
||||
}
|
||||
}
|
||||
|
||||
void ogc_input__update(void)
|
||||
{
|
||||
int i;
|
||||
int num = 0;
|
||||
|
||||
/* update inputs */
|
||||
PAD_ScanPads();
|
||||
|
||||
#ifdef HW_RVL
|
||||
WPAD_ScanPads();
|
||||
if (WPAD_ButtonsHeld(0) & WPAD_BUTTON_HOME)
|
||||
{
|
||||
/* do additional check here to prevent bad controller configuration */
|
||||
ConfigRequested = 1;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i=0; i<MAX_DEVICES; i++)
|
||||
{
|
||||
input.pad[i] = 0;
|
||||
|
||||
if (input.dev[i] != NO_DEVICE)
|
||||
{
|
||||
if (config.input[num].device == 0)
|
||||
pad_update(config.input[num].port, i);
|
||||
|
||||
#ifdef HW_RVL
|
||||
else if (config.input[num].device > 0)
|
||||
wpad_update(config.input[num].port,i, config.input[num].device - 1);
|
||||
#endif
|
||||
num ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ogc_input__config(u8 num, u8 type, u8 padtype)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
pad_config(num, padtype);
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef HW_RVL
|
||||
wpad_config(num,type-1, padtype);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u16 ogc_input__getMenuButtons(void)
|
||||
{
|
||||
/* gamecube pad */
|
||||
PAD_ScanPads();
|
||||
u16 p = PAD_ButtonsDown(0);
|
||||
s8 x = PAD_StickX(0);
|
||||
s8 y = PAD_StickY(0);
|
||||
if (x > 70) p |= PAD_BUTTON_RIGHT;
|
||||
else if (x < -70) p |= PAD_BUTTON_LEFT;
|
||||
if (y > 60) p |= PAD_BUTTON_UP;
|
||||
else if (y < -60) p |= PAD_BUTTON_DOWN;
|
||||
|
||||
#ifdef HW_RVL
|
||||
/* wiimote support */
|
||||
struct ir_t ir;
|
||||
u32 exp;
|
||||
|
||||
WPAD_ScanPads();
|
||||
if (WPAD_Probe(0, &exp) == WPAD_ERR_NONE)
|
||||
{
|
||||
u32 q = WPAD_ButtonsDown(0);
|
||||
x = WPAD_StickX(0, 0);
|
||||
y = WPAD_StickY(0, 0);
|
||||
|
||||
/* default directions */
|
||||
WPAD_IR(0, &ir);
|
||||
if (ir.valid)
|
||||
{
|
||||
/* Wiimote is pointed toward screen */
|
||||
if ((q & WPAD_BUTTON_UP) || (y > 70)) p |= PAD_BUTTON_UP;
|
||||
else if ((q & WPAD_BUTTON_DOWN) || (y < -70)) p |= PAD_BUTTON_DOWN;
|
||||
if ((q & WPAD_BUTTON_LEFT) || (x < -60)) p |= PAD_BUTTON_LEFT;
|
||||
else if ((q & WPAD_BUTTON_RIGHT) || (x > 60)) p |= PAD_BUTTON_RIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wiimote is used horizontally */
|
||||
if ((q & WPAD_BUTTON_RIGHT) || (y > 70)) p |= PAD_BUTTON_UP;
|
||||
else if ((q & WPAD_BUTTON_LEFT) || (y < -70)) p |= PAD_BUTTON_DOWN;
|
||||
if ((q & WPAD_BUTTON_UP) || (x < -60)) p |= PAD_BUTTON_LEFT;
|
||||
else if ((q & WPAD_BUTTON_DOWN) || (x > 60)) p |= PAD_BUTTON_RIGHT;
|
||||
}
|
||||
|
||||
/* default keys */
|
||||
if (q & WPAD_BUTTON_MINUS) p |= PAD_TRIGGER_L;
|
||||
if (q & WPAD_BUTTON_PLUS) p |= PAD_TRIGGER_R;
|
||||
if (q & WPAD_BUTTON_A) p |= PAD_BUTTON_A;
|
||||
if (q & WPAD_BUTTON_B) p |= PAD_BUTTON_B;
|
||||
if (q & WPAD_BUTTON_2) p |= PAD_BUTTON_A;
|
||||
if (q & WPAD_BUTTON_1) p |= PAD_BUTTON_B;
|
||||
if (q & WPAD_BUTTON_HOME) p |= PAD_TRIGGER_Z;
|
||||
|
||||
/* classic controller expansion */
|
||||
if (exp == WPAD_EXP_CLASSIC)
|
||||
{
|
||||
if (q & WPAD_CLASSIC_BUTTON_UP) p |= PAD_BUTTON_UP;
|
||||
else if (q & WPAD_CLASSIC_BUTTON_DOWN) p |= PAD_BUTTON_DOWN;
|
||||
if (q & WPAD_CLASSIC_BUTTON_LEFT) p |= PAD_BUTTON_LEFT;
|
||||
else if (q & WPAD_CLASSIC_BUTTON_RIGHT) p |= PAD_BUTTON_RIGHT;
|
||||
|
||||
if (q & WPAD_CLASSIC_BUTTON_FULL_L) p |= PAD_TRIGGER_L;
|
||||
if (q & WPAD_CLASSIC_BUTTON_FULL_R) p |= PAD_TRIGGER_R;
|
||||
if (q & WPAD_CLASSIC_BUTTON_A) p |= PAD_BUTTON_A;
|
||||
if (q & WPAD_CLASSIC_BUTTON_B) p |= PAD_BUTTON_B;
|
||||
if (q & WPAD_CLASSIC_BUTTON_HOME) p |= PAD_TRIGGER_Z;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return p;
|
||||
}
|
42
source/ngc/ogc_input.h
Normal file
42
source/ngc/ogc_input.h
Normal file
@ -0,0 +1,42 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* SMS Plus - Sega Master System / GameGear Emulator
|
||||
*
|
||||
* NGC/Wii Controller support
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
#ifndef _GC_INPUT_H_
|
||||
#define _GC_INPUT_H_
|
||||
|
||||
/* number of configurable keys */
|
||||
#define MAX_KEYS 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
s8 device;
|
||||
u8 port;
|
||||
} t_input_config;
|
||||
|
||||
|
||||
extern int ConfigRequested;
|
||||
|
||||
extern void ogc_input__init(void);
|
||||
extern void ogc_input__set_defaults(void);
|
||||
extern void ogc_input__update(void);
|
||||
extern void ogc_input__config(u8 num, u8 type, u8 padtype);
|
||||
extern u16 ogc_input__getMenuButtons(void);
|
||||
|
||||
#endif
|
713
source/ngc/ogc_video.c
Normal file
713
source/ngc/ogc_video.c
Normal file
@ -0,0 +1,713 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Genesis Plus - Sega Megadrive / Genesis Emulator
|
||||
*
|
||||
* NGC/Wii Video support
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#include "font.h"
|
||||
#include "gcaram.h"
|
||||
|
||||
/*** PAL 50hz flag ***/
|
||||
uint8 gc_pal = 0;
|
||||
|
||||
/*** VI ***/
|
||||
unsigned int *xfb[2]; /*** Double buffered ***/
|
||||
int whichfb = 0; /*** External framebuffer index ***/
|
||||
GXRModeObj *vmode; /*** Menu video mode ***/
|
||||
|
||||
/*** GX ***/
|
||||
#define TEX_WIDTH 356
|
||||
#define TEX_HEIGHT 576
|
||||
#define DEFAULT_FIFO_SIZE 256 * 1024
|
||||
#define HASPECT 320
|
||||
#define VASPECT 240
|
||||
|
||||
static u8 gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN (32);
|
||||
static u8 texturemem[TEX_WIDTH * (TEX_HEIGHT + 8) * 2] ATTRIBUTE_ALIGN (32);
|
||||
static GXTexObj texobj;
|
||||
static Mtx view;
|
||||
static int vwidth, vheight;
|
||||
static long long int stride;
|
||||
|
||||
/*** custom Video modes (used to emulate original console video modes) ***/
|
||||
/* 288 lines progressive (PAL 50Hz) */
|
||||
GXRModeObj TV50hz_288p =
|
||||
{
|
||||
VI_TVMODE_PAL_DS, // viDisplayMode
|
||||
640, // fbWidth
|
||||
286, // efbHeight
|
||||
286, // xfbHeight
|
||||
(VI_MAX_WIDTH_PAL - 720)/2, // viXOrigin
|
||||
(VI_MAX_HEIGHT_PAL - 572)/2, // viYOrigin
|
||||
720, // viWidth
|
||||
572, // viHeight
|
||||
VI_XFBMODE_SF, // xFBmode
|
||||
GX_FALSE, // field_rendering
|
||||
GX_FALSE, // aa
|
||||
|
||||
// sample points arranged in increasing Y order
|
||||
{
|
||||
{6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each
|
||||
{6,6},{6,6},{6,6}, // pix 1
|
||||
{6,6},{6,6},{6,6}, // pix 2
|
||||
{6,6},{6,6},{6,6} // pix 3
|
||||
},
|
||||
|
||||
// vertical filter[7], 1/64 units, 6 bits each
|
||||
{
|
||||
0, // line n-1
|
||||
0, // line n-1
|
||||
21, // line n
|
||||
22, // line n
|
||||
21, // line n
|
||||
0, // line n+1
|
||||
0 // line n+1
|
||||
}
|
||||
};
|
||||
|
||||
/* 288 lines interlaced (PAL 50Hz) */
|
||||
GXRModeObj TV50hz_288i =
|
||||
{
|
||||
VI_TVMODE_PAL_INT, // viDisplayMode
|
||||
640, // fbWidth
|
||||
286, // efbHeight
|
||||
286, // xfbHeight
|
||||
(VI_MAX_WIDTH_PAL - 720)/2, // viXOrigin
|
||||
(VI_MAX_HEIGHT_PAL - 572)/2, // viYOrigin
|
||||
720, // viWidth
|
||||
572, // viHeight
|
||||
VI_XFBMODE_SF, // xFBmode
|
||||
GX_TRUE, // field_rendering
|
||||
GX_FALSE, // aa
|
||||
|
||||
// sample points arranged in increasing Y order
|
||||
{
|
||||
{6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each
|
||||
{6,6},{6,6},{6,6}, // pix 1
|
||||
{6,6},{6,6},{6,6}, // pix 2
|
||||
{6,6},{6,6},{6,6} // pix 3
|
||||
},
|
||||
|
||||
// vertical filter[7], 1/64 units, 6 bits each
|
||||
{
|
||||
0, // line n-1
|
||||
0, // line n-1
|
||||
21, // line n
|
||||
22, // line n
|
||||
21, // line n
|
||||
0, // line n+1
|
||||
0 // line n+1
|
||||
}
|
||||
};
|
||||
|
||||
/* 576 lines interlaced (PAL 50Hz, scaled) */
|
||||
GXRModeObj TV50hz_576i =
|
||||
{
|
||||
VI_TVMODE_PAL_INT, // viDisplayMode
|
||||
640, // fbWidth
|
||||
480, // efbHeight
|
||||
574, // xfbHeight
|
||||
(VI_MAX_WIDTH_PAL - 720)/2, // viXOrigin
|
||||
(VI_MAX_HEIGHT_PAL - 574)/2, // viYOrigin
|
||||
720, // viWidth
|
||||
574, // viHeight
|
||||
VI_XFBMODE_DF, // xFBmode
|
||||
GX_FALSE, // field_rendering
|
||||
GX_FALSE, // aa
|
||||
|
||||
// sample points arranged in increasing Y order
|
||||
{
|
||||
{6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each
|
||||
{6,6},{6,6},{6,6}, // pix 1
|
||||
{6,6},{6,6},{6,6}, // pix 2
|
||||
{6,6},{6,6},{6,6} // pix 3
|
||||
},
|
||||
|
||||
// vertical filter[7], 1/64 units, 6 bits each
|
||||
{
|
||||
8, // line n-1
|
||||
8, // line n-1
|
||||
10, // line n
|
||||
12, // line n
|
||||
10, // line n
|
||||
8, // line n+1
|
||||
8 // line n+1
|
||||
}
|
||||
};
|
||||
|
||||
/* 240 lines progressive (NTSC or PAL 60Hz) */
|
||||
GXRModeObj TV60hz_240p =
|
||||
{
|
||||
VI_TVMODE_EURGB60_DS, // viDisplayMode
|
||||
640, // fbWidth
|
||||
240, // efbHeight
|
||||
240, // xfbHeight
|
||||
(VI_MAX_WIDTH_NTSC - 720)/2, // viXOrigin
|
||||
(VI_MAX_HEIGHT_NTSC/2 - 480/2)/2, // viYOrigin
|
||||
720, // viWidth
|
||||
480, // viHeight
|
||||
VI_XFBMODE_SF, // xFBmode
|
||||
GX_FALSE, // field_rendering
|
||||
GX_FALSE, // aa
|
||||
|
||||
// sample points arranged in increasing Y order
|
||||
{
|
||||
{6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each
|
||||
{6,6},{6,6},{6,6}, // pix 1
|
||||
{6,6},{6,6},{6,6}, // pix 2
|
||||
{6,6},{6,6},{6,6} // pix 3
|
||||
},
|
||||
|
||||
// vertical filter[7], 1/64 units, 6 bits each
|
||||
{
|
||||
0, // line n-1
|
||||
0, // line n-1
|
||||
21, // line n
|
||||
22, // line n
|
||||
21, // line n
|
||||
0, // line n+1
|
||||
0 // line n+1
|
||||
}
|
||||
};
|
||||
|
||||
/* 240 lines interlaced (NTSC or PAL 60Hz) */
|
||||
GXRModeObj TV60hz_240i =
|
||||
{
|
||||
VI_TVMODE_EURGB60_INT, // viDisplayMode
|
||||
640, // fbWidth
|
||||
240, // efbHeight
|
||||
240, // xfbHeight
|
||||
(VI_MAX_WIDTH_NTSC - 720)/2, // viXOrigin
|
||||
(VI_MAX_HEIGHT_NTSC - 480)/2, // viYOrigin
|
||||
720, // viWidth
|
||||
480, // viHeight
|
||||
VI_XFBMODE_SF, // xFBmode
|
||||
GX_TRUE, // field_rendering
|
||||
GX_FALSE, // aa
|
||||
|
||||
// sample points arranged in increasing Y order
|
||||
{
|
||||
{6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each
|
||||
{6,6},{6,6},{6,6}, // pix 1
|
||||
{6,6},{6,6},{6,6}, // pix 2
|
||||
{6,6},{6,6},{6,6} // pix 3
|
||||
},
|
||||
|
||||
// vertical filter[7], 1/64 units, 6 bits each
|
||||
{
|
||||
0, // line n-1
|
||||
0, // line n-1
|
||||
21, // line n
|
||||
22, // line n
|
||||
21, // line n
|
||||
0, // line n+1
|
||||
0 // line n+1
|
||||
}
|
||||
};
|
||||
|
||||
/* 480 lines interlaced (NTSC or PAL 60Hz) */
|
||||
GXRModeObj TV60hz_480i =
|
||||
{
|
||||
VI_TVMODE_EURGB60_INT, // viDisplayMode
|
||||
640, // fbWidth
|
||||
480, // efbHeight
|
||||
480, // xfbHeight
|
||||
(VI_MAX_WIDTH_NTSC - 720)/2, // viXOrigin
|
||||
(VI_MAX_HEIGHT_NTSC - 480)/2, // viYOrigin
|
||||
720, // viWidth
|
||||
480, // viHeight
|
||||
VI_XFBMODE_DF, // xFBmode
|
||||
GX_FALSE, // field_rendering
|
||||
GX_FALSE, // aa
|
||||
|
||||
// sample points arranged in increasing Y order
|
||||
{
|
||||
{6,6},{6,6},{6,6}, // pix 0, 3 sample points, 1/12 units, 4 bits each
|
||||
{6,6},{6,6},{6,6}, // pix 1
|
||||
{6,6},{6,6},{6,6}, // pix 2
|
||||
{6,6},{6,6},{6,6} // pix 3
|
||||
},
|
||||
|
||||
// vertical filter[7], 1/64 units, 6 bits each
|
||||
{
|
||||
8, // line n-1
|
||||
8, // line n-1
|
||||
10, // line n
|
||||
12, // line n
|
||||
10, // line n
|
||||
8, // line n+1
|
||||
8 // line n+1
|
||||
}
|
||||
};
|
||||
|
||||
/* TV Modes table */
|
||||
GXRModeObj *tvmodes[6] = {
|
||||
&TV60hz_240p, &TV60hz_240i, &TV60hz_480i, /* 60hz modes */
|
||||
&TV50hz_288p, &TV50hz_288i, &TV50hz_576i /* 50Hz modes */
|
||||
};
|
||||
|
||||
typedef struct tagcamera
|
||||
{
|
||||
Vector pos;
|
||||
Vector up;
|
||||
Vector view;
|
||||
} camera;
|
||||
|
||||
/*** Square Matrix
|
||||
This structure controls the size of the image on the screen.
|
||||
Think of the output as a -80 x 80 by -60 x 60 graph.
|
||||
***/
|
||||
static s16 square[] ATTRIBUTE_ALIGN (32) =
|
||||
{
|
||||
/*
|
||||
* X, Y, Z
|
||||
* Values set are for roughly 4:3 aspect
|
||||
*/
|
||||
-HASPECT, VASPECT, 0, // 0
|
||||
HASPECT, VASPECT, 0, // 1
|
||||
HASPECT, -VASPECT, 0, // 2
|
||||
-HASPECT, -VASPECT, 0, // 3
|
||||
};
|
||||
|
||||
static camera cam = {
|
||||
{0.0F, 0.0F, -100.0F},
|
||||
{0.0F, -1.0F, 0.0F},
|
||||
{0.0F, 0.0F, 0.0F}
|
||||
};
|
||||
|
||||
/* rendering initialization */
|
||||
/* should be called each time you change quad aspect ratio */
|
||||
static void draw_init(void)
|
||||
{
|
||||
/* Clear all Vertex params */
|
||||
GX_ClearVtxDesc ();
|
||||
|
||||
/* Set Position Params (set quad aspect ratio) */
|
||||
GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
|
||||
GX_SetVtxDesc (GX_VA_POS, GX_INDEX8);
|
||||
GX_SetArray (GX_VA_POS, square, 3 * sizeof (s16));
|
||||
|
||||
/* Set Tex Coord Params */
|
||||
GX_SetVtxAttrFmt (GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
||||
GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT);
|
||||
GX_SetTevOp (GX_TEVSTAGE0, GX_REPLACE);
|
||||
GX_SetTevOrder (GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLORNULL);
|
||||
GX_SetNumTexGens (1);
|
||||
GX_SetNumChans(0);
|
||||
|
||||
/** Set Modelview **/
|
||||
memset (&view, 0, sizeof (Mtx));
|
||||
guLookAt(view, &cam.pos, &cam.up, &cam.view);
|
||||
GX_LoadPosMtxImm (view, GX_PNMTX0);
|
||||
}
|
||||
|
||||
/* vertex rendering */
|
||||
static void draw_vert(u8 pos, f32 s, f32 t)
|
||||
{
|
||||
GX_Position1x8 (pos);
|
||||
GX_TexCoord2f32 (s, t);
|
||||
}
|
||||
|
||||
/* textured quad rendering */
|
||||
static void draw_square (void)
|
||||
{
|
||||
GX_Begin (GX_QUADS, GX_VTXFMT0, 4);
|
||||
draw_vert (3, 0.0, 0.0);
|
||||
draw_vert (2, 1.0, 0.0);
|
||||
draw_vert (1, 1.0, 1.0);
|
||||
draw_vert (0, 0.0, 1.0);
|
||||
GX_End ();
|
||||
}
|
||||
|
||||
/* retrace handler */
|
||||
static void framestart(u32 retraceCnt)
|
||||
{
|
||||
/* simply increment the tick counter */
|
||||
frameticker++;
|
||||
}
|
||||
|
||||
static void gxStart(void)
|
||||
{
|
||||
Mtx p;
|
||||
GXColor gxbackground = { 0, 0, 0, 0xff };
|
||||
|
||||
/*** Clear out FIFO area ***/
|
||||
memset (&gp_fifo, 0, DEFAULT_FIFO_SIZE);
|
||||
|
||||
/*** GX default ***/
|
||||
GX_Init (&gp_fifo, DEFAULT_FIFO_SIZE);
|
||||
GX_SetCopyClear (gxbackground, 0x00ffffff);
|
||||
|
||||
GX_SetViewport (0.0F, 0.0F, vmode->fbWidth, vmode->efbHeight, 0.0F, 1.0F);
|
||||
GX_SetScissor (0, 0, vmode->fbWidth, vmode->efbHeight);
|
||||
f32 yScale = GX_GetYScaleFactor(vmode->efbHeight, vmode->xfbHeight);
|
||||
u16 xfbHeight = GX_SetDispCopyYScale (yScale);
|
||||
GX_SetDispCopySrc (0, 0, vmode->fbWidth, vmode->efbHeight);
|
||||
GX_SetDispCopyDst (vmode->fbWidth, xfbHeight);
|
||||
GX_SetCopyFilter (vmode->aa, vmode->sample_pattern, GX_TRUE, vmode->vfilter);
|
||||
GX_SetFieldMode (vmode->field_rendering, ((vmode->viHeight == 2 * vmode->xfbHeight) ? GX_ENABLE : GX_DISABLE));
|
||||
GX_SetPixelFmt (GX_PF_RGB8_Z24, GX_ZC_LINEAR);
|
||||
GX_SetCullMode (GX_CULL_NONE);
|
||||
GX_SetDispCopyGamma (GX_GM_1_0);
|
||||
GX_SetZMode(GX_FALSE, GX_ALWAYS, GX_TRUE);
|
||||
GX_SetColorUpdate (GX_TRUE);
|
||||
guOrtho(p, vmode->efbHeight/2, -(vmode->efbHeight/2), -(vmode->fbWidth/2), vmode->fbWidth/2, 100, 1000);
|
||||
GX_LoadProjectionMtx (p, GX_ORTHOGRAPHIC);
|
||||
|
||||
/*** reset XFB ***/
|
||||
GX_CopyDisp (xfb[whichfb ^ 1], GX_TRUE);
|
||||
|
||||
/*** Initialize texture data ***/
|
||||
memset (texturemem, 0, TEX_WIDTH * TEX_HEIGHT * 2);
|
||||
}
|
||||
|
||||
/* set GX scaler */
|
||||
static void gxScale(void)
|
||||
{
|
||||
int xscale, yscale, xshift, yshift, i;
|
||||
|
||||
if (config.overscan)
|
||||
{
|
||||
if (config.aspect)
|
||||
{
|
||||
/* borders are emulated */
|
||||
xscale = (reg[12] & 1) ? 360 : 358;
|
||||
if (gc_pal) xscale -= 1;
|
||||
yscale = (gc_pal && !config.render) ? (vdp_pal ? 144:143) : (vdp_pal ? 121:120);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* fullscreen stretch */
|
||||
xscale = gc_pal ? 354 : 367;
|
||||
yscale = (gc_pal && !config.render) ? (vdp_pal ? (268*144 / bitmap.viewport.h):143) : (vdp_pal ? (224*144 / bitmap.viewport.h):120);
|
||||
}
|
||||
|
||||
xshift = (config.aspect || !gc_pal) ? 8 : 4;
|
||||
yshift = vdp_pal ? 1 : -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (config.aspect)
|
||||
{
|
||||
/* borders are simulated (black) */
|
||||
xscale = 327;
|
||||
yscale = bitmap.viewport.h / 2;
|
||||
if (vdp_pal && (!gc_pal || config.render)) yscale = yscale * 243 / 288;
|
||||
else if (!vdp_pal && gc_pal && !config.render) yscale = yscale * 288 / 243;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* fullscreen stretch */
|
||||
xscale = gc_pal ? 321 : 334;
|
||||
yscale = (gc_pal && !config.render) ? 134 : 112;
|
||||
}
|
||||
|
||||
xshift = config.aspect ? 8 : 0;
|
||||
yshift = vdp_pal ? 0 : 2;
|
||||
}
|
||||
|
||||
if (!config.aspect)
|
||||
{
|
||||
xscale += config.xscale;
|
||||
yscale += config.yscale;
|
||||
}
|
||||
|
||||
xshift += config.xshift;
|
||||
yshift += config.yshift;
|
||||
|
||||
/* check horizontal upscaling */
|
||||
if (xscale > 320)
|
||||
{
|
||||
/* let VI do horizontal scaling */
|
||||
uint32 scale = (xscale <= 360) ? xscale : 360;
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
tvmodes[i]->viXOrigin = (720 - (scale * 2)) / 2;
|
||||
tvmodes[i]->viWidth = scale * 2;
|
||||
}
|
||||
xscale -= (scale - 320);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* let GX do horizontal downscaling */
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
tvmodes[i]->viXOrigin = 40;
|
||||
tvmodes[i]->viWidth = 640;
|
||||
}
|
||||
}
|
||||
|
||||
/* double resolution */
|
||||
if (config.render)
|
||||
{
|
||||
yscale *= 2;
|
||||
yshift *= 2;
|
||||
}
|
||||
|
||||
/* update matrix */
|
||||
square[6] = square[3] = xscale + xshift;
|
||||
square[0] = square[9] = -xscale + xshift;
|
||||
square[4] = square[1] = yscale + yshift;
|
||||
square[7] = square[10] = -yscale + yshift;
|
||||
draw_init();
|
||||
|
||||
/* vertex array have been modified */
|
||||
GX_InvVtxCache ();
|
||||
|
||||
}
|
||||
|
||||
/* Reinitialize GX */
|
||||
void ogc_video__reset()
|
||||
{
|
||||
GXRModeObj *rmode;
|
||||
Mtx p;
|
||||
|
||||
/* reinitialize GC/Wii PAL mode */
|
||||
if ((config.tv_mode == 1) || ((config.tv_mode == 2) && vdp_pal)) gc_pal = 1;
|
||||
else gc_pal = 0;
|
||||
|
||||
/* reset scaler */
|
||||
gxScale();
|
||||
|
||||
/* reinitialize current TV mode */
|
||||
if (config.render == 2)
|
||||
{
|
||||
tvmodes[2]->viTVMode = VI_TVMODE_NTSC_PROG;
|
||||
tvmodes[2]->xfbMode = VI_XFBMODE_SF;
|
||||
}
|
||||
else
|
||||
{
|
||||
tvmodes[2]->viTVMode = tvmodes[0]->viTVMode & ~3;
|
||||
tvmodes[2]->xfbMode = VI_XFBMODE_DF;
|
||||
}
|
||||
|
||||
if (config.render) rmode = tvmodes[gc_pal*3 + 2];
|
||||
else rmode = tvmodes[gc_pal*3 + interlaced];
|
||||
|
||||
|
||||
VIDEO_Configure (rmode);
|
||||
VIDEO_ClearFrameBuffer(rmode, xfb[whichfb], COLOR_BLACK);
|
||||
VIDEO_Flush();
|
||||
VIDEO_WaitVSync();
|
||||
if (rmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||
else while (VIDEO_GetNextField()) VIDEO_WaitVSync();
|
||||
odd_frame = 1;
|
||||
|
||||
/* reset rendering mode */
|
||||
GX_SetViewport (0.0F, 0.0F, rmode->fbWidth, rmode->efbHeight, 0.0F, 1.0F);
|
||||
GX_SetScissor (0, 0, rmode->fbWidth, rmode->efbHeight);
|
||||
f32 yScale = GX_GetYScaleFactor(rmode->efbHeight, rmode->xfbHeight);
|
||||
u16 xfbHeight = GX_SetDispCopyYScale (yScale);
|
||||
GX_SetDispCopySrc (0, 0, rmode->fbWidth, rmode->efbHeight);
|
||||
GX_SetDispCopyDst (rmode->fbWidth, xfbHeight);
|
||||
GX_SetCopyFilter (rmode->aa, rmode->sample_pattern, config.render ? GX_TRUE : GX_FALSE, rmode->vfilter);
|
||||
GX_SetFieldMode (rmode->field_rendering, ((rmode->viHeight == 2 * rmode->xfbHeight) ? GX_ENABLE : GX_DISABLE));
|
||||
GX_SetPixelFmt (GX_PF_RGB8_Z24, GX_ZC_LINEAR);
|
||||
guOrtho(p, rmode->efbHeight/2, -(rmode->efbHeight/2), -(rmode->fbWidth/2), rmode->fbWidth/2, 100, 1000);
|
||||
GX_LoadProjectionMtx (p, GX_ORTHOGRAPHIC);
|
||||
}
|
||||
|
||||
/* GX render update */
|
||||
void ogc_video__update()
|
||||
{
|
||||
int h, w;
|
||||
|
||||
/* texture and bitmap buffers (buffers width is fixed to 360 pixels) */
|
||||
long long int *dst = (long long int *)texturemem;
|
||||
long long int *src1 = (long long int *)(bitmap.data); /* line n */
|
||||
long long int *src2 = src1 + 90; /* line n+1 */
|
||||
long long int *src3 = src2 + 90; /* line n+2 */
|
||||
long long int *src4 = src3 + 90; /* line n+3 */
|
||||
|
||||
/* check if viewport has changed */
|
||||
if (bitmap.viewport.changed)
|
||||
{
|
||||
/* Check interlaced mode changes */
|
||||
if ((bitmap.viewport.changed & 2) && (!config.render))
|
||||
{
|
||||
GXRModeObj *rmode;
|
||||
rmode = tvmodes[gc_pal*3 + interlaced];
|
||||
VIDEO_Configure (rmode);
|
||||
GX_SetFieldMode (rmode->field_rendering, ((rmode->viHeight == 2 * rmode->xfbHeight) ? GX_ENABLE : GX_DISABLE));
|
||||
VIDEO_WaitVSync();
|
||||
if (rmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||
else while (VIDEO_GetNextField()) VIDEO_WaitVSync();
|
||||
}
|
||||
|
||||
bitmap.viewport.changed = 0;
|
||||
|
||||
/* update texture size */
|
||||
vwidth = bitmap.viewport.w + 2 * bitmap.viewport.x;
|
||||
vheight = bitmap.viewport.h + 2 * bitmap.viewport.y;
|
||||
if (interlaced && config.render) vheight *= 2;
|
||||
stride = bitmap.width - (vwidth >> 2);
|
||||
|
||||
/* reset GX scaler */
|
||||
gxScale();
|
||||
|
||||
/* reinitialize texture */
|
||||
GX_InvalidateTexAll ();
|
||||
GX_InitTexObj (&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||||
|
||||
/* original H40 mode: force filtering OFF */
|
||||
if (!config.render && (reg[12]&1))
|
||||
{
|
||||
GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,2.5,9.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1);
|
||||
}
|
||||
}
|
||||
|
||||
GX_InvalidateTexAll ();
|
||||
|
||||
/* update texture data */
|
||||
for (h = 0; h < vheight; h += 4)
|
||||
{
|
||||
for (w = 0; w < (vwidth >> 2); w++)
|
||||
{
|
||||
*dst++ = *src1++;
|
||||
*dst++ = *src2++;
|
||||
*dst++ = *src3++;
|
||||
*dst++ = *src4++;
|
||||
}
|
||||
|
||||
/* jump to next four lines */
|
||||
src1 += stride;
|
||||
src2 += stride;
|
||||
src3 += stride;
|
||||
src4 += stride;
|
||||
}
|
||||
|
||||
/* load texture into GX */
|
||||
DCFlushRange (texturemem, vwidth * vheight * 2);
|
||||
GX_LoadTexObj (&texobj, GX_TEXMAP0);
|
||||
|
||||
/* render textured quad */
|
||||
draw_square ();
|
||||
GX_DrawDone ();
|
||||
|
||||
/* switch external framebuffers then copy EFB to XFB */
|
||||
whichfb ^= 1;
|
||||
GX_CopyDisp (xfb[whichfb], GX_TRUE);
|
||||
GX_Flush ();
|
||||
|
||||
/* set next XFB */
|
||||
VIDEO_SetNextFramebuffer (xfb[whichfb]);
|
||||
VIDEO_Flush ();
|
||||
}
|
||||
|
||||
/* Initialize VIDEO subsystem */
|
||||
void ogc_video__init(void)
|
||||
{
|
||||
/*
|
||||
* Before doing anything else under libogc,
|
||||
* Call VIDEO_Init
|
||||
*/
|
||||
VIDEO_Init ();
|
||||
|
||||
/*
|
||||
* Before any memory is allocated etc.
|
||||
* Rescue any tagged ROM in data 2
|
||||
*/
|
||||
int *romptr = (int *)0x80700000;
|
||||
StartARAM();
|
||||
genromsize = 0;
|
||||
if ( memcmp((char *)romptr,"GENPLUSR",8) == 0 )
|
||||
{
|
||||
genromsize = romptr[2];
|
||||
ARAMPut ((char *) 0x80700000 + 0x20, (char *) 0x8000, genromsize);
|
||||
}
|
||||
|
||||
/* Get the current video mode then :
|
||||
- set menu video mode (fullscreen, 480i or 576i)
|
||||
- set emulator rendering TV modes (PAL/MPAL/NTSC/EURGB60)
|
||||
*/
|
||||
vmode = VIDEO_GetPreferredMode(NULL);
|
||||
|
||||
/* adjust display settings */
|
||||
switch (vmode->viTVMode >> 2)
|
||||
{
|
||||
case VI_PAL: /* 576 lines (PAL 50Hz) */
|
||||
|
||||
TV60hz_240p.viTVMode = VI_TVMODE_EURGB60_DS;
|
||||
TV60hz_240i.viTVMode = VI_TVMODE_EURGB60_INT;
|
||||
TV60hz_480i.viTVMode = VI_TVMODE_EURGB60_INT;
|
||||
config.tv_mode = 1;
|
||||
gc_pal = 1;
|
||||
|
||||
/* display should be centered vertically (borders) */
|
||||
vmode = &TVPal574IntDfScale;
|
||||
vmode->xfbHeight = 480;
|
||||
vmode->viYOrigin = (VI_MAX_HEIGHT_PAL - 480)/2;
|
||||
vmode->viHeight = 480;
|
||||
|
||||
break;
|
||||
|
||||
case VI_NTSC: /* 480 lines (NTSC 60hz) */
|
||||
TV60hz_240p.viTVMode = VI_TVMODE_NTSC_DS;
|
||||
TV60hz_240i.viTVMode = VI_TVMODE_NTSC_INT;
|
||||
TV60hz_480i.viTVMode = VI_TVMODE_NTSC_INT;
|
||||
config.tv_mode = 0;
|
||||
gc_pal = 0;
|
||||
break;
|
||||
|
||||
default: /* 480 lines (PAL 60Hz) */
|
||||
TV60hz_240p.viTVMode = VI_TVMODE(vmode->viTVMode >> 2, VI_NON_INTERLACE);
|
||||
TV60hz_240i.viTVMode = VI_TVMODE(vmode->viTVMode >> 2, VI_INTERLACE);
|
||||
TV60hz_480i.viTVMode = VI_TVMODE(vmode->viTVMode >> 2, VI_INTERLACE);
|
||||
config.tv_mode = 2;
|
||||
gc_pal = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* configure video mode */
|
||||
VIDEO_Configure (vmode);
|
||||
|
||||
/* Configure the framebuffers (double-buffering) */
|
||||
xfb[0] = (u32 *) MEM_K0_TO_K1((u32 *) SYS_AllocateFramebuffer(&TV50hz_576i));
|
||||
xfb[1] = (u32 *) MEM_K0_TO_K1((u32 *) SYS_AllocateFramebuffer(&TV50hz_576i));
|
||||
|
||||
/* Define a console */
|
||||
console_init(xfb[0], 20, 64, 640, 574, 574 * 2);
|
||||
|
||||
/* Clear framebuffers to black */
|
||||
VIDEO_ClearFrameBuffer (vmode, xfb[0], COLOR_BLACK);
|
||||
VIDEO_ClearFrameBuffer (vmode, xfb[1], COLOR_BLACK);
|
||||
|
||||
/* Set the framebuffer to be displayed at next VBlank */
|
||||
VIDEO_SetNextFramebuffer (xfb[0]);
|
||||
|
||||
/* Register Video Retrace handlers */
|
||||
VIDEO_SetPreRetraceCallback(framestart);
|
||||
|
||||
/* Enable Video Interface */
|
||||
VIDEO_SetBlack (FALSE);
|
||||
|
||||
/* Update video settings for next VBlank */
|
||||
VIDEO_Flush ();
|
||||
|
||||
/* Wait for VBlank */
|
||||
VIDEO_WaitVSync();
|
||||
VIDEO_WaitVSync();
|
||||
|
||||
/* initialize GUI */
|
||||
unpackBackdrop ();
|
||||
init_font();
|
||||
|
||||
/* Initialize GX */
|
||||
gxStart();
|
||||
}
|
34
source/ngc/ogc_video.h
Normal file
34
source/ngc/ogc_video.h
Normal file
@ -0,0 +1,34 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* SMS Plus - Sega Master System / GameGear Emulator
|
||||
*
|
||||
* NGC/Wii Video support
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
***************************************************************************/
|
||||
#ifndef _GC_VIDEO_H_
|
||||
#define _GC_VIDEO_H_
|
||||
|
||||
extern void ogc_video__init(void);
|
||||
extern void ogc_video__update(void);
|
||||
extern void ogc_video__reset(void);
|
||||
|
||||
extern u8 gc_pal;
|
||||
extern unsigned int *xfb[2];
|
||||
extern int whichfb;
|
||||
extern GXRModeObj *tvmodes[6];
|
||||
extern GXRModeObj *vmode;
|
||||
|
||||
#endif
|
@ -6,12 +6,42 @@
|
||||
|
||||
#include <gccore.h>
|
||||
#include <ogcsys.h>
|
||||
#include <sdcard.h>
|
||||
#include <gcaram.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <fat.h>
|
||||
#include <sys/dir.h>
|
||||
|
||||
extern void error (char *format, ...);
|
||||
#include "ogc_input.h"
|
||||
#include "ogc_audio.h"
|
||||
#include "ogc_video.h"
|
||||
#include "config.h"
|
||||
#include "history.h"
|
||||
|
||||
#define update_input() ogc_input__update()
|
||||
|
||||
/* globals */
|
||||
extern u32 diff_usec(long long start,long long end);
|
||||
extern long long gettime();
|
||||
extern void error(char *format, ...);
|
||||
extern int getcompany();
|
||||
extern void reloadrom();
|
||||
extern void ClearGGCodes();
|
||||
extern void GetGGEntries();
|
||||
extern void legal();
|
||||
extern void MainMenu();
|
||||
extern void set_region();
|
||||
extern int ManageSRAM(u8 direction, u8 device);
|
||||
extern int ManageState(u8 direction, u8 device);
|
||||
extern void OpenDVD();
|
||||
extern int OpenSD();
|
||||
extern void OpenHistory();
|
||||
extern void memfile_autosave();
|
||||
extern void memfile_autoload();
|
||||
|
||||
extern int peripherals;
|
||||
extern int frameticker;
|
||||
extern int FramesPerSecond;
|
||||
|
||||
#endif /* _OSD_H_ */
|
||||
|
1863
source/ngc/png/crosshair-1.c
Normal file
1863
source/ngc/png/crosshair-1.c
Normal file
File diff suppressed because it is too large
Load Diff
14
source/ngc/png/crosshair-1.h
Normal file
14
source/ngc/png/crosshair-1.h
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
This file was autogenerated by raw2c.
|
||||
Visit http://www.devkitpro.org
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
#ifndef _crosshair-1_h_
|
||||
#define _crosshair-1_h_
|
||||
//---------------------------------------------------------------------------------
|
||||
extern const unsigned char crosshair-1[];
|
||||
extern const int crosshair-1_size;
|
||||
//---------------------------------------------------------------------------------
|
||||
#endif //_crosshair-1_h_
|
||||
//---------------------------------------------------------------------------------
|
BIN
source/ngc/png/crosshair-1.png
Normal file
BIN
source/ngc/png/crosshair-1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
1859
source/ngc/png/crosshair-2.c
Normal file
1859
source/ngc/png/crosshair-2.c
Normal file
File diff suppressed because it is too large
Load Diff
14
source/ngc/png/crosshair-2.h
Normal file
14
source/ngc/png/crosshair-2.h
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
This file was autogenerated by raw2c.
|
||||
Visit http://www.devkitpro.org
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
#ifndef _crosshair-2_h_
|
||||
#define _crosshair-2_h_
|
||||
//---------------------------------------------------------------------------------
|
||||
extern const unsigned char crosshair-2[];
|
||||
extern const int crosshair-2_size;
|
||||
//---------------------------------------------------------------------------------
|
||||
#endif //_crosshair-2_h_
|
||||
//---------------------------------------------------------------------------------
|
BIN
source/ngc/png/crosshair-2.png
Normal file
BIN
source/ngc/png/crosshair-2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
@ -1,34 +1,17 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
/******************************************************************************
|
||||
*
|
||||
* Nintendo Gamecube Zip Support
|
||||
*
|
||||
* Only partial support is included, in that only the first file within the archive
|
||||
* is considered to be a Genesis ROM image.
|
||||
* is considered to be a ROM image.
|
||||
***************************************************************************/
|
||||
#include <zlib.h>
|
||||
#include <sdcard.h>
|
||||
#include "shared.h"
|
||||
#include "dvd.h"
|
||||
#include "font.h"
|
||||
#include <zlib.h>
|
||||
|
||||
extern sd_file *filehandle;
|
||||
extern u8 UseSDCARD;
|
||||
/* SDCARD File access */
|
||||
extern FILE *sdfile;
|
||||
|
||||
/*
|
||||
* PKWare Zip Header - adopted into zip standard
|
||||
@ -95,7 +78,7 @@ int IsZipFile (char *buffer)
|
||||
*
|
||||
* It should be noted that there is a limit of 5MB total size for any ROM
|
||||
******************************************************************************/
|
||||
int UnZipBuffer (unsigned char *outbuffer, u64 discoffset, int length)
|
||||
int UnZipBuffer (unsigned char *outbuffer, u64 discoffset, int length, u8 UseSDCARD)
|
||||
{
|
||||
PKZIPHEADER pkzip;
|
||||
int zipoffset = 0;
|
||||
@ -111,10 +94,13 @@ int UnZipBuffer (unsigned char *outbuffer, u64 discoffset, int length)
|
||||
/*** Read Zip Header ***/
|
||||
if ( UseSDCARD )
|
||||
{
|
||||
SDCARD_SeekFile(filehandle, 0, SDCARD_SEEK_SET);
|
||||
SDCARD_ReadFile(filehandle, &readbuffer, 2048);
|
||||
fseek(sdfile, 0, SEEK_SET);
|
||||
fread(readbuffer, 1, 2048, sdfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
dvd_read (&readbuffer, 2048, discoffset);
|
||||
}
|
||||
else dvd_read (&readbuffer, 2048, discoffset);
|
||||
|
||||
/*** Copy PKZip header to local, used as info ***/
|
||||
memcpy (&pkzip, &readbuffer, sizeof (PKZIPHEADER));
|
||||
@ -169,17 +155,21 @@ int UnZipBuffer (unsigned char *outbuffer, u64 discoffset, int length)
|
||||
/*** Readup the next 2k block ***/
|
||||
zipoffset = 0;
|
||||
zipchunk = ZIPCHUNK;
|
||||
discoffset += 2048;
|
||||
|
||||
if (UseSDCARD) SDCARD_ReadFile(filehandle, &readbuffer, 2048);
|
||||
else dvd_read (&readbuffer, 2048, discoffset);
|
||||
if (UseSDCARD)
|
||||
{
|
||||
fread(readbuffer, 1, 2048, sdfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
discoffset += 2048;
|
||||
dvd_read (&readbuffer, 2048, discoffset);
|
||||
}
|
||||
}
|
||||
while (res != Z_STREAM_END);
|
||||
|
||||
inflateEnd (&zs);
|
||||
|
||||
if ( UseSDCARD ) SDCARD_CloseFile(filehandle);
|
||||
|
||||
if (res == Z_STREAM_END)
|
||||
{
|
||||
if (FLIP32 (pkzip.uncompressedSize) == (u32) bufferoffset) return bufferoffset;
|
||||
|
@ -1,193 +0,0 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Nintendo Gamecube Zip Support
|
||||
*
|
||||
* Only partial support is included, in that only the first file within the archive
|
||||
* is considered to be a Genesis ROM image.
|
||||
***************************************************************************/
|
||||
#include <zlib.h>
|
||||
#include <sdcard.h>
|
||||
#include "shared.h"
|
||||
#include "dvd.h"
|
||||
#include "font.h"
|
||||
#include "diskio.h"
|
||||
#include "vfat.h"
|
||||
|
||||
extern VFATFS fs;
|
||||
extern FSDIRENTRY f;
|
||||
extern u8 UseSDCARD;
|
||||
|
||||
/*
|
||||
* PKWare Zip Header - adopted into zip standard
|
||||
*/
|
||||
#define PKZIPID 0x504b0304
|
||||
#define MAXROM 0x500000
|
||||
#define ZIPCHUNK 2048
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/*
|
||||
* Zip files are stored little endian
|
||||
* Support functions for short and int types
|
||||
*/
|
||||
static inline 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;
|
||||
}
|
||||
|
||||
static inline 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;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* UnZipBuffer
|
||||
*
|
||||
* It should be noted that there is a limit of 5MB total size for any ROM
|
||||
******************************************************************************/
|
||||
int UnZipBuffer (unsigned char *outbuffer, u64 discoffset, int length)
|
||||
{
|
||||
PKZIPHEADER pkzip;
|
||||
int zipoffset = 0;
|
||||
int zipchunk = 0;
|
||||
char out[ZIPCHUNK];
|
||||
z_stream zs;
|
||||
int res;
|
||||
int bufferoffset = 0;
|
||||
int have = 0;
|
||||
char readbuffer[2048];
|
||||
char msg[128];
|
||||
|
||||
/*** Read Zip Header ***/
|
||||
if ( UseSDCARD )
|
||||
{
|
||||
VFAT_fseek(&f, 0, SEEK_SET);
|
||||
VFAT_fread(&f, readbuffer, 2048);
|
||||
}
|
||||
else dvd_read (&readbuffer, 2048, discoffset);
|
||||
|
||||
/*** Copy PKZip header to local, used as info ***/
|
||||
memcpy (&pkzip, &readbuffer, sizeof (PKZIPHEADER));
|
||||
|
||||
sprintf (msg, "Unzipping %d bytes ... Wait", FLIP32 (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;
|
||||
discoffset += 2048;
|
||||
|
||||
if (UseSDCARD) VFAT_fread(&f, readbuffer, 2048);
|
||||
else dvd_read (&readbuffer, 2048, discoffset);
|
||||
}
|
||||
while (res != Z_STREAM_END);
|
||||
|
||||
inflateEnd (&zs);
|
||||
|
||||
if ( UseSDCARD ) VFAT_fclose(&f);
|
||||
|
||||
if (res == Z_STREAM_END)
|
||||
{
|
||||
if (FLIP32 (pkzip.uncompressedSize) == (u32) bufferoffset) return bufferoffset;
|
||||
else return FLIP32 (pkzip.uncompressedSize);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,190 +0,0 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Nintendo Gamecube Zip Support
|
||||
*
|
||||
* Only partial support is included, in that only the first file within the archive
|
||||
* is considered to be a Genesis ROM image.
|
||||
***************************************************************************/
|
||||
#include <zlib.h>
|
||||
#include <sdcard.h>
|
||||
#include "shared.h"
|
||||
#include "dvd.h"
|
||||
#include "font.h"
|
||||
|
||||
extern sd_file *filehandle;
|
||||
extern u8 UseSDCARD;
|
||||
|
||||
/*
|
||||
* PKWare Zip Header - adopted into zip standard
|
||||
*/
|
||||
#define PKZIPID 0x504b0304
|
||||
#define MAXROM 0x500000
|
||||
#define ZIPCHUNK 2048
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/*
|
||||
* Zip files are stored little endian
|
||||
* Support functions for short and int types
|
||||
*/
|
||||
static inline 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;
|
||||
}
|
||||
|
||||
static inline 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;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* UnZipBuffer
|
||||
*
|
||||
* It should be noted that there is a limit of 5MB total size for any ROM
|
||||
******************************************************************************/
|
||||
int UnZipBuffer (unsigned char *outbuffer, u64 discoffset, int length)
|
||||
{
|
||||
PKZIPHEADER pkzip;
|
||||
int zipoffset = 0;
|
||||
int zipchunk = 0;
|
||||
char out[ZIPCHUNK];
|
||||
z_stream zs;
|
||||
int res;
|
||||
int bufferoffset = 0;
|
||||
int have = 0;
|
||||
char readbuffer[2048];
|
||||
char msg[128];
|
||||
|
||||
/*** Read Zip Header ***/
|
||||
if ( UseSDCARD )
|
||||
{
|
||||
SDCARD_SeekFile(filehandle, 0, SDCARD_SEEK_SET);
|
||||
SDCARD_ReadFile(filehandle, &readbuffer, 2048);
|
||||
}
|
||||
else dvd_read (&readbuffer, 2048, discoffset);
|
||||
|
||||
/*** Copy PKZip header to local, used as info ***/
|
||||
memcpy (&pkzip, &readbuffer, sizeof (PKZIPHEADER));
|
||||
|
||||
sprintf (msg, "Unzipping %d bytes ... Wait", FLIP32 (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;
|
||||
discoffset += 2048;
|
||||
|
||||
if (UseSDCARD) SDCARD_ReadFile(filehandle, &readbuffer, 2048);
|
||||
else dvd_read (&readbuffer, 2048, discoffset);
|
||||
}
|
||||
while (res != Z_STREAM_END);
|
||||
|
||||
inflateEnd (&zs);
|
||||
|
||||
if ( UseSDCARD ) SDCARD_CloseFile(filehandle);
|
||||
|
||||
if (res == Z_STREAM_END)
|
||||
{
|
||||
if (FLIP32 (pkzip.uncompressedSize) == (u32) bufferoffset) return bufferoffset;
|
||||
else return FLIP32 (pkzip.uncompressedSize);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,26 +1,14 @@
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
/******************************************************************************
|
||||
*
|
||||
* Nintendo Gamecube Zip Support
|
||||
*
|
||||
* Only partial support is included, in that only the first file within the archive
|
||||
* is considered to be a ROM image.
|
||||
***************************************************************************/
|
||||
#ifndef _UNZIP_H_
|
||||
#define _UNZIP_H_
|
||||
|
||||
extern int IsZipFile (char *buffer);
|
||||
int UnZipBuffer (unsigned char *outbuffer, u64 discoffset, int length);
|
||||
int UnZipBuffer (unsigned char *outbuffer, u64 discoffset, int length, u8 UseSDCARD);
|
||||
|
||||
#endif
|
||||
|
@ -1,99 +0,0 @@
|
||||
/****************************************************************************
|
||||
* FAT16 - VFAT Support
|
||||
*
|
||||
* NOTE: Only supports FAT16 with Long File Names
|
||||
* I have no interest in adding FAT32
|
||||
*
|
||||
* Reference Documentation:
|
||||
*
|
||||
* FAT: General Overview of On-Disk Format
|
||||
* Version 1.02 May 05, 1999
|
||||
* Microsoft Corporation
|
||||
*
|
||||
* FAT: General Overview of On-Disk Format
|
||||
* Version 1.03 December 06, 2000
|
||||
* Microsoft Corporation
|
||||
*
|
||||
* This is targetted at MMC/SD cards.
|
||||
*
|
||||
* Copyright softdev 2007. All rights reserved.
|
||||
*
|
||||
* Diskio Module
|
||||
* -------------
|
||||
*
|
||||
* This module is almost identical to the one found in ChaN's TinyFAT FS.
|
||||
* It's a logical abstration after all :)
|
||||
*
|
||||
* This covers stdio file on a SD image file
|
||||
****************************************************************************/
|
||||
#include <gccore.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sdcard.h>
|
||||
#include "vfat.h"
|
||||
|
||||
/* Not so public exports from card_io.c */
|
||||
#define MAX_DRIVE 2
|
||||
extern u8 g_CID[MAX_DRIVE][16];
|
||||
extern u8 g_CSD[MAX_DRIVE][16];
|
||||
extern u8 g_CardStatus[MAX_DRIVE][64];
|
||||
extern s32 card_initIO(s32 drv_no);
|
||||
extern s32 card_readSector(s32 drv_no,u32 sector_no,u8 *buf,u32 len);
|
||||
extern s32 card_writeSector(s32 drv_no,u32 sector_no,const void *buf,u32 len);
|
||||
extern s32 card_readStatus(s32 drv_no);
|
||||
#define CARDIO_ERROR_READY 0
|
||||
|
||||
/* End of not so public exports */
|
||||
|
||||
/****************************************************************************
|
||||
* DISKIO_Init
|
||||
*
|
||||
* Initialise communication with the disc
|
||||
****************************************************************************/
|
||||
int DISKIO_Init( int drive )
|
||||
{
|
||||
int res;
|
||||
|
||||
if ( drive < 0 || drive > 1 )
|
||||
return FS_ERR_PARAM;
|
||||
|
||||
res = card_initIO( drive );
|
||||
|
||||
if ( res == CARDIO_ERROR_READY )
|
||||
return FS_SUCCESS;
|
||||
|
||||
return FS_ERR_IO;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DISKIO_ReadSectors
|
||||
*
|
||||
* Read sectors from the disc
|
||||
****************************************************************************/
|
||||
int DISKIO_ReadSectors( int drive, void *buffer, int sector, int count )
|
||||
{
|
||||
int res = -1;
|
||||
int i;
|
||||
int bytes = 0;
|
||||
|
||||
if ( drive != 0 && drive != 1 )
|
||||
return FS_ERR_PARAM; /* Must be 0 or 1 */
|
||||
|
||||
/* libOGC appears to only read in single sectors */
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
res = card_readSector( (int)drive, sector + i, buffer + bytes, SECTOR_SIZE);
|
||||
if ( res != CARDIO_ERROR_READY )
|
||||
return FS_ERR_IO;
|
||||
bytes += SECTOR_SIZE;
|
||||
}
|
||||
|
||||
if ( res == CARDIO_ERROR_READY )
|
||||
return FS_SUCCESS;
|
||||
|
||||
return FS_ERR_IO;
|
||||
|
||||
}
|
||||
|
@ -1,36 +0,0 @@
|
||||
/****************************************************************************
|
||||
* FAT16 - VFAT Support
|
||||
*
|
||||
* NOTE: Only supports FAT16 with Long File Names
|
||||
* I have no interest in adding FAT32
|
||||
*
|
||||
* Reference Documentation:
|
||||
*
|
||||
* FAT: General Overview of On-Disk Format
|
||||
* Version 1.02 May 05, 1999
|
||||
* Microsoft Corporation
|
||||
*
|
||||
* FAT: General Overview of On-Disk Format
|
||||
* Version 1.03 December 06, 2000
|
||||
* Microsoft Corporation
|
||||
*
|
||||
* This is targetted at MMC/SD cards.
|
||||
*
|
||||
* Copyright softdev 2007. All rights reserved.
|
||||
*
|
||||
* Diskio Module
|
||||
* -------------
|
||||
*
|
||||
* This module is almost identical to the one found in ChaN's TinyFAT FS.
|
||||
* It's a logical abstration after all :)
|
||||
*
|
||||
* This covers stdio file on a SD image file
|
||||
****************************************************************************/
|
||||
#ifndef __DISKIO__
|
||||
#define __DISKIO__
|
||||
|
||||
int DISKIO_Init( int drive );
|
||||
int DISKIO_ReadSectors( int drive, void *buffer, int sector, int count );
|
||||
|
||||
#endif
|
||||
|
@ -1,841 +0,0 @@
|
||||
/****************************************************************************
|
||||
* FAT16 - VFAT Support
|
||||
*
|
||||
* NOTE: Only supports FAT16 with Long File Names
|
||||
* I have no interest in adding FAT32
|
||||
*
|
||||
* Reference Documentation:
|
||||
*
|
||||
* FAT: General Overview of On-Disk Format
|
||||
* Version 1.02 May 05, 1999
|
||||
* Microsoft Corporation
|
||||
*
|
||||
* FAT: General Overview of On-Disk Format
|
||||
* Version 1.03 December 06, 2000
|
||||
* Microsoft Corporation
|
||||
*
|
||||
* This is targetted at MMC/SD cards.
|
||||
*
|
||||
* Copyright softdev 2007. All rights reserved.
|
||||
*
|
||||
* $Date: 2007-08-03 13:23:19 +0100 (Fri, 03 Aug 2007) $
|
||||
* $Rev: 3 $
|
||||
****************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "vfat.h"
|
||||
#include "diskio.h"
|
||||
|
||||
static BYTE sector[SECTOR_SIZE]; /* Local sector buffer */
|
||||
static VFATFS *vfs[2]; /* VFAT Pointers for 2 drives */
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define strcasecmp stricmp
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Z E R O S E C T O R / B I O S P A R A M E T E R B L O C K
|
||||
*
|
||||
* These functions take care of parsing the 0th sector/BPB
|
||||
* Supports SuperFloppy Format and standard partitioning.
|
||||
*
|
||||
*/
|
||||
|
||||
static int BPBCheck( BYTE *sector )
|
||||
{
|
||||
BPB16 *bpb = (BPB16 *)sector;
|
||||
|
||||
/* Check signatures */
|
||||
if ( ( bpb->sigkey1 == 0x55 ) && ( bpb->sigkey2 == 0xAA ) )
|
||||
{
|
||||
/* Check for FAT16 signature */
|
||||
if ( memcmp(bpb->FilSysType, "FAT16", 5) == 0 )
|
||||
return FS_TYPE_FAT16;
|
||||
/* Non MS utilities simply put FAT */
|
||||
if ( memcmp(bpb->FilSysType, "FAT", 3) == 0 )
|
||||
return FS_TYPE_FAT16;
|
||||
}
|
||||
|
||||
return FS_TYPE_NONE;
|
||||
}
|
||||
|
||||
static int PECheck( BYTE *sector )
|
||||
{
|
||||
int i;
|
||||
PARTENTRY *pe;
|
||||
|
||||
if ( ( sector[SECTOR_SIZE-2] == 0x55 ) && ( sector[SECTOR_SIZE-1] == 0xAA ) )
|
||||
{
|
||||
/* Find a FAT16 partition entry */
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
pe = (PARTENTRY *)(sector + 446 + (i<<4));
|
||||
if ( pe->partitiontype == 0x06 )
|
||||
{
|
||||
return SWAP32(pe->partitionstart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FS_TYPE_NONE;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_Mount
|
||||
*
|
||||
* Function to mount a FAT16-VFAT volume
|
||||
***************************************************************************/
|
||||
int VFAT_mount( int driveid, VFATFS *v )
|
||||
{
|
||||
int ret;
|
||||
int bpbsector = 0;
|
||||
BPB16 *bpb = (BPB16 *)sector;
|
||||
BYTE media = 0;
|
||||
|
||||
if ( driveid < 0 || driveid > 1 )
|
||||
return FS_TYPE_NONE;
|
||||
|
||||
memset(v, 0, sizeof(VFATFS));
|
||||
|
||||
/* Copy pointer */
|
||||
vfs[driveid] = v;
|
||||
|
||||
if ( DISKIO_Init( driveid ) != FS_SUCCESS )
|
||||
return FS_ERR_IO;
|
||||
|
||||
if ( DISKIO_ReadSectors( driveid, sector, 0, 1 ) != FS_SUCCESS )
|
||||
return FS_ERR_IO;
|
||||
|
||||
/* Check for SuperFloppy Format */
|
||||
ret = BPBCheck( sector );
|
||||
|
||||
if ( ret == FS_TYPE_NONE )
|
||||
{
|
||||
/* Check for Partition Entry */
|
||||
bpbsector = PECheck(sector);
|
||||
if ( !bpbsector )
|
||||
return FS_TYPE_NONE;
|
||||
|
||||
if ( DISKIO_ReadSectors( driveid, sector, bpbsector, 1 ) != FS_SUCCESS )
|
||||
return FS_ERR_IO;
|
||||
|
||||
/* Check BPB */
|
||||
ret = BPBCheck( sector );
|
||||
}
|
||||
|
||||
if ( ret == FS_TYPE_FAT16 )
|
||||
{
|
||||
/* Capture defaults to machine native format */
|
||||
v->BaseOffset = bpbsector;
|
||||
v->BytesPerSector = SWAP16(bpb->bytesPerSec);
|
||||
v->SectorsPerFAT = SWAP16(bpb->FATsz16);
|
||||
v->ReservedSectors = SWAP16(bpb->reservedSec);
|
||||
v->NumberOfFATs = bpb->numFATs;
|
||||
v->SectorsPerCluster = bpb->secPerClust;
|
||||
v->RootDirEntries = SWAP16(bpb->rootEntCount);
|
||||
|
||||
/* Calculate number of root directory sectors */
|
||||
v->RootDirSectors = ( ( SWAP16(bpb->rootEntCount) << 5 ) + ( v->BytesPerSector - 1 ) ) / v->BytesPerSector;
|
||||
|
||||
/* First data sector */
|
||||
v->FirstDataSector = v->ReservedSectors + (v->NumberOfFATs * v->SectorsPerFAT) + v->RootDirSectors + v->BaseOffset;
|
||||
|
||||
/* Total sectors */
|
||||
if ( bpb->totSec16 == 0 )
|
||||
v->TotalSectors = SWAP32(bpb->totSec32);
|
||||
else
|
||||
v->TotalSectors = SWAP16(bpb->totSec16);
|
||||
|
||||
/* Data Sectors */
|
||||
v->DataSectors = v->TotalSectors - ( v->ReservedSectors + ( v->NumberOfFATs * v->SectorsPerFAT ) + v->RootDirSectors );
|
||||
|
||||
/* Count of clusters */
|
||||
v->CountOfClusters = v->DataSectors / bpb->secPerClust;
|
||||
|
||||
/* From v1.03 Document - Page 14 - FAT Type Determination */
|
||||
if ( v->CountOfClusters < 4085 )
|
||||
return FS_TYPE_NONE; /* FAT12 Volume */
|
||||
else
|
||||
{
|
||||
if ( v->CountOfClusters >= 65525 )
|
||||
return FS_TYPE_NONE; /* FAT32 Volume */
|
||||
}
|
||||
|
||||
/* Root Directory Offset */
|
||||
v->RootDirOffset = v->ReservedSectors + ( bpb->numFATs * v->SectorsPerFAT ) + v->BaseOffset;
|
||||
|
||||
/* First copy of FAT offset */
|
||||
v->FirstFATOffset = v->ReservedSectors + v->BaseOffset;
|
||||
|
||||
media = bpb->media;
|
||||
|
||||
/* Read first FAT */
|
||||
if ( DISKIO_ReadSectors( driveid, sector, v->FirstFATOffset, 1 ) != FS_SUCCESS )
|
||||
return FS_ERR_IO;
|
||||
|
||||
if ( sector[0] == media )
|
||||
{
|
||||
/* Allocate work spaces */
|
||||
v->FAT = (WORD *)malloc(v->SectorsPerFAT * SECTOR_SIZE);
|
||||
if ( v->FAT == NULL )
|
||||
return FS_ERR_NOMEM;
|
||||
|
||||
/* Save time running in and out - just load up the FAT table */
|
||||
if ( DISKIO_ReadSectors(driveid, v->FAT, v->FirstFATOffset, v->SectorsPerFAT) != FS_SUCCESS )
|
||||
{
|
||||
free(v->FAT);
|
||||
return FS_ERR_IO;
|
||||
}
|
||||
|
||||
/* Likewise, the same for the root directory */
|
||||
v->rootDir = (BYTE *)malloc(v->BytesPerSector * v->RootDirSectors);
|
||||
if ( v->rootDir == NULL )
|
||||
{
|
||||
free(v->FAT);
|
||||
return FS_ERR_NOMEM;
|
||||
}
|
||||
|
||||
/* Read root directory */
|
||||
if ( DISKIO_ReadSectors(driveid, v->rootDir, v->RootDirOffset, v->RootDirSectors) != FS_SUCCESS )
|
||||
{
|
||||
free(v->FAT);
|
||||
free(v->rootDir);
|
||||
return FS_ERR_IO;
|
||||
}
|
||||
return FS_TYPE_FAT16;
|
||||
}
|
||||
}
|
||||
|
||||
return FS_TYPE_NONE;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* F I L E N A M I N G S U P P O R T
|
||||
*
|
||||
* Routines to en/decode long and short file names
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* CalcShortNameChecksum
|
||||
*
|
||||
* Calculate the checksum for a short filename
|
||||
* Filename should be in UPPER case, and padded with spaces to match
|
||||
* a standard directory entry
|
||||
****************************************************************************/
|
||||
static unsigned char CalcShortNameCheckSum( BYTE *fname )
|
||||
{
|
||||
int i;
|
||||
unsigned char sum = 0;
|
||||
|
||||
for( i = 0; i < 11; i++ )
|
||||
sum = ( ( sum & 1 ) ? 0x80 : 0 ) + ( sum >> 1 ) + fname[i];
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* BuildShortNameFromDirEntry
|
||||
*
|
||||
* User friendly shortname
|
||||
****************************************************************************/
|
||||
static void BuildShortNameFromDirEntry( SFNDIRREC *sfn, BYTE *out )
|
||||
{
|
||||
int i,j;
|
||||
|
||||
for(i = 0, j = 0; i < 11; i++ )
|
||||
{
|
||||
if ( sfn->dirname[i] != 32 )
|
||||
{
|
||||
out[j++] = sfn->dirname[i];
|
||||
}
|
||||
|
||||
if ( (i == 7) && ( sfn->dirname[8] != 32 ) )
|
||||
out[j++] = '.';
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* BuildLongNameFromDirEntry
|
||||
*
|
||||
* Build a long name from unicode to asciiz.
|
||||
* Each directory entry may contain up to 13 characters for sub entry.
|
||||
****************************************************************************/
|
||||
static void BuildLongNameFromDirEntry( LFNDIRREC *lfn, int position, BYTE *out )
|
||||
{
|
||||
int j = ( ( position - 1 ) * 13 );
|
||||
int i;
|
||||
|
||||
/* Part one */
|
||||
for( i = 0; i < 10; i += 2 )
|
||||
{
|
||||
if ( lfn->dirname1[i] == 0xFF )
|
||||
return;
|
||||
|
||||
out[j++] = lfn->dirname1[i];
|
||||
}
|
||||
|
||||
/* Part two */
|
||||
for( i = 0; i < 12; i += 2 )
|
||||
{
|
||||
if ( lfn->dirname2[i] == 0xFF )
|
||||
return;
|
||||
|
||||
out[j++] = lfn->dirname2[i];
|
||||
}
|
||||
|
||||
/* Part three */
|
||||
for( i = 0; i < 4; i += 2 )
|
||||
{
|
||||
if ( lfn->dirname3[i] == 0xFF )
|
||||
return;
|
||||
|
||||
out[j++] = lfn->dirname3[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* D I R E C T O R Y F U N C T I O N S
|
||||
*
|
||||
* These routines take care of all directory level parsing
|
||||
*/
|
||||
|
||||
static int SectorFromCluster( int drive, int cluster )
|
||||
{
|
||||
VFATFS *v = vfs[drive];
|
||||
return ( ( cluster - 2 ) * v->SectorsPerCluster ) + v->FirstDataSector;
|
||||
}
|
||||
|
||||
static int ReadCluster( FSDIRENTRY *d )
|
||||
{
|
||||
int sector;
|
||||
|
||||
sector = SectorFromCluster( d->driveid, d->CurrentCluster );
|
||||
if ( DISKIO_ReadSectors( d->driveid, d->clusterdata, sector, vfs[d->driveid]->SectorsPerCluster) != FS_SUCCESS )
|
||||
return FS_ERR_IO;
|
||||
|
||||
d->CachedCluster = d->CurrentCluster;
|
||||
return FS_SUCCESS;
|
||||
}
|
||||
|
||||
static int NextCluster( FSDIRENTRY *d )
|
||||
{
|
||||
d->CurrentCluster = SWAP16(vfs[d->driveid]->FAT[d->CurrentCluster]);
|
||||
if ( d->CurrentCluster >= CLUSTER_END_CHAIN )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* FindEntry
|
||||
*
|
||||
* Look through a directory tree looking for an active entry.
|
||||
* The current cluster should be available in d->clusterdata
|
||||
****************************************************************************/
|
||||
static int FindEntry( FSDIRENTRY *d, int maxentries )
|
||||
{
|
||||
int found = 0;
|
||||
unsigned char *direntry;
|
||||
VFATFS *v = vfs[d->driveid];
|
||||
SFNDIRREC *sfn;
|
||||
LFNDIRREC *lfn;
|
||||
static BYTE checksum = 0;
|
||||
|
||||
if ( !d->crosscluster )
|
||||
{
|
||||
/* Clear names */
|
||||
memset(d->shortname, 0, 13);
|
||||
memset(d->longname, 0, MAX_LONG_NAME);
|
||||
}
|
||||
|
||||
while( d->CurrentDirEntry < maxentries && !found )
|
||||
{
|
||||
/* Pointer to this directory entry */
|
||||
if ( d->CurrentCluster == ROOTCLUSTER )
|
||||
direntry = (v->rootDir + ( d->CurrentDirEntry << 5 ) );
|
||||
else
|
||||
direntry = (d->clusterdata + ( d->CurrentDirEntry << 5 ) );
|
||||
|
||||
switch( direntry[0] )
|
||||
{
|
||||
case 0x00:
|
||||
case 0xE5:
|
||||
break; /* Inactive entries */
|
||||
|
||||
default:
|
||||
|
||||
sfn = (SFNDIRREC *)direntry;
|
||||
d->crosscluster = 1;
|
||||
|
||||
if ( ( sfn->attribute & ATTR_LONG_NAME_MASK ) == ATTR_LONG_NAME )
|
||||
{
|
||||
if ( direntry[0] & LFN_LAST_ENTRY )
|
||||
memset(&d->longname, 0, MAX_LONG_NAME);
|
||||
|
||||
lfn = (LFNDIRREC *)direntry;
|
||||
BuildLongNameFromDirEntry( lfn, direntry[0] & LFN_ENTRY_MASK, d->longname);
|
||||
checksum = lfn->checksum;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Short name entry */
|
||||
found = 1;
|
||||
memcpy(&d->dirent, direntry, 32);
|
||||
BuildShortNameFromDirEntry( sfn, d->shortname );
|
||||
d->fsize = SWAP32(sfn->filesize);
|
||||
d->crosscluster = 0;
|
||||
/* Ensure long name is populated with something */
|
||||
if ( strlen((char *)d->longname) == 0 )
|
||||
{
|
||||
strcpy((char *)d->longname, (char *)d->shortname);
|
||||
return found;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If checksums don't match - the FS is inconsistent
|
||||
To do no harm, skip this entry */
|
||||
if ( checksum == CalcShortNameCheckSum(sfn->dirname) )
|
||||
return found;
|
||||
else
|
||||
found = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d->CurrentDirEntry++;
|
||||
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* FindInRootDirectory
|
||||
*
|
||||
* Root directory is somewhat special. It's a fixed length and has no entry
|
||||
* in the FAT as such.
|
||||
*
|
||||
* Logically, this should be the first 2 clusters, but the spec says it can
|
||||
* be set to any size by the format utility (Think NT! FAT64/128/256)
|
||||
*
|
||||
* For speed, as all searches begin here, the root directory is held in
|
||||
* memory throughout.
|
||||
*
|
||||
* FSDIRENTRY should only have the drive id set.
|
||||
****************************************************************************/
|
||||
static int FindInRootDirectory( FSDIRENTRY *d, char *search )
|
||||
{
|
||||
int found = 0;
|
||||
|
||||
d->CurrentDirEntry++;
|
||||
|
||||
while( (FindEntry(d, vfs[d->driveid]->RootDirEntries)) && !found )
|
||||
{
|
||||
if ( strcasecmp(search, (char *) d->shortname) == 0 )
|
||||
{
|
||||
found = 1;
|
||||
}
|
||||
|
||||
if ( strcasecmp(search, (char *) d->longname) == 0 )
|
||||
{
|
||||
found = 1;
|
||||
}
|
||||
|
||||
if ( !found )
|
||||
d->CurrentDirEntry++;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* FindInClusters
|
||||
*
|
||||
* Generic routine to find a given name in a chain of clusters.
|
||||
* Used for non-Root Directory searching
|
||||
****************************************************************************/
|
||||
static int FindInClusters( FSDIRENTRY *d, char *findme )
|
||||
{
|
||||
int found = 0;
|
||||
|
||||
if ( d->CurrentDirEntry == -1 )
|
||||
d->CurrentDirEntry = 0;
|
||||
|
||||
/* While not at end of chain */
|
||||
while( !found && ( d->CurrentCluster < CLUSTER_END_CHAIN ) )
|
||||
{
|
||||
/* Retrieve dir entries looking for match */
|
||||
while( !found && (FindEntry( d, ( vfs[d->driveid]->BytesPerSector * vfs[d->driveid]->SectorsPerCluster) >> 5 ) ) )
|
||||
{
|
||||
if ( strcasecmp((char *)d->shortname, findme) == 0 )
|
||||
found = 1;
|
||||
if ( strcasecmp((char *)d->longname, findme) == 0 )
|
||||
found = 1;
|
||||
|
||||
if (!found)
|
||||
d->CurrentDirEntry++;
|
||||
}
|
||||
|
||||
/* Read next cluster */
|
||||
if ( !found )
|
||||
{
|
||||
if ( NextCluster(d) )
|
||||
{
|
||||
d->CurrentDirEntry = 0;
|
||||
ReadCluster(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_opendir
|
||||
*
|
||||
* Find the requested directory.
|
||||
****************************************************************************/
|
||||
int VFAT_opendir( int drive, FSDIRENTRY *d, char *search )
|
||||
{
|
||||
char *p;
|
||||
char srchtmp[1024];
|
||||
int searchroot = 1;
|
||||
int found = 0;
|
||||
|
||||
/* Clear out FSDIRENTRY */
|
||||
memset(d, 0, sizeof(FSDIRENTRY));
|
||||
|
||||
/* Set drive and root */
|
||||
d->driveid = drive;
|
||||
d->CurrentCluster = ROOTCLUSTER;
|
||||
d->CurrentDirEntry = -1;
|
||||
|
||||
/* Is this a request for root ? */
|
||||
if ( ( strlen(search) == 0 ) || ( strcmp(search,PSEPS) == 0 ) || ( strcmp(search, DIR_ROOT) == 0 ) )
|
||||
{
|
||||
return FS_FILE_OK;
|
||||
}
|
||||
|
||||
/* Searching for a sub-directory */
|
||||
if ( search[0] == PSEP )
|
||||
strcpy(srchtmp, &search[1]);
|
||||
else
|
||||
strcpy(srchtmp, search);
|
||||
|
||||
p = strtok(srchtmp, PSEPS);
|
||||
while ( p )
|
||||
{
|
||||
found = 0;
|
||||
if ( searchroot )
|
||||
{
|
||||
if ( !FindInRootDirectory(d, p) )
|
||||
return FS_NO_FILE;
|
||||
else
|
||||
{
|
||||
/* MUST be a directory */
|
||||
if ( d->dirent.attribute & ATTR_DIRECTORY )
|
||||
{
|
||||
d->CurrentCluster = d->FirstCluster = SWAP16(d->dirent.fstClustLow);
|
||||
d->CurrentDirEntry = -1;
|
||||
|
||||
/* Allocate the cluster for this data record */
|
||||
d->clusterdata = (BYTE *)malloc(vfs[d->driveid]->SectorsPerCluster * vfs[d->driveid]->BytesPerSector);
|
||||
ReadCluster(d);
|
||||
found = 1;
|
||||
searchroot = 0;
|
||||
}
|
||||
else
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( FindInClusters( d, p ) )
|
||||
{
|
||||
/* MUST be a directory */
|
||||
if ( !( d->dirent.attribute & ATTR_DIRECTORY ) )
|
||||
{
|
||||
free(d->clusterdata);
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
|
||||
/* Read up this cluster */
|
||||
d->CurrentCluster = d->FirstCluster = SWAP16(d->dirent.fstClustLow);
|
||||
d->CurrentDirEntry = 0;
|
||||
ReadCluster(d);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
p = strtok(NULL, PSEPS);
|
||||
}
|
||||
|
||||
if ( !found )
|
||||
{
|
||||
if ( d->clusterdata != NULL )
|
||||
{
|
||||
free(d->clusterdata);
|
||||
d->clusterdata = NULL;
|
||||
}
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
|
||||
return FS_FILE_OK;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_readdir
|
||||
****************************************************************************/
|
||||
int VFAT_readdir( FSDIRENTRY *d )
|
||||
{
|
||||
int ret;
|
||||
|
||||
d->CurrentDirEntry++;
|
||||
/* Are we in root ? */
|
||||
if ( d->CurrentCluster == ROOTCLUSTER )
|
||||
{
|
||||
if( FindEntry( d, vfs[d->driveid]->RootDirEntries ) )
|
||||
return FS_FILE_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
while( d->CurrentCluster < CLUSTER_END_CHAIN )
|
||||
{
|
||||
ret = FindEntry( d, ( vfs[d->driveid]->BytesPerSector * vfs[d->driveid]->SectorsPerCluster) >> 5 );
|
||||
|
||||
if ( ret )
|
||||
return FS_FILE_OK;
|
||||
|
||||
if ( NextCluster(d) )
|
||||
{
|
||||
d->CurrentDirEntry = 0;
|
||||
ReadCluster(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_closedir
|
||||
****************************************************************************/
|
||||
void VFAT_closedir( FSDIRENTRY *d )
|
||||
{
|
||||
if ( d->clusterdata != NULL )
|
||||
{
|
||||
free(d->clusterdata);
|
||||
d->clusterdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_fopen
|
||||
*
|
||||
* v0.1 - VFAT_READ_ONLY Supported
|
||||
****************************************************************************/
|
||||
int VFAT_fopen( int drive, FSDIRENTRY *d, char *fname, int mode )
|
||||
{
|
||||
char filename[1024];
|
||||
char path[1024];
|
||||
char temp[1024];
|
||||
char *p;
|
||||
|
||||
if ( drive < 0 || drive > 1 )
|
||||
return FS_NO_FILE;
|
||||
|
||||
if ( mode != FS_READ )
|
||||
return FS_NO_FILE;
|
||||
|
||||
/* Clear */
|
||||
memset(d, 0, sizeof(FSDIRENTRY));
|
||||
d->driveid = drive;
|
||||
|
||||
path[0] = temp[0] = filename[0] = 0;
|
||||
|
||||
if ( fname[0] == PSEP )
|
||||
strcpy(temp, &fname[1]);
|
||||
else
|
||||
strcpy(temp, fname);
|
||||
|
||||
/* Split into filename and path */
|
||||
p = strrchr(temp, PSEP);
|
||||
if ( p )
|
||||
{
|
||||
/* Have path and filename */
|
||||
*p = 0;
|
||||
strcpy(path, temp);
|
||||
p++;
|
||||
strcpy(filename, p);
|
||||
}
|
||||
else
|
||||
strcpy(filename, temp);
|
||||
|
||||
/* Do search */
|
||||
if ( strlen(path) )
|
||||
{
|
||||
if ( VFAT_opendir(drive, d, path) != FS_FILE_OK )
|
||||
{
|
||||
VFAT_closedir(d);
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
|
||||
if ( !FindInClusters( d, filename ) )
|
||||
{
|
||||
VFAT_closedir(d);
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Much simpler check on root directory */
|
||||
d->CurrentCluster = ROOTCLUSTER;
|
||||
d->CurrentDirEntry = -1;
|
||||
if ( !FindInRootDirectory( d, filename ) )
|
||||
{
|
||||
VFAT_closedir(d);
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
d->clusterdata = (BYTE *)malloc(vfs[d->driveid]->SectorsPerCluster * vfs[d->driveid]->BytesPerSector);
|
||||
}
|
||||
|
||||
/* Must be a file only */
|
||||
if ( d->dirent.attribute & ( ATTR_DIRECTORY | ATTR_VOLUME_ID ) )
|
||||
{
|
||||
VFAT_closedir(d);
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
|
||||
d->FirstCluster = d->CurrentCluster = SWAP16(d->dirent.fstClustLow);
|
||||
d->CachedCluster = -1;
|
||||
|
||||
return FS_FILE_OK;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_fclose
|
||||
****************************************************************************/
|
||||
void VFAT_fclose( FSDIRENTRY *d )
|
||||
{
|
||||
VFAT_closedir(d);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_fread
|
||||
****************************************************************************/
|
||||
int VFAT_fread( FSDIRENTRY *d, void *buffer, int length )
|
||||
{
|
||||
int cluster;
|
||||
int tbytes;
|
||||
int umask;
|
||||
int i;
|
||||
int bytesdone = 0;
|
||||
int reallength;
|
||||
BYTE *p = (BYTE *)buffer;
|
||||
|
||||
if ( length <= 0 )
|
||||
return 0;
|
||||
|
||||
/* Determine which cluster in the chain we are in */
|
||||
tbytes = ( vfs[d->driveid]->SectorsPerCluster * vfs[d->driveid]->BytesPerSector );
|
||||
umask = tbytes - 1;
|
||||
cluster = ( d->fpos / tbytes );
|
||||
|
||||
/* Rewind current cluster */
|
||||
d->CurrentCluster = d->FirstCluster;
|
||||
|
||||
/* Bring this cluster into view */
|
||||
for ( i = 0; i < cluster; i++ )
|
||||
d->CurrentCluster = SWAP16(vfs[d->driveid]->FAT[d->CurrentCluster]);
|
||||
|
||||
/* Read the cluster */
|
||||
if ( d->CachedCluster != d->CurrentCluster )
|
||||
ReadCluster(d);
|
||||
|
||||
/* Get real read length */
|
||||
reallength = ( d->fpos + length ) < d->fsize ? length : d->fsize - d->fpos;
|
||||
|
||||
if ( reallength <= 0 )
|
||||
return 0;
|
||||
|
||||
/* Move data */
|
||||
while( reallength )
|
||||
{
|
||||
if ( !(d->fpos & umask) && ( reallength >= tbytes ) )
|
||||
{
|
||||
/* Move a full cluster */
|
||||
memcpy(p + bytesdone, d->clusterdata, tbytes);
|
||||
reallength -= tbytes;
|
||||
bytesdone += tbytes;
|
||||
d->fpos += tbytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
p[bytesdone++] = d->clusterdata[d->fpos & umask];
|
||||
d->fpos++;
|
||||
reallength--;
|
||||
}
|
||||
|
||||
if ( !( d->fpos & umask ) )
|
||||
{
|
||||
if ( NextCluster(d) )
|
||||
{
|
||||
ReadCluster(d);
|
||||
}
|
||||
else
|
||||
return bytesdone;
|
||||
}
|
||||
}
|
||||
|
||||
return bytesdone;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_fseek
|
||||
****************************************************************************/
|
||||
int VFAT_fseek( FSDIRENTRY *d, int where, int whence )
|
||||
{
|
||||
switch( whence )
|
||||
{
|
||||
case SEEK_SET:
|
||||
if ( ( where >= 0 ) && ( where <= d->fsize ) )
|
||||
{
|
||||
d->fpos = where;
|
||||
return FS_FILE_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
if ( ( ( d->fpos + where ) >= 0 ) && ( ( d->fpos + where ) <= d->fsize ) )
|
||||
{
|
||||
d->fpos += where;
|
||||
return FS_FILE_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
if ( ( where <= 0 ) && ( abs(where) <= d->fsize ) )
|
||||
{
|
||||
d->fpos = d->fsize + where;
|
||||
return FS_FILE_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FS_NO_FILE;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* VFAT_ftell
|
||||
*
|
||||
* Return the current position of a file
|
||||
****************************************************************************/
|
||||
int VFAT_ftell( FSDIRENTRY *d )
|
||||
{
|
||||
return d->fpos;
|
||||
}
|
||||
|
@ -1,226 +0,0 @@
|
||||
/****************************************************************************
|
||||
* FAT16 - VFAT Support
|
||||
*
|
||||
* NOTE: Only supports FAT16 with Long File Names
|
||||
* I have no interest in adding FAT32
|
||||
*
|
||||
* Reference Documentation:
|
||||
*
|
||||
* FAT: General Overview of On-Disk Format
|
||||
* Version 1.02 May 05, 1999
|
||||
* Microsoft Corporation
|
||||
*
|
||||
* FAT: General Overview of On-Disk Format
|
||||
* Version 1.03 December 06, 2000
|
||||
* Microsoft Corporation
|
||||
*
|
||||
* This is targetted at MMC/SD cards.
|
||||
*
|
||||
* Copyright softdev 2007. All rights reserved.
|
||||
*
|
||||
* $Date: 2007-08-03 13:23:19 +0100 (Fri, 03 Aug 2007) $
|
||||
* $Rev: 3 $
|
||||
****************************************************************************/
|
||||
#ifndef __FATVFAT__
|
||||
#define __FATVFAT__
|
||||
|
||||
/* x86 type definitions */
|
||||
typedef unsigned int DWORD;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
/* Big Endian Support */
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define SWAP16(a) (((a&0xff)<<8) | ((a&0xff00)>>8))
|
||||
#define SWAP32(a) (((a&0xff000000)>>24) | ((a&0xff0000) >> 8) | ((a&0xff00)<<8) |((a&0xff)<<24))
|
||||
#else
|
||||
#define SWAP16(a) (a)
|
||||
#define SWAP32(a) (a)
|
||||
#endif
|
||||
|
||||
/* General */
|
||||
#define SECTOR_SIZE 512
|
||||
#define SECTOR_SHIFT_BITS 9
|
||||
#define LFN_LAST_ENTRY 0x40
|
||||
#define LFN_ENTRY_MASK 0x3F
|
||||
#define ROOTCLUSTER 0xdeadc0de
|
||||
#define PSEP '/'
|
||||
#define PSEPS "/"
|
||||
#define DIR_ROOT "."
|
||||
#define DIR_PARENT ".."
|
||||
|
||||
/* FSTYPES */
|
||||
#define FS_TYPE_NONE 0
|
||||
#define FS_TYPE_FAT16 1
|
||||
|
||||
/* Errors */
|
||||
#define FS_FILE_OK 0
|
||||
#define FS_SUCCESS FS_FILE_OK
|
||||
#define FS_ERR_NOMEM -128
|
||||
#define FS_NO_FILE -64
|
||||
#define FS_ERR_IO -32
|
||||
#define FS_ERR_PARAM -16
|
||||
|
||||
/* File modes */
|
||||
#define FS_READ 1
|
||||
|
||||
/* Gamecube Specific */
|
||||
#define FS_SLOTA 0
|
||||
#define FS_SLOTB 1
|
||||
|
||||
/* FAT12/16 */
|
||||
typedef struct
|
||||
{
|
||||
BYTE jmpBoot[3]; /* Always 0xEBxx90 or 0xE9xxxx */
|
||||
BYTE OEMName[8]; /* OEM Name 'MSWIN4.1' or similar */
|
||||
WORD bytesPerSec; /* Bytes per sector */
|
||||
BYTE secPerClust; /* Sectors per cluster */
|
||||
WORD reservedSec; /* Reserved Sector Count */
|
||||
BYTE numFATs; /* Number of FAT copies */
|
||||
WORD rootEntCount; /* FAT12/16 number of root entries. */
|
||||
WORD totSec16; /* Sector count if < 0x10000 */
|
||||
BYTE media; /* Media ID byte (HD == 0xF8) */
|
||||
WORD FATsz16; /* Sectors occupied by one copy of FAT */
|
||||
WORD secPerTrack; /* Sectors per track */
|
||||
WORD numHeads; /* Number of heads */
|
||||
DWORD hiddenSec; /* Hidden sector count */
|
||||
DWORD totSec32; /* Total sectors when >= 0x10000 */
|
||||
BYTE drvNum; /* BIOS Drive Number (0x80) */
|
||||
BYTE reserved1; /* Unused - always zero */
|
||||
BYTE bootSig; /* Boot signature */
|
||||
DWORD volID; /* Volume serial number */
|
||||
BYTE volName[11]; /* Volume Name */
|
||||
BYTE FilSysType[8]; /* File system type */
|
||||
BYTE filler[SECTOR_SIZE-64];
|
||||
BYTE sigkey1; /* 0x55 */
|
||||
BYTE sigkey2; /* 0xAA */
|
||||
}
|
||||
__attribute__((__packed__)) BPB16;
|
||||
|
||||
/* Partition entry */
|
||||
typedef struct
|
||||
{
|
||||
BYTE bootindicator;
|
||||
BYTE startCHS[3];
|
||||
BYTE partitiontype;
|
||||
BYTE endCHS[3];
|
||||
DWORD partitionstart;
|
||||
DWORD partitionsize;
|
||||
}
|
||||
__attribute__((__packed__)) PARTENTRY;
|
||||
|
||||
/* VFAT - Main structure */
|
||||
typedef struct
|
||||
{
|
||||
DWORD BaseOffset;
|
||||
DWORD SectorsPerCluster;
|
||||
DWORD BytesPerSector;
|
||||
DWORD ReservedSectors;
|
||||
DWORD RootDirSectors;
|
||||
DWORD SectorsPerFAT;
|
||||
DWORD NumberOfFATs;
|
||||
DWORD FirstDataSector;
|
||||
DWORD TotalSectors;
|
||||
DWORD CountOfClusters;
|
||||
DWORD DataSectors;
|
||||
DWORD RootDirOffset;
|
||||
DWORD FirstFATOffset;
|
||||
DWORD RootDirEntries;
|
||||
WORD *FAT; /* Holds first FAT copy */
|
||||
BYTE *rootDir; /* Holds entire root directory */
|
||||
}
|
||||
__attribute__((__packed__)) VFATFS;
|
||||
|
||||
/**
|
||||
* Directory
|
||||
*/
|
||||
|
||||
#define MAX_LONG_NAME 256
|
||||
|
||||
/* Directory entry attributes */
|
||||
#define ATTR_READ_ONLY 0x01
|
||||
#define ATTR_HIDDEN 0x02
|
||||
#define ATTR_SYSTEM 0x04
|
||||
#define ATTR_VOLUME_ID 0x08
|
||||
#define ATTR_DIRECTORY 0x10
|
||||
#define ATTR_ARCHIVE 0x20
|
||||
#define ATTR_LONG_NAME (ATTR_READ_ONLY | \
|
||||
ATTR_HIDDEN | \
|
||||
ATTR_SYSTEM | \
|
||||
ATTR_VOLUME_ID )
|
||||
|
||||
#define ATTR_LONG_NAME_MASK ( ATTR_READ_ONLY | \
|
||||
ATTR_HIDDEN | \
|
||||
ATTR_SYSTEM | \
|
||||
ATTR_VOLUME_ID | \
|
||||
ATTR_DIRECTORY | \
|
||||
ATTR_ARCHIVE )
|
||||
|
||||
#define CLUSTER_END_CHAIN 0xFFF8
|
||||
#define CLUSTER_BAD 0xFFF7
|
||||
|
||||
/* Short file name */
|
||||
typedef struct
|
||||
{
|
||||
BYTE dirname[11]; /* Record name */
|
||||
BYTE attribute; /* Attributes */
|
||||
BYTE NTReserved; /* Reserved for Window NT - set 0 */
|
||||
BYTE dirTenthSecs; /* Tenth of a second, 0-199 */
|
||||
WORD dirCreateTime; /* Time of creation */
|
||||
WORD dirCreateDate; /* Date of creation */
|
||||
WORD dirLastAccDate;/* Date of last access */
|
||||
WORD fstClustHigh; /* High word of first cluster - ZERO on FAT16 */
|
||||
WORD dirWriteTime; /* Time of last write */
|
||||
WORD dirWriteDate; /* Date of last write */
|
||||
WORD fstClustLow; /* Low word of first cluster */
|
||||
DWORD filesize; /* Filesize in bytes */
|
||||
}
|
||||
__attribute__((__packed__)) SFNDIRREC;
|
||||
|
||||
/* Long file name */
|
||||
typedef struct
|
||||
{
|
||||
BYTE ordinal; /* Entry number */
|
||||
BYTE dirname1[10];
|
||||
BYTE attribute; /* Attributes */
|
||||
BYTE type; /* Reserved */
|
||||
BYTE checksum; /* SFN Checksum */
|
||||
BYTE dirname2[12];
|
||||
WORD fstClustLo; /* MUST BE ZERO */
|
||||
BYTE dirname3[4];
|
||||
}
|
||||
__attribute__((__packed__)) LFNDIRREC;
|
||||
|
||||
/* User dir entry */
|
||||
typedef struct
|
||||
{
|
||||
BYTE longname[MAX_LONG_NAME];
|
||||
BYTE shortname[13]; /* Keep word aligned*/
|
||||
DWORD fpos;
|
||||
DWORD fsize;
|
||||
DWORD driveid;
|
||||
DWORD FirstCluster;
|
||||
DWORD CurrentCluster;
|
||||
DWORD CachedCluster;
|
||||
DWORD CurrentDirEntry;
|
||||
DWORD crosscluster;
|
||||
BYTE *clusterdata;
|
||||
/* Now a copy of the current directory entry */
|
||||
SFNDIRREC dirent;
|
||||
}
|
||||
__attribute__((__packed__)) FSDIRENTRY;
|
||||
|
||||
/* VFAT API */
|
||||
/* Directory */
|
||||
int VFAT_opendir( int drive, FSDIRENTRY *d, char *search );
|
||||
int VFAT_readdir( FSDIRENTRY *d );
|
||||
void VFAT_closedir( FSDIRENTRY *d );
|
||||
int VFAT_fopen( int drive, FSDIRENTRY *d, char *fname, int mode );
|
||||
void VFAT_fclose( FSDIRENTRY *d );
|
||||
int VFAT_fread( FSDIRENTRY *d, void *buffer, int length );
|
||||
int VFAT_ftell( FSDIRENTRY *d );
|
||||
int VFAT_fseek( FSDIRENTRY *d, int where, int whence );
|
||||
int VFAT_mount( int driveid, VFATFS *v );
|
||||
|
||||
#endif
|
||||
|
160
source/ngc/wdvd.c
Normal file
160
source/ngc/wdvd.c
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Wii DVD interface API
|
||||
* Copyright (C) 2008 Jeff Epler <jepler@unpythonic.net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef WII_DVD
|
||||
#include <ogc/ipc.h>
|
||||
#include <string.h>
|
||||
#include <ogc/system.h>
|
||||
#include "wdvd.h"
|
||||
|
||||
static int di_fd = -1;
|
||||
static s32 di_hid = 0;
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
#define debug_printf printf
|
||||
#define debug_wait printf
|
||||
#else
|
||||
#define debug_printf(...) ;
|
||||
#define debug_wait(...) ;
|
||||
#endif
|
||||
|
||||
bool WDVD_Init()
|
||||
{
|
||||
if(di_fd >= 0) return 1;
|
||||
|
||||
di_fd = IOS_Open("/dev/do", 0);
|
||||
if(di_fd < 0) {
|
||||
debug_printf("IOS_Open(/dev/di) failed with code %d\n", di_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
di_hid = iosCreateHeap(0x10000);
|
||||
if(!di_hid) {
|
||||
IOS_Close(di_fd);
|
||||
di_fd = -1;
|
||||
debug_printf("iosCreateHeap(0x20) failed with code %d\n", di_hid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
debug_printf("fd=%d hid=%d\n", di_fd, di_hid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool WDVD_Reset()
|
||||
{
|
||||
bool result = false;
|
||||
char *inbuf = (char*)iosAlloc(di_hid, 0x20);
|
||||
char *outbuf = (char*)iosAlloc(di_hid, 0x20);
|
||||
if(!inbuf || !outbuf)
|
||||
goto out;
|
||||
|
||||
((u32*)inbuf)[0x00] = 0x8A000000;
|
||||
((u32*)inbuf)[0x01] = 1;
|
||||
|
||||
result = IOS_Ioctl( di_fd, 0x8A, inbuf, 0x20, outbuf, 0x20);
|
||||
out:
|
||||
if(outbuf) iosFree(di_hid, outbuf);
|
||||
if(inbuf) iosFree(di_hid, inbuf);
|
||||
return result;
|
||||
}
|
||||
|
||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
unsigned char* ios_command = 0;
|
||||
unsigned char* ios_out = 0;
|
||||
unsigned int ios_outlen = 0;
|
||||
|
||||
void WDVD_AllocCommand()
|
||||
{
|
||||
if (ios_command == 0)
|
||||
ios_command = (unsigned char*)iosAlloc(di_hid, 0x20);
|
||||
}
|
||||
|
||||
void WDVD_AllocOutput(unsigned int length)
|
||||
{
|
||||
if (ios_out == 0 || ios_outlen != length)
|
||||
{
|
||||
if (ios_out)
|
||||
iosFree(di_hid, ios_out);
|
||||
|
||||
ios_out = (unsigned char*)iosAlloc(di_hid, max(length, 0x20));
|
||||
ios_outlen = length;
|
||||
}
|
||||
}
|
||||
|
||||
int WDVD_LowUnencryptedRead(unsigned char **poutbuf, u32 len, u32 offset)
|
||||
{
|
||||
WDVD_AllocCommand();
|
||||
WDVD_AllocOutput(len);
|
||||
|
||||
unsigned char* inbuf = ios_command;
|
||||
unsigned char* outbuf = ios_out;
|
||||
|
||||
*poutbuf = ios_out;
|
||||
int result = 0;
|
||||
|
||||
if(!inbuf || !outbuf) { result = -1; goto out; }
|
||||
|
||||
((u32*)inbuf)[0] = 0x8d000000;
|
||||
((u32*)inbuf)[1] = len;
|
||||
((u32*)inbuf)[2] = offset;
|
||||
|
||||
// memset(outbuf, 0x00, len);
|
||||
|
||||
result = IOS_Ioctl(di_fd, 0x8d, inbuf, 0x20, outbuf, len);
|
||||
|
||||
if (result != 1)
|
||||
debug_printf("-> %d\n", result);
|
||||
|
||||
// if(result >= 0) {
|
||||
// memcpy(buf, outbuf, len);
|
||||
// }
|
||||
|
||||
out:
|
||||
//if(outbuf) iosFree(di_hid, outbuf);
|
||||
//if(inbuf) iosFree(di_hid, inbuf);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int WDVD_LowReadDiskId(u64 *id)
|
||||
{
|
||||
int result;
|
||||
char *inbuf = (char*)iosAlloc(di_hid, 0x20);
|
||||
char *outbuf = (char*)iosAlloc(di_hid, 0x20);
|
||||
if(!inbuf || !outbuf) { result = -1; goto out; }
|
||||
((u32*)inbuf)[0] = 0x70000000;
|
||||
|
||||
*(u64*)outbuf = 0;
|
||||
result = IOS_Ioctl(di_fd, 0x8D, inbuf, 0x20, outbuf, 0x20);
|
||||
|
||||
*id = *(u64*) outbuf;
|
||||
|
||||
out:
|
||||
if(inbuf) iosFree(di_hid, inbuf);
|
||||
if(outbuf) iosFree(di_hid, outbuf);
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
27
source/ngc/wdvd.h
Normal file
27
source/ngc/wdvd.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Wii DVD interface API
|
||||
* Copyright (C) 2008 Jeff Epler <jepler@unpythonic.net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _WDVD_H_
|
||||
#define _WDVD_H_
|
||||
bool WDVD_Init();
|
||||
bool WDVD_Reset();
|
||||
|
||||
int WDVD_LowUnencryptedRead(unsigned char **outbuf, u32 len, u32 offset);
|
||||
int WDVD_LowReadDiskId(u64 *id);
|
||||
#endif
|
387
source/render.c
387
source/render.c
@ -1,26 +1,70 @@
|
||||
/*
|
||||
only update window clip on window change (?)
|
||||
fix leftmost window/nta render and window bug
|
||||
sprite masking isn't right in sonic/micromachines 2, but
|
||||
seems ok in galaxy force 2
|
||||
|
||||
Eke-Eke (2007):
|
||||
. pixel sprite limit fixed (sonic/micromachines 2)
|
||||
. sprite collision detection added
|
||||
. big endian support improved
|
||||
. fixed leftmost window/nta render and window bug
|
||||
. some code speedup (minor)
|
||||
*/
|
||||
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* Video Display Processor (Rendering)
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
/* Look-up pixel table information */
|
||||
#define LUT_MAX (5)
|
||||
#define LUT_SIZE (0x10000)
|
||||
|
||||
/* Clip structure */
|
||||
typedef struct
|
||||
{
|
||||
uint8 left;
|
||||
uint8 right;
|
||||
uint8 enable;
|
||||
}clip_t;
|
||||
|
||||
/* Function prototypes */
|
||||
void render_obj(int line, uint8 *buf, uint8 *table);
|
||||
void render_obj_im2(int line, uint8 *buf, uint8 *table, uint8 odd);
|
||||
void render_ntw(int line, uint8 *buf);
|
||||
void render_ntw_im2(int line, uint8 *buf, uint8 odd);
|
||||
void render_ntx(int which, int line, uint8 *buf);
|
||||
void render_ntx_im2(int which, int line, uint8 *buf, uint8 odd);
|
||||
void render_ntx_vs(int which, int line, uint8 *buf);
|
||||
void update_bg_pattern_cache(void);
|
||||
void get_hscroll(int line, int shift, uint16 *scroll);
|
||||
void window_clip(int line);
|
||||
int make_lut_bg(int bx, int ax);
|
||||
int make_lut_obj(int bx, int sx);
|
||||
int make_lut_bg_ste(int bx, int ax);
|
||||
int make_lut_obj_ste(int bx, int sx);
|
||||
int make_lut_bgobj_ste(int bx, int sx);
|
||||
void merge(uint8 *srca, uint8 *srcb, uint8 *dst, uint8 *table, int width);
|
||||
void make_name_lut(void);
|
||||
void (*color_update)(int index, uint16 data);
|
||||
void remap_16(uint8 *src, uint16 *dst, uint16 *table, int length);
|
||||
#ifndef NGC
|
||||
void remap_8(uint8 *src, uint8 *dst, uint8 *table, int length);
|
||||
void remap_32(uint8 *src, uint32 *dst, uint32 *table, int length);
|
||||
#endif
|
||||
|
||||
#ifndef LSB_FIRST
|
||||
static uint32 ATTR_MSB;
|
||||
#endif
|
||||
|
||||
#ifdef ALIGN_LONG
|
||||
|
||||
/* Or change the names if you depend on these from elsewhere.. */
|
||||
#undef READ_LONG
|
||||
#undef WRITE_LONG
|
||||
@ -291,17 +335,22 @@ static __inline__ void WRITE_LONG(void *address, uint32 data)
|
||||
|
||||
|
||||
/* Pixel creation macros, input is four bits each */
|
||||
#ifndef NGC
|
||||
|
||||
/* 8:8:8 RGB */
|
||||
#define MAKE_PIXEL_32(r,g,b) ((r) << 20 | (g) << 12 | (b) << 4)
|
||||
|
||||
/* 5:5:5 RGB */
|
||||
#define MAKE_PIXEL_15(r,g,b) ((r) << 11 | (g) << 6 | (b) << 1)
|
||||
|
||||
/* 3:3:2 RGB */
|
||||
#define MAKE_PIXEL_8(r,g,b) ((r) << 5 | (g) << 2 | ((b) >> 1))
|
||||
|
||||
#endif
|
||||
|
||||
/* 5:6:5 RGB */
|
||||
#define MAKE_PIXEL_16(r,g,b) ((r) << 11 | (g) << 5 | (b))
|
||||
|
||||
/* 3:3:2 RGB */
|
||||
#define MAKE_PIXEL_8(r,g,b) ((r) << 5 | (g) << 2 | ((b) >> 1))
|
||||
|
||||
/* Clip data */
|
||||
static clip_t clip[2];
|
||||
@ -313,10 +362,7 @@ static const uint32 atex_table[] = {
|
||||
};
|
||||
|
||||
/* Sprite name look-up table */
|
||||
uint8 name_lut[0x400];
|
||||
|
||||
/* Sprite line buffer data */
|
||||
uint8 object_index_count;
|
||||
static uint8 name_lut[0x400];
|
||||
|
||||
struct
|
||||
{
|
||||
@ -328,31 +374,36 @@ struct
|
||||
} object_info[20];
|
||||
|
||||
/* Pixel look-up tables and table base address */
|
||||
uint8 *lut[5];
|
||||
uint8 *lut_base = NULL;
|
||||
static uint8 *lut[5];
|
||||
static uint8 *lut_base = NULL;
|
||||
|
||||
#ifndef NGC
|
||||
/* 8-bit pixel remapping data */
|
||||
uint8 pixel_8[0x100];
|
||||
uint8 pixel_8_lut[3][0x200];
|
||||
static uint8 pixel_8[0x100];
|
||||
static uint8 pixel_8_lut[3][0x200];
|
||||
|
||||
/* 15-bit pixel remapping data */
|
||||
uint16 pixel_15[0x100];
|
||||
uint16 pixel_15_lut[3][0x200];
|
||||
|
||||
/* 16-bit pixel remapping data */
|
||||
uint16 pixel_16[0x100];
|
||||
uint16 pixel_16_lut[3][0x200];
|
||||
static uint16 pixel_15[0x100];
|
||||
static uint16 pixel_15_lut[3][0x200];
|
||||
|
||||
/* 32-bit pixel remapping data */
|
||||
uint32 pixel_32[0x100];
|
||||
uint32 pixel_32_lut[3][0x200];
|
||||
static uint32 pixel_32[0x100];
|
||||
static uint32 pixel_32_lut[3][0x200];
|
||||
#endif
|
||||
|
||||
/* 16-bit pixel remapping data */
|
||||
static uint16 pixel_16[0x100];
|
||||
static uint16 pixel_16_lut[3][0x200];
|
||||
|
||||
/* Line buffers */
|
||||
uint8 tmp_buf[0x400]; /* Temporary buffer */
|
||||
uint8 bg_buf[0x400]; /* Merged background buffer */
|
||||
uint8 nta_buf[0x400]; /* Plane A / Window line buffer */
|
||||
uint8 ntb_buf[0x400]; /* Plane B line buffer */
|
||||
uint8 obj_buf[0x400]; /* Object layer line buffer */
|
||||
static uint8 tmp_buf[0x400]; /* Temporary buffer */
|
||||
static uint8 bg_buf[0x400]; /* Merged background buffer */
|
||||
static uint8 nta_buf[0x400]; /* Plane A / Window line buffer */
|
||||
static uint8 ntb_buf[0x400]; /* Plane B line buffer */
|
||||
static uint8 obj_buf[0x400]; /* Object layer line buffer */
|
||||
|
||||
/* Sprite line buffer data */
|
||||
static uint8 object_index_count;
|
||||
|
||||
/*
|
||||
3:3:3 to 5:6:5 RGB pixel extrapolation tables
|
||||
@ -383,12 +434,46 @@ uint8 obj_buf[0x400]; /* Object layer line buffer */
|
||||
|
||||
uint8 rgb565_norm[2][8] = {{0 , 4, 9, 13, 18, 22, 27, 31},
|
||||
{0 , 9, 18, 27, 36, 45, 54, 63}};
|
||||
uint8 rgb565_half[2][8] = {{0 , 2, 4, 7, 9, 11, 13, 15},
|
||||
uint8 rgb565_half[2][8] = {{0 , 2, 4, 6, 9, 11, 13, 15},
|
||||
{0 , 4, 9, 13, 18, 22, 27, 31}};
|
||||
uint8 rgb565_high[2][8] = {{15, 18, 20, 22, 24, 27, 29, 31},
|
||||
{31, 36, 40, 45, 49, 54, 58, 63}};
|
||||
uint8 rgb565_high[2][8] = {{15, 17, 19, 21, 24, 26, 28, 31},
|
||||
{31, 35, 40, 44, 49, 53, 58, 63}};
|
||||
|
||||
|
||||
void palette_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 0x200; i += 1)
|
||||
{
|
||||
int r, g, b;
|
||||
|
||||
r = (i >> 6) & 7;
|
||||
g = (i >> 3) & 7;
|
||||
b = (i >> 0) & 7;
|
||||
|
||||
#ifndef NGC
|
||||
pixel_8_lut[0][i] = MAKE_PIXEL_8(r>>1,g>>1,b>>1);
|
||||
pixel_8_lut[1][i] = MAKE_PIXEL_8(r,g,b);
|
||||
pixel_8_lut[2][i] = MAKE_PIXEL_8((r>>1)|4,(g>>1)|4,(b>>1)|4);
|
||||
|
||||
pixel_15_lut[0][i] = MAKE_PIXEL_15(r,g,b);
|
||||
pixel_15_lut[1][i] = MAKE_PIXEL_15(r<<1,g<<1,b<<1);
|
||||
pixel_15_lut[2][i] = MAKE_PIXEL_15(r|8,g|8,b|8);
|
||||
|
||||
pixel_32_lut[0][i] = MAKE_PIXEL_32(r,g,b);
|
||||
pixel_32_lut[1][i] = MAKE_PIXEL_32(r<<1,g<<1,b<<1);
|
||||
pixel_32_lut[2][i] = MAKE_PIXEL_32(r|8,g|8,b|8);
|
||||
#endif
|
||||
|
||||
/* RGB 565 format: we extrapolate each 3-bit value into a 5-bit (R,B) or 6-bit (G) value
|
||||
this is needed to correctly cover full color range: [0-31] for R,B or [0-63] for G */
|
||||
pixel_16_lut[0][i] = MAKE_PIXEL_16(rgb565_half[0][r],rgb565_half[1][g],rgb565_half[0][b]);
|
||||
pixel_16_lut[1][i] = MAKE_PIXEL_16(rgb565_norm[0][r],rgb565_norm[1][g],rgb565_norm[0][b]);
|
||||
pixel_16_lut[2][i] = MAKE_PIXEL_16(rgb565_high[0][r],rgb565_high[1][g],rgb565_high[0][b]);
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Init, reset, shutdown routines */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@ -415,34 +500,10 @@ int render_init (void)
|
||||
}
|
||||
|
||||
/* Make pixel data tables */
|
||||
for (i = 0; i < 0x200; i += 1)
|
||||
{
|
||||
int r, g, b;
|
||||
|
||||
r = (i >> 6) & 7;
|
||||
g = (i >> 3) & 7;
|
||||
b = (i >> 0) & 7;
|
||||
|
||||
pixel_8_lut[0][i] = MAKE_PIXEL_8(r>>1,g>>1,b>>1);
|
||||
pixel_8_lut[1][i] = MAKE_PIXEL_8(r,g,b);
|
||||
pixel_8_lut[2][i] = MAKE_PIXEL_8((r>>1)|4,(g>>1)|4,(b>>1)|4);
|
||||
|
||||
pixel_15_lut[0][i] = MAKE_PIXEL_15(r,g,b);
|
||||
pixel_15_lut[1][i] = MAKE_PIXEL_15(r<<1,g<<1,b<<1);
|
||||
pixel_15_lut[2][i] = MAKE_PIXEL_15(r|8,g|8,b|8);
|
||||
|
||||
/* RGB 565 format: we extrapolate each 3-bit value into a 5-bit (R,B) or 6-bit (G) value
|
||||
this is needed to correctly cover full color range: [0-31] for R,B or [0-63] for G */
|
||||
pixel_16_lut[0][i] = MAKE_PIXEL_16(rgb565_half[0][r],rgb565_half[1][g],rgb565_half[0][b]);
|
||||
pixel_16_lut[1][i] = MAKE_PIXEL_16(rgb565_norm[0][r],rgb565_norm[1][g],rgb565_norm[0][b]);
|
||||
pixel_16_lut[2][i] = MAKE_PIXEL_16(rgb565_high[0][r],rgb565_high[1][g],rgb565_high[0][b]);
|
||||
|
||||
pixel_32_lut[0][i] = MAKE_PIXEL_32(r,g,b);
|
||||
pixel_32_lut[1][i] = MAKE_PIXEL_32(r<<1,g<<1,b<<1);
|
||||
pixel_32_lut[2][i] = MAKE_PIXEL_32(r|8,g|8,b|8);
|
||||
}
|
||||
palette_init();
|
||||
|
||||
/* Set up color update function */
|
||||
#ifndef NGC
|
||||
switch(bitmap.depth)
|
||||
{
|
||||
case 8: color_update = color_update_8; break;
|
||||
@ -450,6 +511,9 @@ int render_init (void)
|
||||
case 16: color_update = color_update_16; break;
|
||||
case 32: color_update = color_update_32; break;
|
||||
}
|
||||
#else
|
||||
color_update = color_update_16;
|
||||
#endif
|
||||
|
||||
/* Make sprite name look-up table */
|
||||
make_name_lut();
|
||||
@ -489,18 +553,22 @@ void make_name_lut(void)
|
||||
|
||||
void render_reset(void)
|
||||
{
|
||||
memset(&clip, 0, sizeof(clip));
|
||||
/* Clear display bitmap */
|
||||
memset(bitmap.data, 0, bitmap.pitch * bitmap.height);
|
||||
|
||||
memset(&clip, 0, sizeof(clip));
|
||||
memset(bg_buf, 0, sizeof(bg_buf));
|
||||
memset(tmp_buf, 0, sizeof(tmp_buf));
|
||||
memset(nta_buf, 0, sizeof(nta_buf));
|
||||
memset(ntb_buf, 0, sizeof(ntb_buf));
|
||||
memset(obj_buf, 0, sizeof(obj_buf));
|
||||
|
||||
#ifndef NGC
|
||||
memset(&pixel_8, 0, sizeof(pixel_8));
|
||||
memset(&pixel_15, 0, sizeof(pixel_15));
|
||||
memset(&pixel_16, 0, sizeof(pixel_16));
|
||||
memset(&pixel_32, 0, sizeof(pixel_32));
|
||||
#endif
|
||||
memset(&pixel_16, 0, sizeof(pixel_16));
|
||||
}
|
||||
|
||||
|
||||
@ -512,15 +580,56 @@ void render_shutdown(void)
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Line render function */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void render_line(int line)
|
||||
void remap_buffer(int line, int width)
|
||||
{
|
||||
/* get line offset from framebuffer */
|
||||
int offset = vdp_pal ? bitmap.viewport.y : (bitmap.viewport.y*11/8); // NTSC is 243 lines
|
||||
int vline = (line + offset) % lines_per_frame;
|
||||
|
||||
/* illegal video mode (screen rolls up) */
|
||||
if (!vdp_pal && (reg[1] & 8)) vline = (vline + frame_cnt)%240;
|
||||
|
||||
/* double resolution mode */
|
||||
if (config.render && interlaced) vline = (vline * 2) + odd_frame;
|
||||
|
||||
void *out =((void *)&bitmap.data[(vline * bitmap.pitch)]);
|
||||
|
||||
#ifndef NGC
|
||||
switch(bitmap.depth)
|
||||
{
|
||||
case 8:
|
||||
remap_8(tmp_buf+0x20-bitmap.viewport.x, (uint8 *)out, pixel_8, width);
|
||||
break;
|
||||
case 15:
|
||||
remap_16(tmp_buf+0x20-bitmap.viewport.x, (uint16 *)out, pixel_15, width);
|
||||
break;
|
||||
case 16:
|
||||
remap_16(tmp_buf+0x20-bitmap.viewport.x, (uint16 *)out, pixel_16, width);
|
||||
break;
|
||||
case 32:
|
||||
remap_32(tmp_buf+0x20-bitmap.viewport.x, (uint32 *)out, pixel_32, width);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
remap_16(tmp_buf+0x20-bitmap.viewport.x, (uint16 *)out, pixel_16, width);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void render_line(int line, uint8 odd_frame)
|
||||
{
|
||||
/* check if we are inside display area (including vertical borders) */
|
||||
int min = bitmap.viewport.h + bitmap.viewport.y;
|
||||
int max = lines_per_frame - bitmap.viewport.y;
|
||||
if ((line >= min) && (line < max)) return;
|
||||
|
||||
uint8 *lb = tmp_buf;
|
||||
int width = bitmap.viewport.w;
|
||||
|
||||
if((reg[1] & 0x40) == 0x00)
|
||||
/* vertical borders or display OFF */
|
||||
if ((line >= bitmap.viewport.h) || (!(reg[1] & 0x40)))
|
||||
{
|
||||
memset(&lb[bitmap.viewport.x], 0x40 | border, width);
|
||||
memset(&lb[0x20], 0x40 | border, width);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -529,9 +638,9 @@ void render_line(int line)
|
||||
|
||||
if(im2_flag)
|
||||
{
|
||||
if (clip[0].enable) render_ntx_im2(0, line, nta_buf);
|
||||
render_ntx_im2(1, line, ntb_buf);
|
||||
if (clip[1].enable) render_ntw_im2(line, nta_buf);
|
||||
if (clip[0].enable) render_ntx_im2(0, line, nta_buf, odd_frame);
|
||||
render_ntx_im2(1, line, ntb_buf, odd_frame);
|
||||
if (clip[1].enable) render_ntw_im2(line, nta_buf, odd_frame);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -553,7 +662,7 @@ void render_line(int line)
|
||||
merge(&nta_buf[0x20], &ntb_buf[0x20], &bg_buf[0x20], lut[2], width);
|
||||
memset(&obj_buf[0x20], 0, width);
|
||||
|
||||
if(im2_flag) render_obj_im2(line, obj_buf, lut[3]);
|
||||
if(im2_flag) render_obj_im2(line, obj_buf, lut[3], odd_frame);
|
||||
else render_obj(line, obj_buf, lut[3]);
|
||||
|
||||
merge(&obj_buf[0x20], &bg_buf[0x20], &lb[0x20], lut[4], width);
|
||||
@ -561,33 +670,43 @@ void render_line(int line)
|
||||
else
|
||||
{
|
||||
merge(&nta_buf[0x20], &ntb_buf[0x20], &lb[0x20], lut[0], width);
|
||||
if(im2_flag) render_obj_im2(line, lb, lut[1]);
|
||||
if(im2_flag) render_obj_im2(line, lb, lut[1], odd_frame);
|
||||
else render_obj(line, lb, lut[1]);
|
||||
}
|
||||
|
||||
/* Mode 4 feature only (unemulated, no games rely on this) */
|
||||
/*if(!(reg[1] & 0x04) && (reg[0] & 0x20)) memset(&lb[0x20], 0x40 | border, 0x08);*/
|
||||
}
|
||||
|
||||
if(reg[0] & 0x20)
|
||||
/* horizontal borders */
|
||||
if (config.overscan)
|
||||
{
|
||||
memset(&lb[bitmap.viewport.x], 0x40 | border, 0x08);
|
||||
memset(&lb[0x20 - bitmap.viewport.x], 0x40 | border, bitmap.viewport.x);
|
||||
memset(&lb[0x20 + bitmap.viewport.w], 0x40 | border, bitmap.viewport.x);
|
||||
width += 2 * bitmap.viewport.x;
|
||||
}
|
||||
|
||||
void *out = (void *)&bitmap.data[(line * bitmap.pitch) + (bitmap.viewport.x * bitmap.granularity)];
|
||||
switch(bitmap.depth)
|
||||
/* LightGun mark */
|
||||
if ((input.dev[4] == DEVICE_LIGHTGUN) && (config.crosshair))
|
||||
{
|
||||
case 8:
|
||||
remap_8(lb+0x20, (uint8 *)out, pixel_8, width);
|
||||
break;
|
||||
case 15:
|
||||
remap_16(lb+0x20, (uint16 *)out, pixel_15, width);
|
||||
break;
|
||||
case 16:
|
||||
remap_16(lb+0x20, (uint16 *)out, pixel_16, width);
|
||||
break;
|
||||
case 32:
|
||||
remap_32(lb+0x20, (uint32 *)out, pixel_32, width);
|
||||
break;
|
||||
int dy = v_counter - input.analog[0][1];
|
||||
|
||||
if (abs(dy) < 6)
|
||||
{
|
||||
int i;
|
||||
int start = input.analog[0][0] - 4;
|
||||
int end = start + 8;
|
||||
if (start < 0) start = 0;
|
||||
if (end > bitmap.viewport.w) end = bitmap.viewport.w;
|
||||
for (i=start; i<end; i++)
|
||||
{
|
||||
lb[0x20+i] = 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remap_buffer(line,width);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Window rendering */
|
||||
@ -610,12 +729,12 @@ void render_ntw(int line, uint8 *buf)
|
||||
}
|
||||
}
|
||||
|
||||
void render_ntw_im2(int line, uint8 *buf)
|
||||
void render_ntw_im2(int line, uint8 *buf, uint8 odd)
|
||||
{
|
||||
int column, v_line, width;
|
||||
uint32 *nt, *src, *dst, atex, atbuf, offs;
|
||||
|
||||
v_line = ((line & 7) << 1 | ((status >> 4) & 1)) << 3;
|
||||
v_line = ((line & 7) << 1 | odd) << 3;
|
||||
width = (reg[12] & 1) ? 7 : 6;
|
||||
nt = (uint32 *)&vram[ntwb | ((line >> 3) << width)];
|
||||
dst = (uint32 *)&buf[0x20 + (clip[1].left << 4)];
|
||||
@ -693,7 +812,7 @@ void render_ntx(int which, int line, uint8 *buf)
|
||||
}
|
||||
}
|
||||
|
||||
void render_ntx_im2(int which, int line, uint8 *buf)
|
||||
void render_ntx_im2(int which, int line, uint8 *buf, uint8 odd)
|
||||
{
|
||||
int column;
|
||||
int start, end;
|
||||
@ -721,7 +840,7 @@ void render_ntx_im2(int which, int line, uint8 *buf)
|
||||
if(which)
|
||||
{
|
||||
start = 0;
|
||||
end = (reg[0x0C] & 1) ? 20 : 16;
|
||||
end = (reg[12] & 1) ? 20 : 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -733,7 +852,7 @@ void render_ntx_im2(int which, int line, uint8 *buf)
|
||||
vs = (uint32 *)&vsram[0];
|
||||
y_scroll = (vs[0] >> vsr_shift[which]) & 0x3FF;
|
||||
y_scroll = (line + y_scroll) & playfield_row_mask;
|
||||
v_line = (((y_scroll & 7) << 1) | ((status >> 4) & 1)) << 3;
|
||||
v_line = (((y_scroll & 7) << 1) | odd) << 3;
|
||||
nt = (uint32 *)&vram[table[which] + (((y_scroll >> 3) << playfield_shift) & y_mask)];
|
||||
|
||||
if(shift)
|
||||
@ -743,8 +862,7 @@ void render_ntx_im2(int which, int line, uint8 *buf)
|
||||
/* Window bug */
|
||||
if (start) atbuf = nt[(index) & playfield_col_mask];
|
||||
else atbuf = nt[(index-1) & playfield_col_mask];
|
||||
|
||||
DRAW_COLUMN(atbuf, v_line);
|
||||
DRAW_COLUMN_IM2(atbuf, v_line);
|
||||
}
|
||||
|
||||
dst = (uint32 *)&buf[0x20 + shift + (start<<4)];
|
||||
@ -782,7 +900,7 @@ void render_ntx_vs(int which, int line, uint8 *buf)
|
||||
if(which)
|
||||
{
|
||||
start = 0;
|
||||
end = (reg[0x0C] & 1) ? 20 : 16;
|
||||
end = (reg[12] & 1) ? 20 : 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1205,7 +1323,7 @@ int make_lut_bgobj_ste(int bx, int sx)
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Remap functions */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef NGC
|
||||
void remap_8(uint8 *src, uint8 *dst, uint8 *table, int length)
|
||||
{
|
||||
int count;
|
||||
@ -1215,15 +1333,6 @@ void remap_8(uint8 *src, uint8 *dst, uint8 *table, int length)
|
||||
}
|
||||
}
|
||||
|
||||
void remap_16(uint8 *src, uint16 *dst, uint16 *table, int length)
|
||||
{
|
||||
int count;
|
||||
for(count = 0; count < length; count += 1)
|
||||
{
|
||||
*dst++ = table[*src++];
|
||||
}
|
||||
}
|
||||
|
||||
void remap_32(uint8 *src, uint32 *dst, uint32 *table, int length)
|
||||
{
|
||||
int count;
|
||||
@ -1232,6 +1341,17 @@ void remap_32(uint8 *src, uint32 *dst, uint32 *table, int length)
|
||||
*dst++ = table[*src++];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void remap_16(uint8 *src, uint16 *dst, uint16 *table, int length)
|
||||
{
|
||||
int count;
|
||||
for(count = 0; count < length; count += 1)
|
||||
{
|
||||
*dst++ = table[*src++];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Merge functions */
|
||||
@ -1252,6 +1372,7 @@ void merge(uint8 *srca, uint8 *srcb, uint8 *dst, uint8 *table, int width)
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Color update functions */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
#ifndef NGC
|
||||
|
||||
void color_update_8(int index, uint16 data)
|
||||
{
|
||||
@ -1287,23 +1408,6 @@ void color_update_15(int index, uint16 data)
|
||||
}
|
||||
}
|
||||
|
||||
void color_update_16(int index, uint16 data)
|
||||
{
|
||||
if(reg[12] & 8)
|
||||
{
|
||||
pixel_16[0x00 | index] = pixel_16_lut[0][data];
|
||||
pixel_16[0x40 | index] = pixel_16_lut[1][data];
|
||||
pixel_16[0x80 | index] = pixel_16_lut[2][data];
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16 temp = pixel_16_lut[1][data];
|
||||
pixel_16[0x00 | index] = temp;
|
||||
pixel_16[0x40 | index] = temp;
|
||||
pixel_16[0x80 | index] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void color_update_32(int index, uint16 data)
|
||||
{
|
||||
if(reg[12] & 8)
|
||||
@ -1321,6 +1425,25 @@ void color_update_32(int index, uint16 data)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void color_update_16(int index, uint16 data)
|
||||
{
|
||||
if(reg[12] & 8)
|
||||
{
|
||||
pixel_16[0x00 | index] = pixel_16_lut[0][data];
|
||||
pixel_16[0x40 | index] = pixel_16_lut[1][data];
|
||||
pixel_16[0x80 | index] = pixel_16_lut[2][data];
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16 temp = pixel_16_lut[1][data];
|
||||
pixel_16[0x00 | index] = temp;
|
||||
pixel_16[0x40 | index] = temp;
|
||||
pixel_16[0x80 | index] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Object render functions */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@ -1455,7 +1578,7 @@ void render_obj(int line, uint8 *buf, uint8 *table)
|
||||
}
|
||||
}
|
||||
|
||||
void render_obj_im2(int line, uint8 *buf, uint8 *table)
|
||||
void render_obj_im2(int line, uint8 *buf, uint8 *table, uint8 odd)
|
||||
{
|
||||
uint16 ypos;
|
||||
uint16 attr;
|
||||
@ -1509,7 +1632,7 @@ void render_obj_im2(int line, uint8 *buf, uint8 *table)
|
||||
|
||||
v_line = (line - ypos);
|
||||
nt_row = (v_line >> 3) & 3;
|
||||
v_line = (((v_line & 7) << 1) | ((status >> 4) & 1)) << 3;
|
||||
v_line = (((v_line & 7) << 1) | odd) << 3;
|
||||
|
||||
name = (attr & 0x03FF);
|
||||
s = &name_lut[((attr >> 3) & 0x300) | (size << 4) | (nt_row << 2)];
|
||||
@ -1517,6 +1640,8 @@ void render_obj_im2(int line, uint8 *buf, uint8 *table)
|
||||
lb = (uint8 *)&buf[0x20 + (xpos - 0x80)];
|
||||
|
||||
/* number of tiles to draw */
|
||||
/* adjusted for sprite limit */
|
||||
if (pixelcount > bitmap.viewport.w) width -= (pixelcount - bitmap.viewport.w);
|
||||
width >>= 3;
|
||||
|
||||
for(column = 0; column < width; column += 1, lb+=8)
|
||||
|
@ -1,53 +1,49 @@
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* Video Display Processor (Rendering)
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef _RENDER_H_
|
||||
#define _RENDER_H_
|
||||
|
||||
|
||||
/* Look-up pixel table information */
|
||||
#define LUT_MAX (5)
|
||||
#define LUT_SIZE (0x10000)
|
||||
|
||||
/* Clip structure */
|
||||
typedef struct
|
||||
{
|
||||
uint8 left;
|
||||
uint8 right;
|
||||
uint8 enable;
|
||||
}clip_t;
|
||||
/* Global variables */
|
||||
extern uint8 rgb565_norm[2][8];
|
||||
extern uint8 rgb565_half[2][8];
|
||||
extern uint8 rgb565_high[2][8];
|
||||
|
||||
/* Function prototypes */
|
||||
int render_init(void);
|
||||
void render_reset(void);
|
||||
void render_shutdown(void);
|
||||
void render_line(int line);
|
||||
void render_obj(int line, uint8 *buf, uint8 *table);
|
||||
void render_obj_im2(int line, uint8 *buf, uint8 *table);
|
||||
void render_ntw(int line, uint8 *buf);
|
||||
void render_ntw_im2(int line, uint8 *buf);
|
||||
void render_ntx(int which, int line, uint8 *buf);
|
||||
void render_ntx_im2(int which, int line, uint8 *buf);
|
||||
void render_ntx_vs(int which, int line, uint8 *buf);
|
||||
void update_bg_pattern_cache(void);
|
||||
void get_hscroll(int line, int shift, uint16 *scroll);
|
||||
void window_clip(int line);
|
||||
int make_lut_bg(int bx, int ax);
|
||||
int make_lut_obj(int bx, int sx);
|
||||
int make_lut_bg_ste(int bx, int ax);
|
||||
int make_lut_obj_ste(int bx, int sx);
|
||||
int make_lut_bgobj_ste(int bx, int sx);
|
||||
void remap_8(uint8 *src, uint8 *dst, uint8 *table, int length);
|
||||
void remap_16(uint8 *src, uint16 *dst, uint16 *table, int length);
|
||||
void remap_32(uint8 *src, uint32 *dst, uint32 *table, int length);
|
||||
void merge(uint8 *srca, uint8 *srcb, uint8 *dst, uint8 *table, int width);
|
||||
void color_update_8(int index, uint16 data);
|
||||
void color_update_15(int index, uint16 data);
|
||||
void color_update_16(int index, uint16 data);
|
||||
void color_update_32(int index, uint16 data);
|
||||
void make_name_lut(void);
|
||||
void parse_satb(int line);
|
||||
|
||||
/* global variables */
|
||||
extern uint8 object_index_count;
|
||||
extern int render_init(void);
|
||||
extern void palette_init(void);
|
||||
extern void render_reset(void);
|
||||
extern void render_shutdown(void);
|
||||
extern void render_line(int line, uint8 odd_frame);
|
||||
#ifndef NGC
|
||||
extern void color_update_8(int index, uint16 data);
|
||||
extern void color_update_15(int index, uint16 data);
|
||||
extern void color_update_32(int index, uint16 data);
|
||||
#endif
|
||||
extern void color_update_16(int index, uint16 data);
|
||||
extern void parse_satb(int line);
|
||||
extern void (*color_update)(int index, uint16 data);
|
||||
extern void remap_buffer(int line,int width);
|
||||
|
||||
#endif /* _RENDER_H_ */
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user