mirror of
https://github.com/dborth/fceugx.git
synced 2024-10-31 22:45:05 +01:00
add 2008-03-26 release
This commit is contained in:
commit
11f8c6a70f
177
Makefile
Normal file
177
Makefile
Normal file
@ -0,0 +1,177 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
# Generic makefile for Gamecube projects
|
||||
#
|
||||
# Tab stops set to 4
|
||||
# | | | |
|
||||
# 0 1 2 3
|
||||
#---------------------------------------------------------------------------------
|
||||
# Clear the implicit built in rules
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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 := fceugc
|
||||
BUILD := build
|
||||
SOURCES := source source/boards source/mappers source/input \
|
||||
source/mbshare source/drivers/common \
|
||||
source/drivers/gamecube source/roms \
|
||||
source/iplfont source/sz
|
||||
INCLUDES := include source/sz source/linux
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
MACHDEP = -DGEKKO -mcpu=750 -meabi -mhard-float
|
||||
CFLAGS = -g -Os -Wall $(MACHDEP) $(INCLUDE) -DFCEU_VERSION_NUMERIC=9812 -DNGC=1 \
|
||||
-DZLIB -DBIG_ENDIAN -DHAVE_ASPRINTF=1 -DSTDC \
|
||||
-D_SZ_ONE_DIRECTORY=1 -D_LZMA_IN_CB=1 -D_LZMA_OUT_READ
|
||||
|
||||
LDFLAGS = $(MACHDEP) -mogc -Wl,-Map,$(notdir $@).map -Wl,--cref
|
||||
|
||||
PREFIX := powerpc-gekko-
|
||||
|
||||
export PATH:= $(DEVKITPPC)/bin:$(PATH)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS :=
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with
|
||||
#---------------------------------------------------------------------------------
|
||||
#LIBS := -logc -lm -lz -lbba -lsdcard
|
||||
LIBS := -logc -lm -lz -logcsys -lsdcard
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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))
|
||||
|
||||
export CC := $(PREFIX)gcc
|
||||
export CXX := $(PREFIX)g++
|
||||
export AR := $(PREFIX)ar
|
||||
export OBJCOPY := $(PREFIX)objcopy
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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)))
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
export LD := $(CC)
|
||||
else
|
||||
export LD := $(CXX)
|
||||
endif
|
||||
|
||||
export OFILES := $(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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# build a list of library paths
|
||||
#---------------------------------------------------------------------------------
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
.PHONY: $(BUILD) clean
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) *.elf
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
run:
|
||||
psoload $(TARGET).dol
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
reload:
|
||||
psoload -r $(TARGET).dol
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
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++
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o : %.cpp
|
||||
@echo $(notdir $<)
|
||||
@$(CXX) -MMD $(CFLAGS) -o $@ -c $<
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o : %.c
|
||||
@echo $(notdir $<)
|
||||
@$(CC) -MMD $(CFLAGS) -o $@ -c $<
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o : %.S
|
||||
@echo $(notdir $<)
|
||||
@$(CC) -MMD $(CFLAGS) -D_LANGUAGE_ASSEMBLY -c $< -o $@
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o : %.s
|
||||
@echo $(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
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
BIN
fceugc.dol
Normal file
BIN
fceugc.dol
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 MiB |
1
fceugc.pnproj
Normal file
1
fceugc.pnproj
Normal file
File diff suppressed because one or more lines are too long
1
fceugc.pnps
Normal file
1
fceugc.pnps
Normal file
@ -0,0 +1 @@
|
||||
<pd><ViewState><e p="fceugc" x="true"></e><e p="fceugc\input" x="false"></e><e p="fceugc\iplfont" x="false"></e><e p="fceugc\mappers" x="false"></e><e p="fceugc\ngc" x="false"></e><e p="fceugc\boards" x="false"></e><e p="fceugc\common" x="false"></e><e p="fceugc\roms" x="false"></e><e p="fceugc\source" x="false"></e><e p="fceugc\sz" x="false"></e><e p="fceugc\mbshare" x="false"></e></ViewState></pd>
|
229
fceugcv108x.txt
Normal file
229
fceugcv108x.txt
Normal file
@ -0,0 +1,229 @@
|
||||
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
|
||||
|
||||
- FCE Ultra GameCube Edition -
|
||||
Version 1.0.8x
|
||||
(Under GPL License)
|
||||
Softdev, 2006
|
||||
|
||||
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
|
||||
|
||||
-=[ Explanation ]=-
|
||||
|
||||
FCE Ultra GC is a modified port of the FCE Ultra 0.98.12 Nintendo Entertainment
|
||||
system for x86 (Windows/Linux) PC's. In English you can play NES games on your
|
||||
GameCube using either a softmod and/or modchip from a DVD or via a networked
|
||||
connection to your PC. If you're unfamiliar with what softmods/modchips please
|
||||
visit the site listed at the bottom of this document.
|
||||
|
||||
-=[ What's New? ]=-
|
||||
|
||||
* XenoGC Support (GC-Linux Homebrew DVD Compatibility)
|
||||
|
||||
-=[ Features ]=-
|
||||
|
||||
* NES Compatibility Based on v0.98.12
|
||||
* Sound Filters
|
||||
* Graphics Filters (GX Chipset, Cheesy and 2x)
|
||||
* 1-2 Player Support
|
||||
* Real Time Saving (RTS) from Memory Card
|
||||
* Load Games from ISO9660 DVD
|
||||
* Supports Joilet Filesystem w/Relaxed Options
|
||||
* Fast Load from Qoob or Viper
|
||||
* GX Graphic Filter Added - Super Fast/Smooth
|
||||
* Joilet FileSystem Support for DVD
|
||||
* Memory Card Idle Bug Fixed
|
||||
|
||||
-=[ Supported Mappers ]=-
|
||||
|
||||
Mappers are the way the Nintendo handles switching from ROM/VROM so the more
|
||||
that are supported the more games will work.
|
||||
|
||||
000 . 112 . 113 . 114 . 117 . 15 . 151 . 16 . 17 . 18 . 180 . 182 . 184 . 187
|
||||
189 . 193 . 200 . 201 . 202 . 203 . 208 . 21 . 22 . 225 . 226 . 227 . 228 . 229
|
||||
23 . 230 . 231 . 232 . 234 . 235 . 240 . 241 . 242 . 244 . 246 . 248 . 24 . 26
|
||||
25 . 255 . 32 . 33 . 40 . 41 . 42 . 43 . 46 . 50 . 51 . 57 . 58 . 59
|
||||
6 . 60 . 61 . 62 . 65 . 67 . 68 . 69 . 71 . 72 . 73 . 75 . 76 . 77
|
||||
79 . 8 . 80 . 82 . 83 . 85 . 86 . 88 . 89 . 91 . 92 . 95 . 97 . 99
|
||||
|
||||
-=[ Requirements ]=-
|
||||
|
||||
* Softmod and/or Hardmod
|
||||
* DVD Burner and/or Broad Band Adapter
|
||||
* Some NES ROMS - http://www.pdroms.de
|
||||
|
||||
-=[ Usage - Preparation ]=-
|
||||
|
||||
You can either put FCEU GC onto a DVD with various ROM files or inject the ROM(s) into
|
||||
the emulator. Either way FCEU GC comes without a ROM file in it and you must first
|
||||
inject one before you can burn a disc. I would suggest if you're using a SoftMod to
|
||||
inject the ROM(s) and create many DOL files as it will cut down on the swapping of
|
||||
discs. Note that the ROMS must be unzipped and be in the iNES format (.NES)
|
||||
|
||||
-[ Injecting the ROM ]-
|
||||
|
||||
These instructions are for Windows users and if you're running Linux I'm sure
|
||||
you wont even need most of these instructions and can figure out how to work
|
||||
it yourself.
|
||||
|
||||
(a) Extract the FCEUGCv108.ZIP and ROMS archives into "C:\NES"
|
||||
(a) Goto the Start Menu and pick "RUN" then type in "CMD"
|
||||
(b) Type in "C:\" then press ENTER (Changes to the "C" drive)
|
||||
(c) Type in "CD\NES" then press ENTER (Changes to the "C:\NES" Folder)
|
||||
(d) Type in "DIR" then press ENTER (Lists all the files in the Folder)
|
||||
(e) Type in "FCEUINJECT (rom_name.nes) (output_name.dol)" and press ENTER
|
||||
Example - "FCEUINJECT Tetris.nes Tetris.dol"
|
||||
(f) Put the Tetris.dol (or whatever you named it) on the media you use for
|
||||
SoftMod Booting (SD Card, DVD, etc)
|
||||
|
||||
If you're going to be creating a DVD for use with ModChips were you can use
|
||||
the DVD loading selection menu then you'll only need to create ONE .DOL file,
|
||||
but if you're using a softmod you may want to create more then one .DOL file.
|
||||
|
||||
-[ Creating the DVD ]-
|
||||
|
||||
(a) Load Nero Burning ROM and pick NEW then DVD then DVD-ROM (ISO)
|
||||
(b) Make sure Multi-Session is set to NO
|
||||
(c) Under the ISO tab set these following options:
|
||||
File system: ISO 9660 Only or ISO 9660 + Joliet
|
||||
File name length (ISO): Max. of 31 chars (Level 2)
|
||||
Character set (ISO): ISO 9660 (Standard ISO CD-ROM)
|
||||
Relax Restrictions: Check all except "Do not add the ';1' ISO file"
|
||||
(d) Under the Label TAB enter in the DVD name (anything you want)
|
||||
(e) Click the NEW button
|
||||
(f) Put the ROMNAME.DOL*** file in the main directory (under the little CD)
|
||||
(g) Right Click in the DVD Window and pick "Create Folder"
|
||||
**(h) Make a Folder named "A", "B", "C", etc
|
||||
(i) Drag and Drop the .NES roms into the main dir or **folders
|
||||
(j) Pick "Recorder" then "Burn Compilation"
|
||||
(k) Pick your speed and make sure to pick "Finalize DVD"
|
||||
If "Finalize DVD" is grayed out don't worry
|
||||
(l) Hit burn and wait a while
|
||||
|
||||
* = You can chose ISO9660 by itself or with Joliet and it doesn't matter
|
||||
if you're using a Viper GC or other solution
|
||||
** = Creating folders based on filenames makes for easier loading if you
|
||||
have a bunch of roms on the DVD
|
||||
*** = This is the DOL file you make with the injection method
|
||||
|
||||
-=[ Usage - Emulator ]=-
|
||||
|
||||
To load the FCEUGC.DOL or any other DOL file(s) you've put NES roms into please
|
||||
refer to the Mod That Cube -FAQ- (http://modthatcube.pxn-os.com) to see how to load
|
||||
DOL files using your SoftMod and/or Modchip.
|
||||
|
||||
Once you load FCEU GC the ROM injected into the emulator will automatically load so
|
||||
you can play it. If you would like to load another ROM you're going to have to access
|
||||
the "Configuration Menu" by pressing "Z" on the GameCube controller.
|
||||
|
||||
-=[ Usage - Controls ]=-
|
||||
|
||||
Analog = UP / DOWN / LEFT / RIGHT
|
||||
D-PAD = UP / DOWN / LEFT / RIGHT
|
||||
Select = X
|
||||
Start = START / PAUSE
|
||||
A Button = A
|
||||
B Button = B
|
||||
|
||||
Z Button = Configuration Menu
|
||||
L & R = Return to SDLOAD (SDLoad Users Only)
|
||||
|
||||
-=[ Usage - Configuration Menu ]=-
|
||||
|
||||
To access the Configuration Menu simply press "Z" while the emulator is running.
|
||||
To access any of the options press "A" and to press the B button to "Quick Exit"
|
||||
the current sub-menu you may be in.
|
||||
|
||||
-[ Emulator Options ]-
|
||||
|
||||
Screen Scaler - How to scale the screen: GX, Cheesy or 2x
|
||||
|
||||
Palette - The colors used while viewing the game:
|
||||
Default . loopy . quor . chris . matt
|
||||
pasofami . crashman . mess . zaphod-cv
|
||||
zaphod-smb . vs-drmar . vs-cv . vs-smb
|
||||
|
||||
Stop DVD Motor - If you're going to be playing a game for a while you might as
|
||||
well stop the DVD motor to save the life of the DVD drive
|
||||
|
||||
Timing - NTSC or PAL (Depends if you're running a PAL or NTSC game)
|
||||
|
||||
Reset NES - This will RESET the Emulator
|
||||
|
||||
-[ Save Game Manager ]-
|
||||
|
||||
If you would like to save in your game simply pick which card to save to
|
||||
and then save it. Later on if you would like to load your save just load
|
||||
the game you had saved in and then pick "Load Game State".
|
||||
|
||||
Save Game State CARD A - Will do a Real Time Save of your current position
|
||||
Load Game State CARD A - Will load your previous Real Time Save
|
||||
|
||||
Save Game State CARD B - Will do a Real Time Save of your current position
|
||||
Load Game State CARD B - Will load your previous Real Time Save
|
||||
|
||||
-[ Game Information ]-
|
||||
|
||||
Displays various technical information about the game including:
|
||||
ROM Size . VROM Size . iNES CRC . Mapper . Mirroring
|
||||
|
||||
-[ Load New ROM ]-
|
||||
|
||||
This will bring up a file browser showing the .NES files you have on
|
||||
the DVD in the GameCube. If you're using a Qoob or Viper chip the
|
||||
emulator will fastload the disc, otherwise you will have to swap
|
||||
discs with an original one. After the file menu comes up simply select
|
||||
you game and press "A" to load it.
|
||||
|
||||
Controls in File Menu:
|
||||
|
||||
A button - Play Selected ROM Image
|
||||
D-Pad UP - Scroll Up Filename List
|
||||
D-Pad DOWN - Scroll Down Filename List
|
||||
D-Pad RIGHT - Skip List Page Forward
|
||||
D-Pad LEFT - Skip List Page Backward
|
||||
Analog Pad UP - Fast Scroll Up Filename List
|
||||
Analog Pad DOWN - Fast Scroll Down Filename List
|
||||
|
||||
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
|
||||
|
||||
-=[ Credits ]=-
|
||||
|
||||
GameCube Port/Coding - SoftDev
|
||||
|
||||
Original FCE by BERO
|
||||
FCE Ultra by Xodnizel
|
||||
DevkitPPC / LibOGC by Wntrmute & Shagkur
|
||||
DVD Codes Courtesy of The NinjaMod Team
|
||||
ZLIB by Jean-loup Gailly
|
||||
IPLFont by Qoob Team
|
||||
|
||||
Beta Testers ...
|
||||
|
||||
brakken
|
||||
mithos
|
||||
luciddream
|
||||
|
||||
Special Thanks To ...
|
||||
|
||||
HonkeyKong
|
||||
|
||||
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
|
||||
|
||||
Disclaimer - Use at your own RISK!
|
||||
|
||||
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
|
||||
|
||||
Documentation Written by Brakken (brakken@tehskeen.com)
|
||||
|
||||
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
|
||||
|
||||
Official Homepage
|
||||
http://www.tehskeen.net
|
||||
|
||||
Official Help Forums
|
||||
http://www.tehskeen.net/forums/forumdisplay.php?f=34
|
||||
|
||||
Mod That Cube -FAQ-
|
||||
http://modthatcube.pxn-os.com
|
||||
|
||||
¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤
|
43
history.txt
Normal file
43
history.txt
Normal file
@ -0,0 +1,43 @@
|
||||
- FCE Ultra GameCube Edition -
|
||||
|
||||
Hello again! This great emulator, for this great console was in "el olvido",
|
||||
so, again, I've decided to add it some new changes to make it a little most complete,
|
||||
please, keep source code when you made a change, this is an open source project.
|
||||
|
||||
This new version have asako and _svpe_ lastest added options.
|
||||
|
||||
Enjoy it!
|
||||
Askot.
|
||||
|
||||
What's new? Askot [20080326]
|
||||
- Added saving state in SD Card (State files will be saved in root of SDCARD).
|
||||
*Note: I can't make it work to save in root:\fceugc\saves, so help needed.
|
||||
- Added SDCARD slot selection for searching roms, meaning, you can search roms
|
||||
from SDCARD SLOT A & SLOT B (Beta, meaning, buggy, but works).
|
||||
- For standarization, you must create folders root:\fceugc\roms to read NES
|
||||
roms files from SDCARD.
|
||||
- Added C-Left to call Menu.
|
||||
- Reading files from SD Card it's faster, now they're called from cache
|
||||
after first reading.
|
||||
- Menu in saving STATE file changed to choose SLOT, DEVICE, Save STATE,
|
||||
Load STATE, Return to previous.
|
||||
- Added option PSO/SD Reload to menu, still works (START+B+X)
|
||||
- Modified controls when going into the rom selection menu (DVD or
|
||||
SDCARD):
|
||||
+ Use B to quit selection list.
|
||||
+ Use L/R triggrers or Pad Left/Right to go down/up one full page.
|
||||
- Some menu rearrangment and a little of sourcecode cleanup:
|
||||
+ Everytime you pressed B button on any option, playgame started, not anymore
|
||||
until you select Play Game option.
|
||||
|
||||
What's new? asako [20070831]
|
||||
- modify mmc3 code for Chinese pirated rom
|
||||
- add some Chinese pirated rom mappers
|
||||
|
||||
What's new? _svpe_ [20070607]
|
||||
- Wii support (PAL50 fix, 1.35GiB restriction removed)
|
||||
- 7zip ROM loading support from the DVD (not from a SD card!!)
|
||||
- dvd_read fix (the read data was always copied to readbuffer instead of *dst)
|
||||
- slower file selection when using the D-Pad (I didn't like the selection to go
|
||||
as fast as in the latest release)
|
||||
|
17
readme_big5.txt
Normal file
17
readme_big5.txt
Normal file
@ -0,0 +1,17 @@
|
||||
====This is CP950 big5 code=====
|
||||
|
||||
|
||||
我想這大概是第一個在GAMECUBE的主機上可以跑對岸中國的盜版的任天堂模擬器。
|
||||
基本上是修改 fceugc070607 的原始碼,然後增加一些對中國的盜版ROM的支援。
|
||||
|
||||
我測式過太空戰士1、2,跟三國誌-中原之霸者2、吞食天地1,這些是可以執行的,
|
||||
有部份不能執行如 中原之霸者1,有些怪怪的如 勇者鬥惡龍2、3、4(可能是rom本
|
||||
身的問題)這是些是名作的部份,其它非名作的中文ROM大多沒什麼問題。
|
||||
|
||||
最後請大家支持台灣加入聯合國,謝謝。
|
||||
其它有指教的請
|
||||
|
||||
Email:asakous@gmail.com
|
||||
|
||||
==========================
|
||||
|
4
source/1.bat
Normal file
4
source/1.bat
Normal file
@ -0,0 +1,4 @@
|
||||
del C:\devkitPro\devkitPPC\Fc\build\ines*.*
|
||||
del C:\devkitPro\devkitPPC\Fc\build\mmc3*.*
|
||||
del C:\devkitPro\devkitPPC\Fc\build\unif*.*
|
||||
del C:\devkitPro\devkitPPC\Fc\build\simple*.*
|
8
source/TODO.TXT
Normal file
8
source/TODO.TXT
Normal file
@ -0,0 +1,8 @@
|
||||
FCEU-GC
|
||||
---------
|
||||
|
||||
TODO
|
||||
|
||||
1. Remove ZLIB Dependencies
|
||||
2. Remove NetPlay Dependencies
|
||||
3. Remove all File I/O
|
153
source/boards/8237.c
Normal file
153
source/boards/8237.c
Normal file
@ -0,0 +1,153 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 "mapinc.h"
|
||||
|
||||
static uint8 cmdin;
|
||||
static uint8 cmd;
|
||||
static uint8 regs[8];
|
||||
static uint8 master,chrm;
|
||||
|
||||
static int32 IRQCount,IRQa;
|
||||
|
||||
static void DoPRG(void)
|
||||
{
|
||||
if(master&0x80)
|
||||
{
|
||||
if(master&0x20)
|
||||
{
|
||||
setprg32(0x8000,(master&0xF)>>1);
|
||||
}
|
||||
else
|
||||
{
|
||||
setprg16(0x8000,master&0xF);
|
||||
setprg16(0xC000,master&0xF);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setprg8(0xA000,regs[4]);
|
||||
setprg8(0xE000,~0);
|
||||
if(cmd&0x40)
|
||||
{
|
||||
setprg8(0xC000,regs[2]);
|
||||
setprg8(0x8000,~1);
|
||||
}
|
||||
else
|
||||
{
|
||||
setprg8(0x8000,regs[2]);
|
||||
setprg8(0xC000,~1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DoCHR(void)
|
||||
{
|
||||
uint32 base=(cmd&0x80)<<5;
|
||||
int orie=(chrm&0x4)<<6;
|
||||
|
||||
setchr2(0x0000^base,(orie|regs[0])>>1); //K
|
||||
setchr2(0x0800^base,(orie|regs[3])>>1); //43
|
||||
|
||||
setchr1(0x1000,orie|regs[1]);
|
||||
setchr1(0x1400,orie|regs[5]);
|
||||
setchr1(0x1800,orie|regs[6]);
|
||||
setchr1(0x1c00,orie|regs[7]);
|
||||
}
|
||||
|
||||
static DECLFW(UNL8237Write)
|
||||
{
|
||||
switch(A&0xF000)
|
||||
{
|
||||
case 0xf000:IRQCount=V;break;
|
||||
case 0xE000:X6502_IRQEnd(FCEU_IQEXT);break;
|
||||
}
|
||||
// if(A<0x8000)
|
||||
// printf("$%04x:$%02x, %d\n",A&0xFFFF,V,scanline);
|
||||
if(A==0x5000)
|
||||
{
|
||||
master=V;
|
||||
DoPRG();
|
||||
DoCHR();
|
||||
}
|
||||
else if(A==0x5001)
|
||||
{
|
||||
chrm=V;
|
||||
DoCHR();
|
||||
}
|
||||
else
|
||||
switch(A&0xE000)
|
||||
{
|
||||
case 0x8000:setmirror(((V|(V>>7))&1)^1);break;
|
||||
case 0xa000:cmd=V;cmdin=1;DoPRG();DoCHR();break;
|
||||
case 0xC000:if(!cmdin) break;
|
||||
regs[cmd&7]=V;
|
||||
DoPRG();
|
||||
DoCHR();
|
||||
cmdin=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void UNL8237Reset(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x=0;x<8;x++) regs[x]=0;
|
||||
master=chrm=cmd=cmdin=IRQCount=IRQa=0;
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x5000,0xFFFF,UNL8237Write);
|
||||
DoPRG();
|
||||
DoCHR();
|
||||
}
|
||||
|
||||
static void hooko(void)
|
||||
{
|
||||
if(IRQCount)
|
||||
{
|
||||
IRQCount--;
|
||||
if(!IRQCount)
|
||||
{
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
//printf("IRQ: %d\n",scanline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void restoreo(int version)
|
||||
{
|
||||
DoPRG();
|
||||
DoCHR();
|
||||
}
|
||||
|
||||
void UNL8237_Init(CartInfo *info)
|
||||
{
|
||||
GameStateRestore=restoreo;
|
||||
GameHBIRQHook=hooko;
|
||||
info->Power=UNL8237Reset;
|
||||
|
||||
AddExState(regs, 8, 0, "REGS");
|
||||
AddExState(&IRQCount, 4, 1, "IRQC");
|
||||
AddExState(&IRQa, 1, 0, "IRQA");
|
||||
AddExState(&master, 1, 0, "MAST");
|
||||
AddExState(&chrm,1,0,"CHRM");
|
||||
AddExState(&cmd,1,0,"CMD");
|
||||
AddExState(&cmdin,1,0,"CMDI");
|
||||
}
|
113
source/boards/h2288.c
Normal file
113
source/boards/h2288.c
Normal file
@ -0,0 +1,113 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2003 Xodnizel
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* Not finished. Darn evil game... *Mumble*... */
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 cmd;
|
||||
static uint8 regs[8];
|
||||
|
||||
static void DoPRG(void)
|
||||
{
|
||||
if(cmd&0x40)
|
||||
{
|
||||
setprg8(0xC000,regs[4]);
|
||||
setprg8(0xA000,regs[5]);
|
||||
setprg8(0x8000,~1);
|
||||
setprg8(0xE000,~0);
|
||||
}
|
||||
else
|
||||
{
|
||||
setprg8(0x8000,regs[4]);
|
||||
setprg8(0xA000,regs[5]);
|
||||
setprg8(0xC000,~1);
|
||||
setprg8(0xE000,~0);
|
||||
}
|
||||
}
|
||||
|
||||
static void DoCHR(void)
|
||||
{
|
||||
uint32 base=(cmd&0x80)<<5;
|
||||
|
||||
setchr2(0x0000^base,regs[0]);
|
||||
setchr2(0x0800^base,regs[2]);
|
||||
|
||||
setchr1(0x1000^base,regs[6]);
|
||||
setchr1(0x1400^base,regs[1]);
|
||||
setchr1(0x1800^base,regs[7]);
|
||||
setchr1(0x1c00^base,regs[3]);
|
||||
}
|
||||
|
||||
static DECLFW(PWrite)
|
||||
{
|
||||
//printf("$%04x:$%02x\n",A,V);
|
||||
}
|
||||
|
||||
static DECLFW(H2288Write)
|
||||
{
|
||||
//printf("$%04x:$%02x, $%04x\n",A,V,X.PC);
|
||||
//FCEUI_DumpMem("dmp",0xc000,0xffff);
|
||||
|
||||
switch(A&0xE001)
|
||||
{
|
||||
case 0xa000:setmirror((V&1)^1);break;
|
||||
case 0x8000:
|
||||
cmd=V;DoPRG();DoCHR();break;
|
||||
case 0x8001:regs[cmd&7]=V;
|
||||
if((cmd&7)==4 || (cmd&7)==5)
|
||||
DoPRG();
|
||||
else
|
||||
DoCHR();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(H2288Read)
|
||||
{
|
||||
int bit;
|
||||
//printf("Read: $%04x, $%04x\n",A,X.PC);
|
||||
//DumpMem("out",0x8000,0xFFFF);
|
||||
bit=(A&1)^1;
|
||||
bit&=((A>>8)&1);
|
||||
bit^=1;
|
||||
return((X.DB&0xFE)|bit);
|
||||
}
|
||||
|
||||
static void H2288Reset(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
SetReadHandler(0x5000,0x5FFF,H2288Read);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x5000,0x5FFF,PWrite);
|
||||
SetWriteHandler(0x8000,0xFFFF,H2288Write);
|
||||
for(x=0;x<8;x++) regs[x]=0;
|
||||
regs[4]=0;
|
||||
regs[5]=1;
|
||||
cmd=0;
|
||||
DoPRG();
|
||||
DoCHR();
|
||||
}
|
||||
|
||||
void H2288_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=H2288Reset;
|
||||
}
|
45
source/boards/malee.c
Normal file
45
source/boards/malee.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 "mapinc.h"
|
||||
|
||||
DECLFW(MWrite)
|
||||
{
|
||||
(GameMemBlock-0x7000)[A]=V;
|
||||
}
|
||||
|
||||
static void MALEEReset(void)
|
||||
{
|
||||
setprg2r(0x10,0x7000,0);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetReadHandler(0x6000,0x67ff,CartBR);
|
||||
SetReadHandler(0x7000,0x77FF,CartBR);
|
||||
SetWriteHandler(0x7000,0x77FF,MWrite);
|
||||
setprg2r(1,0x6000,0);
|
||||
setprg32(0x8000,0);
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
void MALEE_Init(CartInfo *info)
|
||||
{
|
||||
AddExState(GameMemBlock, 2048, 0,"RAM");
|
||||
SetupCartPRGMapping(0x10,GameMemBlock,2048,1);
|
||||
info->Power=MALEEReset;
|
||||
}
|
9
source/boards/mapinc.h
Normal file
9
source/boards/mapinc.h
Normal file
@ -0,0 +1,9 @@
|
||||
#include "../types.h"
|
||||
#include "../x6502.h"
|
||||
#include "../fceu.h"
|
||||
#include "../ppu.h"
|
||||
#include "../memory.h"
|
||||
#include "../sound.h"
|
||||
#include "../state.h"
|
||||
#include "../cart.h"
|
||||
#include "../unif.h"
|
53
source/boards/novel.c
Normal file
53
source/boards/novel.c
Normal file
@ -0,0 +1,53 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 "mapinc.h"
|
||||
|
||||
static void DoNovel(void)
|
||||
{
|
||||
setprg32(0x8000,GameMemBlock[0]&3);
|
||||
setchr8(GameMemBlock[0]&7);
|
||||
}
|
||||
|
||||
static DECLFW(NovelWrite)
|
||||
{
|
||||
GameMemBlock[0]=A&0xFF;
|
||||
DoNovel();
|
||||
}
|
||||
|
||||
static void NovelReset(void)
|
||||
{
|
||||
SetWriteHandler(0x8000,0xFFFF,NovelWrite);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
setprg32(0x8000,0);
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static void NovelRestore(int version)
|
||||
{
|
||||
DoNovel();
|
||||
}
|
||||
|
||||
void Novel_Init(CartInfo *info)
|
||||
{
|
||||
AddExState(&GameMemBlock[0], 1, 0,"L1");
|
||||
info->Power=NovelReset;
|
||||
GameStateRestore=NovelRestore;
|
||||
}
|
319
source/boards/sachen.c
Normal file
319
source/boards/sachen.c
Normal file
@ -0,0 +1,319 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 "mapinc.h"
|
||||
|
||||
static uint8 cmd;
|
||||
static uint8 latch[8];
|
||||
#define CHRRAM (GameMemBlock)
|
||||
|
||||
static void S74LS374NSynco(void)
|
||||
{
|
||||
setprg32(0x8000,latch[0]);
|
||||
setchr8(latch[1]);
|
||||
setmirror(latch[2]&1);
|
||||
// setchr8(6);
|
||||
}
|
||||
|
||||
static DECLFW(S74LS374NWrite)
|
||||
{
|
||||
//printf("$%04x:$%02x\n",A,V);
|
||||
A&=0x4101;
|
||||
if(A==0x4100)
|
||||
cmd=V&7;
|
||||
else
|
||||
{
|
||||
switch(cmd)
|
||||
{
|
||||
case 0:latch[0]=0;latch[1]=3;break;
|
||||
case 4:latch[1]&=3;latch[1]|=(V<<2);break;
|
||||
case 5:latch[0]=V&0x7;break;
|
||||
case 6:latch[1]&=0x1C;latch[1]|=V&3;break;
|
||||
case 7:latch[2]=V&1;break;
|
||||
}
|
||||
S74LS374NSynco();
|
||||
}
|
||||
}
|
||||
|
||||
static void S74LS374NReset(void)
|
||||
{
|
||||
latch[0]=latch[2]=0;
|
||||
latch[1]=3;
|
||||
S74LS374NSynco();
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x4100,0x7FFF,S74LS374NWrite);
|
||||
}
|
||||
|
||||
static void S74LS374NRestore(int version)
|
||||
{
|
||||
S74LS374NSynco();
|
||||
}
|
||||
|
||||
void S74LS374N_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=S74LS374NReset;
|
||||
GameStateRestore=S74LS374NRestore;
|
||||
AddExState(latch, 3, 0, "LATC");
|
||||
AddExState(&cmd, 1, 0, "CMD");
|
||||
}
|
||||
|
||||
static int type;
|
||||
static void S8259Synco(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
setprg32(0x8000,latch[5]&7);
|
||||
|
||||
if(!UNIFchrrama) // No CHR RAM? Then BS'ing is ok.
|
||||
{
|
||||
if(!type)
|
||||
{
|
||||
for(x=0;x<4;x++)
|
||||
setchr2(0x800*x,(x&1)|((latch[x]&7)<<1)|((latch[4]&7)<<4));
|
||||
}
|
||||
else
|
||||
{
|
||||
for(x=0;x<4;x++)
|
||||
setchr2(0x800*x,(latch[x]&0x7)|((latch[4]&7)<<3));
|
||||
}
|
||||
}
|
||||
switch((latch[7]>>1)&3)
|
||||
{
|
||||
case 0:setmirrorw(0,0,0,1);break;
|
||||
case 1:setmirror(MI_H);break;
|
||||
case 2:setmirror(MI_V);break;
|
||||
case 3:setmirror(MI_0);break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(S8259Write)
|
||||
{
|
||||
A&=0x4101;
|
||||
if(A==0x4100) cmd=V;
|
||||
else
|
||||
{
|
||||
latch[cmd&7]=V;
|
||||
S8259Synco();
|
||||
}
|
||||
}
|
||||
|
||||
static void S8259Reset(void)
|
||||
{
|
||||
int x;
|
||||
cmd=0;
|
||||
|
||||
for(x=0;x<8;x++) latch[x]=0;
|
||||
if(UNIFchrrama) setchr8(0);
|
||||
|
||||
S8259Synco();
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x4100,0x7FFF,S8259Write);
|
||||
}
|
||||
|
||||
static void S8259Restore(int version)
|
||||
{
|
||||
S8259Synco();
|
||||
}
|
||||
|
||||
void S8259A_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=S8259Reset;
|
||||
GameStateRestore=S8259Restore;
|
||||
AddExState(latch, 8, 0, "LATC");
|
||||
AddExState(&cmd, 1, 0, "CMD");
|
||||
type=0;
|
||||
|
||||
//if(!CHRsize[0])
|
||||
//{
|
||||
// SetupCartCHRMapping(0,CHRRAM,8192,1);
|
||||
// AddExState(CHRRAM, 8192, 0, "CHRR");
|
||||
//}
|
||||
}
|
||||
|
||||
void S8259B_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=S8259Reset;
|
||||
GameStateRestore=S8259Restore;
|
||||
AddExState(latch, 8, 0, "LATC");
|
||||
AddExState(&cmd, 1, 0, "CMD");
|
||||
type=1;
|
||||
}
|
||||
|
||||
static void(*WSync)(void);
|
||||
|
||||
static void SA0161MSynco()
|
||||
{
|
||||
setprg32(0x8000,(latch[0]>>3)&1);
|
||||
setchr8(latch[0]&7);
|
||||
}
|
||||
|
||||
static DECLFW(SAWrite)
|
||||
{
|
||||
if(A&0x100)
|
||||
{
|
||||
latch[0]=V;
|
||||
WSync();
|
||||
}
|
||||
}
|
||||
|
||||
static void SAReset(void)
|
||||
{
|
||||
latch[0]=0;
|
||||
WSync();
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x4100,0x5FFF,SAWrite);
|
||||
}
|
||||
|
||||
static void SA0161MRestore(int version)
|
||||
{
|
||||
SA0161MSynco();
|
||||
}
|
||||
|
||||
void SA0161M_Init(CartInfo *info)
|
||||
{
|
||||
WSync=SA0161MSynco;
|
||||
GameStateRestore=SA0161MRestore;
|
||||
info->Power=SAReset;
|
||||
AddExState(&latch[0], 1, 0, "LATC");
|
||||
}
|
||||
|
||||
static void SA72007Synco()
|
||||
{
|
||||
setprg32(0x8000,0);
|
||||
setchr8(latch[0]>>7);
|
||||
}
|
||||
|
||||
static void SA72007Restore(int version)
|
||||
{
|
||||
SA72007Synco();
|
||||
}
|
||||
|
||||
void SA72007_Init(CartInfo *info)
|
||||
{
|
||||
WSync=SA72007Synco;
|
||||
GameStateRestore=SA72007Restore;
|
||||
info->Power=SAReset;
|
||||
AddExState(&latch[0], 1, 0, "LATC");
|
||||
}
|
||||
|
||||
static void SA72008Synco()
|
||||
{
|
||||
setprg32(0x8000,(latch[0]>>2)&1);
|
||||
setchr8(latch[0]&3);
|
||||
}
|
||||
|
||||
static void SA72008Restore(int version)
|
||||
{
|
||||
SA72008Synco();
|
||||
}
|
||||
|
||||
void SA72008_Init(CartInfo *info)
|
||||
{
|
||||
WSync=SA72008Synco;
|
||||
GameStateRestore=SA72008Restore;
|
||||
info->Power=SAReset;
|
||||
AddExState(&latch[0], 1, 0, "LATC");
|
||||
}
|
||||
|
||||
static DECLFW(SADWrite)
|
||||
{
|
||||
latch[0]=V;
|
||||
WSync();
|
||||
}
|
||||
|
||||
static void SADReset(void)
|
||||
{
|
||||
latch[0]=0;
|
||||
WSync();
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x8000,0xFFFF,SADWrite);
|
||||
}
|
||||
|
||||
static void SA0036Synco()
|
||||
{
|
||||
setprg32(0x8000,0);
|
||||
setchr8(latch[0]>>7);
|
||||
}
|
||||
|
||||
static void SA0036Restore(int version)
|
||||
{
|
||||
SA0036Synco();
|
||||
}
|
||||
|
||||
static void SA0037Synco()
|
||||
{
|
||||
setprg32(0x8000,(latch[0]>>3)&1);
|
||||
setchr8(latch[0]&7);
|
||||
}
|
||||
|
||||
static void SA0037Restore(int version)
|
||||
{
|
||||
SA0037Synco();
|
||||
}
|
||||
|
||||
void SA0036_Init(CartInfo *info)
|
||||
{
|
||||
WSync=SA0036Synco;
|
||||
GameStateRestore=SA0036Restore;
|
||||
info->Power=SADReset;
|
||||
AddExState(&latch[0], 1, 0, "LATC");
|
||||
}
|
||||
|
||||
void SA0037_Init(CartInfo *info)
|
||||
{
|
||||
WSync=SA0037Synco;
|
||||
GameStateRestore=SA0037Restore;
|
||||
info->Power=SADReset;
|
||||
AddExState(&latch[0], 1, 0, "LATC");
|
||||
}
|
||||
|
||||
static void TCU01Synco()
|
||||
{
|
||||
setprg32(0x8000,(latch[0]>>2)&1);
|
||||
setchr8((latch[0]>>3)&0xF);
|
||||
}
|
||||
|
||||
static DECLFW(TCWrite)
|
||||
{
|
||||
if((A&0x103)==0x102)
|
||||
latch[0]=V;
|
||||
TCU01Synco();
|
||||
}
|
||||
|
||||
static void TCU01Reset(void)
|
||||
{
|
||||
latch[0]=0;
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x4100,0xFFFF,TCWrite);
|
||||
TCU01Synco();
|
||||
}
|
||||
|
||||
static void TCU01Restore(int version)
|
||||
{
|
||||
TCU01Synco();
|
||||
}
|
||||
|
||||
void TCU01_Init(CartInfo *info)
|
||||
{
|
||||
GameStateRestore=TCU01Restore;
|
||||
info->Power=TCU01Reset;
|
||||
AddExState(&latch[0], 1, 0, "LATC");
|
||||
}
|
||||
|
350
source/boards/simple.c
Normal file
350
source/boards/simple.c
Normal file
@ -0,0 +1,350 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 "mapinc.h"
|
||||
|
||||
static uint8 latche, latcheinit;
|
||||
static uint16 addrreg0, addrreg1;
|
||||
static void(*WSync)(void);
|
||||
|
||||
static DECLFW(LatchWrite)
|
||||
{
|
||||
// FCEU_printf("bs %04x %02x\n",A,V);
|
||||
latche=V;
|
||||
WSync();
|
||||
}
|
||||
|
||||
static void LatchPower(void)
|
||||
{
|
||||
latche=latcheinit;
|
||||
WSync();
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(addrreg0,addrreg1,LatchWrite);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
WSync();
|
||||
}
|
||||
|
||||
static void Latch_Init(CartInfo *info, void (*proc)(void), uint8 init, uint16 adr0, uint16 adr1)
|
||||
{
|
||||
latcheinit=init;
|
||||
addrreg0=adr0;
|
||||
addrreg1=adr1;
|
||||
WSync=proc;
|
||||
info->Power=LatchPower;
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&latche, 1, 0, "LATC");
|
||||
}
|
||||
|
||||
//------------------ CPROM ---------------------------
|
||||
|
||||
static void CPROMSync(void)
|
||||
{
|
||||
setchr4(0x0000,0);
|
||||
setchr4(0x1000,latche&3);
|
||||
setprg16(0x8000,0);
|
||||
setprg16(0xC000,1);
|
||||
}
|
||||
|
||||
void CPROM_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, CPROMSync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ Map 184 ---------------------------
|
||||
|
||||
static void M184Sync(void)
|
||||
{
|
||||
setchr4(0x0000,latche);
|
||||
setchr4(0x1000,latche>>4);
|
||||
setprg16(0x8000,0);
|
||||
setprg16(0xC000,1);
|
||||
}
|
||||
|
||||
void Mapper184_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M184Sync, 0, 0x6000, 0x7FFF);
|
||||
}
|
||||
|
||||
//------------------ CNROM ---------------------------
|
||||
|
||||
static void CNROMSync(void)
|
||||
{
|
||||
setchr8(latche&3);
|
||||
setprg16(0x8000,0);
|
||||
setprg16(0xC000,1);
|
||||
}
|
||||
|
||||
void CNROM_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, CNROMSync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ ANROM ---------------------------
|
||||
|
||||
static void ANROMSync()
|
||||
{
|
||||
setprg32(0x8000,latche&0xf);
|
||||
setmirror(MI_0+((latche>>4)&1));
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
void ANROM_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, ANROMSync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ Map 70 ---------------------------
|
||||
|
||||
static void M70Sync()
|
||||
{
|
||||
setprg16(0x8000,latche>>4);
|
||||
setprg16(0xc000,~0);
|
||||
setchr8(latche&0xf);
|
||||
}
|
||||
|
||||
void Mapper70_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M70Sync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ Map 152 ---------------------------
|
||||
|
||||
static void M152Sync()
|
||||
{
|
||||
setprg16(0x8000,(latche>>4)&7);
|
||||
setprg16(0xc000,~0);
|
||||
setchr8(latche&0xf);
|
||||
setmirror(MI_0+((latche>>7)&1)); /* Saint Seiya...hmm. */
|
||||
}
|
||||
|
||||
void Mapper152_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M152Sync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ Map 78 ---------------------------
|
||||
/* Should be two separate emulation functions for this "mapper". Sigh. URGE TO KILL RISING. */
|
||||
static void M78Sync()
|
||||
{
|
||||
setprg16(0x8000,(latche&7));
|
||||
setprg16(0xc000,~0);
|
||||
setchr8(latche>>4);
|
||||
setmirror(MI_0+((latche>>3)&1));
|
||||
}
|
||||
|
||||
void Mapper78_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M78Sync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ MHROM ---------------------------
|
||||
|
||||
static void MHROMSync(void)
|
||||
{
|
||||
setprg32(0x8000,latche>>4);
|
||||
setchr8(latche&0xf);
|
||||
}
|
||||
|
||||
void MHROM_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, MHROMSync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
void Mapper140_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, MHROMSync, 0, 0x6000, 0x7FFF);
|
||||
}
|
||||
|
||||
void Mapper240_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, MHROMSync, 0, 0x4020, 0x5FFF);
|
||||
// need SRAM.
|
||||
}
|
||||
|
||||
//------------------ Map 87 ---------------------------
|
||||
|
||||
static void M87Sync(void)
|
||||
{
|
||||
setprg16(0x8000,0);
|
||||
setprg16(0xC000,1);
|
||||
setchr8(latche>>1);
|
||||
}
|
||||
|
||||
void Mapper87_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M87Sync, ~0, 0x6000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ Map 11 ---------------------------
|
||||
|
||||
static void M11Sync(void)
|
||||
{
|
||||
setprg32(0x8000,latche&0xf);
|
||||
setchr8(latche>>4);
|
||||
}
|
||||
|
||||
void Mapper11_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M11Sync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
void Mapper144_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M11Sync, 0, 0x8001, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ UNROM ---------------------------
|
||||
|
||||
static void UNROMSync(void)
|
||||
{
|
||||
setprg16(0x8000,latche);
|
||||
setprg16(0xc000,~0);
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
void UNROM_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, UNROMSync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ Map 93 ---------------------------
|
||||
|
||||
static void SSUNROMSync(void)
|
||||
{
|
||||
setprg16(0x8000,latche>>4);
|
||||
setprg16(0xc000,~0);
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
void SUNSOFT_UNROM_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, SSUNROMSync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ Map 94 ---------------------------
|
||||
|
||||
static void M94Sync(void)
|
||||
{
|
||||
setprg16(0x8000,latche>>2);
|
||||
setprg16(0xc000,~0);
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
void Mapper94_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M94Sync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ Map 180 ---------------------------
|
||||
|
||||
static void M180Sync(void)
|
||||
{
|
||||
setprg16(0x8000,0);
|
||||
setprg16(0xc000,latche);
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
void Mapper180_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M180Sync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ Map 107 ---------------------------
|
||||
|
||||
static void M107Sync(void)
|
||||
{
|
||||
setprg32(0x8000,(latche>>1)&3);
|
||||
setchr8(latche&7);
|
||||
}
|
||||
|
||||
void Mapper107_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M107Sync, ~0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ Map 113 ---------------------------
|
||||
|
||||
static void M113Sync(void)
|
||||
{
|
||||
setprg32(0x8000,(latche>>3)&7);
|
||||
setchr8(((latche>>3)&8)|(latche&7));
|
||||
// setmirror(latche>>7); // only for HES 6in1
|
||||
}
|
||||
|
||||
void Mapper113_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M113Sync, 0, 0x4100, 0x7FFF);
|
||||
}
|
||||
|
||||
//------------------ A65AS ---------------------------
|
||||
|
||||
// actually, there is two cart in one... First have extra mirroring
|
||||
// mode (one screen) and 32K bankswitching, second one have only
|
||||
// 16 bankswitching mode and normal mirroring... But there is no any
|
||||
// correlations between modes and they can be used in one mapper code.
|
||||
|
||||
static void BMCA65ASSync(void)
|
||||
{
|
||||
if(latche&0x40)
|
||||
setprg32(0x8000,(latche>>1)&0x0F);
|
||||
else
|
||||
{
|
||||
setprg16(0x8000,((latche&0x30)>>1)|(latche&7));
|
||||
setprg16(0xC000,((latche&0x30)>>1)|7);
|
||||
}
|
||||
setchr8(0);
|
||||
if(latche&0x80)
|
||||
setmirror(MI_0+(((latche>>5)&1)));
|
||||
else
|
||||
setmirror(((latche>>3)&1)^1);
|
||||
}
|
||||
|
||||
void BMCA65AS_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, BMCA65ASSync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ NROM ---------------------------
|
||||
|
||||
#ifdef DEBUG_MAPPER
|
||||
static DECLFW(WriteHandler)
|
||||
{
|
||||
FCEU_printf("bs %04x %02x\n",A,V);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void NROMPower(void)
|
||||
{
|
||||
setprg16(0x8000,0);
|
||||
setprg16(0xC000,~0);
|
||||
setchr8(0);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
#ifdef DEBUG_MAPPER
|
||||
SetWriteHandler(0x4020,0xFFFF,WriteHandler);
|
||||
#endif
|
||||
}
|
||||
|
||||
void NROM_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=NROMPower;
|
||||
}
|
235
source/boards/super24.c
Normal file
235
source/boards/super24.c
Normal file
@ -0,0 +1,235 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 "mapinc.h"
|
||||
|
||||
static int32 IRQCount,IRQLatch;
|
||||
static uint8 IRQa,resetmode,mbia;
|
||||
static uint8 sizer,bigbank,bigbank2;
|
||||
|
||||
static uint8 DRegBuf[8],MMC3_cmd;
|
||||
|
||||
static int masko8[8]={63,31,15,1,3,0,0,0};
|
||||
//static int masko1[8]={511,255,127,7,7,0,0,0};
|
||||
|
||||
static void swsetprg8(uint32 A, uint32 V)
|
||||
{
|
||||
V&=masko8[sizer&7];
|
||||
V|=(bigbank*2);
|
||||
setprg8r((V/64)&15,A,V);
|
||||
}
|
||||
|
||||
static void swsetchr1(uint32 A, uint32 V)
|
||||
{
|
||||
if(sizer&0x20)
|
||||
setchr1r(0x10,A,V);
|
||||
else
|
||||
{
|
||||
// V&=masko1[sizer&7];
|
||||
V|=bigbank2*8;
|
||||
setchr1r((V/512)&15,A,V);
|
||||
}
|
||||
}
|
||||
|
||||
static void swsetchr2(uint32 A, uint32 V)
|
||||
{
|
||||
if(sizer&0x20)
|
||||
setchr2r(0x10,A,V);
|
||||
else
|
||||
{
|
||||
//V&=masko1[sizer&7]>>1;
|
||||
V|=bigbank2*4;
|
||||
setchr2r((V/256)&15,A,V);
|
||||
}
|
||||
}
|
||||
|
||||
static void Sup24_hb(void)
|
||||
{
|
||||
resetmode=0;
|
||||
if(scanline==238) X6502_IRQBegin(FCEU_IQEXT);
|
||||
if(IRQCount>=0)
|
||||
{
|
||||
IRQCount--;
|
||||
if(IRQCount<0)
|
||||
{
|
||||
if(IRQa)
|
||||
{
|
||||
resetmode = 1;
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
//printf("IRQ: %d,%d\n",scanline,timestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(Sup24IRQWrite)
|
||||
{
|
||||
//printf("%04x, $%02x, %d, %d\n",A,V,scanline,timestamp);
|
||||
switch(A&0xE001)
|
||||
{
|
||||
case 0xc000:IRQLatch=V;
|
||||
if(resetmode==1)
|
||||
IRQCount=IRQLatch;
|
||||
break;
|
||||
case 0xc001:resetmode=1;
|
||||
IRQCount=IRQLatch;
|
||||
break;
|
||||
case 0xE000:IRQa=0;X6502_IRQEnd(FCEU_IQEXT);
|
||||
if(resetmode==1)
|
||||
{IRQCount=IRQLatch;}
|
||||
break;
|
||||
case 0xE001:IRQa=1;
|
||||
if(resetmode==1)
|
||||
{IRQCount=IRQLatch;}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE void FixMMC3PRG(int V)
|
||||
{
|
||||
swsetprg8(0xA000,DRegBuf[7]);
|
||||
swsetprg8(0xE000,~0);
|
||||
if(V&0x40)
|
||||
{
|
||||
swsetprg8(0xC000,DRegBuf[6]);
|
||||
swsetprg8(0x8000,~1);
|
||||
}
|
||||
else
|
||||
{
|
||||
swsetprg8(0x8000,DRegBuf[6]);
|
||||
swsetprg8(0xC000,~1);
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE void FixMMC3CHR(int V)
|
||||
{
|
||||
int cbase=(V&0x80)<<5;
|
||||
swsetchr2((cbase^0x000),DRegBuf[0]>>1);
|
||||
swsetchr2((cbase^0x800),DRegBuf[1]>>1);
|
||||
swsetchr1(cbase^0x1000,DRegBuf[2]);
|
||||
swsetchr1(cbase^0x1400,DRegBuf[3]);
|
||||
swsetchr1(cbase^0x1800,DRegBuf[4]);
|
||||
swsetchr1(cbase^0x1c00,DRegBuf[5]);
|
||||
}
|
||||
|
||||
static DECLFW(Super24hiwrite)
|
||||
{
|
||||
//printf("$%04x:$%02x, %d\n",A,V,scanline);
|
||||
switch(A&0xE001)
|
||||
{
|
||||
case 0x8000:
|
||||
if((V&0x40) != (MMC3_cmd&0x40))
|
||||
FixMMC3PRG(V);
|
||||
if((V&0x80) != (MMC3_cmd&0x80))
|
||||
FixMMC3CHR(V);
|
||||
MMC3_cmd = V;
|
||||
break;
|
||||
|
||||
case 0x8001:
|
||||
{
|
||||
int cbase=(MMC3_cmd&0x80)<<5;
|
||||
DRegBuf[MMC3_cmd&0x7]=V;
|
||||
switch(MMC3_cmd&0x07)
|
||||
{
|
||||
case 0: V>>=1;swsetchr2((cbase^0x000),V);break;
|
||||
case 1: V>>=1;swsetchr2((cbase^0x800),V);break;
|
||||
case 2: swsetchr1(cbase^0x1000,V); break;
|
||||
case 3: swsetchr1(cbase^0x1400,V); break;
|
||||
case 4: swsetchr1(cbase^0x1800,V); break;
|
||||
case 5: swsetchr1(cbase^0x1C00,V); break;
|
||||
case 6: if (MMC3_cmd&0x40) swsetprg8(0xC000,V);
|
||||
else swsetprg8(0x8000,V);
|
||||
break;
|
||||
case 7: swsetprg8(0xA000,V);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xA000:
|
||||
mbia=V;
|
||||
setmirror((V&1)^1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static DECLFW(Super24Write)
|
||||
{
|
||||
//printf("$%04x:$%02x\n",A,V);
|
||||
switch(A)
|
||||
{
|
||||
case 0x5ff0:sizer=V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
break;
|
||||
case 0x5FF1:
|
||||
bigbank=V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
break;
|
||||
case 0x5FF2:
|
||||
bigbank2=V;
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Super24Reset(void)
|
||||
{
|
||||
SetWriteHandler(0x8000,0xBFFF,Super24hiwrite);
|
||||
SetWriteHandler(0x5000,0x7FFF,Super24Write);
|
||||
SetWriteHandler(0xC000,0xFFFF,Sup24IRQWrite);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
GameHBIRQHook=Sup24_hb;
|
||||
IRQCount=IRQLatch=IRQa=resetmode=0;
|
||||
sizer=0x24;
|
||||
bigbank=159;
|
||||
bigbank2=0;
|
||||
|
||||
MMC3_cmd=0;
|
||||
DRegBuf[6]=0;
|
||||
DRegBuf[7]=1;
|
||||
|
||||
FixMMC3PRG(0);
|
||||
FixMMC3CHR(0);
|
||||
}
|
||||
|
||||
static void MrRestore(int version)
|
||||
{
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
setmirror((mbia&1)^1);
|
||||
}
|
||||
|
||||
void Super24_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=Super24Reset;
|
||||
SetupCartCHRMapping(0x10, GameMemBlock, 8192, 1);
|
||||
GameStateRestore=MrRestore;
|
||||
|
||||
AddExState(GameMemBlock, 8192, 0, "CHRR");
|
||||
AddExState(DRegBuf, 8, 0, "DREG");
|
||||
AddExState(&IRQCount, 4, 1, "IRQC");
|
||||
AddExState(&IRQLatch, 4, 1, "IQL1");
|
||||
AddExState(&IRQa, 1, 0, "IRQA");
|
||||
AddExState(&sizer, 1, 0, "SIZA");
|
||||
AddExState(&bigbank, 1, 0, "BIG1");
|
||||
AddExState(&bigbank2, 1, 0, "BIG2");
|
||||
}
|
77
source/boards/supervision.c
Normal file
77
source/boards/supervision.c
Normal file
@ -0,0 +1,77 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 "mapinc.h"
|
||||
|
||||
#define CHRRAM (GameMemBlock+16)
|
||||
|
||||
static void DoSuper(void)
|
||||
{
|
||||
setprg8r((GameMemBlock[0]&0xC)>>2,0x6000,((GameMemBlock[0]&0x3)<<4)|0xF);
|
||||
if(GameMemBlock[0]&0x10)
|
||||
{
|
||||
setprg16r((GameMemBlock[0]&0xC)>>2,0x8000,((GameMemBlock[0]&0x3)<<3)|(GameMemBlock[1]&7));
|
||||
setprg16r((GameMemBlock[0]&0xC)>>2,0xc000,((GameMemBlock[0]&0x3)<<3)|7);
|
||||
}
|
||||
else
|
||||
setprg32r(4,0x8000,0);
|
||||
|
||||
setmirror(((GameMemBlock[0]&0x20)>>5)^1);
|
||||
}
|
||||
|
||||
static DECLFW(SuperWrite)
|
||||
{
|
||||
if(!(GameMemBlock[0]&0x10))
|
||||
{
|
||||
GameMemBlock[0]=V;
|
||||
DoSuper();
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(SuperHi)
|
||||
{
|
||||
GameMemBlock[1]=V;
|
||||
DoSuper();
|
||||
}
|
||||
|
||||
static void SuperReset(void)
|
||||
{
|
||||
SetWriteHandler(0x6000,0x7FFF,SuperWrite);
|
||||
SetWriteHandler(0x8000,0xFFFF,SuperHi);
|
||||
SetReadHandler(0x6000,0xFFFF,CartBR);
|
||||
GameMemBlock[0]=GameMemBlock[1]=0;
|
||||
setprg32r(4,0x8000,0);
|
||||
setvram8(CHRRAM);
|
||||
FCEU_dwmemset(CHRRAM,0,8192);
|
||||
}
|
||||
|
||||
static void SuperRestore(int version)
|
||||
{
|
||||
DoSuper();
|
||||
}
|
||||
|
||||
void Supervision16_Init(CartInfo *info)
|
||||
{
|
||||
AddExState(&GameMemBlock[0], 1, 0,"L1");
|
||||
AddExState(&GameMemBlock[1], 1, 0,"L2");
|
||||
AddExState(CHRRAM, 8192, 0, "CHRR");
|
||||
info->Power=SuperReset;
|
||||
GameStateRestore=SuperRestore;
|
||||
}
|
679
source/cart.c
Normal file
679
source/cart.c
Normal file
@ -0,0 +1,679 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "fceu.h"
|
||||
#include "ppu.h"
|
||||
|
||||
#include "cart.h"
|
||||
#include "memory.h"
|
||||
#include "x6502.h"
|
||||
|
||||
#include "general.h"
|
||||
|
||||
/*
|
||||
This file contains all code for coordinating the mapping in of the
|
||||
address space external to the NES.
|
||||
It's also (ab)used by the NSF code.
|
||||
*/
|
||||
|
||||
uint8 *Page[32],*VPage[8];
|
||||
uint8 **VPageR=VPage;
|
||||
uint8 *VPageG[8];
|
||||
uint8 *MMC5SPRVPage[8];
|
||||
uint8 *MMC5BGVPage[8];
|
||||
|
||||
static uint8 PRGIsRAM[32]; /* This page is/is not PRG RAM. */
|
||||
|
||||
/* 16 are (sort of) reserved for UNIF/iNES and 16 to map other stuff. */
|
||||
static int CHRram[32];
|
||||
static int PRGram[32];
|
||||
|
||||
uint8 *PRGptr[32];
|
||||
uint8 *CHRptr[32];
|
||||
|
||||
uint32 PRGsize[32];
|
||||
uint32 CHRsize[32];
|
||||
|
||||
uint32 PRGmask2[32];
|
||||
uint32 PRGmask4[32];
|
||||
uint32 PRGmask8[32];
|
||||
uint32 PRGmask16[32];
|
||||
uint32 PRGmask32[32];
|
||||
|
||||
uint32 CHRmask1[32];
|
||||
uint32 CHRmask2[32];
|
||||
uint32 CHRmask4[32];
|
||||
uint32 CHRmask8[32];
|
||||
|
||||
int geniestage=0;
|
||||
|
||||
int modcon;
|
||||
|
||||
uint8 genieval[3];
|
||||
uint8 geniech[3];
|
||||
|
||||
uint32 genieaddr[3];
|
||||
|
||||
static INLINE void setpageptr(int s, uint32 A, uint8 *p, int ram)
|
||||
{
|
||||
uint32 AB=A>>11;
|
||||
int x;
|
||||
|
||||
if(p)
|
||||
for(x=(s>>1)-1;x>=0;x--)
|
||||
{
|
||||
PRGIsRAM[AB+x]=ram;
|
||||
Page[AB+x]=p-A;
|
||||
}
|
||||
else
|
||||
for(x=(s>>1)-1;x>=0;x--)
|
||||
{
|
||||
PRGIsRAM[AB+x]=0;
|
||||
Page[AB+x]=0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8 nothing[8192];
|
||||
void ResetCartMapping(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x=0;x<32;x++)
|
||||
{
|
||||
Page[x]=nothing-x*2048;
|
||||
PRGptr[x]=CHRptr[x]=0;
|
||||
PRGsize[x]=CHRsize[x]=0;
|
||||
}
|
||||
for(x=0;x<8;x++)
|
||||
{
|
||||
MMC5SPRVPage[x]=MMC5BGVPage[x]=VPageR[x]=nothing-0x400*x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SetupCartPRGMapping(int chip, uint8 *p, uint32 size, int ram)
|
||||
{
|
||||
PRGptr[chip]=p;
|
||||
PRGsize[chip]=size;
|
||||
|
||||
PRGmask2[chip]=(size>>11)-1;
|
||||
PRGmask4[chip]=(size>>12)-1;
|
||||
PRGmask8[chip]=(size>>13)-1;
|
||||
PRGmask16[chip]=(size>>14)-1;
|
||||
PRGmask32[chip]=(size>>15)-1;
|
||||
|
||||
PRGram[chip]=ram?1:0;
|
||||
}
|
||||
|
||||
void SetupCartCHRMapping(int chip, uint8 *p, uint32 size, int ram)
|
||||
{
|
||||
CHRptr[chip]=p;
|
||||
CHRsize[chip]=size;
|
||||
|
||||
CHRmask1[chip]=(size>>10)-1;
|
||||
CHRmask2[chip]=(size>>11)-1;
|
||||
CHRmask4[chip]=(size>>12)-1;
|
||||
CHRmask8[chip]=(size>>13)-1;
|
||||
|
||||
CHRram[chip]=ram;
|
||||
}
|
||||
|
||||
DECLFR(CartBR)
|
||||
{
|
||||
return Page[A>>11][A];
|
||||
}
|
||||
|
||||
DECLFW(CartBW)
|
||||
{
|
||||
//printf("Ok: %04x:%02x, %d\n",A,V,PRGIsRAM[A>>11]);
|
||||
if(PRGIsRAM[A>>11] && Page[A>>11])
|
||||
Page[A>>11][A]=V;
|
||||
}
|
||||
|
||||
DECLFR(CartBROB)
|
||||
{
|
||||
if(!Page[A>>11]) return(X.DB);
|
||||
return Page[A>>11][A];
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setprg2r(int r, unsigned int A, unsigned int V)
|
||||
{
|
||||
V&=PRGmask2[r];
|
||||
|
||||
setpageptr(2,A,PRGptr[r]?(&PRGptr[r][V<<11]):0,PRGram[r]);
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setprg2(uint32 A, uint32 V)
|
||||
{
|
||||
setprg2r(0,A,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setprg4r(int r, unsigned int A, unsigned int V)
|
||||
{
|
||||
V&=PRGmask4[r];
|
||||
setpageptr(4,A,PRGptr[r]?(&PRGptr[r][V<<12]):0,PRGram[r]);
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setprg4(uint32 A, uint32 V)
|
||||
{
|
||||
setprg4r(0,A,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setprg8r(int r, unsigned int A, unsigned int V)
|
||||
{
|
||||
if(PRGsize[r]>=8192)
|
||||
{
|
||||
V&=PRGmask8[r];
|
||||
setpageptr(8,A,PRGptr[r]?(&PRGptr[r][V<<13]):0,PRGram[r]);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 VA=V<<2;
|
||||
int x;
|
||||
for(x=0;x<4;x++)
|
||||
setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
|
||||
}
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setprg8(uint32 A, uint32 V)
|
||||
{
|
||||
setprg8r(0,A,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setprg16r(int r, unsigned int A, unsigned int V)
|
||||
{
|
||||
if(PRGsize[r]>=16384)
|
||||
{
|
||||
V&=PRGmask16[r];
|
||||
setpageptr(16,A,PRGptr[r]?(&PRGptr[r][V<<14]):0,PRGram[r]);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 VA=V<<3;
|
||||
int x;
|
||||
|
||||
for(x=0;x<8;x++)
|
||||
setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
|
||||
}
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setprg16(uint32 A, uint32 V)
|
||||
{
|
||||
setprg16r(0,A,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setprg32r(int r,unsigned int A, unsigned int V)
|
||||
{
|
||||
if(PRGsize[r]>=32768)
|
||||
{
|
||||
V&=PRGmask32[r];
|
||||
setpageptr(32,A,PRGptr[r]?(&PRGptr[r][V<<15]):0,PRGram[r]);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 VA=V<<4;
|
||||
int x;
|
||||
|
||||
for(x=0;x<16;x++)
|
||||
setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
|
||||
}
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setprg32(uint32 A, uint32 V)
|
||||
{
|
||||
setprg32r(0,A,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setchr1r(int r, unsigned int A, unsigned int V)
|
||||
{
|
||||
if(!CHRptr[r]) return;
|
||||
FCEUPPU_LineUpdate();
|
||||
V&=CHRmask1[r];
|
||||
if(CHRram[r])
|
||||
PPUCHRRAM|=(1<<(A>>10));
|
||||
else
|
||||
PPUCHRRAM&=~(1<<(A>>10));
|
||||
VPageR[(A)>>10]=&CHRptr[r][(V)<<10]-(A);
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setchr2r(int r, unsigned int A, unsigned int V)
|
||||
{
|
||||
if(!CHRptr[r]) return;
|
||||
FCEUPPU_LineUpdate();
|
||||
V&=CHRmask2[r];
|
||||
VPageR[(A)>>10]=VPageR[((A)>>10)+1]=&CHRptr[r][(V)<<11]-(A);
|
||||
if(CHRram[r])
|
||||
PPUCHRRAM|=(3<<(A>>10));
|
||||
else
|
||||
PPUCHRRAM&=~(3<<(A>>10));
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setchr4r(int r, unsigned int A, unsigned int V)
|
||||
{
|
||||
if(!CHRptr[r]) return;
|
||||
FCEUPPU_LineUpdate();
|
||||
V&=CHRmask4[r];
|
||||
VPageR[(A)>>10]=VPageR[((A)>>10)+1]=
|
||||
VPageR[((A)>>10)+2]=VPageR[((A)>>10)+3]=&CHRptr[r][(V)<<12]-(A);
|
||||
if(CHRram[r])
|
||||
PPUCHRRAM|=(15<<(A>>10));
|
||||
else
|
||||
PPUCHRRAM&=~(15<<(A>>10));
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setchr8r(int r, unsigned int V)
|
||||
{
|
||||
int x;
|
||||
|
||||
if(!CHRptr[r]) return;
|
||||
FCEUPPU_LineUpdate();
|
||||
V&=CHRmask8[r];
|
||||
for(x=7;x>=0;x--)
|
||||
VPageR[x]=&CHRptr[r][V<<13];
|
||||
if(CHRram[r])
|
||||
PPUCHRRAM|=(255);
|
||||
else
|
||||
PPUCHRRAM&=~(255);
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setchr1(unsigned int A, unsigned int V)
|
||||
{
|
||||
setchr1r(0,A,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setchr2(unsigned int A, unsigned int V)
|
||||
{
|
||||
setchr2r(0,A,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setchr4(unsigned int A, unsigned int V)
|
||||
{
|
||||
setchr4r(0,A,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(1) setchr8(unsigned int V)
|
||||
{
|
||||
setchr8r(0,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(1) setvram8(uint8 *p)
|
||||
{
|
||||
int x;
|
||||
for(x=7;x>=0;x--)
|
||||
VPageR[x]=p;
|
||||
PPUCHRRAM|=255;
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setvram4(uint32 A, uint8 *p)
|
||||
{
|
||||
int x;
|
||||
for(x=3;x>=0;x--)
|
||||
VPageR[(A>>10)+x]=p-A;
|
||||
PPUCHRRAM|=(15<<(A>>10));
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setvramb1(uint8 *p, uint32 A, uint32 b)
|
||||
{
|
||||
FCEUPPU_LineUpdate();
|
||||
VPageR[A>>10]=p-A+(b<<10);
|
||||
PPUCHRRAM|=(1<<(A>>10));
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setvramb2(uint8 *p, uint32 A, uint32 b)
|
||||
{
|
||||
FCEUPPU_LineUpdate();
|
||||
VPageR[(A>>10)]=VPageR[(A>>10)+1]=p-A+(b<<11);
|
||||
PPUCHRRAM|=(3<<(A>>10));
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setvramb4(uint8 *p, uint32 A, uint32 b)
|
||||
{
|
||||
int x;
|
||||
|
||||
FCEUPPU_LineUpdate();
|
||||
for(x=3;x>=0;x--)
|
||||
VPageR[(A>>10)+x]=p-A+(b<<12);
|
||||
PPUCHRRAM|=(15<<(A>>10));
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setvramb8(uint8 *p, uint32 b)
|
||||
{
|
||||
int x;
|
||||
|
||||
FCEUPPU_LineUpdate();
|
||||
for(x=7;x>=0;x--)
|
||||
VPageR[x]=p+(b<<13);
|
||||
PPUCHRRAM|=255;
|
||||
}
|
||||
|
||||
/* This function can be called without calling SetupCartMirroring(). */
|
||||
|
||||
void FASTAPASS(3) setntamem(uint8 *p, int ram, uint32 b)
|
||||
{
|
||||
FCEUPPU_LineUpdate();
|
||||
vnapage[b]=p;
|
||||
PPUNTARAM&=~(1<<b);
|
||||
if(ram)
|
||||
PPUNTARAM|=1<<b;
|
||||
}
|
||||
|
||||
static int mirrorhard=0;
|
||||
void setmirrorw(int a, int b, int c, int d)
|
||||
{
|
||||
FCEUPPU_LineUpdate();
|
||||
vnapage[0]=NTARAM+a*0x400;
|
||||
vnapage[1]=NTARAM+b*0x400;
|
||||
vnapage[2]=NTARAM+c*0x400;
|
||||
vnapage[3]=NTARAM+d*0x400;
|
||||
}
|
||||
|
||||
void FASTAPASS(1) setmirror(int t)
|
||||
{
|
||||
FCEUPPU_LineUpdate();
|
||||
if(!mirrorhard)
|
||||
{
|
||||
switch(t)
|
||||
{
|
||||
case MI_H:
|
||||
vnapage[0]=vnapage[1]=NTARAM;vnapage[2]=vnapage[3]=NTARAM+0x400;
|
||||
break;
|
||||
case MI_V:
|
||||
vnapage[0]=vnapage[2]=NTARAM;vnapage[1]=vnapage[3]=NTARAM+0x400;
|
||||
break;
|
||||
case MI_0:
|
||||
vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=NTARAM;
|
||||
break;
|
||||
case MI_1:
|
||||
vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=NTARAM+0x400;
|
||||
break;
|
||||
}
|
||||
PPUNTARAM=0xF;
|
||||
}
|
||||
}
|
||||
|
||||
void SetupCartMirroring(int m, int hard, uint8 *extra)
|
||||
{
|
||||
if(m<4)
|
||||
setmirror(m);
|
||||
else
|
||||
{
|
||||
vnapage[0]=NTARAM;
|
||||
vnapage[1]=NTARAM+0x400;
|
||||
vnapage[2]=extra;
|
||||
vnapage[3]=extra+0x400;
|
||||
PPUNTARAM=0xF;
|
||||
}
|
||||
mirrorhard=hard;
|
||||
}
|
||||
|
||||
static uint8 *GENIEROM=0;
|
||||
|
||||
void FixGenieMap(void);
|
||||
|
||||
/* Called when a game(file) is opened successfully. */
|
||||
void OpenGenie(void)
|
||||
{
|
||||
FILE *fp;
|
||||
int x;
|
||||
|
||||
if(!GENIEROM)
|
||||
{
|
||||
char *fn;
|
||||
|
||||
if(!(GENIEROM=(uint8 *)FCEU_malloc(4096+1024))) return;
|
||||
|
||||
fn=FCEU_MakeFName(FCEUMKF_GGROM,0,0);
|
||||
fp=FCEUD_UTF8fopen(fn,"rb");
|
||||
if(!fp)
|
||||
{
|
||||
FCEU_PrintError("Error opening Game Genie ROM image!");
|
||||
free(GENIEROM);
|
||||
GENIEROM=0;
|
||||
return;
|
||||
}
|
||||
if(fread(GENIEROM,1,16,fp)!=16)
|
||||
{
|
||||
grerr:
|
||||
FCEU_PrintError("Error reading from Game Genie ROM image!");
|
||||
free(GENIEROM);
|
||||
GENIEROM=0;
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
if(GENIEROM[0]==0x4E) /* iNES ROM image */
|
||||
{
|
||||
if(fread(GENIEROM,1,4096,fp)!=4096)
|
||||
goto grerr;
|
||||
if(fseek(fp,16384-4096,SEEK_CUR))
|
||||
goto grerr;
|
||||
if(fread(GENIEROM+4096,1,256,fp)!=256)
|
||||
goto grerr;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(fread(GENIEROM+16,1,4352-16,fp)!=(4352-16))
|
||||
goto grerr;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
/* Workaround for the FCE Ultra CHR page size only being 1KB */
|
||||
for(x=0;x<4;x++)
|
||||
memcpy(GENIEROM+4096+(x<<8),GENIEROM+4096,256);
|
||||
}
|
||||
|
||||
geniestage=1;
|
||||
}
|
||||
|
||||
/* Called when a game is closed. */
|
||||
void CloseGenie(void)
|
||||
{
|
||||
/* No good reason to free() the Game Genie ROM image data. */
|
||||
geniestage=0;
|
||||
FlushGenieRW();
|
||||
VPageR=VPage;
|
||||
}
|
||||
|
||||
void FCEU_KillGenie(void)
|
||||
{
|
||||
if(GENIEROM)
|
||||
{
|
||||
free(GENIEROM);
|
||||
GENIEROM=0;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(GenieRead)
|
||||
{
|
||||
return GENIEROM[A&4095];
|
||||
}
|
||||
|
||||
static DECLFW(GenieWrite)
|
||||
{
|
||||
switch(A)
|
||||
{
|
||||
case 0x800c:
|
||||
case 0x8008:
|
||||
case 0x8004:genieval[((A-4)&0xF)>>2]=V;break;
|
||||
|
||||
case 0x800b:
|
||||
case 0x8007:
|
||||
case 0x8003:geniech[((A-3)&0xF)>>2]=V;break;
|
||||
|
||||
case 0x800a:
|
||||
case 0x8006:
|
||||
case 0x8002:genieaddr[((A-2)&0xF)>>2]&=0xFF00;genieaddr[((A-2)&0xF)>>2]|=V;break;
|
||||
|
||||
case 0x8009:
|
||||
case 0x8005:
|
||||
case 0x8001:genieaddr[((A-1)&0xF)>>2]&=0xFF;genieaddr[((A-1)&0xF)>>2]|=(V|0x80)<<8;break;
|
||||
|
||||
case 0x8000:if(!V)
|
||||
FixGenieMap();
|
||||
else
|
||||
{
|
||||
modcon=V^0xFF;
|
||||
if(V==0x71)
|
||||
modcon=0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static readfunc GenieBackup[3];
|
||||
|
||||
static DECLFR(GenieFix1)
|
||||
{
|
||||
uint8 r=GenieBackup[0](A);
|
||||
|
||||
if((modcon>>1)&1) // No check
|
||||
return genieval[0];
|
||||
else if(r==geniech[0])
|
||||
return genieval[0];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static DECLFR(GenieFix2)
|
||||
{
|
||||
uint8 r=GenieBackup[1](A);
|
||||
|
||||
if((modcon>>2)&1) // No check
|
||||
return genieval[1];
|
||||
else if(r==geniech[1])
|
||||
return genieval[1];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static DECLFR(GenieFix3)
|
||||
{
|
||||
uint8 r=GenieBackup[2](A);
|
||||
|
||||
if((modcon>>3)&1) // No check
|
||||
return genieval[2];
|
||||
else if(r==geniech[2])
|
||||
return genieval[2];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
void FixGenieMap(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
geniestage=2;
|
||||
|
||||
for(x=0;x<8;x++)
|
||||
VPage[x]=VPageG[x];
|
||||
|
||||
VPageR=VPage;
|
||||
FlushGenieRW();
|
||||
//printf("Rightyo\n");
|
||||
for(x=0;x<3;x++)
|
||||
if((modcon>>(4+x))&1)
|
||||
{
|
||||
readfunc tmp[3]={GenieFix1,GenieFix2,GenieFix3};
|
||||
GenieBackup[x]=GetReadHandler(genieaddr[x]);
|
||||
SetReadHandler(genieaddr[x],genieaddr[x],tmp[x]);
|
||||
}
|
||||
}
|
||||
|
||||
void GeniePower(void)
|
||||
{
|
||||
uint32 x;
|
||||
|
||||
if(!geniestage)
|
||||
return;
|
||||
|
||||
geniestage=1;
|
||||
for(x=0;x<3;x++)
|
||||
{
|
||||
genieval[x]=0xFF;
|
||||
geniech[x]=0xFF;
|
||||
genieaddr[x]=0xFFFF;
|
||||
}
|
||||
modcon=0;
|
||||
|
||||
SetWriteHandler(0x8000,0xFFFF,GenieWrite);
|
||||
SetReadHandler(0x8000,0xFFFF,GenieRead);
|
||||
|
||||
for(x=0;x<8;x++)
|
||||
VPage[x]=GENIEROM+4096-0x400*x;
|
||||
|
||||
if(AllocGenieRW())
|
||||
VPageR=VPageG;
|
||||
else
|
||||
geniestage=2;
|
||||
}
|
||||
|
||||
|
||||
void FCEU_SaveGameSave(CartInfo *LocalHWInfo)
|
||||
{
|
||||
if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0])
|
||||
{
|
||||
FILE *sp;
|
||||
char *soot;
|
||||
|
||||
soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
|
||||
if((sp=FCEUD_UTF8fopen(soot,"wb"))==NULL)
|
||||
{
|
||||
FCEU_PrintError("WRAM file \"%s\" cannot be written to.\n",soot);
|
||||
}
|
||||
else
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x=0;x<4;x++)
|
||||
if(LocalHWInfo->SaveGame[x])
|
||||
{
|
||||
fwrite(LocalHWInfo->SaveGame[x],1,
|
||||
LocalHWInfo->SaveGameLen[x],sp);
|
||||
}
|
||||
}
|
||||
free(soot);
|
||||
}
|
||||
}
|
||||
|
||||
void FCEU_LoadGameSave(CartInfo *LocalHWInfo)
|
||||
{
|
||||
if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0])
|
||||
{
|
||||
FILE *sp;
|
||||
char *soot;
|
||||
|
||||
soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
|
||||
sp=FCEUD_UTF8fopen(soot,"rb");
|
||||
if(sp!=NULL)
|
||||
{
|
||||
int x;
|
||||
for(x=0;x<4;x++)
|
||||
if(LocalHWInfo->SaveGame[x])
|
||||
fread(LocalHWInfo->SaveGame[x],1,LocalHWInfo->SaveGameLen[x],sp);
|
||||
}
|
||||
free(soot);
|
||||
}
|
||||
}
|
||||
|
100
source/cart.h
Normal file
100
source/cart.h
Normal file
@ -0,0 +1,100 @@
|
||||
typedef struct {
|
||||
/* Set by mapper/board code: */
|
||||
void (*Power)(void);
|
||||
void (*Reset)(void);
|
||||
void (*Close)(void);
|
||||
uint8 *SaveGame[4]; /* Pointers to memory to save/load. */
|
||||
uint32 SaveGameLen[4]; /* How much memory to save/load. */
|
||||
|
||||
/* Set by iNES/UNIF loading code. */
|
||||
int mirror; /* As set in the header or chunk.
|
||||
iNES/UNIF specific. Intended
|
||||
to help support games like "Karnov"
|
||||
that are not really MMC3 but are
|
||||
set to mapper 4.
|
||||
*/
|
||||
int battery; /* Presence of an actual battery. */
|
||||
uint8 MD5[16];
|
||||
uint32 CRC32; /* Should be set by the iNES/UNIF loading
|
||||
code, used by mapper/board code, maybe
|
||||
other code in the future.
|
||||
*/
|
||||
} CartInfo;
|
||||
|
||||
void FCEU_SaveGameSave(CartInfo *LocalHWInfo);
|
||||
void FCEU_LoadGameSave(CartInfo *LocalHWInfo);
|
||||
|
||||
extern uint8 *Page[32],*VPage[8],*MMC5SPRVPage[8],*MMC5BGVPage[8];
|
||||
|
||||
void ResetCartMapping(void);
|
||||
void SetupCartPRGMapping(int chip, uint8 *p, uint32 size, int ram);
|
||||
void SetupCartCHRMapping(int chip, uint8 *p, uint32 size, int ram);
|
||||
void SetupCartMirroring(int m, int hard, uint8 *extra);
|
||||
|
||||
DECLFR(CartBROB);
|
||||
DECLFR(CartBR);
|
||||
DECLFW(CartBW);
|
||||
|
||||
extern uint8 *PRGptr[32];
|
||||
extern uint8 *CHRptr[32];
|
||||
|
||||
extern uint32 PRGsize[32];
|
||||
extern uint32 CHRsize[32];
|
||||
|
||||
extern uint32 PRGmask2[32];
|
||||
extern uint32 PRGmask4[32];
|
||||
extern uint32 PRGmask8[32];
|
||||
extern uint32 PRGmask16[32];
|
||||
extern uint32 PRGmask32[32];
|
||||
|
||||
extern uint32 CHRmask1[32];
|
||||
extern uint32 CHRmask2[32];
|
||||
extern uint32 CHRmask4[32];
|
||||
extern uint32 CHRmask8[32];
|
||||
|
||||
void FASTAPASS(2) setprg2(uint32 A, uint32 V);
|
||||
void FASTAPASS(2) setprg4(uint32 A, uint32 V);
|
||||
void FASTAPASS(2) setprg8(uint32 A, uint32 V);
|
||||
void FASTAPASS(2) setprg16(uint32 A, uint32 V);
|
||||
void FASTAPASS(2) setprg32(uint32 A, uint32 V);
|
||||
|
||||
void FASTAPASS(3) setprg2r(int r, unsigned int A, unsigned int V);
|
||||
void FASTAPASS(3) setprg4r(int r, unsigned int A, unsigned int V);
|
||||
void FASTAPASS(3) setprg8r(int r, unsigned int A, unsigned int V);
|
||||
void FASTAPASS(3) setprg16r(int r, unsigned int A, unsigned int V);
|
||||
void FASTAPASS(3) setprg32r(int r, unsigned int A, unsigned int V);
|
||||
|
||||
void FASTAPASS(3) setchr1r(int r, unsigned int A, unsigned int V);
|
||||
void FASTAPASS(3) setchr2r(int r, unsigned int A, unsigned int V);
|
||||
void FASTAPASS(3) setchr4r(int r, unsigned int A, unsigned int V);
|
||||
void FASTAPASS(2) setchr8r(int r, unsigned int V);
|
||||
|
||||
void FASTAPASS(2) setchr1(unsigned int A, unsigned int V);
|
||||
void FASTAPASS(2) setchr2(unsigned int A, unsigned int V);
|
||||
void FASTAPASS(2) setchr4(unsigned int A, unsigned int V);
|
||||
void FASTAPASS(1) setchr8(unsigned int V);
|
||||
|
||||
void FASTAPASS(2) setvram4(uint32 A, uint8 *p);
|
||||
void FASTAPASS(1) setvram8(uint8 *p);
|
||||
|
||||
void FASTAPASS(3) setvramb1(uint8 *p, uint32 A, uint32 b);
|
||||
void FASTAPASS(3) setvramb2(uint8 *p, uint32 A, uint32 b);
|
||||
void FASTAPASS(3) setvramb4(uint8 *p, uint32 A, uint32 b);
|
||||
void FASTAPASS(2) setvramb8(uint8 *p, uint32 b);
|
||||
|
||||
void FASTAPASS(1) setmirror(int t);
|
||||
void setmirrorw(int a, int b, int c, int d);
|
||||
void FASTAPASS(3) setntamem(uint8 *p, int ram, uint32 b);
|
||||
|
||||
#define MI_H 0
|
||||
#define MI_V 1
|
||||
#define MI_0 2
|
||||
#define MI_1 3
|
||||
|
||||
extern int geniestage;
|
||||
|
||||
void GeniePower(void);
|
||||
|
||||
void OpenGenie(void);
|
||||
void CloseGenie(void);
|
||||
void FCEU_KillGenie(void);
|
855
source/cheat.c
Normal file
855
source/cheat.c
Normal file
@ -0,0 +1,855 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "x6502.h"
|
||||
#include "cheat.h"
|
||||
#include "fceu.h"
|
||||
#include "general.h"
|
||||
#include "cart.h"
|
||||
#include "memory.h"
|
||||
|
||||
static uint8 *CheatRPtrs[64];
|
||||
|
||||
void FCEU_CheatResetRAM(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x=0;x<64;x++)
|
||||
CheatRPtrs[x]=0;
|
||||
}
|
||||
|
||||
void FCEU_CheatAddRAM(int s, uint32 A, uint8 *p)
|
||||
{
|
||||
uint32 AB=A>>10;
|
||||
int x;
|
||||
|
||||
for(x=s-1;x>=0;x--)
|
||||
CheatRPtrs[AB+x]=p-A;
|
||||
}
|
||||
|
||||
|
||||
struct CHEATF {
|
||||
struct CHEATF *next;
|
||||
char *name;
|
||||
uint16 addr;
|
||||
uint8 val;
|
||||
int compare; /* -1 for no compare. */
|
||||
int type; /* 0 for replace, 1 for substitute(GG). */
|
||||
int status;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint16 addr;
|
||||
uint8 val;
|
||||
int compare;
|
||||
readfunc PrevRead;
|
||||
} CHEATF_SUBFAST;
|
||||
|
||||
|
||||
static CHEATF_SUBFAST SubCheats[256];
|
||||
static int numsubcheats=0;
|
||||
struct CHEATF *cheats=0,*cheatsl=0;
|
||||
|
||||
|
||||
#define CHEATC_NONE 0x8000
|
||||
#define CHEATC_EXCLUDED 0x4000
|
||||
#define CHEATC_NOSHOW 0xC000
|
||||
|
||||
static uint16 *CheatComp=0;
|
||||
static int savecheats;
|
||||
|
||||
static DECLFR(SubCheatsRead)
|
||||
{
|
||||
CHEATF_SUBFAST *s=SubCheats;
|
||||
int x=numsubcheats;
|
||||
|
||||
do
|
||||
{
|
||||
if(s->addr==A)
|
||||
{
|
||||
if(s->compare>=0)
|
||||
{
|
||||
uint8 pv=s->PrevRead(A);
|
||||
|
||||
if(pv==s->compare)
|
||||
return(s->val);
|
||||
else return(pv);
|
||||
}
|
||||
else return(s->val);
|
||||
}
|
||||
s++;
|
||||
} while(--x);
|
||||
return(0); /* We should never get here. */
|
||||
}
|
||||
|
||||
void RebuildSubCheats(void)
|
||||
{
|
||||
int x;
|
||||
struct CHEATF *c=cheats;
|
||||
|
||||
for(x=0;x<numsubcheats;x++)
|
||||
SetReadHandler(SubCheats[x].addr,SubCheats[x].addr,SubCheats[x].PrevRead);
|
||||
|
||||
numsubcheats=0;
|
||||
while(c)
|
||||
{
|
||||
if(c->type==1 && c->status)
|
||||
{
|
||||
if(GetReadHandler(c->addr)==SubCheatsRead)
|
||||
{
|
||||
/* Prevent a catastrophe by this check. */
|
||||
//FCEU_DispMessage("oops");
|
||||
}
|
||||
else
|
||||
{
|
||||
SubCheats[numsubcheats].PrevRead=GetReadHandler(c->addr);
|
||||
SubCheats[numsubcheats].addr=c->addr;
|
||||
SubCheats[numsubcheats].val=c->val;
|
||||
SubCheats[numsubcheats].compare=c->compare;
|
||||
SetReadHandler(c->addr,c->addr,SubCheatsRead);
|
||||
numsubcheats++;
|
||||
}
|
||||
}
|
||||
c=c->next;
|
||||
}
|
||||
}
|
||||
|
||||
void FCEU_PowerCheats()
|
||||
{
|
||||
numsubcheats=0; /* Quick hack to prevent setting of ancient read addresses. */
|
||||
RebuildSubCheats();
|
||||
}
|
||||
|
||||
static int AddCheatEntry(char *name, uint32 addr, uint8 val, int compare, int status, int type);
|
||||
static void CheatMemErr(void)
|
||||
{
|
||||
FCEUD_PrintError("Error allocating memory for cheat data.");
|
||||
}
|
||||
|
||||
/* This function doesn't allocate any memory for "name" */
|
||||
static int AddCheatEntry(char *name, uint32 addr, uint8 val, int compare, int status, int type)
|
||||
{
|
||||
struct CHEATF *temp;
|
||||
if(!(temp=(struct CHEATF *)malloc(sizeof(struct CHEATF))))
|
||||
{
|
||||
CheatMemErr();
|
||||
return(0);
|
||||
}
|
||||
temp->name=name;
|
||||
temp->addr=addr;
|
||||
temp->val=val;
|
||||
temp->status=status;
|
||||
temp->compare=compare;
|
||||
temp->type=type;
|
||||
temp->next=0;
|
||||
|
||||
if(cheats)
|
||||
{
|
||||
cheatsl->next=temp;
|
||||
cheatsl=temp;
|
||||
}
|
||||
else
|
||||
cheats=cheatsl=temp;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
void FCEU_LoadGameCheats(FILE *override)
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned int addr;
|
||||
unsigned int val;
|
||||
unsigned int status;
|
||||
unsigned int type;
|
||||
unsigned int compare;
|
||||
int x;
|
||||
|
||||
char linebuf[2048];
|
||||
char *namebuf;
|
||||
int tc=0;
|
||||
char *fn;
|
||||
|
||||
numsubcheats=savecheats=0;
|
||||
|
||||
if(override)
|
||||
fp = override;
|
||||
else
|
||||
{
|
||||
fn=FCEU_MakeFName(FCEUMKF_CHEAT,0,0);
|
||||
fp=FCEUD_UTF8fopen(fn,"rb");
|
||||
free(fn);
|
||||
if(!fp) return;
|
||||
}
|
||||
|
||||
while(fgets(linebuf,2048,fp)>0)
|
||||
{
|
||||
char *tbuf=linebuf;
|
||||
int doc=0;
|
||||
|
||||
addr=val=compare=status=type=0;
|
||||
|
||||
if(tbuf[0]=='S')
|
||||
{
|
||||
tbuf++;
|
||||
type=1;
|
||||
}
|
||||
else type=0;
|
||||
|
||||
if(tbuf[0]=='C')
|
||||
{
|
||||
tbuf++;
|
||||
doc=1;
|
||||
}
|
||||
|
||||
if(tbuf[0]==':')
|
||||
{
|
||||
tbuf++;
|
||||
status=0;
|
||||
}
|
||||
else status=1;
|
||||
|
||||
if(doc)
|
||||
{
|
||||
char *neo=&tbuf[4+2+2+1+1+1];
|
||||
if(sscanf(tbuf,"%04x%*[:]%02x%*[:]%02x",&addr,&val,&compare)!=3)
|
||||
continue;
|
||||
namebuf=malloc(strlen(neo)+1);
|
||||
strcpy(namebuf,neo);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *neo=&tbuf[4+2+1+1];
|
||||
if(sscanf(tbuf,"%04x%*[:]%02x",&addr,&val)!=2)
|
||||
continue;
|
||||
namebuf=malloc(strlen(neo)+1);
|
||||
strcpy(namebuf,neo);
|
||||
}
|
||||
|
||||
for(x=0;x<strlen(namebuf);x++)
|
||||
{
|
||||
if(namebuf[x]==10 || namebuf[x]==13)
|
||||
{
|
||||
namebuf[x]=0;
|
||||
break;
|
||||
}
|
||||
else if(namebuf[x]<0x20) namebuf[x]=' ';
|
||||
}
|
||||
|
||||
AddCheatEntry(namebuf,addr,val,doc?compare:-1,status,type);
|
||||
tc++;
|
||||
}
|
||||
RebuildSubCheats();
|
||||
if(!override)
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void FCEU_FlushGameCheats(FILE *override, int nosave)
|
||||
{
|
||||
if(CheatComp)
|
||||
{
|
||||
free(CheatComp);
|
||||
CheatComp=0;
|
||||
}
|
||||
if((!savecheats || nosave) && !override) /* Always save cheats if we're being overridden. */
|
||||
{
|
||||
if(cheats)
|
||||
{
|
||||
struct CHEATF *next=cheats;
|
||||
for(;;)
|
||||
{
|
||||
struct CHEATF *last=next;
|
||||
next=next->next;
|
||||
free(last->name);
|
||||
free(last);
|
||||
if(!next) break;
|
||||
}
|
||||
cheats=cheatsl=0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char *fn = 0;
|
||||
|
||||
if(!override)
|
||||
fn = FCEU_MakeFName(FCEUMKF_CHEAT,0,0);
|
||||
|
||||
if(cheats)
|
||||
{
|
||||
struct CHEATF *next=cheats;
|
||||
FILE *fp;
|
||||
|
||||
if(override)
|
||||
fp = override;
|
||||
else
|
||||
fp=FCEUD_UTF8fopen(fn,"wb");
|
||||
|
||||
if(fp)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
struct CHEATF *t;
|
||||
if(next->type)
|
||||
fputc('S',fp);
|
||||
if(next->compare>=0)
|
||||
fputc('C',fp);
|
||||
|
||||
if(!next->status)
|
||||
fputc(':',fp);
|
||||
|
||||
if(next->compare>=0)
|
||||
fprintf(fp,"%04x:%02x:%02x:%s\n",next->addr,next->val,next->compare,next->name);
|
||||
else
|
||||
fprintf(fp,"%04x:%02x:%s\n",next->addr,next->val,next->name);
|
||||
|
||||
free(next->name);
|
||||
t=next;
|
||||
next=next->next;
|
||||
free(t);
|
||||
if(!next) break;
|
||||
}
|
||||
if(!override)
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
FCEUD_PrintError("Error saving cheats.");
|
||||
cheats=cheatsl=0;
|
||||
}
|
||||
//else if(!override)
|
||||
// remove(fn);
|
||||
if(!override)
|
||||
free(fn);
|
||||
}
|
||||
|
||||
RebuildSubCheats(); /* Remove memory handlers. */
|
||||
|
||||
}
|
||||
|
||||
|
||||
int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int type)
|
||||
{
|
||||
char *t;
|
||||
|
||||
if(!(t=(char *)malloc(strlen(name)+1)))
|
||||
{
|
||||
CheatMemErr();
|
||||
return(0);
|
||||
}
|
||||
strcpy(t,name);
|
||||
if(!AddCheatEntry(t,addr,val,compare,1,type))
|
||||
{
|
||||
free(t);
|
||||
return(0);
|
||||
}
|
||||
savecheats=1;
|
||||
RebuildSubCheats();
|
||||
return(1);
|
||||
}
|
||||
|
||||
int FCEUI_DelCheat(uint32 which)
|
||||
{
|
||||
struct CHEATF *prev;
|
||||
struct CHEATF *cur;
|
||||
uint32 x=0;
|
||||
|
||||
for(prev=0,cur=cheats;;)
|
||||
{
|
||||
if(x==which) // Remove this cheat.
|
||||
{
|
||||
if(prev) // Update pointer to this cheat.
|
||||
{
|
||||
if(cur->next) // More cheats.
|
||||
prev->next=cur->next;
|
||||
else // No more.
|
||||
{
|
||||
prev->next=0;
|
||||
cheatsl=prev; // Set the previous cheat as the last cheat.
|
||||
}
|
||||
}
|
||||
else // This is the first cheat.
|
||||
{
|
||||
if(cur->next) // More cheats
|
||||
cheats=cur->next;
|
||||
else
|
||||
cheats=cheatsl=0; // No (more) cheats.
|
||||
}
|
||||
free(cur->name); // Now that all references to this cheat are removed,
|
||||
free(cur); // free the memory.
|
||||
break;
|
||||
} // *END REMOVE THIS CHEAT*
|
||||
|
||||
|
||||
if(!cur->next) // No more cheats to go through(this shouldn't ever happen...)
|
||||
return(0);
|
||||
prev=cur;
|
||||
cur=prev->next;
|
||||
x++;
|
||||
}
|
||||
|
||||
savecheats=1;
|
||||
RebuildSubCheats();
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
void FCEU_ApplyPeriodicCheats(void)
|
||||
{
|
||||
struct CHEATF *cur=cheats;
|
||||
if(!cur) return;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(cur->status && !(cur->type))
|
||||
if(CheatRPtrs[cur->addr>>10])
|
||||
CheatRPtrs[cur->addr>>10][cur->addr]=cur->val;
|
||||
if(cur->next)
|
||||
cur=cur->next;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FCEUI_ListCheats(int (*callb)(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data), void *data)
|
||||
{
|
||||
struct CHEATF *next=cheats;
|
||||
|
||||
while(next)
|
||||
{
|
||||
if(!callb(next->name,next->addr,next->val,next->compare,next->status,next->type,data)) break;
|
||||
next=next->next;
|
||||
}
|
||||
}
|
||||
|
||||
int FCEUI_GetCheat(uint32 which, char **name, uint32 *a, uint8 *v, int *compare, int *s, int *type)
|
||||
{
|
||||
struct CHEATF *next=cheats;
|
||||
uint32 x=0;
|
||||
|
||||
while(next)
|
||||
{
|
||||
if(x==which)
|
||||
{
|
||||
if(name)
|
||||
*name=next->name;
|
||||
if(a)
|
||||
*a=next->addr;
|
||||
if(v)
|
||||
*v=next->val;
|
||||
if(s)
|
||||
*s=next->status;
|
||||
if(compare)
|
||||
*compare=next->compare;
|
||||
if(type)
|
||||
*type=next->type;
|
||||
return(1);
|
||||
}
|
||||
next=next->next;
|
||||
x++;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int GGtobin(char c)
|
||||
{
|
||||
static char lets[16]={'A','P','Z','L','G','I','T','Y','E','O','X','U','K','S','V','N'};
|
||||
int x;
|
||||
|
||||
for(x=0;x<16;x++)
|
||||
if(lets[x] == toupper(c)) return(x);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Returns 1 on success, 0 on failure. Sets *a,*v,*c. */
|
||||
int FCEUI_DecodeGG(const char *str, uint16 *a, uint8 *v, int *c)
|
||||
{
|
||||
uint16 A;
|
||||
uint8 V,C;
|
||||
uint8 t;
|
||||
int s;
|
||||
|
||||
A=0x8000;
|
||||
V=0;
|
||||
C=0;
|
||||
|
||||
s=strlen(str);
|
||||
if(s!=6 && s!=8) return(0);
|
||||
|
||||
t=GGtobin(*str++);
|
||||
V|=(t&0x07);
|
||||
V|=(t&0x08)<<4;
|
||||
|
||||
t=GGtobin(*str++);
|
||||
V|=(t&0x07)<<4;
|
||||
A|=(t&0x08)<<4;
|
||||
|
||||
t=GGtobin(*str++);
|
||||
A|=(t&0x07)<<4;
|
||||
//if(t&0x08) return(0); /* 8-character code?! */
|
||||
|
||||
t=GGtobin(*str++);
|
||||
A|=(t&0x07)<<12;
|
||||
A|=(t&0x08);
|
||||
|
||||
t=GGtobin(*str++);
|
||||
A|=(t&0x07);
|
||||
A|=(t&0x08)<<8;
|
||||
|
||||
if(s==6)
|
||||
{
|
||||
t=GGtobin(*str++);
|
||||
A|=(t&0x07)<<8;
|
||||
V|=(t&0x08);
|
||||
|
||||
*a=A;
|
||||
*v=V;
|
||||
*c=-1;
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
t=GGtobin(*str++);
|
||||
A|=(t&0x07)<<8;
|
||||
C|=(t&0x08);
|
||||
|
||||
t=GGtobin(*str++);
|
||||
C|=(t&0x07);
|
||||
C|=(t&0x08)<<4;
|
||||
|
||||
t=GGtobin(*str++);
|
||||
C|=(t&0x07)<<4;
|
||||
V|=(t&0x08);
|
||||
*a=A;
|
||||
*v=V;
|
||||
*c=C;
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int FCEUI_DecodePAR(const char *str, uint16 *a, uint8 *v, int *c, int *type)
|
||||
{
|
||||
int boo[4];
|
||||
if(strlen(str)!=8) return(0);
|
||||
|
||||
sscanf(str,"%02x%02x%02x%02x",boo,boo+1,boo+2,boo+3);
|
||||
|
||||
*c=-1;
|
||||
|
||||
if(1)
|
||||
{
|
||||
*a=(boo[3]<<8)|(boo[2]+0x7F);
|
||||
*v=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*v=boo[3];
|
||||
*a=boo[2]|(boo[1]<<8);
|
||||
}
|
||||
/* Zero-page addressing modes don't go through the normal read/write handlers in FCEU, so
|
||||
we must do the old hacky method of RAM cheats.
|
||||
*/
|
||||
if(*a<0x0100)
|
||||
*type=0;
|
||||
else
|
||||
*type=1;
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* name can be NULL if the name isn't going to be changed. */
|
||||
/* same goes for a, v, and s(except the values of each one must be <0) */
|
||||
|
||||
int FCEUI_SetCheat(uint32 which, const char *name, int32 a, int32 v, int compare,int s, int type)
|
||||
{
|
||||
struct CHEATF *next=cheats;
|
||||
uint32 x=0;
|
||||
|
||||
while(next)
|
||||
{
|
||||
if(x==which)
|
||||
{
|
||||
if(name)
|
||||
{
|
||||
char *t;
|
||||
|
||||
if((t=(char *)realloc(next->name,strlen(name+1))))
|
||||
{
|
||||
next->name=t;
|
||||
strcpy(next->name,name);
|
||||
}
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
if(a>=0)
|
||||
next->addr=a;
|
||||
if(v>=0)
|
||||
next->val=v;
|
||||
if(s>=0)
|
||||
next->status=s;
|
||||
next->compare=compare;
|
||||
next->type=type;
|
||||
|
||||
savecheats=1;
|
||||
RebuildSubCheats();
|
||||
|
||||
return(1);
|
||||
}
|
||||
next=next->next;
|
||||
x++;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Convenience function. */
|
||||
int FCEUI_ToggleCheat(uint32 which)
|
||||
{
|
||||
struct CHEATF *next=cheats;
|
||||
uint32 x=0;
|
||||
|
||||
while(next)
|
||||
{
|
||||
if(x==which)
|
||||
{
|
||||
next->status=!next->status;
|
||||
savecheats=1;
|
||||
RebuildSubCheats();
|
||||
return(next->status);
|
||||
}
|
||||
next=next->next;
|
||||
x++;
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static int InitCheatComp(void)
|
||||
{
|
||||
uint32 x;
|
||||
|
||||
CheatComp=(uint16*)malloc(65536*sizeof(uint16));
|
||||
if(!CheatComp)
|
||||
{
|
||||
CheatMemErr();
|
||||
return(0);
|
||||
}
|
||||
for(x=0;x<65536;x++)
|
||||
CheatComp[x]=CHEATC_NONE;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
void FCEUI_CheatSearchSetCurrentAsOriginal(void)
|
||||
{
|
||||
uint32 x;
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatRPtrs[x>>10])
|
||||
CheatComp[x]=CheatRPtrs[x>>10][x];
|
||||
else
|
||||
CheatComp[x]|=CHEATC_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void FCEUI_CheatSearchShowExcluded(void)
|
||||
{
|
||||
uint32 x;
|
||||
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
CheatComp[x]&=~CHEATC_EXCLUDED;
|
||||
}
|
||||
|
||||
|
||||
int32 FCEUI_CheatSearchGetCount(void)
|
||||
{
|
||||
uint32 x,c=0;
|
||||
|
||||
if(CheatComp)
|
||||
{
|
||||
for(x=0x0000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW) && CheatRPtrs[x>>10])
|
||||
c++;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
/* This function will give the initial value of the search and the current value at a location. */
|
||||
|
||||
void FCEUI_CheatSearchGet(int (*callb)(uint32 a, uint8 last, uint8 current, void *data),void *data)
|
||||
{
|
||||
uint32 x;
|
||||
|
||||
if(!CheatComp)
|
||||
{
|
||||
if(!InitCheatComp())
|
||||
CheatMemErr();
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW) && CheatRPtrs[x>>10])
|
||||
if(!callb(x,CheatComp[x],CheatRPtrs[x>>10][x],data))
|
||||
break;
|
||||
}
|
||||
|
||||
void FCEUI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a, uint8 last, uint8 current))
|
||||
{
|
||||
uint32 x;
|
||||
uint32 in=0;
|
||||
|
||||
if(!CheatComp)
|
||||
{
|
||||
if(!InitCheatComp())
|
||||
CheatMemErr();
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW) && CheatRPtrs[x>>10])
|
||||
{
|
||||
if(in>=first)
|
||||
if(!callb(x,CheatComp[x],CheatRPtrs[x>>10][x]))
|
||||
break;
|
||||
in++;
|
||||
if(in>last) return;
|
||||
}
|
||||
}
|
||||
|
||||
void FCEUI_CheatSearchBegin(void)
|
||||
{
|
||||
uint32 x;
|
||||
|
||||
if(!CheatComp)
|
||||
{
|
||||
if(!InitCheatComp())
|
||||
{
|
||||
CheatMemErr();
|
||||
return;
|
||||
}
|
||||
}
|
||||
for(x=0;x<0x10000;x++)
|
||||
{
|
||||
if(CheatRPtrs[x>>10])
|
||||
CheatComp[x]=CheatRPtrs[x>>10][x];
|
||||
else
|
||||
CheatComp[x]=CHEATC_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int INLINE CAbs(int x)
|
||||
{
|
||||
if(x<0)
|
||||
return(0-x);
|
||||
return x;
|
||||
}
|
||||
|
||||
void FCEUI_CheatSearchEnd(int type, uint8 v1, uint8 v2)
|
||||
{
|
||||
uint32 x;
|
||||
|
||||
if(!CheatComp)
|
||||
{
|
||||
if(!InitCheatComp())
|
||||
{
|
||||
CheatMemErr();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!type) // Change to a specific value.
|
||||
{
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatComp[x]==v1 && CheatRPtrs[x>>10][x]==v2)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
}
|
||||
else if(type==1) // Search for relative change(between values).
|
||||
{
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatComp[x]==v1 && CAbs(CheatComp[x]-CheatRPtrs[x>>10][x])==v2)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
}
|
||||
else if(type==2) // Purely relative change.
|
||||
{
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CAbs(CheatComp[x]-CheatRPtrs[x>>10][x])==v2)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
}
|
||||
else if(type==3) // Any change.
|
||||
{
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatComp[x]!=CheatRPtrs[x>>10][x])
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
}
|
||||
else if(type==4) // Value decreased.
|
||||
{
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(!(CheatRPtrs[x>>10][x]<CheatComp[x]))
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
}
|
||||
else if(type==5) // Value increased.
|
||||
{
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(!(CheatRPtrs[x>>10][x]>CheatComp[x]))
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
}
|
||||
if(type>4)
|
||||
FCEUI_CheatSearchSetCurrentAsOriginal();
|
||||
}
|
7
source/cheat.h
Normal file
7
source/cheat.h
Normal file
@ -0,0 +1,7 @@
|
||||
void FCEU_CheatResetRAM(void);
|
||||
void FCEU_CheatAddRAM(int s, uint32 A, uint8 *p);
|
||||
|
||||
void FCEU_LoadGameCheats(FILE *override);
|
||||
void FCEU_FlushGameCheats(FILE *override, int nosave);
|
||||
void FCEU_ApplyPeriodicCheats(void);
|
||||
void FCEU_PowerCheats(void);
|
33
source/crc32.c
Normal file
33
source/crc32.c
Normal file
@ -0,0 +1,33 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 "types.h"
|
||||
#include "crc32.h"
|
||||
|
||||
#include <zlib.h>
|
||||
uint32 CalcCRC32(uint32 crc, uint8 *buf, uint32 len)
|
||||
{
|
||||
return(crc32(crc,buf,len));
|
||||
}
|
||||
|
||||
uint32 FCEUI_CRC32(uint32 crc, uint8 *buf, uint32 len)
|
||||
{
|
||||
return(CalcCRC32(crc,buf,len));
|
||||
}
|
1
source/crc32.h
Normal file
1
source/crc32.h
Normal file
@ -0,0 +1 @@
|
||||
uint32 CalcCRC32(uint32 crc, uint8 *buf, uint32 len);
|
520
source/debug.c
Normal file
520
source/debug.c
Normal file
@ -0,0 +1,520 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2003 Xodnizel
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "x6502.h"
|
||||
#include "fceu.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
|
||||
void FCEUI_DumpMem(const char *fname, uint32 start, uint32 end)
|
||||
{
|
||||
FILE *fp=FCEUD_UTF8fopen(fname,"wb");
|
||||
fceuindbg=1;
|
||||
for(;start<=end;start++)
|
||||
fputc(ARead[start](start),fp);
|
||||
fclose(fp);
|
||||
fceuindbg=0;
|
||||
}
|
||||
|
||||
void FCEUI_LoadMem(const char *fname, uint32 start, int hl)
|
||||
{
|
||||
int t;
|
||||
|
||||
FILE *fp=FCEUD_UTF8fopen(fname,"rb");
|
||||
while((t=fgetc(fp))>=0)
|
||||
{
|
||||
if(start>0xFFFF) break;
|
||||
if(hl)
|
||||
{
|
||||
extern uint8 *Page[32];
|
||||
if(Page[start/2048])
|
||||
Page[start/2048][start]=t;
|
||||
}
|
||||
else
|
||||
BWrite[start](start,t);
|
||||
start++;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static char *fstrings[12]=
|
||||
{
|
||||
"#$%02X", // immediate
|
||||
"$%04X", // RELATIVE(jump)
|
||||
"$%02X", // Z
|
||||
"$%02X,X", // Z,x
|
||||
"$%02X,Y", // Z,y
|
||||
"$%04X", //ABS
|
||||
"$%04X,X", // ABS,x
|
||||
"$%04X,Y", // ABS,y
|
||||
"($%04X)", // IND
|
||||
"($%02X,X)", // INX
|
||||
"($%02X),Y", // INY
|
||||
""
|
||||
};
|
||||
static int flengths[12]={1,1,1,1,1,2,2,2,2,1,1,0};
|
||||
|
||||
#define IMD(x) ((0<<16)|x)
|
||||
#define REL(x) ((1<<16)|x)
|
||||
#define ZP(x) ((2<<16)|x)
|
||||
#define ZPX(x) ((3<<16)|x)
|
||||
#define ZPY(x) ((4<<16)|x)
|
||||
#define ABS(x) ((5<<16)|x)
|
||||
#define ABX(x) ((6<<16)|x)
|
||||
#define ABY(x) ((7<<16)|x)
|
||||
#define IND(x) ((8<<16)|x)
|
||||
#define INX(x) ((9<<16)|x)
|
||||
#define INY(x) ((10<<16)|x)
|
||||
#define IMP(x) ((11<<16)|x)
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
int type; /* 1 for read, 2 for write, 3 for r then write. */
|
||||
int32 modes[10];
|
||||
} OPS;
|
||||
#define NUMOPS 56
|
||||
static OPS optable[NUMOPS]=
|
||||
{
|
||||
{"BRK",0,{IMP(0x00),-1}},
|
||||
{"RTI",0,{IMP(0x40),-1}},
|
||||
{"RTS",0,{IMP(0x60),-1}},
|
||||
{"PHA",2,{IMP(0x48),-1}},
|
||||
{"PHP",2,{IMP(0x08),-1}},
|
||||
{"PLA",1,{IMP(0x68),-1}},
|
||||
{"PLP",1,{IMP(0x28),-1}},
|
||||
{"JMP",0,{ABS(0x4C),IND(0x6C),-1}},
|
||||
{"JSR",0,{ABS(0x20),-1}},
|
||||
{"TAX",0,{IMP(0xAA),-1}},
|
||||
{"TXA",0,{IMP(0x8A),-1}},
|
||||
{"TAY",0,{IMP(0xA8),-1}},
|
||||
{"TYA",0,{IMP(0x98),-1}},
|
||||
{"TSX",0,{IMP(0xBA),-1}},
|
||||
{"TXS",0,{IMP(0x9A),-1}},
|
||||
{"DEX",0,{IMP(0xCA),-1}},
|
||||
{"DEY",0,{IMP(0x88),-1}},
|
||||
{"INX",0,{IMP(0xE8),-1}},
|
||||
{"INY",0,{IMP(0xC8),-1}},
|
||||
{"CLC",0,{IMP(0x18),-1}},
|
||||
{"CLD",0,{IMP(0xD8),-1}},
|
||||
{"CLI",0,{IMP(0x58),-1}},
|
||||
{"CLV",0,{IMP(0xB8),-1}},
|
||||
{"SEC",0,{IMP(0x38),-1}},
|
||||
{"SED",0,{IMP(0xF8),-1}},
|
||||
{"SEI",0,{IMP(0x78),-1}},
|
||||
{"NOP",0,{IMP(0xEA),-1}},
|
||||
{"ASL",1,{IMP(0x0a),ZP(0x06),ZPX(0x16),ABS(0x0E),ABX(0x1E),-1}},
|
||||
{"DEC",3,{ZP(0xc6),ZPX(0xd6),ABS(0xcE),ABX(0xdE),-1}},
|
||||
{"INC",3,{ZP(0xe6),ZPX(0xf6),ABS(0xeE),ABX(0xfE),-1}},
|
||||
{"LSR",3,{IMP(0x4a),ZP(0x46),ZPX(0x56),ABS(0x4E),ABX(0x5E),-1}},
|
||||
{"ROL",3,{IMP(0x2a),ZP(0x26),ZPX(0x36),ABS(0x2E),ABX(0x3E),-1}},
|
||||
{"ROR",3,{IMP(0x6a),ZP(0x66),ZPX(0x76),ABS(0x6E),ABX(0x7E),-1}},
|
||||
{"ADC",1,{IMD(0x69),ZP(0x65),ZPX(0x75),ABS(0x6D),ABX(0x7d),ABY(0x79),
|
||||
INX(0x61),INY(0x71),-1}},
|
||||
{"AND",1,{IMD(0x29),ZP(0x25),ZPX(0x35),ABS(0x2D),ABX(0x3d),ABY(0x39),
|
||||
INX(0x21),INY(0x31),-1}},
|
||||
{"BIT",1,{ZP(0x24),ABS(0x2c),-1}},
|
||||
{"CMP",1,{IMD(0xc9),ZP(0xc5),ZPX(0xd5),ABS(0xcD),ABX(0xdd),ABY(0xd9),
|
||||
INX(0xc1),INY(0xd1),-1}},
|
||||
{"CPX",1,{IMD(0xe0),ZP(0xe4),ABS(0xec),-1}},
|
||||
{"CPY",1,{IMD(0xc0),ZP(0xc4),ABS(0xcc),-1}},
|
||||
{"EOR",1,{IMD(0x49),ZP(0x45),ZPX(0x55),ABS(0x4D),ABX(0x5d),ABY(0x59),
|
||||
INX(0x41),INY(0x51),-1}},
|
||||
{"LDA",1,{IMD(0xa9),ZP(0xa5),ZPX(0xb5),ABS(0xaD),ABX(0xbd),ABY(0xb9),
|
||||
INX(0xa1),INY(0xb1),-1}},
|
||||
{"LDX",1,{IMD(0xa2),ZP(0xa6),ZPY(0xB6),ABS(0xae),ABY(0xbe),-1}},
|
||||
{"LDY",1,{IMD(0xa0),ZP(0xa4),ZPX(0xB4),ABS(0xac),ABX(0xbc),-1}},
|
||||
{"ORA",1,{IMD(0x09),ZP(0x05),ZPX(0x15),ABS(0x0D),ABX(0x1d),ABY(0x19),
|
||||
INX(0x01),INY(0x11),-1}},
|
||||
{"SBC",1,{IMD(0xEB),IMD(0xe9),ZP(0xe5),ZPX(0xf5),ABS(0xeD),ABX(0xfd),ABY(0xf9),
|
||||
INX(0xe1),INY(0xf1),-1}},
|
||||
{"STA",2,{ZP(0x85),ZPX(0x95),ABS(0x8D),ABX(0x9d),ABY(0x99),
|
||||
INX(0x81),INY(0x91),-1}},
|
||||
{"STX",2,{ZP(0x86),ZPY(0x96),ABS(0x8E),-1}},
|
||||
{"STY",2,{ZP(0x84),ZPX(0x94),ABS(0x8C),-1}},
|
||||
{"BCC",1,{REL(0x90),-1}},
|
||||
{"BCS",1,{REL(0xb0),-1}},
|
||||
{"BEQ",1,{REL(0xf0),-1}},
|
||||
{"BNE",1,{REL(0xd0),-1}},
|
||||
{"BMI",1,{REL(0x30),-1}},
|
||||
{"BPL",1,{REL(0x10),-1}},
|
||||
{"BVC",1,{REL(0x50),-1}},
|
||||
{"BVS",1,{REL(0x70),-1}},
|
||||
};
|
||||
|
||||
uint16 FCEUI_Disassemble(void *XA, uint16 a, char *stringo)
|
||||
{
|
||||
X6502 *X=XA;
|
||||
uint8 buf;
|
||||
unsigned int arg;
|
||||
int32 info;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
info=-1;
|
||||
fceuindbg=1;
|
||||
|
||||
buf=ARead[a](a);
|
||||
a++;
|
||||
|
||||
for(x=0;x<NUMOPS;x++)
|
||||
{
|
||||
y=0;
|
||||
while(optable[x].modes[y]>=0)
|
||||
{
|
||||
if((optable[x].modes[y]&0xFF)==buf)
|
||||
{
|
||||
info=optable[x].modes[y];
|
||||
goto endy;
|
||||
}
|
||||
y++;
|
||||
}
|
||||
}
|
||||
|
||||
endy:
|
||||
sprintf(stringo,"%02X ",buf);
|
||||
if(info>=0)
|
||||
{
|
||||
int z=flengths[(info>>16)];
|
||||
|
||||
if(z)
|
||||
{
|
||||
arg=ARead[a](a);
|
||||
sprintf(stringo+strlen(stringo),"%02X ",arg);
|
||||
a++;
|
||||
if(z==2) {arg|=ARead[a](a)<<8;sprintf(stringo+strlen(stringo),"%02X ",arg>>8);a++;}
|
||||
else
|
||||
strcat(stringo," ");
|
||||
|
||||
if((info>>16)==1) /* Relative branch */
|
||||
arg=a+(char)arg;
|
||||
sprintf(stringo+strlen(stringo),"%s ",optable[x].name);
|
||||
sprintf(stringo+strlen(stringo),fstrings[info>>16],arg);
|
||||
/*
|
||||
0 "#$%02X", // immediate
|
||||
1 "$%04X", // RELATIVE(jump)
|
||||
2 "$%02X", // Z
|
||||
3 "$%02X,X", // Z,x
|
||||
4 "$%02X,Y", // Z,y
|
||||
5 "$%04X", //ABS
|
||||
6 "$%04X,X", // ABS,x
|
||||
7 "$%04X,Y", // ABS,y
|
||||
8 "($%04X)", // IND
|
||||
9 "($%02X,X)", // INX
|
||||
10 "($%02X),Y", // INY
|
||||
11 #define IMP(x) ((11<<16)|x)
|
||||
*/
|
||||
{
|
||||
unsigned int tmp;
|
||||
switch(info>>16)
|
||||
{
|
||||
case 2:tmp=arg;
|
||||
if(optable[x].type&1)
|
||||
{
|
||||
sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
|
||||
sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
|
||||
}
|
||||
break;
|
||||
case 3:tmp=(arg+X->X)&0xff;
|
||||
sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
|
||||
if(optable[x].type&1)
|
||||
sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
|
||||
break;
|
||||
case 4:tmp=(arg+X->Y)&0xff;
|
||||
sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
|
||||
if(optable[x].type&1)
|
||||
sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
|
||||
break;
|
||||
case 5:tmp=arg;
|
||||
if(optable[x].type&1)
|
||||
{
|
||||
sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
|
||||
sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
|
||||
}
|
||||
break;
|
||||
case 6:tmp=(arg+X->X)&0xffff;
|
||||
sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
|
||||
if(optable[x].type&1)
|
||||
sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
|
||||
break;
|
||||
case 7:tmp=(arg+X->Y)&0xffff;
|
||||
sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
|
||||
if(optable[x].type&1)
|
||||
sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
|
||||
break;
|
||||
case 8:tmp=ARead[arg](arg)|(ARead[(arg+1)&0xffff]((arg+1)&0xffff)<<8);
|
||||
sprintf(stringo+strlen(stringo)," $%04X",tmp);
|
||||
break;
|
||||
case 9:tmp=(arg+X->X)&0xFF;
|
||||
tmp=ARead[tmp](tmp) | (ARead[(tmp+1)&0xFF]((tmp+1)&0xFF)<<8);
|
||||
sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
|
||||
if(optable[x].type&1)
|
||||
sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
|
||||
break;
|
||||
case 10:tmp=ARead[arg](arg) | (ARead[(arg+1)&0xFF]((arg+1)&0xFF)<<8);
|
||||
tmp=(tmp+X->Y)&0xFFFF;
|
||||
sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
|
||||
if(optable[x].type&1)
|
||||
sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
strcat(stringo," ");
|
||||
strcat(stringo,optable[x].name);
|
||||
}
|
||||
}
|
||||
else
|
||||
sprintf(stringo+strlen(stringo)," .db $%02X",buf);
|
||||
fceuindbg=0;
|
||||
return(a);
|
||||
}
|
||||
|
||||
void FCEUI_MemDump(uint16 a, int32 len, void (*callb)(uint16 a, uint8 v))
|
||||
{
|
||||
fceuindbg=1;
|
||||
while(len)
|
||||
{
|
||||
callb(a,ARead[a](a));
|
||||
a++;
|
||||
len--;
|
||||
}
|
||||
fceuindbg=0;
|
||||
}
|
||||
|
||||
uint8 FCEUI_MemSafePeek(uint16 A)
|
||||
{
|
||||
uint8 ret;
|
||||
|
||||
fceuindbg=1;
|
||||
ret=ARead[A](A);
|
||||
fceuindbg=0;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void FCEUI_MemPoke(uint16 a, uint8 v, int hl)
|
||||
{
|
||||
extern uint8 *Page[32];
|
||||
if(hl)
|
||||
{
|
||||
if(Page[a/2048])
|
||||
Page[a/2048][a]=v;
|
||||
}
|
||||
else
|
||||
BWrite[a](a,v);
|
||||
}
|
||||
|
||||
typedef struct __BPOINT {
|
||||
struct __BPOINT *next;
|
||||
void (*Handler)(X6502 *X, int type, unsigned int A);
|
||||
unsigned int A[2];
|
||||
int type;
|
||||
} BPOINT;
|
||||
|
||||
static BPOINT *BreakPoints=NULL;
|
||||
static BPOINT *LastBP=NULL;
|
||||
|
||||
static void (*CPUHook)(X6502 *)=NULL;
|
||||
|
||||
static int FindBPoint(X6502 *X, int who, unsigned int A)
|
||||
{
|
||||
BPOINT *tmp;
|
||||
|
||||
tmp=BreakPoints;
|
||||
while(tmp)
|
||||
{
|
||||
if(tmp->type&who)
|
||||
{
|
||||
if(tmp->type&BPOINT_PC)
|
||||
if(X->PC!=A) goto don; /* Doesn't match, so go on. */
|
||||
|
||||
if((A>=tmp->A[0]) && (A<=tmp->A[1])) /* Whee, match. */
|
||||
{
|
||||
tmp->Handler(X,tmp->type,A);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
don:
|
||||
tmp=tmp->next;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static uint8 ReadHandler(X6502 *X, unsigned int A)
|
||||
{
|
||||
extern X6502 XSave;
|
||||
|
||||
if(X->preexec)
|
||||
FindBPoint(&XSave,BPOINT_READ,A);
|
||||
return(ARead[A](A));
|
||||
}
|
||||
|
||||
static void WriteHandler(X6502 *X, unsigned int A, uint8 V)
|
||||
{
|
||||
extern X6502 XSave;
|
||||
|
||||
if(X->preexec)
|
||||
FindBPoint(&XSave,BPOINT_WRITE,A);
|
||||
else
|
||||
BWrite[A](A,V);
|
||||
}
|
||||
|
||||
int FCEUI_AddBreakPoint(int type, unsigned int A1, unsigned int A2,
|
||||
void (*Handler)(X6502 *, int type, unsigned int A))
|
||||
{
|
||||
BPOINT *tmp;
|
||||
|
||||
tmp=(BPOINT *)malloc(sizeof(BPOINT));
|
||||
|
||||
tmp->A[0]=A1;
|
||||
tmp->A[1]=A2;
|
||||
tmp->Handler=Handler;
|
||||
tmp->type=type;
|
||||
tmp->next=0;
|
||||
|
||||
if(BreakPoints==NULL)
|
||||
BreakPoints=tmp;
|
||||
else
|
||||
LastBP->next=tmp;
|
||||
|
||||
LastBP=tmp;
|
||||
|
||||
X6502_Debug(CPUHook,ReadHandler,WriteHandler);
|
||||
return(1);
|
||||
}
|
||||
|
||||
int FCEUI_SetBreakPoint(uint32 w, int type, unsigned int A1, unsigned int A2,
|
||||
void (*Handler)(X6502 *, int type, unsigned int A))
|
||||
{
|
||||
uint32 x=0;
|
||||
BPOINT *tmp;
|
||||
|
||||
tmp=BreakPoints;
|
||||
|
||||
while(tmp)
|
||||
{
|
||||
if(w==x)
|
||||
{
|
||||
tmp->type=type;
|
||||
tmp->A[0]=A1;
|
||||
tmp->A[1]=A2;
|
||||
tmp->Handler=Handler;
|
||||
return(1);
|
||||
}
|
||||
x++;
|
||||
tmp=tmp->next;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int FCEUI_GetBreakPoint(uint32 w, int *type, unsigned int *A1, unsigned int *A2,
|
||||
void (**Handler)(X6502 *, int type, unsigned int A))
|
||||
{
|
||||
uint32 x=0;
|
||||
BPOINT *tmp;
|
||||
|
||||
tmp=BreakPoints;
|
||||
|
||||
while(tmp)
|
||||
{
|
||||
if(w==x)
|
||||
{
|
||||
*type=tmp->type;
|
||||
*A1=tmp->A[0];
|
||||
*A2=tmp->A[1];
|
||||
*Handler=tmp->Handler;
|
||||
return(1);
|
||||
}
|
||||
x++;
|
||||
tmp=tmp->next;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int FCEUI_ListBreakPoints(int (*callb)(int type, unsigned int A1, unsigned int A2,
|
||||
void (*Handler)(X6502 *, int type, unsigned int A) ))
|
||||
{
|
||||
BPOINT *tmp;
|
||||
tmp=BreakPoints;
|
||||
while(tmp)
|
||||
{
|
||||
callb(tmp->type,tmp->A[0],tmp->A[1],tmp->Handler);
|
||||
tmp=tmp->next;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
int FCEUI_DeleteBreakPoint(uint32 w)
|
||||
{
|
||||
BPOINT *tmp,*prev=NULL;
|
||||
uint32 x=0;
|
||||
|
||||
tmp=BreakPoints;
|
||||
|
||||
while(tmp)
|
||||
{
|
||||
if(w==x)
|
||||
{
|
||||
if(prev) /* Not the first breakpoint. */
|
||||
{
|
||||
if(tmp->next) /* More breakpoints. */
|
||||
prev->next=tmp->next;
|
||||
else /* This is the last breakpoint. */
|
||||
{
|
||||
prev->next=0;
|
||||
LastBP=prev;
|
||||
}
|
||||
}
|
||||
else /* The first breakpoint. */
|
||||
{
|
||||
if(tmp->next) /* More breakpoints. */
|
||||
BreakPoints=tmp->next;
|
||||
else
|
||||
{
|
||||
BreakPoints=LastBP=0; /* No more breakpoints. */
|
||||
/* Update the CPU hooks. */
|
||||
X6502_Debug(CPUHook,BreakPoints?ReadHandler:0,BreakPoints?WriteHandler:0);
|
||||
}
|
||||
}
|
||||
free(tmp);
|
||||
return(1);
|
||||
}
|
||||
prev=tmp;
|
||||
tmp=tmp->next;
|
||||
x++;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
void FCEUI_SetCPUCallback(void (*callb)(X6502 *X))
|
||||
{
|
||||
CPUHook=callb;
|
||||
X6502_Debug(CPUHook,BreakPoints?ReadHandler:0,BreakPoints?WriteHandler:0);
|
||||
}
|
20
source/debug.h
Normal file
20
source/debug.h
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
/* Type attributes, you can OR them together. */
|
||||
#define BPOINT_READ 1
|
||||
#define BPOINT_WRITE 2
|
||||
#define BPOINT_PC 4
|
||||
|
||||
#include "x6502struct.h"
|
||||
|
||||
void FCEUI_DumpMem(const char *fname, uint32 start, uint32 end);
|
||||
void FCEUI_LoadMem(const char *fname, uint32 start, int hl);
|
||||
void FCEUI_SetCPUCallback(void (*callb)(X6502 *X));
|
||||
int FCEUI_DeleteBreakPoint(uint32 w);
|
||||
int FCEUI_ListBreakPoints(int (*callb)(int type, unsigned int A1, unsigned int A2,
|
||||
void (*Handler)(X6502 *, int type, unsigned int A) ));
|
||||
int FCEUI_GetBreakPoint(uint32 w, int *type, unsigned int *A1, unsigned int *A2,
|
||||
void (**Handler)(X6502 *, int type, unsigned int A));
|
||||
int FCEUI_SetBreakPoint(uint32 w, int type, unsigned int A1, unsigned int A2,
|
||||
void (*Handler)(X6502 *, int type, unsigned int A));
|
||||
int FCEUI_AddBreakPoint(int type, unsigned int A1, unsigned int A2,
|
||||
void (*Handler)(X6502 *, int type, unsigned int A));
|
114
source/drawing.h
Normal file
114
source/drawing.h
Normal file
@ -0,0 +1,114 @@
|
||||
void DrawTextLineBG(uint8 *dest)
|
||||
{
|
||||
int x,y;
|
||||
static int otable[7]={81,49,30,17,8,3,0};
|
||||
//100,40,15,10,7,5,2};
|
||||
for(y=0;y<14;y++)
|
||||
{
|
||||
int offs;
|
||||
|
||||
if(y>=7) offs=otable[13-y];
|
||||
else offs=otable[y];
|
||||
|
||||
for(x=offs;x<(256-offs);x++)
|
||||
dest[y*256+x]=(dest[y*256+x]&0x0f)|0xC0;//&=0xe0; //0x80;
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawMessage(void)
|
||||
{
|
||||
if(howlong)
|
||||
{
|
||||
uint8 *t;
|
||||
howlong--;
|
||||
t=XBuf+(FSettings.LastSLine-16)*256;
|
||||
if(t>=XBuf)
|
||||
{
|
||||
DrawTextLineBG(t);
|
||||
DrawTextTrans(t+256*3+(128-strlen(errmsg)*4),256,(uint8 *)errmsg,4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8 fontdata2[2048] =
|
||||
{
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x81,0xa5,0x81,0xbd,0x99,0x81,0x7e,0x7e,0xff,0xdb,0xff,0xc3,0xe7,0xff,0x7e,0x36,0x7f,0x7f,0x7f,0x3e,0x1c,0x08,0x00,0x08,0x1c,0x3e,0x7f,0x3e,0x1c,0x08,0x00,0x1c,0x3e,0x1c,0x7f,0x7f,0x3e,0x1c,0x3e,0x08,0x08,0x1c,0x3e,0x7f,0x3e,0x1c,0x3e,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xf0,0xe0,0xf0,0xbe,0x33,0x33,0x33,0x1e,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,0xfc,0xcc,0xfc,0x0c,0x0c,0x0e,0x0f,0x07,0xfe,0xc6,0xfe,0xc6,0xc6,0xe6,0x67,0x03,0x99,0x5a,0x3c,0xe7,0xe7,0x3c,0x5a,0x99,0x01,0x07,0x1f,0x7f,0x1f,0x07,0x01,0x00,0x40,0x70,0x7c,0x7f,0x7c,0x70,0x40,0x00,0x18,0x3c,0x7e,0x18,0x18,0x7e,0x3c,0x18,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x00,0xfe,0xdb,0xdb,0xde,0xd8,0xd8,0xd8,0x00,0x7c,0xc6,0x1c,0x36,0x36,0x1c,0x33,0x1e,0x00,0x00,0x00,0x00,0x7e,0x7e,0x7e,0x00,0x18,0x3c,0x7e,0x18,0x7e,0x3c,0x18,0xff,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x18,0x30,0x7f,0x30,0x18,0x00,0x00,0x00,0x0c,0x06,0x7f,0x06,0x0c,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x7f,0x00,0x00,0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x00,0x00,0x00,0xff,0xff,0x7e,0x3c,0x18,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x1e,0x0c,0x0c,0x00,0x0c,0x00,0x36,0x36,0x36,0x00,0x00,0x00,0x00,0x00,0x36,0x36,0x7f,0x36,0x7f,0x36,0x36,0x00,0x0c,0x3e,0x03,0x1e,0x30,0x1f,0x0c,0x00,0x00,0x63,0x33,0x18,0x0c,0x66,0x63,0x00,0x1c,0x36,0x1c,0x6e,0x3b,0x33,0x6e,0x00,0x06,0x06,0x03,0x00,0x00,0x00,0x00,0x00,0x18,0x0c,0x06,0x06,0x06,0x0c,0x18,0x00,0x06,0x0c,0x18,0x18,0x18,0x0c,0x06,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x0c,0x0c,0x3f,0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x0c,0x06,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x0c,0x00,0x60,0x30,0x18,0x0c,0x06,0x03,0x01,0x00,0x3e,0x63,0x73,0x7b,0x6f,0x67,0x3e,0x00,0x0c,0x0e,0x0c,0x0c,0x0c,0x0c,0x3f,0x00,0x1e,0x33,0x30,0x1c,0x06,0x33,0x3f,0x00,0x1e,0x33,0x30,0x1c,0x30,0x33,0x1e,0x00,0x38,0x3c,0x36,0x33,0x7f,0x30,0x78,0x00,0x3f,0x03,0x1f,0x30,0x30,0x33,0x1e,0x00,0x1c,0x06,0x03,0x1f,0x33,0x33,0x1e,0x00,0x3f,0x33,0x30,0x18,0x0c,0x0c,0x0c,0x00,0x1e,0x33,0x33,0x1e,0x33,0x33,0x1e,0x00,0x1e,0x33,0x33,0x3e,0x30,0x18,0x0e,0x00,0x00,0x0c,0x0c,0x00,0x00,0x0c,0x0c,0x00,0x00,0x0c,0x0c,0x00,0x00,0x0c,0x0c,0x06,0x18,0x0c,0x06,0x03,0x06,0x0c,0x18,0x00,0x00,0x00,0x3f,0x00,0x00,0x3f,0x00,0x00,0x06,0x0c,0x18,0x30,0x18,0x0c,0x06,0x00,0x1e,0x33,0x30,0x18,0x0c,0x00,0x0c,0x00,
|
||||
0x3e,0x63,0x7b,0x7b,0x7b,0x03,0x1e,0x00,0x0c,0x1e,0x33,0x33,0x3f,0x33,0x33,0x00,0x3f,0x66,0x66,0x3e,0x66,0x66,0x3f,0x00,0x3c,0x66,0x03,0x03,0x03,0x66,0x3c,0x00,0x1f,0x36,0x66,0x66,0x66,0x36,0x1f,0x00,0x7f,0x46,0x16,0x1e,0x16,0x46,0x7f,0x00,0x7f,0x46,0x16,0x1e,0x16,0x06,0x0f,0x00,0x3c,0x66,0x03,0x03,0x73,0x66,0x7c,0x00,0x33,0x33,0x33,0x3f,0x33,0x33,0x33,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x78,0x30,0x30,0x30,0x33,0x33,0x1e,0x00,0x67,0x66,0x36,0x1e,0x36,0x66,0x67,0x00,0x0f,0x06,0x06,0x06,0x46,0x66,0x7f,0x00,0x63,0x77,0x7f,0x7f,0x6b,0x63,0x63,0x00,0x63,0x67,0x6f,0x7b,0x73,0x63,0x63,0x00,0x1c,0x36,0x63,0x63,0x63,0x36,0x1c,0x00,0x3f,0x66,0x66,0x3e,0x06,0x06,0x0f,0x00,0x1e,0x33,0x33,0x33,0x3b,0x1e,0x38,0x00,0x3f,0x66,0x66,0x3e,0x36,0x66,0x67,0x00,0x1e,0x33,0x07,0x0e,0x38,0x33,0x1e,0x00,0x3f,0x2d,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x33,0x33,0x33,0x33,0x33,0x33,0x3f,0x00,0x33,0x33,0x33,0x33,0x33,0x1e,0x0c,0x00,0x63,0x63,0x63,0x6b,0x7f,0x77,0x63,0x00,0x63,0x63,0x36,0x1c,0x1c,0x36,0x63,0x00,0x33,0x33,0x33,0x1e,0x0c,0x0c,0x1e,0x00,0x7f,0x63,0x31,0x18,0x4c,0x66,0x7f,0x00,0x1e,0x06,0x06,0x06,0x06,0x06,0x1e,0x00,0x03,0x06,0x0c,0x18,0x30,0x60,0x40,0x00,0x1e,0x18,0x18,0x18,0x18,0x18,0x1e,0x00,0x08,0x1c,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
|
||||
0x0c,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x30,0x3e,0x33,0x6e,0x00,0x07,0x06,0x06,0x3e,0x66,0x66,0x3b,0x00,0x00,0x00,0x1e,0x33,0x03,0x33,0x1e,0x00,0x38,0x30,0x30,0x3e,0x33,0x33,0x6e,0x00,0x00,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x1c,0x36,0x06,0x0f,0x06,0x06,0x0f,0x00,0x00,0x00,0x6e,0x33,0x33,0x3e,0x30,0x1f,0x07,0x06,0x36,0x6e,0x66,0x66,0x67,0x00,0x0c,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x30,0x00,0x30,0x30,0x30,0x33,0x33,0x1e,0x07,0x06,0x66,0x36,0x1e,0x36,0x67,0x00,0x0e,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x33,0x7f,0x7f,0x6b,0x63,0x00,0x00,0x00,0x1f,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x1e,0x33,0x33,0x33,0x1e,0x00,0x00,0x00,0x3b,0x66,0x66,0x3e,0x06,0x0f,0x00,0x00,0x6e,0x33,0x33,0x3e,0x30,0x78,0x00,0x00,0x3b,0x6e,0x66,0x06,0x0f,0x00,0x00,0x00,0x3e,0x03,0x1e,0x30,0x1f,0x00,0x08,0x0c,0x3e,0x0c,0x0c,0x2c,0x18,0x00,0x00,0x00,0x33,0x33,0x33,0x33,0x6e,0x00,0x00,0x00,0x33,0x33,0x33,0x1e,0x0c,0x00,0x00,0x00,0x63,0x6b,0x7f,0x7f,0x36,0x00,0x00,0x00,0x63,0x36,0x1c,0x36,0x63,0x00,0x00,0x00,0x33,0x33,0x33,0x3e,0x30,0x1f,0x00,0x00,0x3f,0x19,0x0c,0x26,0x3f,0x00,0x38,0x0c,0x0c,0x07,0x0c,0x0c,0x38,0x00,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00,0x07,0x0c,0x0c,0x38,0x0c,0x0c,0x07,0x00,0x6e,0x3b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1c,0x36,0x63,0x63,0x7f,0x00,
|
||||
0x1e,0x33,0x03,0x33,0x1e,0x18,0x30,0x1e,0x00,0x33,0x00,0x33,0x33,0x33,0x7e,0x00,0x38,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x7e,0xc3,0x3c,0x60,0x7c,0x66,0xfc,0x00,0x33,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x07,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x0c,0x0c,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x00,0x00,0x1e,0x03,0x03,0x1e,0x30,0x1c,0x7e,0xc3,0x3c,0x66,0x7e,0x06,0x3c,0x00,0x33,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x07,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x33,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x3e,0x63,0x1c,0x18,0x18,0x18,0x3c,0x00,0x07,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x63,0x1c,0x36,0x63,0x7f,0x63,0x63,0x00,0x0c,0x0c,0x00,0x1e,0x33,0x3f,0x33,0x00,0x38,0x00,0x3f,0x06,0x1e,0x06,0x3f,0x00,0x00,0x00,0xfe,0x30,0xfe,0x33,0xfe,0x00,0x7c,0x36,0x33,0x7f,0x33,0x33,0x73,0x00,0x1e,0x33,0x00,0x1e,0x33,0x33,0x1e,0x00,0x00,0x33,0x00,0x1e,0x33,0x33,0x1e,0x00,0x00,0x07,0x00,0x1e,0x33,0x33,0x1e,0x00,0x1e,0x33,0x00,0x33,0x33,0x33,0x7e,0x00,0x00,0x07,0x00,0x33,0x33,0x33,0x7e,0x00,0x00,0x33,0x00,0x33,0x33,0x3e,0x30,0x1f,0xc3,0x18,0x3c,0x66,0x66,0x3c,0x18,0x00,0x33,0x00,0x33,0x33,0x33,0x33,0x1e,0x00,0x18,0x18,0x7e,0x03,0x03,0x7e,0x18,0x18,0x1c,0x36,0x26,0x0f,0x06,0x67,0x3f,0x00,0x33,0x33,0x1e,0x3f,0x0c,0x3f,0x0c,0x0c,0x1f,0x33,0x33,0x5f,0x63,0xf3,0x63,0xe3,0x70,0xd8,0x18,0x3c,0x18,0x18,0x1b,0x0e,
|
||||
0x38,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x1c,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x38,0x00,0x1e,0x33,0x33,0x1e,0x00,0x00,0x38,0x00,0x33,0x33,0x33,0x7e,0x00,0x00,0x1f,0x00,0x1f,0x33,0x33,0x33,0x00,0x3f,0x00,0x33,0x37,0x3f,0x3b,0x33,0x00,0x3c,0x36,0x36,0x7c,0x00,0x7e,0x00,0x00,0x1c,0x36,0x36,0x1c,0x00,0x3e,0x00,0x00,0x0c,0x00,0x0c,0x06,0x03,0x33,0x1e,0x00,0x00,0x00,0x00,0x3f,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x3f,0x30,0x30,0x00,0x00,0xc3,0x63,0x33,0x7b,0xcc,0x66,0x33,0xf0,0xc3,0x63,0x33,0xdb,0xec,0xf6,0xf3,0xc0,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x00,0x00,0xcc,0x66,0x33,0x66,0xcc,0x00,0x00,0x00,0x33,0x66,0xcc,0x66,0x33,0x00,0x00,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xdb,0xee,0xdb,0x77,0xdb,0xee,0xdb,0x77,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,0x6c,0x6c,0x6c,0x6c,0x6f,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x7f,0x6c,0x6c,0x6c,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x6c,0x6c,0x6f,0x60,0x6f,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x7f,0x60,0x6f,0x6c,0x6c,0x6c,0x6c,0x6c,0x6f,0x60,0x7f,0x00,0x00,0x00,0x6c,0x6c,0x6c,0x6c,0x7f,0x00,0x00,0x00,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,
|
||||
0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x6c,0x6c,0x6c,0x6c,0xec,0x6c,0x6c,0x6c,0x6c,0x6c,0xec,0x0c,0xfc,0x00,0x00,0x00,0x00,0x00,0xfc,0x0c,0xec,0x6c,0x6c,0x6c,0x6c,0x6c,0xef,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xef,0x6c,0x6c,0x6c,0x6c,0x6c,0xec,0x0c,0xec,0x6c,0x6c,0x6c,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x6c,0x6c,0xef,0x00,0xef,0x6c,0x6c,0x6c,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,0x6c,0x6c,0x6c,0x6c,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0xff,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0xfc,0x00,0x00,0x00,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0xfc,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0xff,0x6c,0x6c,0x6c,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x6e,0x3b,0x13,0x3b,0x6e,0x00,0x00,0x1e,0x33,0x1f,0x33,0x1f,0x03,0x03,0x00,0x3f,0x33,0x03,0x03,0x03,0x03,0x00,0x00,0x7f,0x36,0x36,0x36,0x36,0x36,0x00,0x3f,0x33,0x06,0x0c,0x06,0x33,0x3f,0x00,0x00,0x00,0x7e,0x1b,0x1b,0x1b,0x0e,0x00,0x00,0x66,0x66,0x66,0x66,0x3e,0x06,0x03,0x00,0x6e,0x3b,0x18,0x18,0x18,0x18,0x00,0x3f,0x0c,0x1e,0x33,0x33,0x1e,0x0c,0x3f,0x1c,0x36,0x63,0x7f,0x63,0x36,0x1c,0x00,0x1c,0x36,0x63,0x63,0x36,0x36,0x77,0x00,0x38,0x0c,0x18,0x3e,0x33,0x33,0x1e,0x00,0x00,0x00,0x7e,0xdb,0xdb,0x7e,0x00,0x00,0x60,0x30,0x7e,0xdb,0xdb,0x7e,0x06,0x03,0x1c,0x06,0x03,0x1f,0x03,0x06,0x1c,0x00,0x1e,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x3f,0x00,0x3f,0x00,0x3f,0x00,0x00,0x0c,0x0c,0x3f,0x0c,0x0c,0x00,0x3f,0x00,0x06,0x0c,0x18,0x0c,0x06,0x00,0x3f,0x00,0x18,0x0c,0x06,0x0c,0x18,0x00,0x3f,0x00,0x70,0xd8,0xd8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x0e,0x0c,0x0c,0x00,0x3f,0x00,0x0c,0x0c,0x00,0x00,0x6e,0x3b,0x00,0x6e,0x3b,0x00,0x00,0x1c,0x36,0x36,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0xf0,0x30,0x30,0x30,0x37,0x36,0x3c,0x38,0x1e,0x36,0x36,0x36,0x36,0x00,0x00,0x00,0x0e,0x18,0x0c,0x06,0x1e,0x00,0x00,0x00,0x00,0x00,0x3c,0x3c,0x3c,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
};
|
||||
|
||||
void DrawTextTrans(uint8 *dest, uint32 width, uint8 *textmsg, uint8 fgcolor)
|
||||
{
|
||||
uint8 length=strlen((char *)textmsg);
|
||||
uint8 x;
|
||||
uint8 y;
|
||||
uint8 z;
|
||||
|
||||
for(x=0;x<length;x++)
|
||||
for(y=0;y<8;y++)
|
||||
for(z=0;z<8;z++)
|
||||
if((fontdata2[(textmsg[x]<<3)+y]>>z)&1) dest[y*width+(x<<3)+z]=fgcolor;
|
||||
}
|
||||
|
||||
static uint8 sstat[2541] =
|
||||
{
|
||||
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
|
||||
0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,
|
||||
0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x83,0x83,0x83,
|
||||
0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x80,0x83,
|
||||
0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,
|
||||
0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,
|
||||
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
|
||||
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
|
||||
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x81,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
|
||||
0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
|
||||
0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,
|
||||
0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,
|
||||
0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,
|
||||
0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,
|
||||
0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
|
||||
};
|
||||
|
||||
void FCEU_DrawNumberRow(uint8 *XBuf, int *nstatus, int cur)
|
||||
{
|
||||
uint8 *XBaf;
|
||||
int z,x,y;
|
||||
|
||||
XBaf=XBuf - 4 + (FSettings.LastSLine-34)*256;
|
||||
if(XBaf>=XBuf)
|
||||
for(z=1;z<11;z++)
|
||||
{
|
||||
if(nstatus[z%10])
|
||||
{
|
||||
for(y=0;y<13;y++)
|
||||
for(x=0;x<21;x++)
|
||||
XBaf[y*256+x+z*21+z]=sstat[y*21+x+(z-1)*21*12]^0x80;
|
||||
} else {
|
||||
for(y=0;y<13;y++)
|
||||
for(x=0;x<21;x++)
|
||||
if(sstat[y*21+x+(z-1)*21*12]!=0x83)
|
||||
XBaf[y*256+x+z*21+z]=sstat[y*21+x+(z-1)*21*12]^0x80;
|
||||
|
||||
else
|
||||
XBaf[y*256+x+z*21+z]=(XBaf[y*256+x+z*21+z]&0xF)|0xC0;
|
||||
}
|
||||
if(cur==z%10)
|
||||
{
|
||||
for(x=0;x<21;x++)
|
||||
XBaf[x+z*21+z*1]=4;
|
||||
for(x=1;x<12;x++)
|
||||
{
|
||||
XBaf[256*x+z*21+z*1]=
|
||||
XBaf[256*x+z*21+z*1+20]=4;
|
||||
}
|
||||
for(x=0;x<21;x++)
|
||||
XBaf[12*256+x+z*21+z*1]=4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
240
source/driver.h
Normal file
240
source/driver.h
Normal file
@ -0,0 +1,240 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "types.h"
|
||||
#include "git.h"
|
||||
#include "debug.h"
|
||||
|
||||
FILE *FCEUD_UTF8fopen(const char *fn, const char *mode);
|
||||
|
||||
/* This makes me feel dirty for some reason. */
|
||||
void FCEU_printf(char *format, ...);
|
||||
#define FCEUI_printf FCEU_printf
|
||||
|
||||
/* Video interface */
|
||||
void FCEUD_SetPalette(uint8 index, uint8 r, uint8 g, uint8 b);
|
||||
void FCEUD_GetPalette(uint8 i,uint8 *r, uint8 *g, uint8 *b);
|
||||
|
||||
/* Displays an error. Can block or not. */
|
||||
void FCEUD_PrintError(char *s);
|
||||
void FCEUD_Message(char *s);
|
||||
|
||||
#ifdef NETWORK
|
||||
/* Network interface */
|
||||
|
||||
/* Call only when a game is loaded. */
|
||||
int FCEUI_NetplayStart(int nlocal, int divisor);
|
||||
|
||||
/* Call when network play needs to stop. */
|
||||
void FCEUI_NetplayStop(void);
|
||||
|
||||
/* Note: YOU MUST NOT CALL ANY FCEUI_* FUNCTIONS WHILE IN FCEUD_SendData() or
|
||||
FCEUD_RecvData().
|
||||
*/
|
||||
|
||||
/* Return 0 on failure, 1 on success. */
|
||||
int FCEUD_SendData(void *data, uint32 len);
|
||||
int FCEUD_RecvData(void *data, uint32 len);
|
||||
|
||||
/* Display text received over the network. */
|
||||
void FCEUD_NetplayText(uint8 *text);
|
||||
|
||||
/* Encode and send text over the network. */
|
||||
void FCEUI_NetplayText(uint8 *text);
|
||||
|
||||
/* Called when a fatal error occurred and network play can't continue. This function
|
||||
should call FCEUI_NetplayStop() after it has deinitialized the network on the driver
|
||||
side.
|
||||
*/
|
||||
void FCEUD_NetworkClose(void);
|
||||
#endif
|
||||
|
||||
int FCEUI_BeginWaveRecord(char *fn);
|
||||
int FCEUI_EndWaveRecord(void);
|
||||
|
||||
void FCEUI_ResetNES(void);
|
||||
void FCEUI_PowerNES(void);
|
||||
|
||||
void FCEUI_NTSCSELHUE(void);
|
||||
void FCEUI_NTSCSELTINT(void);
|
||||
void FCEUI_NTSCDEC(void);
|
||||
void FCEUI_NTSCINC(void);
|
||||
void FCEUI_GetNTSCTH(int *tint, int *hue);
|
||||
void FCEUI_SetNTSCTH(int n, int tint, int hue);
|
||||
|
||||
void FCEUI_SetInput(int port, int type, void *ptr, int attrib);
|
||||
void FCEUI_SetInputFC(int type, void *ptr, int attrib);
|
||||
void FCEUI_DisableFourScore(int s);
|
||||
|
||||
#define SI_NONE 0
|
||||
#define SI_GAMEPAD 1
|
||||
#define SI_ZAPPER 2
|
||||
#define SI_POWERPADA 3
|
||||
#define SI_POWERPADB 4
|
||||
#define SI_ARKANOID 5
|
||||
|
||||
#define SIFC_NONE 0
|
||||
#define SIFC_ARKANOID 1
|
||||
#define SIFC_SHADOW 2
|
||||
#define SIFC_4PLAYER 3
|
||||
#define SIFC_FKB 4
|
||||
#define SIFC_HYPERSHOT 5
|
||||
#define SIFC_MAHJONG 6
|
||||
#define SIFC_QUIZKING 7
|
||||
#define SIFC_FTRAINERA 8
|
||||
#define SIFC_FTRAINERB 9
|
||||
#define SIFC_OEKAKIDS 10
|
||||
#define SIFC_BWORLD 11
|
||||
#define SIFC_TOPRIDER 12
|
||||
|
||||
#define SIS_NONE 0
|
||||
#define SIS_DATACH 1
|
||||
#define SIS_NWC 2
|
||||
#define SIS_VSUNISYSTEM 3
|
||||
#define SIS_NSF 4
|
||||
|
||||
/* New interface functions */
|
||||
|
||||
/* 0 to order screen snapshots numerically(0.png), 1 to order them file base-numerically(smb3-0.png). */
|
||||
void FCEUI_SetSnapName(int a);
|
||||
|
||||
/* 0 to keep 8-sprites limitation, 1 to remove it */
|
||||
void FCEUI_DisableSpriteLimitation(int a);
|
||||
|
||||
/* -1 = no change, 0 = show, 1 = hide, 2 = internal toggle */
|
||||
void FCEUI_SetRenderDisable(int sprites, int bg);
|
||||
|
||||
/* name=path and file to load. returns 0 on failure, 1 on success */
|
||||
FCEUGI *FCEUI_LoadGame(const char *name);
|
||||
|
||||
/* allocates memory. 0 on failure, 1 on success. */
|
||||
int FCEUI_Initialize(void);
|
||||
|
||||
/* Emulates a frame. */
|
||||
void FCEUI_Emulate(uint8 **, int32 **, int32 *, int);
|
||||
|
||||
/* Closes currently loaded game */
|
||||
void FCEUI_CloseGame(void);
|
||||
|
||||
/* Deallocates all allocated memory. Call after FCEUI_Emulate() returns. */
|
||||
void FCEUI_Kill(void);
|
||||
|
||||
/* Enable/Disable game genie. a=0 disable, a=1 enable */
|
||||
void FCEUI_SetGameGenie(int a);
|
||||
|
||||
/* Set video system a=0 NTSC, a=1 PAL */
|
||||
void FCEUI_SetVidSystem(int a);
|
||||
|
||||
/* Convenience function; returns currently emulated video system(0=NTSC, 1=PAL). */
|
||||
int FCEUI_GetCurrentVidSystem(int *slstart, int *slend);
|
||||
|
||||
#ifdef FRAMESKIP
|
||||
/* Should be called from FCEUD_BlitScreen(). Specifies how many frames
|
||||
to skip until FCEUD_BlitScreen() is called. FCEUD_BlitScreenDummy()
|
||||
will be called instead of FCEUD_BlitScreen() when when a frame is skipped.
|
||||
*/
|
||||
void FCEUI_FrameSkip(int x);
|
||||
#endif
|
||||
|
||||
/* First and last scanlines to render, for ntsc and pal emulation. */
|
||||
void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall);
|
||||
|
||||
/* Sets the base directory(save states, snapshots, etc. are saved in directories
|
||||
below this directory. */
|
||||
void FCEUI_SetBaseDirectory(char *dir);
|
||||
|
||||
/* Tells FCE Ultra to copy the palette data pointed to by pal and use it.
|
||||
Data pointed to by pal needs to be 64*3 bytes in length.
|
||||
*/
|
||||
void FCEUI_SetPaletteArray(uint8 *pal);
|
||||
|
||||
/* Sets up sound code to render sound at the specified rate, in samples
|
||||
per second. Only sample rates of 44100, 48000, and 96000 are currently
|
||||
supported.
|
||||
If "Rate" equals 0, sound is disabled.
|
||||
*/
|
||||
void FCEUI_Sound(int Rate);
|
||||
void FCEUI_SetSoundVolume(uint32 volume);
|
||||
void FCEUI_SetSoundQuality(int quality);
|
||||
|
||||
void FCEUI_SelectState(int);
|
||||
|
||||
/* "fname" overrides the default save state filename code if non-NULL. */
|
||||
void FCEUI_SaveState(char *fname);
|
||||
void FCEUI_LoadState(char *fname);
|
||||
|
||||
void FCEUI_SelectMovie(int);
|
||||
void FCEUI_SaveMovie(char *fname);
|
||||
void FCEUI_LoadMovie(char *fname);
|
||||
|
||||
int32 FCEUI_GetDesiredFPS(void);
|
||||
void FCEUI_SaveSnapshot(void);
|
||||
void FCEU_DispMessage(char *format, ...);
|
||||
#define FCEUI_DispMessage FCEU_DispMessage
|
||||
|
||||
int FCEUI_DecodePAR(const char *code, uint16 *a, uint8 *v, int *c, int *type);
|
||||
int FCEUI_DecodeGG(const char *str, uint16 *a, uint8 *v, int *c);
|
||||
int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int type);
|
||||
int FCEUI_DelCheat(uint32 which);
|
||||
int FCEUI_ToggleCheat(uint32 which);
|
||||
|
||||
int32 FCEUI_CheatSearchGetCount(void);
|
||||
void FCEUI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a, uint8 last, uint8 current));
|
||||
void FCEUI_CheatSearchGet(int (*callb)(uint32 a, uint8 last, uint8 current, void *data), void *data);
|
||||
void FCEUI_CheatSearchBegin(void);
|
||||
void FCEUI_CheatSearchEnd(int type, uint8 v1, uint8 v2);
|
||||
void FCEUI_ListCheats(int (*callb)(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data), void *data);
|
||||
|
||||
int FCEUI_GetCheat(uint32 which, char **name, uint32 *a, uint8 *v, int *compare, int *s, int *type);
|
||||
int FCEUI_SetCheat(uint32 which, const char *name, int32 a, int32 v, int compare,int s, int type);
|
||||
|
||||
void FCEUI_CheatSearchShowExcluded(void);
|
||||
void FCEUI_CheatSearchSetCurrentAsOriginal(void);
|
||||
|
||||
#define FCEUIOD_STATE 0
|
||||
#define FCEUIOD_SNAPS 1
|
||||
#define FCEUIOD_NV 2
|
||||
#define FCEUIOD_CHEATS 3
|
||||
#define FCEUIOD_MISC 4
|
||||
#define FCEUIOD_MOVIE 5
|
||||
|
||||
#define FCEUIOD__COUNT 6
|
||||
|
||||
void FCEUI_SetDirOverride(int which, char *n);
|
||||
|
||||
void FCEUI_MemDump(uint16 a, int32 len, void (*callb)(uint16 a, uint8 v));
|
||||
uint8 FCEUI_MemSafePeek(uint16 A);
|
||||
void FCEUI_MemPoke(uint16 a, uint8 v, int hl);
|
||||
void FCEUI_NMI(void);
|
||||
void FCEUI_IRQ(void);
|
||||
uint16 FCEUI_Disassemble(void *XA, uint16 a, char *stringo);
|
||||
void FCEUI_GetIVectors(uint16 *reset, uint16 *irq, uint16 *nmi);
|
||||
|
||||
uint32 FCEUI_CRC32(uint32 crc, uint8 *buf, uint32 len);
|
||||
|
||||
void FCEUI_ToggleTileView(void);
|
||||
void FCEUI_SetLowPass(int q);
|
||||
|
||||
void FCEUI_NSFSetVis(int mode);
|
||||
int FCEUI_NSFChange(int amount);
|
||||
int FCEUI_NSFGetInfo(uint8 *name, uint8 *artist, uint8 *copyright, int maxlen);
|
||||
|
||||
void FCEUI_VSUniToggleDIPView(void);
|
||||
void FCEUI_VSUniToggleDIP(int w);
|
||||
uint8 FCEUI_VSUniGetDIPs(void);
|
||||
void FCEUI_VSUniSetDIP(int w, int state);
|
||||
void FCEUI_VSUniCoin(void);
|
||||
|
||||
int FCEUI_FDSInsert(int oride);
|
||||
int FCEUI_FDSEject(void);
|
||||
void FCEUI_FDSSelect(void);
|
||||
|
||||
int FCEUI_DatachSet(const uint8 *rcode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
98
source/drivers/common/args.c
Normal file
98
source/drivers/common/args.c
Normal file
@ -0,0 +1,98 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/****************************************************************/
|
||||
/* FCE Ultra */
|
||||
/* */
|
||||
/* This file contains code for parsing command-line */
|
||||
/* options. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../types.h"
|
||||
#include "args.h"
|
||||
|
||||
void ParseEA(int x, int argc, char *argv[], ARGPSTRUCT *argsps)
|
||||
{
|
||||
int y=0;
|
||||
|
||||
do
|
||||
{
|
||||
if(!argsps[y].name)
|
||||
{
|
||||
ParseEA(x,argc,argv,(ARGPSTRUCT*)argsps[y].var);
|
||||
y++;
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(argv[x],argsps[y].name)) // A match.
|
||||
{
|
||||
if(argsps[y].subs)
|
||||
{
|
||||
if((x+1)>=argc)
|
||||
break;
|
||||
if(argsps[y].substype&0x2000)
|
||||
{
|
||||
((void (*)(char *))argsps[y].subs)(argv[x+1]);
|
||||
}
|
||||
else if(argsps[y].substype&0x8000)
|
||||
{
|
||||
*(int *)argsps[y].subs&=~(argsps[y].substype&(~0x8000));
|
||||
*(int *)argsps[y].subs|=atoi(argv[x+1])?(argsps[y].substype&(~0x8000)):0;
|
||||
}
|
||||
else
|
||||
switch(argsps[y].substype&(~0x4000))
|
||||
{
|
||||
case 0: // Integer
|
||||
*(int *)argsps[y].subs=atoi(argv[x+1]);
|
||||
break;
|
||||
case 2: // Double float
|
||||
*(double *)argsps[y].subs=atof(argv[x+1]);
|
||||
break;
|
||||
case 1: // String
|
||||
if(argsps[y].substype&0x4000)
|
||||
{
|
||||
if(*(char **)argsps[y].subs)
|
||||
free(*(char **)argsps[y].subs);
|
||||
if(!( *(char **)argsps[y].subs=(char*)malloc(strlen(argv[x+1])+1) ))
|
||||
break;
|
||||
}
|
||||
strcpy(*(char **)argsps[y].subs,argv[x+1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(argsps[y].var)
|
||||
*argsps[y].var=1;
|
||||
}
|
||||
y++;
|
||||
} while(argsps[y].var || argsps[y].subs);
|
||||
}
|
||||
|
||||
void ParseArguments(int argc, char *argv[], ARGPSTRUCT *argsps)
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x=0;x<argc;x++)
|
||||
ParseEA(x,argc,argv,argsps);
|
||||
}
|
||||
|
12
source/drivers/common/args.h
Normal file
12
source/drivers/common/args.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _DRIVERS_ARGH
|
||||
typedef struct {
|
||||
char *name;
|
||||
int *var;
|
||||
|
||||
void *subs;
|
||||
int substype;
|
||||
} ARGPSTRUCT;
|
||||
|
||||
void ParseArguments(int argc, char *argv[], ARGPSTRUCT *argsps);
|
||||
#define _DRIVERS_ARGH
|
||||
#endif
|
523
source/drivers/common/cheat.c
Normal file
523
source/drivers/common/cheat.c
Normal file
@ -0,0 +1,523 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "../../driver.h"
|
||||
|
||||
static void GetString(char *s, int max)
|
||||
{
|
||||
int x;
|
||||
fgets(s,max,stdin);
|
||||
|
||||
for(x=0;x<max;x++)
|
||||
if(s[x]=='\n')
|
||||
{
|
||||
s[x]=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get unsigned 16-bit integer from stdin in hex. */
|
||||
static uint32 GetH16(unsigned int def)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
fgets(buf,32,stdin);
|
||||
if(buf[0]=='\n')
|
||||
return(def);
|
||||
if(buf[0]=='$')
|
||||
sscanf(buf+1,"%04x",&def);
|
||||
else
|
||||
sscanf(buf,"%04x",&def);
|
||||
return def;
|
||||
}
|
||||
|
||||
/* Get unsigned 8-bit integer from stdin in decimal. */
|
||||
static uint8 Get8(unsigned int def)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
fgets(buf,32,stdin);
|
||||
if(buf[0]=='\n')
|
||||
return(def);
|
||||
sscanf(buf,"%u",&def);
|
||||
return def;
|
||||
}
|
||||
|
||||
static int GetI(int def)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
fgets(buf,32,stdin);
|
||||
if(buf[0]=='\n')
|
||||
return(def);
|
||||
sscanf(buf,"%d",&def);
|
||||
return def;
|
||||
}
|
||||
|
||||
static int GetYN(int def)
|
||||
{
|
||||
char buf[32];
|
||||
printf("(Y/N)[%s]: ",def?"Y":"N");
|
||||
fgets(buf,32,stdin);
|
||||
if(buf[0]=='y' || buf[0]=='Y')
|
||||
return(1);
|
||||
if(buf[0]=='n' || buf[0]=='N')
|
||||
return(0);
|
||||
return(def);
|
||||
}
|
||||
|
||||
/*
|
||||
** Begin list code.
|
||||
**
|
||||
*/
|
||||
static int listcount;
|
||||
static int listids[16];
|
||||
static int listsel;
|
||||
static int mordoe;
|
||||
|
||||
void BeginListShow(void)
|
||||
{
|
||||
listcount=0;
|
||||
listsel=-1;
|
||||
mordoe=0;
|
||||
}
|
||||
|
||||
/* Hmm =0 for in list choices, hmm=1 for end of list choices. */
|
||||
/* Return equals 0 to continue, -1 to stop, otherwise a number. */
|
||||
int ListChoice(int hmm)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
if(!hmm)
|
||||
{
|
||||
int num=0;
|
||||
|
||||
tryagain:
|
||||
printf(" <'Enter' to continue, (S)top, or enter a number.> ");
|
||||
fgets(buf,32,stdin);
|
||||
if(buf[0]=='s' || buf[0]=='S') return(-1);
|
||||
if(buf[0]=='\n') return(0);
|
||||
if(!sscanf(buf,"%d",&num))
|
||||
return(0);
|
||||
if(num<1) goto tryagain;
|
||||
return(num);
|
||||
}
|
||||
else
|
||||
{
|
||||
int num=0;
|
||||
|
||||
tryagain2:
|
||||
printf(" <'Enter' to make no selection or enter a number.> ");
|
||||
fgets(buf,32,stdin);
|
||||
if(buf[0]=='\n') return(0);
|
||||
if(!sscanf(buf,"%d",&num))
|
||||
return(0);
|
||||
if(num<1) goto tryagain2;
|
||||
return(num);
|
||||
}
|
||||
}
|
||||
|
||||
int EndListShow(void)
|
||||
{
|
||||
if(mordoe)
|
||||
{
|
||||
int r=ListChoice(1);
|
||||
if(r>0 && r<=listcount)
|
||||
listsel=listids[r-1];
|
||||
}
|
||||
return(listsel);
|
||||
}
|
||||
|
||||
/* Returns 0 to stop listing, 1 to continue. */
|
||||
int AddToList(char *text, uint32 id)
|
||||
{
|
||||
if(listcount==16)
|
||||
{
|
||||
int t=ListChoice(0);
|
||||
mordoe=0;
|
||||
if(t==-1) return(0); // Stop listing.
|
||||
else if(t>0 && t<17)
|
||||
{
|
||||
listsel=listids[t-1];
|
||||
return(0);
|
||||
}
|
||||
listcount=0;
|
||||
}
|
||||
mordoe=1;
|
||||
listids[listcount]=id;
|
||||
printf("%2d) %s\n",listcount+1,text);
|
||||
listcount++;
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** End list code.
|
||||
**/
|
||||
|
||||
typedef struct MENU {
|
||||
char *text;
|
||||
void *action;
|
||||
int type; // 0 for menu, 1 for function.
|
||||
} MENU;
|
||||
|
||||
static void SetOC(void)
|
||||
{
|
||||
FCEUI_CheatSearchSetCurrentAsOriginal();
|
||||
}
|
||||
|
||||
static void UnhideEx(void)
|
||||
{
|
||||
FCEUI_CheatSearchShowExcluded();
|
||||
}
|
||||
|
||||
static void ToggleCheat(int num)
|
||||
{
|
||||
printf("Cheat %d %sabled.\n",1+num,
|
||||
FCEUI_ToggleCheat(num)?"en":"dis");
|
||||
}
|
||||
|
||||
static void ModifyCheat(int num)
|
||||
{
|
||||
char *name;
|
||||
char buf[256];
|
||||
uint32 A;
|
||||
uint8 V;
|
||||
int compare;
|
||||
int type;
|
||||
|
||||
int s;
|
||||
int t;
|
||||
|
||||
FCEUI_GetCheat(num, &name, &A, &V, &compare, &s, &type);
|
||||
|
||||
printf("Name [%s]: ",name);
|
||||
GetString(buf,256);
|
||||
|
||||
/* This obviously doesn't allow for cheats with no names. Bah. Who wants
|
||||
nameless cheats anyway...
|
||||
*/
|
||||
|
||||
if(buf[0])
|
||||
name=buf; // Change name when FCEUI_SetCheat() is called.
|
||||
else
|
||||
name=0; // Don't change name when FCEUI_SetCheat() is called.
|
||||
|
||||
printf("Address [$%04x]: ",(unsigned int)A);
|
||||
A=GetH16(A);
|
||||
|
||||
printf("Value [%03d]: ",(unsigned int)V);
|
||||
V=Get8(V);
|
||||
|
||||
printf("Compare [%3d]: ",compare);
|
||||
compare=GetI(compare);
|
||||
|
||||
printf("Type(0=Old Style, 1=Read Substitute) [%1d]: ",type);
|
||||
type=GetI(type)?1:0;
|
||||
|
||||
printf("Enable [%s]: ",s?"Y":"N");
|
||||
t=getchar();
|
||||
if(t=='Y' || t=='y') s=1;
|
||||
else if(t=='N' || t=='n') s=0;
|
||||
|
||||
FCEUI_SetCheat(num,name,A,V,compare,s,type);
|
||||
}
|
||||
|
||||
|
||||
static void AddCheatGGPAR(int which)
|
||||
{
|
||||
uint16 A;
|
||||
uint8 V;
|
||||
int C;
|
||||
int type;
|
||||
char name[256],code[256];
|
||||
|
||||
printf("Name: ");
|
||||
GetString(name,256);
|
||||
|
||||
printf("Code: ");
|
||||
GetString(code,256);
|
||||
|
||||
printf("Add cheat \"%s\" for code \"%s\"?",name,code);
|
||||
if(GetYN(0))
|
||||
{
|
||||
if(which)
|
||||
{
|
||||
if(!FCEUI_DecodePAR(code,&A,&V,&C,&type))
|
||||
{
|
||||
puts("Invalid Game Genie code.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!FCEUI_DecodeGG(code,&A,&V,&C))
|
||||
{
|
||||
puts("Invalid Game Genie code.");
|
||||
return;
|
||||
}
|
||||
type=1;
|
||||
}
|
||||
|
||||
if(FCEUI_AddCheat(name,A,V,C,type))
|
||||
puts("Cheat added.");
|
||||
else
|
||||
puts("Error adding cheat.");
|
||||
}
|
||||
}
|
||||
|
||||
static void AddCheatGG(void)
|
||||
{
|
||||
AddCheatGGPAR(0);
|
||||
}
|
||||
|
||||
static void AddCheatPAR(void)
|
||||
{
|
||||
AddCheatGGPAR(1);
|
||||
}
|
||||
|
||||
static void AddCheatParam(uint32 A, uint8 V)
|
||||
{
|
||||
char name[256];
|
||||
|
||||
printf("Name: ");
|
||||
GetString(name,256);
|
||||
printf("Address [$%04x]: ",(unsigned int)A);
|
||||
A=GetH16(A);
|
||||
printf("Value [%03d]: ",(unsigned int)V);
|
||||
V=Get8(V);
|
||||
printf("Add cheat \"%s\" for address $%04x with value %03d?",name,(unsigned int)A,(unsigned int)V);
|
||||
if(GetYN(0))
|
||||
{
|
||||
if(FCEUI_AddCheat(name,A,V,-1,0))
|
||||
puts("Cheat added.");
|
||||
else
|
||||
puts("Error adding cheat.");
|
||||
}
|
||||
}
|
||||
|
||||
static void AddCheat(void)
|
||||
{
|
||||
AddCheatParam(0,0);
|
||||
}
|
||||
|
||||
static int lid;
|
||||
static int clistcallb(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data)
|
||||
{
|
||||
char tmp[512];
|
||||
int ret;
|
||||
|
||||
if(compare>=0)
|
||||
sprintf(tmp,"%s $%04x:%03d:%03d - %s",s?"*":" ",(unsigned int)a,(unsigned int)v,compare,name);
|
||||
else
|
||||
sprintf(tmp,"%s $%04x:%03d - %s",s?"*":" ",(unsigned int)a,(unsigned int)v,name);
|
||||
if(type==1)
|
||||
tmp[2]='S';
|
||||
ret=AddToList(tmp,lid);
|
||||
lid++;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static void ListCheats(void)
|
||||
{
|
||||
int which;
|
||||
lid=0;
|
||||
|
||||
BeginListShow();
|
||||
FCEUI_ListCheats(clistcallb,0);
|
||||
which=EndListShow();
|
||||
if(which>=0)
|
||||
{
|
||||
char tmp[32];
|
||||
printf(" <(T)oggle status, (M)odify, or (D)elete this cheat.> ");
|
||||
fgets(tmp,32,stdin);
|
||||
switch(tolower(tmp[0]))
|
||||
{
|
||||
case 't':ToggleCheat(which);
|
||||
break;
|
||||
case 'd':if(!FCEUI_DelCheat(which))
|
||||
puts("Error deleting cheat!");
|
||||
else
|
||||
puts("Cheat has been deleted.");
|
||||
break;
|
||||
case 'm':ModifyCheat(which);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ResetSearch(void)
|
||||
{
|
||||
FCEUI_CheatSearchBegin();
|
||||
puts("Done.");
|
||||
}
|
||||
|
||||
static int srescallb(uint32 a, uint8 last, uint8 current, void *data)
|
||||
{
|
||||
char tmp[13];
|
||||
sprintf(tmp, "$%04x:%03d:%03d",(unsigned int)a,(unsigned int)last,(unsigned int)current);
|
||||
return(AddToList(tmp,a));
|
||||
}
|
||||
|
||||
static void ShowRes(void)
|
||||
{
|
||||
int n=FCEUI_CheatSearchGetCount();
|
||||
printf(" %d results:\n",n);
|
||||
if(n)
|
||||
{
|
||||
int which;
|
||||
BeginListShow();
|
||||
FCEUI_CheatSearchGet(srescallb,0);
|
||||
which=EndListShow();
|
||||
if(which>=0)
|
||||
AddCheatParam(which,0);
|
||||
}
|
||||
}
|
||||
|
||||
static int ShowShortList(char *moe[], int n, int def)
|
||||
{
|
||||
int x,c;
|
||||
unsigned int baa;
|
||||
char tmp[16];
|
||||
|
||||
red:
|
||||
for(x=0;x<n;x++)
|
||||
printf("%d) %s\n",x+1,moe[x]);
|
||||
puts("D) Display List");
|
||||
clo:
|
||||
|
||||
printf("\nSelection [%d]> ",def+1);
|
||||
fgets(tmp,256,stdin);
|
||||
if(tmp[0]=='\n')
|
||||
return def;
|
||||
c=tolower(tmp[0]);
|
||||
baa=c-'1';
|
||||
|
||||
if(baa<n)
|
||||
return baa;
|
||||
else if(c=='d')
|
||||
goto red;
|
||||
else
|
||||
{
|
||||
puts("Invalid selection.");
|
||||
goto clo;
|
||||
}
|
||||
}
|
||||
|
||||
static void DoSearch(void)
|
||||
{
|
||||
static int v1=0,v2=0;
|
||||
static int method=0;
|
||||
char *m[6]={"O==V1 && C==V2","O==V1 && |O-C|==V2","|O-C|==V2","O!=C","Value decreased","Value increased"};
|
||||
printf("\nSearch Filter:\n");
|
||||
|
||||
method=ShowShortList(m,6,method);
|
||||
if(method<=1)
|
||||
{
|
||||
printf("V1 [%03d]: ",v1);
|
||||
v1=Get8(v1);
|
||||
}
|
||||
if(method<=2)
|
||||
{
|
||||
printf("V2 [%03d]: ",v2);
|
||||
v2=Get8(v2);
|
||||
}
|
||||
FCEUI_CheatSearchEnd(method,v1,v2);
|
||||
puts("Search completed.\n");
|
||||
}
|
||||
|
||||
|
||||
static MENU NewCheatsMenu[]={
|
||||
{"Add Cheat",(void *)AddCheat,1},
|
||||
{"Reset Search",(void *)ResetSearch,1},
|
||||
{"Do Search",(void *)DoSearch,1},
|
||||
{"Set Original to Current",(void *)SetOC,1},
|
||||
{"Unhide Excluded",(void *)UnhideEx,1},
|
||||
{"Show Results",(void *)ShowRes,1},
|
||||
{"Add Game Genie Cheat",(void *)AddCheatGG,1},
|
||||
{"Add PAR Cheat",(void *)AddCheatPAR,1},
|
||||
{0}
|
||||
};
|
||||
|
||||
static MENU MainMenu[]={
|
||||
{"List Cheats",(void *)ListCheats,1},
|
||||
{"New Cheats...",(void *)NewCheatsMenu,0},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void DoMenu(MENU *men)
|
||||
{
|
||||
int x=0;
|
||||
|
||||
redisplay:
|
||||
x=0;
|
||||
puts("");
|
||||
while(men[x].text)
|
||||
{
|
||||
printf("%d) %s\n",x+1,men[x].text);
|
||||
x++;
|
||||
}
|
||||
puts("D) Display Menu\nX) Return to Previous\n");
|
||||
{
|
||||
char buf[32];
|
||||
int c;
|
||||
|
||||
recommand:
|
||||
printf("Command> ");
|
||||
fgets(buf,32,stdin);
|
||||
c=tolower(buf[0]);
|
||||
if(c=='\n')
|
||||
goto recommand;
|
||||
else if(c=='d')
|
||||
goto redisplay;
|
||||
else if(c=='x')
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if(sscanf(buf,"%d",&c))
|
||||
{
|
||||
if(c>x) goto invalid;
|
||||
if(men[c-1].type)
|
||||
{
|
||||
void (*func)(void)=(void(*)())men[c-1].action;
|
||||
func();
|
||||
}
|
||||
else
|
||||
DoMenu((MENU*)men[c-1].action); /* Mmm...recursivey goodness. */
|
||||
goto redisplay;
|
||||
}
|
||||
else
|
||||
{
|
||||
invalid:
|
||||
puts("Invalid command.\n");
|
||||
goto recommand;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void DoConsoleCheatConfig(void)
|
||||
{
|
||||
MENU *curmenu=MainMenu;
|
||||
|
||||
DoMenu(curmenu);
|
||||
}
|
21
source/drivers/common/cheat.h
Normal file
21
source/drivers/common/cheat.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
void DoConsoleCheatConfig(void);
|
152
source/drivers/common/config.c
Normal file
152
source/drivers/common/config.c
Normal file
@ -0,0 +1,152 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/****************************************************************/
|
||||
/* FCE Ultra */
|
||||
/* */
|
||||
/* This file contains routines for reading/writing the */
|
||||
/* configuration file. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../types.h"
|
||||
#include "config.h"
|
||||
|
||||
static int FReadString(FILE *fp, char *str, int n)
|
||||
{
|
||||
int x=0,z;
|
||||
for(;;)
|
||||
{
|
||||
z=fgetc(fp);
|
||||
str[x]=z;
|
||||
x++;
|
||||
if(z<=0) break;
|
||||
if(x>=n) return 0;
|
||||
}
|
||||
if(z<0) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void GetValueR(FILE *fp, char *str, void *v, int c)
|
||||
{
|
||||
char buf[256];
|
||||
int s;
|
||||
|
||||
while(FReadString(fp,buf,256))
|
||||
{
|
||||
fread(&s,1,4,fp);
|
||||
if(!strcmp(str, buf))
|
||||
{
|
||||
if(!c) // String, allocate some memory.
|
||||
{
|
||||
if(!(*(char **)v=(char*)malloc(s)))
|
||||
goto gogl;
|
||||
fread(*(char **)v,1,s,fp);
|
||||
continue;
|
||||
}
|
||||
else if(s>c || s<c)
|
||||
{
|
||||
gogl:
|
||||
fseek(fp,s,SEEK_CUR);
|
||||
continue;
|
||||
}
|
||||
fread((uint8*)v,1,c,fp);
|
||||
}
|
||||
else
|
||||
fseek(fp,s,SEEK_CUR);
|
||||
}
|
||||
fseek(fp,4,SEEK_SET);
|
||||
}
|
||||
|
||||
static void SetValueR(FILE *fp, char *str, void *v, int c)
|
||||
{
|
||||
fwrite(str,1,strlen(str)+1,fp);
|
||||
fwrite((uint8*)&c,1,4,fp);
|
||||
fwrite((uint8*)v,1,c,fp);
|
||||
}
|
||||
|
||||
static void SaveParse(CFGSTRUCT *cfgst, FILE *fp)
|
||||
{
|
||||
int x=0;
|
||||
|
||||
while(cfgst[x].ptr)
|
||||
{
|
||||
if(!cfgst[x].name) // Link to new config structure
|
||||
{
|
||||
SaveParse((CFGSTRUCT*)cfgst[x].ptr,fp); // Recursion is sexy. I could
|
||||
// save a little stack space if I made
|
||||
// the file pointer a non-local
|
||||
// variable...
|
||||
x++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(cfgst[x].len) // Plain data
|
||||
SetValueR(fp,cfgst[x].name,cfgst[x].ptr,cfgst[x].len);
|
||||
else // String
|
||||
if(*(char **)cfgst[x].ptr) // Only save it if there IS a string.
|
||||
SetValueR(fp,cfgst[x].name,*(char **)cfgst[x].ptr,
|
||||
strlen(*(char **)cfgst[x].ptr)+1);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
void SaveFCEUConfig(char *filename, CFGSTRUCT *cfgst)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp=fopen(filename,"wb");
|
||||
if(fp==NULL) return;
|
||||
|
||||
SaveParse(cfgst,fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static void LoadParse(CFGSTRUCT *cfgst, FILE *fp)
|
||||
{
|
||||
int x=0;
|
||||
|
||||
while(cfgst[x].ptr)
|
||||
{
|
||||
if(!cfgst[x].name) // Link to new config structure
|
||||
{
|
||||
LoadParse((CFGSTRUCT*)cfgst[x].ptr,fp);
|
||||
x++;
|
||||
continue;
|
||||
}
|
||||
GetValueR(fp,cfgst[x].name,cfgst[x].ptr,cfgst[x].len);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
void LoadFCEUConfig(char *filename, CFGSTRUCT *cfgst)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp=fopen(filename,"rb");
|
||||
if(fp==NULL) return;
|
||||
LoadParse(cfgst,fp);
|
||||
fclose(fp);
|
||||
}
|
40
source/drivers/common/config.h
Normal file
40
source/drivers/common/config.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef _DRIVERS_CONFIGH
|
||||
typedef struct {
|
||||
char *name;
|
||||
void *ptr;
|
||||
int len;
|
||||
} CFGSTRUCT;
|
||||
|
||||
void SaveFCEUConfig(char *filename, CFGSTRUCT *cfgst);
|
||||
void LoadFCEUConfig(char *filename, CFGSTRUCT *cfgst);
|
||||
|
||||
/* Macros for building CFGSTRUCT structures. */
|
||||
|
||||
/* CFGSTRUCT structures must always end with ENDCFGSTRUCT */
|
||||
#define ENDCFGSTRUCT { 0,0,0 }
|
||||
|
||||
/* When this macro is used, the config loading/saving code will parse
|
||||
the new config structure until the end of it is detected, then it
|
||||
will continue parsing the original config structure.
|
||||
*/
|
||||
#define ADDCFGSTRUCT(x) { 0,&x,0 }
|
||||
|
||||
/* Oops. The NAC* macros shouldn't have the # in front of the w, but
|
||||
fixing this would break configuration files of previous versions and it
|
||||
isn't really hurting much.
|
||||
*/
|
||||
|
||||
/* Single piece of data(integer). */
|
||||
#define AC(x) { #x,&x,sizeof(x)}
|
||||
#define NAC(w,x) { #w,&x,sizeof(x)}
|
||||
|
||||
/* Array. */
|
||||
#define ACA(x) {#x,x,sizeof(x)}
|
||||
#define NACA(w,x) {#w,x,sizeof(x)}
|
||||
|
||||
/* String(pointer) with automatic memory allocation. */
|
||||
#define ACS(x) {#x,&x,0}
|
||||
#define NACS(w,x) {#w,&x,0}
|
||||
|
||||
#define _DRIVERS_CONFIGH
|
||||
#endif
|
2991
source/drivers/common/hq2x.c
Normal file
2991
source/drivers/common/hq2x.c
Normal file
File diff suppressed because it is too large
Load Diff
4
source/drivers/common/hq2x.h
Normal file
4
source/drivers/common/hq2x.h
Normal file
@ -0,0 +1,4 @@
|
||||
void hq2x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL);
|
||||
int hq2x_InitLUTs(void);
|
||||
void hq2x_Kill(void);
|
||||
|
3865
source/drivers/common/hq3x.c
Normal file
3865
source/drivers/common/hq3x.c
Normal file
File diff suppressed because it is too large
Load Diff
4
source/drivers/common/hq3x.h
Normal file
4
source/drivers/common/hq3x.h
Normal file
@ -0,0 +1,4 @@
|
||||
void hq3x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL);
|
||||
int hq3x_InitLUTs(void);
|
||||
void hq3x_Kill(void);
|
||||
|
923
source/drivers/common/scale2x.c
Normal file
923
source/drivers/common/scale2x.c
Normal file
@ -0,0 +1,923 @@
|
||||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains a C and MMX implementation of the Scale2x effect.
|
||||
*
|
||||
* You can find an high level description of the effect at :
|
||||
*
|
||||
* http://scale2x.sourceforge.net/
|
||||
*
|
||||
* Alternatively at the previous license terms, you are allowed to use this
|
||||
* code in your program with these conditions:
|
||||
* - the program is not used in commercial activities.
|
||||
* - the whole source code of the program is released with the binary.
|
||||
* - derivative works of the program are allowed.
|
||||
*/
|
||||
|
||||
#include "scale2x.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/***************************************************************************/
|
||||
/* Scale2x C implementation */
|
||||
|
||||
static inline void scale2x_8_def_single(scale2x_uint8* __restrict__ dst, const scale2x_uint8* __restrict__ src0, const scale2x_uint8* __restrict__ src1, const scale2x_uint8* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[1] = src0[0];
|
||||
else
|
||||
dst[1] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
|
||||
dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale2x_16_def_single(scale2x_uint16* __restrict__ dst, const scale2x_uint16* __restrict__ src0, const scale2x_uint16* __restrict__ src1, const scale2x_uint16* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[1] = src0[0];
|
||||
else
|
||||
dst[1] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
|
||||
dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale2x_32_def_single(scale2x_uint32* __restrict__ dst, const scale2x_uint32* __restrict__ src0, const scale2x_uint32* __restrict__ src1, const scale2x_uint32* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[1] = src0[0];
|
||||
else
|
||||
dst[1] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
|
||||
dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 8 bits.
|
||||
* The function is implemented in C.
|
||||
* The pixels over the left and right borders are assumed of the same color of
|
||||
* the pixels on the border.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
scale2x_8_def_single(dst0, src0, src1, src2, count);
|
||||
scale2x_8_def_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 16 bits.
|
||||
* This function operates like scale2x_8_def() but for 16 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
scale2x_16_def_single(dst0, src0, src1, src2, count);
|
||||
scale2x_16_def_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 32 bits.
|
||||
* This function operates like scale2x_8_def() but for 32 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
scale2x_32_def_single(dst0, src0, src1, src2, count);
|
||||
scale2x_32_def_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* Scale2x MMX implementation */
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
|
||||
/*
|
||||
* Apply the Scale2x effect at a single row.
|
||||
* This function must be called only by the other scale2x functions.
|
||||
*
|
||||
* Considering the pixel map :
|
||||
*
|
||||
* ABC (src0)
|
||||
* DEF (src1)
|
||||
* GHI (src2)
|
||||
*
|
||||
* this functions compute 2 new pixels in substitution of the source pixel E
|
||||
* like this map :
|
||||
*
|
||||
* ab (dst)
|
||||
*
|
||||
* with these variables :
|
||||
*
|
||||
* ¤t -> E
|
||||
* ¤t_left -> D
|
||||
* ¤t_right -> F
|
||||
* ¤t_upper -> B
|
||||
* ¤t_lower -> H
|
||||
*
|
||||
* %0 -> current_upper
|
||||
* %1 -> current
|
||||
* %2 -> current_lower
|
||||
* %3 -> dst
|
||||
* %4 -> counter
|
||||
*
|
||||
* %mm0 -> *current_left
|
||||
* %mm1 -> *current_next
|
||||
* %mm2 -> tmp0
|
||||
* %mm3 -> tmp1
|
||||
* %mm4 -> tmp2
|
||||
* %mm5 -> tmp3
|
||||
* %mm6 -> *current_upper
|
||||
* %mm7 -> *current
|
||||
*/
|
||||
static inline void scale2x_8_mmx_single(scale2x_uint8* dst, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 16);
|
||||
assert(count % 8 == 0);
|
||||
|
||||
/* always do the first and last run */
|
||||
count -= 2*8;
|
||||
|
||||
__asm__ __volatile__(
|
||||
/* first run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq 0(%1), %%mm0\n"
|
||||
"movq 0(%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psllq $56, %%mm0\n"
|
||||
"psllq $56, %%mm1\n"
|
||||
"psrlq $56, %%mm0\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $8, %%mm2\n"
|
||||
"psrlq $8, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqb %%mm6, %%mm2\n"
|
||||
"pcmpeqb %%mm6, %%mm4\n"
|
||||
"pcmpeqb (%2), %%mm3\n"
|
||||
"pcmpeqb (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqb %%mm1, %%mm2\n"
|
||||
"pcmpeqb %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklbw %%mm4, %%mm2\n"
|
||||
"punpckhbw %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
/* central runs */
|
||||
"shrl $3, %4\n"
|
||||
"jz 1f\n"
|
||||
|
||||
"0:\n"
|
||||
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psrlq $56, %%mm0\n"
|
||||
"psllq $56, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $8, %%mm2\n"
|
||||
"psrlq $8, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqb %%mm6, %%mm2\n"
|
||||
"pcmpeqb %%mm6, %%mm4\n"
|
||||
"pcmpeqb (%2), %%mm3\n"
|
||||
"pcmpeqb (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqb %%mm1, %%mm2\n"
|
||||
"pcmpeqb %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklbw %%mm4, %%mm2\n"
|
||||
"punpckhbw %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
"decl %4\n"
|
||||
"jnz 0b\n"
|
||||
"1:\n"
|
||||
|
||||
/* final run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq (%1), %%mm1\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"psrlq $56, %%mm1\n"
|
||||
"psrlq $56, %%mm0\n"
|
||||
"psllq $56, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $8, %%mm2\n"
|
||||
"psrlq $8, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqb %%mm6, %%mm2\n"
|
||||
"pcmpeqb %%mm6, %%mm4\n"
|
||||
"pcmpeqb (%2), %%mm3\n"
|
||||
"pcmpeqb (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqb %%mm1, %%mm2\n"
|
||||
"pcmpeqb %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklbw %%mm4, %%mm2\n"
|
||||
"punpckhbw %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
: "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
|
||||
:
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
||||
static inline void scale2x_16_mmx_single(scale2x_uint16* dst, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 8);
|
||||
assert(count % 4 == 0);
|
||||
|
||||
/* always do the first and last run */
|
||||
count -= 2*4;
|
||||
|
||||
__asm__ __volatile__(
|
||||
/* first run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq 0(%1), %%mm0\n"
|
||||
"movq 0(%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psllq $48, %%mm0\n"
|
||||
"psllq $48, %%mm1\n"
|
||||
"psrlq $48, %%mm0\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $16, %%mm2\n"
|
||||
"psrlq $16, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqw %%mm6, %%mm2\n"
|
||||
"pcmpeqw %%mm6, %%mm4\n"
|
||||
"pcmpeqw (%2), %%mm3\n"
|
||||
"pcmpeqw (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqw %%mm1, %%mm2\n"
|
||||
"pcmpeqw %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklwd %%mm4, %%mm2\n"
|
||||
"punpckhwd %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
/* central runs */
|
||||
"shrl $2, %4\n"
|
||||
"jz 1f\n"
|
||||
|
||||
"0:\n"
|
||||
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psrlq $48, %%mm0\n"
|
||||
"psllq $48, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $16, %%mm2\n"
|
||||
"psrlq $16, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqw %%mm6, %%mm2\n"
|
||||
"pcmpeqw %%mm6, %%mm4\n"
|
||||
"pcmpeqw (%2), %%mm3\n"
|
||||
"pcmpeqw (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqw %%mm1, %%mm2\n"
|
||||
"pcmpeqw %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklwd %%mm4, %%mm2\n"
|
||||
"punpckhwd %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
"decl %4\n"
|
||||
"jnz 0b\n"
|
||||
"1:\n"
|
||||
|
||||
/* final run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq (%1), %%mm1\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"psrlq $48, %%mm1\n"
|
||||
"psrlq $48, %%mm0\n"
|
||||
"psllq $48, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $16, %%mm2\n"
|
||||
"psrlq $16, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqw %%mm6, %%mm2\n"
|
||||
"pcmpeqw %%mm6, %%mm4\n"
|
||||
"pcmpeqw (%2), %%mm3\n"
|
||||
"pcmpeqw (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqw %%mm1, %%mm2\n"
|
||||
"pcmpeqw %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklwd %%mm4, %%mm2\n"
|
||||
"punpckhwd %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
: "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
|
||||
:
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
||||
static inline void scale2x_32_mmx_single(scale2x_uint32* dst, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 4);
|
||||
assert(count % 2 == 0);
|
||||
|
||||
/* always do the first and last run */
|
||||
count -= 2*2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
/* first run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq 0(%1), %%mm0\n"
|
||||
"movq 0(%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psllq $32, %%mm0\n"
|
||||
"psllq $32, %%mm1\n"
|
||||
"psrlq $32, %%mm0\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $32, %%mm2\n"
|
||||
"psrlq $32, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqd %%mm6, %%mm2\n"
|
||||
"pcmpeqd %%mm6, %%mm4\n"
|
||||
"pcmpeqd (%2), %%mm3\n"
|
||||
"pcmpeqd (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqd %%mm1, %%mm2\n"
|
||||
"pcmpeqd %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpckldq %%mm4, %%mm2\n"
|
||||
"punpckhdq %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
/* central runs */
|
||||
"shrl $1, %4\n"
|
||||
"jz 1f\n"
|
||||
|
||||
"0:\n"
|
||||
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psrlq $32, %%mm0\n"
|
||||
"psllq $32, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $32, %%mm2\n"
|
||||
"psrlq $32, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqd %%mm6, %%mm2\n"
|
||||
"pcmpeqd %%mm6, %%mm4\n"
|
||||
"pcmpeqd (%2), %%mm3\n"
|
||||
"pcmpeqd (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqd %%mm1, %%mm2\n"
|
||||
"pcmpeqd %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpckldq %%mm4, %%mm2\n"
|
||||
"punpckhdq %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
"decl %4\n"
|
||||
"jnz 0b\n"
|
||||
"1:\n"
|
||||
|
||||
/* final run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq (%1), %%mm1\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"psrlq $32, %%mm1\n"
|
||||
"psrlq $32, %%mm0\n"
|
||||
"psllq $32, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $32, %%mm2\n"
|
||||
"psrlq $32, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqd %%mm6, %%mm2\n"
|
||||
"pcmpeqd %%mm6, %%mm4\n"
|
||||
"pcmpeqd (%2), %%mm3\n"
|
||||
"pcmpeqd (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqd %%mm1, %%mm2\n"
|
||||
"pcmpeqd %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpckldq %%mm4, %%mm2\n"
|
||||
"punpckhdq %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
: "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
|
||||
:
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 8 bits.
|
||||
* This is a very fast MMX implementation.
|
||||
* The implementation uses a combination of cmp/and/not operations to
|
||||
* completly remove the need of conditional jumps. This trick give the
|
||||
* major speed improvement.
|
||||
* Also, using the 8 bytes MMX registers more than one pixel are computed
|
||||
* at the same time.
|
||||
* Before calling this function you must ensure that the currenct CPU supports
|
||||
* the MMX instruction set. After calling it you must be sure to call the EMMS
|
||||
* instruction before any floating-point operation.
|
||||
* The pixels over the left and right borders are assumed of the same color of
|
||||
* the pixels on the border.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows. It must
|
||||
* be at least 16 and a multiple of 8.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)
|
||||
{
|
||||
if (count % 8 != 0 || count < 16) {
|
||||
scale2x_8_def(dst0, dst1, src0, src1, src2, count);
|
||||
} else {
|
||||
assert(count >= 16);
|
||||
assert(count % 8 == 0);
|
||||
|
||||
scale2x_8_mmx_single(dst0, src0, src1, src2, count);
|
||||
scale2x_8_mmx_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 16 bits.
|
||||
* This function operates like scale2x_8_mmx() but for 16 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows. It must
|
||||
* be at least 8 and a multiple of 4.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)
|
||||
{
|
||||
if (count % 4 != 0 || count < 8) {
|
||||
scale2x_16_def(dst0, dst1, src0, src1, src2, count);
|
||||
} else {
|
||||
assert(count >= 8);
|
||||
assert(count % 4 == 0);
|
||||
|
||||
scale2x_16_mmx_single(dst0, src0, src1, src2, count);
|
||||
scale2x_16_mmx_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 32 bits.
|
||||
* This function operates like scale2x_8_mmx() but for 32 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows. It must
|
||||
* be at least 4 and a multiple of 2.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)
|
||||
{
|
||||
if (count % 2 != 0 || count < 4) {
|
||||
scale2x_32_def(dst0, dst1, src0, src1, src2, count);
|
||||
} else {
|
||||
assert(count >= 4);
|
||||
assert(count % 2 == 0);
|
||||
|
||||
scale2x_32_mmx_single(dst0, src0, src1, src2, count);
|
||||
scale2x_32_mmx_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
52
source/drivers/common/scale2x.h
Normal file
52
source/drivers/common/scale2x.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SCALE2X_H
|
||||
#define __SCALE2X_H
|
||||
|
||||
typedef unsigned char scale2x_uint8;
|
||||
typedef unsigned short scale2x_uint16;
|
||||
typedef unsigned scale2x_uint32;
|
||||
|
||||
void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count);
|
||||
void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count);
|
||||
void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count);
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
|
||||
void scale2x_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count);
|
||||
void scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count);
|
||||
void scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count);
|
||||
|
||||
/**
|
||||
* End the use of the MMX instructions.
|
||||
* This function must be called before using any floating-point operations.
|
||||
*/
|
||||
static inline void scale2x_mmx_emms(void)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
"emms"
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
382
source/drivers/common/scale3x.c
Normal file
382
source/drivers/common/scale3x.c
Normal file
@ -0,0 +1,382 @@
|
||||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains a C and MMX implementation of the Scale2x effect.
|
||||
*
|
||||
* You can find an high level description of the effect at :
|
||||
*
|
||||
* http://scale2x.sourceforge.net/
|
||||
*
|
||||
* Alternatively at the previous license terms, you are allowed to use this
|
||||
* code in your program with these conditions:
|
||||
* - the program is not used in commercial activities.
|
||||
* - the whole source code of the program is released with the binary.
|
||||
* - derivative works of the program are allowed.
|
||||
*/
|
||||
|
||||
#include "scale3x.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/***************************************************************************/
|
||||
/* Scale3x C implementation */
|
||||
|
||||
static inline void scale3x_8_def_border(scale3x_uint8* __restrict__ dst, const scale3x_uint8* __restrict__ src0, const scale3x_uint8* __restrict__ src1, const scale3x_uint8* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[2] = src0[0];
|
||||
else
|
||||
dst[2] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
|
||||
dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
|
||||
dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale3x_8_def_center(scale3x_uint8* __restrict__ dst, const scale3x_uint8* __restrict__ src0, const scale3x_uint8* __restrict__ src1, const scale3x_uint8* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
}
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale3x_16_def_border(scale3x_uint16* __restrict__ dst, const scale3x_uint16* __restrict__ src0, const scale3x_uint16* __restrict__ src1, const scale3x_uint16* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[2] = src0[0];
|
||||
else
|
||||
dst[2] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
|
||||
dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
|
||||
dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale3x_16_def_center(scale3x_uint16* __restrict__ dst, const scale3x_uint16* __restrict__ src0, const scale3x_uint16* __restrict__ src1, const scale3x_uint16* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
}
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale3x_32_def_border(scale3x_uint32* __restrict__ dst, const scale3x_uint32* __restrict__ src0, const scale3x_uint32* __restrict__ src1, const scale3x_uint32* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[2] = src0[0];
|
||||
else
|
||||
dst[2] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
|
||||
dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
|
||||
dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale3x_32_def_center(scale3x_uint32* __restrict__ dst, const scale3x_uint32* __restrict__ src0, const scale3x_uint32* __restrict__ src1, const scale3x_uint32* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
}
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 3 a row of pixels of 8 bits.
|
||||
* The function is implemented in C.
|
||||
* The pixels over the left and right borders are assumed of the same color of
|
||||
* the pixels on the border.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, triple length in pixels.
|
||||
* \param dst1 Second destination row, triple length in pixels.
|
||||
* \param dst2 Third destination row, triple length in pixels.
|
||||
*/
|
||||
void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
scale3x_8_def_border(dst0, src0, src1, src2, count);
|
||||
scale3x_8_def_center(dst1, src0, src1, src2, count);
|
||||
scale3x_8_def_border(dst2, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 3 a row of pixels of 16 bits.
|
||||
* This function operates like scale3x_8_def() but for 16 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, triple length in pixels.
|
||||
* \param dst1 Second destination row, triple length in pixels.
|
||||
* \param dst2 Third destination row, triple length in pixels.
|
||||
*/
|
||||
void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
scale3x_16_def_border(dst0, src0, src1, src2, count);
|
||||
scale3x_16_def_center(dst1, src0, src1, src2, count);
|
||||
scale3x_16_def_border(dst2, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 3 a row of pixels of 32 bits.
|
||||
* This function operates like scale3x_8_def() but for 32 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, triple length in pixels.
|
||||
* \param dst1 Second destination row, triple length in pixels.
|
||||
* \param dst2 Third destination row, triple length in pixels.
|
||||
*/
|
||||
void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
scale3x_32_def_border(dst0, src0, src1, src2, count);
|
||||
scale3x_32_def_center(dst1, src0, src1, src2, count);
|
||||
scale3x_32_def_border(dst2, src2, src1, src0, count);
|
||||
}
|
||||
|
33
source/drivers/common/scale3x.h
Normal file
33
source/drivers/common/scale3x.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SCALE3X_H
|
||||
#define __SCALE3X_H
|
||||
|
||||
typedef unsigned char scale3x_uint8;
|
||||
typedef unsigned short scale3x_uint16;
|
||||
typedef unsigned scale3x_uint32;
|
||||
|
||||
void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count);
|
||||
void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count);
|
||||
void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count);
|
||||
|
||||
#endif
|
||||
|
385
source/drivers/common/scalebit.c
Normal file
385
source/drivers/common/scalebit.c
Normal file
@ -0,0 +1,385 @@
|
||||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2003 Andrea Mazzoleni
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains an example implementation of the Scale effect
|
||||
* applyed to a generic bitmap.
|
||||
*
|
||||
* You can find an high level description of the effect at :
|
||||
*
|
||||
* http://scale2x.sourceforge.net/
|
||||
*
|
||||
* Alternatively at the previous license terms, you are allowed to use this
|
||||
* code in your program with these conditions:
|
||||
* - the program is not used in commercial activities.
|
||||
* - the whole source code of the program is released with the binary.
|
||||
* - derivative works of the program are allowed.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "scale2x.h"
|
||||
#include "scale3x.h"
|
||||
|
||||
#if HAVE_ALLOCA_H
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* Apply the Scale2x effect on a group of rows. Used internally.
|
||||
*/
|
||||
static inline void stage_scale2x(void* dst0, void* dst1, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)
|
||||
{
|
||||
switch (pixel) {
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
case 1 : scale2x_8_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
case 2 : scale2x_16_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
case 4 : scale2x_32_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
#else
|
||||
case 1 : scale2x_8_def(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
case 2 : scale2x_16_def(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
case 4 : scale2x_32_def(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale3x effect on a group of rows. Used internally.
|
||||
*/
|
||||
static inline void stage_scale3x(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)
|
||||
{
|
||||
switch (pixel) {
|
||||
case 1 : scale3x_8_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break;
|
||||
case 2 : scale3x_16_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break;
|
||||
case 4 : scale3x_32_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale4x effect on a group of rows. Used internally.
|
||||
*/
|
||||
static inline void stage_scale4x(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, const void* src2, const void* src3, unsigned pixel, unsigned pixel_per_row)
|
||||
{
|
||||
stage_scale2x(dst0, dst1, src0, src1, src2, pixel, 2 * pixel_per_row);
|
||||
stage_scale2x(dst2, dst3, src1, src2, src3, pixel, 2 * pixel_per_row);
|
||||
}
|
||||
|
||||
#define SCDST(i) (dst+(i)*dst_slice)
|
||||
#define SCSRC(i) (src+(i)*src_slice)
|
||||
#define SCMID(i) (mid[(i)])
|
||||
|
||||
/**
|
||||
* Apply the Scale2x effect on a bitmap.
|
||||
* The destination bitmap is filled with the scaled version of the source bitmap.
|
||||
* The source bitmap isn't modified.
|
||||
* The destination bitmap must be manually allocated before calling the function,
|
||||
* note that the resulting size is exactly 2x2 times the size of the source bitmap.
|
||||
* \param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* \param dst_slice Size in bytes of a destination bitmap row.
|
||||
* \param void_src Pointer at the first pixel of the source bitmap.
|
||||
* \param src_slice Size in bytes of a source bitmap row.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
static void scale2x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
|
||||
{
|
||||
unsigned char* dst = (unsigned char*)void_dst;
|
||||
const unsigned char* src = (unsigned char*)void_src;
|
||||
unsigned count;
|
||||
|
||||
assert(height >= 2);
|
||||
|
||||
count = height;
|
||||
|
||||
stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
|
||||
|
||||
dst = SCDST(2);
|
||||
|
||||
count -= 2;
|
||||
while (count) {
|
||||
stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
|
||||
|
||||
dst = SCDST(2);
|
||||
src = SCSRC(1);
|
||||
|
||||
--count;
|
||||
}
|
||||
|
||||
stage_scale2x(SCDST(0), SCDST(1), SCSRC(1-1), SCSRC(2-1), SCSRC(2-1), pixel, width);
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
scale2x_mmx_emms();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale32x effect on a bitmap.
|
||||
* The destination bitmap is filled with the scaled version of the source bitmap.
|
||||
* The source bitmap isn't modified.
|
||||
* The destination bitmap must be manually allocated before calling the function,
|
||||
* note that the resulting size is exactly 3x3 times the size of the source bitmap.
|
||||
* \param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* \param dst_slice Size in bytes of a destination bitmap row.
|
||||
* \param void_src Pointer at the first pixel of the source bitmap.
|
||||
* \param src_slice Size in bytes of a source bitmap row.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
static void scale3x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
|
||||
{
|
||||
unsigned char* dst = (unsigned char*)void_dst;
|
||||
const unsigned char* src = (unsigned char*)void_src;
|
||||
unsigned count;
|
||||
|
||||
assert(height >= 2);
|
||||
|
||||
count = height;
|
||||
|
||||
stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
|
||||
|
||||
dst = SCDST(3);
|
||||
|
||||
count -= 2;
|
||||
while (count) {
|
||||
stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
|
||||
|
||||
dst = SCDST(3);
|
||||
src = SCSRC(1);
|
||||
|
||||
--count;
|
||||
}
|
||||
|
||||
stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(1-1), SCSRC(2-1), SCSRC(2-1), pixel, width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale4x effect on a bitmap.
|
||||
* The destination bitmap is filled with the scaled version of the source bitmap.
|
||||
* The source bitmap isn't modified.
|
||||
* The destination bitmap must be manually allocated before calling the function,
|
||||
* note that the resulting size is exactly 4x4 times the size of the source bitmap.
|
||||
* \note This function requires also a small buffer bitmap used internally to store
|
||||
* intermediate results. This bitmap must have at least an horizontal size in bytes of 2*width*pixel,
|
||||
* and a vertical size of 6 rows. The memory of this buffer must not be allocated
|
||||
* in video memory because it's also read and not only written. Generally
|
||||
* a heap (malloc) or a stack (alloca) buffer is the best choices.
|
||||
* \param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* \param dst_slice Size in bytes of a destination bitmap row.
|
||||
* \param void_mid Pointer at the first pixel of the buffer bitmap.
|
||||
* \param mid_slice Size in bytes of a buffer bitmap row.
|
||||
* \param void_src Pointer at the first pixel of the source bitmap.
|
||||
* \param src_slice Size in bytes of a source bitmap row.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
static void scale4x_buf(void* void_dst, unsigned dst_slice, void* void_mid, unsigned mid_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
|
||||
{
|
||||
unsigned char* dst = (unsigned char*)void_dst;
|
||||
const unsigned char* src = (unsigned char*)void_src;
|
||||
unsigned count;
|
||||
unsigned char* mid[6];
|
||||
|
||||
assert(height >= 4);
|
||||
|
||||
count = height;
|
||||
|
||||
/* set the 6 buffer pointers */
|
||||
mid[0] = (unsigned char*)void_mid;
|
||||
mid[1] = mid[0] + mid_slice;
|
||||
mid[2] = mid[1] + mid_slice;
|
||||
mid[3] = mid[2] + mid_slice;
|
||||
mid[4] = mid[3] + mid_slice;
|
||||
mid[5] = mid[4] + mid_slice;
|
||||
|
||||
stage_scale2x(SCMID(-2+6), SCMID(-1+6), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
|
||||
stage_scale2x(SCMID(0), SCMID(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
|
||||
stage_scale2x(SCMID(2), SCMID(3), SCSRC(1), SCSRC(2), SCSRC(3), pixel, width);
|
||||
stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-2+6), SCMID(-2+6), SCMID(-1+6), SCMID(0), pixel, width);
|
||||
|
||||
dst = SCDST(4);
|
||||
|
||||
stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-1+6), SCMID(0), SCMID(1), SCMID(2), pixel, width);
|
||||
|
||||
dst = SCDST(4);
|
||||
|
||||
count -= 4;
|
||||
while (count) {
|
||||
unsigned char* tmp;
|
||||
|
||||
stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(4), pixel, width);
|
||||
stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width);
|
||||
|
||||
dst = SCDST(4);
|
||||
src = SCSRC(1);
|
||||
|
||||
tmp = SCMID(0); /* shift by 2 position */
|
||||
SCMID(0) = SCMID(2);
|
||||
SCMID(2) = SCMID(4);
|
||||
SCMID(4) = tmp;
|
||||
tmp = SCMID(1);
|
||||
SCMID(1) = SCMID(3);
|
||||
SCMID(3) = SCMID(5);
|
||||
SCMID(5) = tmp;
|
||||
|
||||
--count;
|
||||
}
|
||||
|
||||
stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(3), pixel, width);
|
||||
stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width);
|
||||
|
||||
dst = SCDST(4);
|
||||
|
||||
stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(3), SCMID(4), SCMID(5), SCMID(5), pixel, width);
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
scale2x_mmx_emms();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale4x effect on a bitmap.
|
||||
* The destination bitmap is filled with the scaled version of the source bitmap.
|
||||
* The source bitmap isn't modified.
|
||||
* The destination bitmap must be manually allocated before calling the function,
|
||||
* note that the resulting size is exactly 4x4 times the size of the source bitmap.
|
||||
* \note This function operates like ::scale4x_buf() but the intermediate buffer is
|
||||
* automatically allocated in the stack.
|
||||
* \param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* \param dst_slice Size in bytes of a destination bitmap row.
|
||||
* \param void_src Pointer at the first pixel of the source bitmap.
|
||||
* \param src_slice Size in bytes of a source bitmap row.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
static void scale4x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
|
||||
{
|
||||
unsigned mid_slice;
|
||||
void* mid;
|
||||
|
||||
mid_slice = 2 * pixel * width; /* required space for 1 row buffer */
|
||||
|
||||
mid_slice = (mid_slice + 0x7) & ~0x7; /* align to 8 bytes */
|
||||
|
||||
#if HAVE_ALLOCA
|
||||
mid = alloca(6 * mid_slice); /* allocate space for 6 row buffers */
|
||||
|
||||
assert(mid != 0); /* alloca should never fails */
|
||||
#else
|
||||
mid = malloc(6 * mid_slice); /* allocate space for 6 row buffers */
|
||||
|
||||
if (!mid)
|
||||
return;
|
||||
#endif
|
||||
|
||||
scale4x_buf(void_dst, dst_slice, mid, mid_slice, void_src, src_slice, pixel, width, height);
|
||||
|
||||
#if !HAVE_ALLOCA
|
||||
free(mid);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the scale implementation is applicable at the given arguments.
|
||||
* \param scale Scale factor. 2, 3 or 4.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
* \return
|
||||
* - -1 on precondition violated.
|
||||
* - 0 on success.
|
||||
*/
|
||||
int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height)
|
||||
{
|
||||
if (scale != 2 && scale != 3 && scale != 4)
|
||||
return -1;
|
||||
|
||||
if (pixel != 1 && pixel != 2 && pixel != 4)
|
||||
return -1;
|
||||
|
||||
switch (scale) {
|
||||
case 2 :
|
||||
case 3 :
|
||||
if (height < 2)
|
||||
return -1;
|
||||
break;
|
||||
case 4 :
|
||||
if (height < 4)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
switch (scale) {
|
||||
case 2 :
|
||||
case 4 :
|
||||
if (width < (16 / pixel))
|
||||
return -1;
|
||||
if (width % (8 / pixel) != 0)
|
||||
return -1;
|
||||
break;
|
||||
case 3 :
|
||||
if (width < 2)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
if (width < 2)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale effect on a bitmap.
|
||||
* This function is simply a common interface for ::scale2x(), ::scale3x() and ::scale4x().
|
||||
* \param scale Scale factor. 2, 3 or 4.
|
||||
* \param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* \param dst_slice Size in bytes of a destination bitmap row.
|
||||
* \param void_src Pointer at the first pixel of the source bitmap.
|
||||
* \param src_slice Size in bytes of a source bitmap row.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
|
||||
{
|
||||
switch (scale) {
|
||||
case 2 :
|
||||
scale2x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
|
||||
break;
|
||||
case 3 :
|
||||
scale3x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
|
||||
break;
|
||||
case 4 :
|
||||
scale4x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
43
source/drivers/common/scalebit.h
Normal file
43
source/drivers/common/scalebit.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2003 Andrea Mazzoleni
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains an example implementation of the Scale effect
|
||||
* applyed to a generic bitmap.
|
||||
*
|
||||
* You can find an high level description of the effect at :
|
||||
*
|
||||
* http://scale2x.sourceforge.net/
|
||||
*
|
||||
* Alternatively at the previous license terms, you are allowed to use this
|
||||
* code in your program with these conditions:
|
||||
* - the program is not used in commercial activities.
|
||||
* - the whole source code of the program is released with the binary.
|
||||
* - derivative works of the program are allowed.
|
||||
*/
|
||||
|
||||
#ifndef __SCALEBIT_H
|
||||
#define __SCALEBIT_H
|
||||
|
||||
int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height);
|
||||
void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height);
|
||||
|
||||
#endif
|
||||
|
843
source/drivers/common/vidblit.c
Normal file
843
source/drivers/common/vidblit.c
Normal file
@ -0,0 +1,843 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include "scalebit.h"
|
||||
#include "hq2x.h"
|
||||
#include "hq3x.h"
|
||||
|
||||
#include "../../types.h"
|
||||
|
||||
static uint32 CBM[3];
|
||||
static uint32 *palettetranslate=0;
|
||||
|
||||
static uint16 *specbuf=NULL; // 8bpp -> 16bpp, pre hq2x/hq3x
|
||||
static uint32 *specbuf32bpp = NULL; // Buffer to hold output
|
||||
// of hq2x/hq3x when converting
|
||||
// to 16bpp and 24bpp
|
||||
static int backBpp, backshiftr[3], backshiftl[3];
|
||||
//static uint32 backmask[3];
|
||||
|
||||
static uint8 *specbuf8bpp = NULL; // For 2xscale, 3xscale.
|
||||
|
||||
|
||||
static int silt;
|
||||
|
||||
static int Bpp; // BYTES per pixel
|
||||
static int highefx;
|
||||
|
||||
#define BLUR_RED 20
|
||||
#define BLUR_GREEN 20
|
||||
#define BLUR_BLUE 10
|
||||
|
||||
#define FVB_SCANLINES 1
|
||||
|
||||
/* The blur effect is only available for bpp>=16. It could be easily modified
|
||||
to look like what happens on the real NES and TV, but lack of decent
|
||||
synchronization to the vertical retrace period makes it look rather
|
||||
blah.
|
||||
*/
|
||||
#define FVB_BLUR 2
|
||||
|
||||
static void CalculateShift(uint32 *CBM, int *cshiftr, int *cshiftl)
|
||||
{
|
||||
int a,x,z,y;
|
||||
cshiftl[0]=cshiftl[1]=cshiftl[2]=-1;
|
||||
for(a=0;a<3;a++)
|
||||
{
|
||||
for(x=0,y=-1,z=0;x<32;x++)
|
||||
{
|
||||
if(CBM[a]&(1<<x))
|
||||
{
|
||||
if(cshiftl[a]==-1) cshiftl[a]=x;
|
||||
z++;
|
||||
}
|
||||
}
|
||||
cshiftr[a]=(8-z);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int efx, int specfilt)
|
||||
{
|
||||
if(specfilt == 2 || specfilt == 4) // scale2x and scale3x
|
||||
{
|
||||
int multi;
|
||||
|
||||
if(specfilt == 2) multi = 2 * 2;
|
||||
else if(specfilt == 4) multi = 3 * 3;
|
||||
|
||||
specbuf8bpp = malloc(256*240*multi);
|
||||
|
||||
}
|
||||
else if(specfilt == 1 || specfilt == 3) // hq2x and hq3x
|
||||
{
|
||||
if(b == 1)
|
||||
return(0);
|
||||
|
||||
if(b == 2 || b == 3) // 8->16->(hq2x)->32-> 24 or 16. YARGH.
|
||||
{
|
||||
uint32 tmpCBM[3];
|
||||
backBpp = b;
|
||||
tmpCBM[0]=rmask;
|
||||
tmpCBM[1]=gmask;
|
||||
tmpCBM[2]=bmask;
|
||||
|
||||
CalculateShift(tmpCBM, backshiftr, backshiftl);
|
||||
|
||||
if(b == 2)
|
||||
{
|
||||
// ark
|
||||
backshiftr[0] += 16;
|
||||
backshiftr[1] += 8;
|
||||
backshiftr[2] += 0;
|
||||
|
||||
// Begin iffy code(requires 16bpp and 32bpp to have same RGB order)
|
||||
//backmask[0] = (rmask>>backshiftl[0]) << (backshiftr[0]);
|
||||
//backmask[1] = (gmask>>backshiftl[1]) << (backshiftr[1]);
|
||||
//backmask[2] = (bmask>>backshiftl[2]) << (backshiftr[2]);
|
||||
|
||||
//int x;
|
||||
//for(x=0;x<3;x++)
|
||||
// backshiftr[x] -= backshiftl[x];
|
||||
// End iffy code
|
||||
}
|
||||
if(specfilt == 1) specbuf32bpp = malloc(256*240*4*sizeof(uint32));
|
||||
else if(specfilt == 3) specbuf32bpp = malloc(256*240*9*sizeof(uint32));
|
||||
}
|
||||
|
||||
efx=0;
|
||||
b=2;
|
||||
rmask=0x1F<<11;
|
||||
gmask=0x3F<<5;
|
||||
bmask=0x1F;
|
||||
|
||||
if(specfilt == 3)
|
||||
hq3x_InitLUTs();
|
||||
else
|
||||
hq2x_InitLUTs();
|
||||
|
||||
specbuf=malloc(256*240*sizeof(uint16));
|
||||
}
|
||||
|
||||
silt = specfilt;
|
||||
|
||||
Bpp=b;
|
||||
|
||||
highefx=efx;
|
||||
|
||||
if(Bpp<=1 || Bpp>4)
|
||||
return(0);
|
||||
|
||||
if(efx&FVB_BLUR)
|
||||
{
|
||||
if(Bpp==2)
|
||||
palettetranslate=(uint32 *)malloc(65536*4);
|
||||
else if(Bpp>=3)
|
||||
palettetranslate=(uint32 *)malloc(65536*4);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(Bpp==2)
|
||||
palettetranslate=(uint32*)malloc(65536*4);
|
||||
else if(Bpp>=3)
|
||||
palettetranslate=(uint32*)malloc(256*4);
|
||||
}
|
||||
|
||||
if(!palettetranslate)
|
||||
return(0);
|
||||
|
||||
|
||||
CBM[0]=rmask;
|
||||
CBM[1]=gmask;
|
||||
CBM[2]=bmask;
|
||||
return(1);
|
||||
}
|
||||
|
||||
void KillBlitToHigh(void)
|
||||
{
|
||||
if(palettetranslate)
|
||||
{
|
||||
free(palettetranslate);
|
||||
palettetranslate=NULL;
|
||||
}
|
||||
|
||||
if(specbuf8bpp)
|
||||
{
|
||||
free(specbuf8bpp);
|
||||
specbuf8bpp = NULL;
|
||||
}
|
||||
if(specbuf32bpp)
|
||||
{
|
||||
free(specbuf32bpp);
|
||||
specbuf32bpp = NULL;
|
||||
}
|
||||
if(specbuf)
|
||||
{
|
||||
if(silt == 3)
|
||||
hq3x_Kill();
|
||||
else
|
||||
hq2x_Kill();
|
||||
specbuf=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SetPaletteBlitToHigh(uint8 *src)
|
||||
{
|
||||
int cshiftr[3];
|
||||
int cshiftl[3];
|
||||
int x,y;
|
||||
|
||||
CalculateShift(CBM, cshiftr, cshiftl);
|
||||
|
||||
switch(Bpp)
|
||||
{
|
||||
case 2:
|
||||
if(highefx&FVB_BLUR)
|
||||
{
|
||||
for(x=0;x<256;x++)
|
||||
{
|
||||
uint32 r,g,b;
|
||||
for(y=0;y<256;y++)
|
||||
{
|
||||
r=src[x<<2]*(100-BLUR_RED);
|
||||
g=src[(x<<2)+1]*(100-BLUR_GREEN);
|
||||
b=src[(x<<2)+2]*(100-BLUR_BLUE);
|
||||
|
||||
r+=src[y<<2]*BLUR_RED;
|
||||
g+=src[(y<<2)+1]*BLUR_GREEN;
|
||||
b+=src[(y<<2)+2]*BLUR_BLUE;
|
||||
r/=100;
|
||||
g/=100;
|
||||
b/=100;
|
||||
|
||||
if(r>255) r=255; if(g>255) g=255; if(b>255) b=255;
|
||||
palettetranslate[x|(y<<8)]=((r>>cshiftr[0])<<cshiftl[0])|
|
||||
((g>>cshiftr[1])<<cshiftl[1])|
|
||||
((b>>cshiftr[2])<<cshiftl[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
for(x=0;x<65536;x++)
|
||||
{
|
||||
uint16 lower,upper;
|
||||
|
||||
lower=(src[((x&255)<<2)]>>cshiftr[0])<<cshiftl[0];
|
||||
lower|=(src[((x&255)<<2)+1]>>cshiftr[1])<<cshiftl[1];
|
||||
lower|=(src[((x&255)<<2)+2]>>cshiftr[2])<<cshiftl[2];
|
||||
upper=(src[((x>>8)<<2)]>>cshiftr[0])<<cshiftl[0];
|
||||
upper|=(src[((x>>8)<<2)+1]>>cshiftr[1])<<cshiftl[1];
|
||||
upper|=(src[((x>>8)<<2)+2]>>cshiftr[2])<<cshiftl[2];
|
||||
|
||||
palettetranslate[x]=lower|(upper<<16);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
for(x=0;x<256;x++)
|
||||
{
|
||||
uint32 r,g,b;
|
||||
|
||||
if(!(highefx&FVB_BLUR))
|
||||
{
|
||||
r=src[x<<2];
|
||||
g=src[(x<<2)+1];
|
||||
b=src[(x<<2)+2];
|
||||
palettetranslate[x]=(r<<cshiftl[0])|(g<<cshiftl[1])|(b<<cshiftl[2]);
|
||||
}
|
||||
else
|
||||
for(y=0;y<256;y++)
|
||||
{
|
||||
r=src[x<<2]*(100-BLUR_RED);
|
||||
g=src[(x<<2)+1]*(100-BLUR_GREEN);
|
||||
b=src[(x<<2)+2]*(100-BLUR_BLUE);
|
||||
|
||||
r+=src[y<<2]*BLUR_RED;
|
||||
g+=src[(y<<2)+1]*BLUR_GREEN;
|
||||
b+=src[(y<<2)+2]*BLUR_BLUE;
|
||||
|
||||
r/=100;
|
||||
g/=100;
|
||||
b/=100;
|
||||
if(r>255) r=255; if(g>255) g=255; if(b>255) b=255;
|
||||
|
||||
palettetranslate[x|(y<<8)]=(r<<cshiftl[0])|(g<<cshiftl[1])|(b<<cshiftl[2]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Blit32to24(uint32 *src, uint8 *dest, int xr, int yr, int dpitch)
|
||||
{
|
||||
int x,y;
|
||||
|
||||
for(y=yr;y;y--)
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
uint32 tmp = *src;
|
||||
*dest = tmp;
|
||||
dest++;
|
||||
*dest = tmp>>8;
|
||||
dest++;
|
||||
*dest = tmp>>16;
|
||||
dest++;
|
||||
src++;
|
||||
}
|
||||
dest += dpitch / 3 - xr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void Blit32to16(uint32 *src, uint16 *dest, int xr, int yr, int dpitch,
|
||||
int shiftr[3], int shiftl[3])
|
||||
{
|
||||
int x,y;
|
||||
//printf("%d\n",shiftl[1]);
|
||||
for(y=yr;y;y--)
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
uint32 tmp = *src;
|
||||
uint16 dtmp;
|
||||
|
||||
// Begin iffy code
|
||||
//dtmp = (tmp & backmask[2]) >> shiftr[2];
|
||||
//dtmp |= (tmp & backmask[1]) >> shiftr[1];
|
||||
//dtmp |= (tmp & backmask[0]) >> shiftr[0];
|
||||
// End iffy code
|
||||
|
||||
// Begin non-iffy code
|
||||
dtmp = ((tmp&0x0000FF) >> shiftr[2]) << shiftl[2];
|
||||
dtmp |= ((tmp&0x00FF00) >> shiftr[1]) << shiftl[1];
|
||||
dtmp |= ((tmp&0xFF0000) >> shiftr[0]) << shiftl[0];
|
||||
// End non-iffy code
|
||||
|
||||
//dtmp = ((tmp&0x0000FF) >> 3);
|
||||
//dtmp |= ((tmp&0x00FC00) >>5);
|
||||
//dtmp |= ((tmp&0xF80000) >>8);
|
||||
|
||||
*dest = dtmp;
|
||||
src++;
|
||||
dest++;
|
||||
}
|
||||
dest += dpitch / 2 - xr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Blit8To8(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, int yscale, int efx, int special)
|
||||
{
|
||||
int x,y;
|
||||
int pinc;
|
||||
|
||||
if(special==2)
|
||||
{
|
||||
if(xscale!=2 || yscale!=2) return;
|
||||
|
||||
scale(2,dest,pitch,src,256,1,xr,yr);
|
||||
return;
|
||||
}
|
||||
|
||||
if(special==4)
|
||||
{
|
||||
if(xscale!=3 || yscale!=3) return;
|
||||
scale(3,dest,pitch,src,256,1,xr,yr);
|
||||
return;
|
||||
}
|
||||
|
||||
pinc=pitch-(xr*xscale);
|
||||
if(xscale!=1 || yscale!=1)
|
||||
{
|
||||
if(efx&FVB_SCANLINES)
|
||||
{
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
int doo=yscale-(yscale>>1);
|
||||
do
|
||||
{
|
||||
for(x=xr;x;x--,src++)
|
||||
{
|
||||
int too=xscale;
|
||||
do
|
||||
{
|
||||
*(uint8 *)dest=*(uint8 *)src;
|
||||
dest++;
|
||||
} while(--too);
|
||||
}
|
||||
src-=xr;
|
||||
dest+=pinc;
|
||||
} while(--doo);
|
||||
//src-=xr*(yscale-(yscale>>1));
|
||||
dest+=pitch*(yscale>>1);
|
||||
|
||||
src+=xr;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
int doo=yscale;
|
||||
do
|
||||
{
|
||||
for(x=xr;x;x--,src++)
|
||||
{
|
||||
int too=xscale;
|
||||
do
|
||||
{
|
||||
*(uint8 *)dest=*(uint8 *)src;
|
||||
dest++;
|
||||
} while(--too);
|
||||
}
|
||||
src-=xr;
|
||||
dest+=pinc;
|
||||
} while(--doo);
|
||||
src+=xr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
for(y=yr;y;y--,dest+=pinc,src+=256-xr)
|
||||
for(x=xr;x;x-=4,dest+=4,src+=4)
|
||||
*(uint32 *)dest=*(uint32 *)src;
|
||||
}
|
||||
}
|
||||
|
||||
/* Todo: Make sure 24bpp code works right with big-endian cpus */
|
||||
|
||||
void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch,
|
||||
int xscale, int yscale)
|
||||
{
|
||||
int x,y;
|
||||
int pinc;
|
||||
uint8 *destbackup = NULL; /* For hq2x */
|
||||
int pitchbackup = 0;
|
||||
|
||||
//static int google=0;
|
||||
//google^=1;
|
||||
|
||||
if(specbuf8bpp) // 2xscale/3xscale
|
||||
{
|
||||
int mult;
|
||||
int base;
|
||||
|
||||
if(silt == 2) mult = 2;
|
||||
else mult = 3;
|
||||
|
||||
Blit8To8(src, specbuf8bpp, xr, yr, 256*mult, xscale, yscale, 0, silt);
|
||||
|
||||
xr *= mult;
|
||||
yr *= mult;
|
||||
xscale=yscale=1;
|
||||
src = specbuf8bpp;
|
||||
base = 256*mult;
|
||||
|
||||
switch(Bpp)
|
||||
{
|
||||
case 4:
|
||||
pinc=pitch-(xr<<2);
|
||||
for(y=yr;y;y--,src+=base-xr)
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
*(uint32 *)dest=palettetranslate[(uint32)*src];
|
||||
dest+=4;
|
||||
src++;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
pinc=pitch-(xr+xr+xr);
|
||||
for(y=yr;y;y--,src+=base-xr)
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
uint32 tmp=palettetranslate[(uint32)*src];
|
||||
*(uint8 *)dest=tmp;
|
||||
*((uint8 *)dest+1)=tmp>>8;
|
||||
*((uint8 *)dest+2)=tmp>>16;
|
||||
dest+=3;
|
||||
src++;
|
||||
src++;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
pinc=pitch-(xr<<1);
|
||||
|
||||
for(y=yr;y;y--,src+=base-xr)
|
||||
{
|
||||
for(x=xr>>1;x;x--)
|
||||
{
|
||||
*(uint32 *)dest=palettetranslate[*(uint16 *)src];
|
||||
dest+=4;
|
||||
src+=2;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if(specbuf)
|
||||
{
|
||||
destbackup=dest;
|
||||
dest=(uint8 *)specbuf;
|
||||
pitchbackup=pitch;
|
||||
|
||||
pitch=xr*sizeof(uint16);
|
||||
xscale=1;
|
||||
yscale=1;
|
||||
}
|
||||
|
||||
if(highefx&FVB_BLUR) // DONE
|
||||
{
|
||||
if(xscale!=1 || yscale!=1 || (highefx&FVB_SCANLINES)) // DONE
|
||||
{
|
||||
switch(Bpp)
|
||||
{
|
||||
case 4:
|
||||
pinc=pitch-((xr*xscale)<<2);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
int doo=yscale;
|
||||
|
||||
if(highefx&FVB_SCANLINES)
|
||||
doo-=yscale>>1;
|
||||
do
|
||||
{
|
||||
uint8 last=0x00;
|
||||
|
||||
//if(doo == 1 && google) dest+=4;
|
||||
for(x=xr;x;x--,src++)
|
||||
{
|
||||
int too=xscale;
|
||||
do
|
||||
{
|
||||
*(uint32 *)dest=palettetranslate[*src|(last<<8)];
|
||||
dest+=4;
|
||||
} while(--too);
|
||||
last=*src;
|
||||
}
|
||||
//if(doo == 1 && google) dest-=4;
|
||||
src-=xr;
|
||||
dest+=pinc;
|
||||
} while(--doo);
|
||||
src+=xr;
|
||||
if(highefx&FVB_SCANLINES)
|
||||
dest+=pitch*(yscale>>1);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
pinc=pitch-((xr*xscale)*3);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
int doo=yscale;
|
||||
|
||||
if(highefx&FVB_SCANLINES)
|
||||
doo-=yscale>>1;
|
||||
do
|
||||
{
|
||||
uint8 last=0x00;
|
||||
for(x=xr;x;x--,src++)
|
||||
{
|
||||
int too=xscale;
|
||||
do
|
||||
{
|
||||
*(uint32 *)dest=palettetranslate[*src|(last<<8)];
|
||||
dest+=3;
|
||||
} while(--too);
|
||||
last=*src;
|
||||
}
|
||||
src-=xr;
|
||||
dest+=pinc;
|
||||
} while(--doo);
|
||||
src+=xr;
|
||||
if(highefx&FVB_SCANLINES)
|
||||
dest+=pitch*(yscale>>1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
pinc=pitch-((xr*xscale)<<1);
|
||||
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
int doo=yscale;
|
||||
|
||||
if(highefx& FVB_SCANLINES)
|
||||
doo-=yscale>>1;
|
||||
do
|
||||
{
|
||||
uint8 last=0x00;
|
||||
for(x=xr;x;x--,src++)
|
||||
{
|
||||
int too=xscale;
|
||||
do
|
||||
{
|
||||
*(uint16 *)dest=palettetranslate[*src|(last<<8)];
|
||||
dest+=2;
|
||||
} while(--too);
|
||||
last=*src;
|
||||
}
|
||||
src-=xr;
|
||||
dest+=pinc;
|
||||
} while(--doo);
|
||||
src+=xr;
|
||||
if(highefx&FVB_SCANLINES)
|
||||
dest+=pitch*(yscale>>1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else // No scaling, no scanlines, just blurring. - DONE
|
||||
switch(Bpp)
|
||||
{
|
||||
case 4:
|
||||
pinc=pitch-(xr<<2);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
uint8 last=0x00;
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
*(uint32 *)dest=palettetranslate[*src|(last<<8)];
|
||||
last=*src;
|
||||
dest+=4;
|
||||
src++;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
pinc=pitch-(xr+xr+xr);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
uint8 last=0x00;
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
uint32 tmp=palettetranslate[*src|(last<<8)];
|
||||
last=*src;
|
||||
*(uint8 *)dest=tmp;
|
||||
*((uint8 *)dest+1)=tmp>>8;
|
||||
*((uint8 *)dest+2)=tmp>>16;
|
||||
dest+=3;
|
||||
src++;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
pinc=pitch-(xr<<1);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
uint8 last=0x00;
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
*(uint16 *)dest=palettetranslate[*src|(last<<8)];
|
||||
last=*src;
|
||||
dest+=2;
|
||||
src++;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else // No blur effects.
|
||||
{
|
||||
if(xscale!=1 || yscale!=1 || (highefx&FVB_SCANLINES))
|
||||
{
|
||||
switch(Bpp)
|
||||
{
|
||||
case 4:
|
||||
pinc=pitch-((xr*xscale)<<2);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
int doo=yscale;
|
||||
|
||||
if(highefx& FVB_SCANLINES)
|
||||
doo-=yscale>>1;
|
||||
do
|
||||
{
|
||||
for(x=xr;x;x--,src++)
|
||||
{
|
||||
int too=xscale;
|
||||
do
|
||||
{
|
||||
*(uint32 *)dest=palettetranslate[*src];
|
||||
dest+=4;
|
||||
} while(--too);
|
||||
}
|
||||
src-=xr;
|
||||
dest+=pinc;
|
||||
} while(--doo);
|
||||
src+=xr;
|
||||
if(highefx&FVB_SCANLINES)
|
||||
dest+=pitch*(yscale>>1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
pinc=pitch-((xr*xscale)*3);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
int doo=yscale;
|
||||
|
||||
if(highefx& FVB_SCANLINES)
|
||||
doo-=yscale>>1;
|
||||
do
|
||||
{
|
||||
for(x=xr;x;x--,src++)
|
||||
{
|
||||
int too=xscale;
|
||||
do
|
||||
{
|
||||
uint32 tmp=palettetranslate[(uint32)*src];
|
||||
*(uint8 *)dest=tmp;
|
||||
*((uint8 *)dest+1)=tmp>>8;
|
||||
*((uint8 *)dest+2)=tmp>>16;
|
||||
dest+=3;
|
||||
|
||||
//*(uint32 *)dest=palettetranslate[*src];
|
||||
//dest+=4;
|
||||
} while(--too);
|
||||
}
|
||||
src-=xr;
|
||||
dest+=pinc;
|
||||
} while(--doo);
|
||||
src+=xr;
|
||||
if(highefx&FVB_SCANLINES)
|
||||
dest+=pitch*(yscale>>1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
pinc=pitch-((xr*xscale)<<1);
|
||||
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
int doo=yscale;
|
||||
|
||||
if(highefx& FVB_SCANLINES)
|
||||
doo-=yscale>>1;
|
||||
do
|
||||
{
|
||||
for(x=xr;x;x--,src++)
|
||||
{
|
||||
int too=xscale;
|
||||
do
|
||||
{
|
||||
*(uint16 *)dest=palettetranslate[*src];
|
||||
dest+=2;
|
||||
} while(--too);
|
||||
}
|
||||
src-=xr;
|
||||
dest+=pinc;
|
||||
} while(--doo);
|
||||
src+=xr;
|
||||
if(highefx&FVB_SCANLINES)
|
||||
dest+=pitch*(yscale>>1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
switch(Bpp)
|
||||
{
|
||||
case 4:
|
||||
pinc=pitch-(xr<<2);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
*(uint32 *)dest=palettetranslate[(uint32)*src];
|
||||
dest+=4;
|
||||
src++;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
pinc=pitch-(xr+xr+xr);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
uint32 tmp=palettetranslate[(uint32)*src];
|
||||
*(uint8 *)dest=tmp;
|
||||
*((uint8 *)dest+1)=tmp>>8;
|
||||
*((uint8 *)dest+2)=tmp>>16;
|
||||
dest+=3;
|
||||
src++;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
pinc=pitch-(xr<<1);
|
||||
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
for(x=xr>>1;x;x--)
|
||||
{
|
||||
*(uint32 *)dest=palettetranslate[*(uint16 *)src];
|
||||
dest+=4;
|
||||
src+=2;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(specbuf)
|
||||
{
|
||||
if(specbuf32bpp)
|
||||
{
|
||||
int mult = (silt == 3)?3:2;
|
||||
|
||||
if(silt == 3)
|
||||
hq3x_32((uint8 *)specbuf,(uint8*)specbuf32bpp,xr,yr,xr*3*sizeof(uint32));
|
||||
else
|
||||
hq2x_32((uint8 *)specbuf,(uint8*)specbuf32bpp,xr,yr,xr*2*sizeof(uint32));
|
||||
|
||||
if(backBpp == 2)
|
||||
Blit32to16(specbuf32bpp, (uint16*)destbackup, xr*mult, yr*mult, pitchbackup, backshiftr,backshiftl);
|
||||
else // == 3
|
||||
Blit32to24(specbuf32bpp, (uint8*)destbackup, xr*mult, yr*mult, pitchbackup);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(silt == 3)
|
||||
hq3x_32((uint8 *)specbuf,destbackup,xr,yr,pitchbackup);
|
||||
else
|
||||
hq2x_32((uint8 *)specbuf,destbackup,xr,yr,pitchbackup);
|
||||
}
|
||||
}
|
||||
}
|
25
source/drivers/common/vidblit.h
Normal file
25
source/drivers/common/vidblit.h
Normal file
@ -0,0 +1,25 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int eefx, int specfilt);
|
||||
void SetPaletteBlitToHigh(uint8 *src);
|
||||
void KillBlitToHigh(void);
|
||||
void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, int yscale);
|
||||
void Blit8To8(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, int yscale, int efx, int special);
|
114
source/drivers/gamecube/audio.c
Normal file
114
source/drivers/gamecube/audio.c
Normal file
@ -0,0 +1,114 @@
|
||||
/****************************************************************************
|
||||
* audio.c
|
||||
*
|
||||
* Gamecube audio driver
|
||||
****************************************************************************/
|
||||
#include <gccore.h>
|
||||
#define SAMPLERATE 48000
|
||||
static unsigned char audiobuffer[2][64 * 1024] __attribute__((__aligned__(32)));
|
||||
/*** Allow for up to 1 full second ***/
|
||||
|
||||
/****************************************************************************
|
||||
* AudioSwitchBuffers
|
||||
*
|
||||
* Manages which buffer is played next
|
||||
****************************************************************************/
|
||||
static int isWriting = 0; /*** Bool for buffer writes ***/
|
||||
static int buffSize[2]; /*** Hold size of current buffer ***/
|
||||
static int whichab = 0; /*** Which Audio Buffer is in use ***/
|
||||
static int isPlaying; /*** Is Playing ***/
|
||||
static void AudioSwitchBuffers()
|
||||
{
|
||||
|
||||
if ( buffSize[whichab] ) {
|
||||
AUDIO_StopDMA();
|
||||
AUDIO_InitDMA((u32)audiobuffer[whichab], buffSize[whichab]);
|
||||
DCFlushRange(&audiobuffer[whichab], buffSize[whichab]);
|
||||
AUDIO_StartDMA();
|
||||
isPlaying = 0;
|
||||
}
|
||||
|
||||
whichab ^= 1;
|
||||
buffSize[whichab] = 0;
|
||||
}
|
||||
|
||||
void InitialiseSound()
|
||||
{
|
||||
|
||||
AUDIO_Init(NULL); /*** Start audio subsystem ***/
|
||||
|
||||
/*** Set default samplerate to 48khz ***/
|
||||
AUDIO_SetDSPSampleRate(AI_SAMPLERATE_48KHZ);
|
||||
|
||||
/*** and the DMA Callback ***/
|
||||
AUDIO_RegisterDMACallback( AudioSwitchBuffers );
|
||||
|
||||
buffSize[0] = buffSize[1] = 0;
|
||||
}
|
||||
|
||||
void StartAudio()
|
||||
{
|
||||
AUDIO_StartDMA();
|
||||
}
|
||||
|
||||
void StopAudio()
|
||||
{
|
||||
AUDIO_StopDMA();
|
||||
}
|
||||
|
||||
static inline unsigned short FLIP16(unsigned short b)
|
||||
{
|
||||
return((b<<8)|((b>>8)&0xFF));
|
||||
}
|
||||
|
||||
static inline u32 FLIP32(u32 b)
|
||||
{
|
||||
return( (b<<24) | ((b>>8)&0xFF00) | ((b<<8)&0xFF0000) | ((b>>24)&0xFF) );
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Audio incoming is monaural
|
||||
*
|
||||
* PlaySound will simply mix to get it right
|
||||
****************************************************************************/
|
||||
#define AUDIOBUFFER ((50 * SAMPLERATE) / 1000 ) << 4
|
||||
static int isPlaying = 0;
|
||||
static short MBuffer[ 8 * 96000 / 50 ];
|
||||
|
||||
void PlaySound( unsigned int *Buffer, int count )
|
||||
{
|
||||
|
||||
int P;
|
||||
unsigned short *s = (unsigned short *)&MBuffer[0];
|
||||
unsigned int *d = (unsigned int *)&audiobuffer[whichab][buffSize[whichab]];
|
||||
unsigned int c;
|
||||
int ms;
|
||||
|
||||
isWriting = 1;
|
||||
|
||||
for ( P = 0; P < count; P++ ) {
|
||||
MBuffer[P] = Buffer[P];
|
||||
}
|
||||
|
||||
/*** Now do Mono - Stereo Conversion ***/
|
||||
ms = count;
|
||||
do
|
||||
{
|
||||
c = 0xffff & *s++;
|
||||
*d++ = (c | (c<<16));
|
||||
} while(--ms);
|
||||
|
||||
buffSize[whichab] += ( count << 2 );
|
||||
/*** This is the kicker for the entire audio loop ***/
|
||||
if ( isPlaying == 0 )
|
||||
{
|
||||
if ( buffSize[whichab] > AUDIOBUFFER )
|
||||
{
|
||||
isPlaying = 1;
|
||||
AudioSwitchBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
isWriting = 0;
|
||||
|
||||
}
|
30
source/drivers/gamecube/common.h
Normal file
30
source/drivers/gamecube/common.h
Normal file
@ -0,0 +1,30 @@
|
||||
/****************************************************************************
|
||||
* Common module
|
||||
****************************************************************************/
|
||||
|
||||
#include "../../driver.h"
|
||||
#include "../common/config.h"
|
||||
|
||||
/* Message logging(non-netplay messages, usually) for all. */
|
||||
extern int NoWaiting;
|
||||
extern FCEUGI *GI;
|
||||
void DSMFix(unsigned int msg);
|
||||
void StopSound(void);
|
||||
|
||||
extern int eoptions;
|
||||
|
||||
#define EO_BGRUN 1
|
||||
|
||||
#define EO_CPALETTE 4
|
||||
#define EO_NOSPRLIM 8
|
||||
#define EO_FSAFTERLOAD 32
|
||||
#define EO_FOAFTERSTART 64
|
||||
#define EO_NOTHROTTLE 128
|
||||
#define EO_CLIPSIDES 256
|
||||
#define EO_SNAPNAME 512
|
||||
#define EO_HIDEMENU 2048
|
||||
#define EO_HIGHPRIO 4096
|
||||
#define EO_FORCEASPECT 8192
|
||||
#define EO_FORCEISCALE 16384
|
||||
#define EO_NOFOURSCORE 32768
|
||||
|
243
source/drivers/gamecube/dvdcode.c
Normal file
243
source/drivers/gamecube/dvdcode.c
Normal file
@ -0,0 +1,243 @@
|
||||
/****************************************************************************
|
||||
* Drive Code Sending
|
||||
*
|
||||
* These codes are courtesy of Ninjamod
|
||||
* and are used with permission.
|
||||
*
|
||||
* http://www.ninjamod.com
|
||||
****************************************************************************/
|
||||
|
||||
#include <gccore.h>
|
||||
|
||||
volatile long *dvdio=(volatile long *)0xCC006000;
|
||||
|
||||
unsigned int Drive04[] = {
|
||||
0x40D000,
|
||||
12,0xf4e1a538,0xcfdc0080,0xf4712aea,
|
||||
12,0x08806ef4,0xe1135fcf,0xdc6e80a0,
|
||||
12,0xf9b801f4,0xe1295fcf,0xf47447d0,
|
||||
12,0x40f7204c,0x80f474d6,0x9c08f720,
|
||||
12,0xd6fcf474,0x28ae08f7,0x20d2fc80,
|
||||
12,0x04c4dafc,0xf4747ed4,0x08f000c8,
|
||||
12,0xdafcf500,0x01e803fc,0xe200a0f4,
|
||||
12,0x7400ec40,0xf51002f5,0x1003f510,
|
||||
12,0x04f51005,0xf51006f5,0x1007f510,
|
||||
12,0x08f51009,0xf5100af5,0x100bf510,
|
||||
12,0x0cf5100d,0xc8dafcf5,0x0002e803,
|
||||
12,0xfc3d01f4,0x74f9ec40,0x8002f020,
|
||||
12,0xc88480c0,0x9c81dcb4,0x80f53000,
|
||||
12,0xf444f9d1,0x40f8aa00,0x10f4d0f4,
|
||||
12,0xd140f001,0xdcb480f5,0x3000f748,
|
||||
12,0xaa00e907,0xf4c4f9d1,0x4010fed8,
|
||||
12,0x32e81df7,0x48a800e8,0x26f748ab,
|
||||
12,0x00e820f7,0x48e100e8,0x1af748ee,
|
||||
12,0x00e83bd8,0x55e82ffe,0x7104fd20,
|
||||
12,0x00f45100,0xd240a0f5,0x1000fef2,
|
||||
12,0xf9f4d200,0xd2407104,0xfd0a00f2,
|
||||
12,0x49fd0500,0x5104f236,0xfef721bc,
|
||||
12,0xfff731bc,0xfffeccb5,0x80fd5300,
|
||||
12,0xea0cccb5,0x80c4b081,0xccb680c4,
|
||||
12,0x9481dcb4,0x80f8e000,0x10a0f510,
|
||||
12,0x01f51002,0xf51003fe,0xccdafcf7,
|
||||
12,0x00feffc4,0xdafccc44,0xfcf700fe,
|
||||
12,0xffc444fc,0xf27cd004,0xcc5b80d8,
|
||||
12,0x01e9027c,0x04f47585,0xd1405120,
|
||||
12,0x7134f47d,0xc18508e9,0x1b8000cd,
|
||||
12,0xdafcd800,0xe906f701,0xf7ffea03,
|
||||
12,0xf50908c5,0xdafcf475,0xf8d14014,
|
||||
12,0xfe8001ea,0xe2f710ff,0xf721f749,
|
||||
12,0x0806e905,0x8502f511,0x0121f479,
|
||||
12,0x00f000e9,0x0e8000f4,0xc9f8d140,
|
||||
12,0xd900e803,0xf5100921,0xd906e90f,
|
||||
12,0x6106f4c8,0xf8d140d8,0x00e802d5,
|
||||
12,0x064106f4,0xe06fdccf,0xccdafcf7,
|
||||
12,0x00fdffc4,0xdafccc44,0xfcf700fe,
|
||||
12,0xffc444fc,0xf27cd004,0xcc5b80d8,
|
||||
12,0x01e9027c,0x04f475ed,0xd1405120,
|
||||
12,0xfef4e05c,0xcbcf0000,0x740a0800,
|
||||
12,0x01000000,0x00000000,0x00000080,
|
||||
12,0x00000000,0x00000000,0x00000000,
|
||||
00,0x00804c,
|
||||
03,0x00D04000,
|
||||
99 };
|
||||
|
||||
unsigned int Drive06[] = {
|
||||
0x40D000,
|
||||
12,0xf4e1a538,0xc7dc0080,0xf471c8e9,
|
||||
12,0x08806ef4,0xe11a5fc7,0xdc6e80a0,
|
||||
12,0xf9ac01f4,0xe1305fc7,0xf47447d0,
|
||||
12,0x40f7204c,0x80f47442,0x9d08f720,
|
||||
12,0xd6fcf474,0x45b108f7,0x20d2fc80,
|
||||
12,0x04c4dafc,0xf4741ed4,0x08f000c8,
|
||||
12,0xdafcf500,0x01e803fc,0xe200a0f4,
|
||||
12,0x7400ec40,0xf51002f5,0x1003f510,
|
||||
12,0x04f51005,0xf51006f5,0x1007f510,
|
||||
12,0x08f51009,0xf5100af5,0x100bf510,
|
||||
12,0x0cf5100d,0xc8dafcf5,0x0002e803,
|
||||
12,0xfc3d01f4,0x7402ed40,0x8002f020,
|
||||
12,0xc87880c0,0x9081dca8,0x80f53000,
|
||||
12,0xf444f9d1,0x40f8aa00,0x10f4d0f4,
|
||||
12,0xd140f001,0xdca880f5,0x3000f748,
|
||||
12,0xaa00e907,0xf4c4f9d1,0x4010fed8,
|
||||
12,0x32e81df7,0x48a800e8,0x26f748ab,
|
||||
12,0x00e820f7,0x48e100e8,0x1af748ee,
|
||||
12,0x00e83bd8,0x55e82ffe,0x7104fd20,
|
||||
12,0x00f45100,0xd240a0f5,0x1000fef2,
|
||||
12,0xf9f4d200,0xd2407104,0xfd0a00f2,
|
||||
12,0x49fd0500,0x5104f236,0xfef721bc,
|
||||
12,0xfff731bc,0xfffecca9,0x80fd5300,
|
||||
12,0xea0ccca9,0x80c4a481,0xccaa80c4,
|
||||
12,0x8881dca8,0x80f8e000,0x10a0f510,
|
||||
12,0x01f51002,0xf51003fe,0xccdafcf7,
|
||||
12,0x00feffc4,0xdafccc44,0xfcf700fe,
|
||||
12,0xffc444fc,0xf27cd004,0xcc5b80d8,
|
||||
12,0x01e9027c,0x04f47585,0xd1405120,
|
||||
12,0x7134f47d,0xb98508e9,0x1b8000cd,
|
||||
12,0xdafcd800,0xe906f701,0xf7ffea03,
|
||||
12,0xf50908c5,0xdafcf475,0xf8d14014,
|
||||
12,0xfe8001ea,0xe2f710ff,0xf721f749,
|
||||
12,0x0806e905,0x8502f511,0x0121f479,
|
||||
12,0x00f000e9,0x0e8000f4,0xc9f8d140,
|
||||
12,0xd900e803,0xf5100921,0xd906e90f,
|
||||
12,0x6106f4c8,0xf8d140d8,0x00e802d5,
|
||||
12,0x064106f4,0xe08cdfc7,0xccdafcf7,
|
||||
12,0x00fdffc4,0xdafccc44,0xfcf700fe,
|
||||
12,0xffc444fc,0xf27cd004,0xcc5b80d8,
|
||||
12,0x01e9027c,0x04f475ed,0xd1405120,
|
||||
12,0xfef4e0de,0xcbc70000,0x740a0800,
|
||||
12,0x01000000,0x00000000,0x00000080,
|
||||
12,0x00000000,0x00000000,0x00000000,
|
||||
00,0x00804c,
|
||||
03,0x00D04000,
|
||||
99 };
|
||||
|
||||
unsigned int Drive08[] = {
|
||||
0x40D000,
|
||||
12,0xf4e1a538,0xcfdc0080,0xf4717cea,
|
||||
12,0x08806ef4,0xe1135fcf,0xdc6e80a0,
|
||||
12,0xf9b601f4,0xe1295fcf,0xf47447d0,
|
||||
12,0x40f7204c,0x80f47432,0x9d08f720,
|
||||
12,0xd6fcf474,0x75ae08f7,0x20d2fc80,
|
||||
12,0x04c4dafc,0xf474d9d4,0x08f000c8,
|
||||
12,0xdafcf500,0x01e803fc,0xe200a0f4,
|
||||
12,0x7400ec40,0xf51002f5,0x1003f510,
|
||||
12,0x04f51005,0xf51006f5,0x1007f510,
|
||||
12,0x08f51009,0xf5100af5,0x100bf510,
|
||||
12,0x0cf5100d,0xc8dafcf5,0x0002e803,
|
||||
12,0xfc3d01f4,0x74f5ec40,0x8002f020,
|
||||
12,0xc88080c0,0x9881dcb0,0x80f53000,
|
||||
12,0xf444f9d1,0x40f8aa00,0x10f4d0f4,
|
||||
12,0xd140f001,0xdcb080f5,0x3000f748,
|
||||
12,0xaa00e907,0xf4c4f9d1,0x4010fed8,
|
||||
12,0x32e81df7,0x48a800e8,0x26f748ab,
|
||||
12,0x00e820f7,0x48e100e8,0x1af748ee,
|
||||
12,0x00e83bd8,0x55e82ffe,0x7104fd20,
|
||||
12,0x00f45100,0xd240a0f5,0x1000fef2,
|
||||
12,0xf9f4d200,0xd2407104,0xfd0a00f2,
|
||||
12,0x49fd0500,0x5104f236,0xfef721bc,
|
||||
12,0xfff731bc,0xfffeccb1,0x80fd5300,
|
||||
12,0xea0cccb1,0x80c4ac81,0xccb280c4,
|
||||
12,0x9081dcb0,0x80f8e000,0x10a0f510,
|
||||
12,0x01f51002,0xf51003fe,0xccdafcf7,
|
||||
12,0x00feffc4,0xdafccc44,0xfcf700fe,
|
||||
12,0xffc444fc,0xf27cd004,0xcc5b80d8,
|
||||
12,0x01e9027c,0x04f47585,0xd1405120,
|
||||
12,0x7134f47d,0xc18508e9,0x1b8000cd,
|
||||
12,0xdafcd800,0xe906f701,0xf7ffea03,
|
||||
12,0xf50908c5,0xdafcf475,0xf8d14014,
|
||||
12,0xfe8001ea,0xe2f710ff,0xf721f749,
|
||||
12,0x0806e905,0x8502f511,0x0121f479,
|
||||
12,0x00f000e9,0x0e8000f4,0xc9f8d140,
|
||||
12,0xd900e803,0xf5100921,0xd906e90f,
|
||||
12,0x6106f4c8,0xf8d140d8,0x00e802d5,
|
||||
12,0x064106f4,0xe0bcdccf,0xccdafcf7,
|
||||
12,0x00fdffc4,0xdafccc44,0xfcf700fe,
|
||||
12,0xffc444fc,0xf27cd004,0xcc5b80d8,
|
||||
12,0x01e9027c,0x04f475ed,0xd1405120,
|
||||
12,0xfef4e0b5,0xcbcf0000,0x740a0800,
|
||||
12,0x01000000,0x00000000,0x00000080,
|
||||
12,0x00000000,0x00000000,0x00000000,
|
||||
00,0x00804c,
|
||||
03,0x00D04000,
|
||||
99 };
|
||||
|
||||
/****************************************************************************
|
||||
* Drivecode
|
||||
*
|
||||
* Dumb C Implementation of Anaconda Send Code
|
||||
****************************************************************************/
|
||||
|
||||
void SendDriveCode( int model )
|
||||
{
|
||||
|
||||
int i = 0;
|
||||
int length;
|
||||
unsigned int cmd = 0xfe010100;
|
||||
unsigned int loadaddress;
|
||||
unsigned int *DriveCode;
|
||||
unsigned char debug[100];
|
||||
|
||||
switch( model )
|
||||
{ case 4: DriveCode = (unsigned int *)Drive04; break;
|
||||
case 6: DriveCode = (unsigned int *)Drive06; break;
|
||||
case 8: DriveCode = (unsigned int *)Drive08; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
loadaddress = DriveCode[i++];
|
||||
length = DriveCode[i++];
|
||||
|
||||
while ( length == 12 )
|
||||
{
|
||||
|
||||
/*** Address Select ***/
|
||||
dvdio[0] |= 0x14;
|
||||
dvdio[1] = 0;
|
||||
dvdio[2] = cmd;
|
||||
dvdio[3] = loadaddress;
|
||||
dvdio[4] = (length << 16);
|
||||
dvdio[5] = 0;
|
||||
dvdio[6] = 0;
|
||||
dvdio[7] = 3;
|
||||
while ( dvdio[7] & 1 );
|
||||
|
||||
dvdio[0] |= 0x14;
|
||||
dvdio[1] = 0;
|
||||
dvdio[2] = DriveCode[i++];
|
||||
dvdio[3] = DriveCode[i++];
|
||||
dvdio[4] = DriveCode[i++];
|
||||
dvdio[5] = 0;
|
||||
dvdio[6] = 0;
|
||||
dvdio[7] = 1;
|
||||
while ( dvdio[7] & 1 );
|
||||
|
||||
loadaddress += length;
|
||||
length = DriveCode[i++];
|
||||
}
|
||||
|
||||
loadaddress = DriveCode[i++];
|
||||
length = DriveCode[i++];
|
||||
|
||||
/*** Do SendDriveCommand End ***/
|
||||
dvdio[0] |= 0x14;
|
||||
dvdio[1] = 0;
|
||||
dvdio[2] = cmd;
|
||||
dvdio[3] = loadaddress;
|
||||
dvdio[4] = (length << 16);
|
||||
dvdio[5] = 0;
|
||||
dvdio[6] = 0;
|
||||
dvdio[7] = 3;
|
||||
while ( dvdio[7] & 1 );
|
||||
|
||||
dvdio[0] |= 0x14;
|
||||
dvdio[1] = 0;
|
||||
dvdio[2] = DriveCode[i++];
|
||||
dvdio[3] = 0;
|
||||
dvdio[4] = 0;
|
||||
dvdio[5] = 0;
|
||||
dvdio[6] = 0;
|
||||
dvdio[7] = 1;
|
||||
while ( dvdio[7] & 1 );
|
||||
|
||||
}
|
||||
|
956
source/drivers/gamecube/gcdvd.c
Normal file
956
source/drivers/gamecube/gcdvd.c
Normal file
@ -0,0 +1,956 @@
|
||||
/****************************************************************************
|
||||
* DVD.CPP
|
||||
*
|
||||
* This module manages all dvd i/o etc.
|
||||
* There is also a simple ISO9660 parser included.
|
||||
****************************************************************************/
|
||||
|
||||
#include <gccore.h>
|
||||
#include <ogcsys.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sdcard.h>
|
||||
#include <gctypes.h>
|
||||
|
||||
#include "sz.h"
|
||||
#include "gcdvd.h"
|
||||
|
||||
/*** Simplified Directory Entry Record
|
||||
I only care about a couple of values ***/
|
||||
#define RECLEN 0
|
||||
#define EXTENT 6
|
||||
#define FILE_LENGTH 14
|
||||
#define FILE_FLAGS 25
|
||||
#define FILENAME_LENGTH 32
|
||||
#define FILENAME 33
|
||||
|
||||
#define PAGESIZE 10
|
||||
|
||||
FILEENTRIES filelist[MAXFILES];
|
||||
int maxfiles = 0;
|
||||
int offset = 0;
|
||||
int selection = 0;
|
||||
|
||||
/*** DVD Read Buffer ***/
|
||||
|
||||
unsigned char readbuffer[2048] ATTRIBUTE_ALIGN(32);
|
||||
unsigned char DVDreadbuffer[2048] ATTRIBUTE_ALIGN (32);
|
||||
volatile long *dvd=(volatile long *)0xCC006000;
|
||||
static unsigned char *inquiry=(unsigned char *)0x80000004;
|
||||
extern void SendDriveCode( int model );
|
||||
extern int font_height;
|
||||
extern bool isZipFile();
|
||||
extern void writex(int x, int y, int sx, int sy, char *string, unsigned int selected);
|
||||
extern unsigned char *nesromptr;
|
||||
extern int IsXenoGCImage( char *buffer );
|
||||
|
||||
void GetSDInfo ();
|
||||
extern int choosenSDSlot;
|
||||
/*extern void ClearScreen();
|
||||
int LoadDVDFile( unsigned char *buffer );
|
||||
extern int unzipDVDFile( unsigned char *outbuffer, unsigned int discoffset, unsigned int length);
|
||||
extern int CentreTextPosition( char *text );*/
|
||||
|
||||
/** true if we the emulator is running on a wii **/
|
||||
bool isWii = false;
|
||||
|
||||
int UseSDCARD = 0;
|
||||
sd_file * filehandle;
|
||||
char rootSDdir[SDCARD_MAX_PATH_LEN];
|
||||
int haveSDdir = 0;
|
||||
|
||||
/****************************************************************************
|
||||
* DVD Lowlevel Functions
|
||||
*
|
||||
* These are here simply because the same functions in libogc are not
|
||||
* exposed to the user
|
||||
****************************************************************************/
|
||||
|
||||
void dvd_inquiry()
|
||||
{
|
||||
|
||||
dvd[0] = 0x2e;
|
||||
dvd[1] = 0;
|
||||
dvd[2] = 0x12000000;
|
||||
dvd[3] = 0;
|
||||
dvd[4] = 0x20;
|
||||
dvd[5] = 0x80000000;
|
||||
dvd[6] = 0x20;
|
||||
dvd[7] = 3;
|
||||
|
||||
while( dvd[7] & 1 );
|
||||
DCFlushRange((void *)0x80000000, 32);
|
||||
}
|
||||
|
||||
void dvd_unlock()
|
||||
{
|
||||
dvd[0] |= 0x00000014;
|
||||
dvd[1] = 0x00000000;
|
||||
dvd[2] = 0xFF014D41;
|
||||
dvd[3] = 0x54534849;
|
||||
dvd[4] = 0x54410200;
|
||||
dvd[7] = 1;
|
||||
while ((dvd[0] & 0x14) == 0) { }
|
||||
dvd[0] |= 0x00000014;
|
||||
dvd[1] = 0x00000000;
|
||||
dvd[2] = 0xFF004456;
|
||||
dvd[3] = 0x442D4741;
|
||||
dvd[4] = 0x4D450300;
|
||||
dvd[7] = 1;
|
||||
while ((dvd[0] & 0x14) == 0) { }
|
||||
}
|
||||
|
||||
void dvd_extension()
|
||||
{
|
||||
dvd[0] = 0x2E;
|
||||
dvd[1] = 0;
|
||||
|
||||
dvd[2] = 0x55010000;
|
||||
dvd[3] = 0;
|
||||
dvd[4] = 0;
|
||||
dvd[5] = 0;
|
||||
dvd[6] = 0;
|
||||
dvd[7] = 1; // enable reading!
|
||||
while (dvd[7] & 1);
|
||||
}
|
||||
|
||||
#define DEBUG_STOP_DRIVE 0
|
||||
#define DEBUG_START_DRIVE 0x100
|
||||
#define DEBUG_ACCEPT_COPY 0x4000
|
||||
#define DEBUG_DISC_CHECK 0x8000
|
||||
|
||||
void dvd_motor_on_extra()
|
||||
{
|
||||
|
||||
dvd[0] = 0x2e;
|
||||
dvd[1] = 0;
|
||||
dvd[2] = 0xfe110000 | DEBUG_START_DRIVE | DEBUG_ACCEPT_COPY | DEBUG_DISC_CHECK;
|
||||
dvd[3] = 0;
|
||||
dvd[4] = 0;
|
||||
dvd[5] = 0;
|
||||
dvd[6] = 0;
|
||||
dvd[7] = 1;
|
||||
while ( dvd[7] & 1 );
|
||||
|
||||
}
|
||||
|
||||
void dvd_motor_off( )
|
||||
{
|
||||
dvd[0] = 0x2e;
|
||||
dvd[1] = 0;
|
||||
dvd[2] = 0xe3000000;
|
||||
dvd[3] = 0;
|
||||
dvd[4] = 0;
|
||||
dvd[5] = 0;
|
||||
dvd[6] = 0;
|
||||
dvd[7] = 1; // Do immediate
|
||||
while (dvd[7] & 1);
|
||||
|
||||
/*** PSO Stops blackscreen at reload ***/
|
||||
dvd[0] = 0x14;
|
||||
dvd[1] = 0;
|
||||
}
|
||||
|
||||
void dvd_setstatus()
|
||||
{
|
||||
dvd[0] = 0x2E;
|
||||
dvd[1] = 0;
|
||||
|
||||
dvd[2] = 0xee060300;
|
||||
dvd[3] = 0;
|
||||
dvd[4] = 0;
|
||||
dvd[5] = 0;
|
||||
dvd[6] = 0;
|
||||
dvd[7] = 1; // enable reading!
|
||||
while (dvd[7] & 1);
|
||||
}
|
||||
|
||||
unsigned int dvd_read_id(void *dst)
|
||||
{
|
||||
if ((((int)dst) & 0xC0000000) == 0x80000000) // cached?
|
||||
DCInvalidateRange((void *)dst, 0x20);
|
||||
|
||||
dvd[0] = 0x2E;
|
||||
dvd[1] = 0;
|
||||
|
||||
dvd[2] = 0xA8000040;
|
||||
dvd[3] = 0;
|
||||
dvd[4] = 0x20;
|
||||
dvd[5] = (unsigned long)dst;
|
||||
dvd[6] = 0x20;
|
||||
dvd[7] = 3; // enable reading!
|
||||
|
||||
while (dvd[7] & 1);
|
||||
|
||||
if (dvd[0] & 0x4)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int dvd_read(void *dst, unsigned int len, u64 offset)
|
||||
{
|
||||
|
||||
unsigned char* buffer = (unsigned char*)(unsigned int)DVDreadbuffer;
|
||||
u32 offset32 = (u32)(offset >> 2);
|
||||
|
||||
if (len > 2048 )
|
||||
return 1;
|
||||
|
||||
DCInvalidateRange ((void *) buffer, len);
|
||||
|
||||
if (offset < 0x57057C00 || (isWii == true && offset < 0x118244F00LL)) // don't read past the end of the dvd
|
||||
{
|
||||
dvd[0] = 0x2E;
|
||||
dvd[1] = 0;
|
||||
dvd[2] = 0xA8000000;
|
||||
dvd[3] = offset32;
|
||||
dvd[4] = len;
|
||||
dvd[5] = (unsigned long)buffer;
|
||||
dvd[6] = len;
|
||||
dvd[7] = 3; // enable reading!
|
||||
while (dvd[7] & 1);
|
||||
memcpy (dst, buffer, len);
|
||||
} else // Let's not read past end of DVD
|
||||
return 1;
|
||||
|
||||
if (dvd[0] & 0x4) /* Ensure it has completed */
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void dvd_reset(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
*(unsigned long*)0xcc006004 = 2;
|
||||
unsigned long v = *(unsigned long*)0xcc003024;
|
||||
*(unsigned long*)0xcc003024 = (v &~4) | 1;
|
||||
|
||||
for ( i = 0; i < 10000; i++ );
|
||||
|
||||
*(unsigned long*)0xcc003024 = v | 5;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* ISO Parsing Functions
|
||||
****************************************************************************/
|
||||
#define PVDROOT 0x9c
|
||||
static int IsJoliet = 0;
|
||||
static u64 rootdir = 0;
|
||||
static int rootdirlength = 0;
|
||||
static int shadowroot, shadowlength;
|
||||
int IsPVD()
|
||||
{
|
||||
int sector = 16;
|
||||
// u32 offset32;
|
||||
|
||||
IsJoliet = rootdir = 0;
|
||||
|
||||
/*** Read the ISO section looking for a valid
|
||||
Primary Volume Decriptor.
|
||||
Spec says first 8 characters are id ***/
|
||||
while ( sector < 32 ) {
|
||||
|
||||
dvd_read( &readbuffer, 2048, sector << 11 );
|
||||
if ( memcmp( &readbuffer, "\2CD001\1", 8 ) == 0 ) {
|
||||
//memcpy(&offset32, &readbuffer[PVDROOT + EXTENT], 4);
|
||||
//memcpy(&rootdirlength, &readbuffer[PVDROOT + FILE_LENGTH], 4);
|
||||
//rootdir = (u64)offset32;
|
||||
memcpy(&rootdir, &readbuffer[PVDROOT + EXTENT], 4);
|
||||
memcpy(&rootdirlength, &readbuffer[PVDROOT + FILE_LENGTH], 4);
|
||||
IsJoliet = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
sector++;
|
||||
}
|
||||
|
||||
if ( IsJoliet == 0 ) {
|
||||
sector = 16;
|
||||
|
||||
while ( sector < 32 ) {
|
||||
|
||||
if ( memcmp( &readbuffer, "\1CD001\1", 8 ) == 0 ) {
|
||||
/*memcpy(&offset32, &readbuffer[PVDROOT + EXTENT], 4);
|
||||
memcpy(&rootdirlength, &readbuffer[PVDROOT + FILE_LENGTH], 4);
|
||||
rootdir = (u64)offset32;*/
|
||||
memcpy(&rootdir, &readbuffer[PVDROOT + EXTENT], 4);
|
||||
memcpy(&rootdirlength, &readbuffer[PVDROOT + FILE_LENGTH], 4);
|
||||
IsJoliet = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
sector++;
|
||||
}
|
||||
}
|
||||
|
||||
rootdir <<= 11;
|
||||
shadowroot = rootdir;
|
||||
shadowlength = rootdirlength;
|
||||
|
||||
return IsJoliet;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* getfiles
|
||||
*
|
||||
* Retrieve the current file directory entry
|
||||
****************************************************************************/
|
||||
static int diroffset = 0;
|
||||
int getfiles( int filecount )
|
||||
{
|
||||
char fname[256];
|
||||
char *ptr;
|
||||
char *filename;
|
||||
char *filenamelength;
|
||||
char *rr;
|
||||
int j;
|
||||
//u32 offset32;
|
||||
|
||||
/*** Do some basic checks ***/
|
||||
if ( filecount == MAXFILES ) return 0;
|
||||
if ( diroffset >= 2048 ) return 0;
|
||||
|
||||
/*** Now decode this entry ***/
|
||||
if ( readbuffer[diroffset] != 0 )
|
||||
{
|
||||
|
||||
ptr = (char *)&readbuffer[0];
|
||||
ptr += diroffset;
|
||||
filename = ptr + FILENAME;
|
||||
filenamelength = ptr + FILENAME_LENGTH;
|
||||
|
||||
if ( diroffset + readbuffer[diroffset] > 2048 ) return 0;
|
||||
|
||||
if ( *filenamelength ) {
|
||||
|
||||
memset(&fname, 0, 128);
|
||||
|
||||
/*** Return the values needed ***/
|
||||
if ( IsJoliet == 1 ) strcpy(fname, filename);
|
||||
else {
|
||||
for ( j = 0; j < ( *filenamelength >> 1 ); j++ ) {
|
||||
fname[j] = filename[j*2+1];
|
||||
}
|
||||
|
||||
fname[j] = 0;
|
||||
|
||||
if ( strlen(fname) >= MAXJOLIET ) fname[MAXJOLIET-1] = 0;
|
||||
|
||||
if ( strlen(fname) == 0 ) fname[0] = filename[0];
|
||||
}
|
||||
|
||||
if ( strlen(fname) == 0 ) strcpy(fname,"ROOT");
|
||||
else {
|
||||
if ( fname[0] == 1 ) strcpy(fname,"..");
|
||||
else{
|
||||
//fname[ *filenamelength ] = 0;
|
||||
/*
|
||||
* Move *filenamelength to t,
|
||||
* Only to stop gcc warning for noobs :)
|
||||
*/
|
||||
int t = *filenamelength;
|
||||
fname[t] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Rockridge Check **/ /*** Remove any trailing ;1 from ISO name ***/
|
||||
rr = strstr (fname, ";"); //if ( fname[ strlen(fname) - 2 ] == ';' )
|
||||
if (rr != NULL) *rr = 0; //fname[ strlen(fname) - 2 ] = 0;*/
|
||||
|
||||
/*strcpy(filelist[filecount].filename, fname);
|
||||
memcpy(&offset32, &readbuffer[diroffset + EXTENT], 4);
|
||||
memcpy(&cdfiles[filecount].length, &readbuffer[diroffset + FILE_LENGTH], 4);
|
||||
memcpy(&cdfiles[filecount].flags, &readbuffer[diroffset + FILE_FLAGS], 1);
|
||||
cdfiles[filecount].offset = (u64)offset32;*/
|
||||
strcpy(filelist[filecount].filename, fname);
|
||||
memcpy(&filelist[filecount].offset, &readbuffer[diroffset + EXTENT], 4);
|
||||
memcpy(&filelist[filecount].length, &readbuffer[diroffset + FILE_LENGTH], 4);
|
||||
memcpy(&filelist[filecount].flags, &readbuffer[diroffset + FILE_FLAGS], 1);
|
||||
|
||||
filelist[filecount].offset <<= 11;
|
||||
filelist[filecount].flags = filelist[filecount].flags & 2;
|
||||
|
||||
/*** Prepare for next entry ***/
|
||||
diroffset += readbuffer[diroffset];
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* ParseDirectory
|
||||
*
|
||||
* Parse the isodirectory, returning the number of files found
|
||||
****************************************************************************/
|
||||
|
||||
int parsedir()
|
||||
{
|
||||
int pdlength;
|
||||
int pdoffset;
|
||||
int rdoffset;
|
||||
int len = 0;
|
||||
int filecount = 0;
|
||||
|
||||
pdoffset = rdoffset = rootdir;
|
||||
pdlength = rootdirlength;
|
||||
filecount = 0;
|
||||
|
||||
/*** Clear any existing values ***/
|
||||
memset(&filelist, 0, sizeof(FILEENTRIES) * MAXFILES);
|
||||
|
||||
/*** Get as many files as possible ***/
|
||||
while ( len < pdlength )
|
||||
{
|
||||
if (dvd_read (&readbuffer, 2048, pdoffset) == 0) return 0;
|
||||
//dvd_read(&readbuffer, 2048, pdoffset);
|
||||
diroffset = 0;
|
||||
|
||||
while ( getfiles( filecount ) )
|
||||
{
|
||||
if ( filecount < MAXFILES )
|
||||
filecount++;
|
||||
}
|
||||
|
||||
len += 2048;
|
||||
pdoffset = rdoffset + len;
|
||||
}
|
||||
|
||||
return filecount;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Update SDCARD curent directory name
|
||||
***************************************************************************/
|
||||
int updateSDdirname()
|
||||
{
|
||||
int size=0;
|
||||
char *test;
|
||||
char temp[1024];
|
||||
char tmpCompare[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 */
|
||||
sprintf(tmpCompare, "dev%d:",choosenSDSlot);
|
||||
if (strcmp(rootSDdir,tmpCompare) == 0)sprintf(rootSDdir,"dev%d:\\fceu\\..", choosenSDSlot);
|
||||
//if (strcmp(rootSDdir,"dev0:") == 0) sprintf(rootSDdir,"dev0:\\fceu\\..");
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* test new directory namelength */
|
||||
if ((strlen(rootSDdir)+1+strlen(filelist[selection].filename)) < SDCARD_MAX_PATH_LEN)
|
||||
{
|
||||
/* handles root name */
|
||||
sprintf(tmpCompare, "dev%d:\\fceu\\..",choosenSDSlot);
|
||||
if (strcmp(rootSDdir, tmpCompare) == 0) sprintf(rootSDdir,"dev%d:",choosenSDSlot);
|
||||
//if (strcmp(rootSDdir,"dev0:\\fceu\\..") == 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;
|
||||
|
||||
/* initialize selection */
|
||||
selection = offset = 0;
|
||||
|
||||
/* Get a list of files from the actual root directory */
|
||||
entries = SDCARD_ReadDir (rootSDdir, &sddir);
|
||||
//entries = SDCARD_ReadDir (sdcardpath, &sddir);
|
||||
|
||||
if (entries <= 0) entries = 0;
|
||||
if (entries>MAXFILES) entries = MAXFILES;
|
||||
|
||||
while (entries)
|
||||
{
|
||||
memset (&filelist[nbfiles], 0, sizeof (FILEENTRIES));
|
||||
strncpy(filelist[nbfiles].filename,(const char*)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--;
|
||||
}
|
||||
|
||||
free(sddir);
|
||||
|
||||
return nbfiles;
|
||||
}
|
||||
/****************************************************************************
|
||||
* ShowFiles
|
||||
*
|
||||
* Support function for FileSelector
|
||||
****************************************************************************/
|
||||
|
||||
void ShowFiles( int offset, int selection )
|
||||
{
|
||||
int i,j;
|
||||
char text[45];
|
||||
|
||||
ClearScreen();
|
||||
|
||||
j = 0;
|
||||
for ( i = offset; i < ( offset + PAGESIZE ) && ( i < maxfiles ); i++ )
|
||||
{
|
||||
if ( filelist[i].flags ) {
|
||||
strcpy(text,"[");
|
||||
strncat(text, filelist[i].filename,43);
|
||||
strcat(text,"]");
|
||||
} else
|
||||
strncpy(text, filelist[i].filename, 45);
|
||||
|
||||
text[45]=0;
|
||||
|
||||
/*if ( j == ( selection - offset ) )
|
||||
writex( CentreTextPosition(text), ( j * font_height ) + 117,
|
||||
GetTextWidth(text), font_height, text, blit_lookup_inv );
|
||||
else
|
||||
writex( CentreTextPosition(text), ( j * font_height ) + 117,
|
||||
GetTextWidth(text), font_height, text, blit_lookup );*/
|
||||
|
||||
writex( CentreTextPosition(text), ( j * font_height ) + 130, GetTextWidth(text), font_height, text, j == ( selection - offset ) );
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
SetScreen();
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* FileSelector
|
||||
*
|
||||
* Let user select another ROM to load
|
||||
****************************************************************************/
|
||||
bool inSz = false;
|
||||
#define PADCAL 70
|
||||
|
||||
void FileSelector()
|
||||
{
|
||||
short p;
|
||||
short q = 0;
|
||||
signed char a;
|
||||
int haverom = 0;
|
||||
int redraw = 1;
|
||||
|
||||
while ( haverom == 0 )
|
||||
{
|
||||
if ( redraw ) ShowFiles( offset, selection );
|
||||
|
||||
redraw = 0;
|
||||
p = PAD_ButtonsDown(0);
|
||||
a = PAD_StickY(0);
|
||||
|
||||
if (p & PAD_BUTTON_B) return;
|
||||
|
||||
if ( ( p & PAD_BUTTON_DOWN ) || ( a < -PADCAL ) ){
|
||||
selection++;
|
||||
if (selection == maxfiles) selection = offset = 0;
|
||||
if ((selection - offset) >= PAGESIZE) offset += PAGESIZE;
|
||||
redraw = 1;
|
||||
} // End of down
|
||||
if ( ( p & PAD_BUTTON_UP ) || ( a > PADCAL ) )
|
||||
{
|
||||
selection--;
|
||||
if ( selection < 0 ){
|
||||
selection = maxfiles - 1;
|
||||
offset = selection - PAGESIZE + 1;
|
||||
}
|
||||
if (selection < offset) offset -= PAGESIZE;
|
||||
if ( offset < 0 ) offset = 0;
|
||||
redraw = 1;
|
||||
} // End of Up
|
||||
|
||||
if ( (p & PAD_BUTTON_LEFT) || (p & PAD_TRIGGER_L) )
|
||||
{
|
||||
/*** Go back a page ***/
|
||||
selection -= PAGESIZE;
|
||||
if ( selection < 0 ) {
|
||||
selection = maxfiles - 1;
|
||||
offset = selection-PAGESIZE + 1;
|
||||
}
|
||||
if ( selection < offset ) offset -= PAGESIZE;
|
||||
if ( offset < 0 ) offset = 0;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
if (( p & PAD_BUTTON_RIGHT ) || (p & PAD_TRIGGER_R))
|
||||
{
|
||||
/*** Go forward a page ***/
|
||||
selection += PAGESIZE;
|
||||
if ( selection > maxfiles - 1 ) selection = offset = 0;
|
||||
if ( ( selection - offset ) >= PAGESIZE ) offset += PAGESIZE;
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
if ( p & PAD_BUTTON_A ) {
|
||||
if ( filelist[selection].flags ) /*** This is directory ***/
|
||||
{
|
||||
if (UseSDCARD)
|
||||
{
|
||||
//if ( filelist[selection].filename[0] == 0x2e) {
|
||||
/* update current directory and set new entry list if directory has changed */
|
||||
int status = updateSDdirname();
|
||||
if (status == 1)
|
||||
{
|
||||
maxfiles = parseSDdirectory();
|
||||
if (!maxfiles)
|
||||
{
|
||||
WaitPrompt ("Error reading directory !");
|
||||
haverom = 1; // quit SD menu
|
||||
haveSDdir = 0; // reset everything at next access
|
||||
}
|
||||
}
|
||||
else if (status == -1)
|
||||
{
|
||||
haverom = 1; // quit SD menu
|
||||
haveSDdir = 0; // reset everything at next access
|
||||
}
|
||||
} else {
|
||||
rootdir = filelist[selection].offset;
|
||||
rootdirlength = filelist[selection].length;
|
||||
offset = selection = 0;
|
||||
maxfiles = parsedir();
|
||||
}
|
||||
}
|
||||
else if(selection == 0 && inSz == true)
|
||||
{
|
||||
rootdir = filelist[1].offset;
|
||||
rootdirlength = filelist[1].length;
|
||||
offset = 0;
|
||||
maxfiles = parsedir();
|
||||
inSz = false;
|
||||
SzClose();
|
||||
}
|
||||
else if(inSz == false && SzDvdIsArchive(filelist[selection].offset) == SZ_OK)
|
||||
{
|
||||
// parse the 7zip file
|
||||
SzParse();
|
||||
if(SzRes == SZ_OK)
|
||||
{
|
||||
inSz = true;
|
||||
offset = selection = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SzDisplayError(SzRes);
|
||||
}
|
||||
}
|
||||
else if(inSz == true)
|
||||
{
|
||||
// extract the selected ROM from the 7zip file to the buffer
|
||||
if(SzExtractROM(filelist[selection].offset, nesromptr) == true)
|
||||
{
|
||||
haverom = 1;
|
||||
inSz = false;
|
||||
|
||||
// go one directory up
|
||||
rootdir = filelist[1].offset;
|
||||
rootdirlength = filelist[1].length;
|
||||
offset = selection = 0;
|
||||
maxfiles = parsedir();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rootdir = filelist[selection].offset;
|
||||
rootdirlength = filelist[selection].length;
|
||||
// Now load the DVD file to it's offset
|
||||
LoadDVDFile(nesromptr);
|
||||
haverom = 1;
|
||||
}
|
||||
redraw = 1;
|
||||
}
|
||||
/*if ( p & PAD_BUTTON_B ) {
|
||||
if ( cdfiles[1].filename[0] == 0x2e && cdfiles[1].filename[1] == 0x2e && cdfiles[1].flags ) {
|
||||
if (UseSDCARD) {
|
||||
char fname[SDCARD_MAX_PATH_LEN];
|
||||
int pathpos = strlen(cdfiles[1].sdcardpath);
|
||||
while (pathpos > 6) {
|
||||
if (cdfiles[1].sdcardpath[pathpos] == '\\') break;
|
||||
pathpos--;
|
||||
}
|
||||
if (pathpos < 7) {pathpos = 16; cdfiles[1].sdcardpath[pathpos-3] = '\\'; cdfiles[1].sdcardpath[pathpos-2] = '.'; cdfiles[1].sdcardpath[pathpos-1] = '.'; } // handle root case
|
||||
strncpy(fname, cdfiles[1].sdcardpath, pathpos);
|
||||
fname[pathpos] = 0;
|
||||
offset = selection = 0;
|
||||
maxfiles = parse_sdcard_dir(fname);
|
||||
}
|
||||
else if(inSz == true)
|
||||
{
|
||||
rootdir = cdfiles[1].offset;
|
||||
rootdirlength = cdfiles[1].length;
|
||||
offset = selection = 0;
|
||||
maxfiles = parsedir();
|
||||
inSz = false;
|
||||
SzClose();
|
||||
}
|
||||
else {
|
||||
rootdir = cdfiles[1].offset;
|
||||
rootdirlength = cdfiles[1].length;
|
||||
offset = selection = 0;
|
||||
maxfiles = parsedir();
|
||||
}
|
||||
redraw = 1;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* LoadDVDFile
|
||||
****************************************************************************/
|
||||
int LoadDVDFile( unsigned char *buffer )
|
||||
{
|
||||
u64 offset;
|
||||
int blocks;
|
||||
int i;
|
||||
u64 discoffset;
|
||||
|
||||
/*** SDCard Addition ***/
|
||||
if (UseSDCARD) GetSDInfo ();
|
||||
if (rootdirlength == 0) return 0;
|
||||
|
||||
/*** How many 2k blocks to read ***/
|
||||
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() == false )
|
||||
{
|
||||
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 unzipDVDFile( buffer, discoffset, rootdirlength);
|
||||
}
|
||||
if (UseSDCARD) SDCARD_CloseFile (filehandle);
|
||||
|
||||
return rootdirlength;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* OpenDVD
|
||||
*
|
||||
* This function performs the swap task for softmodders.
|
||||
* For Viper/Qoob users, sector 0 is read, and if it contains all nulls
|
||||
* an ISO disc is assumed.
|
||||
****************************************************************************/
|
||||
static int havedir = 0;
|
||||
|
||||
int OpenDVD()
|
||||
{
|
||||
|
||||
int i, j;
|
||||
int driveid;//char debug[128];
|
||||
|
||||
haveSDdir = 0;
|
||||
|
||||
/*** Get Drive Type ***/
|
||||
dvd_inquiry();
|
||||
driveid = (int)inquiry[2];
|
||||
|
||||
/*** Make sure it's one I now about ***/
|
||||
if ( ( driveid != 4 ) && ( driveid != 6 ) && ( driveid != 8 ) ) {
|
||||
/*sprintf(debug, "Unknown drive id! (%d) ... Halted", driveid);
|
||||
WaitPrompt(debug);
|
||||
return 0;*/
|
||||
// if the driveid isn't 4, 6 or 8 we are running on a Wii
|
||||
isWii = true;
|
||||
}
|
||||
|
||||
memset(&readbuffer, 0x80, 2048);
|
||||
dvd_read(&readbuffer, 2048,0);
|
||||
|
||||
for ( i = j = 0; i < 2048; i++ )
|
||||
j += readbuffer[i];
|
||||
|
||||
if ( j ) {
|
||||
if ( IsXenoGCImage( (char *)&readbuffer ) )
|
||||
j = 0;
|
||||
}
|
||||
|
||||
/*** Was there any data in sector 0 ? ***/
|
||||
// do not do all this stuff here if we are running on a Wii
|
||||
// because the modchip will take care of this.
|
||||
havedir = offset = selection = 0;
|
||||
if (isWii == false && j ) {
|
||||
/*** Yes - so start swap sequence ***/
|
||||
ShowAction("Stopping DVD ... Wait");
|
||||
dvd_motor_off();
|
||||
WaitPrompt("Insert an ISO 9660 DVD");
|
||||
ShowAction("Resetting DVD ... Wait");
|
||||
dvd_reset();
|
||||
|
||||
/*** Now the fun begins
|
||||
This is essentially the cactus implementation from gc-linux
|
||||
sequence of events. There may well be a better way to do it
|
||||
from inside libogc, but no documentation is available. ***/
|
||||
|
||||
/*** Reset the DVD Drive, to enable the firmware update ***/
|
||||
/*** Reset
|
||||
Unlock
|
||||
SendCode
|
||||
Enable Extension
|
||||
Unlock
|
||||
Motor On
|
||||
SetStatus
|
||||
ReadID ***/
|
||||
|
||||
ShowAction("Sending Drive Code ... Wait");
|
||||
dvd_unlock();
|
||||
SendDriveCode(driveid);
|
||||
dvd_extension();
|
||||
dvd_unlock();
|
||||
ShowAction("Mounting DVD ... Wait");
|
||||
dvd_motor_on_extra();
|
||||
dvd_setstatus();
|
||||
dvd_read_id((void *)0x80000000);
|
||||
}
|
||||
|
||||
/*** At this point I should have an unlocked DVD ... so let's do the ISO ***/
|
||||
if ( havedir != 1 ) {
|
||||
if ( IsPVD() )
|
||||
{
|
||||
/*** Have a valid PVD, so start reading directory entries ***/
|
||||
maxfiles = parsedir();
|
||||
if ( maxfiles ) {
|
||||
offset = selection = 0;
|
||||
FileSelector();
|
||||
havedir = 1;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
FileSelector();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int OpenSD ()
|
||||
{
|
||||
UseSDCARD = 1;
|
||||
char msg[128];
|
||||
|
||||
if (haveSDdir == 0)
|
||||
{
|
||||
/* don't mess with DVD entries */
|
||||
havedir = 0;
|
||||
|
||||
/* Reset SDCARD root directory */
|
||||
sprintf(rootSDdir,"dev%d:\\fceu\\roms",choosenSDSlot);
|
||||
//sprintf(rootSDdir,"dev0:\\fceu\\roms");
|
||||
|
||||
/* Parse initial root directory and get entries list */
|
||||
ShowAction("Reading Directory ...");
|
||||
if ((maxfiles = parseSDdirectory ()))
|
||||
{
|
||||
sprintf (msg, "Found %d entries", maxfiles);
|
||||
WaitPrompt (msg);
|
||||
/* Select an entry */
|
||||
FileSelector ();
|
||||
|
||||
/* memorize last entries list, actual root directory and selection for next access */
|
||||
haveSDdir = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no entries found */
|
||||
sprintf (msg, "Error reading dev%d:\\fceu\\roms", choosenSDSlot);
|
||||
WaitPrompt (msg);
|
||||
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);
|
||||
}
|
14
source/drivers/gamecube/gcdvd.h
Normal file
14
source/drivers/gamecube/gcdvd.h
Normal file
@ -0,0 +1,14 @@
|
||||
#include <sdcard.h>
|
||||
|
||||
#define MAXJOLIET 256
|
||||
#define MAXFILES 1000
|
||||
|
||||
typedef struct {
|
||||
char filename[MAXJOLIET];
|
||||
char sdcardpath[SDCARD_MAX_PATH_LEN];
|
||||
u64 offset;
|
||||
unsigned int length;
|
||||
char flags;
|
||||
}FILEENTRIES;
|
||||
|
||||
extern FILEENTRIES filelist[MAXFILES];
|
471
source/drivers/gamecube/gcvideo.c
Normal file
471
source/drivers/gamecube/gcvideo.c
Normal file
@ -0,0 +1,471 @@
|
||||
/****************************************************************************
|
||||
* GCVideo
|
||||
*
|
||||
* This module contains all GameCube video routines
|
||||
****************************************************************************/
|
||||
|
||||
#include <gccore.h>
|
||||
#include <ogcsys.h>
|
||||
#include <string.h>
|
||||
#include "../../iplfont/iplfont.h"
|
||||
#include "nesback.h"
|
||||
|
||||
//#define FORCE_PAL50 1
|
||||
|
||||
#define TEX_WIDTH 256
|
||||
#define TEX_HEIGHT 512
|
||||
#define WIDTH 640
|
||||
#define DEFAULT_FIFO_SIZE 256 * 1024
|
||||
|
||||
unsigned int *xfb[2]; /*** Framebuffer - used throughout ***/
|
||||
GXRModeObj *vmode;
|
||||
|
||||
/*** Backdrop ***/
|
||||
extern unsigned char backdrop[614400];
|
||||
|
||||
/*** Need something to hold the PC palette ***/
|
||||
struct pcpal {
|
||||
unsigned char r;
|
||||
unsigned char g;
|
||||
unsigned char b;
|
||||
} pcpalette[256];
|
||||
|
||||
unsigned int gcpalette[256]; /*** Much simpler GC palette ***/
|
||||
unsigned short rgb565[256]; /*** Texture map palette ***/
|
||||
static unsigned char gp_fifo[DEFAULT_FIFO_SIZE] __attribute__((__aligned__(32)));
|
||||
static unsigned char texturemem[ TEX_WIDTH * TEX_HEIGHT * 2 ] __attribute__((__aligned__(32)));
|
||||
GXTexObj texobj;
|
||||
GXColor background = {0, 0, 0, 0xff};
|
||||
static Mtx projectionMatrix,modelViewMatrix;
|
||||
void CheesyScale( unsigned char *XBuf );
|
||||
int whichfb = 0;
|
||||
extern int font_height;
|
||||
int copynow = GX_FALSE;
|
||||
|
||||
extern int font_width;
|
||||
|
||||
int GetTextWidth( char *text )
|
||||
{
|
||||
unsigned int i, w = 0;
|
||||
|
||||
for ( i = 0; i < strlen(text); i++ )
|
||||
w += font_width;
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
int CentreTextPosition( char *text )
|
||||
{
|
||||
return ( ( 640 - GetTextWidth(text) ) >> 1 );
|
||||
}
|
||||
|
||||
void WriteCentre( int y, char *text )
|
||||
{
|
||||
write_font( CentreTextPosition(text), y, text);
|
||||
}
|
||||
|
||||
void WaitPrompt( char *msg )
|
||||
{
|
||||
int quit = 0;
|
||||
|
||||
while ( PAD_ButtonsDown(0) & PAD_BUTTON_A ) {} ;
|
||||
|
||||
while( !(PAD_ButtonsDown(0) & PAD_BUTTON_A ) && (quit == 0 ))
|
||||
{
|
||||
ClearScreen();
|
||||
|
||||
WriteCentre( 220, msg);
|
||||
WriteCentre( 220 + font_height, "Press A to Continue");
|
||||
|
||||
if ( PAD_ButtonsDown(0) & PAD_BUTTON_A )
|
||||
quit = 1;
|
||||
|
||||
SetScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void ShowAction( char *msg )
|
||||
{
|
||||
memcpy (xfb[whichfb], &backdrop, 1280 * 480);
|
||||
/*ClearScreen();*/
|
||||
WriteCentre( 220 + ( font_height >> 1), msg);
|
||||
SetScreen();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* GX Chip Copy to XFB
|
||||
****************************************************************************/
|
||||
static void copy_to_xfb()
|
||||
{
|
||||
if ( copynow == GX_TRUE ) {
|
||||
GX_CopyDisp(xfb[whichfb],GX_TRUE);
|
||||
GX_Flush();
|
||||
copynow = GX_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Initialise the GX
|
||||
****************************************************************************/
|
||||
|
||||
void StartGX()
|
||||
{
|
||||
/*** Clear out FIFO area ***/
|
||||
memset(&gp_fifo, 0, DEFAULT_FIFO_SIZE);
|
||||
|
||||
/*** Initialise GX ***/
|
||||
GX_Init(&gp_fifo, DEFAULT_FIFO_SIZE);
|
||||
GX_SetCopyClear(background, 0x00ffffff);
|
||||
|
||||
/*** Additions from libogc ***/
|
||||
GX_SetViewport(10,0,vmode->fbWidth,vmode->efbHeight,0,1);
|
||||
GX_SetDispCopyYScale((f32)vmode->xfbHeight/(f32)vmode->efbHeight);
|
||||
GX_SetDispCopySrc(0,0,vmode->fbWidth,vmode->efbHeight);
|
||||
GX_SetDispCopyDst(vmode->fbWidth,vmode->xfbHeight);
|
||||
|
||||
GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
|
||||
|
||||
GX_SetCullMode(GX_CULL_NONE);
|
||||
GX_SetZMode(GX_FALSE,GX_ALWAYS,GX_TRUE);
|
||||
GX_SetColorUpdate(GX_TRUE);
|
||||
GX_CopyDisp(xfb[whichfb],GX_TRUE);
|
||||
|
||||
/*** Additions from ogc spaceship ***/
|
||||
GX_SetDispCopyGamma(GX_GM_1_0);
|
||||
|
||||
GX_ClearVtxDesc();
|
||||
GX_SetVtxAttrFmt(GX_VTXFMT0,GX_VA_POS,GX_POS_XYZ,GX_F32,0);
|
||||
GX_SetVtxAttrFmt(GX_VTXFMT0,GX_VA_TEX0,GX_TEX_ST,GX_F32,0);
|
||||
GX_SetVtxDesc(GX_VA_POS,GX_DIRECT);
|
||||
GX_SetVtxDesc(GX_VA_TEX0,GX_DIRECT);
|
||||
|
||||
GX_SetNumChans(0); /* default, color = vertex color */
|
||||
GX_SetNumTexGens(1);
|
||||
GX_SetTexCoordGen(GX_TEXCOORD0,GX_TG_MTX2x4,GX_TG_TEX0,GX_IDENTITY);
|
||||
GX_SetTevOrder(GX_TEVSTAGE0,GX_TEXCOORD0,GX_TEXMAP0,GX_COLORNULL);
|
||||
GX_SetTevOp(GX_TEVSTAGE0,GX_REPLACE);
|
||||
|
||||
GX_InitTexObj(&texobj,&texturemem,TEX_WIDTH,TEX_HEIGHT,
|
||||
GX_TF_RGB565,GX_REPEAT,GX_REPEAT,GX_FALSE);
|
||||
|
||||
DCFlushRange(&texturemem, TEX_WIDTH * TEX_HEIGHT * 2);
|
||||
GX_LoadTexObj(&texobj,GX_TEXMAP0);
|
||||
GX_InvalidateTexAll();
|
||||
|
||||
/* load projection matrix */
|
||||
/*** Setting Height to 648 get's it right ? ***/
|
||||
guOrtho(projectionMatrix,10,610,640,0,-1,1);
|
||||
GX_LoadProjectionMtx(projectionMatrix,GX_ORTHOGRAPHIC);
|
||||
|
||||
/* load model view matrix */
|
||||
c_guMtxScale(modelViewMatrix,660,640,1);
|
||||
GX_LoadPosMtxImm(modelViewMatrix,GX_PNMTX0);
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* GXDraw
|
||||
*
|
||||
* Using the texture map draw with quads
|
||||
****************************************************************************/
|
||||
void GXDraw( unsigned char *XBuf )
|
||||
{
|
||||
|
||||
float gs = 1.0;
|
||||
float gt = 1.0;
|
||||
int width, height,t,xb;
|
||||
unsigned short *texture;
|
||||
|
||||
memset(&texturemem, 0, TEX_WIDTH * TEX_HEIGHT * 2);
|
||||
texture = ( unsigned short *)&texturemem[ 16 * TEX_WIDTH ];
|
||||
|
||||
/*** Now draw the texture ***/
|
||||
t = 0;
|
||||
for ( height = 0; height < 120; height++ )
|
||||
{
|
||||
xb = height * 512;
|
||||
for( width = 256; width > 0; width -= 4 )
|
||||
{
|
||||
/*** Row one ***/
|
||||
texture[t++] = rgb565[XBuf[xb + width-1]];
|
||||
texture[t++] = rgb565[XBuf[xb + width-2]];
|
||||
texture[t++] = rgb565[XBuf[xb + width-3]];
|
||||
texture[t++] = rgb565[XBuf[xb + width-4]];
|
||||
|
||||
/*** Row three ***/
|
||||
texture[t++] = rgb565[XBuf[xb + width-1]];
|
||||
texture[t++] = rgb565[XBuf[xb + width-2]];
|
||||
texture[t++] = rgb565[XBuf[xb + width-3]];
|
||||
texture[t++] = rgb565[XBuf[xb + width-4]];
|
||||
|
||||
/*** Row one ***/
|
||||
texture[t++] = rgb565[XBuf[xb + 256 + width-1]];
|
||||
texture[t++] = rgb565[XBuf[xb + 256 + width-2]];
|
||||
texture[t++] = rgb565[XBuf[xb + 256 + width-3]];
|
||||
texture[t++] = rgb565[XBuf[xb + 256 + width-4]];
|
||||
|
||||
/*** Row three ***/
|
||||
texture[t++] = rgb565[XBuf[xb + 256 + width-1]];
|
||||
texture[t++] = rgb565[XBuf[xb + 256 + width-2]];
|
||||
texture[t++] = rgb565[XBuf[xb + 256 + width-3]];
|
||||
texture[t++] = rgb565[XBuf[xb + 256 + width-4]];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DCFlushRange(&texturemem, TEX_WIDTH * TEX_HEIGHT * 2);
|
||||
|
||||
/* setup GX */
|
||||
GX_InvalidateTexAll();
|
||||
|
||||
// ok render the triangles now
|
||||
GX_Begin(GX_QUADS,GX_VTXFMT0,4);
|
||||
{
|
||||
GX_Position3f32(0,0,0);
|
||||
GX_TexCoord2f32(0,0);
|
||||
|
||||
GX_Position3f32(0,1,0);
|
||||
GX_TexCoord2f32(0,gt);
|
||||
|
||||
GX_Position3f32(1,1,0);
|
||||
GX_TexCoord2f32(gs,gt);
|
||||
|
||||
GX_Position3f32(1,0,0);
|
||||
GX_TexCoord2f32(gs,0);
|
||||
}
|
||||
GX_End();
|
||||
GX_DrawDone();
|
||||
copynow = GX_TRUE;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* initDisplay
|
||||
*
|
||||
* It should be noted that this function forces the system to use a
|
||||
* 640x480 viewport for either NTSC or PAL.
|
||||
*
|
||||
* Helps keep the rendering at 2x sweet
|
||||
****************************************************************************/
|
||||
void initDisplay()
|
||||
{
|
||||
|
||||
/*** Start VIDEO Subsystem ***/
|
||||
VIDEO_Init();
|
||||
|
||||
/*** Determine display mode
|
||||
NOTE: Force 60Hz 640x480 for PAL or NTSC ***/
|
||||
|
||||
/* switch(VIDEO_GetCurrentTvMode())
|
||||
{
|
||||
case VI_NTSC:
|
||||
vmode = &TVNtsc480IntDf;
|
||||
break;
|
||||
case VI_PAL:
|
||||
case VI_MPAL:
|
||||
vmode = &TVMpal480IntDf;
|
||||
break;
|
||||
default:
|
||||
vmode = &TVNtsc480IntDf;
|
||||
break;
|
||||
}*/
|
||||
//vmode = &TVPal528IntDf;
|
||||
|
||||
// works for NTSC and PAL on GC and Wii :)
|
||||
vmode = &TVNtsc480IntDf;
|
||||
|
||||
xfb[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(vmode));
|
||||
xfb[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(vmode));
|
||||
/*init_font();*/
|
||||
|
||||
VIDEO_Configure(vmode);
|
||||
VIDEO_SetNextFramebuffer(xfb[0]);
|
||||
VIDEO_SetBlack(FALSE);
|
||||
VIDEO_Flush();
|
||||
VIDEO_WaitVSync();
|
||||
|
||||
if(vmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||
VIDEO_SetPostRetraceCallback(PAD_ScanPads);
|
||||
/*** Setup a console - guard against spurious printf ***/
|
||||
VIDEO_SetPreRetraceCallback(copy_to_xfb);
|
||||
VIDEO_SetNextFramebuffer(xfb[0]);
|
||||
|
||||
PAD_Init();
|
||||
StartGX();
|
||||
DVD_Init();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* RenderFrame
|
||||
*
|
||||
* Render a single frame at 2x zoom
|
||||
****************************************************************************/
|
||||
#define NESWIDTH 256
|
||||
#define NESHEIGHT 240
|
||||
void RenderFrame( char *XBuf, int style )
|
||||
{
|
||||
|
||||
int gcdispOffset = 32; /*** Offset to centre on screen ***/
|
||||
int w,h;
|
||||
int c,i;
|
||||
|
||||
whichfb ^= 1;
|
||||
|
||||
switch( style ) {
|
||||
|
||||
case 0 :
|
||||
VIDEO_ClearFrameBuffer( vmode, xfb[whichfb], COLOR_BLACK);
|
||||
|
||||
/*** Simply go through each row ***/
|
||||
for( h = 0; h < NESHEIGHT; h++ )
|
||||
{
|
||||
for( w = 0; w < NESWIDTH; w++ )
|
||||
{
|
||||
c = ( h << 8 ) + w;
|
||||
i = gcdispOffset + w;
|
||||
/*** Fast Zoom - Repeat each row, use 1 Xbuf == 2 GC
|
||||
To speed up more, use indexed palette array ***/
|
||||
|
||||
xfb[whichfb][i] = gcpalette[ (unsigned char)XBuf[ c ] ];
|
||||
xfb[whichfb][i + 320] = gcpalette[ (unsigned char)XBuf[ c ] ];
|
||||
}
|
||||
gcdispOffset += 640;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
CheesyScale( XBuf );
|
||||
break;
|
||||
|
||||
case 2:
|
||||
GXDraw( XBuf );
|
||||
break;
|
||||
}
|
||||
|
||||
/*** Now resync with VSync ***/
|
||||
VIDEO_SetNextFramebuffer(xfb[whichfb]);
|
||||
VIDEO_Flush();
|
||||
VIDEO_WaitVSync();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* rgbcolor
|
||||
*
|
||||
* Support routine for gcpalette
|
||||
****************************************************************************/
|
||||
|
||||
unsigned int rgbcolor( unsigned char r1, unsigned char g1, unsigned char b1,
|
||||
unsigned char r2, unsigned char g2, unsigned char b2)
|
||||
{
|
||||
int y1,cb1,cr1,y2,cb2,cr2,cb,cr;
|
||||
|
||||
y1=(299*r1+587*g1+114*b1)/1000;
|
||||
cb1=(-16874*r1-33126*g1+50000*b1+12800000)/100000;
|
||||
cr1=(50000*r1-41869*g1-8131*b1+12800000)/100000;
|
||||
|
||||
y2=(299*r2+587*g2+114*b2)/1000;
|
||||
cb2=(-16874*r2-33126*g2+50000*b2+12800000)/100000;
|
||||
cr2=(50000*r2-41869*g2-8131*b2+12800000)/100000;
|
||||
|
||||
cb=(cb1+cb2) >> 1;
|
||||
cr=(cr1+cr2) >> 1;
|
||||
|
||||
return ( (y1 << 24) | (cb << 16) | (y2 << 8) | cr );
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* SetPalette
|
||||
*
|
||||
* A shadow copy of the palette is maintained, in case the NES Emu kernel
|
||||
* requests a copy.
|
||||
****************************************************************************/
|
||||
void FCEUD_SetPalette(unsigned char index, unsigned char r, unsigned char g, unsigned char b)
|
||||
{
|
||||
/*** Make PC compatible copy ***/
|
||||
pcpalette[index].r = r;
|
||||
pcpalette[index].g = g;
|
||||
pcpalette[index].b = b;
|
||||
|
||||
/*** Generate Gamecube palette ***/
|
||||
gcpalette[index] = rgbcolor(r,g,b,r,g,b);
|
||||
|
||||
/*** Generate RGB565 texture palette ***/
|
||||
rgb565[index] = ( ( r & 0xf8 ) << 8 ) |
|
||||
( ( g & 0xfc ) << 3 ) |
|
||||
( ( b & 0xf8 ) >> 3 );
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* GetPalette
|
||||
****************************************************************************/
|
||||
void FCEUD_GetPalette(unsigned char i, unsigned char *r, unsigned char *g, unsigned char *b)
|
||||
{
|
||||
*r = pcpalette[i].r;
|
||||
*g = pcpalette[i].g;
|
||||
*b = pcpalette[i].b;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* NES Cheesy Scaler
|
||||
*
|
||||
* This scaler simply attempts to correct the 1.25 aspect by
|
||||
* stretching the initial 256 pixels to 320.
|
||||
* The standard 2x2 scaler can then be applied
|
||||
****************************************************************************/
|
||||
void CheesyScale( unsigned char *XBuf )
|
||||
{
|
||||
|
||||
static int newrow[320]; /*** New cheesy row ***/
|
||||
unsigned int cheesypal[256]; /*** Enhanced Cheesy Palette ***/
|
||||
int i,j,c,p = 0;
|
||||
unsigned char p1,p2;
|
||||
unsigned int ofs, gcdispOffset = 0;
|
||||
int h, n, nw;
|
||||
|
||||
/*** Stretch ***/
|
||||
for ( h = 0; h < NESHEIGHT; h++ )
|
||||
{
|
||||
j = c = p = 0;
|
||||
for ( i = 0; i < NESWIDTH; i++ )
|
||||
{
|
||||
|
||||
/*** Every fifth pixel is stretched by adding
|
||||
the mid colour range ***/
|
||||
n = ( h << 8 ) + i;
|
||||
newrow[j++] = XBuf[ n ];
|
||||
c++;
|
||||
if ( c == 4 )
|
||||
{ /*** Done 4 pixels, so add the fifth ***/
|
||||
p1 = XBuf[n];
|
||||
p2 = XBuf[n+1];
|
||||
cheesypal[p] = rgbcolor( pcpalette[p1].r, pcpalette[p1].g, pcpalette[p1].b,
|
||||
pcpalette[p2].r, pcpalette[p2].g, pcpalette[p2].b );
|
||||
newrow[j++] = 0x8000 + p;
|
||||
p++;
|
||||
c = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*** Now update the screen display with the new colours ***/
|
||||
ofs = gcdispOffset;
|
||||
for ( nw = 0; nw < 320; nw++ )
|
||||
{
|
||||
if ( newrow[nw] & 0x8000 ) {
|
||||
xfb[whichfb][ofs + nw] = cheesypal[newrow[nw] & 0xff ];
|
||||
xfb[whichfb][ofs + 320 + nw] = cheesypal[newrow[nw] & 0xff];
|
||||
}
|
||||
else
|
||||
{
|
||||
xfb[whichfb][ofs + nw] = gcpalette[ newrow[nw] ];
|
||||
xfb[whichfb][ofs + nw + 320] = gcpalette[ newrow[nw] ];
|
||||
}
|
||||
}
|
||||
|
||||
gcdispOffset += 640;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
23
source/drivers/gamecube/gcxenogc.c
Normal file
23
source/drivers/gamecube/gcxenogc.c
Normal file
@ -0,0 +1,23 @@
|
||||
/*****************************************************************************
|
||||
* Gamecube XenoGC Identifier
|
||||
*
|
||||
* Functions to determine if the DVD is in fact a XenoGC boot disc
|
||||
*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int IsXenoGCImage( char *buffer )
|
||||
{
|
||||
|
||||
/*** All Xeno GC Homebrew Boot have id GBLPGL ***/
|
||||
if ( memcmp( buffer, "GBLPGL", 6 ) )
|
||||
return 0;
|
||||
|
||||
if ( memcmp( &buffer[0x20], "GAMECUBE \"EL TORITO\" BOOTLOADER", 31 ) )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
184
source/drivers/gamecube/gczip.c
Normal file
184
source/drivers/gamecube/gczip.c
Normal file
@ -0,0 +1,184 @@
|
||||
/****************************************************************************
|
||||
* GC Zip Extension
|
||||
*
|
||||
* GC DVD Zip File Loader.
|
||||
*
|
||||
* The idea here is not to support every zip file on the planet!
|
||||
* The unzip routine will simply unzip the first file in the zip archive.
|
||||
*
|
||||
* For maximum compression, I'd recommend using 7Zip,
|
||||
* 7za a -tzip -mx=9 rom.zip rom.smc
|
||||
****************************************************************************/
|
||||
|
||||
#include <gccore.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
#include <sdcard.h>
|
||||
|
||||
extern sd_file *filehandle;
|
||||
extern int UseSDCARD;
|
||||
|
||||
extern void ShowAction( char *msg );
|
||||
extern void WaitPrompt( char *msg );
|
||||
|
||||
extern unsigned char readbuffer[2048];
|
||||
extern unsigned int dvd_read(void *dst, unsigned int len, unsigned int offset);
|
||||
|
||||
#define ZIPCHUNK 2048
|
||||
|
||||
/*** PKWare Zip Header ***/
|
||||
#define PKZIPID 0x504b0304
|
||||
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;
|
||||
|
||||
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
|
||||
*
|
||||
* This ONLY check the zipid, so any file which starts with the correct
|
||||
* 4 bytes will be treated as a zip file.
|
||||
*
|
||||
* It interrogate the first 4 bytes of the common readbuffer, so make sure
|
||||
* it is populated before calling.
|
||||
****************************************************************************/
|
||||
|
||||
bool isZipFile()
|
||||
{
|
||||
u32 check;
|
||||
|
||||
memcpy(&check, &readbuffer, 4);
|
||||
return ( check == PKZIPID ) ? true : false;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* unzipDVDFile
|
||||
*
|
||||
* This loads the zip file in small 2k chunks, and decompresses to the
|
||||
* output buffer.
|
||||
*
|
||||
* Unzip terminates on Z_END_STREAM.
|
||||
***************************************************************************/
|
||||
int unzipDVDFile( unsigned char *outbuffer,
|
||||
unsigned int discoffset, unsigned 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 debug[128];
|
||||
|
||||
/*** Copy PKZip header to local, used as info ***/
|
||||
memcpy(&pkzip, &readbuffer, sizeof(PKZIPHEADER));
|
||||
|
||||
sprintf(debug, "Unzipping %d bytes ... Wait", FLIP32(pkzip.uncompressedSize));
|
||||
ShowAction(debug);
|
||||
|
||||
/*** 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;
|
||||
|
||||
/*** No 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;
|
||||
}
|
||||
|
||||
|
1041
source/drivers/gamecube/info.b
Normal file
1041
source/drivers/gamecube/info.b
Normal file
File diff suppressed because it is too large
Load Diff
1074
source/drivers/gamecube/info.c
Normal file
1074
source/drivers/gamecube/info.c
Normal file
File diff suppressed because it is too large
Load Diff
133
source/drivers/gamecube/main.c
Normal file
133
source/drivers/gamecube/main.c
Normal file
@ -0,0 +1,133 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include "../../types.h"
|
||||
#include "common.h"
|
||||
|
||||
/* Some timing-related variables. */
|
||||
static int fullscreen=0;
|
||||
static int genie=0;
|
||||
static int palyo=0;
|
||||
|
||||
static volatile int nofocus=0;
|
||||
static volatile int userpause=0;
|
||||
|
||||
#define SO_FORCE8BIT 1
|
||||
#define SO_SECONDARY 2
|
||||
#define SO_GFOCUS 4
|
||||
#define SO_D16VOL 8
|
||||
|
||||
#define GOO_DISABLESS 1 /* Disable screen saver when game is loaded. */
|
||||
#define GOO_CONFIRMEXIT 2 /* Confirmation before exiting. */
|
||||
#define GOO_POWERRESET 4 /* Confirm on power/reset. */
|
||||
|
||||
static int soundvolume=100;
|
||||
static int soundquality=0;
|
||||
static int soundo;
|
||||
|
||||
int screenscaler = 2;
|
||||
|
||||
uint8 *xbsave=NULL;
|
||||
int eoptions=EO_BGRUN | EO_FORCEISCALE;
|
||||
|
||||
extern int RenderFrame( char *XBuf , int style);
|
||||
|
||||
extern int ConfigScreen();
|
||||
|
||||
extern void InitialiseSound();
|
||||
extern void initDisplay();
|
||||
extern void InitialisePads();
|
||||
extern int GetJoy();
|
||||
extern void GCMemROM();
|
||||
extern void PlaySound( void *Buf, int samples );
|
||||
long long basetime;
|
||||
|
||||
void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
initDisplay();
|
||||
InitialiseSound();
|
||||
SDCARD_Init ();
|
||||
|
||||
/*** Minimal Emulation Loop ***/
|
||||
if ( !FCEUI_Initialize() ) {
|
||||
printf("Ooops - unable to initialize system\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
palyo=0;
|
||||
FCEUI_SetVidSystem(palyo);
|
||||
genie&=1;
|
||||
FCEUI_SetGameGenie(genie);
|
||||
fullscreen&=1;
|
||||
soundo&=1;
|
||||
FCEUI_SetSoundVolume(soundvolume);
|
||||
FCEUI_SetSoundQuality(soundquality);
|
||||
|
||||
cleanSFMDATA();
|
||||
GCMemROM();
|
||||
|
||||
ConfigScreen();
|
||||
|
||||
while (1)
|
||||
{
|
||||
uint8 *gfx;
|
||||
int32 *sound;
|
||||
int32 ssize;
|
||||
|
||||
FCEUI_Emulate(&gfx, &sound, &ssize, 0);
|
||||
xbsave = gfx;
|
||||
FCEUD_Update(gfx, sound, ssize);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* FCEU Support Functions to be written
|
||||
****************************************************************************/
|
||||
/*** File Control ***/
|
||||
FILE *FCEUD_UTF8fopen(const char *n, const char *m)
|
||||
{
|
||||
return(fopen(n,m));
|
||||
}
|
||||
|
||||
/*** General Logging ***/
|
||||
void FCEUD_PrintError(char *s)
|
||||
{
|
||||
}
|
||||
|
||||
void FCEUD_Message(char *text)
|
||||
{
|
||||
}
|
||||
|
||||
/*** VIDEO ***/
|
||||
void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count)
|
||||
{
|
||||
|
||||
PlaySound(Buffer, Count);
|
||||
RenderFrame( XBuf, screenscaler );
|
||||
GetJoy(); /* Fix by Garglub. Thanks! */
|
||||
|
||||
}
|
||||
|
||||
/*** Netplay ***/
|
||||
int FCEUD_SendData(void *data, uint32 len)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int FCEUD_RecvData(void *data, uint32 len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FCEUD_NetworkClose(void)
|
||||
{
|
||||
}
|
||||
|
||||
void FCEUD_NetplayText(uint8 *text)
|
||||
{
|
||||
}
|
75
source/drivers/gamecube/memload.c
Normal file
75
source/drivers/gamecube/memload.c
Normal file
@ -0,0 +1,75 @@
|
||||
/****************************************************************************
|
||||
* NES Memory Load Game
|
||||
*
|
||||
* This performs the functions of LoadGame and iNESLoad from a single module
|
||||
* Helper function for GameCube injected ROMS
|
||||
****************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "../../types.h"
|
||||
/* Switch to asm for faster compilation
|
||||
*#include "../../roms/nesrom.h"
|
||||
*/
|
||||
#include "../../git.h"
|
||||
#include "../../driver.h"
|
||||
#include "../../palette.h"
|
||||
#include "../../fceu.h"
|
||||
#include "../../sound.h"
|
||||
|
||||
unsigned char *nesromptr;
|
||||
extern FCEUGI *FCEUGameInfo;
|
||||
extern int iNESMemLoad( char *rom );
|
||||
extern void InitialisePads();
|
||||
|
||||
extern unsigned char nesrom[];
|
||||
|
||||
#define SAMPLERATE 48000
|
||||
|
||||
int GCMemROM()
|
||||
{
|
||||
|
||||
nesromptr = &nesrom[0];
|
||||
|
||||
ResetGameLoaded();
|
||||
|
||||
/*** Allocate and clear GameInfo ***/
|
||||
FCEUGameInfo = malloc(sizeof(FCEUGI));
|
||||
memset(FCEUGameInfo, 0, sizeof(FCEUGI));
|
||||
|
||||
/*** Set some default values ***/
|
||||
FCEUGameInfo->soundchan = 1;
|
||||
FCEUGameInfo->soundrate = SAMPLERATE;
|
||||
FCEUGameInfo->name=0;
|
||||
FCEUGameInfo->type=GIT_CART;
|
||||
FCEUGameInfo->vidsys=GIV_USER;
|
||||
FCEUGameInfo->input[0]=FCEUGameInfo->input[1]=-1;
|
||||
FCEUGameInfo->inputfc=-1;
|
||||
FCEUGameInfo->cspecial=0;
|
||||
|
||||
/*** Set internal sound information ***/
|
||||
FCEUI_Sound(SAMPLERATE);
|
||||
FCEUI_SetSoundQuality(0);
|
||||
FCEUI_SetSoundVolume(100);
|
||||
FCEUI_SetLowPass(0);
|
||||
|
||||
InitialisePads();
|
||||
|
||||
if ( iNESMemLoad( nesromptr ) )
|
||||
{
|
||||
FCEU_ResetVidSys();
|
||||
PowerNES();
|
||||
FCEU_ResetPalette();
|
||||
FCEU_ResetMessages(); // Save state, status messages, etc.
|
||||
SetSoundVariables();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Bad cartridge!");
|
||||
while(1) {};
|
||||
}
|
||||
|
||||
return 0;;
|
||||
}
|
||||
|
547
source/drivers/gamecube/memstate.c
Normal file
547
source/drivers/gamecube/memstate.c
Normal file
@ -0,0 +1,547 @@
|
||||
/****************************************************************************
|
||||
* Memory Based Load/Save State Manager
|
||||
*
|
||||
* These are simply the state routines, brought together as GCxxxxx
|
||||
* The original file I/O is replaced with Memory Read/Writes to the
|
||||
* statebuffer below
|
||||
****************************************************************************/
|
||||
#include <gccore.h>
|
||||
#include <string.h>
|
||||
#include <sdcard.h>
|
||||
#include "../../types.h"
|
||||
#include "../../state.h"
|
||||
#include "saveicon.h"
|
||||
|
||||
#define SAVEDIR "fceu\\saves"
|
||||
|
||||
/*** External functions ***/
|
||||
extern void FCEUPPU_SaveState(void);
|
||||
extern void FCEUSND_SaveState(void);
|
||||
extern void WaitPrompt( char *text );
|
||||
extern void FlipByteOrder(uint8 *src, uint32 count);
|
||||
extern void ShowAction( char *text );
|
||||
|
||||
/*** External save structures ***/
|
||||
extern SFORMAT SFCPU[];
|
||||
extern SFORMAT SFCPUC[];
|
||||
extern SFORMAT FCEUPPU_STATEINFO[];
|
||||
extern SFORMAT FCEUCTRL_STATEINFO[];
|
||||
extern SFORMAT FCEUSND_STATEINFO[];
|
||||
extern SFORMAT SFMDATA[64];
|
||||
extern u32 iNESGameCRC32;
|
||||
int CARDSLOT = CARD_SLOTA;
|
||||
|
||||
#define RLSB 0x80000000
|
||||
#define FILESIZEOFFSET 2116
|
||||
|
||||
unsigned char statebuffer[64 * 1024] ATTRIBUTE_ALIGN(32); /*** Never had one this big ! ***/
|
||||
int sboffset; /*** Used as a basic fileptr ***/
|
||||
int mcversion = 0x981211;
|
||||
|
||||
static u8 SysArea[CARD_WORKAREA] ATTRIBUTE_ALIGN(32);
|
||||
|
||||
/****************************************************************************
|
||||
* Memory based file functions
|
||||
****************************************************************************/
|
||||
|
||||
/*** Open a file ***/
|
||||
void memopen()
|
||||
{
|
||||
sboffset = 0;
|
||||
memset(&statebuffer[0], 0, sizeof(statebuffer));
|
||||
}
|
||||
|
||||
/*** Close a file ***/
|
||||
void memclose()
|
||||
{
|
||||
sboffset = 0;
|
||||
}
|
||||
|
||||
/*** Write to the file ***/
|
||||
void memfwrite( void *buffer, int len )
|
||||
{
|
||||
if ( (sboffset + len ) > sizeof(statebuffer))
|
||||
WaitPrompt("Buffer Exceeded");
|
||||
|
||||
if ( len > 0 ) {
|
||||
memcpy(&statebuffer[sboffset], buffer, len );
|
||||
sboffset += len;
|
||||
}
|
||||
}
|
||||
|
||||
/*** Read from a file ***/
|
||||
void memfread( void *buffer, int len )
|
||||
{
|
||||
|
||||
if ( ( sboffset + len ) > sizeof(statebuffer))
|
||||
WaitPrompt("Buffer exceeded");
|
||||
|
||||
if ( len > 0 ) {
|
||||
memcpy(buffer, &statebuffer[sboffset], len);
|
||||
sboffset += len;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* GCReadChunk
|
||||
*
|
||||
* Read the array of SFORMAT structures to memory
|
||||
****************************************************************************/
|
||||
|
||||
int GCReadChunk( int chunkid, SFORMAT *sf )
|
||||
{
|
||||
int csize;
|
||||
static char chunk[6];
|
||||
int chunklength;
|
||||
int thischunk;
|
||||
char info[128];
|
||||
|
||||
memfread(&chunk, 4);
|
||||
memfread(&thischunk, 4);
|
||||
memfread(&chunklength, 4);
|
||||
|
||||
if ( strcmp(chunk, "CHNK") == 0 )
|
||||
{
|
||||
if ( chunkid == thischunk )
|
||||
{
|
||||
/*** Now decode the array of chunks to this one ***/
|
||||
while ( sf->v )
|
||||
{
|
||||
memfread(&chunk, 4);
|
||||
if ( memcmp(&chunk, "CHKE", 4) == 0 )
|
||||
return 1;
|
||||
|
||||
if ( memcmp(&chunk, sf->desc, 4) == 0 )
|
||||
{
|
||||
memfread(&csize, 4);
|
||||
if ( csize == ( sf->s & ( ~RLSB ) ) )
|
||||
{
|
||||
memfread( sf->v, csize );
|
||||
sprintf(info,"%s %d", chunk, csize);
|
||||
} else {
|
||||
WaitPrompt("Bad chunk link");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
sprintf(info, "No Sync %s %s", chunk, sf->desc);
|
||||
WaitPrompt(info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sf++;
|
||||
}
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* GCFCEUSS_Load
|
||||
*
|
||||
* Reads the SFORMAT arrays
|
||||
****************************************************************************/
|
||||
|
||||
int GCFCEUSS_Load()
|
||||
{
|
||||
int totalsize = 0;
|
||||
|
||||
sboffset = 16 + sizeof(saveicon) + 64; /*** Reset memory file pointer ***/
|
||||
|
||||
memcpy(&totalsize, &statebuffer[FILESIZEOFFSET], 4);
|
||||
|
||||
/*** Now read the chunks back ***/
|
||||
if ( GCReadChunk( 1, SFCPU ) )
|
||||
{
|
||||
if ( GCReadChunk( 2, SFCPUC ) )
|
||||
{
|
||||
if ( GCReadChunk( 3, FCEUPPU_STATEINFO ) )
|
||||
{
|
||||
if ( GCReadChunk( 4, FCEUCTRL_STATEINFO ) )
|
||||
{
|
||||
if ( GCReadChunk( 5, FCEUSND_STATEINFO ) )
|
||||
{
|
||||
|
||||
if ( GCReadChunk( 0x10, SFMDATA ) )
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* GCSaveChunk
|
||||
*
|
||||
* Write the array of SFORMAT structures to the file
|
||||
****************************************************************************/
|
||||
int GCSaveChunk( int chunkid, SFORMAT *sf )
|
||||
{
|
||||
int chnkstart;
|
||||
int csize = 0;
|
||||
int chsize = 0;
|
||||
char chunk[] = "CHNK";
|
||||
|
||||
/*** Add chunk marker ***/
|
||||
memfwrite(&chunk, 4);
|
||||
memfwrite(&chunkid, 4);
|
||||
chnkstart = sboffset; /*** Save ptr ***/
|
||||
sboffset += 4; /*** Space for length ***/
|
||||
csize += 12;
|
||||
|
||||
/*** Now run through this structure ***/
|
||||
while (sf->v)
|
||||
{
|
||||
/*** Check that there is a decription ***/
|
||||
if ( sf->desc == NULL)
|
||||
break;
|
||||
|
||||
/*** Write out the description ***/
|
||||
memfwrite( sf->desc, 4);
|
||||
|
||||
/*** Write the length of this chunk ***/
|
||||
chsize = ( sf->s & (~RLSB) );
|
||||
memfwrite( &chsize, 4);
|
||||
|
||||
if ( chsize > 0 )
|
||||
/*** Write the actual data ***/
|
||||
memfwrite( sf->v, chsize );
|
||||
|
||||
csize += 8;
|
||||
csize += chsize;
|
||||
|
||||
sf++;
|
||||
}
|
||||
|
||||
/*** Update CHNK length ***/
|
||||
memcpy(&statebuffer[chnkstart], &csize, 4);
|
||||
|
||||
return csize;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* GCFCEUSS_Save
|
||||
*
|
||||
* This is a modified version of FCEUSS_Save
|
||||
* It uses memory for it's I/O and has an added CHNK block.
|
||||
* The file is terminated with CHNK length of 0.
|
||||
****************************************************************************/
|
||||
int GCFCEUSS_Save()
|
||||
{
|
||||
int totalsize = 0;
|
||||
static unsigned char header[16] = "FCS\xff";
|
||||
char chunk[] = "CHKE";
|
||||
int zero = 0;
|
||||
char Comment[2][32] = { { "FCEU GC Version 1.0.8" }, { "A GAME" } };
|
||||
|
||||
memopen(); /*** Reset Memory File ***/
|
||||
|
||||
/*** Add version ID ***/
|
||||
memcpy(&header[8], &mcversion, 4);
|
||||
|
||||
/*** Do internal Saving ***/
|
||||
FCEUPPU_SaveState();
|
||||
FCEUSND_SaveState();
|
||||
|
||||
/*** Write Icon ***/
|
||||
memfwrite(&saveicon, sizeof(saveicon));
|
||||
totalsize += sizeof(saveicon);
|
||||
|
||||
/*** And Comments ***/
|
||||
sprintf(Comment[1], "NES CRC 0x%08x", iNESGameCRC32);
|
||||
memfwrite(&Comment[0], 64);
|
||||
totalsize += 64;
|
||||
|
||||
/*** Write header ***/
|
||||
memfwrite(&header, 16);
|
||||
totalsize += 16;
|
||||
totalsize += GCSaveChunk(1, SFCPU);
|
||||
totalsize += GCSaveChunk(2, SFCPUC);
|
||||
totalsize += GCSaveChunk(3, FCEUPPU_STATEINFO);
|
||||
totalsize += GCSaveChunk(4, FCEUCTRL_STATEINFO);
|
||||
totalsize += GCSaveChunk(5, FCEUSND_STATEINFO);
|
||||
totalsize += GCSaveChunk(0x10, SFMDATA);
|
||||
|
||||
/*** Add terminating CHNK ***/
|
||||
memfwrite(&chunk,4);
|
||||
memfwrite(&zero,4);
|
||||
totalsize += 8;
|
||||
|
||||
/*** Update size element ***/
|
||||
memcpy(&statebuffer[FILESIZEOFFSET], &totalsize, 4);
|
||||
|
||||
return totalsize;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Card Removed
|
||||
*
|
||||
* Straight copy from MemCard demo
|
||||
****************************************************************************/
|
||||
int CardReady = 0;
|
||||
void CardRemoved(s32 chn,s32 result) {
|
||||
CARD_Unmount(chn);
|
||||
CardReady = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Snes9xGX Memcard
|
||||
****************************************************************************/
|
||||
void uselessinquiry()
|
||||
{
|
||||
volatile long *udvd = ( volatile long *)0xCC006000;
|
||||
|
||||
udvd[0] = 0;
|
||||
udvd[1] = 0;
|
||||
udvd[2] = 0x12000000;
|
||||
udvd[3] = 0;
|
||||
udvd[4] = 0x20;
|
||||
udvd[5] = 0x80000000;
|
||||
udvd[6] = 0x20;
|
||||
udvd[7] = 1;
|
||||
|
||||
while ( udvd[7] & 1 );
|
||||
|
||||
}
|
||||
|
||||
int MountTheCard()
|
||||
{
|
||||
int tries = 0;
|
||||
int CardError;
|
||||
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 ***/
|
||||
if ( CardError == 0 )
|
||||
return 0;
|
||||
else {
|
||||
EXI_ProbeReset();
|
||||
}
|
||||
tries++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* MemCard Save
|
||||
*
|
||||
* This is based on the code from libogc
|
||||
****************************************************************************/
|
||||
|
||||
void MCManage(int mode, int slot)
|
||||
{
|
||||
|
||||
char mcFilename[80];
|
||||
int CardError;
|
||||
card_dir CardDir;
|
||||
card_file CardFile;
|
||||
int SectorSize;
|
||||
int found = 0;
|
||||
int FileSize;
|
||||
int actualSize;
|
||||
int savedBytes=0;
|
||||
char debug[128];
|
||||
|
||||
CARDSLOT = slot;
|
||||
/*** Build the file name ***/
|
||||
sprintf(mcFilename, "FCEU-%08x.fcs", iNESGameCRC32);
|
||||
|
||||
/*** Mount the Card ***/
|
||||
CARD_Init("FCEU", "00");
|
||||
|
||||
/*** Try for memory card in slot A ***/
|
||||
CardError = CARD_Mount(CARDSLOT, SysArea, CardRemoved );
|
||||
|
||||
if ( CardError >= 0 )
|
||||
{
|
||||
/*** Get card sector size ***/
|
||||
CardError = CARD_GetSectorSize(CARDSLOT, &SectorSize);
|
||||
|
||||
switch ( mode ) {
|
||||
|
||||
case 0 : { /*** Save Game ***/
|
||||
/*** Look for this file ***/
|
||||
CardError = CARD_FindFirst(CARDSLOT, &CardDir, true);
|
||||
|
||||
found = 0;
|
||||
|
||||
card_stat CardStatus;
|
||||
while ( CardError != CARD_ERROR_NOFILE )
|
||||
{
|
||||
CardError = CARD_FindNext(&CardDir);
|
||||
if ( strcmp(CardDir.filename, mcFilename) == 0 )
|
||||
found = 1;
|
||||
}
|
||||
|
||||
/*** Determine number of sectors required ***/
|
||||
savedBytes = actualSize = GCFCEUSS_Save();
|
||||
sprintf(debug, "Saving in MC ...");
|
||||
ShowAction(debug);
|
||||
|
||||
FileSize = ( actualSize / SectorSize ) * SectorSize;
|
||||
if ( actualSize % SectorSize )
|
||||
FileSize += SectorSize;
|
||||
|
||||
/*** Now write the file out ***/
|
||||
if ( !found )
|
||||
CardError = CARD_Create(CARDSLOT, mcFilename, FileSize, &CardFile);
|
||||
else
|
||||
CardError = CARD_Open(CARDSLOT, mcFilename, &CardFile);
|
||||
|
||||
CARD_GetStatus( CARDSLOT, CardFile.filenum, &CardStatus);
|
||||
CardStatus.icon_addr = 0;
|
||||
CardStatus.icon_fmt = 2;
|
||||
CardStatus.icon_speed = 1;
|
||||
CardStatus.comment_addr = sizeof(saveicon);
|
||||
CARD_SetStatus( CARDSLOT, CardFile.filenum, &CardStatus);
|
||||
|
||||
/*** Haha! libogc only write one block at a time! ***/
|
||||
if ( CardError == 0 )
|
||||
{
|
||||
int sbo = 0;
|
||||
while ( actualSize > 0 )
|
||||
{
|
||||
CardError = CARD_Write(&CardFile, &statebuffer[sbo], SectorSize, sbo );
|
||||
actualSize -= SectorSize;
|
||||
sbo += SectorSize;
|
||||
}
|
||||
|
||||
CardError = CARD_Close(&CardFile);
|
||||
sprintf(debug, "Saved %d bytes successfully!", savedBytes);
|
||||
WaitPrompt(debug);
|
||||
}
|
||||
else WaitPrompt("Save Failed!");
|
||||
|
||||
CARD_Unmount(CARDSLOT);
|
||||
|
||||
}
|
||||
break; /*** End save ***/
|
||||
|
||||
case 1: { /*** Load state ***/
|
||||
/*** Look for this file ***/
|
||||
CardError = CARD_FindFirst(CARDSLOT, &CardDir, true);
|
||||
|
||||
memopen(); /*** Clear the buffer ***/
|
||||
|
||||
found = 0;
|
||||
|
||||
while ( CardError != CARD_ERROR_NOFILE )
|
||||
{
|
||||
CardError = CARD_FindNext(&CardDir);
|
||||
if ( strcmp(CardDir.filename, mcFilename) == 0 )
|
||||
found = 1;
|
||||
}
|
||||
|
||||
if ( found == 0 )
|
||||
{
|
||||
WaitPrompt("No Save Game Found");
|
||||
CARD_Unmount(CARDSLOT);
|
||||
return;
|
||||
}
|
||||
|
||||
/*** Load the file into memory ***/
|
||||
CardError = CARD_Open(CARDSLOT, mcFilename, &CardFile);
|
||||
CardError = CARD_Read(&CardFile, &statebuffer, SectorSize, 0);
|
||||
|
||||
/*** Get actual size of the file ***/
|
||||
memcpy(&actualSize, &statebuffer[FILESIZEOFFSET], 4);
|
||||
savedBytes = actualSize;
|
||||
|
||||
int sbo = SectorSize;
|
||||
actualSize -= SectorSize;
|
||||
while( actualSize > 0 )
|
||||
{
|
||||
CARD_Read(&CardFile, &statebuffer[sbo], SectorSize, sbo);
|
||||
actualSize -= SectorSize;
|
||||
sbo += SectorSize;
|
||||
}
|
||||
CARD_Close(&CardFile);
|
||||
|
||||
/*** Finally, do load ***/
|
||||
GCFCEUSS_Load();
|
||||
|
||||
CARD_Unmount(CARDSLOT);
|
||||
sprintf(debug, "Loaded %d bytes successfully!", savedBytes);
|
||||
WaitPrompt(debug);
|
||||
|
||||
}
|
||||
break; /*** End load ***/
|
||||
|
||||
default: break;
|
||||
}
|
||||
} else {
|
||||
WaitPrompt("Cannot Mount Memory Card!");
|
||||
}
|
||||
}
|
||||
|
||||
void SD_Manage(int mode, int slot){
|
||||
|
||||
sd_file *handle;
|
||||
char path[1024];
|
||||
char msg[128];
|
||||
int offset = 0;
|
||||
int filesize = 0;
|
||||
int len = 0;
|
||||
|
||||
//sprintf (filepath, "dev%d:\\%s\\%08x.fcs", slot, SAVEDIR, iNESGameCRC32);
|
||||
sprintf (path, "dev%d:\\%08x.fcs", slot, iNESGameCRC32);
|
||||
|
||||
if (mode == 0) ShowAction ("Saving STATE to SD...");
|
||||
else ShowAction ("Loading STATE from SD...");
|
||||
|
||||
handle = (mode == 0) ? SDCARD_OpenFile (path, "wb") : SDCARD_OpenFile (path, "rb");
|
||||
|
||||
if (handle == NULL){
|
||||
sprintf(msg, "Couldn't open %s", path);
|
||||
WaitPrompt(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == 0){ //Save
|
||||
filesize = GCFCEUSS_Save();
|
||||
|
||||
len = SDCARD_WriteFile (handle, statebuffer, filesize);
|
||||
SDCARD_CloseFile (handle);
|
||||
|
||||
if (len != filesize){
|
||||
sprintf (msg, "Error writing %s", path);
|
||||
WaitPrompt (msg);
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf (msg, "Saved %d bytes successfully", filesize);
|
||||
WaitPrompt (msg);
|
||||
}
|
||||
else{ //Load
|
||||
|
||||
memopen();
|
||||
while ((len = SDCARD_ReadFile (handle, &statebuffer[offset], 1024)) > 0) offset += len;
|
||||
SDCARD_CloseFile (handle);
|
||||
|
||||
sprintf (msg, "Loaded %d bytes successfully", offset);
|
||||
WaitPrompt(msg);
|
||||
|
||||
GCFCEUSS_Load();
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
void ManageState(int mode, int slot, int device){
|
||||
|
||||
if (device == 0){
|
||||
MCManage(mode, slot);
|
||||
}
|
||||
else{
|
||||
SD_Manage(mode, slot);
|
||||
}
|
||||
}
|
38408
source/drivers/gamecube/nesback.h
Normal file
38408
source/drivers/gamecube/nesback.h
Normal file
File diff suppressed because it is too large
Load Diff
155
source/drivers/gamecube/pad.c
Normal file
155
source/drivers/gamecube/pad.c
Normal file
@ -0,0 +1,155 @@
|
||||
/****************************************************************************
|
||||
* Gamecube Input
|
||||
*
|
||||
* Use JOY1 and JOY2
|
||||
****************************************************************************/
|
||||
|
||||
#include <gccore.h>
|
||||
#include "../../driver.h"
|
||||
#include "../../fceu.h"
|
||||
|
||||
/* PADStatus joypads[4]; */
|
||||
static uint32 JSReturn = 0;
|
||||
unsigned short skipa[4] = {0, 0, 0, 0};
|
||||
unsigned short skipb[4] = {0, 0, 0, 0};
|
||||
|
||||
unsigned short op[4] = {0, 0, 0, 0};
|
||||
|
||||
extern int ConfigScreen();
|
||||
|
||||
/****************************************************************************
|
||||
* Initialise Pads
|
||||
****************************************************************************/
|
||||
void InitialisePads()
|
||||
{
|
||||
int attrib = 0;
|
||||
void *InputDPR;
|
||||
|
||||
FCEUI_DisableFourScore(1);
|
||||
|
||||
InputDPR = &JSReturn;
|
||||
FCEUI_SetInput(0, SI_GAMEPAD, InputDPR, attrib);
|
||||
FCEUI_SetInput(1, SI_GAMEPAD, InputDPR, attrib);
|
||||
}
|
||||
|
||||
unsigned short gcpadmap[] = { PAD_BUTTON_A, PAD_BUTTON_B, PAD_BUTTON_START, PAD_TRIGGER_Z, PAD_BUTTON_X, PAD_BUTTON_Y,
|
||||
PAD_BUTTON_UP, PAD_BUTTON_DOWN, PAD_BUTTON_LEFT, PAD_BUTTON_RIGHT };
|
||||
|
||||
unsigned int nespadmap[] = { JOY_A, JOY_B, JOY_START, JOY_SELECT, JOY_A, JOY_B,
|
||||
JOY_UP, JOY_DOWN, JOY_LEFT, JOY_RIGHT };
|
||||
|
||||
/****************************************************************************
|
||||
* Convert GC Joystick Readings to JOY
|
||||
****************************************************************************/
|
||||
int PADTUR = 2;
|
||||
|
||||
unsigned char DecodeJoy( unsigned short pp )
|
||||
{
|
||||
unsigned short p = PAD_ButtonsHeld(pp);
|
||||
|
||||
unsigned char J = 0;
|
||||
|
||||
int i;
|
||||
|
||||
if ((skipa[pp] == 0) || ((op[pp] & gcpadmap[4]) == 0)) {
|
||||
nespadmap[4] = JOY_A;
|
||||
skipa[pp] = PADTUR;
|
||||
}
|
||||
|
||||
if ((skipb[pp] == 0) || ((op[pp] & gcpadmap[5]) == 0)) {
|
||||
nespadmap[5] = JOY_B;
|
||||
skipb[pp] = PADTUR;
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (p & gcpadmap[i])
|
||||
J |= nespadmap[i];
|
||||
}
|
||||
|
||||
if (skipa[pp] > 0){
|
||||
nespadmap[4] = 0;
|
||||
skipa[pp]--;
|
||||
}
|
||||
|
||||
if (skipb[pp] > 0){
|
||||
nespadmap[5] = 0;
|
||||
skipb[pp]--;
|
||||
}
|
||||
|
||||
op[pp] = p;
|
||||
|
||||
return J;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* V 1.0.1
|
||||
*
|
||||
* Additional check for Analog X/Y
|
||||
****************************************************************************/
|
||||
int PADCAL = 70;
|
||||
|
||||
unsigned char GetAnalog(int Joy)
|
||||
{
|
||||
|
||||
signed char x, y;
|
||||
unsigned char i = 0;
|
||||
|
||||
x = PAD_StickX(Joy);
|
||||
y = PAD_StickY(Joy);
|
||||
|
||||
if (x * x + y * y > PADCAL * PADCAL) {
|
||||
|
||||
if (x > 0 && y == 0) return JOY_RIGHT;
|
||||
if (x < 0 && y == 0) return JOY_LEFT;
|
||||
if (x == 0 && y > 0) return JOY_UP;
|
||||
if (x == 0 && y < 0) return JOY_DOWN;
|
||||
|
||||
if ((float)y / x >= -2.41421356237 && (float)y / x < 2.41421356237) {
|
||||
if (x >= 0)
|
||||
i |= JOY_RIGHT;
|
||||
else
|
||||
i |= JOY_LEFT;
|
||||
}
|
||||
|
||||
if ((float)x / y >= -2.41421356237 && (float)x / y < 2.41421356237) {
|
||||
if (y >= 0)
|
||||
i |= JOY_UP;
|
||||
else
|
||||
i |= JOY_DOWN;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int GetJoy()
|
||||
{
|
||||
unsigned char pad[4];
|
||||
short i;
|
||||
int t = 0;
|
||||
|
||||
void (*PSOReload)() = (void(*)())0x80001800;
|
||||
|
||||
/*** Before checking anything else, look for PSOReload ***/
|
||||
if ( PAD_ButtonsHeld(0) == ( PAD_BUTTON_B | PAD_BUTTON_X | PAD_BUTTON_START ) )
|
||||
PSOReload();
|
||||
|
||||
/*** Look for config menu ***/
|
||||
signed char px;
|
||||
px = PAD_SubStickX (0);
|
||||
if (((px < -70)) || (PAD_ButtonsHeld(0) == ( PAD_TRIGGER_L | PAD_TRIGGER_R ))) {
|
||||
t = ConfigScreen();
|
||||
if (t == 1) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 4; i++)
|
||||
pad[i] = DecodeJoy(i) | GetAnalog(i);
|
||||
|
||||
|
||||
JSReturn = pad[0] | pad[1] << 8 | pad[2] << 16 | pad[3] << 24;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
132
source/drivers/gamecube/saveicon.h
Normal file
132
source/drivers/gamecube/saveicon.h
Normal file
@ -0,0 +1,132 @@
|
||||
unsigned short saveicon[1024] = {
|
||||
|
||||
0xDAD6, 0xEF7B, 0xE318, 0xCA52, 0xA94A, 0xCA52, 0xF7BD, 0xF7BD,
|
||||
0x8C63, 0xA108, 0xCE73, 0xBDEF, 0x8421, 0x8C63, 0x9CE7, 0x8C63,
|
||||
0xB5AD, 0xAD6B, 0xA94A, 0xCE71, 0xDEF7, 0xCE73, 0xF7BB, 0xFFFF,
|
||||
0xA94A, 0xC20F, 0xEB58, 0xFBBB, 0x8421, 0xC1EE, 0xE2F5, 0xDED3,
|
||||
0xDEF5, 0xDED4, 0xDEF4, 0xDED4, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
|
||||
0xF7BA, 0xF7BA, 0xFBBA, 0xFBBA, 0xDAD4, 0xDED4, 0xDED4, 0xDED4,
|
||||
0xDAB3, 0xDAB3, 0xDAB3, 0xD6B3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
|
||||
0xFBBA, 0xFBBB, 0xFBBA, 0xFBBA, 0xDED4, 0xDEF4, 0xDED4, 0xCA0E,
|
||||
0xD692, 0xD692, 0xD692, 0xD272, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
|
||||
0xFFBB, 0xFFBB, 0xFBBA, 0xFBBA, 0xBD8A, 0xDAB2, 0xE2F4, 0xE2F4,
|
||||
0xD292, 0xD692, 0xD692, 0xD292, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
|
||||
0xFBBA, 0xF7BA, 0xF798, 0xF799, 0xE2F4, 0xE2F4, 0xDAB2, 0xDAD2,
|
||||
0xD272, 0xCE71, 0xBDEE, 0xA529, 0xFFFF, 0xFFFF, 0xFFFF, 0xDAD4,
|
||||
0xFBBA, 0xFBBA, 0xFB99, 0xD270, 0xDED4, 0xDED3, 0xDED3, 0xD670,
|
||||
0x98C6, 0x8C63, 0x8421, 0x8000, 0x9CE7, 0x8842, 0x8000, 0x8000,
|
||||
0x9CE5, 0x8000, 0x8000, 0x8000, 0xA0E5, 0x8000, 0x8000, 0x8000,
|
||||
0x8421, 0x8842, 0x9084, 0x8421, 0x8000, 0x8421, 0x8C63, 0xB9CC,
|
||||
0x8000, 0x8421, 0xB18B, 0xD6B3, 0x8000, 0x8421, 0xD6B3, 0xE717,
|
||||
0xA528, 0xCE71, 0xDED4, 0xDAD3, 0xCE71, 0xE736, 0xE315, 0xE2F5,
|
||||
0xE316, 0xDAD4, 0xDAD4, 0xDAD4, 0xB18B, 0xA528, 0xA528, 0xA128,
|
||||
0xDAB3, 0xDED3, 0xDED4, 0xDED4, 0xE2F5, 0xE715, 0xE715, 0xE715,
|
||||
0xDED4, 0xDED4, 0xDED4, 0xDED4, 0xA107, 0xA507, 0xA528, 0xA528,
|
||||
0xDED4, 0xDED4, 0xDED4, 0xDEB3, 0xE715, 0xE716, 0xE715, 0xE716,
|
||||
0xDED5, 0xDED4, 0xDED5, 0xDEF5, 0xA528, 0xA528, 0xA528, 0xA528,
|
||||
0xDA92, 0xDED3, 0xDED3, 0xDAD3, 0xE716, 0xE716, 0xE715, 0xE2F5,
|
||||
0xDEF5, 0xDEF5, 0xE2F5, 0xE2F5, 0xA528, 0xA528, 0xA528, 0xA528,
|
||||
0xDED3, 0xDED3, 0xDAB2, 0xDAB3, 0xE715, 0xE715, 0xE2F4, 0xE2F5,
|
||||
0xE2F5, 0xE2F5, 0xE315, 0xE315, 0xA528, 0xA528, 0xA528, 0xA528,
|
||||
0xDED3, 0xDED3, 0xDEB2, 0xDA90, 0xE2F5, 0xE315, 0xE2F4, 0xDEB2,
|
||||
0xE316, 0xE716, 0xEB36, 0xEF37, 0xA928, 0xA528, 0xA928, 0xB5AB,
|
||||
0xA927, 0x8000, 0x8000, 0x8000, 0xB589, 0xB189, 0x8000, 0x8000,
|
||||
0xD670, 0xB9AB, 0x98C4, 0x8000, 0xDED3, 0xD26F, 0xA927, 0x8000,
|
||||
0x8000, 0xAD8B, 0xE738, 0xC210, 0x8000, 0xB9CD, 0xF39B, 0xA109,
|
||||
0x8000, 0xBE0F, 0xEB5A, 0xA52A, 0x8000, 0xC20F, 0xE739, 0xAD6D,
|
||||
0x94A4, 0x9084, 0x9084, 0x9084, 0x8442, 0x8842, 0x8842, 0x9083,
|
||||
0x8843, 0x8C63, 0x8C62, 0x8841, 0x98E8, 0x94A6, 0x8862, 0x8842,
|
||||
0x9083, 0x9083, 0x9083, 0x9084, 0x94A5, 0x94A5, 0x94A5, 0x94A4,
|
||||
0x8862, 0x8862, 0x8842, 0x8842, 0x8842, 0x8841, 0x8421, 0x8421,
|
||||
0x9484, 0x9484, 0x9084, 0x9084, 0x94A4, 0x94A5, 0x94A5, 0x94A5,
|
||||
0x8862, 0x8862, 0x8C62, 0x8C62, 0x8421, 0x8421, 0x8421, 0x8421,
|
||||
0x94A4, 0x9084, 0x94A4, 0x94A4, 0x94A5, 0x94A5, 0x94A5, 0x94A5,
|
||||
0x8C62, 0x8C62, 0x8C62, 0x8C62, 0x8421, 0x8421, 0x8421, 0x8421,
|
||||
0x94A4, 0x94A4, 0x94A4, 0x94A4, 0x94A5, 0x94A5, 0x94A5, 0x9083,
|
||||
0x8C62, 0x8C63, 0x8C63, 0x9484, 0x8421, 0x8421, 0x8421, 0x8841,
|
||||
0x94A4, 0x94A4, 0x94A4, 0x9CE6, 0x8C62, 0x8842, 0x8841, 0x8841,
|
||||
0x9083, 0x8C62, 0x8C63, 0x8841, 0x8C62, 0x8C62, 0x8C62, 0x8421,
|
||||
0xB58A, 0xDA91, 0xB58A, 0x8000, 0x94A4, 0xDA91, 0xBDCB, 0x8000,
|
||||
0x9062, 0xD690, 0xBDCB, 0x8000, 0x8C62, 0xDA91, 0xC5ED, 0x8000,
|
||||
0x8000, 0xBDEF, 0xEB5A, 0x98C7, 0x8000, 0xB9CD, 0xEB5A, 0x90A5,
|
||||
0x8000, 0xA549, 0xD294, 0x98E7, 0x8000, 0x8421, 0xC651, 0xA128,
|
||||
0xA96D, 0x9085, 0x8C63, 0x8C63, 0x94A6, 0x8421, 0x9CE7, 0x8C63,
|
||||
0x8422, 0x8421, 0xA529, 0x94A4, 0x8421, 0x8421, 0x98C5, 0x9083,
|
||||
0x8C63, 0x8C63, 0x8C63, 0x8C63, 0x8842, 0x8C62, 0x8C63, 0x9084,
|
||||
0x8842, 0x8C62, 0x9084, 0x8C63, 0x8C42, 0x8C62, 0x8842, 0x8862,
|
||||
0x8421, 0x8421, 0x8421, 0x8421, 0x8C63, 0x8421, 0x8421, 0x8421,
|
||||
0x94A4, 0x8842, 0x8421, 0x8421, 0x9D07, 0x8862, 0x8421, 0x8421,
|
||||
0x8421, 0x8421, 0x8421, 0x8C63, 0x8421, 0x8421, 0x8421, 0x94A4,
|
||||
0x8421, 0x8421, 0x8421, 0xA108, 0x8421, 0x8421, 0x8421, 0xAD6B,
|
||||
0x9084, 0x8421, 0x8421, 0x8441, 0x94A4, 0x8421, 0x8421, 0x8421,
|
||||
0x94A4, 0x8821, 0x8841, 0x8841, 0x9484, 0x8421, 0x8842, 0x8842,
|
||||
0x8841, 0x8421, 0x8841, 0x8420, 0x9084, 0x9084, 0x8C62, 0x8421,
|
||||
0x94A4, 0x9CE7, 0x8842, 0x8421, 0x9084, 0x98C5, 0x8841, 0x8421,
|
||||
0x8C62, 0xDA91, 0xC5ED, 0x8000, 0x9083, 0xDA92, 0xC1ED, 0x8000,
|
||||
0x94A4, 0xC1ED, 0xAD69, 0x8000, 0x98A5, 0xB5AB, 0x8000, 0x8000,
|
||||
0x8000, 0x8421, 0xC230, 0xA94A, 0x8000, 0x8421, 0xBE0F, 0xAD6B,
|
||||
0x8000, 0x8421, 0xA98B, 0xB5CD, 0x8000, 0x8421, 0x8C63, 0xA149,
|
||||
0x8421, 0x8421, 0x94A4, 0x90A4, 0x8020, 0x8421, 0x8841, 0x9484,
|
||||
0x8862, 0x8421, 0x8420, 0x8821, 0xA128, 0xA129, 0xA549, 0x8883,
|
||||
0x8842, 0x8842, 0x8841, 0x8C63, 0x8C42, 0x8842, 0x8841, 0x9084,
|
||||
0x8842, 0x8842, 0x8842, 0x8C63, 0x8441, 0x8421, 0x8421, 0x8842,
|
||||
0x9CE7, 0x8842, 0x8421, 0x8421, 0x9084, 0x8421, 0x8421, 0x8421,
|
||||
0x8842, 0x8422, 0x8421, 0x8421, 0x8421, 0x8822, 0x8822, 0x8421,
|
||||
0x8841, 0x8421, 0x8841, 0x98C5, 0x8441, 0x8421, 0x8441, 0x8C63,
|
||||
0x8421, 0x8421, 0x8441, 0x8421, 0x8421, 0x8421, 0x8421, 0x8421,
|
||||
0x94A4, 0x8000, 0x8421, 0x8842, 0x9084, 0x8842, 0x8421, 0x8842,
|
||||
0x8C42, 0x8C62, 0x8822, 0x8842, 0x8421, 0x8821, 0x8821, 0x8841,
|
||||
0x8842, 0x8C63, 0x8841, 0x8021, 0x8C63, 0x9084, 0x8421, 0x8000,
|
||||
0x8842, 0x8C43, 0x8421, 0x8000, 0x9484, 0xA0E7, 0x9CC6, 0xB58B,
|
||||
0x9CC5, 0xB5AB, 0x8000, 0x8000, 0xA527, 0xB18A, 0x8000, 0x8000,
|
||||
0xB9AB, 0xB18A, 0x8000, 0x8000, 0xDAB3, 0xC1ED, 0xB58A, 0xA106,
|
||||
0x8000, 0x8421, 0x8C63, 0x8421, 0x8000, 0x8421, 0x8C63, 0x8421,
|
||||
0x8000, 0x8421, 0x8C63, 0x8421, 0x8000, 0x8421, 0x8C63, 0xAD8C,
|
||||
0x8000, 0x8000, 0x8000, 0x90C5, 0x8000, 0x8000, 0x90A5, 0xA129,
|
||||
0x98E7, 0xB5CE, 0xC652, 0xC210, 0xC651, 0xE318, 0xDEF7, 0xCE72,
|
||||
0x94C6, 0xA529, 0xB9CE, 0xC632, 0xCA52, 0xDAD6, 0xDAD6, 0xD6B6,
|
||||
0xD6B5, 0xD6B6, 0xD6B6, 0xD6B5, 0xC631, 0xD6B6, 0xD6B6, 0xD6B5,
|
||||
0xC632, 0xB18D, 0xB16C, 0xA108, 0xEF7C, 0xE73A, 0xD6B6, 0xB5AD,
|
||||
0xEB5A, 0xEF9C, 0xDEF7, 0xD693, 0xE73A, 0xF39D, 0xDAB5, 0xD271,
|
||||
0x8401, 0xA108, 0xA528, 0xA508, 0x9083, 0xC20F, 0xCA30, 0xCA30,
|
||||
0xC60F, 0xD272, 0xD271, 0xD250, 0xD671, 0xCE2F, 0xD270, 0xD670,
|
||||
0xA929, 0xB16A, 0xBDED, 0xCA2F, 0xD250, 0xCA0E, 0xDA92, 0xDAB2,
|
||||
0xD24F, 0xD24E, 0xD250, 0xCE2E, 0xD670, 0xD66F, 0xD64F, 0xCE2D,
|
||||
0xD271, 0xDEB4, 0xDED4, 0xDED4, 0xD670, 0xD24F, 0xDA70, 0xD670,
|
||||
0xD24E, 0xD24E, 0xD24E, 0xD24F, 0xD22E, 0xD24E, 0xD64E, 0xD64E,
|
||||
0xDAB2, 0xCE50, 0xCA2E, 0xCA0D, 0xD670, 0xCE2E, 0xC5ED, 0xC5EC,
|
||||
0xD24F, 0xCE0D, 0xC5EC, 0xC5EC, 0xD24E, 0xCE2D, 0xCA0C, 0xCA0D,
|
||||
0x8000, 0x8421, 0xD2B4, 0xDAF7, 0x8000, 0x9D08, 0xE75A, 0xEB7B,
|
||||
0x90C6, 0xB5CE, 0xEF7C, 0xF7BD, 0xBE0F, 0xEB39, 0xE739, 0xF39C,
|
||||
0xE318, 0xDEF7, 0xDEF7, 0xDEF7, 0xDEF8, 0xE318, 0xDEF8, 0xE2F8,
|
||||
0xE739, 0xE318, 0xE318, 0xE318, 0xF39C, 0xE739, 0xE739, 0xE739,
|
||||
0xC630, 0xCA52, 0xDAB6, 0xD6B5, 0xDED6, 0xC20F, 0xD293, 0xD6B5,
|
||||
0xE319, 0xDAD6, 0xC630, 0xDEF7, 0xE718, 0xE739, 0xDAB5, 0xD294,
|
||||
0xE739, 0xF39D, 0xE2F7, 0xDAB3, 0xDEF8, 0xF39D, 0xE718, 0xDAD4,
|
||||
0xDAD6, 0xF39D, 0xE739, 0xDED4, 0xD274, 0xE73A, 0xEB5A, 0xE2F5,
|
||||
0xD270, 0xD670, 0xD671, 0xD691, 0xD670, 0xDA91, 0xDA91, 0xDA91,
|
||||
0xDA91, 0xDEB1, 0xDEB2, 0xE2D2, 0xDEB2, 0xE2D3, 0xE2D3, 0xE2D3,
|
||||
0xDA91, 0xDA91, 0xD66F, 0xD22D, 0xDEB2, 0xDE91, 0xCE2D, 0xD22E,
|
||||
0xE6D3, 0xE2B2, 0xC9EC, 0xCA0D, 0xE6F3, 0xDA90, 0xCA0D, 0xCA0D,
|
||||
0xD24E, 0xD24E, 0xD64E, 0xD66F, 0xD24E, 0xD64E, 0xD66F, 0xDA70,
|
||||
0xD66F, 0xDA70, 0xDA91, 0xDA92, 0xDEB3, 0xDEB3, 0xE2D4, 0xE2D4,
|
||||
0xD64F, 0xCE2E, 0xCE2E, 0xD24F, 0xD670, 0xCE2E, 0xD24F, 0xD670,
|
||||
0xDAB2, 0xD250, 0xCE2E, 0xB148, 0xE2D4, 0xDA92, 0xD24F, 0xB969,
|
||||
0xE739, 0xE317, 0xE318, 0xE739, 0xE318, 0xDEF7, 0xDAD6, 0xDAD6,
|
||||
0xDEF7, 0xDAD6, 0xD6B5, 0xD6B4, 0xDEF7, 0xDAD6, 0xD6B4, 0xD294,
|
||||
0xF7BD, 0xEB5A, 0xE739, 0xE738, 0xE318, 0xE739, 0xDAD6, 0xDAD6,
|
||||
0xD294, 0xDAD6, 0xDAD6, 0xD294, 0xD294, 0xD294, 0xDAD6, 0xD294,
|
||||
0xE738, 0xE739, 0xEB39, 0xD693, 0xDAD6, 0xDAD6, 0xDED6, 0xDAD5,
|
||||
0xD294, 0xD294, 0xD294, 0xD694, 0xD273, 0xD293, 0xD273, 0xD273,
|
||||
0xC630, 0xD6B5, 0xE738, 0xE2F5, 0xC630, 0xC631, 0xD6B5, 0xDAB3,
|
||||
0xCE72, 0xC1EF, 0xCE72, 0xCA30, 0xD293, 0xC630, 0xC610, 0xD272,
|
||||
0xDEB2, 0xE2D3, 0xE2D3, 0xDEB2, 0xD270, 0xD250, 0xCE2F, 0xD24F,
|
||||
0xC60E, 0xCA2F, 0xCE50, 0xD271, 0xCE50, 0xCE51, 0xD251, 0xD271,
|
||||
0xD670, 0xDEB2, 0xE2D3, 0xD691, 0xD691, 0xDAB2, 0xD692, 0xD693,
|
||||
0xD271, 0xCE71, 0xD271, 0xD272, 0xD271, 0xD271, 0xD271, 0xD271,
|
||||
0xE716, 0xE716, 0xE2F5, 0xE716, 0xDAB4, 0xE2F6, 0xDAB4, 0xDEB4,
|
||||
0xD272, 0xDAB4, 0xDAB3, 0xD271, 0xD672, 0xD692, 0xDAB4, 0xD250,
|
||||
0xE6F6, 0xDEB3, 0xD670, 0xD24F, 0xDEB3, 0xD691, 0xD670, 0xD670,
|
||||
0xD270, 0xD270, 0xD250, 0xD671, 0xCE4F, 0xCE4F, 0xCE2F, 0xD24F,
|
||||
};
|
||||
|
354
source/drivers/gamecube/sz.c
Normal file
354
source/drivers/gamecube/sz.c
Normal file
@ -0,0 +1,354 @@
|
||||
/****************************************************************************
|
||||
* SZ.C
|
||||
* svpe June 2007
|
||||
*
|
||||
* This file manages the 7zip support for this emulator.
|
||||
* Currently it only provides functions for loading a 7zip file from a DVD.
|
||||
****************************************************************************/
|
||||
|
||||
#include "gcdvd.h"
|
||||
#include "sz.h"
|
||||
|
||||
|
||||
// 7zip error list
|
||||
char szerrormsg[][30] = {"7z: Data error",
|
||||
"7z: Out of memory",
|
||||
"7z: CRC Error",
|
||||
"7z: Not implemented",
|
||||
"7z: Fail",
|
||||
"7z: Archive error"};
|
||||
|
||||
|
||||
SZ_RESULT SzRes;
|
||||
|
||||
SzFileInStream SzArchiveStream;
|
||||
CArchiveDatabaseEx SzDb;
|
||||
ISzAlloc SzAllocImp;
|
||||
ISzAlloc SzAllocTempImp;
|
||||
UInt32 SzBlockIndex = 0xFFFFFFFF;
|
||||
size_t SzBufferSize;
|
||||
size_t SzOffset;
|
||||
size_t SzOutSizeProcessed;
|
||||
CFileItem *SzF;
|
||||
char sz_buffer[2048];
|
||||
|
||||
// needed because there are no header files -.-
|
||||
#include <sdcard.h>
|
||||
#define MAXFILES 1000
|
||||
#define MAXJOLIET 256
|
||||
|
||||
extern FILEENTRIES filelist[MAXFILES];
|
||||
|
||||
extern int selection;
|
||||
extern int maxfiles;
|
||||
extern int offset;
|
||||
|
||||
// the GC's dvd drive only supports offsets and length which are a multiply of 32 bytes
|
||||
// additionally the max length of a read is 2048 bytes
|
||||
// this function removes these limitations
|
||||
// additionally the 7zip SDK does often read data in 1 byte parts from the DVD even when
|
||||
// it could read 32 bytes. the dvdsf_buffer has been added to avoid having to read the same sector
|
||||
// over and over again
|
||||
unsigned char dvdsf_buffer[DVD_SECTOR_SIZE];
|
||||
u64 dvdsf_last_offset = 0;
|
||||
u64 dvdsf_last_length = 0;
|
||||
|
||||
int dvd_buffered_read(void *dst, u32 len, u64 offset)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
// only read data if the data inside dvdsf_buffer cannot be used
|
||||
if(offset != dvdsf_last_offset || len > dvdsf_last_length)
|
||||
{
|
||||
memset(&dvdsf_buffer, '\0', DVD_SECTOR_SIZE);
|
||||
ret = dvd_read(&dvdsf_buffer, len, offset);
|
||||
dvdsf_last_offset = offset;
|
||||
dvdsf_last_length = len;
|
||||
|
||||
}
|
||||
|
||||
memcpy(dst, &dvdsf_buffer, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dvd_safe_read(void *dst_v, u32 len, u64 offset)
|
||||
{
|
||||
unsigned char buffer[DVD_SECTOR_SIZE]; // buffer for one dvd sector
|
||||
|
||||
// if read size and length are a multiply of DVD_(OFFSET,LENGTH)_MULTIPLY and length < DVD_MAX_READ_LENGTH
|
||||
// we don't need to fix anything
|
||||
if(len % DVD_LENGTH_MULTIPLY == 0 && offset % DVD_OFFSET_MULTIPLY == 0 && len <= DVD_MAX_READ_LENGTH)
|
||||
{
|
||||
int ret = dvd_buffered_read(buffer, len, offset);
|
||||
memcpy(dst_v, &buffer, len);
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no errors yet -> ret = 0
|
||||
// the return value of dvd_read will be OR'd with ret
|
||||
// because dvd_read does return 1 on error and 0 on success and
|
||||
// because 0 | 1 = 1 ret will also contain 1 if at least one error
|
||||
// occured and 0 otherwise ;)
|
||||
int ret = 0; // return value of dvd_read
|
||||
|
||||
// we might need to fix all 3 issues
|
||||
unsigned char *dst = (unsigned char *)dst_v; // gcc will not allow to use var[num] on void* types
|
||||
u64 bytesToRead; // the number of bytes we still need to read & copy to the output buffer
|
||||
u64 currentOffset; // the current dvd offset
|
||||
u64 bufferOffset; // the current buffer offset
|
||||
u64 i, j, k; // temporary variables which might be used for different stuff
|
||||
// unsigned char buffer[DVD_SECTOR_SIZE]; // buffer for one dvd sector
|
||||
|
||||
currentOffset = offset;
|
||||
bytesToRead = len;
|
||||
bufferOffset = 0;
|
||||
|
||||
// fix first issue (offset is not a multiply of 32)
|
||||
if(offset % DVD_OFFSET_MULTIPLY)
|
||||
{
|
||||
// calcualte offset of the prior 32 byte position
|
||||
i = currentOffset - (currentOffset % DVD_OFFSET_MULTIPLY);
|
||||
|
||||
// calculate the offset from which the data of the dvd buffer will be copied
|
||||
j = currentOffset % DVD_OFFSET_MULTIPLY;
|
||||
|
||||
// calculate the number of bytes needed to reach the next DVD_OFFSET_MULTIPLY byte mark
|
||||
k = DVD_OFFSET_MULTIPLY - j;
|
||||
|
||||
// maybe we'll only need to copy a few bytes and we therefore don't even reach the next sector
|
||||
if(k > len)
|
||||
{
|
||||
k = len;
|
||||
}
|
||||
|
||||
// read 32 bytes from the last 32 byte position
|
||||
ret |= dvd_buffered_read(buffer, DVD_OFFSET_MULTIPLY, i);
|
||||
|
||||
// copy the bytes to the output buffer and update currentOffset, bufferOffset and bytesToRead
|
||||
memcpy(&dst[bufferOffset], &buffer[j], k);
|
||||
currentOffset += k;
|
||||
bufferOffset += k;
|
||||
bytesToRead -= k;
|
||||
}
|
||||
|
||||
// fix second issue (more than 2048 bytes are needed)
|
||||
if(bytesToRead > DVD_MAX_READ_LENGTH)
|
||||
{
|
||||
// calculate the number of 2048 bytes sector needed to get all data
|
||||
i = (bytesToRead - (bytesToRead % DVD_MAX_READ_LENGTH)) / DVD_MAX_READ_LENGTH;
|
||||
|
||||
// read data in 2048 byte sector
|
||||
for(j = 0; j < i; j++)
|
||||
{
|
||||
ret |= dvd_buffered_read(buffer, DVD_MAX_READ_LENGTH, currentOffset); // read sector
|
||||
memcpy(&dst[bufferOffset], buffer, DVD_MAX_READ_LENGTH); // copy to output buffer
|
||||
|
||||
// update currentOffset, bufferOffset and bytesToRead
|
||||
currentOffset += DVD_MAX_READ_LENGTH;
|
||||
bufferOffset += DVD_MAX_READ_LENGTH;
|
||||
bytesToRead -= DVD_MAX_READ_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
// fix third issue (length is not a multiply of 32)
|
||||
if(bytesToRead)
|
||||
{
|
||||
ret |= dvd_buffered_read(buffer, DVD_MAX_READ_LENGTH, currentOffset); // read 32 byte from the dvd
|
||||
memcpy(&dst[bufferOffset], buffer, bytesToRead); // copy bytes to output buffer
|
||||
}
|
||||
|
||||
//free(tmp);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// function used by the 7zip SDK to read data from the DVD (fread)
|
||||
SZ_RESULT SzDvdFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize)
|
||||
{
|
||||
// the void* object is a SzFileInStream
|
||||
SzFileInStream *s = (SzFileInStream *)object;
|
||||
|
||||
// calculate dvd sector offset
|
||||
u64 offset = (u64)(s->offset + s->pos);
|
||||
|
||||
if(maxRequiredSize > 2048)
|
||||
{
|
||||
maxRequiredSize = 2048;
|
||||
}
|
||||
|
||||
// read data
|
||||
dvd_safe_read(sz_buffer, maxRequiredSize, offset);
|
||||
*buffer = sz_buffer;
|
||||
*processedSize = maxRequiredSize;
|
||||
s->pos += *processedSize;
|
||||
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
// function used by the 7zip SDK to change the filepointer (fseek(object, pos, SEEK_SET))
|
||||
SZ_RESULT SzDvdFileSeekImp(void *object, CFileSize pos)
|
||||
{
|
||||
// the void* object is a SzFileInStream
|
||||
SzFileInStream *s = (SzFileInStream *)object;
|
||||
|
||||
// check if the 7z SDK wants to move the pointer to somewhere after the EOF
|
||||
if(pos >= s->len)
|
||||
{
|
||||
WaitPrompt("7z Error: The 7z SDK wants to start reading somewhere behind the EOF...");
|
||||
return SZE_FAIL;
|
||||
}
|
||||
|
||||
// save new position and return
|
||||
s->pos = pos;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SZ_RESULT SzDvdIsArchive(u64 dvd_offset)
|
||||
{
|
||||
// 7z signautre
|
||||
static Byte Signature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
|
||||
Byte Candidate[6];
|
||||
|
||||
// read the data from the DVD
|
||||
dvd_safe_read (&Candidate, 6, dvd_offset);
|
||||
|
||||
size_t i;
|
||||
for(i = 0; i < 6; i++)
|
||||
{
|
||||
if(Candidate[i] != Signature[i])
|
||||
{
|
||||
return SZE_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
// display an error message
|
||||
void SzDisplayError(SZ_RESULT res)
|
||||
{
|
||||
WaitPrompt(szerrormsg[(res - 1)]);
|
||||
}
|
||||
|
||||
static u64 rootdir;
|
||||
static int rootdirlength;
|
||||
|
||||
void SzParse(void)
|
||||
{
|
||||
// save the offset and the length of this file inside the archive stream structure
|
||||
SzArchiveStream.offset = filelist[selection].offset;
|
||||
SzArchiveStream.len = filelist[selection].length;
|
||||
SzArchiveStream.pos = 0;
|
||||
|
||||
// set handler functions for reading data from DVD and setting the position
|
||||
SzArchiveStream.InStream.Read = SzDvdFileReadImp;
|
||||
SzArchiveStream.InStream.Seek = SzDvdFileSeekImp;
|
||||
|
||||
// set default 7Zip SDK handlers for allocation and freeing memory
|
||||
SzAllocImp.Alloc = SzAlloc;
|
||||
SzAllocImp.Free = SzFree;
|
||||
SzAllocTempImp.Alloc = SzAllocTemp;
|
||||
SzAllocTempImp.Free = SzFreeTemp;
|
||||
|
||||
// prepare CRC and 7Zip database structures
|
||||
InitCrcTable();
|
||||
SzArDbExInit(&SzDb);
|
||||
|
||||
// open the archive
|
||||
SzRes = SzArchiveOpen(&SzArchiveStream.InStream, &SzDb, &SzAllocImp, &SzAllocTempImp);
|
||||
|
||||
if(SzRes != SZ_OK)
|
||||
{
|
||||
// free memory used by the 7z SDK
|
||||
SzArDbExFree(&SzDb, SzAllocImp.Free);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// archive opened successfully
|
||||
|
||||
// erase all previous entries
|
||||
memset(&filelist, 0, sizeof(FILEENTRIES) * MAXFILES);
|
||||
|
||||
// add '../' folder
|
||||
strncpy(filelist[0].filename, "../", 3);
|
||||
filelist[0].length = rootdirlength; // store rootdir in case the user wants to go one folder up
|
||||
filelist[0].offset = rootdir; // -''- rootdir length -''-
|
||||
filelist[0].flags = 0;
|
||||
|
||||
// get contents and parse them into the dvd file list structure
|
||||
unsigned int SzI, SzJ;
|
||||
SzJ = 1;
|
||||
for(SzI = 0; SzI < SzDb.Database.NumFiles; SzI++)
|
||||
{
|
||||
SzF = SzDb.Database.Files + SzI;
|
||||
|
||||
// skip directories
|
||||
if(SzF->IsDirectory)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// do not exceed MAXFILES to avoid possible buffer overflows
|
||||
if(SzJ == (MAXFILES - 1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// parse information about this file to the dvd file list structure
|
||||
strncpy(filelist[SzJ].filename, SzF->Name, MAXJOLIET); // copy joliet name (useless...)
|
||||
filelist[SzJ].filename[MAXJOLIET] = 0; // terminate string
|
||||
filelist[SzJ].length = SzF->Size; // filesize
|
||||
filelist[SzJ].offset = SzI; // the extraction function identifies the file with this number
|
||||
filelist[SzJ].flags = 0; // only files will be displayed (-> no flags)
|
||||
SzJ++;
|
||||
}
|
||||
|
||||
// update maxfiles and select the first entry
|
||||
maxfiles = SzJ;
|
||||
offset = selection = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void SzClose(void)
|
||||
{
|
||||
SzArDbExFree(&SzDb, SzAllocImp.Free);
|
||||
}
|
||||
|
||||
bool SzExtractROM(int i, unsigned char *buffer)
|
||||
{
|
||||
|
||||
// prepare some variables
|
||||
SzBlockIndex = 0xFFFFFFFF;
|
||||
SzOffset = 0;
|
||||
|
||||
// Unzip the file
|
||||
ShowAction("Un7zipping file. Please wait...");
|
||||
SzRes = SzExtract2(
|
||||
&SzArchiveStream.InStream,
|
||||
&SzDb,
|
||||
i, /* index of file */
|
||||
&SzBlockIndex, /* index of solid block */
|
||||
&buffer,
|
||||
&SzBufferSize,
|
||||
&SzOffset, /* offset of stream for required file in *outBuffer */
|
||||
&SzOutSizeProcessed, /* size of file in *outBuffer */
|
||||
&SzAllocImp,
|
||||
&SzAllocTempImp);
|
||||
|
||||
// check for errors
|
||||
if(SzRes != SZ_OK)
|
||||
{
|
||||
// display error message
|
||||
WaitPrompt(szerrormsg[(SzRes - 1)]);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// close 7Zip archive and free memory
|
||||
SzArDbExFree(&SzDb, SzAllocImp.Free);
|
||||
return true;
|
||||
}
|
||||
}
|
46
source/drivers/gamecube/sz.h
Normal file
46
source/drivers/gamecube/sz.h
Normal file
@ -0,0 +1,46 @@
|
||||
/****************************************************************************
|
||||
* SZ.C
|
||||
* svpe June 2007
|
||||
*
|
||||
* This file manages the 7zip support for this emulator.
|
||||
* Currently it only provides functions for loading a 7zip file from a DVD.
|
||||
****************************************************************************/
|
||||
|
||||
#include <gccore.h>
|
||||
#include <ogcsys.h>
|
||||
#include <gctypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "7zCrc.h"
|
||||
#include "7zIn.h"
|
||||
#include "7zExtract.h"
|
||||
|
||||
typedef struct _SzFileInStream
|
||||
{
|
||||
ISzInStream InStream;
|
||||
u64 offset; // offset of the file
|
||||
unsigned int len; // length of the file
|
||||
u64 pos; // current position of the file pointer
|
||||
} SzFileInStream;
|
||||
|
||||
extern SZ_RESULT SzRes;
|
||||
|
||||
#define DVD_LENGTH_MULTIPLY 32
|
||||
#define DVD_OFFSET_MULTIPLY 32
|
||||
#define DVD_MAX_READ_LENGTH 2048
|
||||
#define DVD_SECTOR_SIZE 2048
|
||||
|
||||
int dvd_buffered_read(void *dst, u32 len, u64 offset);
|
||||
int dvd_safe_read(void *dst_v, u32 len, u64 offset);
|
||||
SZ_RESULT SzDvdFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize);
|
||||
SZ_RESULT SzDvdFileSeekImp(void *object, CFileSize pos);
|
||||
SZ_RESULT SzDvdIsArchive(u64 dvd_offset);
|
||||
void SzDisplayError(SZ_RESULT res);
|
||||
void SzParse(void);
|
||||
void SzClose(void);
|
||||
bool SzExtractROM(int i, unsigned char *buffer);
|
||||
|
||||
// pseudo-header file part for some functions used in the gamecube port
|
||||
extern unsigned int dvd_read(void *dst, unsigned int len, u64 offset);
|
||||
extern void WaitPrompt( char *msg );
|
||||
extern void ShowAction( char *msg );
|
103
source/endian.c
Normal file
103
source/endian.c
Normal file
@ -0,0 +1,103 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* Contains file I/O functions that write/read data */
|
||||
/* LSB first. */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "types.h"
|
||||
#include "endian.h"
|
||||
|
||||
void FlipByteOrder(uint8 *src, uint32 count)
|
||||
{
|
||||
uint8 *start=src;
|
||||
uint8 *end=src+count-1;
|
||||
|
||||
if((count&1) || !count) return; /* This shouldn't happen. */
|
||||
|
||||
while(count--)
|
||||
{
|
||||
uint8 tmp;
|
||||
|
||||
tmp=*end;
|
||||
*end=*start;
|
||||
*start=tmp;
|
||||
end--;
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
int write16le(uint16 b, FILE *fp)
|
||||
{
|
||||
uint8 s[2];
|
||||
s[0]=b;
|
||||
s[1]=b>>8;
|
||||
return((fwrite(s,1,2,fp)<2)?0:2);
|
||||
}
|
||||
|
||||
int write32le(uint32 b, FILE *fp)
|
||||
{
|
||||
uint8 s[4];
|
||||
s[0]=b;
|
||||
s[1]=b>>8;
|
||||
s[2]=b>>16;
|
||||
s[3]=b>>24;
|
||||
return((fwrite(s,1,4,fp)<4)?0:4);
|
||||
}
|
||||
|
||||
int read32le(uint32 *Bufo, FILE *fp)
|
||||
{
|
||||
uint32 buf;
|
||||
if(fread(&buf,1,4,fp)<4)
|
||||
return 0;
|
||||
#ifdef LSB_FIRST
|
||||
*(uint32*)Bufo=buf;
|
||||
#else
|
||||
*(uint32*)Bufo=((buf&0xFF)<<24)|((buf&0xFF00)<<8)|((buf&0xFF0000)>>8)|((buf&0xFF000000)>>24);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
int read16le(char *d, FILE *fp)
|
||||
{
|
||||
#ifdef LSB_FIRST
|
||||
return((fread(d,1,2,fp)<2)?0:2);
|
||||
#else
|
||||
int ret;
|
||||
ret=fread(d+1,1,1,fp);
|
||||
ret+=fread(d,1,1,fp);
|
||||
return ret<2?0:2;
|
||||
#endif
|
||||
}
|
||||
|
||||
void FCEU_en32lsb(uint8 *buf, uint32 morp)
|
||||
{
|
||||
buf[0]=morp;
|
||||
buf[1]=morp>>8;
|
||||
buf[2]=morp>>16;
|
||||
buf[3]=morp>>24;
|
||||
}
|
||||
|
||||
uint32 FCEU_de32lsb(uint8 *morp)
|
||||
{
|
||||
return(morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24));
|
||||
}
|
||||
|
7
source/endian.h
Normal file
7
source/endian.h
Normal file
@ -0,0 +1,7 @@
|
||||
int write16le(uint16 b, FILE *fp);
|
||||
int write32le(uint32 b, FILE *fp);
|
||||
int read32le(uint32 *Bufo, FILE *fp);
|
||||
void FlipByteOrder(uint8 *src, uint32 count);
|
||||
|
||||
void FCEU_en32lsb(uint8 *, uint32);
|
||||
uint32 FCEU_de32lsb(uint8 *);
|
505
source/fceu.c
Normal file
505
source/fceu.c
Normal file
@ -0,0 +1,505 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2003 Xodnizel
|
||||
*
|
||||
* 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 <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "x6502.h"
|
||||
#include "fceu.h"
|
||||
#include "ppu.h"
|
||||
#include "sound.h"
|
||||
#include "netplay.h"
|
||||
#include "general.h"
|
||||
#include "endian.h"
|
||||
#include "memory.h"
|
||||
|
||||
#include "cart.h"
|
||||
#include "nsf.h"
|
||||
#include "fds.h"
|
||||
#include "ines.h"
|
||||
#include "unif.h"
|
||||
#include "cheat.h"
|
||||
#include "palette.h"
|
||||
#include "state.h"
|
||||
#include "movie.h"
|
||||
#include "video.h"
|
||||
#include "input.h"
|
||||
#include "file.h"
|
||||
#include "crc32.h"
|
||||
#include "vsuni.h"
|
||||
|
||||
uint64 timestampbase;
|
||||
|
||||
|
||||
FCEUGI *FCEUGameInfo = NULL;
|
||||
void (*GameInterface)(int h);
|
||||
|
||||
void (*GameStateRestore)(int version);
|
||||
|
||||
readfunc ARead[0x10000];
|
||||
writefunc BWrite[0x10000];
|
||||
static readfunc *AReadG;
|
||||
static writefunc *BWriteG;
|
||||
static int RWWrap=0;
|
||||
|
||||
static DECLFW(BNull)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static DECLFR(ANull)
|
||||
{
|
||||
return(X.DB);
|
||||
}
|
||||
|
||||
int AllocGenieRW(void)
|
||||
{
|
||||
if(!(AReadG=(readfunc *)FCEU_malloc(0x8000*sizeof(readfunc))))
|
||||
return 0;
|
||||
if(!(BWriteG=(writefunc *)FCEU_malloc(0x8000*sizeof(writefunc))))
|
||||
return 0;
|
||||
RWWrap=1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void FlushGenieRW(void)
|
||||
{
|
||||
int32 x;
|
||||
|
||||
if(RWWrap)
|
||||
{
|
||||
for(x=0;x<0x8000;x++)
|
||||
{
|
||||
ARead[x+0x8000]=AReadG[x];
|
||||
BWrite[x+0x8000]=BWriteG[x];
|
||||
}
|
||||
free(AReadG);
|
||||
free(BWriteG);
|
||||
AReadG=0;
|
||||
BWriteG=0;
|
||||
RWWrap=0;
|
||||
}
|
||||
}
|
||||
|
||||
readfunc FASTAPASS(1) GetReadHandler(int32 a)
|
||||
{
|
||||
if(a>=0x8000 && RWWrap)
|
||||
return AReadG[a-0x8000];
|
||||
else
|
||||
return ARead[a];
|
||||
}
|
||||
|
||||
void FASTAPASS(3) SetReadHandler(int32 start, int32 end, readfunc func)
|
||||
{
|
||||
int32 x;
|
||||
|
||||
if(!func)
|
||||
func=ANull;
|
||||
|
||||
if(RWWrap)
|
||||
for(x=end;x>=start;x--)
|
||||
{
|
||||
if(x>=0x8000)
|
||||
AReadG[x-0x8000]=func;
|
||||
else
|
||||
ARead[x]=func;
|
||||
}
|
||||
else
|
||||
|
||||
for(x=end;x>=start;x--)
|
||||
ARead[x]=func;
|
||||
}
|
||||
|
||||
writefunc FASTAPASS(1) GetWriteHandler(int32 a)
|
||||
{
|
||||
if(RWWrap && a>=0x8000)
|
||||
return BWriteG[a-0x8000];
|
||||
else
|
||||
return BWrite[a];
|
||||
}
|
||||
|
||||
void FASTAPASS(3) SetWriteHandler(int32 start, int32 end, writefunc func)
|
||||
{
|
||||
int32 x;
|
||||
|
||||
if(!func)
|
||||
func=BNull;
|
||||
|
||||
if(RWWrap)
|
||||
for(x=end;x>=start;x--)
|
||||
{
|
||||
if(x>=0x8000)
|
||||
BWriteG[x-0x8000]=func;
|
||||
else
|
||||
BWrite[x]=func;
|
||||
}
|
||||
else
|
||||
for(x=end;x>=start;x--)
|
||||
BWrite[x]=func;
|
||||
}
|
||||
|
||||
uint8 GameMemBlock[131072];
|
||||
uint8 RAM[0x800];
|
||||
uint8 PAL=0;
|
||||
|
||||
static DECLFW(BRAML)
|
||||
{
|
||||
RAM[A]=V;
|
||||
}
|
||||
|
||||
static DECLFW(BRAMH)
|
||||
{
|
||||
RAM[A&0x7FF]=V;
|
||||
}
|
||||
|
||||
static DECLFR(ARAML)
|
||||
{
|
||||
return RAM[A];
|
||||
}
|
||||
|
||||
static DECLFR(ARAMH)
|
||||
{
|
||||
return RAM[A&0x7FF];
|
||||
}
|
||||
|
||||
static void CloseGame(void)
|
||||
{
|
||||
if(FCEUGameInfo)
|
||||
{
|
||||
//if(FCEUnetplay)
|
||||
// FCEUD_NetworkClose();
|
||||
if(FCEUGameInfo->name)
|
||||
{
|
||||
free(FCEUGameInfo->name);
|
||||
FCEUGameInfo->name=0;
|
||||
}
|
||||
if(FCEUGameInfo->type!=GIT_NSF)
|
||||
FCEU_FlushGameCheats(0,0);
|
||||
GameInterface(GI_CLOSE);
|
||||
ResetExState(0,0);
|
||||
//CloseGenie();
|
||||
free(FCEUGameInfo);
|
||||
FCEUGameInfo = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ResetGameLoaded(void)
|
||||
{
|
||||
if(FCEUGameInfo) CloseGame();
|
||||
GameStateRestore=0;
|
||||
PPU_hook=0;
|
||||
GameHBIRQHook=0;
|
||||
if(GameExpSound.Kill)
|
||||
GameExpSound.Kill();
|
||||
memset(&GameExpSound,0,sizeof(GameExpSound));
|
||||
MapIRQHook=0;
|
||||
MMC5Hack=0;
|
||||
PAL&=1;
|
||||
pale=0;
|
||||
}
|
||||
|
||||
int UNIFLoad(const char *name, FCEUFILE *fp);
|
||||
int iNESLoad(const char *name, FCEUFILE *fp);
|
||||
int FDSLoad(const char *name, FCEUFILE *fp);
|
||||
int NSFLoad(FCEUFILE *fp);
|
||||
|
||||
FCEUGI *FCEUI_LoadGame(const char *name)
|
||||
{
|
||||
FCEUFILE *fp;
|
||||
char *ipsfn;
|
||||
|
||||
ResetGameLoaded();
|
||||
|
||||
FCEUGameInfo = malloc(sizeof(FCEUGI));
|
||||
memset(FCEUGameInfo, 0, sizeof(FCEUGI));
|
||||
|
||||
FCEUGameInfo->soundchan = 0;
|
||||
FCEUGameInfo->soundrate = 0;
|
||||
FCEUGameInfo->name=0;
|
||||
FCEUGameInfo->type=GIT_CART;
|
||||
FCEUGameInfo->vidsys=GIV_USER;
|
||||
FCEUGameInfo->input[0]=FCEUGameInfo->input[1]=-1;
|
||||
FCEUGameInfo->inputfc=-1;
|
||||
FCEUGameInfo->cspecial=0;
|
||||
|
||||
FCEU_printf("Loading %s...\n\n",name);
|
||||
|
||||
GetFileBase(name);
|
||||
|
||||
ipsfn=FCEU_MakeFName(FCEUMKF_IPS,0,0);
|
||||
fp=FCEU_fopen(name,ipsfn,"rb",0);
|
||||
free(ipsfn);
|
||||
|
||||
if(!fp)
|
||||
{
|
||||
FCEU_PrintError("Error opening \"%s\"!",name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(iNESLoad(name,fp))
|
||||
goto endlseq;
|
||||
if(NSFLoad(fp))
|
||||
goto endlseq;
|
||||
if(UNIFLoad(name,fp))
|
||||
goto endlseq;
|
||||
if(FDSLoad(name,fp))
|
||||
goto endlseq;
|
||||
|
||||
FCEU_PrintError("An error occurred while loading the file.");
|
||||
FCEU_fclose(fp);
|
||||
return 0;
|
||||
|
||||
endlseq:
|
||||
FCEU_fclose(fp);
|
||||
|
||||
FCEU_ResetVidSys();
|
||||
if(FCEUGameInfo->type!=GIT_NSF)
|
||||
if(FSettings.GameGenie)
|
||||
OpenGenie();
|
||||
|
||||
PowerNES();
|
||||
FCEUSS_CheckStates();
|
||||
FCEUMOV_CheckMovies();
|
||||
|
||||
if(FCEUGameInfo->type!=GIT_NSF)
|
||||
{
|
||||
FCEU_LoadGamePalette();
|
||||
FCEU_LoadGameCheats(0);
|
||||
}
|
||||
|
||||
FCEU_ResetPalette();
|
||||
FCEU_ResetMessages(); // Save state, status messages, etc.
|
||||
|
||||
return(FCEUGameInfo);
|
||||
}
|
||||
|
||||
|
||||
int FCEUI_Initialize(void)
|
||||
{
|
||||
if(!FCEU_InitVirtualVideo())
|
||||
return 0;
|
||||
memset(&FSettings,0,sizeof(FSettings));
|
||||
FSettings.UsrFirstSLine[0]=8;
|
||||
FSettings.UsrFirstSLine[1]=0;
|
||||
FSettings.UsrLastSLine[0]=231;
|
||||
FSettings.UsrLastSLine[1]=239;
|
||||
FSettings.SoundVolume=100;
|
||||
FCEUPPU_Init();
|
||||
X6502_Init();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void FCEUI_Kill(void)
|
||||
{
|
||||
FCEU_KillVirtualVideo();
|
||||
FCEU_KillGenie();
|
||||
}
|
||||
|
||||
void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int skip)
|
||||
{
|
||||
int r,ssize;
|
||||
|
||||
FCEU_UpdateInput();
|
||||
if(geniestage!=1) FCEU_ApplyPeriodicCheats();
|
||||
r=FCEUPPU_Loop(skip);
|
||||
|
||||
ssize=FlushEmulateSound();
|
||||
|
||||
timestampbase += timestamp;
|
||||
timestamp = 0;
|
||||
|
||||
*pXBuf=skip?0:XBuf;
|
||||
*SoundBuf=WaveFinal;
|
||||
*SoundBufSize=ssize;
|
||||
}
|
||||
|
||||
void FCEUI_CloseGame(void)
|
||||
{
|
||||
CloseGame();
|
||||
}
|
||||
|
||||
void ResetNES(void)
|
||||
{
|
||||
FCEUMOV_AddCommand(FCEUNPCMD_RESET);
|
||||
if(!FCEUGameInfo) return;
|
||||
GameInterface(GI_RESETM2);
|
||||
FCEUSND_Reset();
|
||||
FCEUPPU_Reset();
|
||||
X6502_Reset();
|
||||
}
|
||||
|
||||
void FCEU_MemoryRand(uint8 *ptr, uint32 size)
|
||||
{
|
||||
int x=0;
|
||||
while(size)
|
||||
{
|
||||
*ptr=(x&4)?0xFF:0x00;
|
||||
x++;
|
||||
size--;
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
void hand(X6502 *X, int type, unsigned int A)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PowerNES(void)
|
||||
{
|
||||
FCEUMOV_AddCommand(FCEUNPCMD_POWER);
|
||||
if(!FCEUGameInfo) return;
|
||||
|
||||
FCEU_CheatResetRAM();
|
||||
FCEU_CheatAddRAM(2,0,RAM);
|
||||
|
||||
GeniePower();
|
||||
|
||||
FCEU_MemoryRand(RAM,0x800);
|
||||
//memset(RAM,0xFF,0x800);
|
||||
|
||||
SetReadHandler(0x0000,0xFFFF,ANull);
|
||||
SetWriteHandler(0x0000,0xFFFF,BNull);
|
||||
|
||||
SetReadHandler(0,0x7FF,ARAML);
|
||||
SetWriteHandler(0,0x7FF,BRAML);
|
||||
|
||||
SetReadHandler(0x800,0x1FFF,ARAMH); /* Part of a little */
|
||||
SetWriteHandler(0x800,0x1FFF,BRAMH); /* hack for a small speed boost. */
|
||||
|
||||
InitializeInput();
|
||||
FCEUSND_Power();
|
||||
FCEUPPU_Power();
|
||||
|
||||
/* Have the external game hardware "powered" after the internal NES stuff.
|
||||
Needed for the NSF code and VS System code.
|
||||
*/
|
||||
GameInterface(GI_POWER);
|
||||
if(FCEUGameInfo->type==GIT_VSUNI)
|
||||
FCEU_VSUniPower();
|
||||
|
||||
|
||||
timestampbase=0;
|
||||
X6502_Power();
|
||||
FCEU_PowerCheats();
|
||||
}
|
||||
|
||||
void FCEU_ResetVidSys(void)
|
||||
{
|
||||
int w;
|
||||
|
||||
if(FCEUGameInfo->vidsys==GIV_NTSC)
|
||||
w=0;
|
||||
else if(FCEUGameInfo->vidsys==GIV_PAL)
|
||||
w=1;
|
||||
else
|
||||
w=FSettings.PAL;
|
||||
|
||||
PAL=w?1:0;
|
||||
FCEUPPU_SetVideoSystem(w);
|
||||
SetSoundVariables();
|
||||
}
|
||||
|
||||
FCEUS FSettings;
|
||||
|
||||
void FCEU_printf(char *format, ...)
|
||||
{
|
||||
char temp[2048];
|
||||
|
||||
va_list ap;
|
||||
|
||||
va_start(ap,format);
|
||||
vsprintf(temp,format,ap);
|
||||
FCEUD_Message(temp);
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void FCEU_PrintError(char *format, ...)
|
||||
{
|
||||
char temp[2048];
|
||||
|
||||
va_list ap;
|
||||
|
||||
va_start(ap,format);
|
||||
vsprintf(temp,format,ap);
|
||||
FCEUD_PrintError(temp);
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall)
|
||||
{
|
||||
FSettings.UsrFirstSLine[0]=ntscf;
|
||||
FSettings.UsrLastSLine[0]=ntscl;
|
||||
FSettings.UsrFirstSLine[1]=palf;
|
||||
FSettings.UsrLastSLine[1]=pall;
|
||||
if(PAL)
|
||||
{
|
||||
FSettings.FirstSLine=FSettings.UsrFirstSLine[1];
|
||||
FSettings.LastSLine=FSettings.UsrLastSLine[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
FSettings.FirstSLine=FSettings.UsrFirstSLine[0];
|
||||
FSettings.LastSLine=FSettings.UsrLastSLine[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void FCEUI_SetVidSystem(int a)
|
||||
{
|
||||
FSettings.PAL=a?1:0;
|
||||
if(FCEUGameInfo)
|
||||
{
|
||||
FCEU_ResetVidSys();
|
||||
FCEU_ResetPalette();
|
||||
}
|
||||
}
|
||||
|
||||
int FCEUI_GetCurrentVidSystem(int *slstart, int *slend)
|
||||
{
|
||||
if(slstart)
|
||||
*slstart=FSettings.FirstSLine;
|
||||
if(slend)
|
||||
*slend=FSettings.LastSLine;
|
||||
return(PAL);
|
||||
}
|
||||
|
||||
void FCEUI_SetGameGenie(int a)
|
||||
{
|
||||
FSettings.GameGenie=a?1:0;
|
||||
}
|
||||
|
||||
void FCEUI_SetSnapName(int a)
|
||||
{
|
||||
FSettings.SnapName=a;
|
||||
}
|
||||
|
||||
int32 FCEUI_GetDesiredFPS(void)
|
||||
{
|
||||
if(PAL)
|
||||
return(838977920); // ~50.007
|
||||
else
|
||||
return(1008307711); // ~60.1
|
||||
}
|
1579
source/fceu.dev
Normal file
1579
source/fceu.dev
Normal file
File diff suppressed because it is too large
Load Diff
103
source/fceu.h
Normal file
103
source/fceu.h
Normal file
@ -0,0 +1,103 @@
|
||||
#ifndef _FCEUH
|
||||
extern int fceuindbg;
|
||||
void ResetGameLoaded(void);
|
||||
|
||||
#define DECLFR(x) uint8 FP_FASTAPASS(1) x (uint32 A)
|
||||
#define DECLFW(x) void FP_FASTAPASS(2) x (uint32 A, uint8 V)
|
||||
|
||||
void FCEU_MemoryRand(uint8 *ptr, uint32 size);
|
||||
void FASTAPASS(3) SetReadHandler(int32 start, int32 end, readfunc func);
|
||||
void FASTAPASS(3) SetWriteHandler(int32 start, int32 end, writefunc func);
|
||||
writefunc FASTAPASS(1) GetWriteHandler(int32 a);
|
||||
readfunc FASTAPASS(1) GetReadHandler(int32 a);
|
||||
|
||||
int AllocGenieRW(void);
|
||||
void FlushGenieRW(void);
|
||||
|
||||
void FCEU_ResetVidSys(void);
|
||||
|
||||
void ResetMapping(void);
|
||||
void ResetNES(void);
|
||||
void PowerNES(void);
|
||||
|
||||
|
||||
extern uint64 timestampbase;
|
||||
extern uint32 MMC5HackVROMMask;
|
||||
extern uint8 *MMC5HackExNTARAMPtr;
|
||||
extern int MMC5Hack;
|
||||
extern uint8 *MMC5HackVROMPTR;
|
||||
extern uint8 MMC5HackCHRMode;
|
||||
extern uint8 MMC5HackSPMode;
|
||||
extern uint8 MMC5HackSPScroll;
|
||||
extern uint8 MMC5HackSPPage;
|
||||
|
||||
extern uint8 RAM[0x800];
|
||||
extern uint8 GameMemBlock[131072];
|
||||
|
||||
extern readfunc ARead[0x10000];
|
||||
extern writefunc BWrite[0x10000];
|
||||
|
||||
extern void (*GameInterface)(int h);
|
||||
extern void (*GameStateRestore)(int version);
|
||||
|
||||
#define GI_RESETM2 1
|
||||
#define GI_POWER 2
|
||||
#define GI_CLOSE 3
|
||||
|
||||
#include "git.h"
|
||||
extern FCEUGI *FCEUGameInfo;
|
||||
extern int GameAttributes;
|
||||
|
||||
extern uint8 PAL;
|
||||
|
||||
#include "driver.h"
|
||||
|
||||
typedef struct {
|
||||
int PAL;
|
||||
int NetworkPlay;
|
||||
int SoundVolume;
|
||||
int GameGenie;
|
||||
|
||||
/* Current first and last rendered scanlines. */
|
||||
int FirstSLine;
|
||||
int LastSLine;
|
||||
|
||||
/* Driver code(user)-specified first and last rendered scanlines.
|
||||
Usr*SLine[0] is for NTSC, Usr*SLine[1] is for PAL.
|
||||
*/
|
||||
int UsrFirstSLine[2];
|
||||
int UsrLastSLine[2];
|
||||
int SnapName;
|
||||
uint32 SndRate;
|
||||
int soundq;
|
||||
int lowpass;
|
||||
} FCEUS;
|
||||
|
||||
extern FCEUS FSettings;
|
||||
|
||||
void FCEU_PrintError(char *format, ...);
|
||||
void FCEU_printf(char *format, ...);
|
||||
void FCEU_DispMessage(char *format, ...);
|
||||
|
||||
void SetNESDeemph(uint8 d, int force);
|
||||
void DrawTextTrans(uint8 *dest, uint32 width, uint8 *textmsg, uint8 fgcolor);
|
||||
void FCEU_PutImage(void);
|
||||
#ifdef FRAMESKIP
|
||||
void FCEU_PutImageDummy(void);
|
||||
#endif
|
||||
|
||||
extern uint8 Exit;
|
||||
extern uint8 pale;
|
||||
extern uint8 vsdip;
|
||||
|
||||
#define JOY_A 1
|
||||
#define JOY_B 2
|
||||
#define JOY_SELECT 4
|
||||
#define JOY_START 8
|
||||
#define JOY_UP 0x10
|
||||
#define JOY_DOWN 0x20
|
||||
#define JOY_LEFT 0x40
|
||||
#define JOY_RIGHT 0x80
|
||||
#else
|
||||
#define _FCEUH
|
||||
#endif
|
506
source/fceu.layout
Normal file
506
source/fceu.layout
Normal file
@ -0,0 +1,506 @@
|
||||
[Editor_109]
|
||||
CursorCol=1
|
||||
CursorRow=1
|
||||
TopLine=1
|
||||
LeftChar=1
|
||||
Open=0
|
||||
Top=0
|
||||
[Editors]
|
||||
Focused=-1
|
||||
Order=132,-1
|
||||
[Editor_0]
|
||||
Open=1
|
||||
Top=1
|
||||
CursorCol=2
|
||||
CursorRow=101
|
||||
TopLine=72
|
||||
LeftChar=1
|
||||
[Editor_1]
|
||||
Open=0
|
||||
Top=0
|
||||
CursorCol=1
|
||||
CursorRow=21
|
||||
TopLine=1
|
||||
LeftChar=1
|
||||
[Editor_2]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_3]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_4]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_5]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_6]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_7]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_8]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_9]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_10]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_11]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_12]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_13]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_14]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_15]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_16]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_17]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_18]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_19]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_20]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_21]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_22]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_23]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_24]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_25]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_26]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_27]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_28]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_29]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_30]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_31]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_32]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_33]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_34]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_35]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_36]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_37]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_38]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_39]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_40]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_41]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_42]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_43]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_44]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_45]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_46]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_47]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_48]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_49]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_50]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_51]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_52]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_53]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_54]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_55]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_56]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_57]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_58]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_59]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_60]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_61]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_62]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_63]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_64]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_65]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_66]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_67]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_68]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_69]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_70]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_71]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_72]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_73]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_74]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_75]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_76]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_77]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_78]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_79]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_80]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_81]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_82]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_83]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_84]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_85]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_86]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_87]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_88]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_89]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_90]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_91]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_92]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_93]
|
||||
Open=0
|
||||
Top=0
|
||||
CursorCol=2
|
||||
CursorRow=106
|
||||
TopLine=90
|
||||
LeftChar=1
|
||||
[Editor_94]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_95]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_96]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_97]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_98]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_99]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_100]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_101]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_102]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_103]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_104]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_105]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_106]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_107]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_108]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_110]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_111]
|
||||
Open=0
|
||||
Top=0
|
||||
CursorCol=1
|
||||
CursorRow=1
|
||||
TopLine=1
|
||||
LeftChar=1
|
||||
[Editor_112]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_113]
|
||||
Open=0
|
||||
Top=0
|
||||
CursorCol=1
|
||||
CursorRow=1
|
||||
TopLine=358
|
||||
LeftChar=1
|
||||
[Editor_114]
|
||||
Open=0
|
||||
Top=0
|
||||
CursorCol=1
|
||||
CursorRow=1
|
||||
TopLine=816
|
||||
LeftChar=1
|
||||
[Editor_115]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_116]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_117]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_118]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_119]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_120]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_121]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_122]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_123]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_124]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_125]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_126]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_127]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_128]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_129]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_130]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_131]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_132]
|
||||
Open=1
|
||||
Top=0
|
||||
CursorCol=20
|
||||
CursorRow=8
|
||||
TopLine=1
|
||||
LeftChar=1
|
||||
[Editor_133]
|
||||
Open=0
|
||||
Top=0
|
||||
CursorCol=34
|
||||
CursorRow=15
|
||||
TopLine=1
|
||||
LeftChar=1
|
||||
[Editor_134]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_135]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_136]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_137]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_138]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_139]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_140]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_141]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_142]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_143]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_144]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_145]
|
||||
Open=0
|
||||
Top=0
|
||||
CursorCol=1
|
||||
CursorRow=3
|
||||
TopLine=1
|
||||
LeftChar=1
|
||||
[Editor_146]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_147]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_148]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_149]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_150]
|
||||
Open=0
|
||||
Top=0
|
||||
[Editor_151]
|
||||
Open=1
|
||||
Top=0
|
||||
CursorCol=26
|
||||
CursorRow=11
|
||||
TopLine=2
|
||||
LeftChar=1
|
||||
[Editor_152]
|
||||
Open=0
|
||||
Top=0
|
27
source/fceustr.c
Normal file
27
source/fceustr.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "fceustr.h"
|
||||
|
||||
|
||||
/* Creates a fceustr from a C-style string. */
|
||||
fceustr *fceustr_create(const char *str)
|
||||
{
|
||||
fceustr *ret;
|
||||
|
||||
ret=malloc(sizeof(fceustr));
|
||||
|
||||
ret->data=malloc(strlen(str)+1);
|
||||
strcpy(ret->data,str);
|
||||
|
||||
ret->len=strlen(str);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void fceustr_destroy(fceustr *str)
|
||||
{
|
||||
if(str->data) free(str->data);
|
||||
free(str);
|
||||
}
|
4
source/fceustr.h
Normal file
4
source/fceustr.h
Normal file
@ -0,0 +1,4 @@
|
||||
typedef struct {
|
||||
uint8 *data;
|
||||
uint32 len; /* Not including extra NULL character. */
|
||||
} fceustr;
|
1589
source/fcoeffs.h
Normal file
1589
source/fcoeffs.h
Normal file
File diff suppressed because it is too large
Load Diff
874
source/fds.c
Normal file
874
source/fds.c
Normal file
@ -0,0 +1,874 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "x6502.h"
|
||||
#include "fceu.h"
|
||||
#include "fds.h"
|
||||
#include "sound.h"
|
||||
#include "general.h"
|
||||
#include "state.h"
|
||||
#include "file.h"
|
||||
#include "memory.h"
|
||||
#include "cart.h"
|
||||
#include "md5.h"
|
||||
#include "netplay.h"
|
||||
|
||||
/* TODO: Add code to put a delay in between the time a disk is inserted
|
||||
and the when it can be successfully read/written to. This should
|
||||
prevent writes to wrong places OR add code to prevent disk ejects
|
||||
when the virtual motor is on(mmm...virtual motor).
|
||||
*/
|
||||
|
||||
static DECLFR(FDSRead4030);
|
||||
static DECLFR(FDSRead4031);
|
||||
static DECLFR(FDSRead4032);
|
||||
static DECLFR(FDSRead4033);
|
||||
|
||||
static DECLFW(FDSWrite);
|
||||
|
||||
static DECLFW(FDSWaveWrite);
|
||||
static DECLFR(FDSWaveRead);
|
||||
|
||||
static DECLFR(FDSSRead);
|
||||
static DECLFW(FDSSWrite);
|
||||
static DECLFR(FDSBIOSRead);
|
||||
static DECLFR(FDSRAMRead);
|
||||
static DECLFW(FDSRAMWrite);
|
||||
static void FDSInit(void);
|
||||
static void FP_FASTAPASS(1) FDSFix(int a);
|
||||
|
||||
#define FDSRAM GameMemBlock
|
||||
#define CHRRAM (GameMemBlock+32768)
|
||||
|
||||
static uint8 FDSRegs[6];
|
||||
static int32 IRQLatch,IRQCount;
|
||||
static uint8 IRQa;
|
||||
static void FDSClose(void);
|
||||
|
||||
static uint8 FDSBIOS[8192];
|
||||
|
||||
/* Original disk data backup, to help in creating save states. */
|
||||
static uint8 *diskdatao[8]={0,0,0,0,0,0,0,0};
|
||||
|
||||
static uint8 *diskdata[8]={0,0,0,0,0,0,0,0};
|
||||
|
||||
static unsigned int TotalSides;
|
||||
static uint8 DiskWritten=0; /* Set to 1 if disk was written to. */
|
||||
static uint8 writeskip;
|
||||
static uint32 DiskPtr;
|
||||
static int32 DiskSeekIRQ;
|
||||
static uint8 SelectDisk,InDisk;
|
||||
|
||||
#define DC_INC 1
|
||||
|
||||
void FDSGI(int h)
|
||||
{
|
||||
switch(h)
|
||||
{
|
||||
case GI_CLOSE: FDSClose();break;
|
||||
case GI_POWER: FDSInit();break;
|
||||
}
|
||||
}
|
||||
|
||||
static void FDSStateRestore(int version)
|
||||
{
|
||||
int x;
|
||||
|
||||
setmirror(((FDSRegs[5]&8)>>3)^1);
|
||||
|
||||
if(version >= 9810)
|
||||
for(x=0;x<TotalSides;x++)
|
||||
{
|
||||
int b;
|
||||
for(b=0; b<65500; b++)
|
||||
diskdata[x][b] ^= diskdatao[x][b];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void FDSSound();
|
||||
void FDSSoundReset(void);
|
||||
void FDSSoundStateAdd(void);
|
||||
static void RenderSound(void);
|
||||
static void RenderSoundHQ(void);
|
||||
|
||||
static void FDSInit(void)
|
||||
{
|
||||
memset(FDSRegs,0,sizeof(FDSRegs));
|
||||
writeskip=DiskPtr=DiskSeekIRQ=0;
|
||||
setmirror(1);
|
||||
|
||||
setprg8r(0,0xe000,0); // BIOS
|
||||
setprg32r(1,0x6000,0); // 32KB RAM
|
||||
setchr8(0); // 8KB CHR RAM
|
||||
|
||||
MapIRQHook=FDSFix;
|
||||
GameStateRestore=FDSStateRestore;
|
||||
|
||||
SetReadHandler(0x4030,0x4030,FDSRead4030);
|
||||
SetReadHandler(0x4031,0x4031,FDSRead4031);
|
||||
SetReadHandler(0x4032,0x4032,FDSRead4032);
|
||||
SetReadHandler(0x4033,0x4033,FDSRead4033);
|
||||
|
||||
SetWriteHandler(0x4020,0x4025,FDSWrite);
|
||||
|
||||
SetWriteHandler(0x6000,0xdfff,FDSRAMWrite);
|
||||
SetReadHandler(0x6000,0xdfff,FDSRAMRead);
|
||||
SetReadHandler(0xE000,0xFFFF,FDSBIOSRead);
|
||||
IRQCount=IRQLatch=IRQa=0;
|
||||
|
||||
FDSSoundReset();
|
||||
InDisk=0;
|
||||
SelectDisk=0;
|
||||
}
|
||||
|
||||
void FCEU_FDSInsert(int oride)
|
||||
{
|
||||
if(InDisk==255)
|
||||
{
|
||||
FCEU_DispMessage("Disk %d Side %s Inserted",SelectDisk>>1,(SelectDisk&1)?"B":"A");
|
||||
InDisk=SelectDisk;
|
||||
}
|
||||
else
|
||||
{
|
||||
FCEU_DispMessage("Disk %d Side %s Ejected",SelectDisk>>1,(SelectDisk&1)?"B":"A");
|
||||
InDisk=255;
|
||||
}
|
||||
}
|
||||
|
||||
void FCEU_FDSEject(void)
|
||||
{
|
||||
InDisk=255;
|
||||
}
|
||||
|
||||
void FCEU_FDSSelect(void)
|
||||
{
|
||||
if(InDisk!=255)
|
||||
{
|
||||
FCEU_DispMessage("Eject disk before selecting.");
|
||||
return;
|
||||
}
|
||||
SelectDisk=((SelectDisk+1)%TotalSides)&3;
|
||||
FCEU_DispMessage("Disk %d Side %s Selected",SelectDisk>>1,(SelectDisk&1)?"B":"A");
|
||||
}
|
||||
|
||||
static void FP_FASTAPASS(1) FDSFix(int a)
|
||||
{
|
||||
if((IRQa&2) && IRQCount)
|
||||
{
|
||||
IRQCount-=a;
|
||||
if(IRQCount<=0)
|
||||
{
|
||||
if(!(IRQa&1))
|
||||
{
|
||||
IRQa&=~2;
|
||||
IRQCount=IRQLatch=0;
|
||||
}
|
||||
else
|
||||
IRQCount=IRQLatch;
|
||||
//IRQCount=IRQLatch; //0xFFFF;
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
//printf("IRQ: %d\n",timestamp);
|
||||
// printf("IRQ: %d\n",scanline);
|
||||
}
|
||||
}
|
||||
if(DiskSeekIRQ>0)
|
||||
{
|
||||
DiskSeekIRQ-=a;
|
||||
if(DiskSeekIRQ<=0)
|
||||
{
|
||||
if(FDSRegs[5]&0x80)
|
||||
{
|
||||
X6502_IRQBegin(FCEU_IQEXT2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(FDSRead4030)
|
||||
{
|
||||
uint8 ret=0;
|
||||
|
||||
/* Cheap hack. */
|
||||
if(X.IRQlow&FCEU_IQEXT) ret|=1;
|
||||
if(X.IRQlow&FCEU_IQEXT2) ret|=2;
|
||||
|
||||
if(!fceuindbg)
|
||||
{
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
X6502_IRQEnd(FCEU_IQEXT2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DECLFR(FDSRead4031)
|
||||
{
|
||||
static uint8 z=0;
|
||||
if(InDisk!=255)
|
||||
{
|
||||
z=diskdata[InDisk][DiskPtr];
|
||||
if(!fceuindbg)
|
||||
{
|
||||
if(DiskPtr<64999) DiskPtr++;
|
||||
DiskSeekIRQ=150;
|
||||
X6502_IRQEnd(FCEU_IQEXT2);
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
static DECLFR(FDSRead4032)
|
||||
{
|
||||
uint8 ret;
|
||||
|
||||
ret=X.DB&~7;
|
||||
if(InDisk==255)
|
||||
ret|=5;
|
||||
|
||||
if(InDisk==255 || !(FDSRegs[5]&1) || (FDSRegs[5]&2))
|
||||
ret|=2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DECLFR(FDSRead4033)
|
||||
{
|
||||
return 0x80; // battery
|
||||
}
|
||||
|
||||
static DECLFW(FDSRAMWrite)
|
||||
{
|
||||
(FDSRAM-0x6000)[A]=V;
|
||||
}
|
||||
|
||||
static DECLFR(FDSBIOSRead)
|
||||
{
|
||||
return (FDSBIOS-0xE000)[A];
|
||||
}
|
||||
|
||||
static DECLFR(FDSRAMRead)
|
||||
{
|
||||
return (FDSRAM-0x6000)[A];
|
||||
}
|
||||
|
||||
/* Begin FDS sound */
|
||||
|
||||
#define FDSClock (1789772.7272727272727272/2)
|
||||
|
||||
typedef struct {
|
||||
int64 cycles; // Cycles per PCM sample
|
||||
int64 count; // Cycle counter
|
||||
int64 envcount; // Envelope cycle counter
|
||||
uint32 b19shiftreg60;
|
||||
uint32 b24adder66;
|
||||
uint32 b24latch68;
|
||||
uint32 b17latch76;
|
||||
int32 clockcount; // Counter to divide frequency by 8.
|
||||
uint8 b8shiftreg88; // Modulation register.
|
||||
uint8 amplitude[2]; // Current amplitudes.
|
||||
uint8 speedo[2];
|
||||
uint8 mwcount;
|
||||
uint8 mwstart;
|
||||
uint8 mwave[0x20]; // Modulation waveform
|
||||
uint8 cwave[0x40]; // Game-defined waveform(carrier)
|
||||
uint8 SPSG[0xB];
|
||||
} FDSSOUND;
|
||||
|
||||
static FDSSOUND fdso;
|
||||
|
||||
#define SPSG fdso.SPSG
|
||||
#define b19shiftreg60 fdso.b19shiftreg60
|
||||
#define b24adder66 fdso.b24adder66
|
||||
#define b24latch68 fdso.b24latch68
|
||||
#define b17latch76 fdso.b17latch76
|
||||
#define b8shiftreg88 fdso.b8shiftreg88
|
||||
#define clockcount fdso.clockcount
|
||||
#define amplitude fdso.amplitude
|
||||
#define speedo fdso.speedo
|
||||
|
||||
void FDSSoundStateAdd(void)
|
||||
{
|
||||
AddExState(fdso.cwave,64,0,"WAVE");
|
||||
AddExState(fdso.mwave,32,0,"MWAV");
|
||||
AddExState(amplitude,2,0,"AMPL");
|
||||
AddExState(SPSG,0xB,0,"SPSG");
|
||||
|
||||
AddExState(&b8shiftreg88,1,0,"B88");
|
||||
|
||||
AddExState(&clockcount, 4, 1, "CLOC");
|
||||
AddExState(&b19shiftreg60,4,1,"B60");
|
||||
AddExState(&b24adder66,4,1,"B66");
|
||||
AddExState(&b24latch68,4,1,"B68");
|
||||
AddExState(&b17latch76,4,1,"B76");
|
||||
|
||||
}
|
||||
|
||||
static DECLFR(FDSSRead)
|
||||
{
|
||||
switch(A&0xF)
|
||||
{
|
||||
case 0x0:return(amplitude[0]|(X.DB&0xC0));
|
||||
case 0x2:return(amplitude[1]|(X.DB&0xC0));
|
||||
}
|
||||
return(X.DB);
|
||||
}
|
||||
|
||||
static DECLFW(FDSSWrite)
|
||||
{
|
||||
if(FSettings.SndRate)
|
||||
{
|
||||
if(FSettings.soundq>=1)
|
||||
RenderSoundHQ();
|
||||
else
|
||||
RenderSound();
|
||||
}
|
||||
A-=0x4080;
|
||||
switch(A)
|
||||
{
|
||||
case 0x0:
|
||||
case 0x4: if(V&0x80)
|
||||
amplitude[(A&0xF)>>2]=V&0x3F; //)>0x20?0x20:(V&0x3F);
|
||||
break;
|
||||
case 0x5://printf("$%04x:$%02x\n",A,V);
|
||||
break;
|
||||
case 0x7: b17latch76=0;SPSG[0x5]=0;//printf("$%04x:$%02x\n",A,V);
|
||||
break;
|
||||
case 0x8:
|
||||
b17latch76=0;
|
||||
// printf("%d:$%02x, $%02x\n",SPSG[0x5],V,b17latch76);
|
||||
fdso.mwave[SPSG[0x5]&0x1F]=V&0x7;
|
||||
SPSG[0x5]=(SPSG[0x5]+1)&0x1F;
|
||||
break;
|
||||
}
|
||||
//if(A>=0x7 && A!=0x8 && A<=0xF)
|
||||
//if(A==0xA || A==0x9)
|
||||
//printf("$%04x:$%02x\n",A,V);
|
||||
SPSG[A]=V;
|
||||
}
|
||||
|
||||
// $4080 - Fundamental wave amplitude data register 92
|
||||
// $4082 - Fundamental wave frequency data register 58
|
||||
// $4083 - Same as $4082($4083 is the upper 4 bits).
|
||||
|
||||
// $4084 - Modulation amplitude data register 78
|
||||
// $4086 - Modulation frequency data register 72
|
||||
// $4087 - Same as $4086($4087 is the upper 4 bits)
|
||||
|
||||
|
||||
static void DoEnv()
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x=0;x<2;x++)
|
||||
if(!(SPSG[x<<2]&0x80) && !(SPSG[0x3]&0x40))
|
||||
{
|
||||
static int counto[2]={0,0};
|
||||
|
||||
if(counto[x]<=0)
|
||||
{
|
||||
if(!(SPSG[x<<2]&0x80))
|
||||
{
|
||||
if(SPSG[x<<2]&0x40)
|
||||
{
|
||||
if(amplitude[x]<0x3F)
|
||||
amplitude[x]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(amplitude[x]>0)
|
||||
amplitude[x]--;
|
||||
}
|
||||
}
|
||||
counto[x]=(SPSG[x<<2]&0x3F);
|
||||
}
|
||||
else
|
||||
counto[x]--;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(FDSWaveRead)
|
||||
{
|
||||
return(fdso.cwave[A&0x3f]|(X.DB&0xC0));
|
||||
}
|
||||
|
||||
static DECLFW(FDSWaveWrite)
|
||||
{
|
||||
//printf("$%04x:$%02x, %d\n",A,V,SPSG[0x9]&0x80);
|
||||
if(SPSG[0x9]&0x80)
|
||||
fdso.cwave[A&0x3f]=V&0x3F;
|
||||
}
|
||||
|
||||
static int ta;
|
||||
static INLINE void ClockRise(void)
|
||||
{
|
||||
if(!clockcount)
|
||||
{
|
||||
ta++;
|
||||
|
||||
b19shiftreg60=(SPSG[0x2]|((SPSG[0x3]&0xF)<<8));
|
||||
b17latch76=(SPSG[0x6]|((SPSG[0x07]&0xF)<<8))+b17latch76;
|
||||
|
||||
if(!(SPSG[0x7]&0x80))
|
||||
{
|
||||
int t=fdso.mwave[(b17latch76>>13)&0x1F]&7;
|
||||
int t2=amplitude[1];
|
||||
int adj = 0;
|
||||
|
||||
if((t&3))
|
||||
{
|
||||
if((t&4))
|
||||
adj -= (t2 * ((4 - (t&3) ) ));
|
||||
else
|
||||
adj += (t2 * ( (t&3) ));
|
||||
}
|
||||
adj *= 2;
|
||||
if(adj > 0x7F) adj = 0x7F;
|
||||
if(adj < -0x80) adj = -0x80;
|
||||
//if(adj) printf("%d ",adj);
|
||||
b8shiftreg88=0x80 + adj;
|
||||
}
|
||||
else
|
||||
{
|
||||
b8shiftreg88=0x80;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
b19shiftreg60<<=1;
|
||||
b8shiftreg88>>=1;
|
||||
}
|
||||
// b24adder66=(b24latch68+b19shiftreg60)&0x3FFFFFF;
|
||||
b24adder66=(b24latch68+b19shiftreg60)&0x1FFFFFF;
|
||||
}
|
||||
|
||||
static INLINE void ClockFall(void)
|
||||
{
|
||||
//if(!(SPSG[0x7]&0x80))
|
||||
{
|
||||
if((b8shiftreg88&1)) // || clockcount==7)
|
||||
b24latch68=b24adder66;
|
||||
}
|
||||
clockcount=(clockcount+1)&7;
|
||||
}
|
||||
|
||||
static INLINE int32 FDSDoSound(void)
|
||||
{
|
||||
fdso.count+=fdso.cycles;
|
||||
if(fdso.count>=((int64)1<<40))
|
||||
{
|
||||
dogk:
|
||||
fdso.count-=(int64)1<<40;
|
||||
ClockRise();
|
||||
ClockFall();
|
||||
fdso.envcount--;
|
||||
if(fdso.envcount<=0)
|
||||
{
|
||||
fdso.envcount+=SPSG[0xA]*3;
|
||||
DoEnv();
|
||||
}
|
||||
}
|
||||
if(fdso.count>=32768) goto dogk;
|
||||
|
||||
// Might need to emulate applying the amplitude to the waveform a bit better...
|
||||
{
|
||||
int k=amplitude[0];
|
||||
if(k>0x20) k=0x20;
|
||||
return (fdso.cwave[b24latch68>>19]*k)*4/((SPSG[0x9]&0x3)+2);
|
||||
}
|
||||
}
|
||||
|
||||
static int32 FBC=0;
|
||||
|
||||
static void RenderSound(void)
|
||||
{
|
||||
int32 end, start;
|
||||
int32 x;
|
||||
|
||||
start=FBC;
|
||||
end=(SOUNDTS<<16)/soundtsinc;
|
||||
if(end<=start)
|
||||
return;
|
||||
FBC=end;
|
||||
|
||||
if(!(SPSG[0x9]&0x80))
|
||||
for(x=start;x<end;x++)
|
||||
{
|
||||
uint32 t=FDSDoSound();
|
||||
t+=t>>1;
|
||||
t>>=4;
|
||||
Wave[x>>4]+=t; //(t>>2)-(t>>3); //>>3;
|
||||
}
|
||||
}
|
||||
|
||||
static void RenderSoundHQ(void)
|
||||
{
|
||||
int32 x;
|
||||
|
||||
if(!(SPSG[0x9]&0x80))
|
||||
for(x=FBC;x<SOUNDTS;x++)
|
||||
{
|
||||
uint32 t=FDSDoSound();
|
||||
t+=t>>1;
|
||||
WaveHi[x]+=t; //(t<<2)-(t<<1);
|
||||
}
|
||||
FBC=SOUNDTS;
|
||||
}
|
||||
|
||||
static void HQSync(int32 ts)
|
||||
{
|
||||
FBC=ts;
|
||||
}
|
||||
|
||||
void FDSSound(int c)
|
||||
{
|
||||
RenderSound();
|
||||
FBC=c;
|
||||
}
|
||||
|
||||
/*
|
||||
static DECLFR(FDSBIOSPatch)
|
||||
{
|
||||
if(FDSRegs[5]&0x4)
|
||||
{
|
||||
X.X=FDSRead4031(0x4031);
|
||||
FDSWrite(0x4024,X.A);
|
||||
X.A=X.X;
|
||||
return(0x60);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(0x58);
|
||||
//puts("Write");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static void FDS_ESI(void)
|
||||
{
|
||||
if(FSettings.SndRate)
|
||||
{
|
||||
if(FSettings.soundq>=1)
|
||||
{
|
||||
fdso.cycles=(int64)1<<39;
|
||||
}
|
||||
else
|
||||
{
|
||||
fdso.cycles=((int64)1<<40)*FDSClock;
|
||||
fdso.cycles/=FSettings.SndRate *16;
|
||||
}
|
||||
}
|
||||
// fdso.cycles=(int64)32768*FDSClock/(FSettings.SndRate *16);
|
||||
SetReadHandler(0x4040,0x407f,FDSWaveRead);
|
||||
SetWriteHandler(0x4040,0x407f,FDSWaveWrite);
|
||||
SetWriteHandler(0x4080,0x408A,FDSSWrite);
|
||||
SetReadHandler(0x4090,0x4092,FDSSRead);
|
||||
|
||||
//SetReadHandler(0xE7A3,0xE7A3,FDSBIOSPatch);
|
||||
}
|
||||
|
||||
void FDSSoundReset(void)
|
||||
{
|
||||
memset(&fdso,0,sizeof(fdso));
|
||||
FDS_ESI();
|
||||
GameExpSound.HiSync=HQSync;
|
||||
GameExpSound.HiFill=RenderSoundHQ;
|
||||
GameExpSound.Fill=FDSSound;
|
||||
GameExpSound.RChange=FDS_ESI;
|
||||
}
|
||||
|
||||
static DECLFW(FDSWrite)
|
||||
{
|
||||
//extern int scanline;
|
||||
//FCEU_printf("$%04x:$%02x, %d\n",A,V,scanline);
|
||||
switch(A)
|
||||
{
|
||||
case 0x4020:
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
IRQLatch&=0xFF00;
|
||||
IRQLatch|=V;
|
||||
// printf("$%04x:$%02x\n",A,V);
|
||||
break;
|
||||
case 0x4021:
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
IRQLatch&=0xFF;
|
||||
IRQLatch|=V<<8;
|
||||
// printf("$%04x:$%02x\n",A,V);
|
||||
break;
|
||||
case 0x4022:
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
IRQCount=IRQLatch;
|
||||
IRQa=V&3;
|
||||
// printf("$%04x:$%02x\n",A,V);
|
||||
break;
|
||||
case 0x4023:break;
|
||||
case 0x4024:
|
||||
if(InDisk!=255 && !(FDSRegs[5]&0x4) && (FDSRegs[3]&0x1))
|
||||
{
|
||||
if(DiskPtr>=0 && DiskPtr<65500)
|
||||
{
|
||||
if(writeskip) writeskip--;
|
||||
else if(DiskPtr>=2)
|
||||
{
|
||||
DiskWritten=1;
|
||||
diskdata[InDisk][DiskPtr-2]=V;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x4025:
|
||||
X6502_IRQEnd(FCEU_IQEXT2);
|
||||
if(InDisk!=255)
|
||||
{
|
||||
if(!(V&0x40))
|
||||
{
|
||||
if(FDSRegs[5]&0x40 && !(V&0x10))
|
||||
{
|
||||
DiskSeekIRQ=200;
|
||||
DiskPtr-=2;
|
||||
}
|
||||
if(DiskPtr<0) DiskPtr=0;
|
||||
}
|
||||
if(!(V&0x4)) writeskip=2;
|
||||
if(V&2) {DiskPtr=0;DiskSeekIRQ=200;}
|
||||
if(V&0x40) DiskSeekIRQ=200;
|
||||
}
|
||||
setmirror(((V>>3)&1)^1);
|
||||
break;
|
||||
}
|
||||
FDSRegs[A&7]=V;
|
||||
}
|
||||
|
||||
static void FreeFDSMemory(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x=0;x<TotalSides;x++)
|
||||
if(diskdata[x])
|
||||
{
|
||||
free(diskdata[x]);
|
||||
diskdata[x]=0;
|
||||
}
|
||||
}
|
||||
|
||||
static int SubLoad(FCEUFILE *fp)
|
||||
{
|
||||
struct md5_context md5;
|
||||
uint8 header[16];
|
||||
int x;
|
||||
|
||||
FCEU_fread(header,16,1,fp);
|
||||
|
||||
if(memcmp(header,"FDS\x1a",4))
|
||||
{
|
||||
if(!(memcmp(header+1,"*NINTENDO-HVC*",14)))
|
||||
{
|
||||
long t;
|
||||
t=FCEU_fgetsize(fp);
|
||||
if(t<65500)
|
||||
t=65500;
|
||||
TotalSides=t/65500;
|
||||
FCEU_fseek(fp,0,SEEK_SET);
|
||||
}
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
TotalSides=header[4];
|
||||
|
||||
md5_starts(&md5);
|
||||
|
||||
if(TotalSides>8) TotalSides=8;
|
||||
if(TotalSides<1) TotalSides=1;
|
||||
|
||||
for(x=0;x<TotalSides;x++)
|
||||
{
|
||||
diskdata[x]=(uint8 *)FCEU_malloc(65500);
|
||||
if(!diskdata[x])
|
||||
{
|
||||
int zol;
|
||||
for(zol=0;zol<x;zol++)
|
||||
free(diskdata[zol]);
|
||||
return 0;
|
||||
}
|
||||
FCEU_fread(diskdata[x],1,65500,fp);
|
||||
md5_update(&md5,diskdata[x],65500);
|
||||
}
|
||||
md5_finish(&md5,FCEUGameInfo->MD5);
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void PreSave(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
//if(DiskWritten)
|
||||
for(x=0;x<TotalSides;x++)
|
||||
{
|
||||
int b;
|
||||
for(b=0; b<65500; b++)
|
||||
diskdata[x][b] ^= diskdatao[x][b];
|
||||
}
|
||||
}
|
||||
|
||||
static void PostSave(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
//if(DiskWritten)
|
||||
for(x=0;x<TotalSides;x++)
|
||||
{
|
||||
int b;
|
||||
|
||||
for(b=0; b<65500; b++)
|
||||
diskdata[x][b] ^= diskdatao[x][b];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int FDSLoad(const char *name, FCEUFILE *fp)
|
||||
{
|
||||
FILE *zp;
|
||||
int x;
|
||||
char *fn;
|
||||
|
||||
FCEU_fseek(fp,0,SEEK_SET);
|
||||
|
||||
if(!SubLoad(fp))
|
||||
return(0);
|
||||
|
||||
|
||||
fn = FCEU_MakeFName(FCEUMKF_FDSROM,0,0);
|
||||
|
||||
if(!(zp=FCEUD_UTF8fopen(fn,"rb")))
|
||||
{
|
||||
FCEU_PrintError("FDS BIOS ROM image missing!");
|
||||
FreeFDSMemory();
|
||||
free(fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(fn);
|
||||
|
||||
if(fread(FDSBIOS,1,8192,zp)!=8192)
|
||||
{
|
||||
fclose(zp);
|
||||
FreeFDSMemory();
|
||||
FCEU_PrintError("Error reading FDS BIOS ROM image.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fclose(zp);
|
||||
|
||||
|
||||
{
|
||||
FCEUFILE *tp;
|
||||
char *fn=FCEU_MakeFName(FCEUMKF_FDS,0,0);
|
||||
|
||||
int x;
|
||||
for(x=0;x<TotalSides;x++)
|
||||
{
|
||||
diskdatao[x]=(uint8 *)FCEU_malloc(65500);
|
||||
memcpy(diskdatao[x],diskdata[x],65500);
|
||||
}
|
||||
|
||||
if((tp=FCEU_fopen(fn,0,"rb",0)))
|
||||
{
|
||||
FreeFDSMemory();
|
||||
if(!SubLoad(tp))
|
||||
{
|
||||
FCEU_PrintError("Error reading auxillary FDS file.");
|
||||
free(fn);
|
||||
return(0);
|
||||
}
|
||||
FCEU_fclose(tp);
|
||||
DiskWritten=1; /* For save state handling. */
|
||||
}
|
||||
free(fn);
|
||||
}
|
||||
|
||||
FCEUGameInfo->type=GIT_FDS;
|
||||
GameInterface=FDSGI;
|
||||
|
||||
SelectDisk=0;
|
||||
InDisk=255;
|
||||
|
||||
ResetExState(PreSave,PostSave);
|
||||
FDSSoundStateAdd();
|
||||
|
||||
for(x=0;x<TotalSides;x++)
|
||||
{
|
||||
char temp[5];
|
||||
sprintf(temp,"DDT%d",x);
|
||||
AddExState(diskdata[x],65500,0,temp);
|
||||
}
|
||||
|
||||
AddExState(FDSRAM,32768,0,"FDSR");
|
||||
AddExState(FDSRegs,sizeof(FDSRegs),0,"FREG");
|
||||
AddExState(CHRRAM,8192,0,"CHRR");
|
||||
AddExState(&IRQCount, 4, 1, "IRQC");
|
||||
AddExState(&IRQLatch, 4, 1, "IQL1");
|
||||
AddExState(&IRQa, 1, 0, "IRQA");
|
||||
AddExState(&writeskip,1,0,"WSKI");
|
||||
AddExState(&DiskPtr,4,1,"DPTR");
|
||||
AddExState(&DiskSeekIRQ,4,1,"DSIR");
|
||||
AddExState(&SelectDisk,1,0,"SELD");
|
||||
AddExState(&InDisk,1,0,"INDI");
|
||||
AddExState(&DiskWritten,1,0,"DSKW");
|
||||
|
||||
ResetCartMapping();
|
||||
SetupCartCHRMapping(0,CHRRAM,8192,1);
|
||||
SetupCartMirroring(0,0,0);
|
||||
memset(CHRRAM,0,8192);
|
||||
memset(FDSRAM,0,32768);
|
||||
|
||||
FCEU_printf(" Sides: %d\n\n",TotalSides);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void FDSClose(void)
|
||||
{
|
||||
FILE *fp;
|
||||
int x;
|
||||
char *fn=FCEU_MakeFName(FCEUMKF_FDS,0,0);
|
||||
|
||||
if(!DiskWritten) return;
|
||||
|
||||
if(!(fp=FCEUD_UTF8fopen(fn,"wb")))
|
||||
{
|
||||
free(fn);
|
||||
return;
|
||||
}
|
||||
free(fn);
|
||||
|
||||
for(x=0;x<TotalSides;x++)
|
||||
{
|
||||
if(fwrite(diskdata[x],1,65500,fp)!=65500)
|
||||
{
|
||||
FCEU_PrintError("Error saving FDS image!");
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
FreeFDSMemory();
|
||||
fclose(fp);
|
||||
}
|
5
source/fds.h
Normal file
5
source/fds.h
Normal file
@ -0,0 +1,5 @@
|
||||
void FDSSoundReset(void);
|
||||
|
||||
void FCEU_FDSInsert(int oride);
|
||||
void FCEU_FDSEject(void);
|
||||
void FCEU_FDSSelect(void);
|
576
source/file.c
Normal file
576
source/file.c
Normal file
@ -0,0 +1,576 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <zlib.h>
|
||||
#include "unzip.h"
|
||||
|
||||
#include "types.h"
|
||||
#include "file.h"
|
||||
#include "endian.h"
|
||||
#include "memory.h"
|
||||
#include "driver.h"
|
||||
#include "general.h"
|
||||
|
||||
typedef struct {
|
||||
uint8 *data;
|
||||
uint32 size;
|
||||
uint32 location;
|
||||
} MEMWRAP;
|
||||
|
||||
void ApplyIPS(FILE *ips, MEMWRAP *dest)
|
||||
{
|
||||
uint8 header[5];
|
||||
uint32 count=0;
|
||||
|
||||
FCEU_printf(" Applying IPS...\n");
|
||||
if(fread(header,1,5,ips)!=5)
|
||||
{
|
||||
fclose(ips);
|
||||
return;
|
||||
}
|
||||
if(memcmp(header,"PATCH",5))
|
||||
{
|
||||
fclose(ips);
|
||||
return;
|
||||
}
|
||||
|
||||
while(fread(header,1,3,ips)==3)
|
||||
{
|
||||
uint32 offset=(header[0]<<16)|(header[1]<<8)|header[2];
|
||||
uint16 size;
|
||||
|
||||
if(!memcmp(header,"EOF",3))
|
||||
{
|
||||
FCEU_printf(" IPS EOF: Did %d patches\n\n",count);
|
||||
fclose(ips);
|
||||
return;
|
||||
}
|
||||
|
||||
size=fgetc(ips)<<8;
|
||||
size|=fgetc(ips);
|
||||
if(!size) /* RLE */
|
||||
{
|
||||
uint8 *start;
|
||||
uint8 b;
|
||||
size=fgetc(ips)<<8;
|
||||
size|=fgetc(ips);
|
||||
|
||||
//FCEU_printf(" Offset: %8d Size: %5d RLE\n",offset,size);
|
||||
|
||||
if((offset+size)>dest->size)
|
||||
{
|
||||
uint8 *tmp;
|
||||
|
||||
// Probably a little slow.
|
||||
tmp=(uint8 *)realloc(dest->data,offset+size);
|
||||
if(!tmp)
|
||||
{
|
||||
FCEU_printf(" Oops. IPS patch %d(type RLE) goes beyond end of file. Could not allocate memory.\n",count);
|
||||
fclose(ips);
|
||||
return;
|
||||
}
|
||||
dest->size=offset+size;
|
||||
dest->data=tmp;
|
||||
memset(dest->data+dest->size,0,offset+size-dest->size);
|
||||
}
|
||||
b=fgetc(ips);
|
||||
start=dest->data+offset;
|
||||
do
|
||||
{
|
||||
*start=b;
|
||||
start++;
|
||||
} while(--size);
|
||||
}
|
||||
else /* Normal patch */
|
||||
{
|
||||
//FCEU_printf(" Offset: %8d Size: %5d\n",offset,size);
|
||||
if((offset+size)>dest->size)
|
||||
{
|
||||
uint8 *tmp;
|
||||
|
||||
// Probably a little slow.
|
||||
tmp=(uint8 *)realloc(dest->data,offset+size);
|
||||
if(!tmp)
|
||||
{
|
||||
FCEU_printf(" Oops. IPS patch %d(type normal) goes beyond end of file. Could not allocate memory.\n",count);
|
||||
fclose(ips);
|
||||
return;
|
||||
}
|
||||
dest->data=tmp;
|
||||
memset(dest->data+dest->size,0,offset+size-dest->size);
|
||||
}
|
||||
fread(dest->data+offset,1,size,ips);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
fclose(ips);
|
||||
FCEU_printf(" Hard IPS end!\n");
|
||||
}
|
||||
|
||||
static MEMWRAP *MakeMemWrap(void *tz, int type)
|
||||
{
|
||||
MEMWRAP *tmp;
|
||||
|
||||
if(!(tmp=(MEMWRAP *)FCEU_malloc(sizeof(MEMWRAP))))
|
||||
goto doret;
|
||||
tmp->location=0;
|
||||
|
||||
if(type==0)
|
||||
{
|
||||
fseek((FILE *)tz,0,SEEK_END);
|
||||
tmp->size=ftell((FILE *)tz);
|
||||
fseek((FILE *)tz,0,SEEK_SET);
|
||||
if(!(tmp->data=(uint8*)FCEU_malloc(tmp->size)))
|
||||
{
|
||||
free(tmp);
|
||||
tmp=0;
|
||||
goto doret;
|
||||
}
|
||||
fread(tmp->data,1,tmp->size,(FILE *)tz);
|
||||
}
|
||||
else if(type==1)
|
||||
{
|
||||
/* Bleck. The gzip file format has the size of the uncompressed data,
|
||||
but I can't get to the info with the zlib interface(?). */
|
||||
for(tmp->size=0; gzgetc(tz) != EOF; tmp->size++);
|
||||
gzseek(tz,0,SEEK_SET);
|
||||
if(!(tmp->data=(uint8 *)FCEU_malloc(tmp->size)))
|
||||
{
|
||||
free(tmp);
|
||||
tmp=0;
|
||||
goto doret;
|
||||
}
|
||||
gzread(tz,tmp->data,tmp->size);
|
||||
}
|
||||
else if(type==2)
|
||||
{
|
||||
unz_file_info ufo;
|
||||
unzGetCurrentFileInfo(tz,&ufo,0,0,0,0,0,0);
|
||||
|
||||
tmp->size=ufo.uncompressed_size;
|
||||
if(!(tmp->data=(uint8 *)FCEU_malloc(ufo.uncompressed_size)))
|
||||
{
|
||||
free(tmp);
|
||||
tmp=0;
|
||||
goto doret;
|
||||
}
|
||||
unzReadCurrentFile(tz,tmp->data,ufo.uncompressed_size);
|
||||
}
|
||||
|
||||
doret:
|
||||
if(type==0)
|
||||
{
|
||||
fclose((FILE *)tz);
|
||||
}
|
||||
else if(type==1)
|
||||
{
|
||||
gzclose(tz);
|
||||
}
|
||||
else if(type==2)
|
||||
{
|
||||
unzCloseCurrentFile(tz);
|
||||
unzClose(tz);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#ifndef __GNUC__
|
||||
#define strcasecmp strcmp
|
||||
#endif
|
||||
|
||||
|
||||
FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext)
|
||||
{
|
||||
FILE *ipsfile=0;
|
||||
FCEUFILE *fceufp;
|
||||
void *t;
|
||||
|
||||
if(strchr(mode,'r'))
|
||||
ipsfile=FCEUD_UTF8fopen(ipsfn,"rb");
|
||||
|
||||
fceufp=(FCEUFILE *)malloc(sizeof(FCEUFILE));
|
||||
|
||||
{
|
||||
unzFile tz;
|
||||
if((tz=unzOpen(path))) // If it's not a zip file, use regular file handlers.
|
||||
// Assuming file type by extension usually works,
|
||||
// but I don't like it. :)
|
||||
{
|
||||
if(unzGoToFirstFile(tz)==UNZ_OK)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
char tempu[512]; // Longer filenames might be possible, but I don't
|
||||
// think people would name files that long in zip files...
|
||||
unzGetCurrentFileInfo(tz,0,tempu,512,0,0,0,0);
|
||||
tempu[511]=0;
|
||||
if(strlen(tempu)>=4)
|
||||
{
|
||||
char *za=tempu+strlen(tempu)-4;
|
||||
|
||||
if(!ext)
|
||||
{
|
||||
if(!strcasecmp(za,".nes") || !strcasecmp(za,".fds") ||
|
||||
!strcasecmp(za,".nsf") || !strcasecmp(za,".unf") ||
|
||||
!strcasecmp(za,".nez"))
|
||||
break;
|
||||
}
|
||||
else if(!strcasecmp(za,ext))
|
||||
break;
|
||||
}
|
||||
if(strlen(tempu)>=5)
|
||||
{
|
||||
if(!strcasecmp(tempu+strlen(tempu)-5,".unif"))
|
||||
break;
|
||||
}
|
||||
if(unzGoToNextFile(tz)!=UNZ_OK)
|
||||
{
|
||||
if(unzGoToFirstFile(tz)!=UNZ_OK) goto zpfail;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(unzOpenCurrentFile(tz)!=UNZ_OK)
|
||||
goto zpfail;
|
||||
}
|
||||
else
|
||||
{
|
||||
zpfail:
|
||||
free(fceufp);
|
||||
unzClose(tz);
|
||||
return 0;
|
||||
}
|
||||
if(!(fceufp->fp=MakeMemWrap(tz,2)))
|
||||
{
|
||||
free(fceufp);
|
||||
return(0);
|
||||
}
|
||||
fceufp->type=2;
|
||||
if(ipsfile)
|
||||
ApplyIPS(ipsfile,(MEMWRAP *)fceufp->fp);
|
||||
return(fceufp);
|
||||
}
|
||||
}
|
||||
|
||||
if((t=FCEUD_UTF8fopen(path,"rb")))
|
||||
{
|
||||
uint32 magic;
|
||||
|
||||
magic=fgetc((FILE *)t);
|
||||
magic|=fgetc((FILE *)t)<<8;
|
||||
magic|=fgetc((FILE *)t)<<16;
|
||||
|
||||
if(magic!=0x088b1f) /* Not gzip... */
|
||||
fclose((FILE *)t);
|
||||
else /* Probably gzip */
|
||||
{
|
||||
int fd;
|
||||
|
||||
/*** REMOVED GCV1.0
|
||||
fd = dup(fileno( (FILE *)t));
|
||||
REMOVED GCV1.0 ***/
|
||||
|
||||
fclose(t);
|
||||
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
|
||||
if((t=gzdopen(fd,mode)))
|
||||
{
|
||||
fceufp->type=1;
|
||||
fceufp->fp=t;
|
||||
if(ipsfile)
|
||||
{
|
||||
fceufp->fp=MakeMemWrap(t,1);
|
||||
gzclose(t);
|
||||
|
||||
if(fceufp->fp)
|
||||
{
|
||||
free(fceufp);
|
||||
return(0);
|
||||
}
|
||||
|
||||
fceufp->type=3;
|
||||
ApplyIPS(ipsfile,(MEMWRAP *)fceufp->fp);
|
||||
}
|
||||
return(fceufp);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if((t=FCEUD_UTF8fopen(path,mode)))
|
||||
{
|
||||
fseek((FILE *)t,0,SEEK_SET);
|
||||
fceufp->type=0;
|
||||
fceufp->fp=t;
|
||||
if(ipsfile)
|
||||
{
|
||||
if(!(fceufp->fp=MakeMemWrap(t,0)))
|
||||
{
|
||||
free(fceufp);
|
||||
return(0);
|
||||
}
|
||||
fceufp->type=3;
|
||||
ApplyIPS(ipsfile,(MEMWRAP *)fceufp->fp);
|
||||
}
|
||||
return(fceufp);
|
||||
}
|
||||
|
||||
free(fceufp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FCEU_fclose(FCEUFILE *fp)
|
||||
{
|
||||
if(fp->type==1)
|
||||
{
|
||||
gzclose(fp->fp);
|
||||
}
|
||||
else if(fp->type>=2)
|
||||
{
|
||||
free(((MEMWRAP*)(fp->fp))->data);
|
||||
free(fp->fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose((FILE *)fp->fp);
|
||||
}
|
||||
free(fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64 FCEU_fread(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp)
|
||||
{
|
||||
if(fp->type==1)
|
||||
{
|
||||
return gzread(fp->fp,ptr,size*nmemb);
|
||||
}
|
||||
else if(fp->type>=2)
|
||||
{
|
||||
MEMWRAP *wz;
|
||||
uint32 total=size*nmemb;
|
||||
|
||||
wz=(MEMWRAP*)fp->fp;
|
||||
if(wz->location>=wz->size) return 0;
|
||||
|
||||
if((wz->location+total)>wz->size)
|
||||
{
|
||||
int ak=wz->size-wz->location;
|
||||
memcpy((uint8*)ptr,wz->data+wz->location,ak);
|
||||
wz->location=wz->size;
|
||||
return(ak/size);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy((uint8*)ptr,wz->data+wz->location,total);
|
||||
wz->location+=total;
|
||||
return nmemb;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return fread(ptr,size,nmemb,(FILE *)fp->fp);
|
||||
}
|
||||
}
|
||||
|
||||
uint64 FCEU_fwrite(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp)
|
||||
{
|
||||
if(fp->type==1)
|
||||
{
|
||||
return gzwrite(fp->fp,ptr,size*nmemb);
|
||||
}
|
||||
else if(fp->type>=2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return fwrite(ptr,size,nmemb,(FILE *)fp->fp);
|
||||
}
|
||||
|
||||
int FCEU_fseek(FCEUFILE *fp, long offset, int whence)
|
||||
{
|
||||
if(fp->type==1)
|
||||
{
|
||||
return( (gzseek(fp->fp,offset,whence)>0)?0:-1);
|
||||
}
|
||||
else if(fp->type>=2)
|
||||
{
|
||||
MEMWRAP *wz;
|
||||
wz=(MEMWRAP*)fp->fp;
|
||||
|
||||
switch(whence)
|
||||
{
|
||||
case SEEK_SET:if(offset>=wz->size)
|
||||
return(-1);
|
||||
wz->location=offset;break;
|
||||
case SEEK_CUR:if(offset+wz->location>wz->size)
|
||||
return (-1);
|
||||
wz->location+=offset;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return fseek((FILE *)fp->fp,offset,whence);
|
||||
}
|
||||
|
||||
uint64 FCEU_ftell(FCEUFILE *fp)
|
||||
{
|
||||
if(fp->type==1)
|
||||
{
|
||||
return gztell(fp->fp);
|
||||
}
|
||||
else if(fp->type>=2)
|
||||
{
|
||||
return (((MEMWRAP *)(fp->fp))->location);
|
||||
}
|
||||
else
|
||||
return ftell((FILE *)fp->fp);
|
||||
}
|
||||
|
||||
void FCEU_rewind(FCEUFILE *fp)
|
||||
{
|
||||
if(fp->type==1)
|
||||
{
|
||||
gzrewind(fp->fp);
|
||||
}
|
||||
else if(fp->type>=2)
|
||||
{
|
||||
((MEMWRAP *)(fp->fp))->location=0;
|
||||
}
|
||||
else
|
||||
/* Rewind */
|
||||
fseek(fp->fp,0,SEEK_SET);
|
||||
}
|
||||
|
||||
int FCEU_read16le(uint16 *val, FCEUFILE *fp)
|
||||
{
|
||||
uint8 t[2];
|
||||
|
||||
if(fp->type>=1)
|
||||
{
|
||||
if(fp->type>=2)
|
||||
{
|
||||
MEMWRAP *wz;
|
||||
wz=(MEMWRAP *)fp->fp;
|
||||
if(wz->location+2>wz->size)
|
||||
{return 0;}
|
||||
*(uint32 *)t=*(uint32 *)(wz->data+wz->location);
|
||||
wz->location+=2;
|
||||
}
|
||||
else if(fp->type==1)
|
||||
if(gzread(fp->fp,&t,2)!=2) return(0);
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(fread(t,1,2,(FILE *)fp->fp)!=2) return(0);
|
||||
}
|
||||
*val=t[0]|(t[1]<<8);
|
||||
return(1);
|
||||
}
|
||||
|
||||
int FCEU_read32le(uint32 *Bufo, FCEUFILE *fp)
|
||||
{
|
||||
if(fp->type>=1)
|
||||
{
|
||||
uint8 t[4];
|
||||
#ifndef LSB_FIRST
|
||||
uint8 x[4];
|
||||
#endif
|
||||
if(fp->type>=2)
|
||||
{
|
||||
MEMWRAP *wz;
|
||||
wz=(MEMWRAP *)fp->fp;
|
||||
if(wz->location+4>wz->size)
|
||||
{return 0;}
|
||||
*(uint32 *)t=*(uint32 *)(wz->data+wz->location);
|
||||
wz->location+=4;
|
||||
}
|
||||
else if(fp->type==1)
|
||||
gzread(fp->fp,&t,4);
|
||||
#ifndef LSB_FIRST
|
||||
x[0]=t[3];
|
||||
x[1]=t[2];
|
||||
x[2]=t[1];
|
||||
x[3]=t[0];
|
||||
*(uint32*)Bufo=*(uint32*)x;
|
||||
#else
|
||||
*(uint32*)Bufo=*(uint32*)t;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return read32le(Bufo,(FILE *)fp->fp);
|
||||
}
|
||||
}
|
||||
|
||||
int FCEU_fgetc(FCEUFILE *fp)
|
||||
{
|
||||
if(fp->type==1)
|
||||
return gzgetc(fp->fp);
|
||||
else if(fp->type>=2)
|
||||
{
|
||||
MEMWRAP *wz;
|
||||
wz=(MEMWRAP *)fp->fp;
|
||||
if(wz->location<wz->size)
|
||||
return wz->data[wz->location++];
|
||||
return EOF;
|
||||
}
|
||||
else
|
||||
return fgetc((FILE *)fp->fp);
|
||||
}
|
||||
|
||||
uint64 FCEU_fgetsize(FCEUFILE *fp)
|
||||
{
|
||||
if(fp->type==1)
|
||||
{
|
||||
int x,t;
|
||||
t=gztell(fp->fp);
|
||||
gzrewind(fp->fp);
|
||||
for(x=0; gzgetc(fp->fp) != EOF; x++);
|
||||
gzseek(fp->fp,t,SEEK_SET);
|
||||
return(x);
|
||||
}
|
||||
else if(fp->type>=2)
|
||||
return ((MEMWRAP*)(fp->fp))->size;
|
||||
else
|
||||
{
|
||||
long t,r;
|
||||
t=ftell((FILE *)fp->fp);
|
||||
fseek((FILE *)fp->fp,0,SEEK_END);
|
||||
r=ftell((FILE *)fp->fp);
|
||||
fseek((FILE *)fp->fp,t,SEEK_SET);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
int FCEU_fisarchive(FCEUFILE *fp)
|
||||
{
|
||||
if(fp->type==2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
18
source/file.h
Normal file
18
source/file.h
Normal file
@ -0,0 +1,18 @@
|
||||
typedef struct {
|
||||
void *fp; // FILE* or ptr to ZIPWRAP
|
||||
uint32 type; // 0=normal file, 1=gzip, 2=zip
|
||||
} FCEUFILE;
|
||||
|
||||
FCEUFILE *FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext);
|
||||
int FCEU_fclose(FCEUFILE*);
|
||||
uint64 FCEU_fread(void *ptr, size_t size, size_t nmemb, FCEUFILE*);
|
||||
uint64 FCEU_fwrite(void *ptr, size_t size, size_t nmemb, FCEUFILE*);
|
||||
int FCEU_fseek(FCEUFILE*, long offset, int whence);
|
||||
uint64 FCEU_ftell(FCEUFILE*);
|
||||
void FCEU_rewind(FCEUFILE*);
|
||||
int FCEU_read32le(uint32 *Bufo, FCEUFILE*);
|
||||
int FCEU_read16le(uint16 *Bufo, FCEUFILE*);
|
||||
int FCEU_fgetc(FCEUFILE*);
|
||||
uint64 FCEU_fgetsize(FCEUFILE*);
|
||||
int FCEU_fisarchive(FCEUFILE*);
|
||||
|
200
source/filter.c
Normal file
200
source/filter.c
Normal file
@ -0,0 +1,200 @@
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "types.h"
|
||||
|
||||
#include "sound.h"
|
||||
#include "x6502.h"
|
||||
#include "fceu.h"
|
||||
#include "filter.h"
|
||||
|
||||
#include "fcoeffs.h"
|
||||
|
||||
static uint32 mrindex;
|
||||
static uint32 mrratio;
|
||||
|
||||
void SexyFilter2(int32 *in, int32 count)
|
||||
{
|
||||
#ifdef moo
|
||||
static int64 acc=0;
|
||||
double x,p;
|
||||
int64 c;
|
||||
|
||||
x=2*M_PI*6000/FSettings.SndRate;
|
||||
p=((double)2-cos(x)) - sqrt(pow((double)2-cos(x),2) -1 );
|
||||
|
||||
c=p*0x100000;
|
||||
//printf("%f\n",(double)c/0x100000);
|
||||
#endif
|
||||
static int64 acc=0;
|
||||
|
||||
while(count--)
|
||||
{
|
||||
int64 dropcurrent;
|
||||
dropcurrent=((*in<<16)-acc)>>3;
|
||||
|
||||
acc+=dropcurrent;
|
||||
*in=acc>>16;
|
||||
in++;
|
||||
//acc=((int64)0x100000-c)* *in + ((c*acc)>>20);
|
||||
//*in=acc>>20;
|
||||
//in++;
|
||||
}
|
||||
}
|
||||
|
||||
void SexyFilter(int32 *in, int32 *out, int32 count)
|
||||
{
|
||||
static int64 acc1=0,acc2=0;
|
||||
int32 mul1,mul2,vmul;
|
||||
|
||||
mul1=(94<<16)/FSettings.SndRate;
|
||||
mul2=(24<<16)/FSettings.SndRate;
|
||||
vmul=(FSettings.SoundVolume<<16)*3/4/100;
|
||||
|
||||
if(FSettings.soundq) vmul/=4;
|
||||
else vmul*=2; /* TODO: Increase volume in low quality sound rendering code itself */
|
||||
|
||||
while(count)
|
||||
{
|
||||
int64 ino=(int64)*in*vmul;
|
||||
acc1+=((ino-acc1)*mul1)>>16;
|
||||
acc2+=((ino-acc1-acc2)*mul2)>>16;
|
||||
//printf("%d ",*in);
|
||||
*in=0;
|
||||
{
|
||||
int32 t=(acc1-ino+acc2)>>16;
|
||||
//if(t>32767 || t<-32768) printf("Flow: %d\n",t);
|
||||
if(t>32767) t=32767;
|
||||
if(t<-32768) t=-32768;
|
||||
*out=t;
|
||||
}
|
||||
in++;
|
||||
out++;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns number of samples written to out. */
|
||||
/* leftover is set to the number of samples that need to be copied
|
||||
from the end of in to the beginning of in.
|
||||
*/
|
||||
|
||||
//static uint32 mva=1000;
|
||||
|
||||
/* This filtering code assumes that almost all input values stay below 32767.
|
||||
Do not adjust the volume in the wlookup tables and the expansion sound
|
||||
code to be higher, or you *might* overflow the FIR code.
|
||||
*/
|
||||
|
||||
int32 NeoFilterSound(int32 *in, int32 *out, uint32 inlen, int32 *leftover)
|
||||
{
|
||||
uint32 x;
|
||||
uint32 max;
|
||||
int32 *outsave=out;
|
||||
int32 count=0;
|
||||
|
||||
// for(x=0;x<inlen;x++)
|
||||
// {
|
||||
// if(in[x]>mva){ mva=in[x]; printf("%ld\n",in[x]);}
|
||||
// }
|
||||
max=(inlen-1)<<16;
|
||||
|
||||
if(FSettings.soundq==2)
|
||||
for(x=mrindex;x<max;x+=mrratio)
|
||||
{
|
||||
int32 acc=0,acc2=0;
|
||||
unsigned int c;
|
||||
int32 *S,*D;
|
||||
|
||||
for(c=SQ2NCOEFFS,S=&in[(x>>16)-SQ2NCOEFFS],D=sq2coeffs;c;c--,D++)
|
||||
{
|
||||
acc+=(S[c]**D)>>6;
|
||||
acc2+=(S[1+c]**D)>>6;
|
||||
}
|
||||
|
||||
acc=((int64)acc*(65536-(x&65535))+(int64)acc2*(x&65535))>>(16+11);
|
||||
*out=acc;
|
||||
out++;
|
||||
count++;
|
||||
}
|
||||
else
|
||||
for(x=mrindex;x<max;x+=mrratio)
|
||||
{
|
||||
int32 acc=0,acc2=0;
|
||||
unsigned int c;
|
||||
int32 *S,*D;
|
||||
|
||||
for(c=NCOEFFS,S=&in[(x>>16)-NCOEFFS],D=coeffs;c;c--,D++)
|
||||
{
|
||||
acc+=(S[c]**D)>>6;
|
||||
acc2+=(S[1+c]**D)>>6;
|
||||
}
|
||||
|
||||
acc=((int64)acc*(65536-(x&65535))+(int64)acc2*(x&65535))>>(16+11);
|
||||
*out=acc;
|
||||
out++;
|
||||
count++;
|
||||
}
|
||||
mrindex=x-max;
|
||||
|
||||
if(FSettings.soundq==2)
|
||||
{
|
||||
mrindex+=SQ2NCOEFFS*65536;
|
||||
*leftover=SQ2NCOEFFS+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
mrindex+=NCOEFFS*65536;
|
||||
*leftover=NCOEFFS+1;
|
||||
}
|
||||
|
||||
if(GameExpSound.NeoFill)
|
||||
GameExpSound.NeoFill(outsave,count);
|
||||
|
||||
SexyFilter(outsave,outsave,count);
|
||||
if(FSettings.lowpass)
|
||||
SexyFilter2(outsave,count);
|
||||
return(count);
|
||||
}
|
||||
|
||||
void MakeFilters(int32 rate)
|
||||
{
|
||||
int32 *tabs[6]={C44100NTSC,C44100PAL,C48000NTSC,C48000PAL,C96000NTSC,
|
||||
C96000PAL};
|
||||
int32 *sq2tabs[6]={SQ2C44100NTSC,SQ2C44100PAL,SQ2C48000NTSC,SQ2C48000PAL,
|
||||
SQ2C96000NTSC,SQ2C96000PAL};
|
||||
|
||||
int32 *tmp;
|
||||
int32 x;
|
||||
uint32 nco;
|
||||
|
||||
if(FSettings.soundq==2)
|
||||
nco=SQ2NCOEFFS;
|
||||
else
|
||||
nco=NCOEFFS;
|
||||
|
||||
mrindex=(nco+1)<<16;
|
||||
mrratio=(PAL?(int64)(PAL_CPU*65536):(int64)(NTSC_CPU*65536))/rate;
|
||||
|
||||
if(FSettings.soundq==2)
|
||||
tmp=sq2tabs[(PAL?1:0)|(rate==48000?2:0)|(rate==96000?4:0)];
|
||||
else
|
||||
tmp=tabs[(PAL?1:0)|(rate==48000?2:0)|(rate==96000?4:0)];
|
||||
|
||||
if(FSettings.soundq==2)
|
||||
for(x=0;x<SQ2NCOEFFS>>1;x++)
|
||||
sq2coeffs[x]=sq2coeffs[SQ2NCOEFFS-1-x]=tmp[x];
|
||||
else
|
||||
for(x=0;x<NCOEFFS>>1;x++)
|
||||
coeffs[x]=coeffs[NCOEFFS-1-x]=tmp[x];
|
||||
|
||||
#ifdef MOO
|
||||
/* Some tests involving precision and error. */
|
||||
{
|
||||
static int64 acc=0;
|
||||
int x;
|
||||
for(x=0;x<SQ2NCOEFFS;x++)
|
||||
acc+=(int64)32767*sq2coeffs[x];
|
||||
printf("Foo: %lld\n",acc);
|
||||
}
|
||||
#endif
|
||||
}
|
3
source/filter.h
Normal file
3
source/filter.h
Normal file
@ -0,0 +1,3 @@
|
||||
int32 NeoFilterSound(int32 *in, int32 *out, uint32 inlen, int32 *leftover);
|
||||
void MakeFilters(int32 rate);
|
||||
void SexyFilter(int32 *in, int32 *out, int32 count);
|
1039
source/fir/c44100ntsc.coef
Normal file
1039
source/fir/c44100ntsc.coef
Normal file
File diff suppressed because it is too large
Load Diff
512
source/fir/c44100ntsc.h
Normal file
512
source/fir/c44100ntsc.h
Normal file
@ -0,0 +1,512 @@
|
||||
116,
|
||||
9,
|
||||
9,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
9,
|
||||
9,
|
||||
8,
|
||||
8,
|
||||
7,
|
||||
6,
|
||||
5,
|
||||
4,
|
||||
3,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
-1,
|
||||
-2,
|
||||
-4,
|
||||
-5,
|
||||
-7,
|
||||
-9,
|
||||
-10,
|
||||
-12,
|
||||
-14,
|
||||
-16,
|
||||
-18,
|
||||
-20,
|
||||
-22,
|
||||
-24,
|
||||
-25,
|
||||
-27,
|
||||
-29,
|
||||
-31,
|
||||
-33,
|
||||
-34,
|
||||
-36,
|
||||
-37,
|
||||
-39,
|
||||
-40,
|
||||
-41,
|
||||
-42,
|
||||
-43,
|
||||
-44,
|
||||
-44,
|
||||
-44,
|
||||
-45,
|
||||
-45,
|
||||
-44,
|
||||
-44,
|
||||
-43,
|
||||
-42,
|
||||
-41,
|
||||
-40,
|
||||
-39,
|
||||
-37,
|
||||
-35,
|
||||
-33,
|
||||
-30,
|
||||
-28,
|
||||
-25,
|
||||
-22,
|
||||
-18,
|
||||
-15,
|
||||
-11,
|
||||
-7,
|
||||
-3,
|
||||
0,
|
||||
4,
|
||||
9,
|
||||
13,
|
||||
18,
|
||||
22,
|
||||
27,
|
||||
32,
|
||||
36,
|
||||
41,
|
||||
46,
|
||||
50,
|
||||
55,
|
||||
59,
|
||||
64,
|
||||
68,
|
||||
72,
|
||||
76,
|
||||
79,
|
||||
82,
|
||||
85,
|
||||
88,
|
||||
91,
|
||||
93,
|
||||
94,
|
||||
96,
|
||||
97,
|
||||
97,
|
||||
97,
|
||||
97,
|
||||
96,
|
||||
95,
|
||||
93,
|
||||
91,
|
||||
88,
|
||||
85,
|
||||
81,
|
||||
77,
|
||||
73,
|
||||
68,
|
||||
62,
|
||||
56,
|
||||
50,
|
||||
43,
|
||||
36,
|
||||
28,
|
||||
20,
|
||||
12,
|
||||
4,
|
||||
-4,
|
||||
-13,
|
||||
-22,
|
||||
-32,
|
||||
-41,
|
||||
-51,
|
||||
-60,
|
||||
-70,
|
||||
-79,
|
||||
-89,
|
||||
-98,
|
||||
-107,
|
||||
-116,
|
||||
-125,
|
||||
-133,
|
||||
-141,
|
||||
-148,
|
||||
-155,
|
||||
-162,
|
||||
-168,
|
||||
-173,
|
||||
-178,
|
||||
-182,
|
||||
-186,
|
||||
-188,
|
||||
-190,
|
||||
-192,
|
||||
-192,
|
||||
-191,
|
||||
-190,
|
||||
-188,
|
||||
-185,
|
||||
-181,
|
||||
-176,
|
||||
-170,
|
||||
-163,
|
||||
-156,
|
||||
-147,
|
||||
-138,
|
||||
-128,
|
||||
-117,
|
||||
-105,
|
||||
-93,
|
||||
-79,
|
||||
-66,
|
||||
-51,
|
||||
-36,
|
||||
-20,
|
||||
-4,
|
||||
11,
|
||||
28,
|
||||
45,
|
||||
63,
|
||||
80,
|
||||
98,
|
||||
115,
|
||||
133,
|
||||
150,
|
||||
167,
|
||||
183,
|
||||
200,
|
||||
215,
|
||||
231,
|
||||
245,
|
||||
259,
|
||||
272,
|
||||
284,
|
||||
295,
|
||||
305,
|
||||
314,
|
||||
322,
|
||||
328,
|
||||
334,
|
||||
338,
|
||||
340,
|
||||
341,
|
||||
341,
|
||||
339,
|
||||
336,
|
||||
331,
|
||||
324,
|
||||
316,
|
||||
307,
|
||||
296,
|
||||
283,
|
||||
269,
|
||||
253,
|
||||
236,
|
||||
218,
|
||||
198,
|
||||
176,
|
||||
154,
|
||||
131,
|
||||
106,
|
||||
80,
|
||||
54,
|
||||
26,
|
||||
-1,
|
||||
-29,
|
||||
-58,
|
||||
-88,
|
||||
-117,
|
||||
-147,
|
||||
-177,
|
||||
-207,
|
||||
-236,
|
||||
-265,
|
||||
-294,
|
||||
-321,
|
||||
-348,
|
||||
-374,
|
||||
-399,
|
||||
-423,
|
||||
-445,
|
||||
-466,
|
||||
-486,
|
||||
-503,
|
||||
-519,
|
||||
-533,
|
||||
-545,
|
||||
-554,
|
||||
-562,
|
||||
-567,
|
||||
-570,
|
||||
-570,
|
||||
-568,
|
||||
-564,
|
||||
-557,
|
||||
-547,
|
||||
-535,
|
||||
-520,
|
||||
-503,
|
||||
-483,
|
||||
-461,
|
||||
-436,
|
||||
-409,
|
||||
-379,
|
||||
-347,
|
||||
-314,
|
||||
-278,
|
||||
-240,
|
||||
-200,
|
||||
-159,
|
||||
-117,
|
||||
-72,
|
||||
-27,
|
||||
18,
|
||||
65,
|
||||
113,
|
||||
161,
|
||||
210,
|
||||
258,
|
||||
306,
|
||||
354,
|
||||
402,
|
||||
448,
|
||||
494,
|
||||
538,
|
||||
581,
|
||||
622,
|
||||
661,
|
||||
698,
|
||||
733,
|
||||
765,
|
||||
795,
|
||||
822,
|
||||
846,
|
||||
866,
|
||||
883,
|
||||
897,
|
||||
907,
|
||||
914,
|
||||
916,
|
||||
915,
|
||||
910,
|
||||
901,
|
||||
887,
|
||||
870,
|
||||
848,
|
||||
823,
|
||||
793,
|
||||
759,
|
||||
722,
|
||||
680,
|
||||
635,
|
||||
587,
|
||||
534,
|
||||
479,
|
||||
420,
|
||||
359,
|
||||
295,
|
||||
228,
|
||||
159,
|
||||
88,
|
||||
15,
|
||||
-58,
|
||||
-134,
|
||||
-210,
|
||||
-287,
|
||||
-364,
|
||||
-441,
|
||||
-518,
|
||||
-593,
|
||||
-668,
|
||||
-741,
|
||||
-813,
|
||||
-882,
|
||||
-949,
|
||||
-1013,
|
||||
-1074,
|
||||
-1131,
|
||||
-1185,
|
||||
-1235,
|
||||
-1280,
|
||||
-1321,
|
||||
-1357,
|
||||
-1387,
|
||||
-1412,
|
||||
-1432,
|
||||
-1446,
|
||||
-1454,
|
||||
-1456,
|
||||
-1451,
|
||||
-1440,
|
||||
-1423,
|
||||
-1400,
|
||||
-1370,
|
||||
-1333,
|
||||
-1290,
|
||||
-1241,
|
||||
-1185,
|
||||
-1123,
|
||||
-1055,
|
||||
-981,
|
||||
-901,
|
||||
-816,
|
||||
-726,
|
||||
-631,
|
||||
-531,
|
||||
-427,
|
||||
-319,
|
||||
-208,
|
||||
-93,
|
||||
24,
|
||||
143,
|
||||
265,
|
||||
388,
|
||||
511,
|
||||
635,
|
||||
759,
|
||||
882,
|
||||
1004,
|
||||
1124,
|
||||
1242,
|
||||
1357,
|
||||
1468,
|
||||
1575,
|
||||
1678,
|
||||
1776,
|
||||
1868,
|
||||
1955,
|
||||
2034,
|
||||
2107,
|
||||
2172,
|
||||
2229,
|
||||
2278,
|
||||
2318,
|
||||
2349,
|
||||
2370,
|
||||
2382,
|
||||
2384,
|
||||
2376,
|
||||
2357,
|
||||
2327,
|
||||
2287,
|
||||
2237,
|
||||
2175,
|
||||
2103,
|
||||
2020,
|
||||
1926,
|
||||
1822,
|
||||
1708,
|
||||
1583,
|
||||
1449,
|
||||
1306,
|
||||
1153,
|
||||
992,
|
||||
822,
|
||||
645,
|
||||
461,
|
||||
270,
|
||||
74,
|
||||
-127,
|
||||
-333,
|
||||
-543,
|
||||
-757,
|
||||
-972,
|
||||
-1189,
|
||||
-1406,
|
||||
-1623,
|
||||
-1839,
|
||||
-2052,
|
||||
-2263,
|
||||
-2469,
|
||||
-2670,
|
||||
-2866,
|
||||
-3055,
|
||||
-3235,
|
||||
-3407,
|
||||
-3569,
|
||||
-3721,
|
||||
-3861,
|
||||
-3988,
|
||||
-4102,
|
||||
-4201,
|
||||
-4286,
|
||||
-4355,
|
||||
-4407,
|
||||
-4441,
|
||||
-4458,
|
||||
-4456,
|
||||
-4434,
|
||||
-4393,
|
||||
-4331,
|
||||
-4249,
|
||||
-4145,
|
||||
-4020,
|
||||
-3873,
|
||||
-3704,
|
||||
-3512,
|
||||
-3299,
|
||||
-3063,
|
||||
-2806,
|
||||
-2526,
|
||||
-2224,
|
||||
-1900,
|
||||
-1556,
|
||||
-1190,
|
||||
-804,
|
||||
-398,
|
||||
27,
|
||||
471,
|
||||
933,
|
||||
1412,
|
||||
1908,
|
||||
2419,
|
||||
2945,
|
||||
3484,
|
||||
4036,
|
||||
4599,
|
||||
5172,
|
||||
5754,
|
||||
6344,
|
||||
6940,
|
||||
7541,
|
||||
8146,
|
||||
8754,
|
||||
9363,
|
||||
9971,
|
||||
10578,
|
||||
11182,
|
||||
11781,
|
||||
12374,
|
||||
12959,
|
||||
13536,
|
||||
14103,
|
||||
14658,
|
||||
15199,
|
||||
15727,
|
||||
16239,
|
||||
16734,
|
||||
17211,
|
||||
17669,
|
||||
18106,
|
||||
18521,
|
||||
18914,
|
||||
19283,
|
||||
19627,
|
||||
19946,
|
||||
20239,
|
||||
20505,
|
||||
20743,
|
||||
20952,
|
||||
21133,
|
||||
21284,
|
||||
21405,
|
||||
21497,
|
||||
21558,
|
||||
21588,
|
12
source/fir/c44100ntsc.scm
Normal file
12
source/fir/c44100ntsc.scm
Normal file
@ -0,0 +1,12 @@
|
||||
(title "44100 NTSC")
|
||||
|
||||
(verbose #t)
|
||||
|
||||
(cosine-symmetry)
|
||||
(filter-length 1024)
|
||||
(sampling-frequency 1789772.727272727272)
|
||||
(limit-= (band 0 15000) 1)
|
||||
(limit-= (band 22050 894886.363636) 0 .5)
|
||||
(output-file "c44100ntsc.coef")
|
||||
(plot-file "c44100ntsc.plot")
|
||||
(go)
|
1039
source/fir/c44100pal.coef
Normal file
1039
source/fir/c44100pal.coef
Normal file
File diff suppressed because it is too large
Load Diff
512
source/fir/c44100pal.h
Normal file
512
source/fir/c44100pal.h
Normal file
@ -0,0 +1,512 @@
|
||||
-116,
|
||||
-8,
|
||||
-8,
|
||||
-8,
|
||||
-8,
|
||||
-8,
|
||||
-8,
|
||||
-8,
|
||||
-8,
|
||||
-7,
|
||||
-7,
|
||||
-6,
|
||||
-5,
|
||||
-5,
|
||||
-4,
|
||||
-3,
|
||||
-2,
|
||||
-1,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
4,
|
||||
5,
|
||||
7,
|
||||
9,
|
||||
10,
|
||||
12,
|
||||
14,
|
||||
16,
|
||||
18,
|
||||
19,
|
||||
21,
|
||||
23,
|
||||
25,
|
||||
27,
|
||||
28,
|
||||
30,
|
||||
32,
|
||||
33,
|
||||
34,
|
||||
36,
|
||||
37,
|
||||
38,
|
||||
38,
|
||||
39,
|
||||
40,
|
||||
40,
|
||||
40,
|
||||
40,
|
||||
39,
|
||||
39,
|
||||
38,
|
||||
37,
|
||||
36,
|
||||
34,
|
||||
33,
|
||||
31,
|
||||
29,
|
||||
26,
|
||||
24,
|
||||
21,
|
||||
18,
|
||||
14,
|
||||
11,
|
||||
7,
|
||||
4,
|
||||
0,
|
||||
-3,
|
||||
-8,
|
||||
-12,
|
||||
-16,
|
||||
-21,
|
||||
-25,
|
||||
-29,
|
||||
-34,
|
||||
-38,
|
||||
-43,
|
||||
-47,
|
||||
-51,
|
||||
-55,
|
||||
-59,
|
||||
-62,
|
||||
-66,
|
||||
-69,
|
||||
-72,
|
||||
-75,
|
||||
-77,
|
||||
-79,
|
||||
-80,
|
||||
-81,
|
||||
-82,
|
||||
-83,
|
||||
-83,
|
||||
-82,
|
||||
-81,
|
||||
-80,
|
||||
-78,
|
||||
-75,
|
||||
-72,
|
||||
-69,
|
||||
-65,
|
||||
-61,
|
||||
-56,
|
||||
-51,
|
||||
-45,
|
||||
-39,
|
||||
-33,
|
||||
-26,
|
||||
-19,
|
||||
-11,
|
||||
-4,
|
||||
3,
|
||||
12,
|
||||
20,
|
||||
29,
|
||||
37,
|
||||
46,
|
||||
55,
|
||||
64,
|
||||
72,
|
||||
81,
|
||||
89,
|
||||
97,
|
||||
105,
|
||||
112,
|
||||
119,
|
||||
126,
|
||||
132,
|
||||
138,
|
||||
143,
|
||||
147,
|
||||
151,
|
||||
154,
|
||||
156,
|
||||
158,
|
||||
159,
|
||||
159,
|
||||
158,
|
||||
157,
|
||||
154,
|
||||
151,
|
||||
146,
|
||||
141,
|
||||
135,
|
||||
128,
|
||||
121,
|
||||
112,
|
||||
103,
|
||||
93,
|
||||
82,
|
||||
70,
|
||||
58,
|
||||
45,
|
||||
31,
|
||||
17,
|
||||
3,
|
||||
-11,
|
||||
-26,
|
||||
-41,
|
||||
-57,
|
||||
-72,
|
||||
-88,
|
||||
-104,
|
||||
-119,
|
||||
-134,
|
||||
-149,
|
||||
-163,
|
||||
-177,
|
||||
-191,
|
||||
-203,
|
||||
-215,
|
||||
-226,
|
||||
-236,
|
||||
-246,
|
||||
-254,
|
||||
-261,
|
||||
-267,
|
||||
-271,
|
||||
-274,
|
||||
-276,
|
||||
-277,
|
||||
-276,
|
||||
-274,
|
||||
-270,
|
||||
-264,
|
||||
-258,
|
||||
-249,
|
||||
-240,
|
||||
-228,
|
||||
-216,
|
||||
-201,
|
||||
-186,
|
||||
-169,
|
||||
-151,
|
||||
-132,
|
||||
-111,
|
||||
-90,
|
||||
-68,
|
||||
-44,
|
||||
-20,
|
||||
3,
|
||||
28,
|
||||
54,
|
||||
80,
|
||||
106,
|
||||
132,
|
||||
158,
|
||||
184,
|
||||
209,
|
||||
234,
|
||||
258,
|
||||
281,
|
||||
304,
|
||||
325,
|
||||
345,
|
||||
364,
|
||||
381,
|
||||
397,
|
||||
411,
|
||||
423,
|
||||
433,
|
||||
441,
|
||||
447,
|
||||
451,
|
||||
453,
|
||||
452,
|
||||
449,
|
||||
444,
|
||||
436,
|
||||
426,
|
||||
413,
|
||||
399,
|
||||
381,
|
||||
362,
|
||||
340,
|
||||
316,
|
||||
289,
|
||||
261,
|
||||
231,
|
||||
199,
|
||||
165,
|
||||
130,
|
||||
93,
|
||||
55,
|
||||
16,
|
||||
-23,
|
||||
-63,
|
||||
-104,
|
||||
-145,
|
||||
-187,
|
||||
-228,
|
||||
-269,
|
||||
-310,
|
||||
-349,
|
||||
-388,
|
||||
-425,
|
||||
-461,
|
||||
-495,
|
||||
-528,
|
||||
-558,
|
||||
-586,
|
||||
-612,
|
||||
-635,
|
||||
-655,
|
||||
-673,
|
||||
-687,
|
||||
-698,
|
||||
-705,
|
||||
-709,
|
||||
-710,
|
||||
-707,
|
||||
-700,
|
||||
-690,
|
||||
-675,
|
||||
-657,
|
||||
-636,
|
||||
-610,
|
||||
-581,
|
||||
-549,
|
||||
-513,
|
||||
-473,
|
||||
-431,
|
||||
-385,
|
||||
-336,
|
||||
-285,
|
||||
-232,
|
||||
-176,
|
||||
-118,
|
||||
-59,
|
||||
1,
|
||||
64,
|
||||
127,
|
||||
190,
|
||||
254,
|
||||
318,
|
||||
381,
|
||||
444,
|
||||
505,
|
||||
566,
|
||||
624,
|
||||
680,
|
||||
734,
|
||||
786,
|
||||
834,
|
||||
879,
|
||||
920,
|
||||
957,
|
||||
990,
|
||||
1019,
|
||||
1043,
|
||||
1062,
|
||||
1076,
|
||||
1085,
|
||||
1088,
|
||||
1086,
|
||||
1079,
|
||||
1065,
|
||||
1046,
|
||||
1022,
|
||||
991,
|
||||
955,
|
||||
913,
|
||||
866,
|
||||
814,
|
||||
756,
|
||||
693,
|
||||
626,
|
||||
554,
|
||||
478,
|
||||
398,
|
||||
314,
|
||||
228,
|
||||
138,
|
||||
46,
|
||||
-47,
|
||||
-143,
|
||||
-240,
|
||||
-337,
|
||||
-435,
|
||||
-532,
|
||||
-628,
|
||||
-723,
|
||||
-817,
|
||||
-907,
|
||||
-995,
|
||||
-1080,
|
||||
-1161,
|
||||
-1237,
|
||||
-1309,
|
||||
-1375,
|
||||
-1436,
|
||||
-1490,
|
||||
-1538,
|
||||
-1579,
|
||||
-1612,
|
||||
-1639,
|
||||
-1657,
|
||||
-1667,
|
||||
-1669,
|
||||
-1662,
|
||||
-1647,
|
||||
-1623,
|
||||
-1590,
|
||||
-1548,
|
||||
-1498,
|
||||
-1439,
|
||||
-1372,
|
||||
-1296,
|
||||
-1212,
|
||||
-1120,
|
||||
-1020,
|
||||
-913,
|
||||
-800,
|
||||
-680,
|
||||
-553,
|
||||
-422,
|
||||
-286,
|
||||
-145,
|
||||
0,
|
||||
146,
|
||||
296,
|
||||
447,
|
||||
599,
|
||||
752,
|
||||
904,
|
||||
1054,
|
||||
1203,
|
||||
1348,
|
||||
1490,
|
||||
1627,
|
||||
1759,
|
||||
1885,
|
||||
2004,
|
||||
2115,
|
||||
2218,
|
||||
2312,
|
||||
2396,
|
||||
2470,
|
||||
2533,
|
||||
2584,
|
||||
2623,
|
||||
2650,
|
||||
2664,
|
||||
2665,
|
||||
2652,
|
||||
2625,
|
||||
2584,
|
||||
2529,
|
||||
2460,
|
||||
2376,
|
||||
2278,
|
||||
2167,
|
||||
2041,
|
||||
1902,
|
||||
1750,
|
||||
1585,
|
||||
1407,
|
||||
1218,
|
||||
1018,
|
||||
808,
|
||||
588,
|
||||
359,
|
||||
123,
|
||||
-120,
|
||||
-369,
|
||||
-623,
|
||||
-881,
|
||||
-1142,
|
||||
-1403,
|
||||
-1665,
|
||||
-1926,
|
||||
-2184,
|
||||
-2439,
|
||||
-2688,
|
||||
-2931,
|
||||
-3166,
|
||||
-3392,
|
||||
-3607,
|
||||
-3810,
|
||||
-4000,
|
||||
-4176,
|
||||
-4335,
|
||||
-4478,
|
||||
-4602,
|
||||
-4706,
|
||||
-4790,
|
||||
-4852,
|
||||
-4891,
|
||||
-4906,
|
||||
-4897,
|
||||
-4862,
|
||||
-4801,
|
||||
-4713,
|
||||
-4598,
|
||||
-4454,
|
||||
-4283,
|
||||
-4082,
|
||||
-3853,
|
||||
-3595,
|
||||
-3308,
|
||||
-2992,
|
||||
-2647,
|
||||
-2274,
|
||||
-1873,
|
||||
-1445,
|
||||
-990,
|
||||
-509,
|
||||
-3,
|
||||
527,
|
||||
1081,
|
||||
1657,
|
||||
2254,
|
||||
2870,
|
||||
3505,
|
||||
4156,
|
||||
4823,
|
||||
5504,
|
||||
6196,
|
||||
6898,
|
||||
7609,
|
||||
8326,
|
||||
9048,
|
||||
9773,
|
||||
10498,
|
||||
11222,
|
||||
11943,
|
||||
12658,
|
||||
13366,
|
||||
14065,
|
||||
14753,
|
||||
15427,
|
||||
16086,
|
||||
16728,
|
||||
17351,
|
||||
17953,
|
||||
18533,
|
||||
19088,
|
||||
19616,
|
||||
20118,
|
||||
20590,
|
||||
21032,
|
||||
21441,
|
||||
21818,
|
||||
22160,
|
||||
22467,
|
||||
22738,
|
||||
22971,
|
||||
23167,
|
||||
23324,
|
||||
23443,
|
||||
23522,
|
||||
23561,
|
12
source/fir/c44100pal.scm
Normal file
12
source/fir/c44100pal.scm
Normal file
@ -0,0 +1,12 @@
|
||||
(title "44100 PAL")
|
||||
|
||||
(verbose #t)
|
||||
|
||||
(cosine-symmetry)
|
||||
(filter-length 1024)
|
||||
(sampling-frequency 1662607.125)
|
||||
(limit-= (band 0 15500) 1)
|
||||
(limit-= (band 22050 831303.5625) 0 .5)
|
||||
(output-file "c44100pal.coef")
|
||||
(plot-file "c44100pal.plot")
|
||||
(go)
|
1039
source/fir/c48000ntsc.coef
Normal file
1039
source/fir/c48000ntsc.coef
Normal file
File diff suppressed because it is too large
Load Diff
512
source/fir/c48000ntsc.h
Normal file
512
source/fir/c48000ntsc.h
Normal file
@ -0,0 +1,512 @@
|
||||
-115,
|
||||
-12,
|
||||
-13,
|
||||
-14,
|
||||
-14,
|
||||
-14,
|
||||
-15,
|
||||
-15,
|
||||
-15,
|
||||
-15,
|
||||
-15,
|
||||
-15,
|
||||
-15,
|
||||
-15,
|
||||
-14,
|
||||
-14,
|
||||
-13,
|
||||
-12,
|
||||
-11,
|
||||
-10,
|
||||
-9,
|
||||
-8,
|
||||
-7,
|
||||
-5,
|
||||
-3,
|
||||
-2,
|
||||
0,
|
||||
1,
|
||||
3,
|
||||
5,
|
||||
7,
|
||||
10,
|
||||
12,
|
||||
14,
|
||||
17,
|
||||
19,
|
||||
22,
|
||||
24,
|
||||
26,
|
||||
29,
|
||||
31,
|
||||
33,
|
||||
35,
|
||||
37,
|
||||
39,
|
||||
41,
|
||||
42,
|
||||
44,
|
||||
45,
|
||||
46,
|
||||
47,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
48,
|
||||
47,
|
||||
47,
|
||||
45,
|
||||
44,
|
||||
42,
|
||||
40,
|
||||
38,
|
||||
35,
|
||||
33,
|
||||
30,
|
||||
26,
|
||||
23,
|
||||
19,
|
||||
15,
|
||||
10,
|
||||
6,
|
||||
1,
|
||||
-3,
|
||||
-8,
|
||||
-13,
|
||||
-18,
|
||||
-23,
|
||||
-28,
|
||||
-33,
|
||||
-39,
|
||||
-44,
|
||||
-49,
|
||||
-54,
|
||||
-59,
|
||||
-63,
|
||||
-68,
|
||||
-72,
|
||||
-76,
|
||||
-80,
|
||||
-83,
|
||||
-86,
|
||||
-88,
|
||||
-91,
|
||||
-92,
|
||||
-94,
|
||||
-94,
|
||||
-95,
|
||||
-94,
|
||||
-93,
|
||||
-92,
|
||||
-90,
|
||||
-88,
|
||||
-85,
|
||||
-81,
|
||||
-77,
|
||||
-73,
|
||||
-67,
|
||||
-62,
|
||||
-55,
|
||||
-49,
|
||||
-42,
|
||||
-34,
|
||||
-26,
|
||||
-18,
|
||||
-9,
|
||||
0,
|
||||
9,
|
||||
18,
|
||||
28,
|
||||
38,
|
||||
48,
|
||||
57,
|
||||
67,
|
||||
77,
|
||||
87,
|
||||
96,
|
||||
106,
|
||||
114,
|
||||
123,
|
||||
131,
|
||||
139,
|
||||
146,
|
||||
152,
|
||||
158,
|
||||
163,
|
||||
168,
|
||||
171,
|
||||
174,
|
||||
176,
|
||||
177,
|
||||
177,
|
||||
177,
|
||||
175,
|
||||
172,
|
||||
168,
|
||||
164,
|
||||
158,
|
||||
151,
|
||||
143,
|
||||
135,
|
||||
125,
|
||||
115,
|
||||
103,
|
||||
91,
|
||||
78,
|
||||
65,
|
||||
50,
|
||||
35,
|
||||
20,
|
||||
3,
|
||||
-12,
|
||||
-29,
|
||||
-46,
|
||||
-63,
|
||||
-80,
|
||||
-98,
|
||||
-115,
|
||||
-132,
|
||||
-148,
|
||||
-165,
|
||||
-180,
|
||||
-196,
|
||||
-210,
|
||||
-224,
|
||||
-237,
|
||||
-248,
|
||||
-259,
|
||||
-269,
|
||||
-277,
|
||||
-285,
|
||||
-290,
|
||||
-295,
|
||||
-298,
|
||||
-299,
|
||||
-299,
|
||||
-297,
|
||||
-294,
|
||||
-289,
|
||||
-282,
|
||||
-274,
|
||||
-264,
|
||||
-252,
|
||||
-239,
|
||||
-224,
|
||||
-208,
|
||||
-190,
|
||||
-171,
|
||||
-151,
|
||||
-129,
|
||||
-106,
|
||||
-82,
|
||||
-57,
|
||||
-31,
|
||||
-5,
|
||||
22,
|
||||
49,
|
||||
77,
|
||||
105,
|
||||
134,
|
||||
162,
|
||||
190,
|
||||
217,
|
||||
244,
|
||||
270,
|
||||
295,
|
||||
320,
|
||||
343,
|
||||
365,
|
||||
385,
|
||||
404,
|
||||
421,
|
||||
436,
|
||||
449,
|
||||
460,
|
||||
469,
|
||||
475,
|
||||
479,
|
||||
481,
|
||||
480,
|
||||
477,
|
||||
471,
|
||||
462,
|
||||
451,
|
||||
437,
|
||||
421,
|
||||
402,
|
||||
380,
|
||||
357,
|
||||
330,
|
||||
302,
|
||||
271,
|
||||
238,
|
||||
203,
|
||||
167,
|
||||
129,
|
||||
89,
|
||||
48,
|
||||
6,
|
||||
-35,
|
||||
-79,
|
||||
-123,
|
||||
-167,
|
||||
-211,
|
||||
-255,
|
||||
-298,
|
||||
-341,
|
||||
-383,
|
||||
-423,
|
||||
-462,
|
||||
-500,
|
||||
-535,
|
||||
-569,
|
||||
-600,
|
||||
-628,
|
||||
-654,
|
||||
-677,
|
||||
-697,
|
||||
-713,
|
||||
-726,
|
||||
-735,
|
||||
-741,
|
||||
-743,
|
||||
-741,
|
||||
-735,
|
||||
-725,
|
||||
-711,
|
||||
-693,
|
||||
-671,
|
||||
-645,
|
||||
-616,
|
||||
-582,
|
||||
-545,
|
||||
-504,
|
||||
-459,
|
||||
-412,
|
||||
-361,
|
||||
-307,
|
||||
-251,
|
||||
-192,
|
||||
-132,
|
||||
-69,
|
||||
-5,
|
||||
60,
|
||||
126,
|
||||
193,
|
||||
260,
|
||||
328,
|
||||
394,
|
||||
460,
|
||||
525,
|
||||
588,
|
||||
650,
|
||||
709,
|
||||
765,
|
||||
819,
|
||||
869,
|
||||
916,
|
||||
958,
|
||||
997,
|
||||
1031,
|
||||
1060,
|
||||
1084,
|
||||
1103,
|
||||
1116,
|
||||
1124,
|
||||
1126,
|
||||
1123,
|
||||
1113,
|
||||
1097,
|
||||
1075,
|
||||
1047,
|
||||
1013,
|
||||
973,
|
||||
928,
|
||||
876,
|
||||
819,
|
||||
756,
|
||||
689,
|
||||
616,
|
||||
539,
|
||||
457,
|
||||
372,
|
||||
283,
|
||||
190,
|
||||
95,
|
||||
-1,
|
||||
-100,
|
||||
-201,
|
||||
-302,
|
||||
-404,
|
||||
-506,
|
||||
-607,
|
||||
-706,
|
||||
-804,
|
||||
-900,
|
||||
-993,
|
||||
-1082,
|
||||
-1167,
|
||||
-1248,
|
||||
-1324,
|
||||
-1395,
|
||||
-1459,
|
||||
-1517,
|
||||
-1569,
|
||||
-1613,
|
||||
-1649,
|
||||
-1678,
|
||||
-1698,
|
||||
-1710,
|
||||
-1713,
|
||||
-1707,
|
||||
-1692,
|
||||
-1667,
|
||||
-1634,
|
||||
-1591,
|
||||
-1539,
|
||||
-1478,
|
||||
-1408,
|
||||
-1329,
|
||||
-1242,
|
||||
-1146,
|
||||
-1043,
|
||||
-931,
|
||||
-813,
|
||||
-688,
|
||||
-556,
|
||||
-419,
|
||||
-277,
|
||||
-131,
|
||||
19,
|
||||
172,
|
||||
328,
|
||||
485,
|
||||
643,
|
||||
801,
|
||||
958,
|
||||
1113,
|
||||
1266,
|
||||
1416,
|
||||
1561,
|
||||
1702,
|
||||
1836,
|
||||
1964,
|
||||
2085,
|
||||
2197,
|
||||
2300,
|
||||
2393,
|
||||
2476,
|
||||
2548,
|
||||
2608,
|
||||
2656,
|
||||
2690,
|
||||
2712,
|
||||
2720,
|
||||
2713,
|
||||
2692,
|
||||
2657,
|
||||
2607,
|
||||
2542,
|
||||
2462,
|
||||
2367,
|
||||
2257,
|
||||
2133,
|
||||
1994,
|
||||
1842,
|
||||
1676,
|
||||
1497,
|
||||
1305,
|
||||
1102,
|
||||
888,
|
||||
663,
|
||||
430,
|
||||
187,
|
||||
-61,
|
||||
-317,
|
||||
-579,
|
||||
-844,
|
||||
-1113,
|
||||
-1383,
|
||||
-1653,
|
||||
-1922,
|
||||
-2189,
|
||||
-2452,
|
||||
-2709,
|
||||
-2960,
|
||||
-3203,
|
||||
-3437,
|
||||
-3659,
|
||||
-3869,
|
||||
-4065,
|
||||
-4245,
|
||||
-4409,
|
||||
-4556,
|
||||
-4682,
|
||||
-4789,
|
||||
-4873,
|
||||
-4935,
|
||||
-4973,
|
||||
-4986,
|
||||
-4972,
|
||||
-4933,
|
||||
-4865,
|
||||
-4770,
|
||||
-4646,
|
||||
-4492,
|
||||
-4309,
|
||||
-4096,
|
||||
-3853,
|
||||
-3579,
|
||||
-3276,
|
||||
-2942,
|
||||
-2578,
|
||||
-2185,
|
||||
-1763,
|
||||
-1313,
|
||||
-835,
|
||||
-330,
|
||||
200,
|
||||
755,
|
||||
1335,
|
||||
1937,
|
||||
2560,
|
||||
3203,
|
||||
3864,
|
||||
4543,
|
||||
5236,
|
||||
5942,
|
||||
6660,
|
||||
7387,
|
||||
8122,
|
||||
8863,
|
||||
9608,
|
||||
10354,
|
||||
11099,
|
||||
11842,
|
||||
12580,
|
||||
13311,
|
||||
14033,
|
||||
14745,
|
||||
15443,
|
||||
16125,
|
||||
16791,
|
||||
17436,
|
||||
18061,
|
||||
18663,
|
||||
19239,
|
||||
19789,
|
||||
20310,
|
||||
20801,
|
||||
21261,
|
||||
21687,
|
||||
22079,
|
||||
22435,
|
||||
22755,
|
||||
23037,
|
||||
23281,
|
||||
23485,
|
||||
23649,
|
||||
23772,
|
||||
23854,
|
||||
23896,
|
12
source/fir/c48000ntsc.scm
Normal file
12
source/fir/c48000ntsc.scm
Normal file
@ -0,0 +1,12 @@
|
||||
(title "48000 NTSC")
|
||||
|
||||
(verbose #t)
|
||||
|
||||
(cosine-symmetry)
|
||||
(filter-length 1024)
|
||||
(sampling-frequency 1789772.727272727272)
|
||||
(limit-= (band 0 17000) 1)
|
||||
(limit-= (band 24000 894886.363636) 0 .5)
|
||||
(output-file "c48000ntsc.coef")
|
||||
(plot-file "c48000ntsc.plot")
|
||||
(go)
|
1039
source/fir/c48000pal.coef
Normal file
1039
source/fir/c48000pal.coef
Normal file
File diff suppressed because it is too large
Load Diff
512
source/fir/c48000pal.h
Normal file
512
source/fir/c48000pal.h
Normal file
@ -0,0 +1,512 @@
|
||||
113,
|
||||
14,
|
||||
15,
|
||||
15,
|
||||
16,
|
||||
16,
|
||||
17,
|
||||
17,
|
||||
18,
|
||||
18,
|
||||
18,
|
||||
18,
|
||||
18,
|
||||
17,
|
||||
17,
|
||||
16,
|
||||
16,
|
||||
15,
|
||||
14,
|
||||
12,
|
||||
11,
|
||||
10,
|
||||
8,
|
||||
6,
|
||||
4,
|
||||
2,
|
||||
0,
|
||||
-1,
|
||||
-3,
|
||||
-6,
|
||||
-8,
|
||||
-11,
|
||||
-13,
|
||||
-16,
|
||||
-18,
|
||||
-21,
|
||||
-24,
|
||||
-26,
|
||||
-29,
|
||||
-31,
|
||||
-33,
|
||||
-35,
|
||||
-37,
|
||||
-39,
|
||||
-41,
|
||||
-42,
|
||||
-44,
|
||||
-45,
|
||||
-46,
|
||||
-46,
|
||||
-47,
|
||||
-47,
|
||||
-46,
|
||||
-46,
|
||||
-45,
|
||||
-44,
|
||||
-42,
|
||||
-40,
|
||||
-38,
|
||||
-36,
|
||||
-33,
|
||||
-30,
|
||||
-26,
|
||||
-23,
|
||||
-19,
|
||||
-15,
|
||||
-10,
|
||||
-6,
|
||||
-1,
|
||||
3,
|
||||
8,
|
||||
13,
|
||||
19,
|
||||
24,
|
||||
29,
|
||||
35,
|
||||
40,
|
||||
45,
|
||||
50,
|
||||
55,
|
||||
60,
|
||||
64,
|
||||
68,
|
||||
72,
|
||||
75,
|
||||
79,
|
||||
81,
|
||||
83,
|
||||
85,
|
||||
86,
|
||||
87,
|
||||
87,
|
||||
87,
|
||||
86,
|
||||
84,
|
||||
82,
|
||||
79,
|
||||
76,
|
||||
72,
|
||||
67,
|
||||
62,
|
||||
56,
|
||||
50,
|
||||
43,
|
||||
36,
|
||||
28,
|
||||
20,
|
||||
11,
|
||||
2,
|
||||
-6,
|
||||
-15,
|
||||
-25,
|
||||
-34,
|
||||
-44,
|
||||
-54,
|
||||
-63,
|
||||
-73,
|
||||
-82,
|
||||
-91,
|
||||
-100,
|
||||
-109,
|
||||
-117,
|
||||
-124,
|
||||
-131,
|
||||
-137,
|
||||
-142,
|
||||
-147,
|
||||
-151,
|
||||
-154,
|
||||
-156,
|
||||
-158,
|
||||
-158,
|
||||
-157,
|
||||
-156,
|
||||
-153,
|
||||
-149,
|
||||
-145,
|
||||
-139,
|
||||
-132,
|
||||
-124,
|
||||
-115,
|
||||
-105,
|
||||
-95,
|
||||
-83,
|
||||
-71,
|
||||
-58,
|
||||
-44,
|
||||
-29,
|
||||
-14,
|
||||
0,
|
||||
16,
|
||||
32,
|
||||
48,
|
||||
65,
|
||||
81,
|
||||
98,
|
||||
114,
|
||||
129,
|
||||
145,
|
||||
159,
|
||||
174,
|
||||
187,
|
||||
199,
|
||||
211,
|
||||
221,
|
||||
231,
|
||||
239,
|
||||
246,
|
||||
251,
|
||||
255,
|
||||
257,
|
||||
258,
|
||||
257,
|
||||
255,
|
||||
251,
|
||||
245,
|
||||
237,
|
||||
228,
|
||||
217,
|
||||
205,
|
||||
191,
|
||||
175,
|
||||
158,
|
||||
140,
|
||||
120,
|
||||
99,
|
||||
77,
|
||||
54,
|
||||
30,
|
||||
6,
|
||||
-19,
|
||||
-44,
|
||||
-70,
|
||||
-96,
|
||||
-123,
|
||||
-148,
|
||||
-174,
|
||||
-199,
|
||||
-223,
|
||||
-247,
|
||||
-269,
|
||||
-291,
|
||||
-311,
|
||||
-329,
|
||||
-346,
|
||||
-361,
|
||||
-374,
|
||||
-385,
|
||||
-393,
|
||||
-400,
|
||||
-404,
|
||||
-406,
|
||||
-405,
|
||||
-401,
|
||||
-395,
|
||||
-387,
|
||||
-376,
|
||||
-362,
|
||||
-346,
|
||||
-327,
|
||||
-306,
|
||||
-282,
|
||||
-256,
|
||||
-228,
|
||||
-198,
|
||||
-166,
|
||||
-133,
|
||||
-98,
|
||||
-61,
|
||||
-23,
|
||||
14,
|
||||
53,
|
||||
93,
|
||||
133,
|
||||
173,
|
||||
212,
|
||||
251,
|
||||
290,
|
||||
327,
|
||||
363,
|
||||
397,
|
||||
430,
|
||||
461,
|
||||
489,
|
||||
515,
|
||||
538,
|
||||
558,
|
||||
575,
|
||||
589,
|
||||
600,
|
||||
607,
|
||||
610,
|
||||
609,
|
||||
605,
|
||||
597,
|
||||
585,
|
||||
569,
|
||||
549,
|
||||
526,
|
||||
498,
|
||||
467,
|
||||
432,
|
||||
395,
|
||||
353,
|
||||
309,
|
||||
262,
|
||||
213,
|
||||
161,
|
||||
107,
|
||||
51,
|
||||
-5,
|
||||
-63,
|
||||
-122,
|
||||
-181,
|
||||
-240,
|
||||
-299,
|
||||
-357,
|
||||
-414,
|
||||
-469,
|
||||
-523,
|
||||
-575,
|
||||
-623,
|
||||
-669,
|
||||
-712,
|
||||
-751,
|
||||
-786,
|
||||
-817,
|
||||
-843,
|
||||
-865,
|
||||
-881,
|
||||
-893,
|
||||
-899,
|
||||
-899,
|
||||
-894,
|
||||
-884,
|
||||
-867,
|
||||
-845,
|
||||
-817,
|
||||
-784,
|
||||
-745,
|
||||
-701,
|
||||
-651,
|
||||
-597,
|
||||
-537,
|
||||
-474,
|
||||
-406,
|
||||
-334,
|
||||
-259,
|
||||
-181,
|
||||
-100,
|
||||
-17,
|
||||
67,
|
||||
152,
|
||||
239,
|
||||
325,
|
||||
412,
|
||||
497,
|
||||
581,
|
||||
663,
|
||||
742,
|
||||
818,
|
||||
890,
|
||||
959,
|
||||
1022,
|
||||
1081,
|
||||
1133,
|
||||
1180,
|
||||
1220,
|
||||
1254,
|
||||
1280,
|
||||
1299,
|
||||
1310,
|
||||
1313,
|
||||
1308,
|
||||
1295,
|
||||
1273,
|
||||
1243,
|
||||
1205,
|
||||
1159,
|
||||
1104,
|
||||
1042,
|
||||
972,
|
||||
894,
|
||||
809,
|
||||
718,
|
||||
621,
|
||||
517,
|
||||
409,
|
||||
296,
|
||||
179,
|
||||
58,
|
||||
-64,
|
||||
-190,
|
||||
-316,
|
||||
-443,
|
||||
-570,
|
||||
-696,
|
||||
-820,
|
||||
-941,
|
||||
-1059,
|
||||
-1173,
|
||||
-1281,
|
||||
-1384,
|
||||
-1480,
|
||||
-1569,
|
||||
-1649,
|
||||
-1722,
|
||||
-1785,
|
||||
-1838,
|
||||
-1881,
|
||||
-1912,
|
||||
-1933,
|
||||
-1942,
|
||||
-1939,
|
||||
-1924,
|
||||
-1897,
|
||||
-1858,
|
||||
-1806,
|
||||
-1741,
|
||||
-1665,
|
||||
-1576,
|
||||
-1476,
|
||||
-1365,
|
||||
-1243,
|
||||
-1110,
|
||||
-968,
|
||||
-816,
|
||||
-657,
|
||||
-490,
|
||||
-316,
|
||||
-136,
|
||||
47,
|
||||
235,
|
||||
426,
|
||||
619,
|
||||
811,
|
||||
1003,
|
||||
1193,
|
||||
1380,
|
||||
1563,
|
||||
1740,
|
||||
1910,
|
||||
2072,
|
||||
2225,
|
||||
2368,
|
||||
2499,
|
||||
2618,
|
||||
2723,
|
||||
2814,
|
||||
2889,
|
||||
2949,
|
||||
2991,
|
||||
3016,
|
||||
3022,
|
||||
3010,
|
||||
2979,
|
||||
2929,
|
||||
2859,
|
||||
2769,
|
||||
2660,
|
||||
2531,
|
||||
2384,
|
||||
2217,
|
||||
2032,
|
||||
1830,
|
||||
1611,
|
||||
1376,
|
||||
1126,
|
||||
862,
|
||||
585,
|
||||
297,
|
||||
0,
|
||||
-307,
|
||||
-621,
|
||||
-940,
|
||||
-1262,
|
||||
-1586,
|
||||
-1910,
|
||||
-2232,
|
||||
-2550,
|
||||
-2862,
|
||||
-3165,
|
||||
-3459,
|
||||
-3740,
|
||||
-4007,
|
||||
-4258,
|
||||
-4491,
|
||||
-4703,
|
||||
-4893,
|
||||
-5059,
|
||||
-5200,
|
||||
-5313,
|
||||
-5396,
|
||||
-5449,
|
||||
-5470,
|
||||
-5457,
|
||||
-5409,
|
||||
-5326,
|
||||
-5206,
|
||||
-5048,
|
||||
-4853,
|
||||
-4618,
|
||||
-4345,
|
||||
-4032,
|
||||
-3681,
|
||||
-3290,
|
||||
-2861,
|
||||
-2393,
|
||||
-1888,
|
||||
-1347,
|
||||
-769,
|
||||
-158,
|
||||
486,
|
||||
1162,
|
||||
1868,
|
||||
2602,
|
||||
3362,
|
||||
4146,
|
||||
4952,
|
||||
5777,
|
||||
6619,
|
||||
7475,
|
||||
8342,
|
||||
9219,
|
||||
10102,
|
||||
10988,
|
||||
11874,
|
||||
12757,
|
||||
13635,
|
||||
14504,
|
||||
15361,
|
||||
16204,
|
||||
17029,
|
||||
17833,
|
||||
18615,
|
||||
19370,
|
||||
20096,
|
||||
20790,
|
||||
21451,
|
||||
22075,
|
||||
22660,
|
||||
23205,
|
||||
23707,
|
||||
24164,
|
||||
24574,
|
||||
24937,
|
||||
25250,
|
||||
25513,
|
||||
25725,
|
||||
25884,
|
||||
25991,
|
||||
26044,
|
12
source/fir/c48000pal.scm
Normal file
12
source/fir/c48000pal.scm
Normal file
@ -0,0 +1,12 @@
|
||||
(title "48000 PAL")
|
||||
|
||||
(verbose #t)
|
||||
|
||||
(cosine-symmetry)
|
||||
(filter-length 1024)
|
||||
(sampling-frequency 1662607.125)
|
||||
(limit-= (band 0 17500) 1)
|
||||
(limit-= (band 24000 831303.5625) 0 .5)
|
||||
(output-file "c48000pal.coef")
|
||||
(plot-file "c48000pal.plot")
|
||||
(go)
|
1039
source/fir/c96000ntsc.coef
Normal file
1039
source/fir/c96000ntsc.coef
Normal file
File diff suppressed because it is too large
Load Diff
512
source/fir/c96000ntsc.h
Normal file
512
source/fir/c96000ntsc.h
Normal file
@ -0,0 +1,512 @@
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
-1,
|
||||
-2,
|
||||
-2,
|
||||
-2,
|
||||
-3,
|
||||
-3,
|
||||
-3,
|
||||
-3,
|
||||
-3,
|
||||
-3,
|
||||
-3,
|
||||
-3,
|
||||
-3,
|
||||
-2,
|
||||
-2,
|
||||
-1,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
6,
|
||||
7,
|
||||
7,
|
||||
7,
|
||||
7,
|
||||
7,
|
||||
7,
|
||||
6,
|
||||
6,
|
||||
5,
|
||||
4,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
-1,
|
||||
-3,
|
||||
-5,
|
||||
-6,
|
||||
-8,
|
||||
-10,
|
||||
-11,
|
||||
-12,
|
||||
-13,
|
||||
-14,
|
||||
-14,
|
||||
-14,
|
||||
-14,
|
||||
-14,
|
||||
-13,
|
||||
-11,
|
||||
-10,
|
||||
-8,
|
||||
-6,
|
||||
-3,
|
||||
0,
|
||||
1,
|
||||
4,
|
||||
7,
|
||||
10,
|
||||
13,
|
||||
16,
|
||||
18,
|
||||
21,
|
||||
22,
|
||||
24,
|
||||
25,
|
||||
25,
|
||||
25,
|
||||
24,
|
||||
23,
|
||||
21,
|
||||
18,
|
||||
15,
|
||||
12,
|
||||
8,
|
||||
3,
|
||||
-1,
|
||||
-6,
|
||||
-11,
|
||||
-16,
|
||||
-20,
|
||||
-25,
|
||||
-29,
|
||||
-33,
|
||||
-36,
|
||||
-39,
|
||||
-41,
|
||||
-42,
|
||||
-42,
|
||||
-41,
|
||||
-39,
|
||||
-36,
|
||||
-32,
|
||||
-27,
|
||||
-22,
|
||||
-15,
|
||||
-8,
|
||||
-1,
|
||||
6,
|
||||
14,
|
||||
22,
|
||||
30,
|
||||
37,
|
||||
44,
|
||||
51,
|
||||
56,
|
||||
60,
|
||||
64,
|
||||
65,
|
||||
66,
|
||||
65,
|
||||
62,
|
||||
58,
|
||||
53,
|
||||
46,
|
||||
38,
|
||||
28,
|
||||
18,
|
||||
6,
|
||||
-4,
|
||||
-17,
|
||||
-29,
|
||||
-41,
|
||||
-53,
|
||||
-64,
|
||||
-74,
|
||||
-83,
|
||||
-90,
|
||||
-95,
|
||||
-99,
|
||||
-100,
|
||||
-100,
|
||||
-97,
|
||||
-91,
|
||||
-84,
|
||||
-74,
|
||||
-62,
|
||||
-49,
|
||||
-33,
|
||||
-17,
|
||||
0,
|
||||
18,
|
||||
36,
|
||||
55,
|
||||
72,
|
||||
89,
|
||||
104,
|
||||
118,
|
||||
129,
|
||||
138,
|
||||
144,
|
||||
148,
|
||||
148,
|
||||
144,
|
||||
138,
|
||||
128,
|
||||
114,
|
||||
98,
|
||||
79,
|
||||
58,
|
||||
34,
|
||||
9,
|
||||
-16,
|
||||
-42,
|
||||
-69,
|
||||
-95,
|
||||
-120,
|
||||
-143,
|
||||
-163,
|
||||
-181,
|
||||
-195,
|
||||
-205,
|
||||
-211,
|
||||
-212,
|
||||
-209,
|
||||
-201,
|
||||
-188,
|
||||
-171,
|
||||
-149,
|
||||
-124,
|
||||
-94,
|
||||
-62,
|
||||
-27,
|
||||
8,
|
||||
46,
|
||||
84,
|
||||
121,
|
||||
156,
|
||||
189,
|
||||
219,
|
||||
245,
|
||||
267,
|
||||
283,
|
||||
294,
|
||||
298,
|
||||
295,
|
||||
287,
|
||||
271,
|
||||
249,
|
||||
221,
|
||||
187,
|
||||
148,
|
||||
104,
|
||||
57,
|
||||
7,
|
||||
-44,
|
||||
-96,
|
||||
-148,
|
||||
-198,
|
||||
-245,
|
||||
-288,
|
||||
-326,
|
||||
-358,
|
||||
-382,
|
||||
-400,
|
||||
-408,
|
||||
-408,
|
||||
-399,
|
||||
-381,
|
||||
-354,
|
||||
-318,
|
||||
-274,
|
||||
-223,
|
||||
-165,
|
||||
-102,
|
||||
-35,
|
||||
34,
|
||||
105,
|
||||
175,
|
||||
244,
|
||||
309,
|
||||
370,
|
||||
424,
|
||||
470,
|
||||
507,
|
||||
533,
|
||||
549,
|
||||
553,
|
||||
545,
|
||||
524,
|
||||
492,
|
||||
447,
|
||||
392,
|
||||
326,
|
||||
252,
|
||||
169,
|
||||
81,
|
||||
-10,
|
||||
-105,
|
||||
-200,
|
||||
-293,
|
||||
-383,
|
||||
-466,
|
||||
-541,
|
||||
-606,
|
||||
-660,
|
||||
-700,
|
||||
-726,
|
||||
-737,
|
||||
-732,
|
||||
-710,
|
||||
-672,
|
||||
-619,
|
||||
-550,
|
||||
-467,
|
||||
-372,
|
||||
-266,
|
||||
-152,
|
||||
-31,
|
||||
93,
|
||||
219,
|
||||
344,
|
||||
464,
|
||||
577,
|
||||
680,
|
||||
771,
|
||||
847,
|
||||
907,
|
||||
948,
|
||||
970,
|
||||
970,
|
||||
949,
|
||||
907,
|
||||
843,
|
||||
760,
|
||||
657,
|
||||
537,
|
||||
403,
|
||||
256,
|
||||
99,
|
||||
-62,
|
||||
-228,
|
||||
-392,
|
||||
-552,
|
||||
-704,
|
||||
-845,
|
||||
-970,
|
||||
-1077,
|
||||
-1164,
|
||||
-1226,
|
||||
-1264,
|
||||
-1274,
|
||||
-1257,
|
||||
-1211,
|
||||
-1138,
|
||||
-1038,
|
||||
-912,
|
||||
-763,
|
||||
-593,
|
||||
-407,
|
||||
-206,
|
||||
3,
|
||||
219,
|
||||
435,
|
||||
647,
|
||||
851,
|
||||
1040,
|
||||
1212,
|
||||
1361,
|
||||
1484,
|
||||
1578,
|
||||
1639,
|
||||
1666,
|
||||
1656,
|
||||
1610,
|
||||
1528,
|
||||
1409,
|
||||
1257,
|
||||
1073,
|
||||
860,
|
||||
623,
|
||||
367,
|
||||
95,
|
||||
-184,
|
||||
-468,
|
||||
-749,
|
||||
-1020,
|
||||
-1277,
|
||||
-1512,
|
||||
-1719,
|
||||
-1894,
|
||||
-2033,
|
||||
-2130,
|
||||
-2182,
|
||||
-2188,
|
||||
-2146,
|
||||
-2056,
|
||||
-1918,
|
||||
-1734,
|
||||
-1507,
|
||||
-1240,
|
||||
-939,
|
||||
-610,
|
||||
-257,
|
||||
109,
|
||||
484,
|
||||
859,
|
||||
1225,
|
||||
1574,
|
||||
1898,
|
||||
2190,
|
||||
2441,
|
||||
2646,
|
||||
2798,
|
||||
2893,
|
||||
2926,
|
||||
2897,
|
||||
2802,
|
||||
2643,
|
||||
2421,
|
||||
2140,
|
||||
1803,
|
||||
1416,
|
||||
986,
|
||||
522,
|
||||
32,
|
||||
-472,
|
||||
-983,
|
||||
-1487,
|
||||
-1974,
|
||||
-2433,
|
||||
-2853,
|
||||
-3223,
|
||||
-3534,
|
||||
-3777,
|
||||
-3944,
|
||||
-4030,
|
||||
-4029,
|
||||
-3940,
|
||||
-3760,
|
||||
-3492,
|
||||
-3137,
|
||||
-2701,
|
||||
-2189,
|
||||
-1611,
|
||||
-977,
|
||||
-298,
|
||||
411,
|
||||
1139,
|
||||
1868,
|
||||
2584,
|
||||
3270,
|
||||
3910,
|
||||
4489,
|
||||
4991,
|
||||
5404,
|
||||
5713,
|
||||
5909,
|
||||
5982,
|
||||
5926,
|
||||
5735,
|
||||
5409,
|
||||
4948,
|
||||
4356,
|
||||
3639,
|
||||
2808,
|
||||
1873,
|
||||
851,
|
||||
-241,
|
||||
-1385,
|
||||
-2559,
|
||||
-3738,
|
||||
-4899,
|
||||
-6016,
|
||||
-7064,
|
||||
-8015,
|
||||
-8845,
|
||||
-9529,
|
||||
-10043,
|
||||
-10366,
|
||||
-10479,
|
||||
-10363,
|
||||
-10006,
|
||||
-9397,
|
||||
-8529,
|
||||
-7398,
|
||||
-6005,
|
||||
-4355,
|
||||
-2456,
|
||||
-320,
|
||||
2033,
|
||||
4587,
|
||||
7316,
|
||||
10193,
|
||||
13188,
|
||||
16268,
|
||||
19400,
|
||||
22548,
|
||||
25673,
|
||||
28740,
|
||||
31710,
|
||||
34547,
|
||||
37216,
|
||||
39683,
|
||||
41916,
|
||||
43887,
|
||||
45570,
|
||||
46943,
|
||||
47990,
|
||||
48695,
|
||||
49050,
|
12
source/fir/c96000ntsc.scm
Normal file
12
source/fir/c96000ntsc.scm
Normal file
@ -0,0 +1,12 @@
|
||||
(title "96000 NTSC")
|
||||
|
||||
(verbose #t)
|
||||
|
||||
(cosine-symmetry)
|
||||
(filter-length 1024)
|
||||
(sampling-frequency 1789772.727272727272)
|
||||
(limit-= (band 0 36850) 1)
|
||||
(limit-= (band 48000 894886.363636) 0 .5)
|
||||
(output-file "c96000ntsc.coef")
|
||||
(plot-file "c96000ntsc.plot")
|
||||
(go)
|
1039
source/fir/c96000pal.coef
Normal file
1039
source/fir/c96000pal.coef
Normal file
File diff suppressed because it is too large
Load Diff
512
source/fir/c96000pal.h
Normal file
512
source/fir/c96000pal.h
Normal file
@ -0,0 +1,512 @@
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
-1,
|
||||
-2,
|
||||
-3,
|
||||
-3,
|
||||
-4,
|
||||
-4,
|
||||
-5,
|
||||
-5,
|
||||
-5,
|
||||
-5,
|
||||
-5,
|
||||
-5,
|
||||
-4,
|
||||
-4,
|
||||
-3,
|
||||
-2,
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
9,
|
||||
8,
|
||||
7,
|
||||
6,
|
||||
4,
|
||||
2,
|
||||
0,
|
||||
-1,
|
||||
-4,
|
||||
-6,
|
||||
-8,
|
||||
-11,
|
||||
-13,
|
||||
-15,
|
||||
-16,
|
||||
-18,
|
||||
-19,
|
||||
-19,
|
||||
-19,
|
||||
-19,
|
||||
-18,
|
||||
-17,
|
||||
-15,
|
||||
-13,
|
||||
-10,
|
||||
-6,
|
||||
-3,
|
||||
0,
|
||||
4,
|
||||
8,
|
||||
12,
|
||||
17,
|
||||
20,
|
||||
24,
|
||||
27,
|
||||
30,
|
||||
32,
|
||||
33,
|
||||
34,
|
||||
34,
|
||||
33,
|
||||
31,
|
||||
28,
|
||||
25,
|
||||
20,
|
||||
15,
|
||||
9,
|
||||
3,
|
||||
-3,
|
||||
-10,
|
||||
-17,
|
||||
-24,
|
||||
-31,
|
||||
-37,
|
||||
-43,
|
||||
-48,
|
||||
-52,
|
||||
-55,
|
||||
-57,
|
||||
-57,
|
||||
-56,
|
||||
-54,
|
||||
-50,
|
||||
-45,
|
||||
-38,
|
||||
-30,
|
||||
-21,
|
||||
-11,
|
||||
0,
|
||||
10,
|
||||
21,
|
||||
33,
|
||||
44,
|
||||
55,
|
||||
64,
|
||||
73,
|
||||
80,
|
||||
86,
|
||||
90,
|
||||
92,
|
||||
91,
|
||||
88,
|
||||
84,
|
||||
76,
|
||||
67,
|
||||
56,
|
||||
42,
|
||||
27,
|
||||
11,
|
||||
-5,
|
||||
-23,
|
||||
-41,
|
||||
-59,
|
||||
-76,
|
||||
-92,
|
||||
-106,
|
||||
-119,
|
||||
-129,
|
||||
-136,
|
||||
-141,
|
||||
-142,
|
||||
-140,
|
||||
-134,
|
||||
-125,
|
||||
-112,
|
||||
-96,
|
||||
-77,
|
||||
-56,
|
||||
-32,
|
||||
-6,
|
||||
19,
|
||||
47,
|
||||
74,
|
||||
100,
|
||||
125,
|
||||
149,
|
||||
169,
|
||||
186,
|
||||
199,
|
||||
208,
|
||||
213,
|
||||
212,
|
||||
206,
|
||||
195,
|
||||
179,
|
||||
158,
|
||||
132,
|
||||
102,
|
||||
68,
|
||||
32,
|
||||
-6,
|
||||
-46,
|
||||
-86,
|
||||
-126,
|
||||
-164,
|
||||
-200,
|
||||
-232,
|
||||
-259,
|
||||
-282,
|
||||
-298,
|
||||
-308,
|
||||
-311,
|
||||
-307,
|
||||
-294,
|
||||
-275,
|
||||
-248,
|
||||
-214,
|
||||
-173,
|
||||
-128,
|
||||
-77,
|
||||
-23,
|
||||
33,
|
||||
91,
|
||||
149,
|
||||
205,
|
||||
258,
|
||||
307,
|
||||
350,
|
||||
386,
|
||||
415,
|
||||
434,
|
||||
443,
|
||||
442,
|
||||
431,
|
||||
408,
|
||||
375,
|
||||
332,
|
||||
280,
|
||||
219,
|
||||
151,
|
||||
76,
|
||||
-1,
|
||||
-82,
|
||||
-164,
|
||||
-245,
|
||||
-322,
|
||||
-394,
|
||||
-459,
|
||||
-515,
|
||||
-561,
|
||||
-595,
|
||||
-615,
|
||||
-622,
|
||||
-613,
|
||||
-590,
|
||||
-552,
|
||||
-499,
|
||||
-433,
|
||||
-354,
|
||||
-264,
|
||||
-165,
|
||||
-59,
|
||||
51,
|
||||
164,
|
||||
277,
|
||||
387,
|
||||
490,
|
||||
586,
|
||||
670,
|
||||
741,
|
||||
797,
|
||||
835,
|
||||
854,
|
||||
853,
|
||||
832,
|
||||
790,
|
||||
729,
|
||||
647,
|
||||
548,
|
||||
433,
|
||||
304,
|
||||
163,
|
||||
15,
|
||||
-138,
|
||||
-293,
|
||||
-445,
|
||||
-592,
|
||||
-729,
|
||||
-852,
|
||||
-959,
|
||||
-1046,
|
||||
-1111,
|
||||
-1151,
|
||||
-1165,
|
||||
-1151,
|
||||
-1110,
|
||||
-1040,
|
||||
-944,
|
||||
-822,
|
||||
-677,
|
||||
-512,
|
||||
-329,
|
||||
-133,
|
||||
71,
|
||||
280,
|
||||
489,
|
||||
693,
|
||||
886,
|
||||
1063,
|
||||
1220,
|
||||
1353,
|
||||
1458,
|
||||
1530,
|
||||
1569,
|
||||
1571,
|
||||
1535,
|
||||
1462,
|
||||
1352,
|
||||
1206,
|
||||
1027,
|
||||
818,
|
||||
584,
|
||||
328,
|
||||
57,
|
||||
-222,
|
||||
-505,
|
||||
-785,
|
||||
-1054,
|
||||
-1306,
|
||||
-1534,
|
||||
-1733,
|
||||
-1896,
|
||||
-2019,
|
||||
-2097,
|
||||
-2128,
|
||||
-2108,
|
||||
-2038,
|
||||
-1917,
|
||||
-1747,
|
||||
-1529,
|
||||
-1269,
|
||||
-970,
|
||||
-639,
|
||||
-283,
|
||||
90,
|
||||
474,
|
||||
857,
|
||||
1233,
|
||||
1590,
|
||||
1921,
|
||||
2216,
|
||||
2467,
|
||||
2667,
|
||||
2810,
|
||||
2890,
|
||||
2904,
|
||||
2849,
|
||||
2724,
|
||||
2530,
|
||||
2270,
|
||||
1946,
|
||||
1566,
|
||||
1135,
|
||||
664,
|
||||
160,
|
||||
-363,
|
||||
-895,
|
||||
-1425,
|
||||
-1938,
|
||||
-2423,
|
||||
-2866,
|
||||
-3256,
|
||||
-3582,
|
||||
-3834,
|
||||
-4003,
|
||||
-4082,
|
||||
-4067,
|
||||
-3953,
|
||||
-3741,
|
||||
-3431,
|
||||
-3028,
|
||||
-2537,
|
||||
-1967,
|
||||
-1328,
|
||||
-632,
|
||||
106,
|
||||
871,
|
||||
1646,
|
||||
2413,
|
||||
3154,
|
||||
3849,
|
||||
4482,
|
||||
5034,
|
||||
5489,
|
||||
5833,
|
||||
6051,
|
||||
6134,
|
||||
6074,
|
||||
5864,
|
||||
5504,
|
||||
4994,
|
||||
4339,
|
||||
3546,
|
||||
2628,
|
||||
1599,
|
||||
477,
|
||||
-716,
|
||||
-1958,
|
||||
-3223,
|
||||
-4482,
|
||||
-5708,
|
||||
-6869,
|
||||
-7936,
|
||||
-8878,
|
||||
-9666,
|
||||
-10273,
|
||||
-10671,
|
||||
-10839,
|
||||
-10755,
|
||||
-10402,
|
||||
-9767,
|
||||
-8843,
|
||||
-7623,
|
||||
-6110,
|
||||
-4308,
|
||||
-2228,
|
||||
114,
|
||||
2701,
|
||||
5505,
|
||||
8499,
|
||||
11650,
|
||||
14923,
|
||||
18277,
|
||||
21673,
|
||||
25068,
|
||||
28417,
|
||||
31678,
|
||||
34807,
|
||||
37762,
|
||||
40502,
|
||||
42991,
|
||||
45192,
|
||||
47076,
|
||||
48617,
|
||||
49792,
|
||||
50584,
|
||||
50983,
|
12
source/fir/c96000pal.scm
Normal file
12
source/fir/c96000pal.scm
Normal file
@ -0,0 +1,12 @@
|
||||
(title "96000 PAL")
|
||||
|
||||
(verbose #t)
|
||||
|
||||
(cosine-symmetry)
|
||||
(filter-length 1024)
|
||||
(sampling-frequency 1662607.125)
|
||||
(limit-= (band 0 33400) 1)
|
||||
(limit-= (band 48000 831303.5625) 0 .5)
|
||||
(output-file "c96000pal.coef")
|
||||
(plot-file "c96000pal.plot")
|
||||
(go)
|
24
source/fir/toh.c
Normal file
24
source/fir/toh.c
Normal file
@ -0,0 +1,24 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#define MAX 512
|
||||
|
||||
main()
|
||||
{
|
||||
char buf[256];
|
||||
int count=0;
|
||||
|
||||
while(fgets(buf,256,stdin)>0)
|
||||
{
|
||||
double p;
|
||||
|
||||
if(sscanf(buf,"%lf",&p)==1)
|
||||
{
|
||||
p*=65536*16;
|
||||
printf("%ld,\n",(long)p);
|
||||
count++;
|
||||
if(count==MAX) break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
225
source/general.c
Normal file
225
source/general.c
Normal file
@ -0,0 +1,225 @@
|
||||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "fceu.h"
|
||||
|
||||
#include "general.h"
|
||||
#include "state.h"
|
||||
#include "movie.h"
|
||||
|
||||
#include "driver.h"
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
static char BaseDirectory[2048];
|
||||
static char FileBase[2048];
|
||||
static char FileExt[2048]; /* Includes the . character, as in ".nes" */
|
||||
|
||||
static char FileBaseDirectory[2048];
|
||||
|
||||
void FCEUI_SetBaseDirectory(char *dir)
|
||||
{
|
||||
strncpy(BaseDirectory,dir,2047);
|
||||
BaseDirectory[2047]=0;
|
||||
}
|
||||
|
||||
static char *odirs[FCEUIOD__COUNT]={0,0,0,0,0,0}; // odirs, odors. ^_^
|
||||
|
||||
void FCEUI_SetDirOverride(int which, char *n)
|
||||
{
|
||||
odirs[which]=n;
|
||||
|
||||
if(FCEUGameInfo) /* Rebuild cache of present states/movies. */
|
||||
{
|
||||
if(which==FCEUIOD_STATE)
|
||||
FCEUSS_CheckStates();
|
||||
else if(which == FCEUIOD_MOVIE)
|
||||
FCEUMOV_CheckMovies();
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef HAVE_ASPRINTF
|
||||
static int asprintf(char **strp, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
va_start(ap,fmt);
|
||||
if(!(*strp=malloc(2048)))
|
||||
return(0);
|
||||
ret=vsnprintf(*strp,2048,fmt,ap);
|
||||
va_end(ap);
|
||||
return(ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
char *FCEU_MakeFName(int type, int id1, char *cd1)
|
||||
{
|
||||
char *ret=0;
|
||||
|
||||
/*** REMOVED GC V1.0
|
||||
struct stat tmpstat;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case FCEUMKF_NPTEMP: asprintf(&ret,"%s"PSS"m590plqd94fo.tmp",BaseDirectory);break;
|
||||
case FCEUMKF_MOVIE:if(odirs[FCEUIOD_STATE])
|
||||
asprintf(&ret,"%s"PSS"%s.%d.fcm",odirs[FCEUIOD_STATE],FileBase,id1);
|
||||
else
|
||||
asprintf(&ret,"%s"PSS"fcs"PSS"%s.%d.fcm",BaseDirectory,FileBase,id1);
|
||||
if(stat(ret,&tmpstat)==-1)
|
||||
{
|
||||
if(odirs[FCEUIOD_STATE])
|
||||
asprintf(&ret,"%s"PSS"%s.%s.%d.fcm",odirs[FCEUIOD_STATE],FileBase,md5_asciistr(FCEUGameInfo->MD5),id1);
|
||||
else
|
||||
asprintf(&ret,"%s"PSS"fcs"PSS"%s.%s.%d.fcm",BaseDirectory,FileBase,md5_asciistr(FCEUGameInfo->MD5),id1);
|
||||
}
|
||||
break;
|
||||
case FCEUMKF_STATE:if(odirs[FCEUIOD_STATE])
|
||||
asprintf(&ret,"%s"PSS"%s.fc%d",odirs[FCEUIOD_STATE],FileBase,id1);
|
||||
else
|
||||
asprintf(&ret,"%s"PSS"fcs"PSS"%s.fc%d",BaseDirectory,FileBase,id1);
|
||||
if(stat(ret,&tmpstat)==-1)
|
||||
{
|
||||
if(odirs[FCEUIOD_STATE])
|
||||
asprintf(&ret,"%s"PSS"%s.%s.fc%d",odirs[FCEUIOD_STATE],FileBase,md5_asciistr(FCEUGameInfo->MD5),id1);
|
||||
else
|
||||
asprintf(&ret,"%s"PSS"fcs"PSS"%s.%s.fc%d",BaseDirectory,FileBase,md5_asciistr(FCEUGameInfo->MD5),id1);
|
||||
}
|
||||
break;
|
||||
case FCEUMKF_SNAP:
|
||||
if(FSettings.SnapName)
|
||||
{
|
||||
if(odirs[FCEUIOD_SNAPS])
|
||||
asprintf(&ret,"%s"PSS"%s-%d.%s",odirs[FCEUIOD_SNAPS],FileBase,id1,cd1);
|
||||
else
|
||||
asprintf(&ret,"%s"PSS"snaps"PSS"%s-%d.%s",BaseDirectory,FileBase,id1,cd1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(odirs[FCEUIOD_SNAPS])
|
||||
asprintf(&ret,"%s"PSS"%d.%s",odirs[FCEUIOD_SNAPS],id1,cd1);
|
||||
else
|
||||
asprintf(&ret,"%s"PSS"snaps"PSS"%d.%s",BaseDirectory,id1,cd1);
|
||||
}
|
||||
break;
|
||||
case FCEUMKF_FDS:if(odirs[FCEUIOD_NV])
|
||||
asprintf(&ret,"%s"PSS"%s.%s.fds",odirs[FCEUIOD_NV],FileBase,md5_asciistr(FCEUGameInfo->MD5));
|
||||
else
|
||||
asprintf(&ret,"%s"PSS"sav"PSS"%s.%s.fds",BaseDirectory,FileBase,md5_asciistr(FCEUGameInfo->MD5));
|
||||
break;
|
||||
case FCEUMKF_SAV:if(odirs[FCEUIOD_NV])
|
||||
asprintf(&ret,"%s"PSS"%s.%s",odirs[FCEUIOD_NV],FileBase,cd1);
|
||||
else
|
||||
asprintf(&ret,"%s"PSS"sav"PSS"%s.%s",BaseDirectory,FileBase,cd1);
|
||||
if(stat(ret,&tmpstat)==-1)
|
||||
{
|
||||
if(odirs[FCEUIOD_NV])
|
||||
asprintf(&ret,"%s"PSS"%s.%s.%s",odirs[FCEUIOD_NV],FileBase,md5_asciistr(FCEUGameInfo->MD5),cd1);
|
||||
else
|
||||
asprintf(&ret,"%s"PSS"sav"PSS"%s.%s.%s",BaseDirectory,FileBase,md5_asciistr(FCEUGameInfo->MD5),cd1);
|
||||
}
|
||||
break;
|
||||
case FCEUMKF_CHEAT:
|
||||
if(odirs[FCEUIOD_CHEATS])
|
||||
asprintf(&ret,"%s"PSS"%s.cht",odirs[FCEUIOD_CHEATS],FileBase);
|
||||
else
|
||||
asprintf(&ret,"%s"PSS"cheats"PSS"%s.cht",BaseDirectory,FileBase);
|
||||
break;
|
||||
case FCEUMKF_IPS: asprintf(&ret,"%s"PSS"%s%s.ips",FileBaseDirectory,FileBase,FileExt);
|
||||
break;
|
||||
case FCEUMKF_GGROM:asprintf(&ret,"%s"PSS"gg.rom",BaseDirectory);break;
|
||||
case FCEUMKF_FDSROM:asprintf(&ret,"%s"PSS"disksys.rom",BaseDirectory);break;
|
||||
case FCEUMKF_PALETTE:
|
||||
if(odirs[FCEUIOD_MISC])
|
||||
asprintf(&ret,"%s"PSS"%s.pal",odirs[FCEUIOD_MISC],FileBase);
|
||||
else
|
||||
asprintf(&ret,"%s"PSS"gameinfo"PSS"%s.pal",BaseDirectory,FileBase);
|
||||
break;
|
||||
}
|
||||
|
||||
REMOVED GC V1.0 ***/
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void GetFileBase(const char *f)
|
||||
{
|
||||
const char *tp1,*tp3;
|
||||
|
||||
#if PSS_STYLE==4
|
||||
tp1=((char *)strrchr(f,':'));
|
||||
#elif PSS_STYLE==1
|
||||
tp1=((char *)strrchr(f,'/'));
|
||||
#else
|
||||
tp1=((char *)strrchr(f,'\\'));
|
||||
#if PSS_STYLE!=3
|
||||
tp3=((char *)strrchr(f,'/'));
|
||||
if(tp1<tp3) tp1=tp3;
|
||||
#endif
|
||||
#endif
|
||||
if(!tp1)
|
||||
{
|
||||
tp1=f;
|
||||
strcpy(FileBaseDirectory,".");
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(FileBaseDirectory,f,tp1-f);
|
||||
FileBaseDirectory[tp1-f]=0;
|
||||
tp1++;
|
||||
}
|
||||
|
||||
if(((tp3=strrchr(f,'.'))!=NULL) && (tp3>tp1))
|
||||
{
|
||||
memcpy(FileBase,tp1,tp3-tp1);
|
||||
FileBase[tp3-tp1]=0;
|
||||
strcpy(FileExt,tp3);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(FileBase,tp1);
|
||||
FileExt[0]=0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 uppow2(uint32 n)
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x=31;x>=0;x--)
|
||||
if(n&(1<<x))
|
||||
{
|
||||
if((1<<x)!=n)
|
||||
return(1<<(x+1));
|
||||
break;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
16
source/general.h
Normal file
16
source/general.h
Normal file
@ -0,0 +1,16 @@
|
||||
void GetFileBase(const char *f);
|
||||
extern uint32 uppow2(uint32 n);
|
||||
|
||||
char *FCEU_MakeFName(int type, int id1, char *cd1);
|
||||
|
||||
#define FCEUMKF_STATE 1
|
||||
#define FCEUMKF_SNAP 2
|
||||
#define FCEUMKF_SAV 3
|
||||
#define FCEUMKF_CHEAT 4
|
||||
#define FCEUMKF_FDSROM 5
|
||||
#define FCEUMKF_PALETTE 6
|
||||
#define FCEUMKF_GGROM 7
|
||||
#define FCEUMKF_IPS 8
|
||||
#define FCEUMKF_FDS 9
|
||||
#define FCEUMKF_MOVIE 10
|
||||
#define FCEUMKF_NPTEMP 11
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user