add 2008-03-26 release

This commit is contained in:
dsbomb 2008-04-03 03:58:35 +00:00
commit 11f8c6a70f
297 changed files with 105722 additions and 0 deletions

177
Makefile Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

1
fceugc.pnproj Normal file

File diff suppressed because one or more lines are too long

1
fceugc.pnps Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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");
}

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

@ -0,0 +1 @@
uint32 CalcCRC32(uint32 crc, uint8 *buf, uint32 len);

520
source/debug.c Normal file
View 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
View 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
View 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
View 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

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

View 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

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

View 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);

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

View 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

File diff suppressed because it is too large Load Diff

View 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

File diff suppressed because it is too large Load Diff

View 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);

View 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 :
*
* &current -> E
* &current_left -> D
* &current_right -> F
* &current_upper -> B
* &current_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

View 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

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

View 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

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

View 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

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

View 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);

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

View 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

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

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

View 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];

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

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

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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)
{
}

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

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

File diff suppressed because it is too large Load Diff

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

View 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,
};

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

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

File diff suppressed because it is too large Load Diff

103
source/fceu.h Normal file
View 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
View 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
View 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
View File

@ -0,0 +1,4 @@
typedef struct {
uint8 *data;
uint32 len; /* Not including extra NULL character. */
} fceustr;

1589
source/fcoeffs.h Normal file

File diff suppressed because it is too large Load Diff

874
source/fds.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

512
source/fir/c44100ntsc.h Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

512
source/fir/c44100pal.h Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

512
source/fir/c48000ntsc.h Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

512
source/fir/c48000pal.h Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

512
source/fir/c96000ntsc.h Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

512
source/fir/c96000pal.h Normal file
View 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
View 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
View 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
View 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
View 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