Compare commits
1 Commits
master
...
release_0_
Author | SHA1 | Date |
---|---|---|
![]() |
0e7d46a55e |
|
@ -1,19 +0,0 @@
|
|||
---
|
||||
name: New Issue, Bug report, Question
|
||||
about: New Issue, Bug report, Question
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## State your operating system:
|
||||
Windows/Mac/Linux. in case of linux, whether you use CLI, gtk2, or gtk3 version.
|
||||
|
||||
## DesMuME version
|
||||
e.g. 0.9.13 or git master
|
||||
|
||||
## Isse
|
||||
type here what's bothering you, in a detailed manner.
|
||||
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
name: DeSmuME
|
||||
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build DeSmuME (Linux)
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: install dependencies
|
||||
run: sudo apt update && sudo apt install meson libsdl2-dev libpcap-dev libgtk-3-dev
|
||||
|
||||
- name: meson
|
||||
run: |
|
||||
cd desmume/src/frontend/posix/
|
||||
meson build
|
||||
|
||||
- name: ninja
|
||||
run: ninja -C desmume/src/frontend/posix/build
|
||||
|
||||
build_gtk2:
|
||||
name: Build DeSmuME (Linux/GTK+2)
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: install dependencies
|
||||
run: sudo apt update && sudo apt install autoconf libglu1-mesa-dev libsdl2-dev libpcap-dev libgtk2.0-dev
|
||||
|
||||
- name: buildit
|
||||
run: |
|
||||
cd desmume/src/frontend/posix/
|
||||
autoreconf -i
|
||||
./configure --prefix=/usr --enable-gdb-stub --enable-wifi
|
||||
make -j8
|
||||
make DESTDIR=/tmp/DeSmuME install
|
||||
|
||||
- name: Pack artifact
|
||||
run: |
|
||||
cd /tmp
|
||||
tar cJf DeSmuME.tar.xz DeSmuME/
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: desmume-linux-gtk2-cli-x86_64
|
||||
path: /tmp/DeSmuME.tar.xz
|
||||
|
||||
build_macos:
|
||||
name: Build DeSmuME (macOS)
|
||||
runs-on: macos-14
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: xcodebuild
|
||||
run: |
|
||||
cd desmume/src/frontend/cocoa/
|
||||
xcodebuild archive -project "DeSmuME (Latest).xcodeproj" -scheme "DeSmuME (macOS App; Intel64 -- Latest Xcode)" -arch x86_64 -archivePath "$(pwd)/desmume.xcarchive" | xcpretty -c
|
||||
|
||||
- name: make zip
|
||||
run: |
|
||||
cd desmume/src/frontend/cocoa/desmume.xcarchive/Products/Applications/
|
||||
7z a DeSmuME.app.zip DeSmuME.app
|
||||
|
||||
- name: Upload artifict
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macos
|
||||
path: desmume/src/frontend/cocoa/desmume.xcarchive/Products/Applications/DeSmuME.app.zip
|
||||
if-no-files-found: error
|
|
@ -1,87 +0,0 @@
|
|||
name: DeSmuME Interface (DLL/SO)
|
||||
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
runs-on: ubuntu-24.04
|
||||
name: Build Linux
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt update && sudo apt install meson libsdl2-dev libpcap-dev
|
||||
|
||||
- name: Build - Meson
|
||||
run: |
|
||||
cd desmume/src/frontend/interface/
|
||||
meson build
|
||||
|
||||
- name: Build - ninja
|
||||
run: ninja -C desmume/src/frontend/interface/build
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: linux
|
||||
path: desmume/src/frontend/interface/build/libdesmume.so
|
||||
|
||||
build_macos:
|
||||
runs-on: macos-14
|
||||
name: Build MacOS
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install MacOS build deps
|
||||
run: brew install coreutils sdl2 meson
|
||||
|
||||
- name: Build - Meson
|
||||
run: |
|
||||
cd desmume/src/frontend/interface/
|
||||
meson build
|
||||
env:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
|
||||
- name: Build - ninja
|
||||
run: ninja -C desmume/src/frontend/interface/build
|
||||
env:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macos
|
||||
path: desmume/src/frontend/interface/build/libdesmume.dylib
|
||||
|
||||
build_windows:
|
||||
runs-on: windows-2022
|
||||
name: Build Windows
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [ 'x64', 'x86' ]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
with:
|
||||
msbuild-architecture: ${{ matrix.arch }}
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cd desmume\src\frontend\interface\windows
|
||||
MSBuild.exe DeSmuME_Interface.vcxproj /p:configuration="Release Fastbuild" /p:Platform=${{ matrix.arch }}
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: win-${{ matrix.arch }}
|
||||
path: desmume/src/frontend/interface/windows/__bins/*.dll
|
|
@ -1,30 +0,0 @@
|
|||
name: DeSmuME Windows build
|
||||
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
build-sln:
|
||||
runs-on: windows-2022
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup MSBuild.exe
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
with:
|
||||
msbuild-architecture: x64
|
||||
|
||||
- name: Build solution
|
||||
run: |
|
||||
SET CL=-Wno-c++11-narrowing
|
||||
msbuild 'desmume/src/frontend/windows/DeSmuME.sln' /p:configuration="Release" /p:platform=x64 /p:CL_cgthreads=1 /p:CLToolExe=clang-cl.exe
|
||||
cmd /c desmume\src\frontend\windows\ci_postbuild.bat
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: desmume-win-x64
|
||||
path: desmume/src/frontend/windows/__bins/*.exe
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
name: Generate Source Tarball
|
||||
|
||||
# Trigger whenever a release is created
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: archive
|
||||
id: archive
|
||||
run: |
|
||||
THISDIR="$PWD"
|
||||
cd desmume/src/frontend/posix
|
||||
autoreconf -i
|
||||
cd "$THISDIR"
|
||||
VERSION=$(printf "%s\n" ${{ github.event.release.tag_name }} | sed -e 's/^release_//' -e 's/_/./g')
|
||||
PKGNAME="desmume-$VERSION"
|
||||
mkdir -p /tmp/$PKGNAME
|
||||
mv * /tmp/$PKGNAME
|
||||
mv /tmp/$PKGNAME .
|
||||
TARBALL=$PKGNAME.tar.xz
|
||||
tar cJf $TARBALL $PKGNAME
|
||||
echo "::set-output name=tarball::$TARBALL"
|
||||
|
||||
- name: upload tarball
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ github.event.release.upload_url }}
|
||||
asset_path: ./${{ steps.archive.outputs.tarball }}
|
||||
asset_name: ${{ steps.archive.outputs.tarball }}
|
||||
asset_content_type: application/x-xz
|
|
@ -1,77 +0,0 @@
|
|||
/desmume/src/scmrev.h
|
||||
/desmume/src/frontend/windows/defaultconfig/scmrev.h
|
||||
/desmume/src/frontend/windows/.libs
|
||||
/desmume/src/frontend/windows/.obj
|
||||
/desmume/src/frontend/windows/__bins
|
||||
/desmume/src/frontend/windows/*.tlog
|
||||
/desmume/src/frontend/windows/*.aps
|
||||
.vs/
|
||||
*.user
|
||||
*.suo
|
||||
*.VC.db
|
||||
*.VC.opendb
|
||||
*.o
|
||||
*.ipch
|
||||
.deps
|
||||
*.dirstamp
|
||||
Makefile.in
|
||||
/desmume/src/frontend/posix/missing
|
||||
/desmume/src/frontend/posix/*.a
|
||||
/desmume/src/frontend/posix/autom4te.cache
|
||||
/desmume/src/frontend/posix/Makefile
|
||||
/desmume/src/frontend/posix/aclocal.m4
|
||||
/desmume/src/frontend/posix/configure
|
||||
/desmume/src/frontend/posix/cli/Makefile
|
||||
/desmume/src/frontend/posix/cli/desmume-cli
|
||||
/desmume/src/frontend/posix/cli/doc/Makefile
|
||||
/desmume/src/frontend/posix/compile
|
||||
/desmume/src/frontend/posix/config.guess
|
||||
/desmume/src/frontend/posix/config.log
|
||||
/desmume/src/frontend/posix/config.status
|
||||
/desmume/src/frontend/posix/config.sub
|
||||
/desmume/src/frontend/posix/depcomp
|
||||
/desmume/src/frontend/posix/gtk/Makefile
|
||||
/desmume/src/frontend/posix/gtk/desmume
|
||||
/desmume/src/frontend/posix/gtk/doc/Makefile
|
||||
/desmume/src/frontend/posix/gtk-glade/Makefile
|
||||
/desmume/src/frontend/posix/gtk-glade/desmume-glade
|
||||
/desmume/src/frontend/posix/gtk-glade/doc/Makefile
|
||||
/desmume/src/frontend/posix/install-sh
|
||||
/desmume/src/frontend/cocoa/openemu/OpenEmuBase.framework/
|
||||
/desmume/src/frontend/cocoa/OptimizationProfiles/
|
||||
|
||||
# Xcode
|
||||
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData/
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata/
|
||||
.vs/ProjectSettings.json
|
||||
|
||||
## Other
|
||||
*.moved-aside
|
||||
*.xcuserstate
|
||||
*.xcscmblueprint
|
||||
|
||||
## Obj-C/Swift specific
|
||||
*.hmap
|
||||
*.ipa
|
||||
*.dSYM.zip
|
||||
*.dSYM
|
||||
|
||||
## Eclipse CDT generated files
|
||||
/.autotools
|
||||
/.cproject
|
||||
/config.log
|
||||
/.project
|
||||
.DS_Store
|
|
@ -6,12 +6,21 @@ Current team
|
|||
------------
|
||||
Guillaume Duhamel
|
||||
Normmatt
|
||||
Bernat Muñoz (shash)
|
||||
thoduv
|
||||
Tim Seidel (Mighty Max)
|
||||
Pascal Giard (evilynux)
|
||||
Ben Jaques (masscat)
|
||||
Jeff Bland
|
||||
Andres Delikat
|
||||
Riccardo Magliocchetti
|
||||
Max Tabachenko (CrazyMax/mtabachenko)
|
||||
zeromus
|
||||
rogerman
|
||||
Luigi__
|
||||
adelikat
|
||||
|
||||
Contributors
|
||||
------------
|
||||
Bernat Muñoz (shash)
|
||||
Allustar
|
||||
amponzi
|
||||
Anthony Molinaro
|
||||
|
@ -21,30 +30,3 @@ delfare
|
|||
Romain Vallet
|
||||
snkmad
|
||||
Theo Berkau
|
||||
thoduv
|
||||
Tim Seidel (Mighty Max)
|
||||
Pascal Giard (evilynux)
|
||||
Ben Jaques (masscat)
|
||||
Jeff Bland
|
||||
Bernat Muñoz (shash)
|
||||
matusz
|
||||
nitsuja
|
||||
gocha
|
||||
pa__
|
||||
adelikat
|
||||
hi-coder
|
||||
WinterMute
|
||||
pengvado
|
||||
dormito
|
||||
ldesnogue
|
||||
mtheall
|
||||
thelemonman
|
||||
nash679
|
||||
pokefan999
|
||||
dottorleo
|
||||
yki
|
||||
Luigi__
|
||||
CrazyMax
|
||||
Riccardo Magliocchetti
|
||||
CyberWarriorX
|
||||
mic
|
|
@ -1,12 +1,12 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
|
@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
|
|||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
|
@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
|
|||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
|
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
|
|||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
|
@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
|
|||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
|
@ -225,7 +225,7 @@ impose that choice.
|
|||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
|
@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
|
|||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
|
@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
|||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
|
@ -303,16 +303,17 @@ the "copyright" line and a pointer to where the full notice is found.
|
|||
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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
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
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
@ -335,5 +336,5 @@ necessary. Here is a sample; alter the names:
|
|||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,277 @@
|
|||
0.8 -> 0.9
|
||||
There have been so many changes that this list can hardly be considered complete.
|
||||
For this release, we have formatted the list into a high level overview of big changes and bad bugs relative to the previous release. Hopefully what you're interested in.
|
||||
This list does not include items which are solely performance boosts, for let us just say that virtually every system has been speeded up.
|
||||
|
||||
* The savestate system is totally changed and incompatible with old savestates.
|
||||
* The 3d system should be considered rewritten.
|
||||
|
||||
General/Core:
|
||||
enh: Convert to c++
|
||||
enh: Add functions for a lid open/close. Holding key (default "Backspace" in Windows port) while game is freeze/non freeze. [CrazyMax]
|
||||
enh: Add secure area decryption from ndstool [zeromus]
|
||||
enh: Change savestate code to support loosely bound chunks and more easily other parts of the emu (GE, GPU).
|
||||
The savestate format is changed, but from now on it is in principle more resilient
|
||||
(though it will continue to break as we tinker with the internals) [zeromus]
|
||||
enh: Added SSE2 optimizations for matrices. Since we now make an SSE2 build, more optimizations can be made. [CrazyMax]
|
||||
enh: Add a preliminary GUI hud system [CrazyMax,zeromus]
|
||||
|
||||
CPU/MMU:
|
||||
bug: Many fixes in IPC and GE FIFOs. Fixes freezes in NSMB, dsracing, and others. [CrazyMax,luigi__,shash]
|
||||
bug: Fix ARM instructions SBC and RSC (likewise SBC in thumb) [normatt]
|
||||
bug: Fixed Thumb LDMIA (fixes ingame Dead'n'Furious) [shash]
|
||||
bug: Fix repeating DMA (fixes NSMB parallax BG) [zeromus]
|
||||
bug: Proper handling for unaligned CPU accesses [luigi__]
|
||||
bug: Proper handling for undefined instruction exceptions [Salva Peiró]
|
||||
enh: Remove 16MB of WRAM at 0x01****** from arm9. Mapped to unused instead. Nobody knows what this was. [zeromus]
|
||||
enh: Changed instruction execution to 16 at a time blocks (tested and stable) [shash]
|
||||
|
||||
Hardware:
|
||||
bug: Newer and better sqrt and div emulation; makes SM64DS playable [luigi__,shash,zeromus]
|
||||
bug: Add preliminary RTC implementations [CrazyMax]
|
||||
enh: Add cosine interpolation in the SPU (conditionally compiled) [zeromus,luigi__]
|
||||
enh: Experimental: always one silent non-mixing SPU core at 44.1khz synched with emu, for more precision.
|
||||
The audible core runs with the host, causing music to slow down but not tear or pitch bend. [zeromus]
|
||||
|
||||
Graphics:
|
||||
- Overhaul 3d:
|
||||
. Move entire GE to core emu.
|
||||
. Move OpenGL renderer to emu core for optional use by platforms, removing ogl_collector. Now every platform shares the same 3d code.
|
||||
. Reorganize 3d code to defer rendering to after 3d vblank. Eliminates tearing, and texturing artifacts. [zeromus]
|
||||
. Move lighting model to software instead of using opengl's fixed function model [zeromus]
|
||||
. Render shadow volumes; toon shading and highlight table [zeromus, luigi__]
|
||||
. Added texture caching! big speed up. [CrazyMax]
|
||||
|
||||
bug: Many assorted tweaks and improvements to 3d and 2d precision [zeromus,CrazyMax,luigi__]
|
||||
bug: Fixes to GE: command unpacking, projection and pos-vector mode matrix handling, mult and load commands [zeromus]
|
||||
bug: Fix a bug in texture transformation mode 1 [zeromus]
|
||||
bug: Fixed GPU rendering bugs in sprites and BG [CrazyMax]
|
||||
bug: Fixes to texture conversion [CrazyMax,zeromus]
|
||||
bug: Fixes in capture display (no blinking in many games with dual 3D) [CrazyMax]
|
||||
bug: Fixes in master brightness (this fixes some games with black screens) [CrazyMax]
|
||||
bug: Fixes in screen, backdrop, and sprite blending [luigi__]
|
||||
bug: Changed clear depths and how depth initial values are calculated (fixes SM64DS skybox, Castlevania) [shash,lugi__]
|
||||
bug: Add 3d layer h-scrolling [zeromus]
|
||||
bug: Added transparency and fixed material alpha support and alpha testing on the 3D core [shash]
|
||||
bug: Rewrite VRAM mapping control and rendering (more accurate) [CrazyMax,luigi__]
|
||||
bug: convert colors to opengl better to prevent alpha=31 polys from being ever so slightly transparent [zeromus]
|
||||
enh: Add MMU->GPU signal for when vram mappings change to function as a texture cache invalidate signal [zeromus]
|
||||
enh: Make matrix 4x4 multiply routines use W-coordinate; carry w coord through pipeline [zeromus]
|
||||
|
||||
Mac OS X port:
|
||||
bug: Fixed: Filenames and paths with unicode characters now work. [Jeff]
|
||||
bug: Fixed: Load state from file button works again. [Jeff]
|
||||
enh: Save State panel now pauses emulation while the file selection box is open. [Jeff]
|
||||
bug: Fixed: Frozen video output (and/or messed 3d emulation) after loading a state. [Jeff]
|
||||
bug: Added option to load the most recent file upon launching the program. [Jeff]
|
||||
enh: Added French translation (thanks to Pierre Rudloff). [Jeff]
|
||||
enh: Added basic key mapping configuration to application preferences (thanks to Julio GorgŽ). [Jeff]
|
||||
enh: Added keyboard shortcuts for Execute, Pause and Reset command (thanks to Julio GorgŽ). [Jeff]
|
||||
enh: Default key mappings are no longer case sensitive. [Jeff]
|
||||
enh: Added ability to limit speed. [Jeff]
|
||||
enh: Fixed: Video output should work on software-only 3D renderers. [Jeff]
|
||||
|
||||
Windows port:
|
||||
bug: Fix a race condition in NDS_3D_Reset and NDS_glInit [zeromus]
|
||||
bug: Fix the buggy auto frameskip logic which made the emu slow to a crawl. Now it runs fast! [zeromus]
|
||||
bug: Fix resizing, rotate & aspect ration of main window. [CrazyMax,_zeromus]
|
||||
bug: Remove multithreading from user interface after finding several synchronization issues [zeromus]
|
||||
enh: recent roms menu [luigi_]
|
||||
enh: Changed graphics render core to DirectDraw (work faster) [CrazyMax]
|
||||
enh: Add an arm9 cpu load average calculator similar to no$. but I dont think it works right. [zeromus]
|
||||
enh: Rewrite all debug tools (autoupdate works now) [CrazyMax]
|
||||
enh: Rewrite input core & replace config input dialog [CrazyMax]
|
||||
enh: Add AVI output [zeromus]
|
||||
enh: Add pause toggle and frame advance hotkeys [adelikat]
|
||||
enh: Add frame counter display and hud messages framework [adelikat]
|
||||
enh: Main window remembers position, size, and a few other emu preferences [adelikat]
|
||||
enh: Removed directx sdk dependency for easier building. [zeromus]
|
||||
enh: Savestate doesnt unpause emu if it is already paused [adelikat]
|
||||
|
||||
0.7.3 -> 0.8
|
||||
Cocoa:
|
||||
- Save State As function now works. [Jeff B]
|
||||
- Recent Items menu now works. [Jeff B]
|
||||
- Opening NDS files from Finder now works. [Jeff B]
|
||||
- Added screenshot feature. [Jeff B]
|
||||
- Added preferences. [Jeff B]
|
||||
- Many more strings are translatable now. [Jeff B]
|
||||
- Default screen color is black (better represents being "off" and easier on eyes at night). [Jeff B]
|
||||
- Added sound. [Jeff B]
|
||||
- Now is a universal binary. [Jeff B]
|
||||
- Leopard resolution icon added. [Jeff B]
|
||||
- Added a Japanese translation. [Jeff B]
|
||||
- Added an optional status bar (resize handle no longer overlaps screen). [Jeff B]
|
||||
- New ROM Info and About DeSmuME windows have been added. [Jeff B]
|
||||
- Fixed several bugs in window resizing. [Jeff B]
|
||||
- Added FAT image support for homebrew games (thanks to TypeError). [Jeff B]
|
||||
- Key config can be changed on the command line. Save/load hotkeys changed (so expose doesn't override). [Jeff B]
|
||||
- Key bindings may work better on non-US keyboards now (needs testing). [Jeff B]
|
||||
general:
|
||||
- Encapsulate GDB debug stub to avoid certain problems [shash]
|
||||
- Fixed CPU LD*/ST* bugs [shash]
|
||||
- Fixed New SMB mini-games freeze [shash]
|
||||
- Fixed possible segfault in ROMReader on ia64 and amd64. [evilynux]
|
||||
- Fixed a crash bug with 2D background corrupting memory [shash]
|
||||
- Flag check optimization [carlo_bramini]
|
||||
- Applied some endian fixes in GPU (thanks to Phazz) [Jeff B]
|
||||
gtk-glade:
|
||||
- Added DeSmuME version in about dialog. [evilynux]
|
||||
- Updated website url in about dialog. [evilynux]
|
||||
- Added Brazilian Portuguese translation by Dreampeppers99. [evilynux]
|
||||
- Better desktop menu entry following FreeDesktop specifications. [evilynux]
|
||||
gtk:
|
||||
- Updated website url in about dialog. [evilynux]
|
||||
- Better desktop menu entry following FreeDesktop specifications. [evilynux]
|
||||
windows port:
|
||||
- Added an "about" box [shash]
|
||||
- DirectInput control interface with joystick support [CrazyMax]
|
||||
- Matrix and Light viewer [Acid Burn]
|
||||
|
||||
0.7.2 -> 0.7.3
|
||||
gtk-glade:
|
||||
- Full localization using intltool/gettext. [evilynux]
|
||||
general:
|
||||
- Added a README.TRANSLATION documenting the localization process. [evilynux]
|
||||
MacOS X:
|
||||
- Initial version of the Mac interface added. [Jeff B]
|
||||
|
||||
0.7.1 -> 0.7.2
|
||||
spu:
|
||||
- big endian fixes. [cyberwarriorx]
|
||||
gpu:
|
||||
- big endian fixes. [marcus_c]
|
||||
gtk-glade:
|
||||
- opengl improvements. [masscat]
|
||||
general:
|
||||
- Added support for setting NDS firmware language value. [masscat]
|
||||
- Function added for setting firmware language. [masscat]
|
||||
- Mac/msys compilation fixes. [cyberwarriorx]
|
||||
- Fix compilation when pkg-config macros are not available [evilynux]
|
||||
|
||||
0.7.0 -> 0.7.1
|
||||
general:
|
||||
- Added GDB debugger stub [masscat]
|
||||
- Added new/different GBAMP CFlash image reader/writer [masscat]
|
||||
gpu:
|
||||
- Major speedup to the 2D core [shash]
|
||||
gtk-glade:
|
||||
- Added command line options. [masscat]
|
||||
- Added FPS limiter [masscat]
|
||||
cli:
|
||||
- Added command line options. [masscat]
|
||||
- Added FPS limiter [masscat]
|
||||
- Added option to use OpenGl to render window (allows resizing). [masscat]
|
||||
windows port:
|
||||
- Added command line options. [masscat]
|
||||
- Added multiple language support [cyberwarriorx]
|
||||
- Added Danish language translation [thomas-2007]
|
||||
|
||||
0.6.0 -> 0.7.0
|
||||
general:
|
||||
- Added support for *.duc files [cyberwarriorx]
|
||||
gpu:
|
||||
- Added support for sprite rotation/scaling [shash]
|
||||
- Added support for the 3D core (openGL and null plugins) [shash]
|
||||
windows port:
|
||||
- A bunch of fixes [Dmitry Krutskih]
|
||||
- Fixed a bug in sound that was causing it to still not work for some
|
||||
people [cyberwarriorx]
|
||||
gtk:
|
||||
- Added 3D emulation
|
||||
- Added command line options.
|
||||
- Added option to use OpenGL to render window (allows resizing).
|
||||
gtk-glade:
|
||||
- Added 3D emulation
|
||||
|
||||
0.5.0 -> 0.6.0
|
||||
general:
|
||||
- Added zipped (based on zziplib) and gzipped (based on zlib) rom support.
|
||||
arm:
|
||||
- Added relocation interrupt vector.
|
||||
- Added region access right checks.
|
||||
- Enabled LDC/STC instructions.
|
||||
- Fixed powersave (cp15) IRQ wait.
|
||||
- Fixed MOV instructions
|
||||
gpu:
|
||||
- Added special color effects.
|
||||
- Added windowing feature.
|
||||
- Fixed transparent direct color backgrounds.
|
||||
- Fixed disabled sprites showing.
|
||||
- Fixed 8/32 bit access to gpu registers.
|
||||
- Fixed missing backgrounds
|
||||
- Support for master brightness
|
||||
wifi:
|
||||
- Added RF chip interface.
|
||||
- Added BB chip interface.
|
||||
windows port:
|
||||
- Fixed address calculation in disassembler.
|
||||
- Added Force Maintain Ratio option for window stretching
|
||||
linux port (cli, gtk and gtk-glade):
|
||||
all:
|
||||
- Added joystick support.
|
||||
- Fixed X and Y buttons.
|
||||
gtk-glade:
|
||||
- Added joystick configuration.
|
||||
- Improved I/O registers viewer tool.
|
||||
- Added save and load states support.
|
||||
|
||||
0.3.3 -> 0.5.0
|
||||
arm:
|
||||
- Fixed MSR with immediate value opcode.
|
||||
- Fixed LSR_0 thumb opcode (C flag is correctly set now).
|
||||
- Fixed LDR*/STR* opcodes.
|
||||
- Fixed unaligned memory access on THUMB Core.
|
||||
- Added relocating SWI routines.
|
||||
bios:
|
||||
- Added decompression functions.
|
||||
- Added GetPitchTable function.
|
||||
- Added GetVolumeTable function.
|
||||
- Added GetCRC16 function.
|
||||
- Added experimental SoundBias function.
|
||||
- Added GetSineTable function.
|
||||
cart:
|
||||
- Added CompactFlash/FAT emulation.
|
||||
- Added Get ROM chip ID Cartridge command.
|
||||
gpu:
|
||||
- Added framebuffer emulation.
|
||||
- Fixed a bug in GPU (xfin could be greater than LG causing a segfault).
|
||||
- Added support for Display Mode 0(Display Off).
|
||||
- Added the basic framework for Display Mode 3(Display from Main RAM).
|
||||
spu:
|
||||
- Added sound emulation.
|
||||
- Added sound core system.
|
||||
- Added WAV write core.
|
||||
- Added dummy core.
|
||||
- Added Direct Sound core.
|
||||
linux port:
|
||||
- Added GTK+ GUI.
|
||||
- Added command line interface.
|
||||
- Added stylus and arm9 keypad support in CLI version.
|
||||
- Added FPS display.
|
||||
- Added basic frameskip.
|
||||
windows port:
|
||||
- Fixed a bug when displaying a ROM's information.
|
||||
- Added key configuration.
|
||||
- Removed the debug key.
|
||||
- Added new experimental auto frameskip/frame limit code.
|
||||
- Added sound settings dialog.
|
||||
- Added a few menu options for accessing the website, forums, and for
|
||||
submitting bugs.
|
||||
general:
|
||||
- Rewrote code in C.
|
||||
- Fixed warnings.
|
||||
- Used defines and typedef's to make things more portable and easier to
|
||||
read.
|
||||
- Added autotools stuff.
|
||||
- Changes to logging system.
|
||||
- Added screenshot function.
|
||||
- Translated most french to english.
|
||||
- Added savestate support.
|
||||
- Added firmware reading support(needs work).
|
||||
- Added Backup Memory support with autodetection.
|
||||
- Fixed some endianess issues.
|
||||
- Fixed things so Visual C++ can compile code.
|
||||
- Added bsd support.
|
||||
- Reworked ROM loading so you can load a different rom without any problems.
|
||||
- Finished NDS_Reset. Now the emulation can be reset even while running.
|
|
@ -0,0 +1,237 @@
|
|||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||
2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
Briefly, the shell commands `./configure; make; make install' should
|
||||
configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
instructions specific to this package.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||
you want to change it or regenerate `configure' using a newer version
|
||||
of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system.
|
||||
|
||||
Running `configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
6. Often, you can also type `make uninstall' to remove the installed
|
||||
files again.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that the
|
||||
`configure' script does not know about. Run `./configure --help' for
|
||||
details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
With a non-GNU `make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use `make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out automatically,
|
||||
but needs to determine by the type of machine the package will run on.
|
||||
Usually, assuming the package is built to be run on the _same_
|
||||
architectures, `configure' can figure that out, but if it prints a
|
||||
message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share, you
|
||||
can create a site shell script called `config.site' that gives default
|
||||
values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
EXTRA_DIST = README.LIN README.MAC README.WIN README.TRANSLATION autogen.sh \
|
||||
$(PO_FILES_IN)
|
||||
DISTCLEANFILES = $(PO_FILES)
|
||||
SUBDIRS = $(PO_DIR) src
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
DeSmuME
|
||||
_________________________________________
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2007 DeSmuME team
|
||||
|
||||
|
||||
1) Introduction.............................................13
|
||||
2) Staff/Thanks.............................................36
|
||||
3) Contact information......................................72
|
||||
4) Disclaimer...............................................82
|
||||
|
||||
|
||||
1 Introduction________________________________________________
|
||||
|
||||
DeSmuME is a Nintendo DS emulator under GNU GPL.
|
||||
|
||||
DeSmuME can boot homebrew and games, some of which are
|
||||
playable.
|
||||
|
||||
For installation/how to use informations, check the ports
|
||||
specific README files:
|
||||
|
||||
* README.LIN for the linux port
|
||||
* README.WIN for the windows port
|
||||
* README.MAC for the mac port
|
||||
|
||||
|
||||
2 Staff/Thanks________________________________________________
|
||||
|
||||
See the AUTHORS file for team members list.
|
||||
|
||||
Thanks to:
|
||||
|
||||
* yopyop (original author of DeSMUME),
|
||||
for releasing the source code of this great emulator.
|
||||
|
||||
* Martin Korth (author of GBATEK),
|
||||
for his well-written Gameboy Advance and Nintendo DS
|
||||
documentation.
|
||||
|
||||
|
||||
3 Contact information_________________________________________
|
||||
|
||||
E-mail: guillaume.duhamel@gmail.com
|
||||
Web: http://desmume.org
|
||||
IRC: irc://irc.freenode.net/desmume
|
||||
|
||||
Please don't ask for roms, bios files or any other
|
||||
copyrighted stuff.
|
||||
|
||||
|
||||
4 Disclaimer__________________________________________________
|
||||
|
||||
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
|
||||
|
||||
See the GNU General Public License details in COPYING.
|
|
@ -0,0 +1,177 @@
|
|||
DeSmuME
|
||||
_________________________________________
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2007 DeSmuME team
|
||||
|
||||
|
||||
1) Compiling instructions...................................13
|
||||
2) How to use DeSmuME.......................................53
|
||||
3) Contact information......................................142
|
||||
4) Disclaimer...............................................160
|
||||
|
||||
|
||||
1 Compiling instructions______________________________________
|
||||
|
||||
DeSmuME is written in C using the gtk+ and SDL libraries.
|
||||
So you need a working C compiler, such as gcc and
|
||||
the above libraries runtime and development packages:
|
||||
|
||||
* http://www.gtk.org
|
||||
|
||||
* http://www.libsdl.org/
|
||||
|
||||
Once these libraries are installed, you should be ready to
|
||||
install DeSmuME.
|
||||
|
||||
DeSmuME provides another interface based on libglade, to use
|
||||
it, you'll need glade:
|
||||
|
||||
* http://glade.gnome.org/
|
||||
|
||||
1.1 From a release archive____________________________________
|
||||
|
||||
Uncompress the DeSmuME archive, move to the newly created
|
||||
directory, type "./configure", then "make".
|
||||
It will generate three programs:
|
||||
1) "desmume" in the "src/gtk" directory;
|
||||
2) "desmume-cli" in the "src/cli" directory.
|
||||
If glade is installed on your system, you'll get a third
|
||||
binary:
|
||||
3) "desmume-glade" in the "src/gtk-glade" directory.
|
||||
|
||||
You can even type "make install" to install those programs on
|
||||
your system (in /usr/local/ by default), then uninstalling is
|
||||
done by typing "make uninstall".
|
||||
|
||||
1.2 From a CVS copy___________________________________________
|
||||
|
||||
Move to the toplevel directory (the one that contains the
|
||||
configure.ac file). Type "./autogen.sh" to generate the
|
||||
configure/install scripts and needed Makefiles. Then you can follow the
|
||||
same procedure as in 1.1 .
|
||||
|
||||
2 How to use DeSmuME__________________________________________
|
||||
|
||||
There are three versions of DeSmuME under Linux. These are a
|
||||
Gtk+ build, a Glade build and a CLI SDL build. All these builds
|
||||
have some common command line options:
|
||||
|
||||
--disable-limiter Disables the 60 fps limiter
|
||||
--soft-convert Use software colour conversion during OpenGL
|
||||
screen rendering. May produce better or worse
|
||||
frame rates depending on hardware.
|
||||
|
||||
--arm9gdb=PORT_NUM Enable the ARM9 GDB stub on the given port
|
||||
--arm7gdb=PORT_NUM Enable the ARM7 GDB stub on the given port
|
||||
|
||||
--cflash=PATH_TO_DISK_IMAGE
|
||||
Enable disk image GBAMP compact flash emulation
|
||||
|
||||
--help Display this message
|
||||
|
||||
|
||||
NOTE:
|
||||
The Gtk+ and Glade builds use gtkGLext to handle the OpenGL
|
||||
rendering and contexts. You may get improved performance by
|
||||
also passing the argument --gdk-gl-force-indirect. This has
|
||||
been seen to improve things for Nvidia based graphics cards
|
||||
under Linux.
|
||||
|
||||
|
||||
GDB Debugger Stubs:
|
||||
Source level debugging of ARM9 and/or ARM7 code is supported
|
||||
using a GDB/Insight debugger.
|
||||
The GDB stubs are enabled from the command line using the
|
||||
following options:
|
||||
|
||||
--arm9gdb=<PORT_NUM> (for the ARM9)
|
||||
--arm7gdb=<PORT_NUM> (for the ARM7)
|
||||
|
||||
The PORT_NUM is the TCP port upon which the stub will listen for
|
||||
connections. Once enabled you can connect to the stub using the
|
||||
following command at the GDB debugger prompt (assuming GDB and
|
||||
DeSmuME are running on the same machine):
|
||||
|
||||
target remote :<PORT_NUM>
|
||||
|
||||
NOTE: there are problems with the ARM support when stepping code
|
||||
with GDB versions prior to version 6.6. It is recommended that
|
||||
you use at least version 6.6 if possible.
|
||||
|
||||
|
||||
GBAMP compact flash emulation:
|
||||
|
||||
The default behaviour of DeSmumME is to attempt to emulate the
|
||||
FAT image for the contents of the directory where the running
|
||||
.nds file was located.
|
||||
This behaviour can be altered using the
|
||||
--cflash=<DISK_IMAGE_FILE> command line option. Using this
|
||||
option DeSmuME will emulation a GBAMP and read and write sectors
|
||||
from/to the disk image file.
|
||||
The disk image file must be created and populated with files
|
||||
using some external tool.
|
||||
NOTE: currently if desmume fails to open the disk image file it
|
||||
will silently continue minus a working GBAMP emulation.
|
||||
|
||||
|
||||
2.1 Gtk+ version______________________________________________
|
||||
|
||||
Type "desmume" in a shell, a window should appear, then open
|
||||
a rom file using the "open" button, next use the "run" button
|
||||
to start emulation.
|
||||
|
||||
The following command line options are specific to the Gtk+
|
||||
build:
|
||||
|
||||
--opengl-2d Enables using OpenGL for screen rendering
|
||||
--disable-sound Disables the sound emulation
|
||||
--disable-3d Disables the 3D emulation
|
||||
|
||||
|
||||
2.2 CLI SDL version_______________________________________________
|
||||
|
||||
Just type "desmume-cli path-to-a-rom" in a shell.
|
||||
|
||||
The following command line options are specific to the CLI
|
||||
build:
|
||||
|
||||
--opengl-2d Enables using OpenGL for screen rendering
|
||||
--disable-sound Disables the sound emulation
|
||||
|
||||
|
||||
3 Contact information_________________________________________
|
||||
|
||||
General inquiries should go to:
|
||||
E-mail: guillaume@desmume.org
|
||||
|
||||
Linux Port-related inquiries should go to:
|
||||
E-mail: guillaume@desmume.org
|
||||
|
||||
Web: http://desmume.org
|
||||
|
||||
Please don't ask for roms, bios files or any other copyrighted
|
||||
stuff.
|
||||
|
||||
If you want to submit a bug report, please run desmume, go into
|
||||
the "Help" menu, and click on "Submit a bug report". If you're
|
||||
having trouble with it, please feel free to email.
|
||||
|
||||
|
||||
4 Disclaimer__________________________________________________
|
||||
|
||||
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
|
||||
|
||||
See the GNU General Public License details in COPYING.
|
|
@ -0,0 +1,107 @@
|
|||
DeSmuME
|
||||
_________________________________________
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2007 DeSmuME team
|
||||
|
||||
|
||||
1) Compiling instructions...................................13
|
||||
2) How to use DeSmuME.......................................31
|
||||
3) Contact information......................................73
|
||||
4) Disclaimer...............................................90
|
||||
|
||||
|
||||
1 Compiling instructions______________________________________
|
||||
|
||||
DeSmuME is written in C, and the Cocoa interface was written
|
||||
in Objective-C. It uses the Cocoa, OpenGL, and [optionally]
|
||||
the zlib library.
|
||||
|
||||
So you need a working C and Objective-C compiler, such as
|
||||
GCC for Mac OS X.
|
||||
|
||||
* Cocoa and OpenGL come standard with Mac OS X
|
||||
|
||||
* zlib can be found at http://www.zlib.net, and may
|
||||
also come with Mac OS X.
|
||||
|
||||
DeSmuME for Mac OS X can be compiled using the XCode IDE
|
||||
or the CodeBlocks IDE. Project files are available in the
|
||||
Cocoa source folder.
|
||||
|
||||
2 How to use DeSmuME__________________________________________
|
||||
|
||||
To install DeSmuME, copy DeSmuME.app into the folder of your
|
||||
choice (Applications folder is recommended). You can also drag
|
||||
it to your dock for quicker launching.
|
||||
|
||||
Double click the application to launch DeSmuME.
|
||||
|
||||
Most options can be found in the menu bar a the top of the
|
||||
screen. On Leopard, you can use the search box under the help
|
||||
menu to find things.
|
||||
|
||||
DeSmuME for Mac OS X does not support all the features of the
|
||||
Linux and Windows versions.
|
||||
|
||||
Click the lower screen for DS touch-screen input.
|
||||
|
||||
Key mappings can be changed or viewed from the preferences
|
||||
panel. Here are the defaults (may be subject to change):
|
||||
up arrow - Up
|
||||
left arrow - Left
|
||||
down arrow - Down
|
||||
right arrow - Right
|
||||
v - A button
|
||||
b - B button
|
||||
g - X button
|
||||
h - Y button
|
||||
c - Left Trigger
|
||||
n - Right Trigger
|
||||
enter - Start button
|
||||
space - Select button
|
||||
|
||||
States can be saved with shift + number keys.
|
||||
States can be loaded with the number keys.
|
||||
|
||||
To set up a FAT disk image (for homebrew apps) you can use the
|
||||
"Emulation > Set FAT Image File" option in the menu. You can
|
||||
also set this from the command line by launching DeSmuME
|
||||
inside its app bundle:
|
||||
|
||||
DeSmuME.app/Contents/MacOS/DeSmuME -FlashFile /path/to/file.img
|
||||
|
||||
3 Contact information_________________________________________
|
||||
|
||||
General inquiries should go to:
|
||||
E-mail: guillaume.duhamel@gmail.com
|
||||
|
||||
Mac OS X Port-related inquiries should go to:
|
||||
E-mail: osx@desmume.org
|
||||
|
||||
Web: http://desmume.org
|
||||
|
||||
Please don't ask for roms, bios files or any other copyrighted
|
||||
stuff.
|
||||
|
||||
If you want to submit a bug report, please run desmume, go
|
||||
into the "Help" menu, and click on "Submit a bug report". If
|
||||
you're having trouble with it, please feel free to email.
|
||||
|
||||
4 Disclaimer__________________________________________________
|
||||
|
||||
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
|
||||
|
||||
See the GNU General Public License details in COPYING.
|
|
@ -0,0 +1,169 @@
|
|||
__________________________ Localization of DeSmuME _____________________________
|
||||
|
||||
Users and translators:
|
||||
1) Supported UIs
|
||||
2) Starting a new translation
|
||||
3) Editors
|
||||
4) Contact Us
|
||||
|
||||
Developpers:
|
||||
5) Creating translation friendly strings (gtk-glade)
|
||||
6) Updating the template (gtk-glade)
|
||||
7) Integrating new translations
|
||||
|
||||
|
||||
1 Supported UIs ________________________________________________________________
|
||||
|
||||
Although there are 4 UIs, only 3 currently support localization:
|
||||
windows, gtk-glade, and Cocoa (Mac OS X).
|
||||
|
||||
To translate DeSmuME, see "Starting a new translation" below.
|
||||
|
||||
If you have created a new translation, or improved an existing one, please
|
||||
send us your translation by getting in touch with us: see "Contact Us" below.
|
||||
|
||||
1.1 gtk-glade UI _____________________________________________________________
|
||||
|
||||
Localization is done with gettext. gettext uses po files.
|
||||
The po files are located in the po/ folder.
|
||||
Note that there is one po file per language.
|
||||
|
||||
To use the available translations, set up your environment properly.
|
||||
e.g. under GNU/Linux you can verify that the value of your LANG variable.
|
||||
|
||||
1.2 Windows UI ______________________________________________________________
|
||||
|
||||
Localization is located in one single file: src/windows/resources.rc .
|
||||
|
||||
1.3 Mac OS X (Cocoa) UI _____________________________________________________
|
||||
|
||||
Localization files are located within the application bundle (in Finder right
|
||||
click on DeSmuME and select "Show Package Contents"). Within the
|
||||
Contents/Resources folder there is a folder for each localization.
|
||||
|
||||
2 Starting a new translation ___________________________________________________
|
||||
|
||||
2.1 gtk-glade UI _____________________________________________________________
|
||||
|
||||
Grab a copy of po/desmume.pot and rename it.
|
||||
You can use the two letter iso code of the language as the filename
|
||||
e.g. fr.po
|
||||
or you can specify the country code as well
|
||||
e.g. fr_CA.po
|
||||
|
||||
Open the newly created file with an editor: see "Editors" below.
|
||||
Translate the strings.
|
||||
|
||||
2.2 Windows UI _______________________________________________________________
|
||||
|
||||
Grab a copy of src/windows/resources.rc .
|
||||
Create a section for your language by looking at another language e.g. french.
|
||||
Translate the strings.
|
||||
|
||||
2.3 Max OS X (Cocoa) UI ______________________________________________________
|
||||
|
||||
Copy and paste one of the localization folders mentioned in 1.3.
|
||||
Rename the part before ".lproj" to the language of the translation.
|
||||
Within your newly created folder edit "Localizable.strings".
|
||||
|
||||
The MainMenu.nib opaque folder also contains localization of the Application
|
||||
menu, however since this is a standard menu in Mac OS X, for most languages
|
||||
standard strings can be generated by Apple's Interface Builder.
|
||||
|
||||
The strings file should stay in UTF-16 encoding (UTF-8 or others may work,
|
||||
but UTF-16 is preferred).
|
||||
|
||||
If your strings file has an error, no translated strings will show in DeSmuME.
|
||||
|
||||
Debugging the string file:
|
||||
If you have Mac OS X developer tools installed, from the console you can type
|
||||
"plutil FILE", replacing FILE with the name and path of the string file, and
|
||||
it will tell you if there are any errors (and on what line).
|
||||
|
||||
3 Editors ______________________________________________________________________
|
||||
|
||||
You can use plain text editors but there are many po file editors.
|
||||
Here are some recommanded po editors, in no particular order.
|
||||
|
||||
3.1 GNU/Linux ________________________________________________________________
|
||||
|
||||
- gtranslator: http://gtranslator.sourceforge.net/
|
||||
- KBabel: http://kbabel.kde.org/
|
||||
|
||||
3.2 OSX ______________________________________________________________________
|
||||
|
||||
- LocFactory Editor:
|
||||
http://www.triplespin.com/en/products/locfactoryeditor.html
|
||||
|
||||
3.3 All platforms ____________________________________________________________
|
||||
|
||||
- poEdit: http://www.poedit.net/
|
||||
- OmegaT: http://www.omegat.org/omegat/omegat.html
|
||||
- GNUEmacs/XEmacs/AquaEmacs with po-mode
|
||||
- Vim with PO ftplugin
|
||||
- Eclipse with gted
|
||||
|
||||
|
||||
4 Contact Us ___________________________________________________________________
|
||||
|
||||
As there isn't many translations so far, we're still asking you to get in touch
|
||||
via the forum located at http://forums.desmume.org/ .
|
||||
|
||||
You can upload your translation files to your favorite sharing site and paste
|
||||
the link in a post under General.
|
||||
|
||||
|
||||
5 Creating translation friendly strings (gtk-glade) ____________________________
|
||||
|
||||
5.1 In the code ______________________________________________________________
|
||||
|
||||
Make sure libintl.h is included and that _() is defined.
|
||||
e.g. see src/gtk-glade/globals.h
|
||||
Add the filename to po/POTFILES.in if it's not already there.
|
||||
|
||||
Where you would use "my text", use _("my text").
|
||||
For long strings, for translators' sanity, please do something like:
|
||||
|
||||
printf( _(" This is a\n\
|
||||
very long text\n") );
|
||||
|
||||
5.2 Glade interface __________________________________________________________
|
||||
|
||||
You have nothing special to do aside from adding the filename to
|
||||
po/POTFILES.in.
|
||||
|
||||
|
||||
6 Updating the template (gtk-glade) ____________________________________________
|
||||
|
||||
To update po/desmume.pot, move to the po/ folder and execute "make update-po".
|
||||
|
||||
|
||||
7 Integrating new translations
|
||||
|
||||
7.1 gtk-glade UI _____________________________________________________________
|
||||
|
||||
Add the new po file to po/ .
|
||||
Add the new language to ALL_LINGUAS in configure.ac .
|
||||
Regenerated the build files (./autogen.sh) and rebuild (./configure && make).
|
||||
You can also add the language to po/LINGUAS (it's a convention? it has no effect).
|
||||
|
||||
7.2 Windows UI _______________________________________________________________
|
||||
|
||||
Update the src/windows/resource.rc .
|
||||
Add the new language to to the list in src/windows/resource.h .
|
||||
Rebuild.
|
||||
|
||||
7.3 Max OS X (Cocoa) UI ______________________________________________________________
|
||||
|
||||
After following the steps in 2.3, your translation is ready to go.
|
||||
You can set the DeSmuME language one of three ways:
|
||||
|
||||
1) Set the system language (System Preferences -> International).
|
||||
|
||||
2) Right click on DeSmuME in Finder, select Get Info and disable the other translations.
|
||||
|
||||
3) From a command line, run the following line after replacing LANG with the language:
|
||||
|
||||
DeSmuME.app/Contents/MacOS/DeSmuME -AppleLanguages '<array><string>LANG</string></array>'
|
||||
|
||||
All of these methods require a restart of DeSmuME.
|
|
@ -0,0 +1,201 @@
|
|||
DeSmuME
|
||||
_________________________________________
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2007 DeSmuME team
|
||||
|
||||
|
||||
1) Compiling instructions...................................13
|
||||
2) How to use DeSmuME.......................................51
|
||||
3) Contact information.....................................166
|
||||
4) Disclaimer..............................................184
|
||||
|
||||
|
||||
1 Compiling instructions______________________________________
|
||||
|
||||
DeSmuME is written in C, using the DirectX 8.0, OpenGL, zlib,
|
||||
zziplib libraries, so you need a working C compiler(such as
|
||||
mingw). Other supported compilers include Visual C++ 2005 and
|
||||
dev-cpp.
|
||||
|
||||
* You can find DirectX headers and libraries(for mingw) at
|
||||
http://alleg.sourceforge.net/wip.html as the file
|
||||
"dx80_mgw.zip". The actual runtime libraries(or
|
||||
headers/libraries for MSVC) can be gotten from
|
||||
http://www.microsoft.com/DirectX
|
||||
|
||||
* OpenGL should be included with your compiler, if it isn't,
|
||||
check on your compiler's website for links.
|
||||
|
||||
* zlib can be found at http://www.zlib.net
|
||||
|
||||
* zziplib can be found at http://zziplib.sourceforge.net
|
||||
|
||||
mingw:
|
||||
All you have to do now is go into your mingw shell
|
||||
environment, go into the directory where you extracted DeSmuME,
|
||||
and type: "./configure". Once that's done(and there was no
|
||||
errors), type: "make". It should now take some time to compile so
|
||||
go grab yourself a sandwich or beer - whatever suits your fancy
|
||||
and it should be done in a few minutes. Now all you have to do is
|
||||
type "./src/desmume" in order to run it.
|
||||
|
||||
dev-cpp:
|
||||
Load the project file DeSmuME.dev in the src/windows directory,
|
||||
compile, and you're set.
|
||||
|
||||
Visual C++:
|
||||
Load the project file DeSmuME.vcproj in the src/windows directory,
|
||||
compile, and you're set.
|
||||
|
||||
|
||||
2 How to use DeSmuME__________________________________________
|
||||
|
||||
Execute "desmume". A new window should pop up. The default
|
||||
settings should be fine for most people, but in case you need to
|
||||
adjust them, here's a brief explanation:
|
||||
|
||||
Under the "Config", there are a number of items:
|
||||
|
||||
Save Type:
|
||||
Here you can select which type of Backup Memory DeSmuME should
|
||||
emulate. By default, Autodetect works fine, but in some cases
|
||||
DeSmuME doesn't correctly detect the Backup Memory. In that
|
||||
case, you will want to select the correct one.
|
||||
|
||||
Control Config:
|
||||
Here you can change the default key mappings. For now only the
|
||||
keyboard is supported, but in the near future gamepads and
|
||||
joysticks will be supported.
|
||||
|
||||
Here are the default key mappings(they may be subject to change):
|
||||
Up arrow - Up
|
||||
Left arrow - Left
|
||||
Down arrow - Down
|
||||
right arrow - Right
|
||||
v - A button
|
||||
b - B button
|
||||
g - X button
|
||||
h - Y button
|
||||
c - Left Trigger
|
||||
n - Right Trigger
|
||||
enter - Start button
|
||||
space - Select button
|
||||
|
||||
Sound Settings:
|
||||
Here you can change the default sound settings. By default
|
||||
DeSmuME uses Direct Sound, a buffer size of 2940, and
|
||||
volume set to max. But if you want to mute the sound, you can
|
||||
set the sound core to none. Or if you want to save the sound
|
||||
to a file, you can set the sound core to WAV write. If you find
|
||||
the sound is crackling a lot, try increasing the buffer size. On
|
||||
the other hand, if you find the sound somewhat delayed or jumpy,
|
||||
try decreasing the buffer size.
|
||||
|
||||
Frame Skip:
|
||||
Here you can adjust the amount of frame draws to skip during
|
||||
emulation. Normally the emulator detects whether the emulator
|
||||
is running too fast or slow and skips a frame or more if it
|
||||
needs to speed things up. However some people don't like the
|
||||
results of it, so here you can adjust that.
|
||||
|
||||
After all the settings are set to your satisfaction, you can then
|
||||
load a ROM image by going into the "File" menu, and choosing
|
||||
"Open". Select which file you'd like to open, and the emulator
|
||||
will automatically load and start running the selected ROM.
|
||||
|
||||
You can save the current emulation state by press shift + one of
|
||||
the twelve F keys. To load, just press one of the twelve F keys
|
||||
(without shift pressed).
|
||||
|
||||
Under the View menu there's also a few additional options you may
|
||||
wish to change.
|
||||
|
||||
Rotation:
|
||||
Here you can adjust which angle of the display. Some programs
|
||||
require that you normally turn the DS on its side. You can set it
|
||||
up in that manner using this.
|
||||
|
||||
Magnify/DeMagnify:
|
||||
With these options you can increase or decrease the window size.
|
||||
|
||||
Note: You can also adjust the window size by clicking on the edge
|
||||
of the window, and dragging the mouse.
|
||||
|
||||
Force Maintain Ratio:
|
||||
Sometimes when the window size is changed it's doesn't look
|
||||
correct on the screen. This option forces the window to maintain
|
||||
a correct ratio so it looks correct.
|
||||
|
||||
|
||||
GDB Debugger Stubs:
|
||||
Source level debugging of ARM9 and/or ARM7 code is supported
|
||||
using a GDB/Insight debugger.
|
||||
The GDB stubs are enabled from the command line using the
|
||||
following options:
|
||||
|
||||
--arm9gdb=<PORT_NUM> (for the ARM9)
|
||||
--arm7gdb=<PORT_NUM> (for the ARM7)
|
||||
|
||||
The PORT_NUM is the TCP port upon which the stub will listen for
|
||||
connections. Once enabled you can connect to the stub using the
|
||||
following command at the GDB debugger prompt (assuming GDB and
|
||||
DeSmuME are running on the same machine):
|
||||
|
||||
target remote :<PORT_NUM>
|
||||
|
||||
NOTE: there are problems with the ARM support when stepping code
|
||||
with GDB versions prior to version 6.6. It is recommended that
|
||||
you use at least version 6.6 if possible.
|
||||
|
||||
|
||||
GBAMP compact flash emulation:
|
||||
|
||||
The default behaviour of DeSmumME is to attempt to emulate the
|
||||
FAT image for the contents of the directory where the running
|
||||
.nds file was located.
|
||||
This behaviour can be altered using the
|
||||
--cflash=<DISK_IMAGE_FILE> command line option. Using this
|
||||
option DeSmuME will emulation a GBAMP and read and write sectors
|
||||
from/to the disk image file.
|
||||
The disk image file must be created and populated with files
|
||||
using some external tool.
|
||||
NOTE: currently if desmume fails to open the disk image file it
|
||||
will silently continue minus a working GBAMP emulation.
|
||||
|
||||
|
||||
3 Contact information_________________________________________
|
||||
|
||||
General inquiries should go to:
|
||||
E-mail: guillaume@desmume.org
|
||||
|
||||
Windows Port-related inquiries should go to:
|
||||
E-mail:
|
||||
|
||||
Web: http://desmume.org
|
||||
|
||||
Please don't ask for roms, bios files or any other copyrighted
|
||||
stuff.
|
||||
|
||||
If you want to submit a bug report, please run desmume, go into
|
||||
the "Help" menu, and click on "Submit a bug report". If you're
|
||||
having trouble with it, please feel free to email.
|
||||
|
||||
|
||||
4 Disclaimer__________________________________________________
|
||||
|
||||
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
|
||||
|
||||
See the GNU General Public License details in COPYING.
|
|
@ -1,6 +0,0 @@
|
|||
# DeSmuME
|
||||
[](https://ci.appveyor.com/project/zeromus/desmume)
|
||||
|
||||
DeSmuME is a Nintendo DS emulator.
|
||||
|
||||
http://desmume.org/download
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/sh
|
||||
# intltoolize is optionnal as it's only required for the gtk-glade UI.
|
||||
|
||||
if test ! "x$(which intltoolize)" = "x"; then
|
||||
echo "Running intltoolize"
|
||||
intltoolize --copy --force --automake
|
||||
else
|
||||
if test ! "x$(which gintltoolize)" = "x"; then
|
||||
echo "Running gintltoolize"
|
||||
gintltoolize --copy --force --automake
|
||||
fi
|
||||
fi
|
||||
|
||||
autoreconf --install --force --verbose
|
|
@ -0,0 +1,39 @@
|
|||
# -*-shell-script-*-
|
||||
|
||||
[Meta]
|
||||
RootName: @desmume.sf.net/desmume:$SOFTWAREVERSION
|
||||
DisplayName: DeSmuME Nintendo DS Emulator
|
||||
ShortName: desmume
|
||||
Maintainer: Guillaume Duhamel <guillaume.duhamel@gmail.com>
|
||||
Packager: Guillaume Duhamel <guillaume.duhamel@gmail.com>
|
||||
Summary: DeSmuME is a Nintendo DS emulator.
|
||||
URL: http://desmume.sf.net/
|
||||
License: GNU General Public License, Version 2
|
||||
SoftwareVersion: @VERSION@
|
||||
AutopackageTarget: 1.0
|
||||
|
||||
[Description]
|
||||
This is a Nintendo DS emulator.
|
||||
|
||||
[BuildPrepare]
|
||||
prepareBuild
|
||||
|
||||
[BuildUnprepare]
|
||||
unprepareBuild
|
||||
|
||||
[Imports]
|
||||
echo '*' | import
|
||||
|
||||
[Prepare]
|
||||
# Dependency checking
|
||||
require @gtk.org/gtk 2.4
|
||||
|
||||
[Install]
|
||||
# Put your installation script here
|
||||
installExe bin/desmume
|
||||
installExe bin/desmume-cli
|
||||
installExe bin/desmume-glade
|
||||
|
||||
[Uninstall]
|
||||
# Usually just the following line is enough to uninstall everything
|
||||
uninstallFromLog
|
|
@ -0,0 +1,142 @@
|
|||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand `-c -o'.
|
||||
|
||||
scriptversion=2005-05-14.22
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand `-c -o'.
|
||||
Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file `INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
eat=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as `compile cc -o foo foo.c'.
|
||||
# So we strip `-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no `-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# `.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use `[/.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
|
@ -0,0 +1,246 @@
|
|||
dnl --- Package name is first argument to AC_INIT
|
||||
dnl --- Release version is second argument to AC_INIT
|
||||
|
||||
AC_INIT(desmume, [0.9])
|
||||
|
||||
dnl -- find target architecture for some os specific libraries
|
||||
AC_CANONICAL_TARGET
|
||||
case $target in
|
||||
*linux*) desmume_arch=linux;;
|
||||
*mingw*) desmume_arch=windows;;
|
||||
*darwin*) desmume_arch=linux;;
|
||||
*bsd*) desmume_arch=linux;;
|
||||
esac
|
||||
AC_SUBST(desmume_arch)
|
||||
|
||||
AM_INIT_AUTOMAKE
|
||||
|
||||
dnl -- make sure we have a C compiler
|
||||
AC_PROG_CC
|
||||
|
||||
dnl -- make sure we have a c++ compiler
|
||||
AC_PROG_CXX
|
||||
|
||||
dnl -- use ranlib for libraries
|
||||
AC_PROG_RANLIB
|
||||
|
||||
dnl -- check for endianess
|
||||
AC_C_BIGENDIAN
|
||||
|
||||
dnl --- Other prerequisites ---
|
||||
dnl - Check for pkg-config macros
|
||||
m4_ifdef([PKG_PROG_PKG_CONFIG], [PKG_PROG_PKG_CONFIG])
|
||||
dnl - Check for intltool/gettext macros
|
||||
m4_ifdef([IT_PROG_INTLTOOL],[IT_PROG_INTLTOOL])
|
||||
|
||||
dnl - Check for zlib
|
||||
AC_CHECK_LIB(z, gzopen)
|
||||
|
||||
dnl - Check for zziplib
|
||||
AC_CHECK_LIB(zzip, zzip_open)
|
||||
|
||||
dnl - Check for SDL
|
||||
AC_PATH_PROGS(SDLCONFIG, [sdl-config sdl11-config])
|
||||
if test ! "x$SDLCONFIG" = "x" ; then
|
||||
SDL_CFLAGS=`$SDLCONFIG --cflags`
|
||||
SDL_LIBS=`$SDLCONFIG --libs`
|
||||
AC_SUBST(SDL_CFLAGS)
|
||||
AC_SUBST(SDL_LIBS)
|
||||
HAVE_SDL="yes"
|
||||
else
|
||||
HAVE_SDL="no"
|
||||
fi
|
||||
|
||||
dnl - Check for the OpenGL includes
|
||||
AC_CHECK_HEADERS([GL/gl.h])
|
||||
AC_CHECK_HEADERS([GL/glu.h])
|
||||
|
||||
dnl - Check for GTK and/or libglade
|
||||
GLIB_VER=2.8
|
||||
GTK_VER=2.6
|
||||
AC_CHECK_TOOL(HAVE_PKG, pkg-config)
|
||||
AC_PROVIDE_IFELSE([PKG_PROG_PKG_CONFIG], [
|
||||
if test ! "x$HAVE_PKG" = "x" ; then
|
||||
PKG_CHECK_MODULES(GLIB,
|
||||
glib-2.0 >= $GLIB_VER,
|
||||
HAVE_GLIB=yes,
|
||||
HAVE_GLIB=no)
|
||||
if test "$HAVE_GLIB" = "no"; then
|
||||
AC_MSG_ERROR([glib-2.0 >= $GLIB_VER is required to build desmume gtk frontend])
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES(GTK,
|
||||
gtk+-2.0 >= $GTK_VER,
|
||||
HAVE_GTK=yes,
|
||||
HAVE_GTK=no)
|
||||
if test "$HAVE_GTK" = "no"; then
|
||||
AC_MSG_ERROR([gtk-2.0 >= $GTK_VER is required to build desmume gtk frontend])
|
||||
fi
|
||||
AC_SUBST(GTK_CFLAGS)
|
||||
AC_SUBST(GTK_LIBS)
|
||||
|
||||
PKG_CHECK_MODULES(GTKGLEXT,
|
||||
"gtkglext-1.0",
|
||||
HAVE_GTKGLEXT=yes,
|
||||
HAVE_GTKGLEXT=no)
|
||||
AC_SUBST(GTKGLEXT_CFLAGS)
|
||||
AC_SUBST(GTKGLEXT_LIBS)
|
||||
|
||||
PKG_CHECK_MODULES(GTHREAD,
|
||||
"gthread-2.0",
|
||||
HAVE_GTHREAD=yes,
|
||||
HAVE_GTHREAD=no)
|
||||
AC_SUBST(GTHREAD_CFLAGS)
|
||||
AC_SUBST(GTHREAD_LIBS)
|
||||
|
||||
|
||||
AC_CHECK_LIB(gdkglext-x11-1.0, gdk_gl_init)
|
||||
|
||||
PKG_CHECK_MODULES(LIBGLADE,
|
||||
"libglade-2.0",
|
||||
HAVE_LIBGLADE=yes,
|
||||
HAVE_LIBGLADE=no)
|
||||
AC_SUBST(LIBGLADE_CFLAGS)
|
||||
AC_SUBST(LIBGLADE_LIBS)
|
||||
|
||||
dnl uninstalled glade ui dir
|
||||
AC_DEFINE_UNQUOTED(GLADEUI_UNINSTALLED_DIR,"`pwd`/src/gtk-glade/glade/",[path to glade ui dir])
|
||||
AC_SUBST(GLADEUI_UNINSTALLED_DIR)
|
||||
fi
|
||||
],[
|
||||
echo "WARNING: pkg-config is not available therefore gtk and gtk-glade UIs are not available either."
|
||||
])
|
||||
|
||||
dnl - If the gtkGLext package is available define the corresponding C macro
|
||||
if test "x$HAVE_GTKGLEXT" = "xyes"; then
|
||||
AC_DEFINE([GTKGLEXT_AVAILABLE], [1])
|
||||
fi
|
||||
|
||||
dnl - Determine which UIs to build and if po/ should be included
|
||||
PO_DIR=""
|
||||
PO_FILES=""
|
||||
PO_FILES_IN=""
|
||||
if test "x$HAVE_SDL" = "xyes"; then
|
||||
# SDL adds just a cli
|
||||
UI_DIR="cli $UI_DIR"
|
||||
if test "x$HAVE_GTK" = "xyes"; then
|
||||
# GTK requires SDL
|
||||
UI_DIR="gtk $UI_DIR"
|
||||
fi
|
||||
|
||||
if test "x$HAVE_LIBGLADE" = "xyes"; then
|
||||
AC_PROVIDE_IFELSE([IT_PROG_INTLTOOL],[
|
||||
# libglade requires SDL too
|
||||
UI_DIR="gtk-glade $UI_DIR"
|
||||
|
||||
dnl -- localization for gtk-glade UI
|
||||
GETTEXT_PACKAGE=desmume
|
||||
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [Define to the gettext package name])
|
||||
AC_SUBST(GETTEXT_PACKAGE)
|
||||
ALL_LINGUAS="fr pt_BR"
|
||||
AM_GLIB_GNU_GETTEXT
|
||||
PO_DIR="po"
|
||||
PO_FILES="intltool-extract intltool-merge intltool-update"
|
||||
PO_FILES_IN="intltool-extract.in intltool-merge.in intltool-update.in"
|
||||
PO_MAKEFILE="po/Makefile.in"
|
||||
],[
|
||||
echo "WARNING: intltool and/or gettext are not available therefore the gtk-glade interface won't be installed. The gtk-glade UI requires intltool and gettext."
|
||||
])
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl Set compiler library flags per target.
|
||||
case $target in
|
||||
*linux* | *bsd*)
|
||||
LIBS="$LIBS -lGL -lGLU"
|
||||
;;
|
||||
*mingw*)
|
||||
LIBS="$LIBS -ldxguid -ldxerr8 -ldsound -lopengl32 -lws2_32 -mwindows"
|
||||
UI_DIR="windows"
|
||||
;;
|
||||
*darwin*)
|
||||
LIBS="$LIBS -framework OpenGL"
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_SUBST(UI_DIR)
|
||||
AC_SUBST(PO_DIR)
|
||||
AC_SUBST(PO_FILES)
|
||||
AC_SUBST(PO_FILES_IN)
|
||||
|
||||
dnl - Gdb stub
|
||||
AC_ARG_ENABLE(gdb-stub,
|
||||
[AC_HELP_STRING(--enable-gdb-stub, enable gdb stub)],
|
||||
[
|
||||
AC_DEFINE(GDB_STUB)
|
||||
wantgdbstub=yes
|
||||
])
|
||||
AM_CONDITIONAL([HAVE_GDB_STUB], [test "${wantgdbstub}" = "yes"])
|
||||
|
||||
dnl - Compiler warnings
|
||||
|
||||
# for developer use, enable lots of compile warnings,
|
||||
# but don't require this generally, because some system's
|
||||
# header files (BSD) can't handle it
|
||||
#
|
||||
# NB: must add -Werror after AC_PROG_CC, etc., so do this last
|
||||
AC_ARG_ENABLE(hardcore,
|
||||
[AC_HELP_STRING(--enable-hardcore, turn on -W -Wall -Werror)],
|
||||
[case "${enableval}" in
|
||||
yes) ENABLE_HARDCORE=1 ;;
|
||||
no) ENABLE_HARDCORE=0 ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-hardcore) ;; esac],
|
||||
[ENABLE_HARDCORE=0])
|
||||
|
||||
if test "x[$]ENABLE_HARDCORE" = "x1"; then
|
||||
AC_MSG_WARN(enable hardcore compile warnings)
|
||||
if test "x$CXX" = "x"; then
|
||||
dnl - only valid for C with newer gcc's
|
||||
CPPFLAGS="[$]CPPFLAGS -Wmissing-prototypes"
|
||||
fi
|
||||
CPPFLAGS="[$]CPPFLAGS -Wall -Wextra -Wno-missing-field-initializers -Wpointer-arith -Wcast-align -Wwrite-strings -Wno-unused-parameter -Wmissing-declarations -Wundef -Wmissing-noreturn -Wshadow"
|
||||
fi
|
||||
|
||||
dnl - Enable debug mode
|
||||
AC_ARG_ENABLE(debug,
|
||||
AC_HELP_STRING(--enable-debug, enable debug information),
|
||||
AC_DEFINE(DEBUG))
|
||||
AC_ARG_ENABLE(gpu-debug,
|
||||
AC_HELP_STRING(--enable-gpu-debug, enable gpu debug information),
|
||||
AC_DEFINE(GPUDEBUG))
|
||||
AC_ARG_ENABLE(div-debug,
|
||||
AC_HELP_STRING(--enable-div-debug, enable div debug information),
|
||||
AC_DEFINE(DIVDEBUG))
|
||||
AC_ARG_ENABLE(sqrt-debug,
|
||||
AC_HELP_STRING(--enable-sqrt-debug, enable sqrt debug information),
|
||||
AC_DEFINE(SQRTDEBUG))
|
||||
AC_ARG_ENABLE(dma-debug,
|
||||
AC_HELP_STRING(--enable-dma-debug, enable dma debug information),
|
||||
AC_DEFINE(DMADEBUG))
|
||||
|
||||
dnl - Enable memory profiling
|
||||
AC_ARG_ENABLE(memory-profiling,
|
||||
AC_HELP_STRING(--enable-memory-profiling, enable memory profiling information),
|
||||
AC_DEFINE(PROFILE_MEMORY_ACCESS))
|
||||
|
||||
dnl -- set maintainer mode
|
||||
AM_MAINTAINER_MODE
|
||||
AC_SUBST(USE_MAINTAINER_MODE)
|
||||
|
||||
|
||||
dnl --- Finally, output all the makefiles
|
||||
AC_CONFIG_FILES([Makefile
|
||||
${PO_MAKEFILE}
|
||||
src/Makefile
|
||||
src/cli/Makefile
|
||||
src/cli/doc/Makefile
|
||||
src/cocoa/Makefile
|
||||
src/gtk/Makefile
|
||||
src/gtk/doc/Makefile
|
||||
src/gtk-glade/Makefile
|
||||
src/gtk-glade/doc/Makefile
|
||||
src/windows/Makefile
|
||||
src/gdbstub/Makefile
|
||||
autopackage/default.apspec
|
||||
])
|
||||
AC_OUTPUT
|
|
@ -1,972 +0,0 @@
|
|||
0.9.12 -> 0.9.13
|
||||
|
||||
In this version we have added support for high-resolution 3D rendering. Try the new "GPU Scaling Factor" feature to
|
||||
increase the 3D resolution beyond the native resolution of 256x192 pixels. Also, the Cocoa frontend sees continued
|
||||
radical enhancements and while the Windows frontend sees some new incremental enhancements.
|
||||
|
||||
General/Core:
|
||||
bug: numerous host compatibility and accuracy improvements to OpenGL renderer, tho off-by-1 sampling bugs will remain.
|
||||
bug: fixes to 'edge marking', shadows, box tests, maths & depths precision, and some other rarer 3d rendering usecases
|
||||
bug: fixes to AR cheat processing
|
||||
bug: fixes to cheat database game identification
|
||||
bug: fix interpolation at SPU loop points, emulation of SPU half/byte size registers & others
|
||||
bug: backlight emulation added (for fade effects)
|
||||
bug: other small ongoing fixes to 2d rendering and GPU memory maps
|
||||
bug: emulate slot-1 read timings, probably for AP-related purposes
|
||||
bug: general improvement to hardware component power-off state handling, especially 3d engine
|
||||
bug: fix virtual fat (homebrew) building in environment with symlinks
|
||||
bug: fix some rarely-bugged CPU instructions
|
||||
bug: fix bugs in homebrew filesystems
|
||||
bug: fix bugs in big-endian hosts
|
||||
bug: fix loading gzipped files and some newer rars
|
||||
bug: fix inconsistencies and omissions in command-line processing
|
||||
bug: extensive improvement to wifi emulation, though wifi is still not supported.
|
||||
bug: firmware file settings/management now behaves more or less sensibly as advertised
|
||||
bug: fix movie (dsm) being bitrotted and failing to sync settings or manage sram properly
|
||||
enh: movie (dsm) add record from state feature
|
||||
enh: high-resolution 3d rendering, from 1x-16x the native resolution of 256x192 pixels
|
||||
enh: texture upscaling for 3d rendering, from 1x-4x the native texture size
|
||||
enh: texture smoothing option for OpenGL renderer
|
||||
enh: user-selectable internal GPU bpp 15/18/24 to change from accuracy to attractiveness
|
||||
enh: game-specific hacks library finally implemented internally, user-selectable.
|
||||
enh: game-specific hack for popular games that randomly corrupt their sprites when going in and out of doors
|
||||
enh: officially supported arm and arm64 jits and overall improvements on arm hosts
|
||||
enh: emulator now makes "(backups)" states on every loadstate, for in case you hit loadstate on accident
|
||||
enh: User-selectable MSAA level for OpenGL renderer.
|
||||
enh: "interface" for dll/so control of a desmume core
|
||||
enh: optimizations, cpu arch-specific, and otherwise, to all 3d and 2d rendering, ranging from SSE to AVX2
|
||||
enh: lua - Add raw joystick API and setlayermask API (windows only)
|
||||
enh: lua - Add gamecode APU for game-specific hacks in scripts and 'freelook' script functionality
|
||||
enh: add options to emulate game cards more badly, to trip AP on purpose
|
||||
enh: fix some save type / slot type autodetections and save memory import codepaths
|
||||
enh: add fake impossible debug AR code to select CPU: DFFFFFFF 77777777/99999999
|
||||
enh: add --rtc-day and --rtc-hour to specify an offset from host RTC
|
||||
enh: support newer duc files
|
||||
enh: upgrade and add some upscalers, hq3x, 6xBRZ, etc.
|
||||
enh: add "interface" frontend for use via dll/so
|
||||
|
||||
Windows:
|
||||
note: windows xp and x86 support is dropped for official builds. windows 7 support will be dropped over my dead body.
|
||||
bug: fix numerous bugs involving filenames and path with non-latin characters
|
||||
bug: fix bugs in various display layout, rotate, vsync, gaps, and display method configurations
|
||||
bug: fix bugs in user configured paths
|
||||
bug: aviout/wavout is now more robust
|
||||
bug: fix bugs in window clearing and various display method configurations which leave garbage on screen
|
||||
enh: add fullscreen display options
|
||||
enh: major revisions to mic sample feature, loaded as a bunch and rotated with hotkeys
|
||||
enh: add user-facing option to control console window visibility
|
||||
enh: add some crude capability for breakpoints to cpu debugger and memory viewer, and other bugfixes
|
||||
enh: add "screen size ratio" for smaller sub-screens, etc.
|
||||
enh: add some hotkeys
|
||||
enh: add option to kill stylus input when outside the NDS screen
|
||||
enh: improve cheat list UX
|
||||
enh: optimizations to reduce cpu usage overall and during idle especially for high resolutions, scalers, etc.
|
||||
enh: improve pen&touch support
|
||||
|
||||
Cocoa:
|
||||
bug: fix issues with v-sync causing frame rate issues under various circumstances
|
||||
bug: fix issues when running a display window in fullscreen
|
||||
enh: add native binary support for Apple Silicon CPUs
|
||||
enh: Macs with an Intel Haswell or later CPU now benefit from the new AVX2 optimizations
|
||||
enh: add support for Apple's Dark Mode user interface introduced in macOS Mojave
|
||||
enh: add some new toolbar items for the following: Frame Advance, Enable/Disable HUD, Toggle Displays
|
||||
enh: turbo inputs can now be configured with a frame-by-frame press/release pattern
|
||||
enh: display windows now run their video output using Metal, if available
|
||||
enh: display windows now support HiDPI monitors like Apple's Retina monitors
|
||||
enh: display windows have new "Hybrid" layouts for better fit on modern widescreen monitors (View > Display Layout)
|
||||
enh: display windows can now change the video source going to each individual DS screen (View > Display Video Source)
|
||||
enh: display windows can now run a Heads-Up Display for reporting useful info (View > Show HUD Settings)
|
||||
enh: add support for changing the NDS stylus pressure (Emulation > Show Stylus Settings)
|
||||
enh: screenshots can now be captured using a dedicated tool for it (Tools > Show Screenshot Capture Tool)
|
||||
enh: lots of miscellaneous stability and performance improvements
|
||||
|
||||
Linux:
|
||||
note: SDL2 now employed
|
||||
note: GTK3 port added, built with meson
|
||||
note: CLI and GTK ports improved, according to their respective niche (gaming vs functionality)
|
||||
note: CLI: added horizontal screen layout
|
||||
note: CLI: added floating-point scale factor support with HW stretching
|
||||
note: CLI/GTK2: improved gdb stub for game debugging
|
||||
note: CLI/GTK2/GTK3: various other improvements
|
||||
|
||||
0.9.11 -> 0.9.12
|
||||
|
||||
We decided to start skipping even versions to disambiguate official releases from several years of interim builds,
|
||||
and to insulate ourselves from consideration for world record of "longest time between consecutive releases" by
|
||||
creating confusion as to what constitutes a consecutive release.
|
||||
|
||||
0.9.10 -> 0.9.11 (r4908-r5146)
|
||||
|
||||
In this version, we have focused on the Cocoa frontend, but there have been some good core fixes over so long.
|
||||
Notably, the save-related issues resulting in the advice "dont use 0.9.10" have been resolved.
|
||||
|
||||
General/Core:
|
||||
bug: fix large numbers of games not being able to save anymore
|
||||
bug: fix some missing sound effects due to wrong volumes in some boot scenarios and other things
|
||||
bug: fix freezes due to tiny looping sounds
|
||||
bug: fix many big endian issues
|
||||
bug: fix some apparently rarely-used CPU instructions, no known consequences
|
||||
bug: fix (block) reading of some GPU registers
|
||||
bug: fix action replay code type 0xE
|
||||
bug: fix reading of last 4 bytes of rom
|
||||
bug: large improvements to stability of GDB stub
|
||||
bug: support w-buffer support in OpenGL renderers
|
||||
bug: fix unpredictable crashes in some 3d scenes from w=0
|
||||
enh: better loading of roms (bad patches) with wrong size info in header
|
||||
enh: warn user sometimes when 'stream rom from disk' will create malfunctions
|
||||
enh: add xBRZ filters
|
||||
enh: add "TXT Hack" for software rasterizer to improve text rendering in some games
|
||||
|
||||
Windows:
|
||||
bug: fix 5x filters
|
||||
enh: support import of action replay save files (.dss)
|
||||
enh: add antialiasing option for OpenGL renderers
|
||||
enh: don't malfunction if saveram is unavailable or read-only
|
||||
|
||||
Cocoa:
|
||||
bug: 16-bit to 32-bit color space conversions no longer darken video or images
|
||||
bug: fix intermittent issues with loading user defaults on app startup
|
||||
bug: fix rendering inaccuracies of the video preview in the app display preferences
|
||||
bug: fix various UI font rendering and text alignment issues on OS X Yosemite
|
||||
bug: fix crackly sound from N-sync and Z-sync methods
|
||||
enh: make N-sync method the default sound sync method since it has much lower latency than P-sync method
|
||||
enh: add support for gdbstub (Tools > Show GDB Stub Control) (only available on custom builds using the dev+ build target)
|
||||
enh: optimize input handling to use less CPU
|
||||
enh: add support for App Nap when the app is in an idle state (only supported on OS X Mavericks and later)
|
||||
enh: add Execution Control panel (Emulation > Show Execution Control), now with frame advance and frame jump controls
|
||||
enh: auto frame skip is now smoother
|
||||
enh: further improve execution timing accuracy
|
||||
enh: improve overall video performance
|
||||
enh: render video through a 3-stage filtering pipeline, (Video Source)-->(Pixel Scaler)-->(Video Output)
|
||||
enh: add the following video source filters - Deposterize
|
||||
enh: add the following video output filters - Bicubic B-Spline, Bicubic Mitchell-Netravali, Lanczos2, Lanczos3
|
||||
enh: add ability to run all existing pixel scalers on either the CPU or the GPU
|
||||
enh: add ability to toggle the main and touch display positions (View > Toggle All Displays)
|
||||
enh: add preliminary support for replay playback and recording
|
||||
enh: add support for turbo and autohold
|
||||
enh: add support for the entire suite of slot-2 devices (Emulation > Show SLOT-2 Manager)
|
||||
enh: add support for using the host machine's audio input device for emulating the NDS microphone (Emulation > Show Microphone Settings)
|
||||
enh: change the sine wave tone generator's range from 100Hz-5000Hz to 40Hz-4000Hz
|
||||
enh: reorganize the menu options to more logical locations
|
||||
enh: greatly improve the File Migration Assistant (now renamed Game Data Migration Assistant) and ROM Info panel with a more modern and space efficient look and feel
|
||||
enh: miscellaneous user interface improvements
|
||||
|
||||
Linux:
|
||||
bug: fix screen gap bug
|
||||
bug: workaround for std::bad_alloc exceptions compiler bugs
|
||||
enh: add experimental AV recording
|
||||
enh: generally improve main loop throttling and skipping
|
||||
enh: massive improvements to HUD and menu layout
|
||||
enh: add window sizing options and sound interpolation options
|
||||
enh: add Lid button; disallow U+D, L+R; manual option saving
|
||||
|
||||
0.9.9 -> 0.9.10 (r4623-r4908)
|
||||
|
||||
In this version, we have focused on trying to clean up some complexities in the user experience and emulator internals. Pretty unglamorous stuff, but some games are newly compatible.
|
||||
|
||||
General/Core:
|
||||
enh: break savestate back-compatibility
|
||||
bug: improve save size autodetection for some games
|
||||
bug: cpu: fix many basic jit cpu bugs
|
||||
bug: 3d: tweak softrasterizer edge marking
|
||||
bug: 3d: fix stale 4x4 texture palettes
|
||||
bug: fix some GPU sprite blending scenarios
|
||||
bug: fix bios HLE BitUnPack, UnCompHuffman
|
||||
enh: modular slot-1 device system, emulate GC bus more faithfully
|
||||
enh: support NAND slot-1 device
|
||||
enh: auto-detect appropriate slot-1 and slot-2 device
|
||||
enh: many revisions to firmware boot process for more authenticity. iQue and FlashME versions function, .dfc rewritten.
|
||||
enh: support streaming NDS file from disk (like an ISO, to avoid long initial load time)
|
||||
enh: run .dsv directly on disk, to save long flushing times. should speed backup operations.
|
||||
enh: spu synch mode and method on commandline
|
||||
|
||||
Windows:
|
||||
bug: fixes to advanscene DB import
|
||||
bug: save opengl display method filter option
|
||||
bug: general bugfixes to various screen layout modes
|
||||
enh: add option to stop non-integer scaling during fullscreen or maximize
|
||||
enh: improvements to save import dialog
|
||||
enh: improved memory viewer tool
|
||||
enh: operate better when run, against our advice, from a zipfile
|
||||
enh: add slot-1 Nitro Filesystem viewer tool
|
||||
|
||||
Cocoa:
|
||||
bug: fix slot1-R4 path saving
|
||||
bug: fix bug with mic samples < 16khz
|
||||
bug: fix bugs and enhancements in multi display windows
|
||||
bug: fix handling of some joystick analog inputs
|
||||
enh: save display windows configuration and emulation speed on app exit
|
||||
|
||||
0.9.8 -> 0.9.9 (r4228-r4623)
|
||||
|
||||
Yes, it's been a while since the last release, but we haven't been completely idle. There's a brand new jit cpu core which yields some impressive speedups!
|
||||
|
||||
General/Core:
|
||||
!!!: add optional arm cpu jit (functioning on x86 and x64 hosts only)
|
||||
bug: we're not going to list 70% of the emulation fixes, as is traditional.
|
||||
bug: savestate reliability fixes related to halt states, gxstat, firmware
|
||||
bug: lua: fix readbyterange, gdscreenshot functions
|
||||
bug: commandline slot-1 handling straightened out
|
||||
enh: fixes and additions to resize filter options
|
||||
|
||||
Graphics:
|
||||
enh: opengl 3d driver compatibility improvements
|
||||
bug: fix giant regression from 0.9.7 that left garbage from previous frames on the screen in some games
|
||||
bug: 3d: fix some single poly pixels
|
||||
bug: 3d: fix some polygon and texture coloring bugs on big-endian systems
|
||||
|
||||
Windows:
|
||||
bug: fix some full screen stretching bugs
|
||||
enh: add xaudio2 output driver
|
||||
enh: add opengl display method (as opposed to directdraw), with controllable bilinear filter
|
||||
enh: upgrade archive handling system, lzma2 supported
|
||||
enh: reorganize main menu quite a bit
|
||||
enh: add rotation hotkeys, and hotkey to control mouse cursor visibility
|
||||
enh: memory viewer improvements and fixes
|
||||
enh: improve interface for rom eject to prevent accidents and improve usefulness (hide in slot-1 config screen)
|
||||
|
||||
Cocoa:
|
||||
bug: fix missing display when running on OS X v10.8 Mountain Lion
|
||||
bug: fix possible sound crash when using Dual SPU Synch/Asynch
|
||||
bug: fix File menu items being disabled after the file migration sheet is used
|
||||
bug: fix window resizing issues
|
||||
bug: fix text rendering in About box
|
||||
enh: show the icon and name of the loaded ROM
|
||||
enh: add Support Request and Bug Report forms to the Help menu
|
||||
enh: add more detailed info to the About box
|
||||
enh: add OpenGL as a 3D rendering option
|
||||
enh: add support for MSAA when using OpenGL as the 3D rendering engine
|
||||
enh: add V-Sync option
|
||||
enh: add Display Orientation, Display Order, and Display Separation options for Combo Display mode
|
||||
enh: add HQ4xS filter
|
||||
enh: completely revamp the user interface for Input Preferences
|
||||
enh: many emulator commands may now be mapped
|
||||
enh: add ability to map an input to user-defined touch screen coordinates
|
||||
enh: add support for saving and applying input profiles
|
||||
enh: add support for using an audio file for the microphone input
|
||||
enh: add sine wave tone generator for microphone input
|
||||
enh: add support for multiple display windows (File > New Display Window)
|
||||
enh: add support for SLOT-1 devices (Emulation > Show SLOT-1 Manager)
|
||||
enh: overall performance and stability improvements
|
||||
enh: miscellaneous user interface improvements
|
||||
|
||||
0.9.7 -> 0.9.8 (r3812-r4228)
|
||||
|
||||
Yes, it's been a while since the last release, but we haven't been completely idle. There's a brand new top shelf Cocoa frontend to make life far more pleasant for OSX users, and a host of compatibility fixes.
|
||||
|
||||
General/Core:
|
||||
bug: fix more IPC FIFO errors
|
||||
bug: import more save files correctly
|
||||
bug: don't autopatch already-patched roms
|
||||
bug: fix bugs in piano and guitar grip
|
||||
bug: fix ARM7's VRAMSTAT register
|
||||
bug: fix memory leaks on compact flash emulation
|
||||
bug: fix reading of rom from low header area
|
||||
bug: spu: fix some poppy interpolation audio quality issues
|
||||
bug: improve timing of dma operations by running through normal mem cycle accounting; fixes an annoying number of games and graphical glitches
|
||||
bug: fix opcode MRC and fake bios CRC16
|
||||
enh: jitter some related register and irq events to simulate pipeline effects and stimulate some race conditions to other outcomes
|
||||
enh: fake (deterministic) some tiny jitter from human's hand holding stylus; some games were accidentally depending on this
|
||||
enh: support nocash-style prints from arm
|
||||
enh: add lua apis for accessing vram
|
||||
enh: platforms other than windows receive threading optimizations
|
||||
enh: provide diagnostics when system powers off (useful for homebrewers returning from main())
|
||||
enh: clarify handling of different console types within the family (ds,dslite,debug)
|
||||
enh: vfat support for slot-1 devices
|
||||
enh: emulate temperature register
|
||||
enh: add paddle emulation
|
||||
|
||||
Graphics:
|
||||
bug: fix occasional crash from uninitialized blending table
|
||||
bug: fix some 2d alpha blending cases resulting in white screens
|
||||
bug: fix VRAM_I B_OBJ mirroring and fix sprites rendering across the end of vram
|
||||
bug: fix rotoscaled sprites wrapping around screen
|
||||
bug: dont fix rotscaled bitmap sprites with alpha==0
|
||||
bug: opengl: fix degradation of toon rendering during loadstate
|
||||
bug: opengl: alpha blending fixes
|
||||
bug: many refinements to opengl renderer
|
||||
bug: opengl: support rear-plane/ClearImage emulation (fixes many graphics)
|
||||
bug: rasterizer: fix some rare alpha blending cases
|
||||
bug: fix bug in environment mapping introduced after 0.9.6
|
||||
bug: fix totally glitched out 3d graphics with several improvements involving matrix stack
|
||||
bug: fix memory overflows in epx filter
|
||||
bug: prevent backdrop from blending with ???
|
||||
enh: opengl: better depth buffering emulation
|
||||
enh: better support for line segment "polys" by detection and special rendering logic
|
||||
enh: opengl: support quad primitives directly
|
||||
enh: add hq4x filter
|
||||
|
||||
Windows:
|
||||
bug: fix a long-standing loadstate crash
|
||||
bug: fix lag frame accounting
|
||||
bug: fix glitches in cheat entry menu
|
||||
bug: stop compact flash emulation from accidentally scanning c:\ sometimes
|
||||
enh: add support for game database for improved save type detection
|
||||
enh: hotkey for limit framerate toggle
|
||||
enh: remove stop and reset toolbar buttons which were accidentally getting used
|
||||
enh: additional complexification to desmume's behaviour run from a console prompt. whether it's better is uncertain.
|
||||
enh: add support for cheats databases
|
||||
enh: improvements to ram search tool
|
||||
enh: preliminary support for varying stylus pressure
|
||||
enh: add [Display] Show Console=1 to ini file
|
||||
enh: more graceful cheat parsing and add some hotkeys
|
||||
enh: add 5x window size
|
||||
enh: add big endian and 20.12 toggle to memview and ramwatch
|
||||
enh: improve FPS throttle feedback and granularity
|
||||
enh: add lua menu API
|
||||
enh: hud font switching
|
||||
enh: add optional file association for .nds to path config dialog
|
||||
|
||||
Cocoa:
|
||||
enh: Big update to cocoa frontend. Pretty much entirely new. (rogerman)
|
||||
|
||||
Linux:
|
||||
bug: gtk: glitches in rom and recent rom loading
|
||||
bug: glade: normalize savestate slot to hotkey mapping
|
||||
enh: support soundtouch for use by metaspu
|
||||
enh: gtk: add SPU mode selection (Tobias Jakobi)
|
||||
enh: cli: better fps limiting (Thomas Jones)
|
||||
|
||||
Wx:
|
||||
bug: some small fixes here and there (Jan Bücken)
|
||||
enh: lot of code cleanup (Jan Bücken)
|
||||
|
||||
0.9.6 -> 0.9.7 (r3493-r3812)
|
||||
|
||||
General/Core:
|
||||
bug: fix a ton of old, broken cpu opcodes and CP15 logic
|
||||
bug: return Z1 and Z2 from TSC (fixes some touch logic)
|
||||
bug: gba slot save type detection improved
|
||||
bug: handle unusual rom headers more correctly
|
||||
bug: dont confuse motion pack commands with save memory commands
|
||||
bug: make cheat system a little less flaky and add AR 1.54 support
|
||||
bug: fix nondeterministic backup memory behaviour while rerecording
|
||||
bug: correct emulation of register accesses of wrong size and during powerdown
|
||||
bug: rewrite --cflash-path emulation
|
||||
bug: rewrite IPC/GX FIFO, IRQ flag generation, and wait-for-IRQ logics
|
||||
bug: rewrite RTC calendar handling; now supports years > 2038
|
||||
enh: auto-DLDI patching for homebrew
|
||||
enh: --gbaslot-rom=self mounts self.nds in slot2
|
||||
enh: more realistic exception handling
|
||||
enh: piano controller emulation
|
||||
enh: modular slot-1 system for exact emulation of homebrew cards
|
||||
|
||||
Graphics:
|
||||
bug: edge marking colors were wrong
|
||||
bug: handle some "invalid" vram configurations correctly
|
||||
bug: convert half of geometry engine to fixed point
|
||||
bug: fix sprite blend+fadein/fadeout
|
||||
bug: improve rasterizer shadows
|
||||
bug: fix main memory display DMA
|
||||
bug: fix some raster fx timing bugs
|
||||
enh: add a hack for improving some non-stencil shadows
|
||||
|
||||
Windows:
|
||||
bug: misc fixes and improvements to gpu viewer tools
|
||||
bug: sub screen layer display toggling fixed
|
||||
bug: fixes and improvements to ram watch, ram search, cheats list
|
||||
bug: fix start-paused commandline
|
||||
bug: fix memory leaks when sound disabled
|
||||
bug: improve load average calculators and add arm7 load average
|
||||
enh: background input support
|
||||
enh: add vsync option
|
||||
enh: support more knobs on joysticks
|
||||
enh: import cheats from R4 database
|
||||
enh: add xinput rumble for 360 pads
|
||||
|
||||
Linux/OSX:
|
||||
bug: crash less in recent roms list
|
||||
enh: Add horizontal screen layout and swap screen ability to gtk frontend (noodlebox)
|
||||
enh: Big improvement to joystick support, support complex configurations and multiple devices (noodlebox)
|
||||
|
||||
|
||||
0.9.5 -> 0.9.6 (r3075-r3493)
|
||||
|
||||
Users of gtk, cli and gtk-glade frontends please note that now we
|
||||
have a common directory in ~/.config/desmume for config file,
|
||||
saves and savestates. The old .desmume.ini will be moved
|
||||
automatically with the name config but you have to move your saves
|
||||
manually.
|
||||
|
||||
Some save files may be invalidated due to use of broken crc logic.
|
||||
Back up your DSV files before using this version of the emulator or else
|
||||
the game might wipe it.
|
||||
|
||||
General/Core:
|
||||
bug: emulate keypad interrupt
|
||||
bug: spu overhaul, add capture support
|
||||
bug: fix dma address reloading
|
||||
bug: fix rom close memory corruption
|
||||
bug: fix div and sqrt busy flag bug
|
||||
bug: fix vectest
|
||||
bug: fix lid savestate desync
|
||||
bug: fix texcache memory GB explosion when games use tons of tiny 3d sprites
|
||||
bug: fix huge rerecording movie file handle leak
|
||||
bug: fix EXXXXXXX cheat codes and some add/edit/save/load bugs
|
||||
bug: add 8MBit - 512MBit flash emulation
|
||||
bug: fix firmware booted-from-card flag
|
||||
bug: fix some failures to wake
|
||||
bug: fix some rtc calendar logic
|
||||
bug: op_bkpt emulation
|
||||
bug: correctly emulate POWCNT1 and POWCNT2 and SPI power device
|
||||
bug: corrections to bootup stack configuration
|
||||
bug: protect bios from being overwritten
|
||||
bug: initialize save data to 0xFF instead of 0x00
|
||||
bug: handle relocated irq vectors
|
||||
bug: support patched firmwares
|
||||
bug: handle 8bit auxspidata, 32bit BLDY, 32bit div regs
|
||||
bug: fix some divide by zero cases
|
||||
bug: don't print \n in ideas debug message
|
||||
bug: don't let games read off end of cart and crash emulator
|
||||
bug: fix SWI 0x0E crc16 ; some save files using wrong crc may be invalidated
|
||||
bug: fix many big endian bugs
|
||||
bug: fix CPSR.I idle wakeup
|
||||
bug: fix loadstate crashes, mostly when sound is enabled
|
||||
enh: support devkitpro argv
|
||||
enh: add gbaslot-rom commandline
|
||||
enh: add no$gba debug message
|
||||
enh: add rtc start to dsm header
|
||||
|
||||
Graphics:
|
||||
bug: fix a mistakenly rendered OBJ window and 3d blend effects
|
||||
bug: fixes to matrix stacks, fixing lots of garbled geometry
|
||||
bug: fix fog density registers
|
||||
bug: fix hblank dma to run also on scanline 262
|
||||
bug: fix w/z depth flags for broken GUIs in dual screen 3d games
|
||||
bug: fixes to poly sorting
|
||||
bug: block 8bit vram writes
|
||||
enh: improve accuracy of opengl shaders
|
||||
|
||||
Windows:
|
||||
bug: fix 16bpp display
|
||||
bug: more fixes to multi-gamepads
|
||||
bug: cheat windows robustification
|
||||
bug: fix that sticky pause state when resetting and loading roms
|
||||
bug: dont crash when no sound device is available
|
||||
bug: change F10 to be save slot 0
|
||||
bug: fix --start-paused
|
||||
enh: try not to screensave while using gamepad
|
||||
enh: add EPX and EPX1.5X resize filters
|
||||
enh: add a japanese translation which will soon be stale like the others
|
||||
enh: add fancy ctrl+printscreen with emulator info on it
|
||||
enh: add "lockdown" window mode to keep window safe from fast stylus action
|
||||
enh: add alt+enter fullscreen command
|
||||
enh: add card eject command
|
||||
enh: add ddraw software mode forcer
|
||||
enh: improve oam viewer
|
||||
enh: default 3d to rasterizer so we dont have to suggest it 1000 times a day
|
||||
enh: add dump-all-memory tool
|
||||
enh: add reload rom menu/hotkey
|
||||
|
||||
Linux/OSX:
|
||||
bug: fix building for nosse2 systems
|
||||
bug: fix --num-cores
|
||||
bug: fix occasional touchscreen failures
|
||||
bug: fix crash starting dsm record
|
||||
enh: add --nojoy=1 to fix laptops with accelerometers
|
||||
enh: add simple auto frameskip mode in the gtk frontend
|
||||
enh: add gui for configuring joystick in the gtk frontend
|
||||
enh: make the cli frontend read the ini config file too
|
||||
enh: additional OpenAL microphone backend (ncalexan)
|
||||
enh: common place for config and saves (Jan Steffens)
|
||||
enh: libagg is now optional if you don't need the hud
|
||||
|
||||
0.9.4 -> 0.9.5 (r2437-r3075)
|
||||
|
||||
0.9.5 introduces an entirely rewritten main emulation loop
|
||||
This totally changes the timing, and totally breaks old savestates.
|
||||
The OSX build is now based on the GTK port which is more up-to-date.
|
||||
|
||||
Assorted Highlights:
|
||||
* synchronous SPU mode to fix streaming sounds
|
||||
* win32: lua engine, path configuration, 7z dearchiving support
|
||||
|
||||
General/Core:
|
||||
bug: rewrite main emulation loop and cycle accounting, fixes a lot of timings
|
||||
bug: add more detailed timing emulation, removes much bogus lag
|
||||
bug: rewrite DMA,gxfifo,gxstat; fix many games and no more alternate flush mode
|
||||
bug: fix cflash directory support for non-windows and sector-writing
|
||||
bug: fix freeze in cart irq
|
||||
bug: correctly emulate dma to/from tcm
|
||||
bug: fix in thumb LSR carryflag
|
||||
bug: fix thumb BX PC switch to arm state
|
||||
bug: fix adpcm looping, remove adpcm caching (no longer necessary)
|
||||
bug: fixes to swi 3,4,5,8,0x10
|
||||
bug: fixes to exmemstat and ipc sync registers
|
||||
bug: support new backup commands
|
||||
bug: improve bootup bios/firmware emulation steps
|
||||
enh: gbaslot: add guitar grip, gbagame flash support, expansion memory pak
|
||||
enh: add more powerful antigrain-based drawing library and rewrite OSD system
|
||||
enh: ideas-style debugging prints
|
||||
enh: most optimizations now SSE instead of SSE2
|
||||
enh: more improvements to frameskipping and frame advance/speed controls
|
||||
|
||||
Graphics:
|
||||
bug: fix backdrop blending with garbage
|
||||
bug: fix 256B granularity sprite addressing for sub gpu
|
||||
bug: fix obj blending, bmp obj rendering, and some obj window cases
|
||||
bug: fix 128-wide captures
|
||||
bug: fix 16color BG line buffer overflow
|
||||
bug: fix color overflow in capture blending
|
||||
bug: fix disp fifo capture
|
||||
bug: fix simultaneous vram display and capture via same bank
|
||||
bug: fix 3d overflow acknowledge registers
|
||||
bug: fix 32bit toon table writes
|
||||
bug: change 3d cores to use 18bit color
|
||||
bug: fix boxtest (addition overflow!), move clipper to main graphics engine
|
||||
bug: fix failure in some cases of polygon clipping
|
||||
bug: fix disp3dcnt emulations
|
||||
bug: fixes to poly sorting
|
||||
bug: fix ogl renderer wireframe support
|
||||
bug: swrast: fix backface culling of nonconvex polys
|
||||
bug: swrast: add clear image and scroll emulation
|
||||
bug: swrast: add fog emulation
|
||||
bug: swrast: fixes to shadow rendering
|
||||
bug: swrast: preliminary edge marking, works decent
|
||||
enh: swrast: multicore optimization for a few fps speedup
|
||||
|
||||
Windows:
|
||||
bug: fix support for multiple gamepads and gamepad hotkeys
|
||||
bug: fix mic noise code and load wav instead of raw; effective in more cases
|
||||
bug: fix for several sticky and broken hotkeys, and f10 hotkeys
|
||||
bug: fixes in ram search, add DTCM and ITCM searching, ...
|
||||
bug: fix sound settings vol slider
|
||||
bug: recover from missing window -32000 problem
|
||||
bug: don't turn on mic unless mic input is enabled
|
||||
enh: x64 build type now supported
|
||||
enh: side-by-side and single screen view modes, many fixes to window resizing
|
||||
enh: choose any gap size by dragging bottom window edge (must be enabled)
|
||||
enh: choose a gap color
|
||||
enh: import/export no$GBA savefiles directly
|
||||
enh: multicore optimization for filters, rotation, OSD
|
||||
enh: soundview can now mute channels
|
||||
enh: new ioregview
|
||||
enh: common commandline system, many arguments shared with linux
|
||||
enh: improve map view tool to support more modes
|
||||
enh: add "FORCE AS CURRENT" recovery tool for mis-sized savefiles
|
||||
enh: add some kind of very small savestate rewinding buffer
|
||||
enh: autoframeskip works better
|
||||
enh: add Italian translation
|
||||
enh: added 2x resizing filters (hq2x, hq2xs, lq2x, lq2xs, 2xsai, supereagle)
|
||||
(scanlines, nearest2x, bilinear)
|
||||
|
||||
Linux:
|
||||
enh: alsa microphone support
|
||||
enh: hud and osd notification for gtk and cli frontends
|
||||
enh: add support for the SSE optimizations
|
||||
|
||||
0.9.2 -> 0.9.4 (r1844->r2352->r2437)
|
||||
|
||||
0.9.3 was skipped due to emu news sites sneaking it out of our staging area and
|
||||
releasing it prematurely while it still had bugs. I was going to curse them
|
||||
individually, but then I decided that they would just like the publicity.
|
||||
|
||||
Highlights:
|
||||
* New save autodetection and save file format
|
||||
* Full rerecording support
|
||||
|
||||
General/Core:
|
||||
bug: fix many 64 bit and endian issues
|
||||
bug: fix mic input, which was nearly useless before
|
||||
bug: fix failures of large dmas
|
||||
bug: fix in ipc sync which broke devkitpro touch
|
||||
bug: screenshots now exclude hud and rotation
|
||||
bug: rewritten vram mapping (fixes corrupted or missing BG)
|
||||
enh: add universal commandline system (same commandline options on every port)
|
||||
enh: cheats: added Action Replay code parser
|
||||
enh: more reliable and useful frameskipping
|
||||
enh: SPU: speedup: add adpcm caching
|
||||
enh: SPU: speedup: interpolation is now optional
|
||||
enh: print svn build number so we can identify people's svn builds from screenshots
|
||||
|
||||
Graphics:
|
||||
bug: add polygon y-sorting (fixes 3d guis)
|
||||
bug: fix texcoordgen mode 3; fixes some ortho sprites and some entirely broken games
|
||||
bug: display capture fixes
|
||||
bug: fix a number of OBJ modes
|
||||
bug: fixes to affine BG modes
|
||||
bug: better emulate some translucent OBJ
|
||||
bug: more correct handling of color effect windows and backdrop colors
|
||||
bug: fix matrix stack overrun which crashed emulator
|
||||
bug: swrast: add clear depth image emulation and other fixes to depth buffering
|
||||
bug: swrast: fix some toon and highlight cases
|
||||
bug: fix bug in matrix stack, fixes some broken models
|
||||
enh: add alternate flush mode HACK 3d config toggle, fixes some entirely broken 3d games
|
||||
|
||||
Windows:
|
||||
bug: more robust cheats engine and dialog
|
||||
enh: more solid avi and wav recording
|
||||
enh: improved tools: memory viewer
|
||||
enh: added tools: spu viewer, ram watch, ram search
|
||||
enh: change build configuration system
|
||||
enh: speedup: add gpu core disabling to hide useless screens
|
||||
enh: add background pause feature (for when emulator loses focus)
|
||||
enh: add missing autohold for L and R
|
||||
enh: add chinese translation
|
||||
|
||||
Gtk frontend:
|
||||
enh: switch all of menu/toolbar system to GtkAction + GtkUIManager
|
||||
enh: remove the gtglext 3d code
|
||||
enh: improve/speedup screen resize and final presentation logic in gtk frontend
|
||||
enh: minimal rerecording hookups
|
||||
|
||||
Cli frontend:
|
||||
enh: hooked the frameskip (szigor)
|
||||
enh: misc usability improvements: auto pause switch for pausing when focus is lost and exit on escape pressing (szigor)
|
||||
enh: hook the fake noise mic; use m to toggle
|
||||
|
||||
0.9.1 -> 0.9.2
|
||||
General/Core:
|
||||
bug: fix error in SBCS/RSCS flags; fixes many odd behaviors and crashes [zeromus]
|
||||
bug: add support for sleep mode and power registers [luigi__]
|
||||
bug: important fixes to RTC so correct time is actually told [luigi__]
|
||||
bug: fix card reads below 0x8000; fixes some game freezes [normatt]
|
||||
bug: fix 4 mbit save type; fix non-autodetect savefile dumping [zeromus, matusz]
|
||||
enh: add sram to GBA game addon emulation for importing savefiles [zeromus]
|
||||
enh: many improvements and feature hookups in linux ports [matusz, luigi__]
|
||||
|
||||
Graphics:
|
||||
bug: fix specular texture mapping mode [luigi__]
|
||||
bug: repairs to some capture modes and vram mapping [zeromus, CrazyMax]
|
||||
bug: viewports finally correctly handled [zeromus]
|
||||
enh: add software rasterizer. quirky, but on par with opengl [zeromus]
|
||||
|
||||
Windows:
|
||||
bug: mitigate bad frameskipper; default to old frameskipping mode [zeromus]
|
||||
bug: fixes with recent roms and zipfile loading [zeromus]
|
||||
bug: fix window position memory [zeromus]
|
||||
enh: bios and firmware may now be used and booted [luigi__]
|
||||
enh: many display, OSD, and input enhancements [luigi__]
|
||||
enh: brand new hotkey and controls binding system [zeromus]
|
||||
enh: configurable screen separation [luigi__]
|
||||
enh: fast forward key [pa__]
|
||||
enh: improvements to mic [luigi__]
|
||||
enh: faster updates in debug tools, up to once per frame [pa__]
|
||||
|
||||
Mac OS X Port:
|
||||
enh: added Italian translation thanks to Paolo Bernini [jeff]
|
||||
enh: resurrection of GDB stub [sigmaris]
|
||||
|
||||
0.9 -> 0.9.1
|
||||
General/Core:
|
||||
enh: GBA slot emulation [CrazyMax]
|
||||
- Rumble support (windows only)
|
||||
- GBA game
|
||||
enh: Mic support (windows only?) [luigi__]
|
||||
enh: Preliminary cheats system [CrazyMax]
|
||||
enh: Savestates invalidated, as more variables have been added.
|
||||
bug: Added PSG white noise [luigi__]
|
||||
bug: fix arm/thumb ROR [zeromus]
|
||||
bug: [ 2550645 ] Super Princess Peach: crash when starting a puzzle [zeromus]
|
||||
bug: win32: fix spu wav file writer (regression from 0.8) [zeromus,luigi__]
|
||||
bug: Much work on FIFOs, still not finished [CrazyMax]
|
||||
bug: Many fixes to dma [zeromus, CrazyMax]
|
||||
bug: bios WaitForVblank and WaitForInterrupt fixed [luigi__]
|
||||
|
||||
Graphics:
|
||||
bug: Added sprite blending [luigi__]
|
||||
bug: more correct mosaic effects, still imperfect [zeromus]
|
||||
bug: Many fixes to tile rendering; all graphics tests now pass [luigi__]
|
||||
bug: fix crashes in some affine BG [zeromus]
|
||||
bug: Implement some pos test function [luigi__]
|
||||
bug: fix texture mapping across texture and palette banks and to unmapped banks [zeromus]
|
||||
bug: fix texture handling for texels with MSB set (fixes some texture corruption) [zeromus]
|
||||
bug: fix texture coordinate generation, including environment mapping [zeromus]
|
||||
bug: texture cache invalidates when palettes change, prevents some texture corruption [zeromus]
|
||||
bug: fix display capturing from 2d+3d source when display mode is display-vram [zeromus]
|
||||
bug: [ 2488334 ].1 fixes to layer compositing [luigi__]
|
||||
bug: [ 2488334 ].3 fix bug in support for hdma affine bg parameters [zeromus]
|
||||
bug: Improvements to 3d h-scrolling [luigi__]
|
||||
bug: Fix some errors in rendering 512 tall BG [zeromus,CrazyMax] (still not fully resolved)
|
||||
bug: Add optional fragment shading pipeline (more precision) [luigi__]
|
||||
bug: Fix bug where some sprites got cut of on x=255 [zeromus]
|
||||
bug: Implement GXSTAT register [CrazyMax]
|
||||
|
||||
Windows:
|
||||
bug: resizing and rotating work in vista [luigi__]
|
||||
enh: 0 frameskip now lets emulator run at excess speed [zeromus]
|
||||
|
||||
Mac OS X Port:
|
||||
bug: left key setting no longer gets confused with the right key [jeff]
|
||||
enh: more keys can be mapped
|
||||
|
||||
0.8 -> 0.9
|
||||
There have been so many changes that this list can hardly be considered complete.
|
||||
For this release, we have formatted the list into a high level overview of big changes and bad bugs relative to the previous release. Hopefully what you're interested in.
|
||||
This list does not include items which are solely performance boosts, for let us just say that virtually every system has been speeded up.
|
||||
|
||||
* The savestate system is totally changed and incompatible with old savestates.
|
||||
* The 3d system should be considered rewritten.
|
||||
|
||||
General/Core:
|
||||
enh: Convert to c++
|
||||
enh: Add functions for a lid open/close. Holding key (default "Backspace" in Windows port) while game is freeze/non freeze. [CrazyMax]
|
||||
enh: Add secure area decryption from ndstool [zeromus]
|
||||
enh: Change savestate code to support loosely bound chunks and more easily other parts of the emu (GE, GPU).
|
||||
The savestate format is changed, but from now on it is in principle more resilient
|
||||
(though it will continue to break as we tinker with the internals) [zeromus]
|
||||
enh: Added SSE2 optimizations for matrices. Since we now make an SSE2 build, more optimizations can be made. [CrazyMax]
|
||||
enh: Add a preliminary GUI hud system [CrazyMax,zeromus]
|
||||
|
||||
CPU/MMU:
|
||||
bug: Many fixes in IPC and GE FIFOs. Fixes freezes in NSMB, dsracing, and others. [CrazyMax,luigi__,shash]
|
||||
bug: Fix ARM instructions SBC and RSC (likewise SBC in thumb) [normatt]
|
||||
bug: Fixed Thumb LDMIA (fixes ingame Dead'n'Furious) [shash]
|
||||
bug: Fix repeating DMA (fixes NSMB parallax BG) [zeromus]
|
||||
bug: Proper handling for unaligned CPU accesses [luigi__]
|
||||
bug: Proper handling for undefined instruction exceptions [Salva Peiró]
|
||||
bug: correctly return vram control register values (fixes homebrew 3d games) [zeromus]
|
||||
enh: Remove 16MB of WRAM at 0x01****** from arm9. Mapped to unused instead. Nobody knows what this was. [zeromus]
|
||||
enh: Changed instruction execution to 16 at a time blocks (tested and stable) [shash]
|
||||
|
||||
Hardware:
|
||||
bug: Newer and better sqrt and div emulation; makes SM64DS playable [luigi__,shash,zeromus]
|
||||
bug: Add preliminary RTC implementations [CrazyMax]
|
||||
enh: Add cosine interpolation in the SPU (conditionally compiled) [zeromus,luigi__]
|
||||
enh: Experimental: always one silent non-mixing SPU core at 44.1khz synched with emu, for more precision.
|
||||
The audible core runs with the host, causing music to slow down but not tear or pitch bend. [zeromus]
|
||||
|
||||
Graphics:
|
||||
- Overhaul 3d:
|
||||
. Move entire GE to core emu.
|
||||
. Move OpenGL renderer to emu core for optional use by platforms, removing ogl_collector. Now every platform shares the same 3d code.
|
||||
. Reorganize 3d code to defer rendering to after 3d vblank. Eliminates tearing, and texturing artifacts. [zeromus]
|
||||
. Add optional fragment shading pipeline (more precision) [luigi__]
|
||||
. Move lighting model to software instead of using opengl's fixed function model [zeromus]
|
||||
. Render shadow volumes; toon shading and highlight table [zeromus, luigi__]
|
||||
. Added texture caching! big speed up. [CrazyMax]
|
||||
|
||||
bug: Many assorted tweaks and improvements to 3d and 2d precision [zeromus,CrazyMax,luigi__]
|
||||
bug: Fixes to GE: command unpacking, projection and pos-vector mode matrix handling, mult and load commands [zeromus]
|
||||
bug: Fix a bug in texture transformation mode 1 [zeromus]
|
||||
bug: Fixed GPU rendering bugs in sprites and BG [CrazyMax]
|
||||
bug: Fixes to texture conversion [CrazyMax,zeromus]
|
||||
bug: Fixes in capture display (no blinking in many games with dual 3D) [CrazyMax]
|
||||
bug: Fixes in master brightness (this fixes some games with black screens) [CrazyMax]
|
||||
bug: Fixes in screen, backdrop, and sprite blending [luigi__]
|
||||
bug: Changed clear depths and how depth initial values are calculated (fixes SM64DS skybox, Castlevania) [shash,lugi__]
|
||||
bug: Add 3d layer h-scrolling [zeromus]
|
||||
bug: Added transparency and fixed material alpha support and alpha testing on the 3D core [shash]
|
||||
bug: Rewrite VRAM mapping control and rendering (more accurate) [CrazyMax,luigi__]
|
||||
|
||||
bug: convert colors to opengl better to prevent alpha=31 polys from being ever so slightly transparent [zeromus]
|
||||
enh: Add MMU->GPU signal for when vram mappings change to function as a texture cache invalidate signal [zeromus]
|
||||
enh: Make matrix 4x4 multiply routines use W-coordinate; carry w coord through pipeline [zeromus]
|
||||
|
||||
Mac OS X port:
|
||||
bug: Fixed: Filenames and paths with unicode characters now work. [Jeff]
|
||||
bug: Fixed: Load state from file button works again. [Jeff]
|
||||
enh: Save State panel now pauses emulation while the file selection box is open. [Jeff]
|
||||
bug: Fixed: Frozen video output (and/or messed 3d emulation) after loading a state. [Jeff]
|
||||
bug: Added option to load the most recent file upon launching the program. [Jeff]
|
||||
enh: Added French translation (thanks to Pierre Rudloff). [Jeff]
|
||||
enh: Added basic key mapping configuration to application preferences (thanks to Julio Gorg). [Jeff]
|
||||
enh: Added keyboard shortcuts for Execute, Pause and Reset command (thanks to Julio Gorg). [Jeff]
|
||||
enh: Default key mappings are no longer case sensitive. [Jeff]
|
||||
enh: Added ability to limit speed. [Jeff]
|
||||
enh: Fixed: Video output should work on software-only 3D renderers. [Jeff]
|
||||
|
||||
Windows port:
|
||||
bug: Fix a race condition in NDS_3D_Reset and NDS_glInit [zeromus]
|
||||
bug: Fix the buggy auto frameskip logic which made the emu slow to a crawl. Now it runs fast! [zeromus]
|
||||
bug: Fix resizing, rotate & aspect ration of main window. [CrazyMax,_zeromus]
|
||||
bug: Remove multithreading from user interface after finding several synchronization issues [zeromus]
|
||||
enh: recent roms menu [luigi_]
|
||||
enh: Changed graphics render core to DirectDraw (work faster) [CrazyMax]
|
||||
enh: Add an arm9 cpu load average calculator similar to no$. but I dont think it works right. [zeromus]
|
||||
enh: Rewrite all debug tools (autoupdate works now) [CrazyMax]
|
||||
enh: Rewrite input core & replace config input dialog [CrazyMax]
|
||||
enh: Add AVI output [zeromus]
|
||||
enh: Add pause toggle and frame advance hotkeys [adelikat]
|
||||
enh: Add frame counter display and hud messages framework [adelikat]
|
||||
enh: Main window remembers position, size, and a few other emu preferences [adelikat]
|
||||
enh: Removed directx sdk dependency for easier building. [zeromus]
|
||||
enh: Savestate doesnt unpause emu if it is already paused [adelikat]
|
||||
|
||||
0.7.3 -> 0.8
|
||||
Cocoa:
|
||||
- Save State As function now works. [Jeff B]
|
||||
- Recent Items menu now works. [Jeff B]
|
||||
- Opening NDS files from Finder now works. [Jeff B]
|
||||
- Added screenshot feature. [Jeff B]
|
||||
- Added preferences. [Jeff B]
|
||||
- Many more strings are translatable now. [Jeff B]
|
||||
- Default screen color is black (better represents being "off" and easier on eyes at night). [Jeff B]
|
||||
- Added sound. [Jeff B]
|
||||
- Now is a universal binary. [Jeff B]
|
||||
- Leopard resolution icon added. [Jeff B]
|
||||
- Added a Japanese translation. [Jeff B]
|
||||
- Added an optional status bar (resize handle no longer overlaps screen). [Jeff B]
|
||||
- New ROM Info and About DeSmuME windows have been added. [Jeff B]
|
||||
- Fixed several bugs in window resizing. [Jeff B]
|
||||
- Added FAT image support for homebrew games (thanks to TypeError). [Jeff B]
|
||||
- Key config can be changed on the command line. Save/load hotkeys changed (so expose doesn't override). [Jeff B]
|
||||
- Key bindings may work better on non-US keyboards now (needs testing). [Jeff B]
|
||||
general:
|
||||
- Encapsulate GDB debug stub to avoid certain problems [shash]
|
||||
- Fixed CPU LD*/ST* bugs [shash]
|
||||
- Fixed New SMB mini-games freeze [shash]
|
||||
- Fixed possible segfault in ROMReader on ia64 and amd64. [evilynux]
|
||||
- Fixed a crash bug with 2D background corrupting memory [shash]
|
||||
- Flag check optimization [carlo_bramini]
|
||||
- Applied some endian fixes in GPU (thanks to Phazz) [Jeff B]
|
||||
gtk-glade:
|
||||
- Added DeSmuME version in about dialog. [evilynux]
|
||||
- Updated website url in about dialog. [evilynux]
|
||||
- Added Brazilian Portuguese translation by Dreampeppers99. [evilynux]
|
||||
- Better desktop menu entry following FreeDesktop specifications. [evilynux]
|
||||
gtk:
|
||||
- Updated website url in about dialog. [evilynux]
|
||||
- Better desktop menu entry following FreeDesktop specifications. [evilynux]
|
||||
windows port:
|
||||
- Added an "about" box [shash]
|
||||
- DirectInput control interface with joystick support [CrazyMax]
|
||||
- Matrix and Light viewer [Acid Burn]
|
||||
|
||||
0.7.2 -> 0.7.3
|
||||
gtk-glade:
|
||||
- Full localization using intltool/gettext. [evilynux]
|
||||
general:
|
||||
- Added a README.TRANSLATION documenting the localization process. [evilynux]
|
||||
MacOS X:
|
||||
- Initial version of the Mac interface added. [Jeff B]
|
||||
|
||||
0.7.1 -> 0.7.2
|
||||
spu:
|
||||
- big endian fixes. [cyberwarriorx]
|
||||
gpu:
|
||||
- big endian fixes. [marcus_c]
|
||||
gtk-glade:
|
||||
- opengl improvements. [masscat]
|
||||
general:
|
||||
- Added support for setting NDS firmware language value. [masscat]
|
||||
- Function added for setting firmware language. [masscat]
|
||||
- Mac/msys compilation fixes. [cyberwarriorx]
|
||||
- Fix compilation when pkg-config macros are not available [evilynux]
|
||||
|
||||
0.7.0 -> 0.7.1
|
||||
general:
|
||||
- Added GDB debugger stub [masscat]
|
||||
- Added new/different GBAMP CFlash image reader/writer [masscat]
|
||||
gpu:
|
||||
- Major speedup to the 2D core [shash]
|
||||
gtk-glade:
|
||||
- Added command line options. [masscat]
|
||||
- Added FPS limiter [masscat]
|
||||
cli:
|
||||
- Added command line options. [masscat]
|
||||
- Added FPS limiter [masscat]
|
||||
- Added option to use OpenGl to render window (allows resizing). [masscat]
|
||||
windows port:
|
||||
- Added command line options. [masscat]
|
||||
- Added multiple language support [cyberwarriorx]
|
||||
- Added Danish language translation [thomas-2007]
|
||||
|
||||
0.6.0 -> 0.7.0
|
||||
general:
|
||||
- Added support for *.duc files [cyberwarriorx]
|
||||
gpu:
|
||||
- Added support for sprite rotation/scaling [shash]
|
||||
- Added support for the 3D core (openGL and null plugins) [shash]
|
||||
windows port:
|
||||
- A bunch of fixes [Dmitry Krutskih]
|
||||
- Fixed a bug in sound that was causing it to still not work for some
|
||||
people [cyberwarriorx]
|
||||
gtk:
|
||||
- Added 3D emulation
|
||||
- Added command line options.
|
||||
- Added option to use OpenGL to render window (allows resizing).
|
||||
gtk-glade:
|
||||
- Added 3D emulation
|
||||
|
||||
0.5.0 -> 0.6.0
|
||||
general:
|
||||
- Added zipped (based on zziplib) and gzipped (based on zlib) rom support.
|
||||
arm:
|
||||
- Added relocation interrupt vector.
|
||||
- Added region access right checks.
|
||||
- Enabled LDC/STC instructions.
|
||||
- Fixed powersave (cp15) IRQ wait.
|
||||
- Fixed MOV instructions
|
||||
gpu:
|
||||
- Added special color effects.
|
||||
- Added windowing feature.
|
||||
- Fixed transparent direct color backgrounds.
|
||||
- Fixed disabled sprites showing.
|
||||
- Fixed 8/32 bit access to gpu registers.
|
||||
- Fixed missing backgrounds
|
||||
- Support for master brightness
|
||||
wifi:
|
||||
- Added RF chip interface.
|
||||
- Added BB chip interface.
|
||||
windows port:
|
||||
- Fixed address calculation in disassembler.
|
||||
- Added Force Maintain Ratio option for window stretching
|
||||
linux port (cli, gtk and gtk-glade):
|
||||
all:
|
||||
- Added joystick support.
|
||||
- Fixed X and Y buttons.
|
||||
gtk-glade:
|
||||
- Added joystick configuration.
|
||||
- Improved I/O registers viewer tool.
|
||||
- Added save and load states support.
|
||||
|
||||
0.3.3 -> 0.5.0
|
||||
arm:
|
||||
- Fixed MSR with immediate value opcode.
|
||||
- Fixed LSR_0 thumb opcode (C flag is correctly set now).
|
||||
- Fixed LDR*/STR* opcodes.
|
||||
- Fixed unaligned memory access on THUMB Core.
|
||||
- Added relocating SWI routines.
|
||||
bios:
|
||||
- Added decompression functions.
|
||||
- Added GetPitchTable function.
|
||||
- Added GetVolumeTable function.
|
||||
- Added GetCRC16 function.
|
||||
- Added experimental SoundBias function.
|
||||
- Added GetSineTable function.
|
||||
cart:
|
||||
- Added CompactFlash/FAT emulation.
|
||||
- Added Get ROM chip ID Cartridge command.
|
||||
gpu:
|
||||
- Added framebuffer emulation.
|
||||
- Fixed a bug in GPU (xfin could be greater than LG causing a segfault).
|
||||
- Added support for Display Mode 0(Display Off).
|
||||
- Added the basic framework for Display Mode 3(Display from Main RAM).
|
||||
spu:
|
||||
- Added sound emulation.
|
||||
- Added sound core system.
|
||||
- Added WAV write core.
|
||||
- Added dummy core.
|
||||
- Added Direct Sound core.
|
||||
linux port:
|
||||
- Added GTK+ GUI.
|
||||
- Added command line interface.
|
||||
- Added stylus and arm9 keypad support in CLI version.
|
||||
- Added FPS display.
|
||||
- Added basic frameskip.
|
||||
windows port:
|
||||
- Fixed a bug when displaying a ROM's information.
|
||||
- Added key configuration.
|
||||
- Removed the debug key.
|
||||
- Added new experimental auto frameskip/frame limit code.
|
||||
- Added sound settings dialog.
|
||||
- Added a few menu options for accessing the website, forums, and for
|
||||
submitting bugs.
|
||||
general:
|
||||
- Rewrote code in C.
|
||||
- Fixed warnings.
|
||||
- Used defines and typedef's to make things more portable and easier to
|
||||
read.
|
||||
- Added autotools stuff.
|
||||
- Changes to logging system.
|
||||
- Added screenshot function.
|
||||
- Translated most french to english.
|
||||
- Added savestate support.
|
||||
- Added firmware reading support(needs work).
|
||||
- Added Backup Memory support with autodetection.
|
||||
- Fixed some endianess issues.
|
||||
- Fixed things so Visual C++ can compile code.
|
||||
- Added bsd support.
|
||||
- Reworked ROM loading so you can load a different rom without any problems.
|
||||
- Finished NDS_Reset. Now the emulation can be reset even while running.
|
|
@ -1,97 +0,0 @@
|
|||
DeSmuME
|
||||
_________________________________________
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2022 DeSmuME team
|
||||
Last Updated: May 23, 2022
|
||||
|
||||
Contents:
|
||||
1) About ................................................................... 14
|
||||
2) Credits ................................................................. 59
|
||||
3) Contact Information ..................................................... 72
|
||||
4) License ................................................................. 82
|
||||
|
||||
|
||||
1) About ______________________________________________________________________
|
||||
|
||||
DeSmuME is software that allows you to emulate a Nintendo DS system. Think of
|
||||
it as a Swiss-Army knife for Nintendo DS emulation, giving you access to many
|
||||
powerful tools for testing DS features, from viewing ROM properties to managing
|
||||
Action Replay cheats. And best of all, this software is completely free and
|
||||
open-source.
|
||||
|
||||
For information on how to install or operate DeSmuME for your operating system,
|
||||
please see the README file that should be present with your installation.
|
||||
|
||||
Port-specific README files:
|
||||
* README.LIN for the Linux ports
|
||||
* README.WIN for the Windows port
|
||||
* README.MAC for the Macintosh port
|
||||
|
||||
Note that each DeSmuME port may have a different feature set from another port.
|
||||
You may see more feature parity between ports over time as we continue
|
||||
developing DeSmuME.
|
||||
|
||||
You can find our documentation on our online Wiki page. The major pages of
|
||||
interest are:
|
||||
|
||||
* Official Documentation: https://wiki.desmume.org/index.php?title=Main_Page
|
||||
|
||||
This is the main Wiki page that contains all of our official documentation.
|
||||
|
||||
* Manuals: https://wiki.desmume.org/index.php?title=Manual
|
||||
|
||||
The manuals contain detailed information about how to operate DeSmuME for each
|
||||
port.
|
||||
|
||||
* FAQ: https://wiki.desmume.org/index.php?title=Faq
|
||||
|
||||
The Frequently Asked Questions (FAQ) page has a lot of useful general
|
||||
information about DeSmuME. Do note that some of the information may be platform
|
||||
specific, and may not directly apply to your version of DeSmuME.
|
||||
|
||||
* Build Instructions:
|
||||
https://wiki.desmume.org/index.php?title=Installing_DeSmuME_from_source
|
||||
|
||||
This page contains detailed port-specific instructions about how to make your
|
||||
own build of DeSmuME directly from the source code.
|
||||
|
||||
|
||||
2) Credits ____________________________________________________________________
|
||||
|
||||
See the AUTHORS file for list of DeSmuME team members.
|
||||
|
||||
Special thanks go to:
|
||||
|
||||
* yopyop (original author of DeSmuME),
|
||||
for releasing the source code of this great emulator.
|
||||
|
||||
* Martin Korth (author of GBATEK),
|
||||
for his well-written Gameboy Advance and Nintendo DS documentation.
|
||||
|
||||
|
||||
3) Contact Information ________________________________________________________
|
||||
|
||||
Official Website: https://desmume.org
|
||||
Public Forum: https://forums.desmume.org
|
||||
Developer Chat: irc://irc.libera.chat:6697/desmume
|
||||
Source & Bug Reports: https://github.com/TASEmulators/desmume
|
||||
|
||||
Please don't ask for ROMs, BIOS files, or any other copyrighted stuff.
|
||||
|
||||
|
||||
4) License ____________________________________________________________________
|
||||
|
||||
This file 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 file 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 software. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
* See the GNU General Public License details in COPYING.
|
|
@ -1,441 +0,0 @@
|
|||
DeSmuME DLL/SO
|
||||
|
||||
DeSmuME is written in C++ using the SDL libraries.
|
||||
|
||||
* http://www.libsdl.org/
|
||||
|
||||
|
||||
Reference Usage
|
||||
===============
|
||||
A Python library using the DLL/SO interface can be found at
|
||||
`https://github.com/SkyTemple/py-desmume/blob/master/desmume/emulator.py`.
|
||||
|
||||
|
||||
Build Linux & Mac
|
||||
=================
|
||||
|
||||
DeSmuME uses the Meson build system to the shared object under Linux and MacOS:
|
||||
|
||||
* https://mesonbuild.com/
|
||||
|
||||
To build, first cd to src/frontend/interface and then run `meson build`
|
||||
|
||||
Then build the library by running `ninja -C build`
|
||||
|
||||
It will generate a shared object under `build/libdesmume.so`.
|
||||
|
||||
Build Windows
|
||||
=============
|
||||
To build open and build the Visual Studio solution at
|
||||
`src/frontend/interface/windows/DeSmuME_Interface.sln`.
|
||||
|
||||
|
||||
Interface
|
||||
=========
|
||||
The interface has the following API functions exposed in the DLL/SO.
|
||||
|
||||
|
||||
Emulator key indices
|
||||
--------------------
|
||||
Internal ID numbers for emulator keys (used for some functions):
|
||||
|
||||
#define KEY_NONE 0
|
||||
#define KEY_A 1
|
||||
#define KEY_B 2
|
||||
#define KEY_SELECT 3
|
||||
#define KEY_START 4
|
||||
#define KEY_RIGHT 5
|
||||
#define KEY_LEFT 6
|
||||
#define KEY_UP 7
|
||||
#define KEY_DOWN 8
|
||||
#define KEY_R 9
|
||||
#define KEY_L 10
|
||||
#define KEY_X 11
|
||||
#define KEY_Y 12
|
||||
#define KEY_DEBUG 13
|
||||
#define KEY_BOOST 14
|
||||
#define KEY_LID 15
|
||||
|
||||
|
||||
int desmume_init(void);
|
||||
-----------------------
|
||||
Initializes the emulator. Needs to be called before any other API functions.
|
||||
|
||||
|
||||
void desmume_free(void);
|
||||
------------------------
|
||||
Destroys the emulator, needs to be called to free memory. After this no API
|
||||
functions must be called.
|
||||
|
||||
|
||||
void desmume_set_language(unsigned char language);
|
||||
--------------------------------------------------
|
||||
Sets the firmware language. Valid values:
|
||||
0 = Japanese, 1 = English, 2 = French, 3 = German, 4 = Italian, 5 = Spanish
|
||||
|
||||
|
||||
int desmume_open(const char *filename);
|
||||
---------------------------------------
|
||||
Loads a ROM into the emulator. Returns 0 on success and another number on error.
|
||||
|
||||
|
||||
void desmume_set_savetype(int type);
|
||||
------------------------------------
|
||||
Sets the type of SRAM save. 0 for auto.
|
||||
|
||||
|
||||
void desmume_pause(void);
|
||||
-------------------------
|
||||
Pauses the emulator.
|
||||
|
||||
|
||||
void desmume_resume(void);
|
||||
--------------------------
|
||||
Resumes the emulator.
|
||||
|
||||
|
||||
void desmume_reset(void);
|
||||
-------------------------
|
||||
Resets the emulator and resumes.
|
||||
|
||||
|
||||
BOOL desmume_running(void);
|
||||
---------------------------
|
||||
Returns 0 if the emulator is not running and 1 if it is.
|
||||
|
||||
|
||||
void desmume_skip_next_frame(void);
|
||||
-----------------------------------
|
||||
Instructs the emulator to not draw the next frame.
|
||||
|
||||
|
||||
void desmume_cycle(BOOL with_joystick);
|
||||
---------------------------------------
|
||||
Runs one loop iteration (tick) of the emulation.
|
||||
The parameter must be 1 if `desmume_input_joy_init` was called before and
|
||||
joystick input should be processed
|
||||
and 0 otherwise.
|
||||
|
||||
|
||||
int desmume_sdl_get_ticks();
|
||||
----------------------------
|
||||
Get the current tick number as reported by SDL.
|
||||
|
||||
|
||||
void desmume_draw_opengl(GLuint *texture);
|
||||
------------------------------------------
|
||||
Only available if INCLUDE_OPENGL_2D was defined.
|
||||
|
||||
Draws the current tick onto the provided OpenGL texture.
|
||||
|
||||
|
||||
BOOL desmume_has_opengl();
|
||||
--------------------------
|
||||
Returns whether or not OpenGL support is available.
|
||||
|
||||
|
||||
int desmume_draw_window_init(BOOL auto_pause, BOOL use_opengl_if_possible);
|
||||
---------------------------------------------------------------------------
|
||||
Opens an SDL-powered window for drawing the emulator on and processing input.
|
||||
If `auto_pause` is >0, the emulator is paused when the window is not in focus.
|
||||
If `use_opengl_if_possible` is >0, OpenGL-based drawing is used
|
||||
if OpenGL is available.
|
||||
|
||||
|
||||
void desmume_draw_window_input();
|
||||
---------------------------------
|
||||
Process user input on the SDL window for this tick.
|
||||
Requires `desmume_draw_window_init` to be called first.
|
||||
|
||||
|
||||
void desmume_draw_window_frame();
|
||||
---------------------------------
|
||||
Draw the SDL window for this tick. Requires `desmume_draw_window_init` to be called first.
|
||||
|
||||
|
||||
BOOL desmume_draw_window_has_quit();
|
||||
------------------------------------
|
||||
Returns 1 if the SDL window was closed by the user and 0 if not.
|
||||
Requires `desmume_draw_window_init` to be called first.
|
||||
|
||||
|
||||
void desmume_draw_window_free();
|
||||
--------------------------------
|
||||
Destroys the SDL window and frees memory. Requires `desmume_draw_window_init` to be called first.
|
||||
No other SDL window functions must be called after this.
|
||||
|
||||
|
||||
unsigned short *desmume_draw_raw();
|
||||
-----------------------------------
|
||||
Returns the content of the raw framebuffer of the emulator.
|
||||
|
||||
|
||||
void desmume_draw_raw_as_rgbx(unsigned char *buffer);
|
||||
-----------------------------------------------------
|
||||
Fills the provided buffer as an RGBx formatted version of the emulator's framebuffer.
|
||||
|
||||
|
||||
void desmume_savestate_clear();
|
||||
-------------------------------
|
||||
Deletes all savestates stored on slots.
|
||||
|
||||
|
||||
BOOL desmume_savestate_load(const char *file_name);
|
||||
---------------------------------------------------
|
||||
Loads a savestate from a file. Returns 1 on success, 0 on failure.
|
||||
|
||||
|
||||
BOOL desmume_savestate_save(const char *file_name);
|
||||
---------------------------------------------------
|
||||
Saves a savestate to a file. Returns 1 on success, 0 on failure.
|
||||
|
||||
|
||||
void desmume_savestate_scan();
|
||||
------------------------------
|
||||
Scans the savestate slots for data. Required for `desmume_savestate_slot_exists` and
|
||||
`desmume_savestate_save_slot` to return the correct data.
|
||||
|
||||
|
||||
void desmume_savestate_slot_load(int index);
|
||||
--------------------------------------------
|
||||
Loads the savestate from slot `index`.
|
||||
|
||||
|
||||
void desmume_savestate_slot_save(int index);
|
||||
--------------------------------------------
|
||||
Saves the current state to the savestate in slot `index`.
|
||||
|
||||
|
||||
BOOL desmume_savestate_slot_exists(int index);
|
||||
----------------------------------------------
|
||||
Returns whether or not the savetstate at slot `index` exists.
|
||||
|
||||
|
||||
char* desmume_savestate_slot_date(int index);
|
||||
---------------------------------------------
|
||||
Returns the date (as string) that the savestate at slot `index` was saved.
|
||||
|
||||
|
||||
BOOL desmume_gpu_get_layer_main_enable_state(int layer_index);
|
||||
--------------------------------------------------------------
|
||||
Returns whether or not the layer with the given index for the main GPU is enabled.
|
||||
|
||||
|
||||
BOOL desmume_gpu_get_layer_sub_enable_state(int layer_index);
|
||||
-------------------------------------------------------------
|
||||
Returns whether or not the layer with the given index for the sub GPU is enabled.
|
||||
|
||||
|
||||
void desmume_gpu_set_layer_main_enable_state(int layer_index, BOOL the_state);
|
||||
------------------------------------------------------------------------------
|
||||
Disables or enables the layer with the given index for the main GPU.
|
||||
Disabled layers are not drawn.
|
||||
|
||||
|
||||
void desmume_gpu_set_layer_sub_enable_state(int layer_index, BOOL the_state);
|
||||
-----------------------------------------------------------------------------
|
||||
Disables or enables the layer with the given index for the sub GPU.
|
||||
Disabled layers are not drawn.
|
||||
|
||||
|
||||
int desmume_volume_get();
|
||||
-------------------------
|
||||
Returns the current emulator volume in a range from 0-100.
|
||||
|
||||
|
||||
void desmume_volume_set(int volume);
|
||||
------------------------------------
|
||||
Sets the current emulator volume in a range from 0-100.
|
||||
|
||||
|
||||
unsigned char desmume_memory_read_byte(int address);
|
||||
signed char desmume_memory_read_byte_signed(int address);
|
||||
unsigned short desmume_memory_read_short(int address);
|
||||
signed short desmume_memory_read_short_signed(int address);
|
||||
unsigned long desmume_memory_read_long(int address);
|
||||
signed long desmume_memory_read_long_signed(int address);
|
||||
-----------------------------------------------------------
|
||||
Read the emulated memory at `address` with different sizes and sign settings.
|
||||
|
||||
|
||||
void desmume_memory_write_byte(int address, unsigned char value);
|
||||
void desmume_memory_write_short(int address, unsigned short value);
|
||||
void desmume_memory_write_long(int address, unsigned long value);
|
||||
-------------------------------------------------------------------
|
||||
Write the value `value` as bytes/shorts/longs to `address` in the emulated memory.
|
||||
|
||||
|
||||
int desmume_memory_read_register(char* register_name);
|
||||
void desmume_memory_write_register(char* register_name, long value);
|
||||
--------------------------------------------------------------------
|
||||
Read or write the value of the specified register.
|
||||
|
||||
Valid register names:
|
||||
- arm9.r0 - arm9.r15 : Registers r0 - r15 on the ARM9 processor.
|
||||
- arm9.cpsr
|
||||
- arm9.spsr
|
||||
- arm7.r0 - arm7.r15 : Registers r0 - r15 on the ARM7 processor.
|
||||
- arm7.cpsr
|
||||
- arm7.spsr
|
||||
|
||||
`main` may be used as an alias for `arm9` and `sub` for `arm7`.
|
||||
If the prefix is omitted, `arm9` is used.
|
||||
|
||||
|
||||
typedef BOOL (*memory_cb_fnc)(unsigned int, int);
|
||||
void desmume_memory_register_write(int address, int size, memory_cb_fnc cb);
|
||||
void desmume_memory_register_read(int address, int size, memory_cb_fnc cb);
|
||||
void desmume_memory_register_exec(int address, int size, memory_cb_fnc cb);
|
||||
----------------------------------------------------------------------------
|
||||
Register a callback function to execute when the emulator writes/reads or executes
|
||||
an instruction at `address`. `size` is the size in bytes to monitor for that location
|
||||
(should always be 2 to exec).
|
||||
|
||||
The passed callback function gets to arguments when called. The first argument
|
||||
is the address the callback was triggered for, the second the size.
|
||||
|
||||
Only one callback can be specified per address and type (write/read/exec).
|
||||
Pass 0 instead for `cb` to unregister previously registered callbacks.
|
||||
|
||||
|
||||
void desmume_screenshot(char *screenshot_buffer);
|
||||
-------------------------------------------------
|
||||
Fills the 98304*3 bytes long `screenshot_buffer` with an RGB snapshot of
|
||||
the framebuffer.
|
||||
|
||||
|
||||
BOOL desmume_input_joy_init(void);
|
||||
----------------------------------
|
||||
Initialize SDL joypad handling. Returns 1 on success, 0 otherwise.
|
||||
Must be called before any other joypad operation.
|
||||
|
||||
void desmume_input_joy_uninit(void);
|
||||
------------------------------------
|
||||
Destroys the joypad functionality. After calling this, no other joypad
|
||||
operations must be called.
|
||||
|
||||
|
||||
unsigned short desmume_input_joy_number_connected(void);
|
||||
--------------------------------------------------------
|
||||
Returns the number of connected joypads.
|
||||
|
||||
|
||||
unsigned short desmume_input_joy_get_key(int index);
|
||||
----------------------------------------------------
|
||||
Returns the joypad key assigned to the specified emulator key.
|
||||
|
||||
|
||||
unsigned short desmume_input_joy_get_set_key(int index);
|
||||
--------------------------------------------------------
|
||||
Pause and wait for the user to press a button on a joypad.
|
||||
This button will be assigned to the specified emulator key.
|
||||
|
||||
void desmume_input_joy_set_key(int index, int joystick_key_index);
|
||||
------------------------------------------------------------------
|
||||
Sets the emulator key `index` to the specified joypad key `joystick_key_index`.
|
||||
|
||||
|
||||
void desmume_input_keypad_update(unsigned short keys);
|
||||
------------------------------------------------------
|
||||
Update the currently pressed emulator keys. This is a bitmask where each bit
|
||||
is one of the emulator's keys. See:
|
||||
|
||||
#define ADD_KEY(keypad,key) ( (keypad) |= (key) )
|
||||
#define RM_KEY(keypad,key) ( (keypad) &= ~(key) )
|
||||
#define KEYMASK_(k) (1 << (k))
|
||||
|
||||
|
||||
unsigned short desmume_input_keypad_get(void);
|
||||
----------------------------------------------
|
||||
Get the currently pressed emulator keys. This is a bitmask where each bit is
|
||||
one of the emulator's keys.
|
||||
|
||||
|
||||
void desmume_input_set_touch_pos(unsigned short x, unsigned short y);
|
||||
---------------------------------------------------------------------
|
||||
Register a touch input at the specified location on the bottom screen.
|
||||
Use `desmume_input_release_touch` to release.
|
||||
|
||||
|
||||
void desmume_input_release_touch();
|
||||
-----------------------------------
|
||||
Release the current touch.
|
||||
|
||||
|
||||
BOOL desmume_movie_is_active();
|
||||
BOOL desmume_movie_is_recording();
|
||||
BOOL desmume_movie_is_playing();
|
||||
BOOL desmume_movie_is_finished();
|
||||
----------------------------------
|
||||
Returns whether the movie system is active/recording/playing/finished.
|
||||
|
||||
|
||||
int desmume_movie_get_length();
|
||||
-------------------------------
|
||||
Returns the size of the movie records.
|
||||
|
||||
|
||||
char *desmume_movie_get_name();
|
||||
-------------------------------
|
||||
Returns the name of the movie.
|
||||
|
||||
|
||||
int desmume_movie_get_rerecord_count();
|
||||
---------------------------------------
|
||||
Returns the current rerecount counter value of the movie.
|
||||
|
||||
|
||||
void desmume_movie_set_rerecord_count(int count);
|
||||
-------------------------------------------------
|
||||
Sets the current rerecount counter value of the movie.
|
||||
|
||||
|
||||
BOOL desmume_movie_get_readonly();
|
||||
----------------------------------
|
||||
Returns 1 if the movie can only be read, 0 if it can also be modified.
|
||||
|
||||
|
||||
void desmume_movie_set_readonly(BOOL state);
|
||||
--------------------------------------------
|
||||
Change whether or not the movie is only read-only (can not be modified).
|
||||
|
||||
|
||||
// Returns NULL on success, error message otherwise.
|
||||
const char *desmume_movie_play(const char *file_name);
|
||||
------------------------------------------------------
|
||||
Play the movie from the file `file_name`. Returns NULL on success, otherwise
|
||||
an error message.
|
||||
|
||||
|
||||
enum START_FROM {START_BLANK = 0, START_SRAM, START_SAVESTATE};
|
||||
struct SimpleDate {int year; int month; int day; int hour; int minute; int second; int millisecond;};
|
||||
void desmume_movie_record_simple(const char *save_file_name, const char *author_name);
|
||||
void desmume_movie_record(const char *save_file_name, const char *author_name,
|
||||
START_FROM start_from, const char* sram_file_name);
|
||||
void desmume_movie_record_from_date(const char *save_file_name, const char *author_name,
|
||||
START_FROM start_from, const char* sram_file_name,
|
||||
SimpleDate date);
|
||||
----------------------------------------------------------------------------------------
|
||||
Record a movie.
|
||||
|
||||
- `save_file_name`: The name of the file to save the movie to.
|
||||
- `author_name`: The name of the author of the movie.
|
||||
- `start_from`: Where to start from:
|
||||
- START_BLANK (0): Reset the emulator, start without SRAM (no savefile).
|
||||
- START_SRAM (1): Reset the emulator, start using the SRAM loaded from `sram_file_name`.
|
||||
- START_SAVESTATE (2): Not supported.
|
||||
- `sram_file_name`: Name of the SRAM to load, if `start_from` == 1. NULL otherwise.
|
||||
- `date`: Date to set the emulated device's clock to.
|
||||
|
||||
|
||||
void desmume_movie_replay();
|
||||
----------------------------
|
||||
Restart playback of the current movie.
|
||||
|
||||
|
||||
void desmume_movie_stop();
|
||||
----------------------------
|
||||
Stop playback/recording of the current movie.
|
||||
|
||||
|
||||
Visit us on the web at http://www.desmume.org
|
|
@ -1,72 +0,0 @@
|
|||
DeSmuME
|
||||
|
||||
DeSmuME is written in C++ using the GTK+ and SDL2 libraries.
|
||||
|
||||
* https://gtk.org/
|
||||
* https://libsdl.org/
|
||||
|
||||
It uses the Meson build system to build the GTK+3 and SDL2 port:
|
||||
|
||||
* https://mesonbuild.com/
|
||||
|
||||
... and the autotools build system for the GTK+2 and SDL2 port.
|
||||
|
||||
to build GTK+2 or SDL2 frontend with autotools, cd to src/frontend/posix, then
|
||||
|
||||
autoreconf -i (or alternatively: ./autogen.sh)
|
||||
./configure
|
||||
make -jN (where N is the number of CPU cores to use).
|
||||
|
||||
|
||||
DeSmuME provides another interface based on libglade, to use
|
||||
, you'll need glade:
|
||||
|
||||
* http://glade.gnome.org/
|
||||
|
||||
To build, first cd to src/frontend/posix and run
|
||||
`meson build --buildtype=release`
|
||||
|
||||
Then build the program by running `ninja -C build`
|
||||
|
||||
It will generate three programs:
|
||||
1) "desmume" in the "build/gtk" directory;
|
||||
2) "desmume-cli" in the "build/cli" directory.
|
||||
|
||||
If glade is installed on your system, you'll get a third
|
||||
binary:
|
||||
|
||||
3) "desmume-glade" in the "build/gtk-glade" directory.
|
||||
|
||||
You can even type "ninja -C build install" to install those programs on
|
||||
your system (in /usr/local/ by default); then uninstalling is
|
||||
done by typing "ninja -C build uninstall".
|
||||
|
||||
For more information on the available commandline options,
|
||||
check the other README files which will be more up to date.
|
||||
|
||||
The following options specially are available on these posix ports:
|
||||
|
||||
--disable-limiter Disables the 60 fps limiter
|
||||
--soft-convert Use software colour conversion during OpenGL
|
||||
screen rendering. May produce better or worse
|
||||
frame rates depending on hardware.
|
||||
|
||||
The following options specially are available on the Gtk+ port:
|
||||
|
||||
--opengl-2d Enables using OpenGL for screen rendering
|
||||
--disable-sound Disables the sound emulation
|
||||
--disable-3d Disables the 3D emulation
|
||||
|
||||
The following options specially are available on the CLI port:
|
||||
|
||||
--opengl-2d Enables using OpenGL for screen rendering
|
||||
--disable-sound Disables the sound emulation
|
||||
|
||||
NOTE:
|
||||
The Gtk+ and Glade builds use gtkGLext to handle the OpenGL
|
||||
rendering and contexts. You may get improved performance by
|
||||
also passing the argument --gdk-gl-force-indirect. This has
|
||||
been seen to improve things for Nvidia based graphics cards
|
||||
under Linux.
|
||||
|
||||
Visit us on the web at http://www.desmume.org
|
|
@ -1,392 +0,0 @@
|
|||
DeSmuME
|
||||
_________________________________________
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2022 DeSmuME team
|
||||
Last Updated: May 23, 2022
|
||||
|
||||
Contents:
|
||||
1) System Requirements ..................................................... 17
|
||||
2) Quick Start Guide for Using DeSmuME for macOS ........................... 58
|
||||
3) Improving Emulation Performance ........................................ 204
|
||||
4) Troubleshooting ........................................................ 230
|
||||
5) Additional Documentation ............................................... 245
|
||||
6) Contact Information .................................................... 275
|
||||
7) License ................................................................ 377
|
||||
|
||||
|
||||
1) System Requirements ________________________________________________________
|
||||
|
||||
Operating System: macOS v10.5 (Leopard) or later
|
||||
|
||||
CPU: Can run on any PowerPC G4, G5, or Intel processor
|
||||
Minimum Recommended: 2.4 GHz Intel Core 2 Duo
|
||||
Best Experience Recommended: 2.4 GHz Intel i5 (Haswell)
|
||||
|
||||
RAM: 512 MB (minimum)
|
||||
2 GB (recommended)
|
||||
|
||||
Before you begin, make sure that your Mac meets the listed system requirements.
|
||||
In general, any Mac with an Intel Core 2 Duo processor (from Mid-2007) should
|
||||
be sufficient for basic gaming. However, it is possible to run DeSmuME with
|
||||
even older hardware than that. In this case, you will need to use the settings
|
||||
listed in the section "Improving Emulation Performance" to make things usable.
|
||||
With this level of hardware, running any additional graphics enhancing features
|
||||
will result in a poor experience. Some frameskip will also be necessary in
|
||||
order maintain your execution speed.
|
||||
|
||||
If your Mac meets the minimum recommended requirements, then you should be able
|
||||
to run all games at full speed without any frameskip. You may need to use some
|
||||
of the settings listed in the section "Improving Emulation Performance" for
|
||||
certain games, but they should not be required for most games. You will also be
|
||||
able to use some basic graphical enhancements, such as using some of the
|
||||
display filters. However, increased 3D rendering resolution may not be possible
|
||||
for all games for this level of hardware.
|
||||
|
||||
However, if your Mac has an Intel Haswell (from late 2013) or an Apple Silicon
|
||||
processor (from 2020), you will be able to run all games with all of DeSmuME's
|
||||
features without any performance problems. Graphics enhancements, such as
|
||||
increased 3D rendering resolution, can be adjusted as needed to fit the
|
||||
performance level of your hardware.
|
||||
|
||||
Please note that running DeSmuME on a PowerPC, while possible, is not fully
|
||||
supported. The PowerPC binary exists mostly for testing and development
|
||||
purposes, and also just because we can. Most games don't work well on PowerPC,
|
||||
and so you will be limited to running only the most basic of games, such as
|
||||
"Phoenix Wright: Ace Attorney" or "Picross DS."
|
||||
|
||||
|
||||
2) Quick Start Guide for Using DeSmuME for macOS ______________________________
|
||||
|
||||
Installing DeSmuME is as easy as copying DeSmuME.app to your Applications
|
||||
folder (or other folder of your choice). Double-click the app to start DeSmuME.
|
||||
|
||||
Note that DeSmuME for macOS may have a different feature set than DeSmuME for
|
||||
Windows and DeSmuME for Linux. As of this writing, some features that are
|
||||
present in DeSmuME for Windows are not present in DeSmuME for macOS.
|
||||
|
||||
The rest of this section will be a guide to help you quickly get started using
|
||||
DeSmuME for macOS.
|
||||
|
||||
Loading a ROM and Starting the Emulator:
|
||||
Simply double-click the desired ROM from the Finder to play the game. By
|
||||
default, DeSmuME will load the ROM and start emulation. Also, there are
|
||||
additional ROM loading options that you can change in DeSmuME > Preferences if
|
||||
you need them.
|
||||
|
||||
Using the NDS Controller:
|
||||
Each NDS controller button can be mapped to a button of your choice on your
|
||||
keyboard, gamepad, or joystick. You can view the mappings by clicking on Input
|
||||
in DeSmuME > Preferences. To change a mapping, click on the NDS control that
|
||||
you want to change, then press the button on your input device to map it.
|
||||
|
||||
By default, the NDS controller is mapped to the following keys on your keyboard:
|
||||
Up - Up Arrow
|
||||
Down - Down Arrow
|
||||
Left - Left Arrow
|
||||
Right - Right Arrow
|
||||
A Button - X
|
||||
B Button - Z
|
||||
X Button - S
|
||||
Y Button - A
|
||||
L Trigger - Q
|
||||
R Trigger - W
|
||||
Start - Return
|
||||
Select - Tab
|
||||
Lid - Delete (Backspace)
|
||||
Microphone (Internal Noise Samples) - ` (Accent)
|
||||
|
||||
The NDS can support a variety of SLOT-2 devices. Some devices, such as the
|
||||
Guitar Grip, EasyPiano, and Taito Paddle have inputs, which are mapped to your
|
||||
keyboard using these defaults:
|
||||
Guitar Grip:
|
||||
Green - E
|
||||
Red - R
|
||||
Yellow - T
|
||||
Blue - Y
|
||||
|
||||
EasyPiano:
|
||||
C - C
|
||||
C# - F
|
||||
D - V
|
||||
D# - G
|
||||
E - B
|
||||
F - N
|
||||
F# - J
|
||||
G - M
|
||||
G# - K
|
||||
A - , (Comma)
|
||||
A# - L
|
||||
B - . (Period)
|
||||
High C - / (Forward Slash)
|
||||
|
||||
Paddle:
|
||||
Paddle Adjust -5 - O
|
||||
Paddle Adjust +5 - P
|
||||
|
||||
In addition, the following emulator functions are mapped to your keyboard by
|
||||
default:
|
||||
Execute/Pause - Forward Delete
|
||||
Reset - Page Down
|
||||
Rotate Display Left - [ (Left Bracket)
|
||||
Rotate Display Right - ] (Right Bracket)
|
||||
Set Speed to Half - - (Dash)
|
||||
Set Speed to Double - = (Equal)
|
||||
|
||||
Using the NDS Touch Pad:
|
||||
Touch pad input is emulated using the left mouse button by default. Simply
|
||||
click in the touch pad area of the NDS display window to use the NDS touch pad.
|
||||
|
||||
Using the NDS Microphone:
|
||||
Some games make use of the NDS microphone. DeSmuME emulates the NDS microphone
|
||||
by using the default audio input device selected in your System Preferences.
|
||||
You can choose Emulation > Show Microphone Settings to view the audio input
|
||||
device that DeSmuME is currently using, as well as setting its gain.
|
||||
|
||||
DeSmuME will track the audio input level on the meter as the NDS reads the
|
||||
microphone. The meter reflects the audio input level as seen by the NDS, not
|
||||
the host. Note that some games ignore the microphone, and therefore will not
|
||||
register on the meter. If you need to view the audio input level from the host
|
||||
machine's perspective, you can view the host's audio input level in your System
|
||||
Preferences.
|
||||
|
||||
Finally, you can generate audio samples in software by using one of DeSmuME's
|
||||
audio generators, and send those audio samples to the NDS. This is what the
|
||||
Microphone command in your Input Preferences does. As long as the Microphone
|
||||
command is engaged, the host input device will be ignored. When you disengage
|
||||
the Microphone command, DeSmuME will automatically return to reading the host
|
||||
input device.
|
||||
|
||||
The microphone icon serves to indicate the current status of the NDS
|
||||
microphone, and will change color for each status:
|
||||
Black - The microphone is inactive due to the emulation being paused.
|
||||
Dark Gray - The host audio input is inactive because the user has muted it
|
||||
or because the user never authorized its usage. The emulation
|
||||
is currently only accepting software-generated sources.
|
||||
Bright Gray - A software-generated source is being used for the microphone
|
||||
input. This overrides any host audio input.
|
||||
Dark Green - The host audio input is active. However, the input level is
|
||||
too low to be meaningful, or the game is ignoring the
|
||||
microphone.
|
||||
Bright Green - The microphone is active and the game is reading a
|
||||
meaningful input level from the host audio input.
|
||||
Bright Red - The microphone is active and the game is reading a clipped
|
||||
input level. Depending on the situation, this may or may not
|
||||
be desirable. Use the gain slider to influence the host audio
|
||||
input level if needed.
|
||||
|
||||
Rotating the NDS Display:
|
||||
Some games require that the NDS display be at a certain rotation in order to
|
||||
look correct. Rotation options can be found by choosing
|
||||
View > Display Rotation. You can also use the toolbar buttons Rotate Left and
|
||||
Rotate Right to rotate the display by 90 degrees counterclockwise or clockwise,
|
||||
respectively. Finally, you can assign inputs to Rotate Left and Rotate Right in
|
||||
your Input Preferences.
|
||||
|
||||
Freezing and Restoring the Emulation State:
|
||||
Save states are a powerful feature that allows you to freeze the emulation
|
||||
state and restore it later. However, note that save states are only a
|
||||
temporary means of saving -- more permanent saves must be done using the
|
||||
in-game save (or ROM save).
|
||||
|
||||
- To freeze the emulation state, choose File > Save State File.
|
||||
- To restore the emulation state, choose File > Open State File.
|
||||
|
||||
You can also freeze/restore emulation states without having to manage the
|
||||
Open/Save dialogs. There are ten available save state "slots" that you can
|
||||
use to quickly freeze/restore the emulation state.
|
||||
|
||||
- To quick freeze the emulation state, choose File > Save State Slot > Slot #.
|
||||
The default hotkey for this is (Shift-#).
|
||||
- To quick restore the emulation state, choose File > Load State Slot > Slot #.
|
||||
The default hotkey for this is (#).
|
||||
|
||||
|
||||
3) Improving Emulation Performance ____________________________________________
|
||||
|
||||
There are many settings you can change in order to improve DeSmuME's emulation
|
||||
performance. All of the settings listed below affect performance the most. Use
|
||||
the settings as shown for the best possible performance. All of these settings
|
||||
may be found in DeSmuME > Preferences.
|
||||
|
||||
- WARNING: Changing any Emulation setting may cause emulation glitches in
|
||||
certain ROMs. Do not change these settings unless you are willing to
|
||||
accept reduced emulation accuracy or ROM compatibility.
|
||||
|
||||
Emulation:
|
||||
Advanced Bus Level Timing - Off (May cause glitches)
|
||||
Rigorous 3D Rendering Timing - On (May cause graphical glitches)
|
||||
CPU Emulation Engine - Dynamic Recompiler (Reduces ROM compatibility)
|
||||
Dynamic Recompiler Block Size - 100 (May cause glitches)
|
||||
Use External BIOS Images - Off (May reduce ROM compatibility)
|
||||
|
||||
3D Rendering:
|
||||
3D Rendering Engine - SoftRasterizer (or OpenGL if GPU Scaling Factor
|
||||
is greater than 4)
|
||||
GPU Scaling Factor - 1
|
||||
GPU Color Depth - 15-bit (Reduces color accuracy of 3D rendering)
|
||||
Texture Scaling Factor - 1
|
||||
|
||||
|
||||
4) Troubleshooting ____________________________________________________________
|
||||
|
||||
The vast majority of problems can be resolved by simply resetting DeSmuME's
|
||||
settings back to their defaults. The easiest way to do this is to delete the
|
||||
org.desmume.DeSmuME.plist file in your ~/Library/Preferences folder. There is
|
||||
also a DeleteUserDefaults.applescript script that is included with your DeSmuME
|
||||
installation that will do this for you.
|
||||
|
||||
If you are still experiencing problems after restoring your DeSmuME settings to
|
||||
their defaults, then you may want to post your issue on our DeSmuME forum. Your
|
||||
post may gain the attention of another user, or even a DeSmuME developer, to
|
||||
help assist you with your issue. See the section "Contact Information" for how
|
||||
to contact us on the forum.
|
||||
|
||||
|
||||
5) Additional Documentation ___________________________________________________
|
||||
|
||||
The quick start guide in this Read Me is by no means a complete reference to
|
||||
everything that DeSmuME can do! If you need any additional information about
|
||||
DeSmuME, then you can reference our online Wiki pages for up-to-date
|
||||
information.
|
||||
|
||||
* Official Documentation: https://wiki.desmume.org/index.php?title=Main_Page
|
||||
|
||||
This is the main Wiki page that contains all of our official documentation.
|
||||
|
||||
* FAQ: https://wiki.desmume.org/index.php?title=Faq
|
||||
|
||||
The Frequently Asked Questions (FAQ) page has a lot of useful general
|
||||
information about DeSmuME. Do note that some of the information may be platform
|
||||
specific, and may not directly apply to the macOS version of DeSmuME.
|
||||
|
||||
* DeSmuME Manual for macOS:
|
||||
https://wiki.desmume.org/index.php?title=DeSmuME_Manual_for_the_Macintosh_port
|
||||
|
||||
This page contains complete and detailed information about how to operate
|
||||
DeSmuME for macOS.
|
||||
|
||||
* DeSmuME Build Instructions for macOS:
|
||||
https://wiki.desmume.org/index.php?title=Installing_DeSmuME_from_source_on_OS_X
|
||||
|
||||
This page contains complete and detailed instructions about how to make your
|
||||
own build of DeSmuME for macOS directly from the source code.
|
||||
|
||||
|
||||
6) Contact Information ________________________________________________________
|
||||
|
||||
Thank you for you interest in DeSmuME! If you want to tell us how useful
|
||||
DeSmuME is in your life, your love (or hate) of certain NDS games, your passion
|
||||
for NDS homebrew development, or anything else related to DeSmuME or NDS
|
||||
emulation, then there are various ways for you to contact us!
|
||||
|
||||
However, keep in mind that there are a few of rules that you need to follow:
|
||||
- Do not ask us to provide ROMs, BIOS files, or any other copyrighted stuff.
|
||||
We don't want to have to deal with any legal issues that could get us in
|
||||
trouble, or worse, completely shut down.
|
||||
|
||||
- When contacting us, please use the appropriate means to do it. For example,
|
||||
if you simply want to tell us how much you love or hate us, then use the
|
||||
comments on the official webpage. Another example: If you want to post on the
|
||||
forum, be sure to keep the topic focused on DeSmuME; questions that ask for
|
||||
things like us providing you the latest Pokemon cheats are not DeSmuME
|
||||
related, and we will instead refer you to a Pokemon cheaters forum. Finally,
|
||||
our developer chat channel is intended for furthering the development work of
|
||||
DeSmuME; questions about how to use DeSmuME should not come here, but instead
|
||||
go to the Support forum. In short, use the appropriate contact method. That's
|
||||
why the different methods exist!
|
||||
|
||||
* Official Website: https://desmume.org
|
||||
|
||||
Our official website has the latest news on DeSmuME releases, and also has a
|
||||
lot of other useful information about DeSmuME. You can comment on different
|
||||
posts telling us how you feel about DeSmuME. Is DeSmuME the best thing in your
|
||||
life? Is it making you cry? Or is it a bunch of blah? Let us know here!
|
||||
|
||||
* Public Forum: https://forums.desmume.org
|
||||
|
||||
If you have a question about DeSmuME, then this is the place to ask it. But
|
||||
before you ask it, be aware that your question may have already been answered
|
||||
before, so try the following things first:
|
||||
|
||||
- Read the manual and the FAQ. A lot of questions people have are usually
|
||||
already answered in our documentation.
|
||||
- Do a forum search about your question.
|
||||
|
||||
If you still need to ask a question, choose Help > Submit a Support Request in
|
||||
the DeSmuME application. Follow the onscreen instructions on the Support
|
||||
Request Form.
|
||||
|
||||
* Live Developer Chat Channel: irc://irc.libera.chat:6697/desmume
|
||||
|
||||
We have a live developer chatline on Libera IRC at #desmume. This channel
|
||||
is meant for discussing the development of DeSmuME, and shows the real work
|
||||
that goes on behind the scenes. If you are interested in doing any sort of
|
||||
software programming, software testing, documentation, or graphics work, then
|
||||
please join our chat channel! We would love for you to join us!
|
||||
|
||||
* Bug Reports:
|
||||
|
||||
If you believe that you have found a bug, you may submit a bug report by
|
||||
choosing Help > Submit a Bug Report in the DeSmuME application. Follow the
|
||||
onscreen instructions on the Bug Report Form.
|
||||
|
||||
When you click Go To Bug Report Webpage, you will be taken to our bug tracker
|
||||
on SourceForge. Do note that you will need a SourceForge account in order to
|
||||
submit a bug report.
|
||||
|
||||
Bug submissions are very welcome and encouraged. However, when you submit a bug
|
||||
to us, you MUST provide the following information, or else your bug submission
|
||||
may be rejected:
|
||||
|
||||
- DeSmuME app version
|
||||
- Your operating system and OS version
|
||||
- Your Mac model identifier
|
||||
- The name of the running ROM when the bug was observed (or "None", if no ROM
|
||||
was running)
|
||||
- The serial code of the running ROM when the bug was observed (or "None", if
|
||||
no ROM was running)
|
||||
- A description of the exact behavior you observed
|
||||
- A description of the behavior you expected
|
||||
|
||||
All of this information will be prepared for you if you use the Bug Report Form
|
||||
from Help > Submit a Bug Report.
|
||||
|
||||
When you write your description, make sure that they are as detailed as
|
||||
possible. The better your descriptions are, the faster we can test and fix
|
||||
bugs. For example, if you observed a bug in the game "Golden Sun: Dark Dawn,"
|
||||
then the bug report could look something like this:
|
||||
|
||||
App Version: 0.9.13
|
||||
Operating System: macOS v12.4 (21F79)
|
||||
Mac Model Identifier: MacBookPro15,1
|
||||
ROM Name: GOLDENSUN_DD
|
||||
ROM Serial: NTR-BO5E-USA
|
||||
Observed Behavior: I tried to load a save state using the
|
||||
File > Load State > Slot 3 menu option, but the game froze. If I reset, I
|
||||
can get the game working again.
|
||||
Expected Behavior: The game should continue running from the point where I
|
||||
made the save state.
|
||||
|
||||
We will try to get your bug tested as soon as possible, but any fixes may take
|
||||
longer, depending on the complexity of the bug. Also, some bugs may require us
|
||||
to ask you for certain files, such as your ROM saves, save states, or console
|
||||
logs. For the above example, we would probably ask you for your save states to
|
||||
help us track down the bug.
|
||||
|
||||
|
||||
7) License ____________________________________________________________________
|
||||
|
||||
This file 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 file 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 software. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
* See the GNU General Public License details in COPYING.
|
1092
desmume/README.WIN
1092
desmume/README.WIN
File diff suppressed because it is too large
Load Diff
|
@ -1,74 +0,0 @@
|
|||
DSM is ascii plain text. It is derived from the FCEUX FM2 format.
|
||||
It consists of several key-value pairs followed by an inputlog section.
|
||||
The inputlog section can be identified by its starting with a | (pipe).
|
||||
The inputlog section terminates at eof.
|
||||
Newlines may be \r\n or \n
|
||||
|
||||
Key-value pairs consist of a key identifier, followed by a space separator, followed by the value text.
|
||||
Value text is always terminated by a newline, which the value text will not include.
|
||||
The value text is parsed differently depending on the type of the key.
|
||||
The key-value pairs may be in any order, except that the first key must be version.
|
||||
|
||||
Integer keys (also used for booleans, with a 1 or 0) will have a value that is a simple integer not to exceed 32bits
|
||||
- version (required) - the version of the movie file format; for now it is always 3
|
||||
- emuVersion (required) - the version of the emulator used to produce the movie
|
||||
- rerecordCount (optional) - the rerecord count
|
||||
- romChecksum (optional) - the CRC32 of the rom used to make the movie. should match values specified on advanscene.com
|
||||
- romSerial (optional) - a concatenation of other uniquely identifying information about the rom (name,gamecode,makercode)
|
||||
- useExtBios (optional) - were bios files was used? defaults to false.
|
||||
- swiFromBios (optional) - were swi emulated by ExtBios? (alternative is internal HLE bios). defaults to false.
|
||||
|
||||
The rom identification information may be used at a later point to warn about mismatches between movies and roms, but is not right now.
|
||||
|
||||
String keys have values that consist of the remainder of the key-value pair line. As a consequence, string values cannot contain newlines.
|
||||
- romFilename (required) - the name of the file used to record the movie
|
||||
- comment (optional) - simply a memo.
|
||||
by convention, the first token in the comment value is the subject of the comment.
|
||||
by convention, subsequent comments with the same subject will have their ordering preserved and may be used to approximate multiline comments.
|
||||
by convention, the author of the movie should be stored in comment(s) with a subject of: author
|
||||
|
||||
Hex string keys (used for binary blobs) will have a value that is like 0x0123456789ABCDEF...
|
||||
- romChecksum (required) - this is currently unused.
|
||||
|
||||
GUID keys have a value which is in the standard guid format: 452DE2C3-EF43-2FA9-77AC-0677FC51543B
|
||||
- guid (required) a unique identifier for a movie, generated when the movie is created, which is used when loading a savestate to make sure it belongs to the current movie.
|
||||
|
||||
The inputlog section consists of lines beginning and ending with a | (pipe).
|
||||
The fields are as follows, except as noted in note C.
|
||||
|c|.............XXX YYY Z|
|
||||
|
||||
'R','L','D','U','T','S','B','A','Y','X','W','E','G'
|
||||
|
||||
field c is a variable length decimal integer which is a bitfield corresponding to miscellaneous input states which are valid at the start of the frame.
|
||||
Therefore, no miscellaneous commands is represented by a value of 0.
|
||||
Here are the currently defined bit values:
|
||||
0x01 - Microphone Noise (hardcoded noise sample; to be held through duration of frame)
|
||||
0x02 - Reset
|
||||
0x04 - Lid
|
||||
|
||||
|
||||
the format of the main section is as follows:
|
||||
|
||||
the field begins with 13 characters which constitute a bitfield.
|
||||
any character other than ' ' or '.' means that the button was pressed.
|
||||
by convention, the following mnemonics will be used in a column to remind us of which button corresponds to which column:
|
||||
RLDUTSBAYXWEG (Right,Left,Down,Up,sTart,Select,B,A,Y,X,lshoulder,rshoulder,debuG)
|
||||
This ordering is based on FCEUX to a certain extent, and arbitrary after that.
|
||||
W and E were chosen for shoulders to suggest West and East for Left and Right.
|
||||
While the emulator supports a 'lid' button, and to some extent a 'blow' button, these are not supported in the movies.
|
||||
|
||||
XXX: %03d, the x position of the stylus (0,0 topleft, 255,191 bottomright)
|
||||
YYY: %03d, the y position of the stylus
|
||||
Z: %1d, 1 if the stylus is pressed pressed; 0 if not
|
||||
|
||||
Additional fields after this main section may be added later without breaking the file format.
|
||||
|
||||
* Notes *
|
||||
A. There is no key-value pair that indicates the length of the movie. This must be read by scanning the inputlog and counting the number of lines.
|
||||
|
||||
B. All movies start from power-on.
|
||||
|
||||
C. The emulator uses these framerate constants
|
||||
arm7_cycles_per_frame = 560190
|
||||
frames_per_second = 59.8261
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
The desmume save file format is merely a raw save file with a FOOTER.
|
||||
|
||||
This was chosen in order to maximize compatibility with other emulators,
|
||||
which tend load the savefile as-is and let the game read out of whatever range
|
||||
it is expecting. To assist with this, before writing the save file, desmume
|
||||
will pad the raw save file out to the next highest known length. Note that this
|
||||
may sometimes be incorrect if the savefile hasnt been written through to the end
|
||||
during initialization. This could cause other emulators to fail to recognize the
|
||||
save file.
|
||||
|
||||
Additionally, the footer makes it easier to analyze save files, because the
|
||||
game's data will be at the correct addresses starting at offset 0x0000.
|
||||
|
||||
The footer format can be identified by locating the 16Byte ascii string
|
||||
"|-DESMUME SAVE-|"
|
||||
at the end of the file. This corresponds with the following save structure:
|
||||
|
||||
struct Footer {
|
||||
u32 actually_written_size;
|
||||
u32 padded_size;
|
||||
u32 save_type; //(not currently used)
|
||||
u32 address_size; //address bus size
|
||||
u32 save_size; //size parameter of the save type (not currently used)
|
||||
u32 version_number; //should be 0
|
||||
char cookie[16];
|
||||
};
|
||||
|
||||
note that padded_size should be where you see the end of the raw save data
|
||||
and the beginning of desmume-specific information, including some junk before
|
||||
the actual footer.
|
||||
|
||||
actually_written_size is the highest address (plus one) written to by the game.
|
||||
|
||||
The new desmume savefile system tries to make as few decisions as possible,
|
||||
which is the reason for the behavior of actually_written_size and the disuse
|
||||
of save_type and save_size. If few decisions are made, then few mistakes can
|
||||
be made. That is the idea, anyway. We'll make decisions later if we need to.
|
||||
save_type and save_size are reserved in case we do.
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,8 +0,0 @@
|
|||
Tips:
|
||||
* Set hotkeys for "Mic Prev Sample" and "Mic Next Sample" in the "Main" section of hotkey configuration (suggest [ and ])
|
||||
* This will rotate through all the provided desmume_N.wav. You can add your own in the series, just pick the next number.
|
||||
* Keep the microphone hotkey held down for as long as you want the noise to play! Just tapping it will make a very short sound indeed.
|
||||
|
||||
desmume_0.wav was formerly "PERFECT BLOW FOR DS EMULATORS.wav"
|
||||
desmume_1.wav was formerly "noise_loud.wav"
|
||||
desmume_4.wav came to us as "pcm0822m.wav"; these are alleged to work well for Giant Bowser fights in Bowser's Inside Story.
|
Binary file not shown.
|
@ -1,4 +0,0 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = tab
|
|
@ -1,392 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2008-2021 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "Database.h"
|
||||
#include "retro_miscellaneous.h"
|
||||
|
||||
//------------------------------------------------------------
|
||||
//large databases are first. scroll down to ENDLARGE to find the code
|
||||
|
||||
struct MAKER
|
||||
{
|
||||
u16 code;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
|
||||
static const char regions_index[] = "JPFSEODIRKHXVWUC";
|
||||
static const char *regions[] = {
|
||||
"JPN", // J
|
||||
"EUR", // P
|
||||
"FRA", // F
|
||||
"ESP", // S
|
||||
"USA", // E
|
||||
"INT", // O
|
||||
"NOE", // D
|
||||
"ITA", // I
|
||||
"RUS", // R
|
||||
"KOR", // K
|
||||
"HOL", // H
|
||||
"EUU", // X
|
||||
"EUU", // V
|
||||
"EUU", // W
|
||||
"AUS", // U
|
||||
"CHN", // C
|
||||
};
|
||||
|
||||
static MAKER makerCodes[] = {
|
||||
{ 0x3130, "Nintendo" },
|
||||
{ 0x3230, "Rocket Games, Ajinomoto" },
|
||||
{ 0x3330, "Imagineer-Zoom" },
|
||||
{ 0x3430, "Gray Matter?" },
|
||||
{ 0x3530, "Zamuse" },
|
||||
{ 0x3630, "Falcom" },
|
||||
{ 0x3730, "Enix?" },
|
||||
{ 0x3830, "Capcom" },
|
||||
{ 0x3930, "Hot B Co." },
|
||||
{ 0x4130, "Jaleco" },
|
||||
{ 0x4230, "Coconuts Japan" },
|
||||
{ 0x4330, "Coconuts Japan/G.X.Media" },
|
||||
{ 0x4430, "Micronet?" },
|
||||
{ 0x4530, "Technos" },
|
||||
{ 0x4630, "Mebio Software" },
|
||||
{ 0x4730, "Shouei System" },
|
||||
{ 0x4830, "Starfish" },
|
||||
{ 0x4A30, "Mitsui Fudosan/Dentsu" },
|
||||
{ 0x4C30, "Warashi Inc." },
|
||||
{ 0x4E30, "Nowpro" },
|
||||
{ 0x5030, "Game Village" },
|
||||
{ 0x3031, "?????????????" },
|
||||
{ 0x3231, "Infocom" },
|
||||
{ 0x3331, "Electronic Arts Japan" },
|
||||
{ 0x3531, "Cobra Team" },
|
||||
{ 0x3631, "Human/Field" },
|
||||
{ 0x3731, "KOEI" },
|
||||
{ 0x3831, "Hudson Soft" },
|
||||
{ 0x3931, "S.C.P." },
|
||||
{ 0x4131, "Yanoman" },
|
||||
{ 0x4331, "Tecmo Products" },
|
||||
{ 0x4431, "Japan Glary Business" },
|
||||
{ 0x4531, "Forum/OpenSystem" },
|
||||
{ 0x4631, "Virgin Games" },
|
||||
{ 0x4731, "SMDE" },
|
||||
{ 0x4A31, "Daikokudenki" },
|
||||
{ 0x5031, "Creatures Inc." },
|
||||
{ 0x5131, "TDK Deep Impresion" },
|
||||
{ 0x3032, "Destination Software, KSS" },
|
||||
{ 0x3132, "Sunsoft/Tokai Engineering??" },
|
||||
{ 0x3232, "POW, VR 1 Japan??" },
|
||||
{ 0x3332, "Micro World" },
|
||||
{ 0x3532, "San-X" },
|
||||
{ 0x3632, "Enix" },
|
||||
{ 0x3732, "Loriciel/Electro Brain" },
|
||||
{ 0x3832, "Kemco Japan" },
|
||||
{ 0x3932, "Seta" },
|
||||
{ 0x4132, "Culture Brain" },
|
||||
{ 0x4332, "Palsoft" },
|
||||
{ 0x4432, "Visit Co.,Ltd." },
|
||||
{ 0x4532, "Intec" },
|
||||
{ 0x4632, "System Sacom" },
|
||||
{ 0x4732, "Poppo" },
|
||||
{ 0x4832, "Ubisoft Japan" },
|
||||
{ 0x4A32, "Media Works" },
|
||||
{ 0x4B32, "NEC InterChannel" },
|
||||
{ 0x4C32, "Tam" },
|
||||
{ 0x4D32, "Jordan" },
|
||||
{ 0x4E32, "Smilesoft ???, Rocket ???" },
|
||||
{ 0x5132, "Mediakite" },
|
||||
{ 0x3033, "Viacom" },
|
||||
{ 0x3133, "Carrozzeria" },
|
||||
{ 0x3233, "Dynamic" },
|
||||
{ 0x3433, "Magifact" },
|
||||
{ 0x3533, "Hect" },
|
||||
{ 0x3633, "Codemasters" },
|
||||
{ 0x3733, "Taito/GAGA Communications" },
|
||||
{ 0x3833, "Laguna" },
|
||||
{ 0x3933, "Telstar Fun & Games, Event/Taito" },
|
||||
{ 0x4233, "Arcade Zone Ltd" },
|
||||
{ 0x4333, "Entertainment International/Empire Software?" },
|
||||
{ 0x4433, "Loriciel" },
|
||||
{ 0x4533, "Gremlin Graphics" },
|
||||
{ 0x4633, "K.Amusement Leasing Co." },
|
||||
{ 0x3034, "Seika Corp." },
|
||||
{ 0x3134, "Ubi Soft Entertainment" },
|
||||
{ 0x3234, "Sunsoft US?" },
|
||||
{ 0x3434, "Life Fitness" },
|
||||
{ 0x3634, "System 3" },
|
||||
{ 0x3734, "Spectrum Holobyte" },
|
||||
{ 0x3934, "IREM" },
|
||||
{ 0x4234, "Raya Systems" },
|
||||
{ 0x4334, "Renovation Products" },
|
||||
{ 0x4434, "Malibu Games" },
|
||||
{ 0x4634, "Eidos (was U.S. Gold <=1995)" },
|
||||
{ 0x4734, "Playmates Interactive?" },
|
||||
{ 0x4A34, "Fox Interactive" },
|
||||
{ 0x4B34, "Time Warner Interactive" },
|
||||
{ 0x5134, "Disney Interactive" },
|
||||
{ 0x5334, "Black Pearl" },
|
||||
{ 0x5534, "Advanced Productions" },
|
||||
{ 0x5834, "GT Interactive" },
|
||||
{ 0x5934, "RARE?" },
|
||||
{ 0x5A34, "Crave Entertainment" },
|
||||
{ 0x3035, "Absolute Entertainment" },
|
||||
{ 0x3135, "Acclaim" },
|
||||
{ 0x3235, "Activision" },
|
||||
{ 0x3335, "American Sammy" },
|
||||
{ 0x3435, "Take 2 Interactive (before it was GameTek)" },
|
||||
{ 0x3535, "Hi Tech" },
|
||||
{ 0x3635, "LJN LTD." },
|
||||
{ 0x3835, "Mattel" },
|
||||
{ 0x4135, "Mindscape, Red Orb Entertainment?" },
|
||||
{ 0x4235, "Romstar" },
|
||||
{ 0x4335, "Taxan" },
|
||||
{ 0x4435, "Midway (before it was Tradewest)" },
|
||||
{ 0x4635, "American Softworks" },
|
||||
{ 0x4735, "Majesco Sales Inc" },
|
||||
{ 0x4835, "3DO" },
|
||||
{ 0x4B35, "Hasbro" },
|
||||
{ 0x4C35, "NewKidCo" },
|
||||
{ 0x4D35, "Telegames" },
|
||||
{ 0x4E35, "Metro3D" },
|
||||
{ 0x5035, "Vatical Entertainment" },
|
||||
{ 0x5135, "LEGO Media" },
|
||||
{ 0x5335, "Xicat Interactive" },
|
||||
{ 0x5435, "Cryo Interactive" },
|
||||
{ 0x5735, "Red Storm Entertainment" },
|
||||
{ 0x5835, "Microids" },
|
||||
{ 0x5A35, "Conspiracy/Swing" },
|
||||
{ 0x3036, "Titus" },
|
||||
{ 0x3136, "Virgin Interactive" },
|
||||
{ 0x3236, "Maxis" },
|
||||
{ 0x3436, "LucasArts Entertainment" },
|
||||
{ 0x3736, "Ocean" },
|
||||
{ 0x3936, "Electronic Arts" },
|
||||
{ 0x4236, "Laser Beam" },
|
||||
{ 0x4536, "Elite Systems" },
|
||||
{ 0x4636, "Electro Brain" },
|
||||
{ 0x4736, "The Learning Company" },
|
||||
{ 0x4836, "BBC" },
|
||||
{ 0x4A36, "Software 2000" },
|
||||
{ 0x4C36, "BAM! Entertainment" },
|
||||
{ 0x4D36, "Studio 3" },
|
||||
{ 0x5136, "Classified Games" },
|
||||
{ 0x5336, "TDK Mediactive" },
|
||||
{ 0x5536, "DreamCatcher" },
|
||||
{ 0x5636, "JoWood Produtions" },
|
||||
{ 0x5736, "SEGA" },
|
||||
{ 0x5836, "Wannado Edition" },
|
||||
{ 0x5936, "LSP" },
|
||||
{ 0x5A36, "ITE Media" },
|
||||
{ 0x3037, "Infogrames" },
|
||||
{ 0x3137, "Interplay" },
|
||||
{ 0x3237, "JVC" },
|
||||
{ 0x3337, "Parker Brothers" },
|
||||
{ 0x3537, "Sales Curve" },
|
||||
{ 0x3837, "THQ" },
|
||||
{ 0x3937, "Accolade" },
|
||||
{ 0x4137, "Triffix Entertainment" },
|
||||
{ 0x4337, "Microprose Software" },
|
||||
{ 0x4437, "Universal Interactive, Sierra, Simon & Schuster?" },
|
||||
{ 0x4637, "Kemco" },
|
||||
{ 0x4737, "Rage Software" },
|
||||
{ 0x4837, "Encore" },
|
||||
{ 0x4A37, "Zoo" },
|
||||
{ 0x4B37, "BVM" },
|
||||
{ 0x4C37, "Simon & Schuster Interactive" },
|
||||
{ 0x4D37, "Asmik Ace Entertainment Inc./AIA" },
|
||||
{ 0x4E37, "Empire Interactive?" },
|
||||
{ 0x5137, "Jester Interactive" },
|
||||
{ 0x5437, "Scholastic" },
|
||||
{ 0x5537, "Ignition Entertainment" },
|
||||
{ 0x5737, "Stadlbauer" },
|
||||
{ 0x3038, "Misawa" },
|
||||
{ 0x3138, "Teichiku" },
|
||||
{ 0x3238, "Namco Ltd." },
|
||||
{ 0x3338, "LOZC" },
|
||||
{ 0x3438, "KOEI" },
|
||||
{ 0x3638, "Tokuma Shoten Intermedia" },
|
||||
{ 0x3738, "Tsukuda Original" },
|
||||
{ 0x3838, "DATAM-Polystar" },
|
||||
{ 0x4238, "Bulletproof Software" },
|
||||
{ 0x4338, "Vic Tokai Inc." },
|
||||
{ 0x4538, "Character Soft" },
|
||||
{ 0x4638, "I'Max" },
|
||||
{ 0x4738, "Saurus" },
|
||||
{ 0x4A38, "General Entertainment" },
|
||||
{ 0x4E38, "Success" },
|
||||
{ 0x5038, "SEGA Japan" },
|
||||
{ 0x3039, "Takara Amusement" },
|
||||
{ 0x3139, "Chun Soft" },
|
||||
{ 0x3239, "Video System, McO'River???" },
|
||||
{ 0x3339, "BEC" },
|
||||
{ 0x3539, "Varie" },
|
||||
{ 0x3639, "Yonezawa/S'pal" },
|
||||
{ 0x3739, "Kaneko" },
|
||||
{ 0x3939, "Victor Interactive Software, Pack in Video" },
|
||||
{ 0x4139, "Nichibutsu/Nihon Bussan" },
|
||||
{ 0x4239, "Tecmo" },
|
||||
{ 0x4339, "Imagineer" },
|
||||
{ 0x4639, "Nova" },
|
||||
{ 0x4739, "Den'Z" },
|
||||
{ 0x4839, "Bottom Up" },
|
||||
{ 0x4A39, "TGL" },
|
||||
{ 0x4C39, "Hasbro Japan?" },
|
||||
{ 0x4E39, "Marvelous Entertainment" },
|
||||
{ 0x5039, "Keynet Inc." },
|
||||
{ 0x5139, "Hands-On Entertainment" },
|
||||
{ 0x3041, "Telenet" },
|
||||
{ 0x3141, "Hori" },
|
||||
{ 0x3441, "Konami" },
|
||||
{ 0x3541, "K.Amusement Leasing Co." },
|
||||
{ 0x3641, "Kawada" },
|
||||
{ 0x3741, "Takara" },
|
||||
{ 0x3941, "Technos Japan Corp." },
|
||||
{ 0x4141, "JVC, Victor Musical Indutries" },
|
||||
{ 0x4341, "Toei Animation" },
|
||||
{ 0x4441, "Toho" },
|
||||
{ 0x4641, "Namco" },
|
||||
{ 0x4741, "Media Rings Corporation" },
|
||||
{ 0x4841, "J-Wing" },
|
||||
{ 0x4A41, "Pioneer LDC" },
|
||||
{ 0x4B41, "KID" },
|
||||
{ 0x4C41, "Mediafactory" },
|
||||
{ 0x5041, "Infogrames Hudson" },
|
||||
{ 0x5141, "Kiratto. Ludic Inc" },
|
||||
{ 0x3042, "Acclaim Japan" },
|
||||
{ 0x3142, "ASCII (was Nexoft?)" },
|
||||
{ 0x3242, "Bandai" },
|
||||
{ 0x3442, "Enix" },
|
||||
{ 0x3642, "HAL Laboratory" },
|
||||
{ 0x3742, "SNK" },
|
||||
{ 0x3942, "Pony Canyon" },
|
||||
{ 0x4142, "Culture Brain" },
|
||||
{ 0x4242, "Sunsoft" },
|
||||
{ 0x4342, "Toshiba EMI" },
|
||||
{ 0x4442, "Sony Imagesoft" },
|
||||
{ 0x4642, "Sammy" },
|
||||
{ 0x4742, "Magical" },
|
||||
{ 0x4842, "Visco" },
|
||||
{ 0x4A42, "Compile " },
|
||||
{ 0x4C42, "MTO Inc." },
|
||||
{ 0x4E42, "Sunrise Interactive" },
|
||||
{ 0x5042, "Global A Entertainment" },
|
||||
{ 0x5142, "Fuuki" },
|
||||
{ 0x3043, "Taito" },
|
||||
{ 0x3243, "Kemco" },
|
||||
{ 0x3343, "Square" },
|
||||
{ 0x3443, "Tokuma Shoten" },
|
||||
{ 0x3543, "Data East" },
|
||||
{ 0x3643, "Tonkin House (was Tokyo Shoseki)" },
|
||||
{ 0x3843, "Koei" },
|
||||
{ 0x4143, "Konami/Ultra/Palcom" },
|
||||
{ 0x4243, "NTVIC/VAP" },
|
||||
{ 0x4343, "Use Co.,Ltd." },
|
||||
{ 0x4443, "Meldac" },
|
||||
{ 0x4543, "Pony Canyon" },
|
||||
{ 0x4643, "Angel, Sotsu Agency/Sunrise" },
|
||||
{ 0x4A43, "Boss" },
|
||||
{ 0x4743, "Yumedia/Aroma Co., Ltd" },
|
||||
{ 0x4B43, "Axela/Crea-Tech?" },
|
||||
{ 0x4C43, "Sekaibunka-Sha, Sumire kobo?, Marigul Management Inc.?" },
|
||||
{ 0x4D43, "Konami Computer Entertainment Osaka" },
|
||||
{ 0x5043, "Enterbrain" },
|
||||
{ 0x3044, "Taito/Disco" },
|
||||
{ 0x3144, "Sofel" },
|
||||
{ 0x3244, "Quest, Bothtec" },
|
||||
{ 0x3344, "Sigma, ?????" },
|
||||
{ 0x3444, "Ask Kodansha" },
|
||||
{ 0x3644, "Naxat" },
|
||||
{ 0x3744, "Copya System" },
|
||||
{ 0x3844, "Capcom Co., Ltd." },
|
||||
{ 0x3944, "Banpresto" },
|
||||
{ 0x4144, "TOMY" },
|
||||
{ 0x4244, "LJN Japan" },
|
||||
{ 0x4444, "NCS" },
|
||||
{ 0x4544, "Human Entertainment" },
|
||||
{ 0x4644, "Altron" },
|
||||
{ 0x4744, "Jaleco???" },
|
||||
{ 0x4844, "Gaps Inc." },
|
||||
{ 0x4C44, "????" },
|
||||
{ 0x4E44, "Elf" },
|
||||
{ 0x3045, "Jaleco" },
|
||||
{ 0x3145, "????" },
|
||||
{ 0x3245, "Yutaka" },
|
||||
{ 0x3345, "Varie" },
|
||||
{ 0x3445, "T&ESoft" },
|
||||
{ 0x3545, "Epoch" },
|
||||
{ 0x3745, "Athena" },
|
||||
{ 0x3845, "Asmik" },
|
||||
{ 0x3945, "Natsume" },
|
||||
{ 0x4145, "King Records" },
|
||||
{ 0x4245, "Atlus" },
|
||||
{ 0x4345, "Epic/Sony Records" },
|
||||
{ 0x4545, "IGS" },
|
||||
{ 0x4745, "Chatnoir" },
|
||||
{ 0x4845, "Right Stuff" },
|
||||
{ 0x4C45, "Spike" },
|
||||
{ 0x4D45, "Konami Computer Entertainment Tokyo" },
|
||||
{ 0x4E45, "Alphadream Corporation" },
|
||||
{ 0x3046, "A Wave" },
|
||||
{ 0x3146, "Motown Software" },
|
||||
{ 0x3246, "Left Field Entertainment" },
|
||||
{ 0x3346, "Extreme Ent. Grp." },
|
||||
{ 0x3446, "TecMagik" },
|
||||
{ 0x3946, "Cybersoft" },
|
||||
{ 0x4246, "Psygnosis" },
|
||||
{ 0x4546, "Davidson/Western Tech." },
|
||||
{ 0x3147, "PCCW Japan" },
|
||||
{ 0x3447, "KiKi Co Ltd" },
|
||||
{ 0x3547, "Open Sesame Inc???" },
|
||||
{ 0x3647, "Sims" },
|
||||
{ 0x3747, "Broccoli" },
|
||||
{ 0x3847, "Avex" },
|
||||
{ 0x3947, "D3 Publisher" },
|
||||
{ 0x4247, "Konami Computer Entertainment Japan" },
|
||||
{ 0x4447, "Square-Enix" },
|
||||
{ 0x4849, "Yojigen" },
|
||||
};
|
||||
|
||||
//------------------------------------------------------------
|
||||
//ENDLARGE
|
||||
//------------------------------------------------------------
|
||||
|
||||
namespace Database
|
||||
{
|
||||
const char* RegionXXXForCode(char code, bool unknownAsString)
|
||||
{
|
||||
size_t regions_num = ARRAY_SIZE(regions);
|
||||
|
||||
const char* found = strchr(regions_index,code);
|
||||
if(found && found-regions_index < strlen(regions_index)) return regions[found-regions_index];
|
||||
else return unknownAsString ? "???" : NULL;
|
||||
}
|
||||
|
||||
const char *MakerNameForMakerCode(u16 id, bool unknownAsString)
|
||||
{
|
||||
//too bad these aren't sorted
|
||||
for (size_t i = 0; i < ARRAY_SIZE(makerCodes); i++)
|
||||
{
|
||||
if (makerCodes[i].code == id)
|
||||
return makerCodes[i].name;
|
||||
}
|
||||
|
||||
return unknownAsString ? "Unknown" : NULL;
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef DESMUME_DATABASE_H_
|
||||
#define DESMUME_DATABASE_H_
|
||||
|
||||
namespace Database
|
||||
{
|
||||
const char* RegionXXXForCode(char code, bool unknownAsString);
|
||||
const char* MakerNameForMakerCode(u16 id, bool unknownAsString);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,549 +0,0 @@
|
|||
/*
|
||||
Copyright 2006 yopyop
|
||||
Copyright 2007 shash
|
||||
Copyright 2007-2024 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "FIFO.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "armcpu.h"
|
||||
#include "debug.h"
|
||||
#include "mem.h"
|
||||
#include "MMU.h"
|
||||
#include "registers.h"
|
||||
#include "NDSSystem.h"
|
||||
#include "gfx3d.h"
|
||||
|
||||
#if defined(ENABLE_AVX512_1)
|
||||
#define USEVECTORSIZE_512
|
||||
#define VECTORSIZE 64
|
||||
#elif defined(ENABLE_AVX2)
|
||||
#define USEVECTORSIZE_256
|
||||
#define VECTORSIZE 32
|
||||
#elif defined(ENABLE_SSE2)
|
||||
#define USEVECTORSIZE_128
|
||||
#define VECTORSIZE 16
|
||||
#elif defined(ENABLE_NEON_A64)
|
||||
#define USEVECTORSIZE_128
|
||||
#define VECTORSIZE 16
|
||||
#elif defined(ENABLE_ALTIVEC)
|
||||
#define USEVECTORSIZE_128
|
||||
#define VECTORSIZE 16
|
||||
#endif
|
||||
|
||||
#if defined(USEVECTORSIZE_512) || defined(USEVECTORSIZE_256) || defined(USEVECTORSIZE_128)
|
||||
#define USEMANUALVECTORIZATION
|
||||
#endif
|
||||
|
||||
|
||||
// ========================================================= IPC FIFO
|
||||
IPC_FIFO ipc_fifo[2];
|
||||
|
||||
void IPC_FIFOinit(u8 proc)
|
||||
{
|
||||
memset(&ipc_fifo[proc], 0, sizeof(IPC_FIFO));
|
||||
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, 0x00000101);
|
||||
}
|
||||
|
||||
void IPC_FIFOsend(u8 proc, u32 val)
|
||||
{
|
||||
u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184);
|
||||
if (!(cnt_l & IPCFIFOCNT_FIFOENABLE)) return; // FIFO disabled
|
||||
u8 proc_remote = proc ^ 1;
|
||||
|
||||
if (ipc_fifo[proc].size > 15)
|
||||
{
|
||||
cnt_l |= IPCFIFOCNT_FIFOERROR;
|
||||
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
|
||||
return;
|
||||
}
|
||||
|
||||
u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc_remote][0x40], 0x184);
|
||||
|
||||
//LOG("IPC%s send FIFO 0x%08X size %03i (l 0x%X, tail %02i) (r 0x%X, tail %02i)\n",
|
||||
// proc?"7":"9", val, ipc_fifo[proc].size, cnt_l, ipc_fifo[proc].tail, cnt_r, ipc_fifo[proc^1].tail);
|
||||
|
||||
cnt_l &= 0xBFFC; // clear send empty bit & full
|
||||
cnt_r &= 0xBCFF; // set recv empty bit & full
|
||||
ipc_fifo[proc].buf[ipc_fifo[proc].tail] = val;
|
||||
ipc_fifo[proc].tail++;
|
||||
ipc_fifo[proc].size++;
|
||||
if (ipc_fifo[proc].tail > 15) ipc_fifo[proc].tail = 0;
|
||||
|
||||
if (ipc_fifo[proc].size > 15)
|
||||
{
|
||||
cnt_l |= IPCFIFOCNT_SENDFULL; // set send full bit
|
||||
cnt_r |= IPCFIFOCNT_RECVFULL; // set recv full bit
|
||||
}
|
||||
|
||||
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
|
||||
T1WriteWord(MMU.MMU_MEM[proc_remote][0x40], 0x184, cnt_r);
|
||||
|
||||
if(cnt_r&IPCFIFOCNT_RECVIRQEN)
|
||||
NDS_makeIrq(proc_remote, IRQ_BIT_IPCFIFO_RECVNONEMPTY);
|
||||
|
||||
NDS_Reschedule();
|
||||
}
|
||||
|
||||
u32 IPC_FIFOrecv(u8 proc)
|
||||
{
|
||||
u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184);
|
||||
if (!(cnt_l & IPCFIFOCNT_FIFOENABLE)) return (0); // FIFO disabled
|
||||
u8 proc_remote = proc ^ 1;
|
||||
|
||||
u32 val = 0;
|
||||
|
||||
if ( ipc_fifo[proc_remote].size == 0 ) // remote FIFO error
|
||||
{
|
||||
cnt_l |= IPCFIFOCNT_FIFOERROR;
|
||||
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
|
||||
return (0);
|
||||
}
|
||||
|
||||
u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc_remote][0x40], 0x184);
|
||||
|
||||
cnt_l &= 0xBCFF; // clear send full bit & empty
|
||||
cnt_r &= 0xBFFC; // set recv full bit & empty
|
||||
|
||||
val = ipc_fifo[proc_remote].buf[ipc_fifo[proc_remote].head];
|
||||
ipc_fifo[proc_remote].head++;
|
||||
ipc_fifo[proc_remote].size--;
|
||||
if (ipc_fifo[proc_remote].head > 15) ipc_fifo[proc_remote].head = 0;
|
||||
|
||||
//LOG("IPC%s recv FIFO 0x%08X size %03i (l 0x%X, tail %02i) (r 0x%X, tail %02i)\n",
|
||||
// proc?"7":"9", val, ipc_fifo[proc].size, cnt_l, ipc_fifo[proc].tail, cnt_r, ipc_fifo[proc^1].tail);
|
||||
|
||||
if ( ipc_fifo[proc_remote].size == 0 ) // FIFO empty
|
||||
{
|
||||
cnt_l |= IPCFIFOCNT_RECVEMPTY;
|
||||
cnt_r |= IPCFIFOCNT_SENDEMPTY;
|
||||
|
||||
if(cnt_r&IPCFIFOCNT_SENDIRQEN)
|
||||
NDS_makeIrq(proc_remote, IRQ_BIT_IPCFIFO_SENDEMPTY);
|
||||
}
|
||||
|
||||
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
|
||||
T1WriteWord(MMU.MMU_MEM[proc_remote][0x40], 0x184, cnt_r);
|
||||
|
||||
NDS_Reschedule();
|
||||
|
||||
return (val);
|
||||
}
|
||||
|
||||
void IPC_FIFOcnt(u8 proc, u16 val)
|
||||
{
|
||||
u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184);
|
||||
u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc^1][0x40], 0x184);
|
||||
|
||||
if (val & IPCFIFOCNT_FIFOERROR)
|
||||
{
|
||||
//at least SPP uses this, maybe every retail game
|
||||
cnt_l &= ~IPCFIFOCNT_FIFOERROR;
|
||||
}
|
||||
|
||||
if (val & IPCFIFOCNT_SENDCLEAR)
|
||||
{
|
||||
ipc_fifo[proc].head = 0; ipc_fifo[proc].tail = 0; ipc_fifo[proc].size = 0;
|
||||
|
||||
cnt_l |= IPCFIFOCNT_SENDEMPTY;
|
||||
cnt_r |= IPCFIFOCNT_RECVEMPTY;
|
||||
|
||||
cnt_l &= ~IPCFIFOCNT_SENDFULL;
|
||||
cnt_r &= ~IPCFIFOCNT_RECVFULL;
|
||||
|
||||
}
|
||||
cnt_l &= ~IPCFIFOCNT_WRITEABLE;
|
||||
cnt_l |= val & IPCFIFOCNT_WRITEABLE;
|
||||
|
||||
//IPCFIFOCNT_SENDIRQEN may have been set (and/or the fifo may have been cleared) so we may need to trigger this irq
|
||||
//(this approach is used by libnds fifo system on occasion in fifoInternalSend, and began happening frequently for value32 with r4326)
|
||||
if(cnt_l&IPCFIFOCNT_SENDIRQEN) if(cnt_l & IPCFIFOCNT_SENDEMPTY)
|
||||
NDS_makeIrq(proc, IRQ_BIT_IPCFIFO_SENDEMPTY);
|
||||
|
||||
//IPCFIFOCNT_RECVIRQEN may have been set so we may need to trigger this irq
|
||||
if(cnt_l&IPCFIFOCNT_RECVIRQEN) if(!(cnt_l & IPCFIFOCNT_RECVEMPTY))
|
||||
NDS_makeIrq(proc, IRQ_BIT_IPCFIFO_RECVNONEMPTY);
|
||||
|
||||
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
|
||||
T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, cnt_r);
|
||||
|
||||
NDS_Reschedule();
|
||||
}
|
||||
|
||||
// ========================================================= GFX FIFO
|
||||
GFX_PIPE gxPIPE;
|
||||
GFX_FIFO gxFIFO;
|
||||
|
||||
void GFX_PIPEclear()
|
||||
{
|
||||
gxPIPE.head = 0;
|
||||
gxPIPE.tail = 0;
|
||||
gxPIPE.size = 0;
|
||||
gxFIFO.matrix_stack_op_size = 0;
|
||||
}
|
||||
|
||||
void GFX_FIFOclear()
|
||||
{
|
||||
gxFIFO.head = 0;
|
||||
gxFIFO.tail = 0;
|
||||
gxFIFO.size = 0;
|
||||
gxFIFO.matrix_stack_op_size = 0;
|
||||
}
|
||||
|
||||
static void GXF_FIFO_handleEvents()
|
||||
{
|
||||
bool low = gxFIFO.size <= 127;
|
||||
bool lowchange = MMU_new.gxstat.fifo_low ^ low;
|
||||
MMU_new.gxstat.fifo_low = low;
|
||||
if(low) triggerDma(EDMAMode_GXFifo);
|
||||
|
||||
bool empty = gxFIFO.size == 0;
|
||||
bool emptychange = MMU_new.gxstat.fifo_empty ^ empty;
|
||||
MMU_new.gxstat.fifo_empty = empty;
|
||||
|
||||
|
||||
MMU_new.gxstat.sb = gxFIFO.matrix_stack_op_size != 0;
|
||||
|
||||
if(emptychange||lowchange) NDS_Reschedule();
|
||||
}
|
||||
|
||||
static bool IsMatrixStackCommand(u8 cmd)
|
||||
{
|
||||
return cmd == 0x11 || cmd == 0x12;
|
||||
}
|
||||
|
||||
void GFX_FIFOsend(u8 cmd, u32 param)
|
||||
{
|
||||
//INFO("gxFIFO: send 0x%02X = 0x%08X (size %03i/0x%02X) gxstat 0x%08X\n", cmd, param, gxFIFO.size, gxFIFO.size, gxstat);
|
||||
//printf("fifo recv: %02X: %08X upto:%d\n",cmd,param,gxFIFO.size+1);
|
||||
|
||||
//TODO - WOAH ! NOT HANDLING A TOO-BIG FIFO RIGHT NOW!
|
||||
//if (gxFIFO.size > 255)
|
||||
//{
|
||||
// GXF_FIFO_handleEvents();
|
||||
// //NEED TO HANDLE THIS!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
// //gxstat |= 0x08000000; // busy
|
||||
// NDS_RescheduleGXFIFO(1);
|
||||
// //INFO("ERROR: gxFIFO is full (cmd 0x%02X = 0x%08X) (prev cmd 0x%02X = 0x%08X)\n", cmd, param, gxFIFO.cmd[255], gxFIFO.param[255]);
|
||||
// return;
|
||||
//}
|
||||
|
||||
|
||||
gxFIFO.cmd[gxFIFO.tail] = cmd;
|
||||
gxFIFO.param[gxFIFO.tail] = param;
|
||||
gxFIFO.tail++;
|
||||
gxFIFO.size++;
|
||||
if (gxFIFO.tail > HACK_GXIFO_SIZE-1) gxFIFO.tail = 0;
|
||||
|
||||
//if a matrix op is entering the pipeline, do accounting for it
|
||||
//(this is tested by wild west, which will jam a few ops in the fifo and then wait for the matrix stack to be
|
||||
//un-busy so it can read back the current matrix stack position).
|
||||
//it is definitely only pushes and pops which set this flag.
|
||||
//seems like it would be less work in the HW to make a counter than do cmps on all the command bytes, so maybe we're even doing it right.
|
||||
if(IsMatrixStackCommand(cmd))
|
||||
gxFIFO.matrix_stack_op_size++;
|
||||
|
||||
//along the same lines:
|
||||
//american girls julie finds a way will put a bunch of stuff and then a box test into the fifo and then immediately test the busy flag
|
||||
//so we need to set the busy flag here.
|
||||
//does it expect the fifo to be running then? well, it's definitely jammed -- making it unjammed at one point did fix this bug.
|
||||
//it's still not clear whether we're handling the immediate vs fifo commands properly at all :(
|
||||
//anyway, here we go, similar treatment. consider this a hack.
|
||||
if(cmd == 0x70) MMU_new.gxstat.tb = 1; //just set the flag--youre insane if you queue more than one of these anyway
|
||||
if(cmd == 0x71) MMU_new.gxstat.tb = 1;
|
||||
|
||||
if(gxFIFO.size>=HACK_GXIFO_SIZE) {
|
||||
printf("--FIFO FULL-- : %d\n",gxFIFO.size);
|
||||
}
|
||||
|
||||
//gxstat |= 0x08000000; // set busy flag
|
||||
|
||||
GXF_FIFO_handleEvents();
|
||||
|
||||
NDS_RescheduleGXFIFO(1);
|
||||
}
|
||||
|
||||
// this function used ONLY in gxFIFO
|
||||
BOOL GFX_PIPErecv(u8 *cmd, u32 *param)
|
||||
{
|
||||
//gxstat &= 0xF7FFFFFF; // clear busy flag
|
||||
|
||||
if (gxFIFO.size == 0)
|
||||
{
|
||||
GXF_FIFO_handleEvents();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*cmd = gxFIFO.cmd[gxFIFO.head];
|
||||
*param = gxFIFO.param[gxFIFO.head];
|
||||
|
||||
//see the associated increment in another function
|
||||
if(IsMatrixStackCommand(*cmd))
|
||||
{
|
||||
gxFIFO.matrix_stack_op_size--;
|
||||
if(gxFIFO.matrix_stack_op_size>0x10000000)
|
||||
printf("bad news disaster in matrix_stack_op_size\n");
|
||||
}
|
||||
|
||||
gxFIFO.head++;
|
||||
gxFIFO.size--;
|
||||
if (gxFIFO.head > HACK_GXIFO_SIZE-1) gxFIFO.head = 0;
|
||||
|
||||
GXF_FIFO_handleEvents();
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
void GFX_FIFOcnt(u32 val)
|
||||
{
|
||||
////INFO("gxFIFO: write cnt 0x%08X (prev 0x%08X) FIFO size %03i PIPE size %03i\n", val, gxstat, gxFIFO.size, gxPIPE.size);
|
||||
|
||||
if (val & (1<<29)) // clear? (only in homebrew?)
|
||||
{
|
||||
GFX_PIPEclear();
|
||||
GFX_FIFOclear();
|
||||
return;
|
||||
}
|
||||
|
||||
//zeromus says: what happened to clear stack?
|
||||
//if (val & (1<<15)) // projection stack pointer reset
|
||||
//{
|
||||
// gfx3d_ClearStack();
|
||||
// val &= 0xFFFF5FFF; // clear reset (bit15) & stack level (bit13)
|
||||
//}
|
||||
|
||||
T1WriteLong(MMU.ARM9_REG, 0x600, val);
|
||||
}
|
||||
|
||||
// ========================================================= DISP FIFO
|
||||
DISP_FIFO disp_fifo;
|
||||
|
||||
void DISP_FIFOinit()
|
||||
{
|
||||
memset(&disp_fifo, 0, sizeof(DISP_FIFO));
|
||||
}
|
||||
|
||||
template <typename T, size_t ADDROFFSET>
|
||||
void DISP_FIFOsend(const T val)
|
||||
{
|
||||
//INFO("DISP_FIFO send value 0x%08X (head 0x%06X, tail 0x%06X)\n", val, disp_fifo.head, disp_fifo.tail);
|
||||
|
||||
const size_t numBytes = sizeof(T);
|
||||
const size_t baseWriteAddress = disp_fifo.tail * sizeof(u32);
|
||||
const size_t finalWriteAddress = baseWriteAddress + ADDROFFSET;
|
||||
|
||||
switch (numBytes)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
#ifndef MSB_FIRST
|
||||
HostWriteByte((u8 *)disp_fifo.buf, (u32)finalWriteAddress, val);
|
||||
#else
|
||||
switch (ADDROFFSET)
|
||||
{
|
||||
case 0:
|
||||
HostWriteByte((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 2, val);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
HostWriteByte((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 3, val);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
HostWriteByte((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 0, val);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
HostWriteByte((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 1, val);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef MSB_FIRST
|
||||
if (ADDROFFSET == 3)
|
||||
#else
|
||||
if (ADDROFFSET == 1)
|
||||
#endif
|
||||
{
|
||||
disp_fifo.tail++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
#ifndef MSB_FIRST
|
||||
HostWriteWord((u8 *)disp_fifo.buf, (u32)finalWriteAddress, val);
|
||||
#else
|
||||
switch (ADDROFFSET)
|
||||
{
|
||||
case 0:
|
||||
HostWriteWord((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 2, val);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
HostWriteWord((u8 *)disp_fifo.buf, (u32)baseWriteAddress + 0, val);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef MSB_FIRST
|
||||
if (ADDROFFSET == 2)
|
||||
#else
|
||||
if (ADDROFFSET == 0)
|
||||
#endif
|
||||
{
|
||||
disp_fifo.tail++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
HostWriteTwoWords((u8 *)disp_fifo.buf, (u32)finalWriteAddress, val);
|
||||
disp_fifo.tail++;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (disp_fifo.tail >= 0x6000)
|
||||
{
|
||||
disp_fifo.tail = 0;
|
||||
}
|
||||
}
|
||||
|
||||
u32 DISP_FIFOrecv_u32()
|
||||
{
|
||||
//if (disp_fifo.tail == disp_fifo.head) return (0); // FIFO is empty
|
||||
u32 val = disp_fifo.buf[disp_fifo.head];
|
||||
|
||||
disp_fifo.head++;
|
||||
if (disp_fifo.head >= 0x6000)
|
||||
{
|
||||
disp_fifo.head = 0;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void _DISP_FIFOrecv_LineAdvance()
|
||||
{
|
||||
disp_fifo.head += (GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16)) / sizeof(u32);
|
||||
if (disp_fifo.head >= 0x6000)
|
||||
{
|
||||
disp_fifo.head -= 0x6000;
|
||||
}
|
||||
}
|
||||
|
||||
void DISP_FIFOrecv_Line16(u16 *__restrict dst)
|
||||
{
|
||||
#ifdef USEMANUALVECTORIZATION
|
||||
if ( (disp_fifo.head + (GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16)) / sizeof(u32) <= 0x6000) && (disp_fifo.head == (disp_fifo.head & ~(VECTORSIZE - 1))) )
|
||||
{
|
||||
buffer_copy_fast<GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16)>(dst, disp_fifo.buf + disp_fifo.head);
|
||||
_DISP_FIFOrecv_LineAdvance();
|
||||
}
|
||||
else
|
||||
#endif // USEMANUALVECTORIZATION
|
||||
{
|
||||
for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16) / sizeof(u32); i++)
|
||||
{
|
||||
const u32 src = DISP_FIFOrecv_u32();
|
||||
((u32 *)dst)[i] = src;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <NDSColorFormat OUTPUTFORMAT>
|
||||
void DISP_FIFOrecv_LineOpaque(u32 *__restrict dst)
|
||||
{
|
||||
#ifdef USEMANUALVECTORIZATION
|
||||
if ( (disp_fifo.head + (GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16)) / sizeof(u32) <= 0x6000) && (disp_fifo.head == (disp_fifo.head & ~(VECTORSIZE - 1))) )
|
||||
{
|
||||
if (OUTPUTFORMAT == NDSColorFormat_BGR555_Rev)
|
||||
{
|
||||
buffer_copy_or_constant_s16_fast<GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16), false>(dst, disp_fifo.buf + disp_fifo.head, 0x8000);
|
||||
}
|
||||
else if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
|
||||
{
|
||||
ColorspaceConvertBuffer555xTo6665Opaque<false, false, BESwapDst>((u16 *)(disp_fifo.buf + disp_fifo.head), dst, GPU_FRAMEBUFFER_NATIVE_WIDTH);
|
||||
}
|
||||
else if (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev)
|
||||
{
|
||||
ColorspaceConvertBuffer555xTo8888Opaque<false, false, BESwapDst>((u16 *)(disp_fifo.buf + disp_fifo.head), dst, GPU_FRAMEBUFFER_NATIVE_WIDTH);
|
||||
}
|
||||
|
||||
_DISP_FIFOrecv_LineAdvance();
|
||||
}
|
||||
else
|
||||
#endif // USEMANUALVECTORIZATION
|
||||
{
|
||||
if (OUTPUTFORMAT == NDSColorFormat_BGR555_Rev)
|
||||
{
|
||||
for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16) / sizeof(u32); i++)
|
||||
{
|
||||
const u32 src = DISP_FIFOrecv_u32();
|
||||
dst[i] = src | 0x80008000;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH; i+=2)
|
||||
{
|
||||
const u32 src = DISP_FIFOrecv_u32();
|
||||
|
||||
if (OUTPUTFORMAT == NDSColorFormat_BGR666_Rev)
|
||||
{
|
||||
dst[i+0] = LE_TO_LOCAL_32( ColorspaceConvert555To6665Opaque<false>((src >> 0) & 0x7FFF) );
|
||||
dst[i+1] = LE_TO_LOCAL_32( ColorspaceConvert555To6665Opaque<false>((src >> 16) & 0x7FFF) );
|
||||
}
|
||||
else if (OUTPUTFORMAT == NDSColorFormat_BGR888_Rev)
|
||||
{
|
||||
dst[i+0] = LE_TO_LOCAL_32( ColorspaceConvert555To8888Opaque<false>((src >> 0) & 0x7FFF) );
|
||||
dst[i+1] = LE_TO_LOCAL_32( ColorspaceConvert555To8888Opaque<false>((src >> 16) & 0x7FFF) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DISP_FIFOreset()
|
||||
{
|
||||
disp_fifo.head = 0;
|
||||
disp_fifo.tail = 0;
|
||||
}
|
||||
|
||||
template void DISP_FIFOsend< u8, 0>(const u8 val);
|
||||
template void DISP_FIFOsend< u8, 1>(const u8 val);
|
||||
template void DISP_FIFOsend< u8, 2>(const u8 val);
|
||||
template void DISP_FIFOsend< u8, 3>(const u8 val);
|
||||
template void DISP_FIFOsend<u16, 0>(const u16 val);
|
||||
template void DISP_FIFOsend<u16, 2>(const u16 val);
|
||||
template void DISP_FIFOsend<u32, 0>(const u32 val);
|
||||
|
||||
template void DISP_FIFOrecv_LineOpaque<NDSColorFormat_BGR555_Rev>(u32 *__restrict dst);
|
||||
template void DISP_FIFOrecv_LineOpaque<NDSColorFormat_BGR666_Rev>(u32 *__restrict dst);
|
||||
template void DISP_FIFOrecv_LineOpaque<NDSColorFormat_BGR888_Rev>(u32 *__restrict dst);
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
Copyright 2006 yopyop
|
||||
Copyright 2007 shash
|
||||
Copyright 2007-2022 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FIFO_H
|
||||
#define FIFO_H
|
||||
|
||||
#include "types.h"
|
||||
#include "./utils/colorspacehandler/colorspacehandler.h"
|
||||
|
||||
//=================================================== IPC FIFO
|
||||
typedef struct
|
||||
{
|
||||
u32 buf[16];
|
||||
|
||||
u8 head;
|
||||
u8 tail;
|
||||
u8 size;
|
||||
} IPC_FIFO;
|
||||
|
||||
extern IPC_FIFO ipc_fifo[2];
|
||||
extern void IPC_FIFOinit(u8 proc);
|
||||
extern void IPC_FIFOsend(u8 proc, u32 val);
|
||||
extern u32 IPC_FIFOrecv(u8 proc);
|
||||
extern void IPC_FIFOcnt(u8 proc, u16 val);
|
||||
|
||||
//=================================================== GFX FIFO
|
||||
|
||||
//yeah, its oversize for now. thats a simpler solution
|
||||
//moon seems to overdrive the fifo with immediate dmas
|
||||
//i think this might be nintendo code too
|
||||
#define HACK_GXIFO_SIZE 200000
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 cmd[HACK_GXIFO_SIZE];
|
||||
u32 param[HACK_GXIFO_SIZE];
|
||||
|
||||
u32 head; // start position
|
||||
u32 tail; // tail
|
||||
u32 size; // size FIFO buffer
|
||||
u32 matrix_stack_op_size; //number of matrix stack items in the fifo (stack is busy when this is nonzero)
|
||||
} GFX_FIFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 cmd[4];
|
||||
u32 param[4];
|
||||
|
||||
u8 head;
|
||||
u8 tail;
|
||||
u8 size;
|
||||
} GFX_PIPE;
|
||||
|
||||
extern GFX_PIPE gxPIPE;
|
||||
extern GFX_FIFO gxFIFO;
|
||||
void GFX_PIPEclear();
|
||||
void GFX_FIFOclear();
|
||||
void GFX_FIFOsend(u8 cmd, u32 param);
|
||||
BOOL GFX_PIPErecv(u8 *cmd, u32 *param);
|
||||
void GFX_FIFOcnt(u32 val);
|
||||
|
||||
//=================================================== Display memory FIFO
|
||||
typedef struct
|
||||
{
|
||||
CACHE_ALIGN u32 buf[0x6000]; // 256x192 32K color
|
||||
u32 head; // head
|
||||
u32 tail; // tail
|
||||
} DISP_FIFO;
|
||||
|
||||
extern DISP_FIFO disp_fifo;
|
||||
void DISP_FIFOinit();
|
||||
|
||||
template<typename T, size_t ADDROFFSET> void DISP_FIFOsend(const T val);
|
||||
u32 DISP_FIFOrecv_u32();
|
||||
|
||||
void DISP_FIFOrecv_Line16(u16 *__restrict dst);
|
||||
template<NDSColorFormat OUTPUTFORMAT> void DISP_FIFOrecv_LineOpaque(u32 *__restrict dst);
|
||||
|
||||
void DISP_FIFOreset();
|
||||
|
||||
#endif
|
6606
desmume/src/GPU.cpp
6606
desmume/src/GPU.cpp
File diff suppressed because it is too large
Load Diff
2038
desmume/src/GPU.h
2038
desmume/src/GPU.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,96 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2021-2023 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GPU_OPERATIONS_H
|
||||
#define GPU_OPERATIONS_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "./utils/colorspacehandler/colorspacehandler.h"
|
||||
|
||||
#include "GPU.h"
|
||||
|
||||
|
||||
template <s32 INTEGERSCALEHINT, bool SCALEVERTICAL, bool USELINEINDEX, bool NEEDENDIANSWAP, size_t ELEMENTSIZE>
|
||||
void CopyLineExpandHinted(const void *__restrict srcBuffer, const size_t srcLineIndex,
|
||||
void *__restrict dstBuffer, const size_t dstLineIndex, const size_t dstLineWidth, const size_t dstLineCount);
|
||||
|
||||
template <s32 INTEGERSCALEHINT, bool SCALEVERTICAL, bool USELINEINDEX, bool NEEDENDIANSWAP, size_t ELEMENTSIZE>
|
||||
void CopyLineExpandHinted(const GPUEngineLineInfo &lineInfo, const void *__restrict srcBuffer, void *__restrict dstBuffer);
|
||||
|
||||
template <s32 INTEGERSCALEHINT, bool USELINEINDEX, bool NEEDENDIANSWAP, size_t ELEMENTSIZE>
|
||||
void CopyLineReduceHinted(const void *__restrict srcBuffer, const size_t srcLineIndex, const size_t srcLineWidth,
|
||||
void *__restrict dstBuffer, const size_t dstLineIndex);
|
||||
|
||||
template <s32 INTEGERSCALEHINT, bool USELINEINDEX, bool NEEDENDIANSWAP, size_t ELEMENTSIZE>
|
||||
void CopyLineReduceHinted(const GPUEngineLineInfo &lineInfo, const void *__restrict srcBuffer, void *__restrict dstBuffer);
|
||||
|
||||
class ColorOperation
|
||||
{
|
||||
public:
|
||||
ColorOperation() {};
|
||||
|
||||
FORCEINLINE u16 blend(const u16 colA, const u16 colB, const u16 blendEVA, const u16 blendEVB) const;
|
||||
FORCEINLINE u16 blend(const u16 colA, const u16 colB, const TBlendTable *blendTable) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE Color4u8 blend(const Color4u8 colA, const Color4u8 colB, const u16 blendEVA, const u16 blendEVB) const;
|
||||
|
||||
FORCEINLINE u16 blend3D(const Color4u8 colA, const u16 colB) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE Color4u8 blend3D(const Color4u8 colA, const Color4u8 colB) const;
|
||||
|
||||
FORCEINLINE u16 increase(const u16 col, const u16 blendEVY) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE Color4u8 increase(const Color4u8 col, const u16 blendEVY) const;
|
||||
|
||||
FORCEINLINE u16 decrease(const u16 col, const u16 blendEVY) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE Color4u8 decrease(const Color4u8 col, const u16 blendEVY) const;
|
||||
};
|
||||
|
||||
class PixelOperation
|
||||
{
|
||||
private:
|
||||
template<GPULayerType LAYERTYPE> FORCEINLINE void __selectedEffect(const GPUEngineCompositorInfo &compInfo, const u8 &dstLayerID, const bool enableColorEffect, const u8 spriteAlpha, const OBJMode spriteMode, ColorEffect &selectedEffect, TBlendTable **selectedBlendTable, u8 &blendEVA, u8 &blendEVB) const;
|
||||
|
||||
protected:
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy32(GPUEngineCompositorInfo &compInfo, const Color4u8 srcColor32) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp32(GPUEngineCompositorInfo &compInfo, const Color4u8 srcColor32) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown32(GPUEngineCompositorInfo &compInfo, const Color4u8 srcColor32) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE> FORCEINLINE void _unknownEffect16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16, const bool enableColorEffect, const u8 spriteAlpha, const OBJMode spriteMode) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE> FORCEINLINE void _unknownEffect32(GPUEngineCompositorInfo &compInfo, const Color4u8 srcColor32, const bool enableColorEffect, const u8 spriteAlpha, const OBJMode spriteMode) const;
|
||||
|
||||
public:
|
||||
static CACHE_ALIGN u8 BlendTable555[17][17][32][32];
|
||||
static CACHE_ALIGN u16 BrightnessUpTable555[17][0x8000];
|
||||
static CACHE_ALIGN Color4u8 BrightnessUpTable666[17][0x8000];
|
||||
static CACHE_ALIGN Color4u8 BrightnessUpTable888[17][0x8000];
|
||||
static CACHE_ALIGN u16 BrightnessDownTable555[17][0x8000];
|
||||
static CACHE_ALIGN Color4u8 BrightnessDownTable666[17][0x8000];
|
||||
static CACHE_ALIGN Color4u8 BrightnessDownTable888[17][0x8000];
|
||||
static void InitLUTs();
|
||||
|
||||
PixelOperation() {};
|
||||
|
||||
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE> FORCEINLINE void Composite16(GPUEngineCompositorInfo &compInfo, const u16 srcColor16, const bool enableColorEffect, const u8 spriteAlpha, const u8 spriteMode) const;
|
||||
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE> FORCEINLINE void Composite32(GPUEngineCompositorInfo &compInfo, Color4u8 srcColor32, const bool enableColorEffect, const u8 spriteAlpha, const u8 spriteMode) const;
|
||||
};
|
||||
|
||||
#endif // GPU_OPERATIONS_H
|
File diff suppressed because it is too large
Load Diff
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2021 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GPU_OPERATIONS_AVX2_H
|
||||
#define GPU_OPERATIONS_AVX2_H
|
||||
|
||||
#include "GPU_Operations.h"
|
||||
|
||||
#ifndef ENABLE_AVX2
|
||||
#warning This header requires AVX2 support.
|
||||
#else
|
||||
|
||||
class ColorOperation_AVX2
|
||||
{
|
||||
public:
|
||||
ColorOperation_AVX2() {};
|
||||
|
||||
FORCEINLINE v256u16 blend(const v256u16 &colA, const v256u16 &colB, const v256u16 &blendEVA, const v256u16 &blendEVB) const;
|
||||
template<NDSColorFormat COLORFORMAT, bool USECONSTANTBLENDVALUESHINT> FORCEINLINE v256u32 blend(const v256u32 &colA, const v256u32 &colB, const v256u16 &blendEVA, const v256u16 &blendEVB) const;
|
||||
|
||||
FORCEINLINE v256u16 blend3D(const v256u32 &colA_Lo, const v256u32 &colA_Hi, const v256u16 &colB) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v256u32 blend3D(const v256u32 &colA, const v256u32 &colB) const;
|
||||
|
||||
FORCEINLINE v256u16 increase(const v256u16 &col, const v256u16 &blendEVY) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v256u32 increase(const v256u32 &col, const v256u16 &blendEVY) const;
|
||||
|
||||
FORCEINLINE v256u16 decrease(const v256u16 &col, const v256u16 &blendEVY) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v256u32 decrease(const v256u32 &col, const v256u16 &blendEVY) const;
|
||||
};
|
||||
|
||||
class PixelOperation_AVX2
|
||||
{
|
||||
protected:
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy16(GPUEngineCompositorInfo &compInfo, const v256u8 &srcLayerID, const v256u16 &src1, const v256u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy32(GPUEngineCompositorInfo &compInfo, const v256u8 &srcLayerID, const v256u32 &src3, const v256u32 &src2, const v256u32 &src1, const v256u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copyMask16(GPUEngineCompositorInfo &compInfo, const v256u8 &passMask8, const v256u8 &srcLayerID, const v256u16 &src1, const v256u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copyMask32(GPUEngineCompositorInfo &compInfo, const v256u8 &passMask8, const v256u8 &srcLayerID, const v256u32 &src3, const v256u32 &src2, const v256u32 &src1, const v256u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp16(GPUEngineCompositorInfo &compInfo, const v256u16 &evy16, const v256u8 &srcLayerID, const v256u16 &src1, const v256u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp32(GPUEngineCompositorInfo &compInfo, const v256u16 &evy16, const v256u8 &srcLayerID, const v256u32 &src3, const v256u32 &src2, const v256u32 &src1, const v256u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUpMask16(GPUEngineCompositorInfo &compInfo, const v256u8 &passMask8, const v256u16 &evy16, const v256u8 &srcLayerID, const v256u16 &src1, const v256u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUpMask32(GPUEngineCompositorInfo &compInfo, const v256u8 &passMask8, const v256u16 &evy16, const v256u8 &srcLayerID, const v256u32 &src3, const v256u32 &src2, const v256u32 &src1, const v256u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown16(GPUEngineCompositorInfo &compInfo, const v256u16 &evy16, const v256u8 &srcLayerID, const v256u16 &src1, const v256u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown32(GPUEngineCompositorInfo &compInfo, const v256u16 &evy16, const v256u8 &srcLayerID, const v256u32 &src3, const v256u32 &src2, const v256u32 &src1, const v256u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDownMask16(GPUEngineCompositorInfo &compInfo, const v256u8 &passMask8, const v256u16 &evy16, const v256u8 &srcLayerID, const v256u16 &src1, const v256u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDownMask32(GPUEngineCompositorInfo &compInfo, const v256u8 &passMask8, const v256u16 &evy16, const v256u8 &srcLayerID, const v256u32 &src3, const v256u32 &src2, const v256u32 &src1, const v256u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE>
|
||||
FORCEINLINE void _unknownEffectMask16(GPUEngineCompositorInfo &compInfo,
|
||||
const v256u8 &passMask8,
|
||||
const v256u16 &evy16,
|
||||
const v256u8 &srcLayerID,
|
||||
const v256u16 &src1, const v256u16 &src0,
|
||||
const v256u8 &srcEffectEnableMask,
|
||||
const v256u8 &dstBlendEnableMaskLUT,
|
||||
const v256u8 &enableColorEffectMask,
|
||||
const v256u8 &spriteAlpha,
|
||||
const v256u8 &spriteMode) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE>
|
||||
FORCEINLINE void _unknownEffectMask32(GPUEngineCompositorInfo &compInfo,
|
||||
const v256u8 &passMask8,
|
||||
const v256u16 &evy16,
|
||||
const v256u8 &srcLayerID,
|
||||
const v256u32 &src3, const v256u32 &src2, const v256u32 &src1, const v256u32 &src0,
|
||||
const v256u8 &srcEffectEnableMask,
|
||||
const v256u8 &dstBlendEnableMaskLUT,
|
||||
const v256u8 &enableColorEffectMask,
|
||||
const v256u8 &spriteAlpha,
|
||||
const v256u8 &spriteMode) const;
|
||||
|
||||
public:
|
||||
PixelOperation_AVX2() {};
|
||||
|
||||
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST>
|
||||
FORCEINLINE void Composite16(GPUEngineCompositorInfo &compInfo,
|
||||
const bool didAllPixelsPass,
|
||||
const v256u8 &passMask8,
|
||||
const v256u16 &evy16,
|
||||
const v256u8 &srcLayerID,
|
||||
const v256u16 &src1, const v256u16 &src0,
|
||||
const v256u8 &srcEffectEnableMask,
|
||||
const v256u8 &dstBlendEnableMaskLUT,
|
||||
const u8 *__restrict enableColorEffectPtr,
|
||||
const u8 *__restrict sprAlphaPtr,
|
||||
const u8 *__restrict sprModePtr) const;
|
||||
|
||||
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST>
|
||||
FORCEINLINE void Composite32(GPUEngineCompositorInfo &compInfo,
|
||||
const bool didAllPixelsPass,
|
||||
const v256u8 &passMask8,
|
||||
const v256u16 &evy16,
|
||||
const v256u8 &srcLayerID,
|
||||
const v256u32 &src3, const v256u32 &src2, const v256u32 &src1, const v256u32 &src0,
|
||||
const v256u8 &srcEffectEnableMask,
|
||||
const v256u8 &dstBlendEnableMaskLUT,
|
||||
const u8 *__restrict enableColorEffectPtr,
|
||||
const u8 *__restrict sprAlphaPtr,
|
||||
const u8 *__restrict sprModePtr) const;
|
||||
};
|
||||
|
||||
#endif // ENABLE_AVX2
|
||||
|
||||
#endif // GPU_OPERATIONS_AVX2_H
|
File diff suppressed because it is too large
Load Diff
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2025 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GPU_OPERATIONS_NEON_H
|
||||
#define GPU_OPERATIONS_NEON_H
|
||||
|
||||
#include "GPU_Operations.h"
|
||||
|
||||
#ifndef ENABLE_NEON_A64
|
||||
#warning This header requires ARM64 NEON support.
|
||||
#else
|
||||
|
||||
class ColorOperation_NEON
|
||||
{
|
||||
public:
|
||||
ColorOperation_NEON() {};
|
||||
|
||||
FORCEINLINE v128u16 blend(const v128u16 &colA, const v128u16 &colB, const v128u16 &blendEVA, const v128u16 &blendEVB) const;
|
||||
template<NDSColorFormat COLORFORMAT, bool USECONSTANTBLENDVALUESHINT> FORCEINLINE v128u32 blend(const v128u32 &colA, const v128u32 &colB, const v128u16 &blendEVA, const v128u16 &blendEVB) const;
|
||||
|
||||
FORCEINLINE v128u16 blend3D(const v128u32 &colA_Lo, const v128u32 &colA_Hi, const v128u16 &colB) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v128u32 blend3D(const v128u32 &colA, const v128u32 &colB) const;
|
||||
|
||||
FORCEINLINE v128u16 increase(const v128u16 &col, const v128u16 &blendEVY) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v128u32 increase(const v128u32 &col, const v128u16 &blendEVY) const;
|
||||
|
||||
FORCEINLINE v128u16 decrease(const v128u16 &col, const v128u16 &blendEVY) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v128u32 decrease(const v128u32 &col, const v128u16 &blendEVY) const;
|
||||
};
|
||||
|
||||
class PixelOperation_NEON
|
||||
{
|
||||
protected:
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy16(GPUEngineCompositorInfo &compInfo, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy32(GPUEngineCompositorInfo &compInfo, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copyMask16(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copyMask32(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp16(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp32(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUpMask16(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUpMask32(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown16(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown32(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDownMask16(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDownMask32(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE>
|
||||
FORCEINLINE void _unknownEffectMask16(GPUEngineCompositorInfo &compInfo,
|
||||
const v128u8 &passMask8,
|
||||
const v128u16 &evy16,
|
||||
const v128u8 &srcLayerID,
|
||||
const v128u16 &src1, const v128u16 &src0,
|
||||
const v128u8 &srcEffectEnableMask,
|
||||
const v128u8 &dstBlendEnableMaskLUT,
|
||||
const v128u8 &enableColorEffectMask,
|
||||
const v128u8 &spriteAlpha,
|
||||
const v128u8 &spriteMode) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE>
|
||||
FORCEINLINE void _unknownEffectMask32(GPUEngineCompositorInfo &compInfo,
|
||||
const v128u8 &passMask8,
|
||||
const v128u16 &evy16,
|
||||
const v128u8 &srcLayerID,
|
||||
const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0,
|
||||
const v128u8 &srcEffectEnableMask,
|
||||
const v128u8 &dstBlendEnableMaskLUT,
|
||||
const v128u8 &enableColorEffectMask,
|
||||
const v128u8 &spriteAlpha,
|
||||
const v128u8 &spriteMode) const;
|
||||
|
||||
public:
|
||||
PixelOperation_NEON() {};
|
||||
|
||||
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST>
|
||||
FORCEINLINE void Composite16(GPUEngineCompositorInfo &compInfo,
|
||||
const bool didAllPixelsPass,
|
||||
const v128u8 &passMask8,
|
||||
const v128u16 &evy16,
|
||||
const v128u8 &srcLayerID,
|
||||
const v128u16 &src1, const v128u16 &src0,
|
||||
const v128u8 &srcEffectEnableMask,
|
||||
const v128u8 &dstBlendEnableMaskLUT,
|
||||
const u8 *__restrict enableColorEffectPtr,
|
||||
const u8 *__restrict sprAlphaPtr,
|
||||
const u8 *__restrict sprModePtr) const;
|
||||
|
||||
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST>
|
||||
FORCEINLINE void Composite32(GPUEngineCompositorInfo &compInfo,
|
||||
const bool didAllPixelsPass,
|
||||
const v128u8 &passMask8,
|
||||
const v128u16 &evy16,
|
||||
const v128u8 &srcLayerID,
|
||||
const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0,
|
||||
const v128u8 &srcEffectEnableMask,
|
||||
const v128u8 &dstBlendEnableMaskLUT,
|
||||
const u8 *__restrict enableColorEffectPtr,
|
||||
const u8 *__restrict sprAlphaPtr,
|
||||
const u8 *__restrict sprModePtr) const;
|
||||
};
|
||||
|
||||
#endif // ENABLE_NEON_A64
|
||||
|
||||
#endif // GPU_OPERATIONS_NEON_H
|
File diff suppressed because it is too large
Load Diff
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2021 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GPU_OPERATIONS_SSE2_H
|
||||
#define GPU_OPERATIONS_SSE2_H
|
||||
|
||||
#include "GPU_Operations.h"
|
||||
|
||||
#ifndef ENABLE_SSE2
|
||||
#warning This header requires SSE2 support.
|
||||
#else
|
||||
|
||||
class ColorOperation_SSE2
|
||||
{
|
||||
public:
|
||||
ColorOperation_SSE2() {};
|
||||
|
||||
FORCEINLINE v128u16 blend(const v128u16 &colA, const v128u16 &colB, const v128u16 &blendEVA, const v128u16 &blendEVB) const;
|
||||
template<NDSColorFormat COLORFORMAT, bool USECONSTANTBLENDVALUESHINT> FORCEINLINE v128u32 blend(const v128u32 &colA, const v128u32 &colB, const v128u16 &blendEVA, const v128u16 &blendEVB) const;
|
||||
|
||||
FORCEINLINE v128u16 blend3D(const v128u32 &colA_Lo, const v128u32 &colA_Hi, const v128u16 &colB) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v128u32 blend3D(const v128u32 &colA, const v128u32 &colB) const;
|
||||
|
||||
FORCEINLINE v128u16 increase(const v128u16 &col, const v128u16 &blendEVY) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v128u32 increase(const v128u32 &col, const v128u16 &blendEVY) const;
|
||||
|
||||
FORCEINLINE v128u16 decrease(const v128u16 &col, const v128u16 &blendEVY) const;
|
||||
template<NDSColorFormat COLORFORMAT> FORCEINLINE v128u32 decrease(const v128u32 &col, const v128u16 &blendEVY) const;
|
||||
};
|
||||
|
||||
class PixelOperation_SSE2
|
||||
{
|
||||
protected:
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy16(GPUEngineCompositorInfo &compInfo, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copy32(GPUEngineCompositorInfo &compInfo, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copyMask16(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT, bool ISDEBUGRENDER> FORCEINLINE void _copyMask32(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp16(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUp32(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUpMask16(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessUpMask32(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown16(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDown32(GPUEngineCompositorInfo &compInfo, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDownMask16(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u16 &src1, const v128u16 &src0) const;
|
||||
template<NDSColorFormat OUTPUTFORMAT> FORCEINLINE void _brightnessDownMask32(GPUEngineCompositorInfo &compInfo, const v128u8 &passMask8, const v128u16 &evy16, const v128u8 &srcLayerID, const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE>
|
||||
FORCEINLINE void _unknownEffectMask16(GPUEngineCompositorInfo &compInfo,
|
||||
const v128u8 &passMask8,
|
||||
const v128u16 &evy16,
|
||||
const v128u8 &srcLayerID,
|
||||
const v128u16 &src1, const v128u16 &src0,
|
||||
const v128u8 &srcEffectEnableMask,
|
||||
const v128u8 &dstBlendEnableMaskLUT,
|
||||
const v128u8 &enableColorEffectMask,
|
||||
const v128u8 &spriteAlpha,
|
||||
const v128u8 &spriteMode) const;
|
||||
|
||||
template<NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE>
|
||||
FORCEINLINE void _unknownEffectMask32(GPUEngineCompositorInfo &compInfo,
|
||||
const v128u8 &passMask8,
|
||||
const v128u16 &evy16,
|
||||
const v128u8 &srcLayerID,
|
||||
const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0,
|
||||
const v128u8 &srcEffectEnableMask,
|
||||
const v128u8 &dstBlendEnableMaskLUT,
|
||||
const v128u8 &enableColorEffectMask,
|
||||
const v128u8 &spriteAlpha,
|
||||
const v128u8 &spriteMode) const;
|
||||
|
||||
public:
|
||||
PixelOperation_SSE2() {};
|
||||
|
||||
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST>
|
||||
FORCEINLINE void Composite16(GPUEngineCompositorInfo &compInfo,
|
||||
const bool didAllPixelsPass,
|
||||
const v128u8 &passMask8,
|
||||
const v128u16 &evy16,
|
||||
const v128u8 &srcLayerID,
|
||||
const v128u16 &src1, const v128u16 &src0,
|
||||
const v128u8 &srcEffectEnableMask,
|
||||
const v128u8 &dstBlendEnableMaskLUT,
|
||||
const u8 *__restrict enableColorEffectPtr,
|
||||
const u8 *__restrict sprAlphaPtr,
|
||||
const u8 *__restrict sprModePtr) const;
|
||||
|
||||
template <GPUCompositorMode COMPOSITORMODE, NDSColorFormat OUTPUTFORMAT, GPULayerType LAYERTYPE, bool WILLPERFORMWINDOWTEST>
|
||||
FORCEINLINE void Composite32(GPUEngineCompositorInfo &compInfo,
|
||||
const bool didAllPixelsPass,
|
||||
const v128u8 &passMask8,
|
||||
const v128u16 &evy16,
|
||||
const v128u8 &srcLayerID,
|
||||
const v128u32 &src3, const v128u32 &src2, const v128u32 &src1, const v128u32 &src0,
|
||||
const v128u8 &srcEffectEnableMask,
|
||||
const v128u8 &dstBlendEnableMaskLUT,
|
||||
const u8 *__restrict enableColorEffectPtr,
|
||||
const u8 *__restrict sprAlphaPtr,
|
||||
const u8 *__restrict sprModePtr) const;
|
||||
};
|
||||
|
||||
#endif // ENABLE_SSE2
|
||||
|
||||
#endif // GPU_OPERATIONS_SSE2_H
|
6536
desmume/src/MMU.cpp
6536
desmume/src/MMU.cpp
File diff suppressed because it is too large
Load Diff
1102
desmume/src/MMU.h
1102
desmume/src/MMU.h
File diff suppressed because it is too large
Load Diff
|
@ -1,460 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2007 shash
|
||||
Copyright (C) 2007-2017 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// this file is split from MMU.h for the purpose of avoiding ridiculous recompile times
|
||||
// when changing it, because practically everything includes MMU.h.
|
||||
#ifndef MMUTIMING_H
|
||||
#define MMUTIMING_H
|
||||
|
||||
#include <algorithm>
|
||||
#include "MMU.h"
|
||||
#include "cp15.h"
|
||||
#include "readwrite.h"
|
||||
#include "debug.h"
|
||||
#include "NDSSystem.h"
|
||||
#include "emufile.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// MEMORY TIMING ACCURACY CONFIGURATION
|
||||
//
|
||||
// the more of these are enabled,
|
||||
// the more accurate memory access timing _should_ become.
|
||||
// they should be listed roughly in order of most to least important.
|
||||
// it's reasonable to disable some of these as a speed hack.
|
||||
// obviously, these defines don't cover all the variables or features needed,
|
||||
// and in particular, DMA or code+data access bus contention is still missing.
|
||||
|
||||
//disable this to prevent the advanced timing logic from ever running at all
|
||||
#define ENABLE_ADVANCED_TIMING
|
||||
|
||||
#ifdef ENABLE_ADVANCED_TIMING
|
||||
// makes non-sequential accesses slower than sequential ones.
|
||||
#define ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS
|
||||
//(SOMETIMES THIS IS A BIG SPEED HIT!)
|
||||
|
||||
// enables emulation of code fetch waits.
|
||||
#define ACCOUNT_FOR_CODE_FETCH_CYCLES
|
||||
|
||||
// makes access to DTCM (arm9 only) fast.
|
||||
#define ACCOUNT_FOR_DATA_TCM_SPEED
|
||||
|
||||
// enables simulation of cache hits and cache misses.
|
||||
#define ENABLE_CACHE_CONTROLLER_EMULATION
|
||||
|
||||
#endif //ENABLE_ADVANCED_TIMING
|
||||
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
FORCEINLINE bool USE_TIMING() {
|
||||
#ifdef ENABLE_ADVANCED_TIMING
|
||||
return CommonSettings.advanced_timing;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
enum MMU_ACCESS_DIRECTION
|
||||
{
|
||||
MMU_AD_READ, MMU_AD_WRITE
|
||||
};
|
||||
|
||||
|
||||
// note that we don't actually emulate the cache contents here,
|
||||
// only enough to guess what would be a cache hit or a cache miss.
|
||||
// this doesn't really get used unless ENABLE_CACHE_CONTROLLER_EMULATION is defined.
|
||||
template<int SIZESHIFT, int ASSOCIATIVESHIFT, int BLOCKSIZESHIFT>
|
||||
class CacheController
|
||||
{
|
||||
public:
|
||||
template<MMU_ACCESS_DIRECTION DIR>
|
||||
FORCEINLINE bool Cached(u32 addr)
|
||||
{
|
||||
u32 blockMasked = addr & BLOCKMASK;
|
||||
if(blockMasked == m_cacheCache)
|
||||
return true;
|
||||
else
|
||||
return this->CachedInternal<DIR>(addr, blockMasked);
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
for(int blockIndex = 0; blockIndex < NUMBLOCKS; blockIndex++)
|
||||
m_blocks[blockIndex].Reset();
|
||||
m_cacheCache = ~0;
|
||||
}
|
||||
CacheController()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void savestate(EMUFILE &os, int version)
|
||||
{
|
||||
os.write_32LE(m_cacheCache);
|
||||
for (int i = 0; i < NUMBLOCKS; i++)
|
||||
{
|
||||
for (int j = 0; j < ASSOCIATIVITY; j++)
|
||||
os.write_32LE(m_blocks[i].tag[j]);
|
||||
os.write_32LE(m_blocks[i].nextWay);
|
||||
}
|
||||
}
|
||||
bool loadstate(EMUFILE &is, int version)
|
||||
{
|
||||
is.read_32LE(m_cacheCache);
|
||||
for (int i = 0; i < NUMBLOCKS; i++)
|
||||
{
|
||||
for (int j = 0; j < ASSOCIATIVITY; j++)
|
||||
is.read_32LE(m_blocks[i].tag[j]);
|
||||
is.read_32LE(m_blocks[i].nextWay);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
template<MMU_ACCESS_DIRECTION DIR>
|
||||
bool CachedInternal(u32 addr, u32 blockMasked)
|
||||
{
|
||||
u32 blockIndex = blockMasked >> BLOCKSIZESHIFT;
|
||||
CacheBlock& block = m_blocks[blockIndex];
|
||||
addr &= TAGMASK;
|
||||
|
||||
for(int way = 0; way < ASSOCIATIVITY; way++)
|
||||
if(addr == block.tag[way])
|
||||
{
|
||||
// found it, already allocated
|
||||
m_cacheCache = blockMasked;
|
||||
return true;
|
||||
}
|
||||
if(DIR == MMU_AD_READ)
|
||||
{
|
||||
// TODO: support other allocation orders?
|
||||
block.tag[block.nextWay++] = addr;
|
||||
block.nextWay %= ASSOCIATIVITY;
|
||||
m_cacheCache = blockMasked;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
enum { SIZE = 1 << SIZESHIFT };
|
||||
enum { ASSOCIATIVITY = 1 << ASSOCIATIVESHIFT };
|
||||
enum { BLOCKSIZE = 1 << BLOCKSIZESHIFT };
|
||||
enum { TAGSHIFT = SIZESHIFT - ASSOCIATIVESHIFT };
|
||||
enum { TAGMASK = (u32)(~0U << TAGSHIFT) };
|
||||
enum { BLOCKMASK = ((u32)~0U >> (32 - TAGSHIFT)) & (u32)(~0U << BLOCKSIZESHIFT) };
|
||||
enum { WORDSIZE = sizeof(u32) };
|
||||
enum { WORDSPERBLOCK = (1 << BLOCKSIZESHIFT) / WORDSIZE };
|
||||
enum { DATAPERWORD = WORDSIZE * ASSOCIATIVITY };
|
||||
enum { DATAPERBLOCK = DATAPERWORD * WORDSPERBLOCK };
|
||||
enum { NUMBLOCKS = SIZE / DATAPERBLOCK };
|
||||
|
||||
struct CacheBlock
|
||||
{
|
||||
u32 tag [ASSOCIATIVITY];
|
||||
u32 nextWay;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
nextWay = 0;
|
||||
for(int way = 0; way < ASSOCIATIVITY; way++)
|
||||
tag[way] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
u32 m_cacheCache; // optimization
|
||||
|
||||
CacheBlock m_blocks [NUMBLOCKS];
|
||||
};
|
||||
|
||||
|
||||
template<int PROCNUM, MMU_ACCESS_TYPE AT, int READSIZE, MMU_ACCESS_DIRECTION DIRECTION, bool TIMING>
|
||||
FORCEINLINE u32 _MMU_accesstime(u32 addr, bool sequential);
|
||||
|
||||
|
||||
template<int PROCNUM, MMU_ACCESS_TYPE AT>
|
||||
class FetchAccessUnit
|
||||
{
|
||||
public:
|
||||
template<int READSIZE, MMU_ACCESS_DIRECTION DIRECTION, bool TIMING>
|
||||
FORCEINLINE u32 Fetch(u32 address)
|
||||
{
|
||||
#ifdef ACCOUNT_FOR_CODE_FETCH_CYCLES
|
||||
const bool prohibit = TIMING;
|
||||
#else
|
||||
const bool prohibit = false;
|
||||
#endif
|
||||
|
||||
if(AT == MMU_AT_CODE && !prohibit)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
u32 time = _MMU_accesstime<PROCNUM, AT, READSIZE, DIRECTION,TIMING>(address,
|
||||
#ifdef ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS
|
||||
(TIMING?
|
||||
(address == (m_lastAddress + (READSIZE>>3)))
|
||||
:true
|
||||
)
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
);
|
||||
|
||||
#ifdef ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS
|
||||
m_lastAddress = address;
|
||||
#endif
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_lastAddress = ~0;
|
||||
}
|
||||
FetchAccessUnit() { this->Reset(); }
|
||||
|
||||
void savestate(EMUFILE &os, int version)
|
||||
{
|
||||
os.write_32LE(m_lastAddress);
|
||||
}
|
||||
bool loadstate(EMUFILE &is, int version)
|
||||
{
|
||||
is.read_32LE(m_lastAddress);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
u32 m_lastAddress;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct MMU_struct_timing
|
||||
{
|
||||
// technically part of the cp15, but I didn't want the dereferencing penalty.
|
||||
// these template values correspond with the value of armcp15->cacheType.
|
||||
CacheController<13,2,5> arm9codeCache; // 8192 bytes, 4-way associative, 32-byte blocks
|
||||
CacheController<12,2,5> arm9dataCache; // 4096 bytes, 4-way associative, 32-byte blocks
|
||||
|
||||
// technically part of armcpu_t, but that struct isn't templated on PROCNUM
|
||||
FetchAccessUnit<0,MMU_AT_CODE> arm9codeFetch;
|
||||
FetchAccessUnit<0,MMU_AT_DATA> arm9dataFetch;
|
||||
FetchAccessUnit<1,MMU_AT_CODE> arm7codeFetch;
|
||||
FetchAccessUnit<1,MMU_AT_DATA> arm7dataFetch;
|
||||
|
||||
template<int PROCNUM> FORCEINLINE FetchAccessUnit<PROCNUM,MMU_AT_CODE>& armCodeFetch();
|
||||
template<int PROCNUM> FORCEINLINE FetchAccessUnit<PROCNUM,MMU_AT_DATA>& armDataFetch();
|
||||
};
|
||||
template<> FORCEINLINE FetchAccessUnit<0,MMU_AT_CODE>& MMU_struct_timing::armCodeFetch<0>() { return this->arm9codeFetch; }
|
||||
template<> FORCEINLINE FetchAccessUnit<1,MMU_AT_CODE>& MMU_struct_timing::armCodeFetch<1>() { return this->arm7codeFetch; }
|
||||
template<> FORCEINLINE FetchAccessUnit<0,MMU_AT_DATA>& MMU_struct_timing::armDataFetch<0>() { return this->arm9dataFetch; }
|
||||
template<> FORCEINLINE FetchAccessUnit<1,MMU_AT_DATA>& MMU_struct_timing::armDataFetch<1>() { return this->arm7dataFetch; }
|
||||
|
||||
|
||||
extern MMU_struct_timing MMU_timing;
|
||||
|
||||
|
||||
|
||||
// calculates the time a single memory access takes,
|
||||
// in units of cycles of the current processor.
|
||||
// this function replaces what used to be MMU_WAIT16 and MMU_WAIT32.
|
||||
// this may have side effects, so don't call it more than necessary.
|
||||
template<int PROCNUM, MMU_ACCESS_TYPE AT, int READSIZE, MMU_ACCESS_DIRECTION DIRECTION, bool TIMING>
|
||||
FORCEINLINE u32 _MMU_accesstime(u32 addr, bool sequential)
|
||||
{
|
||||
static const int MC = 1; // cached or tcm memory speed
|
||||
static const int M32 = (PROCNUM==ARMCPU_ARM9) ? 2 : 1; // access through 32-bit bus
|
||||
static const int M16 = M32 * ((READSIZE>16) ? 2 : 1); // access through 16-bit bus
|
||||
static const int MSLW = M16 * 8; // this needs tuning
|
||||
|
||||
if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_CODE && addr < 0x02000000)
|
||||
return MC; // ITCM
|
||||
|
||||
#ifdef ACCOUNT_FOR_DATA_TCM_SPEED
|
||||
if(TIMING && PROCNUM==ARMCPU_ARM9 && AT==MMU_AT_DATA && (addr&(~0x3FFF)) == MMU.DTCMRegion)
|
||||
return MC; // DTCM
|
||||
#endif
|
||||
|
||||
// for now, assume the cache is always enabled for all of main memory
|
||||
if(AT != MMU_AT_DMA && TIMING && PROCNUM==ARMCPU_ARM9 && (addr & 0x0F000000) == 0x02000000)
|
||||
{
|
||||
#ifdef ENABLE_CACHE_CONTROLLER_EMULATION
|
||||
bool cached = false;
|
||||
if(AT==MMU_AT_CODE)
|
||||
cached = MMU_timing.arm9codeCache.Cached<DIRECTION>(addr);
|
||||
if(AT==MMU_AT_DATA)
|
||||
cached = MMU_timing.arm9dataCache.Cached<DIRECTION>(addr);
|
||||
if(cached)
|
||||
return MC;
|
||||
u32 c;
|
||||
if(sequential && AT==MMU_AT_DATA)
|
||||
c = M16; // bonus for sequential data access
|
||||
else if(DIRECTION == MMU_AD_READ)
|
||||
c = M16 * 5;
|
||||
else
|
||||
c = M16 * 2; // should be 4, but write buffer isn't emulated yet.
|
||||
if(DIRECTION == MMU_AD_READ)
|
||||
{
|
||||
// cache miss while reading means it has to fill a whole cache line
|
||||
// by reading 32 bytes...
|
||||
c += 8 * M32*2;
|
||||
}
|
||||
|
||||
if(CheckDebugEvent(DEBUG_EVENT_CACHE_MISS))
|
||||
{
|
||||
DebugEventData.addr = addr;
|
||||
DebugEventData.size = READSIZE;
|
||||
HandleDebugEvent(DEBUG_EVENT_CACHE_MISS);
|
||||
}
|
||||
|
||||
return c;
|
||||
#elif defined(ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS)
|
||||
// this is the closest approximation I could find
|
||||
// to the with-cache-controller timing
|
||||
// that doesn't do any actual caching logic.
|
||||
return sequential ? MC : M16;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const TWaitState MMU_WAIT[16*16] = {
|
||||
// ITCM, ITCM, MAIN, SWI, REG, VMEM, LCD, OAM, ROM, ROM, RAM, U, U, U, U, BIOS
|
||||
#define X MC, MC, M16, M32, M32, M16, M16, M32, MSLW, MSLW, MSLW, M32,M32,M32,M32, M32,
|
||||
// duplicate it 16 times (this was somehow faster than using a mask of 0xF)
|
||||
X X X X X X X X X X X X X X X X
|
||||
#undef X
|
||||
};
|
||||
|
||||
u32 c = MMU_WAIT[(addr >> 24)];
|
||||
|
||||
#ifdef ACCOUNT_FOR_NON_SEQUENTIAL_ACCESS
|
||||
if(TIMING && !sequential)
|
||||
{
|
||||
//if(c != MC || PROCNUM==ARMCPU_ARM7) // check not needed anymore because ITCM/DTCM return earlier
|
||||
{
|
||||
c += (PROCNUM==ARMCPU_ARM9) ? 3*2 : 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// calculates the cycle time of a single memory access in the MEM stage.
|
||||
// to be used to calculate the memCycles argument for MMU_aluMemCycles.
|
||||
// this may have side effects, so don't call it more than necessary.
|
||||
template<int PROCNUM, int READSIZE, MMU_ACCESS_DIRECTION DIRECTION, bool TIMING>
|
||||
FORCEINLINE u32 MMU_memAccessCycles(u32 addr)
|
||||
{
|
||||
if(TIMING)
|
||||
return MMU_timing.armDataFetch<PROCNUM>().template Fetch<READSIZE,DIRECTION,true>((addr)&(~((READSIZE>>3)-1)));
|
||||
else
|
||||
return MMU_timing.armDataFetch<PROCNUM>().template Fetch<READSIZE,DIRECTION,false>((addr)&(~((READSIZE>>3)-1)));
|
||||
}
|
||||
|
||||
template<int PROCNUM, int READSIZE, MMU_ACCESS_DIRECTION DIRECTION>
|
||||
FORCEINLINE u32 MMU_memAccessCycles(u32 addr)
|
||||
{
|
||||
if(USE_TIMING())
|
||||
return MMU_memAccessCycles<PROCNUM,READSIZE,DIRECTION,true>(addr);
|
||||
else
|
||||
return MMU_memAccessCycles<PROCNUM,READSIZE,DIRECTION,false>(addr);
|
||||
}
|
||||
|
||||
// calculates the cycle time of a single code fetch in the FETCH stage
|
||||
// to be used to calculate the fetchCycles argument for MMU_fetchExecuteCycles.
|
||||
// this may have side effects, so don't call it more than necessary.
|
||||
template<int PROCNUM, int READSIZE>
|
||||
FORCEINLINE u32 MMU_codeFetchCycles(u32 addr)
|
||||
{
|
||||
if(USE_TIMING())
|
||||
return MMU_timing.armCodeFetch<PROCNUM>().template Fetch<READSIZE,MMU_AD_READ,true>((addr)&(~((READSIZE>>3)-1)));
|
||||
else
|
||||
return MMU_timing.armCodeFetch<PROCNUM>().template Fetch<READSIZE,MMU_AD_READ,false>((addr)&(~((READSIZE>>3)-1)));
|
||||
}
|
||||
|
||||
// calculates the cycle contribution of ALU + MEM stages (= EXECUTE)
|
||||
// given ALU cycle time and the summation of multiple memory access cycle times.
|
||||
// this function might belong more in armcpu, but I don't think it matters.
|
||||
template<int PROCNUM>
|
||||
FORCEINLINE u32 MMU_aluMemCycles(u32 aluCycles, u32 memCycles)
|
||||
{
|
||||
if(PROCNUM==ARMCPU_ARM9)
|
||||
{
|
||||
// ALU and MEM are different stages of the 5-stage pipeline.
|
||||
// we approximate the pipeline throughput using max,
|
||||
// since simply adding the cycles of each instruction together
|
||||
// fails to take into account the parallelism of the arm pipeline
|
||||
// and would make the emulated system unnaturally slow.
|
||||
return std::max(aluCycles, memCycles);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ALU and MEM are part of the same stage of the 3-stage pipeline,
|
||||
// thus they occur in sequence and we can simply add the counts together.
|
||||
return aluCycles + memCycles;
|
||||
}
|
||||
}
|
||||
|
||||
// calculates the cycle contribution of ALU + MEM stages (= EXECUTE)
|
||||
// given ALU cycle time and the description of a single memory access.
|
||||
// this may have side effects, so don't call it more than necessary.
|
||||
template<int PROCNUM, int READSIZE, MMU_ACCESS_DIRECTION DIRECTION>
|
||||
FORCEINLINE u32 MMU_aluMemAccessCycles(u32 aluCycles, u32 addr)
|
||||
{
|
||||
u32 memCycles;
|
||||
if(USE_TIMING())
|
||||
memCycles = MMU_memAccessCycles<PROCNUM,READSIZE,DIRECTION,true>(addr);
|
||||
else memCycles = MMU_memAccessCycles<PROCNUM,READSIZE,DIRECTION,false>(addr);
|
||||
return MMU_aluMemCycles<PROCNUM>(aluCycles, memCycles);
|
||||
}
|
||||
|
||||
// calculates the cycle contribution of FETCH + EXECUTE stages
|
||||
// given executeCycles = the combined ALU+MEM cycles
|
||||
// and fetchCycles = the cycle time of the FETCH stage
|
||||
// this function might belong more in armcpu, but I don't think it matters.
|
||||
template<int PROCNUM>
|
||||
FORCEINLINE u32 MMU_fetchExecuteCycles(u32 executeCycles, u32 fetchCycles)
|
||||
{
|
||||
#ifdef ACCOUNT_FOR_CODE_FETCH_CYCLES
|
||||
const bool allow = true;
|
||||
#else
|
||||
const bool allow = false;
|
||||
#endif
|
||||
|
||||
if(USE_TIMING() && allow)
|
||||
{
|
||||
// execute and fetch are different stages of the pipeline for both arm7 and arm9.
|
||||
// again, we approximate the pipeline throughput using max.
|
||||
return std::max(executeCycles, fetchCycles);
|
||||
// TODO: add an option to support conflict between MEM and FETCH cycles
|
||||
// if they're both using the same data bus.
|
||||
// in the case of a conflict this should be:
|
||||
// return std::max(aluCycles, memCycles + fetchCycles);
|
||||
}
|
||||
return executeCycles;
|
||||
}
|
||||
|
||||
|
||||
#endif //MMUTIMING_H
|
File diff suppressed because it is too large
Load Diff
|
@ -1,702 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2008-2022 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NDSSYSTEM_H
|
||||
#define NDSSYSTEM_H
|
||||
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "types.h"
|
||||
#include "ROMReader.h"
|
||||
#include "firmware.h"
|
||||
|
||||
class CFIRMWARE;
|
||||
class EMUFILE;
|
||||
|
||||
template<typename Type>
|
||||
struct buttonstruct {
|
||||
union {
|
||||
struct {
|
||||
// changing the order of these fields would break stuff
|
||||
//fRLDUTSBAYXWEg
|
||||
Type G; // debug
|
||||
Type E; // right shoulder
|
||||
Type W; // left shoulder
|
||||
Type X;
|
||||
Type Y;
|
||||
Type A;
|
||||
Type B;
|
||||
Type S; // start
|
||||
Type T; // select
|
||||
Type U; // up
|
||||
Type D; // down
|
||||
Type L; // left
|
||||
Type R; // right
|
||||
Type F; // lid
|
||||
};
|
||||
Type array[14];
|
||||
};
|
||||
};
|
||||
|
||||
extern buttonstruct<bool> Turbo;
|
||||
extern buttonstruct<u32> TurboTime;
|
||||
extern buttonstruct<bool> AutoHold;
|
||||
extern volatile bool execute;
|
||||
extern BOOL click;
|
||||
|
||||
/*
|
||||
* The firmware language values
|
||||
*/
|
||||
#define NDS_FW_LANG_JAP 0
|
||||
#define NDS_FW_LANG_ENG 1
|
||||
#define NDS_FW_LANG_FRE 2
|
||||
#define NDS_FW_LANG_GER 3
|
||||
#define NDS_FW_LANG_ITA 4
|
||||
#define NDS_FW_LANG_SPA 5
|
||||
#define NDS_FW_LANG_CHI 6
|
||||
#define NDS_FW_LANG_RES 7
|
||||
|
||||
extern CFIRMWARE *extFirmwareObj;
|
||||
|
||||
#define DSGBA_LOADER_SIZE 512
|
||||
enum
|
||||
{
|
||||
ROM_NDS = 0,
|
||||
ROM_DSGBA
|
||||
};
|
||||
|
||||
enum EmuHaltReasonCode
|
||||
{
|
||||
EMUHALT_REASON_USER_REQUESTED_HALT = 0,
|
||||
|
||||
EMUHALT_REASON_SYSTEM_POWERED_OFF = 1000,
|
||||
|
||||
EMUHALT_REASON_JIT_UNMAPPED_ADDRESS_EXCEPTION = 2000,
|
||||
EMUHALT_REASON_ARM_RESERVED_0X14_EXCEPTION,
|
||||
EMUHALT_REASON_ARM_UNDEFINED_INSTRUCTION_EXCEPTION,
|
||||
|
||||
EMUHALT_REASON_UNKNOWN = 10000
|
||||
};
|
||||
|
||||
enum NDSErrorCode
|
||||
{
|
||||
NDSError_NoError = 0,
|
||||
|
||||
NDSError_SystemPoweredOff = 1000,
|
||||
|
||||
NDSError_JITUnmappedAddressException = 2000,
|
||||
NDSError_ARMUndefinedInstructionException,
|
||||
|
||||
NDSError_UnknownError = 10000
|
||||
};
|
||||
|
||||
enum NDSErrorTag
|
||||
{
|
||||
NDSErrorTag_None = 0,
|
||||
NDSErrorTag_ARM9 = 1,
|
||||
NDSErrorTag_ARM7 = 2,
|
||||
NDSErrorTag_BothCPUs = 3,
|
||||
};
|
||||
|
||||
struct NDSError
|
||||
{
|
||||
NDSErrorCode code;
|
||||
NDSErrorTag tag;
|
||||
u32 programCounterARM9;
|
||||
u32 instructionARM9;
|
||||
u32 instructionAddrARM9;
|
||||
u32 programCounterARM7;
|
||||
u32 instructionARM7;
|
||||
u32 instructionAddrARM7;
|
||||
};
|
||||
typedef struct NDSError NDSError;
|
||||
|
||||
//#define LOG_ARM9
|
||||
//#define LOG_ARM7
|
||||
|
||||
#include "PACKED.h"
|
||||
struct NDS_header
|
||||
{
|
||||
char gameTile[12]; // 000 - Game Title (uppercase ASCII, padded with 00h)
|
||||
char gameCode[4]; // 00C - Gamecode (uppercase ASCII, NTR-<code>, 0=homebrew)
|
||||
u16 makerCode; // 010 - Makercode (uppercase ASCII, 0=homebrew)
|
||||
u8 unitCode; // 012 - Unitcode (00h=Nintendo DS)
|
||||
u8 deviceCode; // 013 - Encryption Seed Select (00..07h, usually 00h)
|
||||
u8 cardSize; // 014 - Devicecapacity (Chipsize = 128KB SHL nn) (eg. 7 = 16MB)
|
||||
u8 reserved1[8]; // 015 - Must be set to 0x00
|
||||
u8 region; // 01D - Specific region: 0x80 - China, 0x40 - Korea, 0x00 - Other
|
||||
u8 romversion; // 01E - ROM Version (usually 00h)
|
||||
u8 autostart; // 01F - Autostart (Bit2: Skip "Press Button" after Health and Safety)
|
||||
// (Also skips bootmenu, even in Manual mode & even Start pressed)
|
||||
u32 ARM9src; // 020 - ARM9 rom_offset (4000h and up, align 1000h)
|
||||
u32 ARM9exe; // 024 - ARM9 entry_address (2000000h..23BFE00h)
|
||||
u32 ARM9cpy; // 028 - ARM9 ram_address (2000000h..23BFE00h)
|
||||
u32 ARM9binSize; // 02C - ARM9 size (max 3BFE00h) (3839.5KB)
|
||||
|
||||
u32 ARM7src; // 030 - ARM7 rom_offset (8000h and up)
|
||||
u32 ARM7exe; // 034 - ARM7 entry_address (2000000h..23BFE00h, or 37F8000h..3807E00h)
|
||||
u32 ARM7cpy; // 038 - ARM7 ram_address (2000000h..23BFE00h, or 37F8000h..3807E00h)
|
||||
u32 ARM7binSize; // 03C - ARM7 size (max 3BFE00h, or FE00h) (3839.5KB, 63.5KB)
|
||||
|
||||
u32 FNameTblOff; // 040 - File Name Table (FNT) offset
|
||||
u32 FNameTblSize; // 044 - File Name Table (FNT) size
|
||||
|
||||
u32 FATOff; // 048 - File Allocation Table (FAT) offset
|
||||
u32 FATSize; // 04C - File Allocation Table (FAT) size
|
||||
|
||||
u32 ARM9OverlayOff; // 050 - File ARM9 overlay_offset
|
||||
u32 ARM9OverlaySize; // 054 - File ARM9 overlay_size
|
||||
u32 ARM7OverlayOff; // 058 - File ARM7 overlay_offset
|
||||
u32 ARM7OverlaySize; // 05C - File ARM7 overlay_size
|
||||
|
||||
u32 normalCmd; // 060 - Port 40001A4h setting for normal commands (usually 00586000h)
|
||||
u32 Key1Cmd; // 064 - Port 40001A4h setting for KEY1 commands (usually 001808F8h)
|
||||
|
||||
u32 IconOff; // 068 - Icon_title_offset (0=None) (8000h and up)
|
||||
u16 CRC16; // 06C - Secure Area Checksum, CRC-16 of [ [20h]..7FFFh] - Calculations with this algorithm use 0xffff as the initial value
|
||||
u16 ROMtimeout; // 06E - Secure Area Loading Timeout (usually 051Eh)
|
||||
u32 ARM9autoload; // 070 - ARM9 Auto Load List RAM Address
|
||||
u32 ARM7autoload; // 074 - ARM7 Auto Load List RAM Address
|
||||
|
||||
u8 infoResevedRegion[8]; // 078 - ROM Information Reserved Region (must be set to 0x00)
|
||||
u32 endROMoffset; // 080 - Total Used ROM size (remaining/unused bytes usually FFh-padded)
|
||||
u32 HeaderSize; // 084 - ROM Header Size (4000h)
|
||||
u32 ARM9module; // 088 - ARM9 Module Parameter Address (auto-load parameters)
|
||||
u32 ARM7module; // 08C - ARM7 Module Parameter Address (auto-load parameters)
|
||||
u8 reserved2[48]; // 090 - Must be set to 0x00 - "PASS" is contained within here?
|
||||
u8 logo[156]; // 0C0 - Nintendo Logo (compressed bitmap, same as in GBA Headers)
|
||||
u16 logoCRC16; // 15C - Nintendo Logo Checksum, CRC-16 of [0C0h-15Bh], fixed CF56h
|
||||
u16 headerCRC16; // 15E - Header Checksum, CRC-16 of [000h-15Dh]
|
||||
u8 reserved[160]; // Must be set to 0x00
|
||||
};
|
||||
#include "PACKED_END.h"
|
||||
|
||||
extern void debug();
|
||||
NDSError NDS_GetLastError();
|
||||
void emu_halt(EmuHaltReasonCode reasonCode, NDSErrorTag errorTag);
|
||||
|
||||
extern u64 nds_timer;
|
||||
void NDS_Reschedule();
|
||||
void NDS_RescheduleGXFIFO(u32 cost);
|
||||
void NDS_RescheduleDMA();
|
||||
void NDS_RescheduleReadSlot1(int procnum, int size);
|
||||
void NDS_RescheduleTimers();
|
||||
|
||||
enum ENSATA_HANDSHAKE
|
||||
{
|
||||
ENSATA_HANDSHAKE_none = 0,
|
||||
ENSATA_HANDSHAKE_query = 1,
|
||||
ENSATA_HANDSHAKE_ack = 2,
|
||||
ENSATA_HANDSHAKE_confirm = 3,
|
||||
ENSATA_HANDSHAKE_complete = 4
|
||||
};
|
||||
|
||||
enum NDS_CONSOLE_TYPE
|
||||
{
|
||||
NDS_CONSOLE_TYPE_FAT = 0xFF,
|
||||
NDS_CONSOLE_TYPE_LITE = 0x20,
|
||||
NDS_CONSOLE_TYPE_IQUE = 0x43,
|
||||
NDS_CONSOLE_TYPE_IQUE_LITE = 0x63,
|
||||
NDS_CONSOLE_TYPE_DSI = 0xFE
|
||||
};
|
||||
|
||||
struct NDSSystem
|
||||
{
|
||||
s32 wifiCycle;
|
||||
s32 cycles;
|
||||
u64 timerCycle[2][4];
|
||||
u32 VCount;
|
||||
u32 old;
|
||||
u8 overclock;
|
||||
|
||||
//raw adc touch coords for old NDS
|
||||
u16 adc_touchX;
|
||||
u16 adc_touchY;
|
||||
s32 adc_jitterctr;
|
||||
|
||||
//the DSI returns calibrated touch coords from its TSC (?), so we need to save these separately
|
||||
u16 scr_touchX;
|
||||
u16 scr_touchY;
|
||||
|
||||
//whether the console is using our faked-bootup process
|
||||
BOOL isFakeBooted;
|
||||
|
||||
BOOL isTouch;
|
||||
|
||||
u16 paddle;
|
||||
|
||||
u8 *FW_ARM9BootCode;
|
||||
u8 *FW_ARM7BootCode;
|
||||
u32 FW_ARM9BootCodeAddr;
|
||||
u32 FW_ARM7BootCodeAddr;
|
||||
u32 FW_ARM9BootCodeSize;
|
||||
u32 FW_ARM7BootCodeSize;
|
||||
|
||||
BOOL sleeping;
|
||||
BOOL cardEjected;
|
||||
u32 freezeBus;
|
||||
|
||||
//this is not essential NDS runtime state.
|
||||
//it was perhaps a mistake to put it here.
|
||||
//it is far less important than the above.
|
||||
//maybe I should move it.
|
||||
s32 idleCycles[2];
|
||||
s32 runCycleCollector[2][16];
|
||||
s32 idleFrameCounter;
|
||||
s32 cpuloopIterationCount; //counts the number of times during a frame that a reschedule happened
|
||||
|
||||
//console type must be copied in when the system boots. it can't be changed on the fly.
|
||||
int ConsoleType;
|
||||
bool Is_DSI() { return ConsoleType == NDS_CONSOLE_TYPE_DSI; }
|
||||
bool Is_DebugConsole() { return _DebugConsole!=0; }
|
||||
BOOL _DebugConsole;
|
||||
|
||||
//set if the user requests ensata emulation
|
||||
BOOL ensataEmulation;
|
||||
|
||||
//there is a hack in the ipc sync for ensata. this tracks its state
|
||||
u32 ensataIpcSyncCounter;
|
||||
|
||||
//maintains the state of the ensata handshaking protocol
|
||||
u32 ensataHandshake;
|
||||
|
||||
struct {
|
||||
u8 lcd, gpuMain, gfx3d_render, gfx3d_geometry, gpuSub, dispswap;
|
||||
} power1; //POWCNT1
|
||||
|
||||
struct {
|
||||
u8 speakers, wifi /*(initial value=0)*/;
|
||||
} power2; //POWCNT2
|
||||
|
||||
BOOL power_render, power_geometry;
|
||||
|
||||
bool isInVblank() const { return VCount >= 192; }
|
||||
bool isIn3dVblank() const { return VCount >= 192 && VCount<215; }
|
||||
};
|
||||
|
||||
extern NDSSystem nds;
|
||||
|
||||
int NDS_Init();
|
||||
|
||||
void Desmume_InitOnce();
|
||||
|
||||
void NDS_DeInit(void);
|
||||
|
||||
BOOL NDS_SetROM(u8 * rom, u32 mask);
|
||||
NDS_header * NDS_getROMHeader(void);
|
||||
|
||||
struct RomBanner
|
||||
{
|
||||
RomBanner(bool defaultInit = true);
|
||||
u16 version; //Version (0001h)
|
||||
u16 crc16; //CRC16 across entries 020h..83Fh
|
||||
u8 reserved[0x1C]; //Reserved (zero-filled)
|
||||
u8 bitmap[0x200]; //Icon Bitmap (32x32 pix) (4x4 tiles, each 4x8 bytes, 4bit depth)
|
||||
u16 palette[0x10]; //Icon Palette (16 colors, 16bit, range 0000h-7FFFh) (Color 0 is transparent, so the 1st palette entry is ignored)
|
||||
enum { NUM_TITLES = 6 };
|
||||
union {
|
||||
struct {
|
||||
u16 title_jp[0x80]; //Title 0 Japanese (128 characters, 16bit Unicode)
|
||||
u16 title_en[0x80]; //Title 1 English ("")
|
||||
u16 title_fr[0x80]; //Title 2 French ("")
|
||||
u16 title_de[0x80]; //Title 3 German ("")
|
||||
u16 title_it[0x80]; //Title 4 Italian ("")
|
||||
u16 title_es[0x80]; //Title 5 Spanish ("")
|
||||
};
|
||||
u16 titles[NUM_TITLES][0x80];
|
||||
};
|
||||
u8 end0xFF[0x1C0];
|
||||
//840h ? (Maybe newer/chinese firmware do also support chinese title?)
|
||||
//840h - End of Icon/Title structure (next 1C0h bytes usually FFh-filled)
|
||||
};
|
||||
|
||||
struct GameInfo
|
||||
{
|
||||
void *fROM;
|
||||
ROMReader_struct *reader;
|
||||
u8 *romdataForReader;
|
||||
u32 romsize;
|
||||
u32 cardSize;
|
||||
u32 mask;
|
||||
u32 crc;
|
||||
u32 crcForCheatsDb;
|
||||
u32 chipID;
|
||||
u32 romType;
|
||||
u32 headerOffset;
|
||||
char ROMserial[20];
|
||||
char ROMname[13];
|
||||
bool _isDSiEnhanced;
|
||||
NDS_header header;
|
||||
//a copy of the pristine secure area from the rom
|
||||
u8 secureArea[0x4000];
|
||||
RomBanner banner;
|
||||
const RomBanner& getRomBanner();
|
||||
|
||||
GameInfo() : fROM(NULL),
|
||||
romdataForReader(NULL),
|
||||
crc(0),
|
||||
chipID(0x00000FC2),
|
||||
romsize(0),
|
||||
cardSize(0),
|
||||
mask(0),
|
||||
romType(ROM_NDS),
|
||||
headerOffset(0),
|
||||
_isDSiEnhanced(false)
|
||||
{
|
||||
memset(&header, 0, sizeof(header));
|
||||
memset(&ROMserial[0], 0, sizeof(ROMserial));
|
||||
memset(&ROMname[0], 0, sizeof(ROMname));
|
||||
}
|
||||
|
||||
~GameInfo() { closeROM(); }
|
||||
|
||||
bool IsCode(const char* code) const;
|
||||
|
||||
bool loadROM(std::string fname, u32 type = ROM_NDS);
|
||||
void closeROM();
|
||||
u32 readROM(u32 pos);
|
||||
bool ValidateHeader();
|
||||
void populate();
|
||||
bool isDSiEnhanced();
|
||||
bool isHomebrew();
|
||||
bool hasRomBanner();
|
||||
|
||||
};
|
||||
|
||||
typedef struct TSCalInfo
|
||||
{
|
||||
struct
|
||||
{
|
||||
u16 x1, x2;
|
||||
u16 y1, y2;
|
||||
u16 width;
|
||||
u16 height;
|
||||
} adc;
|
||||
|
||||
struct
|
||||
{
|
||||
u8 x1, x2;
|
||||
u8 y1, y2;
|
||||
u16 width;
|
||||
u16 height;
|
||||
} scr;
|
||||
|
||||
} TSCalInfo;
|
||||
|
||||
extern GameInfo gameInfo;
|
||||
|
||||
extern std::vector<u32> memReadBreakPoints;
|
||||
extern std::vector<u32> memWriteBreakPoints;
|
||||
|
||||
|
||||
struct UserButtons : buttonstruct<bool>
|
||||
{
|
||||
};
|
||||
struct UserTouch
|
||||
{
|
||||
u16 touchX;
|
||||
u16 touchY;
|
||||
bool isTouch;
|
||||
};
|
||||
struct UserMicrophone
|
||||
{
|
||||
u32 micButtonPressed;
|
||||
u8 micSample;
|
||||
};
|
||||
struct UserInput
|
||||
{
|
||||
UserButtons buttons;
|
||||
UserTouch touch;
|
||||
UserMicrophone mic;
|
||||
};
|
||||
|
||||
// set physical user input
|
||||
// these functions merely request the input to be changed.
|
||||
// the actual change happens later at a specific time during the frame.
|
||||
// this is to minimize the risk of desyncs.
|
||||
void NDS_setTouchPos(u16 x, u16 y);
|
||||
void NDS_releaseTouch(void);
|
||||
void NDS_setPad(bool right,bool left,bool down,bool up,bool select,bool start,bool B,bool A,bool Y,bool X,bool leftShoulder,bool rightShoulder,bool debug, bool lid);
|
||||
void NDS_setMic(bool pressed);
|
||||
|
||||
// get physical user input
|
||||
// not including the results of autofire/etc.
|
||||
// the effects of calls to "set physical user input" functions will be immediately reflected here though.
|
||||
const UserInput& NDS_getRawUserInput();
|
||||
const UserInput& NDS_getPrevRawUserInput();
|
||||
|
||||
// get final (fully processed) user input
|
||||
// this should match whatever was or would be sent to the game
|
||||
const UserInput& NDS_getFinalUserInput();
|
||||
|
||||
// set/get to-be-processed or in-the-middle-of-being-processed user input
|
||||
// to process input, simply call this function and edit the return value.
|
||||
// (applying autofire is one example of processing the input.)
|
||||
// (movie playback is another example.)
|
||||
// this must be done after the raw user input is set
|
||||
// and before that input is sent to the game's memory.
|
||||
UserInput& NDS_getProcessingUserInput();
|
||||
bool NDS_isProcessingUserInput();
|
||||
// call once per frame to prepare input for processing
|
||||
void NDS_beginProcessingInput();
|
||||
// call once per frame to copy the processed input to the final input
|
||||
void NDS_endProcessingInput();
|
||||
|
||||
// this is in case something needs reentrancy while processing input
|
||||
void NDS_suspendProcessingInput(bool suspend);
|
||||
|
||||
|
||||
|
||||
int NDS_LoadROM(const char *filename, const char* physicalFilename=0, const char* logicalFilename=0);
|
||||
void NDS_FreeROM(void);
|
||||
void NDS_Reset();
|
||||
|
||||
bool NDS_LegitBoot();
|
||||
bool NDS_FakeBoot();
|
||||
|
||||
void nds_savestate(EMUFILE &os);
|
||||
bool nds_loadstate(EMUFILE &is, int size);
|
||||
|
||||
void NDS_Sleep();
|
||||
void NDS_TriggerCardEjectIRQ();
|
||||
|
||||
void NDS_SkipNextFrame();
|
||||
#define NDS_SkipFrame(s) if(s) NDS_SkipNext2DFrame();
|
||||
void NDS_OmitFrameSkip(int force=0);
|
||||
|
||||
void NDS_debug_break();
|
||||
void NDS_debug_continue();
|
||||
void NDS_debug_step();
|
||||
|
||||
int NDS_GetCPUCoreCount();
|
||||
void NDS_GetCPULoadAverage(u32 &outLoadAvgARM9, u32 &outLoadAvgARM7);
|
||||
void NDS_SetupDefaultFirmware();
|
||||
|
||||
//void execHardware_doAllDma(EDMAMode modeNum);
|
||||
|
||||
template<bool FORCE> void NDS_exec(s32 nb = 560190<<1);
|
||||
|
||||
extern int lagframecounter;
|
||||
|
||||
extern struct TCommonSettings
|
||||
{
|
||||
TCommonSettings()
|
||||
: GFX3D_HighResolutionInterpolateColor(true)
|
||||
, GFX3D_EdgeMark(true)
|
||||
, GFX3D_Fog(true)
|
||||
, GFX3D_Texture(true)
|
||||
, GFX3D_LineHack(true)
|
||||
, GFX3D_Renderer_MultisampleSize(0)
|
||||
, GFX3D_Renderer_TextureScalingFactor(1) // Possible values: 1, 2, 4
|
||||
, GFX3D_Renderer_TextureDeposterize(false)
|
||||
, GFX3D_Renderer_TextureSmoothing(false)
|
||||
, GFX3D_TXTHack(false)
|
||||
, OpenGL_Emulation_ShadowPolygon(true)
|
||||
, OpenGL_Emulation_SpecialZeroAlphaBlending(true)
|
||||
, OpenGL_Emulation_NDSDepthCalculation(true)
|
||||
, OpenGL_Emulation_DepthLEqualPolygonFacing(false)
|
||||
, jit_max_block_size(12)
|
||||
, loadToMemory(false)
|
||||
, UseExtBIOS(false)
|
||||
, SWIFromBIOS(false)
|
||||
, PatchSWI3(false)
|
||||
, UseExtFirmware(false)
|
||||
, UseExtFirmwareSettings(false)
|
||||
, RetailCardProtection8000(true)
|
||||
, BootFromFirmware(false)
|
||||
, DebugConsole(false)
|
||||
, EnsataEmulation(false)
|
||||
, cheatsDisable(false)
|
||||
, rigorous_timing(false)
|
||||
, advanced_timing(true)
|
||||
, micMode(InternalNoise)
|
||||
, spuInterpolationMode(2)
|
||||
, manualBackupType(0)
|
||||
, autodetectBackupMethod(0)
|
||||
, spu_captureMuted(false)
|
||||
, spu_advanced(true)
|
||||
, StylusPressure(50)
|
||||
, ConsoleType(NDS_CONSOLE_TYPE_FAT)
|
||||
, backupSave(false)
|
||||
, SPU_sync_mode(1)
|
||||
, SPU_sync_method(0)
|
||||
, WifiBridgeDeviceID(0)
|
||||
{
|
||||
strcpy(ARM9BIOS, "biosnds9.bin");
|
||||
strcpy(ARM7BIOS, "biosnds7.bin");
|
||||
strcpy(ExtFirmwarePath, "firmware.bin");
|
||||
|
||||
for(int i=0;i<16;i++)
|
||||
spu_muteChannels[i] = false;
|
||||
|
||||
for(int g=0;g<2;g++)
|
||||
for(int x=0;x<5;x++)
|
||||
dispLayers[g][x]=true;
|
||||
#ifdef HAVE_JIT
|
||||
//zero 06-sep-2012 - shouldnt be defaulting this to true for now, since the jit is buggy.
|
||||
//id rather have people discover a bonus speedhack than discover new bugs in a new version
|
||||
use_jit = false;
|
||||
#else
|
||||
use_jit = false;
|
||||
#endif
|
||||
|
||||
num_cores = NDS_GetCPUCoreCount();
|
||||
NDS_SetupDefaultFirmware();
|
||||
}
|
||||
bool GFX3D_HighResolutionInterpolateColor;
|
||||
bool GFX3D_EdgeMark;
|
||||
bool GFX3D_Fog;
|
||||
bool GFX3D_Texture;
|
||||
bool GFX3D_LineHack;
|
||||
int GFX3D_Renderer_MultisampleSize;
|
||||
int GFX3D_Renderer_TextureScalingFactor; //must be one of {1,2,4}
|
||||
bool GFX3D_Renderer_TextureDeposterize;
|
||||
bool GFX3D_Renderer_TextureSmoothing;
|
||||
bool GFX3D_TXTHack;
|
||||
|
||||
bool OpenGL_Emulation_ShadowPolygon;
|
||||
bool OpenGL_Emulation_SpecialZeroAlphaBlending;
|
||||
bool OpenGL_Emulation_NDSDepthCalculation;
|
||||
bool OpenGL_Emulation_DepthLEqualPolygonFacing;
|
||||
|
||||
bool loadToMemory;
|
||||
|
||||
bool UseExtBIOS;
|
||||
char ARM9BIOS[MAX_PATH];
|
||||
char ARM7BIOS[MAX_PATH];
|
||||
bool SWIFromBIOS;
|
||||
bool PatchSWI3;
|
||||
|
||||
bool RetailCardProtection8000;
|
||||
bool UseExtFirmware;
|
||||
bool UseExtFirmwareSettings;
|
||||
char ExtFirmwarePath[MAX_PATH];
|
||||
char ExtFirmwareUserSettingsPath[MAX_PATH];
|
||||
bool BootFromFirmware;
|
||||
FirmwareConfig fwConfig;
|
||||
|
||||
NDS_CONSOLE_TYPE ConsoleType;
|
||||
bool DebugConsole;
|
||||
bool EnsataEmulation;
|
||||
|
||||
bool cheatsDisable;
|
||||
|
||||
int num_cores;
|
||||
bool single_core() { return num_cores==1; }
|
||||
bool rigorous_timing;
|
||||
|
||||
struct GameHacks {
|
||||
GameHacks()
|
||||
: en(true)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
bool en;
|
||||
|
||||
struct {
|
||||
bool overclock;
|
||||
bool stylusjitter;
|
||||
} flags;
|
||||
|
||||
void apply();
|
||||
void clear();
|
||||
} gamehacks;
|
||||
|
||||
int StylusPressure;
|
||||
|
||||
bool dispLayers[2][5];
|
||||
|
||||
FAST_ALIGN bool advanced_timing;
|
||||
|
||||
bool use_jit;
|
||||
u32 jit_max_block_size;
|
||||
|
||||
int WifiBridgeDeviceID;
|
||||
|
||||
enum MicMode
|
||||
{
|
||||
InternalNoise = 0,
|
||||
Sample = 1,
|
||||
Random = 2,
|
||||
Physical = 3
|
||||
} micMode;
|
||||
|
||||
|
||||
int spuInterpolationMode;
|
||||
|
||||
//this is a temporary hack until we straighten out the flushing logic and/or gxfifo
|
||||
//int gfx3d_flushMode;
|
||||
|
||||
int autodetectBackupMethod;
|
||||
//this is the user's choice of manual backup type, for cases when the autodetection can't be trusted
|
||||
int manualBackupType;
|
||||
bool backupSave;
|
||||
|
||||
int SPU_sync_mode;
|
||||
int SPU_sync_method;
|
||||
|
||||
bool spu_muteChannels[16];
|
||||
bool spu_captureMuted;
|
||||
bool spu_advanced;
|
||||
|
||||
struct _ShowGpu {
|
||||
_ShowGpu() : main(true), sub(true) {}
|
||||
union {
|
||||
struct { bool main,sub; };
|
||||
bool screens[2];
|
||||
};
|
||||
} showGpu;
|
||||
|
||||
struct _Hud {
|
||||
_Hud()
|
||||
: ShowInputDisplay(false)
|
||||
, ShowGraphicalInputDisplay(false)
|
||||
, FpsDisplay(false)
|
||||
, FrameCounterDisplay(false)
|
||||
, ShowLagFrameCounter(false)
|
||||
, ShowMicrophone(false)
|
||||
, ShowRTC(false)
|
||||
{}
|
||||
bool ShowInputDisplay, ShowGraphicalInputDisplay, FpsDisplay, FrameCounterDisplay, ShowLagFrameCounter, ShowMicrophone, ShowRTC;
|
||||
} hud;
|
||||
|
||||
std::string run_advanscene_import;
|
||||
|
||||
} CommonSettings;
|
||||
|
||||
void NDS_RunAdvansceneAutoImport();
|
||||
|
||||
extern std::string InputDisplayString;
|
||||
extern int LagFrameFlag;
|
||||
extern int lastLag, TotalLagFrames;
|
||||
extern u8 MicSampleSelection;
|
||||
extern std::vector< std::vector<u8> > micSamples;
|
||||
|
||||
void MovieSRAM();
|
||||
|
||||
void ClearAutoHold(void);
|
||||
|
||||
bool ValidateSlot2Access(u32 procnum, u32 demandSRAMSpeed, u32 demand1stROMSpeed, u32 demand2ndROMSpeed, int clockbits);
|
||||
|
||||
//MUSTANG
|
||||
//extern ADVANsCEne advsc;
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,176 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2007 shash
|
||||
Copyright (C) 2008-2024 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OGLRENDER_3_2_H
|
||||
#define OGLRENDER_3_2_H
|
||||
|
||||
#include "OGLRender.h"
|
||||
|
||||
#define MAX_CLIPPED_POLY_COUNT_FOR_UBO 16384
|
||||
|
||||
extern const char *GeometryVtxShader_150;
|
||||
extern const char *GeometryFragShader_150;
|
||||
extern const char *GeometryZeroDstAlphaPixelMaskVtxShader_150;
|
||||
extern const char *GeometryZeroDstAlphaPixelMaskFragShader_150;
|
||||
extern const char *MSGeometryZeroDstAlphaPixelMaskFragShader_150;
|
||||
extern const char *ClearImageVtxShader_150;
|
||||
extern const char *ClearImageFragShader_150;
|
||||
extern const char *EdgeMarkVtxShader_150;
|
||||
extern const char *EdgeMarkFragShader_150;
|
||||
extern const char *FogVtxShader_150;
|
||||
extern const char *FogFragShader_150;
|
||||
extern const char *FramebufferOutputVtxShader_150;
|
||||
extern const char *FramebufferOutput6665FragShader_150;
|
||||
|
||||
// A port that wants to use the OpenGL 3.2 renderer must assign the two following functions
|
||||
// to OGLLoadEntryPoints_3_2_Func and OGLCreateRenderer_3_2_Func, respectively.
|
||||
//
|
||||
// In addition, the port must add the following GPU3DInterface objects to core3DList:
|
||||
// - gpu3Dgl: Automatically selects the most fully featured version of standard OpenGL that
|
||||
// is available on the host system, prefering OpenGL 3.2 Core Profile.
|
||||
// - gpu3Dgl_3_2: Selects the OpenGL 3.2 Core Profile renderer, and returns an error if it
|
||||
// is not available on the host system.
|
||||
//
|
||||
// Finally, the port must call GPU->Set3DRendererByID() and pass in the index where
|
||||
// gpu3Dgl_3_2 exists in core3DList so that the emulator can create the appropriate
|
||||
// OpenGLRenderer object.
|
||||
//
|
||||
// Example code:
|
||||
// OGLLoadEntryPoints_3_2_Func = &OGLLoadEntryPoints_3_2;
|
||||
// OGLCreateRenderer_3_2_Func = &OGLCreateRenderer_3_2;
|
||||
// GPU3DInterface *core3DList[] = { &gpu3DNull, &gpu3DRasterize, &gpu3Dgl_3_2, NULL };
|
||||
// GPU->Set3DRendererByID(2);
|
||||
|
||||
void OGLLoadEntryPoints_3_2();
|
||||
void OGLCreateRenderer_3_2(OpenGLRenderer **rendererPtr);
|
||||
|
||||
class OpenGLGeometryResource : public Render3DResourceGeometry
|
||||
{
|
||||
protected:
|
||||
GLuint _vboID[3];
|
||||
GLuint _eboID[3];
|
||||
GLuint _vaoID[3];
|
||||
GLuint _uboPolyStatesID[3];
|
||||
GLuint _tboPolyStatesID[3];
|
||||
GLuint _texPolyStatesID[3];
|
||||
GLsync _syncGeometryRender[3];
|
||||
|
||||
u16 *_indexBuffer[3];
|
||||
OGLPolyStates *_polyStatesBuffer[3];
|
||||
|
||||
public:
|
||||
OpenGLGeometryResource(const OpenGLVariantID variantID);
|
||||
~OpenGLGeometryResource();
|
||||
|
||||
size_t BindWrite(const size_t rawVtxCount, const size_t clippedPolyCount);
|
||||
|
||||
size_t BindUsage();
|
||||
size_t UnbindUsage();
|
||||
size_t RebindUsage();
|
||||
|
||||
u16* GetIndexBuffer(const size_t index);
|
||||
OGLPolyStates* GetPolyStatesBuffer(const size_t index);
|
||||
bool IsPolyStatesBufferUBO();
|
||||
bool IsPolyStatesBufferTBO();
|
||||
};
|
||||
|
||||
class OpenGLRenderStatesResource : public Render3DResource
|
||||
{
|
||||
protected:
|
||||
GLsync _sync[3];
|
||||
GLuint _uboRenderStatesID[3];
|
||||
OGLRenderStates *_buffer[3];
|
||||
|
||||
public:
|
||||
OpenGLRenderStatesResource();
|
||||
~OpenGLRenderStatesResource();
|
||||
|
||||
size_t BindWrite();
|
||||
size_t BindUsage();
|
||||
size_t UnbindUsage();
|
||||
|
||||
OGLRenderStates* GetRenderStatesBuffer(const size_t index);
|
||||
};
|
||||
|
||||
class OpenGLRenderer_3_2 : public OpenGLRenderer_2_1
|
||||
{
|
||||
protected:
|
||||
bool _isShaderFixedLocationSupported;
|
||||
bool _isConservativeDepthSupported;
|
||||
bool _isConservativeDepthAMDSupported;
|
||||
|
||||
OpenGLGeometryResource *_gResource;
|
||||
OpenGLRenderStatesResource *_rsResource;
|
||||
|
||||
virtual Render3DError CreateVBOs();
|
||||
virtual Render3DError CreatePBOs();
|
||||
virtual Render3DError CreateFBOs();
|
||||
virtual void DestroyFBOs();
|
||||
virtual Render3DError CreateMultisampledFBO(GLsizei numSamples);
|
||||
virtual void DestroyMultisampledFBO();
|
||||
virtual void ResizeMultisampledFBOs(GLsizei numSamples);
|
||||
virtual Render3DError CreateVAOs();
|
||||
virtual void DestroyVAOs();
|
||||
|
||||
virtual Render3DError CreateGeometryPrograms();
|
||||
virtual Render3DError CreateClearImageProgram(const char *vsCString, const char *fsCString);
|
||||
virtual void DestroyClearImageProgram();
|
||||
virtual Render3DError CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual Render3DError CreateMSGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual void DestroyMSGeometryZeroDstAlphaProgram();
|
||||
virtual Render3DError CreateEdgeMarkProgram(const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual Render3DError CreateFramebufferOutput6665Program(const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual Render3DError CreateFramebufferOutput8888Program(const char *vtxShaderCString, const char *fragShaderCString);
|
||||
|
||||
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
|
||||
virtual void _SetupGeometryShaders(const OGLGeometryFlags flags);
|
||||
virtual void _RenderGeometryVertexAttribEnable();
|
||||
virtual void _RenderGeometryVertexAttribDisable();
|
||||
virtual Render3DError ZeroDstAlphaPass(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
|
||||
virtual void _RenderGeometryLoopBegin();
|
||||
virtual void _RenderGeometryLoopEnd();
|
||||
virtual void _ResolveWorkingBackFacing();
|
||||
virtual void _ResolveGeometry();
|
||||
virtual void _ResolveFinalFramebuffer();
|
||||
virtual void _FramebufferProcessVertexAttribEnable();
|
||||
virtual void _FramebufferProcessVertexAttribDisable();
|
||||
virtual Render3DError _FramebufferConvertColorFormat();
|
||||
|
||||
virtual Render3DError BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList);
|
||||
virtual Render3DError PostprocessFramebuffer();
|
||||
|
||||
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID);
|
||||
virtual Render3DError ClearUsingValues(const Color4u8 &clearColor6665, const FragmentAttributes &clearAttributes);
|
||||
|
||||
virtual void SetPolygonIndex(const size_t index);
|
||||
virtual Render3DError SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer, bool isBackFacing);
|
||||
virtual Render3DError SetupTexture(const POLY &thePoly, size_t polyRenderIndex);
|
||||
|
||||
public:
|
||||
OpenGLRenderer_3_2();
|
||||
~OpenGLRenderer_3_2();
|
||||
|
||||
virtual Render3DError InitExtensions();
|
||||
virtual Render3DError RenderFinish();
|
||||
virtual Render3DError RenderPowerOff();
|
||||
virtual Render3DError SetFramebufferSize(size_t w, size_t h);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,963 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2024 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "OGLRender_ES3.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "utils/bits.h"
|
||||
#include "common.h"
|
||||
#include "debug.h"
|
||||
#include "NDSSystem.h"
|
||||
|
||||
|
||||
static const GLenum GeometryDrawBuffersEnumES[8][4] = {
|
||||
{ OGL_COLOROUT_ATTACHMENT_ID, GL_NONE, GL_NONE, GL_NONE },
|
||||
{ OGL_COLOROUT_ATTACHMENT_ID, GL_NONE, GL_NONE, OGL_FOGATTRIBUTES_ATTACHMENT_ID },
|
||||
{ OGL_COLOROUT_ATTACHMENT_ID, GL_NONE, OGL_POLYID_ATTACHMENT_ID, GL_NONE },
|
||||
{ OGL_COLOROUT_ATTACHMENT_ID, GL_NONE, OGL_POLYID_ATTACHMENT_ID, OGL_FOGATTRIBUTES_ATTACHMENT_ID },
|
||||
{ OGL_COLOROUT_ATTACHMENT_ID, OGL_WORKING_ATTACHMENT_ID, GL_NONE, GL_NONE },
|
||||
{ OGL_COLOROUT_ATTACHMENT_ID, OGL_WORKING_ATTACHMENT_ID, GL_NONE, OGL_FOGATTRIBUTES_ATTACHMENT_ID },
|
||||
{ OGL_COLOROUT_ATTACHMENT_ID, OGL_WORKING_ATTACHMENT_ID, OGL_POLYID_ATTACHMENT_ID, GL_NONE },
|
||||
{ OGL_COLOROUT_ATTACHMENT_ID, OGL_WORKING_ATTACHMENT_ID, OGL_POLYID_ATTACHMENT_ID, OGL_FOGATTRIBUTES_ATTACHMENT_ID }
|
||||
};
|
||||
|
||||
static const GLint GeometryAttachmentWorkingBufferES[8] = { 1,1,1,1,1,1,1,1 };
|
||||
static const GLint GeometryAttachmentPolyIDES[8] = { 2,2,2,2,2,2,2,2 };
|
||||
static const GLint GeometryAttachmentFogAttributesES[8] = { 3,3,3,3,3,3,3,3 };
|
||||
|
||||
// Vertex shader for geometry, GLSL ES 3.00
|
||||
static const char *GeometryVtxShader_ES300 = {"\
|
||||
IN_VTX_POSITION vec4 inPosition;\n\
|
||||
IN_VTX_TEXCOORD0 vec2 inTexCoord0;\n\
|
||||
IN_VTX_COLOR vec3 inColor; \n\
|
||||
\n\
|
||||
#if IS_USING_UBO_POLY_STATES\n\
|
||||
layout (std140) uniform PolyStates\n\
|
||||
{\n\
|
||||
ivec4 value[4096];\n\
|
||||
} polyState;\n\
|
||||
#elif IS_USING_TBO_POLY_STATES\n\
|
||||
uniform highp isamplerBuffer PolyStates;\n\
|
||||
#else\n\
|
||||
uniform highp isampler2D PolyStates;\n\
|
||||
#endif\n\
|
||||
uniform mediump int polyIndex;\n\
|
||||
uniform bool polyDrawShadow;\n\
|
||||
\n\
|
||||
out vec2 vtxTexCoord;\n\
|
||||
out vec4 vtxColor;\n\
|
||||
flat out lowp int polyID;\n\
|
||||
flat out lowp int polyMode;\n\
|
||||
flat out lowp int polyIsWireframe;\n\
|
||||
flat out lowp int polyEnableFog;\n\
|
||||
flat out lowp int polySetNewDepthForTranslucent;\n\
|
||||
flat out lowp int polyEnableTexture;\n\
|
||||
flat out lowp int texSingleBitAlpha;\n\
|
||||
flat out lowp int polyIsBackFacing;\n\
|
||||
flat out lowp int isPolyDrawable;\n\
|
||||
\n\
|
||||
void main()\n\
|
||||
{\n\
|
||||
#if IS_USING_UBO_POLY_STATES\n\
|
||||
ivec4 polyStateVec = polyState.value[polyIndex >> 2];\n\
|
||||
int polyStateBits = polyStateVec[polyIndex & 0x03];\n\
|
||||
#elif IS_USING_TBO_POLY_STATES\n\
|
||||
int polyStateBits = texelFetch(PolyStates, polyIndex).r;\n\
|
||||
#else\n\
|
||||
int polyStateBits = texelFetch(PolyStates, ivec2(polyIndex & 0x00FF, (polyIndex >> 8) & 0x007F), 0).r;\n\
|
||||
#endif\n\
|
||||
int texSizeShiftS = (polyStateBits >> 18) & 0x07;\n\
|
||||
int texSizeShiftT = (polyStateBits >> 21) & 0x07;\n\
|
||||
\n\
|
||||
float polyAlpha = float((polyStateBits >> 8) & 0x1F) / 31.0;\n\
|
||||
vec2 polyTexScale = vec2(1.0 / float(8 << texSizeShiftS), 1.0 / float(8 << texSizeShiftT));\n\
|
||||
\n\
|
||||
polyID = (polyStateBits >> 0) & 0x3F;\n\
|
||||
polyMode = (polyStateBits >> 6) & 0x03;\n\
|
||||
polyIsWireframe = (polyStateBits >> 13) & 0x01;\n\
|
||||
polyEnableFog = (polyStateBits >> 14) & 0x01;\n\
|
||||
polySetNewDepthForTranslucent = (polyStateBits >> 15) & 0x01;\n\
|
||||
polyEnableTexture = (polyStateBits >> 16) & 0x01;\n\
|
||||
texSingleBitAlpha = (polyStateBits >> 17) & 0x01;\n\
|
||||
polyIsBackFacing = (polyStateBits >> 24) & 0x01;\n\
|
||||
\n\
|
||||
isPolyDrawable = int((polyMode != 3) || polyDrawShadow);\n\
|
||||
\n\
|
||||
mat2 texScaleMtx = mat2( vec2(polyTexScale.x, 0.0), \n\
|
||||
vec2( 0.0, polyTexScale.y)); \n\
|
||||
\n\
|
||||
vtxTexCoord = (texScaleMtx * inTexCoord0) / 16.0;\n\
|
||||
vtxColor = vec4(inColor / 63.0, polyAlpha);\n\
|
||||
gl_Position = vec4(inPosition.x, -inPosition.y, inPosition.z, inPosition.w) / 4096.0;\n\
|
||||
}\n\
|
||||
"};
|
||||
|
||||
// Fragment shader for geometry, GLSL ES 3.00
|
||||
static const char *GeometryFragShader_ES300 = {"\
|
||||
in vec2 vtxTexCoord;\n\
|
||||
in vec4 vtxColor;\n\
|
||||
flat in lowp int polyID;\n\
|
||||
flat in lowp int polyMode;\n\
|
||||
flat in lowp int polyIsWireframe;\n\
|
||||
flat in lowp int polyEnableFog;\n\
|
||||
flat in lowp int polySetNewDepthForTranslucent;\n\
|
||||
flat in lowp int polyEnableTexture;\n\
|
||||
flat in lowp int texSingleBitAlpha;\n\
|
||||
flat in lowp int polyIsBackFacing;\n\
|
||||
flat in lowp int isPolyDrawable;\n\
|
||||
\n\
|
||||
layout (std140) uniform RenderStates\n\
|
||||
{\n\
|
||||
bool enableAntialiasing;\n\
|
||||
bool enableFogAlphaOnly;\n\
|
||||
int clearPolyID;\n\
|
||||
float clearDepth;\n\
|
||||
float alphaTestRef;\n\
|
||||
float fogOffset;\n\
|
||||
float fogStep;\n\
|
||||
float pad_0;\n\
|
||||
vec4 fogColor;\n\
|
||||
vec4 edgeColor[8];\n\
|
||||
vec4 toonColor[32];\n\
|
||||
} state;\n\
|
||||
\n\
|
||||
uniform sampler2D texRenderObject;\n\
|
||||
uniform bool texDrawOpaque;\n\
|
||||
uniform bool drawModeDepthEqualsTest;\n\
|
||||
uniform bool polyDrawShadow;\n\
|
||||
uniform float polyDepthOffset;\n\
|
||||
\n\
|
||||
OUT_COLOR vec4 outFragColor;\n\
|
||||
\n\
|
||||
#if DRAW_MODE_OPAQUE\n\
|
||||
OUT_WORKING_BUFFER vec4 outDstBackFacing;\n\
|
||||
#elif USE_DEPTH_LEQUAL_POLYGON_FACING\n\
|
||||
uniform sampler2D inDstBackFacing;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#if ENABLE_EDGE_MARK\n\
|
||||
OUT_POLY_ID vec4 outPolyID;\n\
|
||||
#endif\n\
|
||||
#if ENABLE_FOG\n\
|
||||
OUT_FOG_ATTRIBUTES vec4 outFogAttributes;\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
void main()\n\
|
||||
{\n\
|
||||
#if USE_DEPTH_LEQUAL_POLYGON_FACING && !DRAW_MODE_OPAQUE\n\
|
||||
bool isOpaqueDstBackFacing = bool( texelFetch(inDstBackFacing, ivec2(gl_FragCoord.xy), 0).r );\n\
|
||||
if ( drawModeDepthEqualsTest && (bool(polyIsBackFacing) || !isOpaqueDstBackFacing) )\n\
|
||||
{\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
vec4 mainTexColor = (ENABLE_TEXTURE_SAMPLING && bool(polyEnableTexture)) ? texture(texRenderObject, vtxTexCoord) : vec4(1.0, 1.0, 1.0, 1.0);\n\
|
||||
\n\
|
||||
if (!bool(texSingleBitAlpha))\n\
|
||||
{\n\
|
||||
if (texDrawOpaque)\n\
|
||||
{\n\
|
||||
if ( (polyMode != 1) && (mainTexColor.a <= 0.999) )\n\
|
||||
{\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
else\n\
|
||||
{\n\
|
||||
if ( ((polyMode != 1) && (mainTexColor.a * vtxColor.a > 0.999)) || ((polyMode == 1) && (vtxColor.a > 0.999)) )\n\
|
||||
{\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
}\n\
|
||||
#if USE_TEXTURE_SMOOTHING\n\
|
||||
else\n\
|
||||
{\n\
|
||||
if (mainTexColor.a < 0.500)\n\
|
||||
{\n\
|
||||
mainTexColor.a = 0.0;\n\
|
||||
}\n\
|
||||
else\n\
|
||||
{\n\
|
||||
mainTexColor.rgb = mainTexColor.rgb / mainTexColor.a;\n\
|
||||
mainTexColor.a = 1.0;\n\
|
||||
}\n\
|
||||
}\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
outFragColor = mainTexColor * vtxColor;\n\
|
||||
\n\
|
||||
if (polyMode == 1)\n\
|
||||
{\n\
|
||||
outFragColor.rgb = (ENABLE_TEXTURE_SAMPLING && bool(polyEnableTexture)) ? mix(vtxColor.rgb, mainTexColor.rgb, mainTexColor.a) : vtxColor.rgb;\n\
|
||||
outFragColor.a = vtxColor.a;\n\
|
||||
}\n\
|
||||
else if (polyMode == 2)\n\
|
||||
{\n\
|
||||
vec3 newToonColor = state.toonColor[int((vtxColor.r * 31.0) + 0.5)].rgb;\n\
|
||||
#if TOON_SHADING_MODE\n\
|
||||
outFragColor.rgb = min((mainTexColor.rgb * vtxColor.r) + newToonColor.rgb, 1.0);\n\
|
||||
#else\n\
|
||||
outFragColor.rgb = mainTexColor.rgb * newToonColor.rgb;\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
else if ((polyMode == 3) && polyDrawShadow)\n\
|
||||
{\n\
|
||||
outFragColor = vtxColor;\n\
|
||||
}\n\
|
||||
\n\
|
||||
if ( (isPolyDrawable != 0) && ((outFragColor.a < 0.001) || (ENABLE_ALPHA_TEST && outFragColor.a < state.alphaTestRef)) )\n\
|
||||
{\n\
|
||||
discard;\n\
|
||||
}\n\
|
||||
#if ENABLE_EDGE_MARK\n\
|
||||
outPolyID = (isPolyDrawable != 0) ? vec4( float(polyID)/63.0, float(polyIsWireframe == 1), 0.0, float(outFragColor.a > 0.999) ) : vec4(0.0, 0.0, 0.0, 0.0);\n\
|
||||
#endif\n\
|
||||
#if ENABLE_FOG\n\
|
||||
outFogAttributes = (isPolyDrawable != 0) ? vec4( float(polyEnableFog), 0.0, 0.0, float((outFragColor.a > 0.999) ? 1.0 : 0.5) ) : vec4(0.0, 0.0, 0.0, 0.0);\n\
|
||||
#endif\n\
|
||||
#if DRAW_MODE_OPAQUE\n\
|
||||
outDstBackFacing = vec4(float(polyIsBackFacing), 0.0, 0.0, 1.0);\n\
|
||||
#endif\n\
|
||||
\n\
|
||||
#if USE_NDS_DEPTH_CALCULATION || ENABLE_FOG\n\
|
||||
// It is tempting to perform the NDS depth calculation in the vertex shader rather than in the fragment shader.\n\
|
||||
// Resist this temptation! It is much more reliable to do the depth calculation in the fragment shader due to\n\
|
||||
// subtle interpolation differences between various GPUs and/or drivers. If the depth calculation is not done\n\
|
||||
// here, then it is very possible for the user to experience Z-fighting in certain rendering situations.\n\
|
||||
\n\
|
||||
#if ENABLE_W_DEPTH\n\
|
||||
gl_FragDepth = clamp( ((1.0/gl_FragCoord.w) * (4096.0/16777215.0)) + polyDepthOffset, 0.0, 1.0 );\n\
|
||||
#else\n\
|
||||
// hack: when using z-depth, drop some LSBs so that the overworld map in Dragon Quest IV shows up correctly\n\
|
||||
gl_FragDepth = clamp( (floor(gl_FragCoord.z * 4194303.0) * (4.0/16777215.0)) + polyDepthOffset, 0.0, 1.0 );\n\
|
||||
#endif\n\
|
||||
#endif\n\
|
||||
}\n\
|
||||
"};
|
||||
|
||||
void OGLLoadEntryPoints_ES_3_0()
|
||||
{
|
||||
OGLLoadEntryPoints_3_2();
|
||||
}
|
||||
|
||||
void OGLCreateRenderer_ES_3_0(OpenGLRenderer **rendererPtr)
|
||||
{
|
||||
if (IsOpenGLDriverVersionSupported(3, 0, 0))
|
||||
{
|
||||
*rendererPtr = new OpenGLESRenderer_3_0;
|
||||
(*rendererPtr)->SetVersion(3, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
OpenGLESRenderer_3_0::OpenGLESRenderer_3_0()
|
||||
{
|
||||
_variantID = OpenGLVariantID_ES3_3_0;
|
||||
|
||||
_geometryDrawBuffersEnum = GeometryDrawBuffersEnumES;
|
||||
_geometryAttachmentWorkingBuffer = GeometryAttachmentWorkingBufferES;
|
||||
_geometryAttachmentPolyID = GeometryAttachmentPolyIDES;
|
||||
_geometryAttachmentFogAttributes = GeometryAttachmentFogAttributesES;
|
||||
|
||||
ref->textureSrcTypeCIColor = GL_UNSIGNED_BYTE;
|
||||
ref->textureSrcTypeCIFog = GL_UNSIGNED_BYTE;
|
||||
ref->textureSrcTypeEdgeColor = GL_UNSIGNED_BYTE;
|
||||
ref->textureSrcTypeToonTable = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::InitExtensions()
|
||||
{
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
|
||||
// Get OpenGL extensions
|
||||
std::set<std::string> oglExtensionSet;
|
||||
this->GetExtensionSet(&oglExtensionSet);
|
||||
|
||||
// OpenGL ES 3.0 should fully support FBOs, so we don't need the default framebuffer.
|
||||
// However, OpenGL ES has traditionally required some kind of surface buffer attached
|
||||
// to the context before using it. We don't want it, nor would we ever use it here.
|
||||
// Therefore, check if our context supports being surfaceless before doing anything else,
|
||||
// as this works as a kind of compatibility check.
|
||||
if (!this->IsExtensionPresent(&oglExtensionSet, "GL_OES_surfaceless_context"))
|
||||
{
|
||||
INFO("OpenGL ES: Client contexts are not expected to have any surfaces attached\n");
|
||||
INFO(" to the default framebuffer. The fact that the context does not\n");
|
||||
INFO(" work surfaceless may indicate an error in the context creation,\n");
|
||||
INFO(" or that your platform's context creation is too old.\n");
|
||||
error = OGLERROR_FEATURE_UNSUPPORTED;
|
||||
return error;
|
||||
}
|
||||
|
||||
// Mirrored Repeat Mode Support
|
||||
OGLRef.stateTexMirroredRepeat = GL_MIRRORED_REPEAT;
|
||||
|
||||
// Blending Support
|
||||
this->_isBlendFuncSeparateSupported = true;
|
||||
this->_isBlendEquationSeparateSupported = true;
|
||||
|
||||
// Fixed locations in shaders are supported in ES 3.0 by default.
|
||||
this->_isShaderFixedLocationSupported = true;
|
||||
|
||||
GLfloat maxAnisotropyOGL = 1.0f;
|
||||
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropyOGL);
|
||||
this->_deviceInfo.maxAnisotropy = (float)maxAnisotropyOGL;
|
||||
|
||||
// OpenGL ES 3.0 should be able to handle the GL_RGBA format in glReadPixels without any performance penalty.
|
||||
OGLRef.readPixelsBestFormat = GL_RGBA;
|
||||
OGLRef.readPixelsBestDataType = GL_UNSIGNED_BYTE;
|
||||
|
||||
this->_deviceInfo.isEdgeMarkSupported = true;
|
||||
this->_deviceInfo.isFogSupported = true;
|
||||
|
||||
// Need to generate this texture first because FBO creation needs it.
|
||||
// This texture is only required by shaders, and so if shader creation
|
||||
// fails, then we can immediately delete this texture if an error occurs.
|
||||
glGenTextures(1, &OGLRef.texFinalColorID);
|
||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FinalColor);
|
||||
glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// OpenGL ES 3.0 should have all the necessary features to be able to flip and convert the framebuffer.
|
||||
this->_willConvertFramebufferOnGPU = true;
|
||||
|
||||
this->_enableTextureSmoothing = CommonSettings.GFX3D_Renderer_TextureSmoothing;
|
||||
this->_emulateShadowPolygon = CommonSettings.OpenGL_Emulation_ShadowPolygon;
|
||||
this->_emulateSpecialZeroAlphaBlending = CommonSettings.OpenGL_Emulation_SpecialZeroAlphaBlending;
|
||||
this->_emulateNDSDepthCalculation = CommonSettings.OpenGL_Emulation_NDSDepthCalculation;
|
||||
this->_emulateDepthLEqualPolygonFacing = CommonSettings.OpenGL_Emulation_DepthLEqualPolygonFacing;
|
||||
|
||||
// Load and create shaders. Return on any error, since ES 3.0 makes shaders mandatory.
|
||||
this->isShaderSupported = true;
|
||||
|
||||
this->_rsResource = new OpenGLRenderStatesResource();
|
||||
|
||||
if (IsOpenGLDriverVersionSupported(3, 2, 0))
|
||||
{
|
||||
this->_gResource = new OpenGLGeometryResource(OpenGLVariantID_ES3_3_2);
|
||||
}
|
||||
else if (IsOpenGLDriverVersionSupported(3, 1, 0))
|
||||
{
|
||||
this->_gResource = new OpenGLGeometryResource(OpenGLVariantID_ES3_3_1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->_gResource = new OpenGLGeometryResource(OpenGLVariantID_ES3_3_0);
|
||||
}
|
||||
|
||||
error = this->CreateGeometryPrograms();
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryPrograms();
|
||||
this->isShaderSupported = false;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
error = this->CreateClearImageProgram(ClearImageVtxShader_150, ClearImageFragShader_150);
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryPrograms();
|
||||
this->isShaderSupported = false;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
error = this->CreateGeometryZeroDstAlphaProgram(GeometryZeroDstAlphaPixelMaskVtxShader_150, GeometryZeroDstAlphaPixelMaskFragShader_150);
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryPrograms();
|
||||
this->DestroyClearImageProgram();
|
||||
this->isShaderSupported = false;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
INFO("OpenGL ES: Successfully created geometry shaders.\n");
|
||||
error = this->InitPostprocessingPrograms(EdgeMarkVtxShader_150,
|
||||
EdgeMarkFragShader_150,
|
||||
FramebufferOutputVtxShader_150,
|
||||
FramebufferOutput6665FragShader_150,
|
||||
NULL);
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryPrograms();
|
||||
this->DestroyClearImageProgram();
|
||||
this->DestroyGeometryZeroDstAlphaProgram();
|
||||
this->isShaderSupported = false;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
this->isVBOSupported = true;
|
||||
this->CreateVBOs();
|
||||
|
||||
// PBOs are only used when reading back the rendered framebuffer for the emulated
|
||||
// BG0 layer. For desktop-class GPUs, doing an asynchronous glReadPixels() call
|
||||
// is always advantageous since such devices are expected to have their GPUs
|
||||
// connected to a data bus.
|
||||
//
|
||||
// However, many ARM-based mobile devices use integrated GPUs of varying degrees
|
||||
// of memory latency and implementation quality. This means that the performance
|
||||
// of an asynchronous glReadPixels() call is NOT guaranteed on such devices.
|
||||
//
|
||||
// In fact, many ARM-based devices suffer devastating performance drops when trying
|
||||
// to do asynchronous framebuffer reads. Therefore, since most OpenGL ES users will
|
||||
// be running an ARM-based iGPU, we will disable PBOs for OpenGL ES and stick with
|
||||
// a traditional synchronous glReadPixels() call instead.
|
||||
this->isPBOSupported = false;
|
||||
|
||||
this->isVAOSupported = true;
|
||||
this->CreateVAOs();
|
||||
|
||||
// Load and create FBOs. Return on any error, since OpenGL ES 3.0 includes FBOs as core functionality.
|
||||
this->isFBOSupported = true;
|
||||
error = this->CreateFBOs();
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
this->isFBOSupported = false;
|
||||
return error;
|
||||
}
|
||||
|
||||
this->_isFBOBlitSupported = true;
|
||||
this->isMultisampledFBOSupported = true;
|
||||
this->_selectedMultisampleSize = CommonSettings.GFX3D_Renderer_MultisampleSize;
|
||||
|
||||
GLint maxSamplesOGL = 0;
|
||||
glGetIntegerv(GL_MAX_SAMPLES, &maxSamplesOGL);
|
||||
this->_deviceInfo.maxSamples = (u8)maxSamplesOGL;
|
||||
|
||||
if (this->_deviceInfo.maxSamples >= 2)
|
||||
{
|
||||
// Try and initialize the multisampled FBOs with the GFX3D_Renderer_MultisampleSize.
|
||||
// However, if the client has this set to 0, then set sampleSize to 2 in order to
|
||||
// force the generation and the attachments of the buffers at a meaningful sample
|
||||
// size. If GFX3D_Renderer_MultisampleSize is 0, then we can deallocate the buffer
|
||||
// memory afterwards.
|
||||
GLsizei sampleSize = this->GetLimitedMultisampleSize();
|
||||
if (sampleSize == 0)
|
||||
{
|
||||
sampleSize = 2;
|
||||
}
|
||||
|
||||
error = this->CreateMultisampledFBO(sampleSize);
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
this->isMultisampledFBOSupported = false;
|
||||
}
|
||||
|
||||
// If GFX3D_Renderer_MultisampleSize is 0, then we can deallocate the buffers now
|
||||
// in order to save some memory.
|
||||
if (this->_selectedMultisampleSize == 0)
|
||||
{
|
||||
this->ResizeMultisampledFBOs(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->isMultisampledFBOSupported = false;
|
||||
INFO("OpenGL ES: Driver does not support at least 2x multisampled FBOs.\n");
|
||||
}
|
||||
|
||||
this->_isDepthLEqualPolygonFacingSupported = true;
|
||||
this->_enableMultisampledRendering = ((this->_selectedMultisampleSize >= 2) && this->isMultisampledFBOSupported);
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::CreateGeometryPrograms()
|
||||
{
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
// Create shader resources.
|
||||
glGenTextures(1, &OGLRef.texFogDensityTableID);
|
||||
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_LookupTable);
|
||||
glBindTexture(GL_TEXTURE_2D, OGLRef.texFogDensityTableID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 32, 1, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
OGLGeometryFlags programFlags;
|
||||
programFlags.value = 0;
|
||||
|
||||
std::stringstream shaderHeader;
|
||||
shaderHeader << "#version 300 es\n";
|
||||
shaderHeader << "precision highp float;\n";
|
||||
shaderHeader << "precision highp int;\n";
|
||||
shaderHeader << "\n";
|
||||
|
||||
std::stringstream vsHeader;
|
||||
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
|
||||
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
|
||||
vsHeader << "\n";
|
||||
vsHeader << "#define IS_USING_UBO_POLY_STATES " << ((this->_gResource->IsPolyStatesBufferUBO()) ? 1 : 0) << "\n";
|
||||
vsHeader << "#define IS_USING_TBO_POLY_STATES " << ((this->_gResource->IsPolyStatesBufferTBO()) ? 1 : 0) << "\n";
|
||||
vsHeader << "#define DEPTH_EQUALS_TEST_TOLERANCE " << DEPTH_EQUALS_TEST_TOLERANCE << ".0\n";
|
||||
vsHeader << "\n";
|
||||
|
||||
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(GeometryVtxShader_ES300);
|
||||
|
||||
for (size_t flagsValue = 0; flagsValue < 128; flagsValue++, programFlags.value++)
|
||||
{
|
||||
std::stringstream shaderFlags;
|
||||
shaderFlags << "#define OUT_COLOR layout (location = 0) out\n";
|
||||
shaderFlags << "#define OUT_WORKING_BUFFER layout (location = " << (OGL_WORKING_ATTACHMENT_ID - GL_COLOR_ATTACHMENT0) << ") out\n";
|
||||
shaderFlags << "#define OUT_POLY_ID layout (location = " << (OGL_POLYID_ATTACHMENT_ID - GL_COLOR_ATTACHMENT0) << ") out\n";
|
||||
shaderFlags << "#define OUT_FOG_ATTRIBUTES layout (location = " << (OGL_FOGATTRIBUTES_ATTACHMENT_ID - GL_COLOR_ATTACHMENT0) << ") out\n";
|
||||
shaderFlags << "\n";
|
||||
shaderFlags << "#define USE_TEXTURE_SMOOTHING " << ((this->_enableTextureSmoothing) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define USE_NDS_DEPTH_CALCULATION " << ((this->_emulateNDSDepthCalculation) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define USE_DEPTH_LEQUAL_POLYGON_FACING " << ((this->_emulateDepthLEqualPolygonFacing) ? 1 : 0) << "\n";
|
||||
shaderFlags << "\n";
|
||||
shaderFlags << "#define ENABLE_W_DEPTH " << ((programFlags.EnableWDepth) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define ENABLE_ALPHA_TEST " << ((programFlags.EnableAlphaTest) ? "true\n" : "false\n");
|
||||
shaderFlags << "#define ENABLE_TEXTURE_SAMPLING " << ((programFlags.EnableTextureSampling) ? "true\n" : "false\n");
|
||||
shaderFlags << "#define TOON_SHADING_MODE " << ((programFlags.ToonShadingMode) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define ENABLE_FOG " << ((programFlags.EnableFog) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define ENABLE_EDGE_MARK " << ((programFlags.EnableEdgeMark) ? 1 : 0) << "\n";
|
||||
shaderFlags << "#define DRAW_MODE_OPAQUE " << ((programFlags.OpaqueDrawMode) ? 1 : 0) << "\n";
|
||||
shaderFlags << "\n";
|
||||
|
||||
std::string fragShaderCode = shaderHeader.str() + shaderFlags.str() + std::string(GeometryFragShader_ES300);
|
||||
|
||||
error = this->ShaderProgramCreate(OGLRef.vertexGeometryShaderID,
|
||||
OGLRef.fragmentGeometryShaderID[flagsValue],
|
||||
OGLRef.programGeometryID[flagsValue],
|
||||
vtxShaderCode.c_str(),
|
||||
fragShaderCode.c_str());
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
INFO("OpenGL ES: Failed to create the GEOMETRY shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryPrograms();
|
||||
return error;
|
||||
}
|
||||
|
||||
glLinkProgram(OGLRef.programGeometryID[flagsValue]);
|
||||
if (!this->ValidateShaderProgramLink(OGLRef.programGeometryID[flagsValue]))
|
||||
{
|
||||
INFO("OpenGL ES: Failed to link the GEOMETRY shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryPrograms();
|
||||
return OGLERROR_SHADER_CREATE_ERROR;
|
||||
}
|
||||
|
||||
glValidateProgram(OGLRef.programGeometryID[flagsValue]);
|
||||
glUseProgram(OGLRef.programGeometryID[flagsValue]);
|
||||
|
||||
// Set up render states UBO
|
||||
const GLuint uniformBlockRenderStates = glGetUniformBlockIndex(OGLRef.programGeometryID[flagsValue], "RenderStates");
|
||||
glUniformBlockBinding(OGLRef.programGeometryID[flagsValue], uniformBlockRenderStates, OGLBindingPointID_RenderStates);
|
||||
|
||||
GLint uboSize = 0;
|
||||
glGetActiveUniformBlockiv(OGLRef.programGeometryID[flagsValue], uniformBlockRenderStates, GL_UNIFORM_BLOCK_DATA_SIZE, &uboSize);
|
||||
assert(uboSize == sizeof(OGLRenderStates));
|
||||
|
||||
const GLint uniformTexRenderObject = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "texRenderObject");
|
||||
glUniform1i(uniformTexRenderObject, 0);
|
||||
|
||||
if (this->_gResource->IsPolyStatesBufferUBO())
|
||||
{
|
||||
const GLuint uniformBlockPolyStates = glGetUniformBlockIndex(OGLRef.programGeometryID[flagsValue], "PolyStates");
|
||||
glUniformBlockBinding(OGLRef.programGeometryID[flagsValue], uniformBlockPolyStates, OGLBindingPointID_PolyStates);
|
||||
}
|
||||
else
|
||||
{
|
||||
const GLint uniformTexBufferPolyStates = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "PolyStates");
|
||||
glUniform1i(uniformTexBufferPolyStates, OGLTextureUnitID_PolyStates);
|
||||
}
|
||||
|
||||
if (this->_emulateDepthLEqualPolygonFacing && !programFlags.OpaqueDrawMode)
|
||||
{
|
||||
const GLint uniformTexBackfacing = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "inDstBackFacing");
|
||||
glUniform1i(uniformTexBackfacing, OGLTextureUnitID_FinalColor);
|
||||
}
|
||||
|
||||
OGLRef.uniformTexDrawOpaque[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "texDrawOpaque");
|
||||
OGLRef.uniformDrawModeDepthEqualsTest[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "drawModeDepthEqualsTest");
|
||||
OGLRef.uniformPolyDrawShadow[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDrawShadow");
|
||||
OGLRef.uniformPolyStateIndex[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyIndex");
|
||||
OGLRef.uniformPolyDepthOffset[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDepthOffset");
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::CreateClearImageProgram(const char *vsCString, const char *fsCString)
|
||||
{
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
std::stringstream shaderHeader;
|
||||
shaderHeader << "#version 300 es\n";
|
||||
shaderHeader << "precision highp float;\n";
|
||||
shaderHeader << "precision highp int;\n";
|
||||
shaderHeader << "\n";
|
||||
|
||||
std::stringstream vsHeader;
|
||||
if (this->_isShaderFixedLocationSupported)
|
||||
{
|
||||
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
vsHeader << "#define IN_VTX_POSITION in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 in\n";
|
||||
}
|
||||
vsHeader << "\n";
|
||||
|
||||
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vsCString);
|
||||
std::stringstream fsHeader;
|
||||
if (this->_isShaderFixedLocationSupported)
|
||||
{
|
||||
fsHeader << "#define OUT_COLOR layout (location = 0) out\n";
|
||||
fsHeader << "#define OUT_FOGATTR layout (location = 1) out\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
fsHeader << "#define OUT_COLOR out\n";
|
||||
fsHeader << "#define OUT_FOGATTR out\n";
|
||||
}
|
||||
fsHeader << "\n";
|
||||
|
||||
std::string fragShaderCodeFogColor = shaderHeader.str() + fsHeader.str() + std::string(fsCString);
|
||||
error = this->ShaderProgramCreate(OGLRef.vsClearImageID,
|
||||
OGLRef.fsClearImageID,
|
||||
OGLRef.pgClearImageID,
|
||||
vtxShaderCode.c_str(),
|
||||
fragShaderCodeFogColor.c_str());
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
INFO("OpenGL ES: Failed to create the CLEAR_IMAGE shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyClearImageProgram();
|
||||
return error;
|
||||
}
|
||||
|
||||
glLinkProgram(OGLRef.pgClearImageID);
|
||||
if (!this->ValidateShaderProgramLink(OGLRef.pgClearImageID))
|
||||
{
|
||||
INFO("OpenGL ES: Failed to link the CLEAR_IMAGE shader color/fog program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyClearImageProgram();
|
||||
return OGLERROR_SHADER_CREATE_ERROR;
|
||||
}
|
||||
|
||||
glValidateProgram(OGLRef.pgClearImageID);
|
||||
glUseProgram(OGLRef.pgClearImageID);
|
||||
|
||||
const GLint uniformTexCIColor = glGetUniformLocation(OGLRef.pgClearImageID, "texCIColor");
|
||||
const GLint uniformTexCIFogAttr = glGetUniformLocation(OGLRef.pgClearImageID, "texCIFogAttr");
|
||||
const GLint uniformTexCIDepthCF = glGetUniformLocation(OGLRef.pgClearImageID, "texCIDepth");
|
||||
glUniform1i(uniformTexCIColor, OGLTextureUnitID_CIColor);
|
||||
glUniform1i(uniformTexCIFogAttr, OGLTextureUnitID_CIFogAttr);
|
||||
glUniform1i(uniformTexCIDepthCF, OGLTextureUnitID_CIDepth);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString)
|
||||
{
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
if ( (vtxShaderCString == NULL) || (fragShaderCString == NULL) )
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
std::stringstream shaderHeader;
|
||||
shaderHeader << "#version 300 es\n";
|
||||
shaderHeader << "precision highp float;\n";
|
||||
shaderHeader << "precision highp int;\n";
|
||||
shaderHeader << "\n";
|
||||
|
||||
std::stringstream vsHeader;
|
||||
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
|
||||
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
|
||||
|
||||
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vtxShaderCString);
|
||||
std::string fragShaderCode = shaderHeader.str() + std::string(fragShaderCString);
|
||||
|
||||
error = this->ShaderProgramCreate(OGLRef.vtxShaderGeometryZeroDstAlphaID,
|
||||
OGLRef.fragShaderGeometryZeroDstAlphaID,
|
||||
OGLRef.programGeometryZeroDstAlphaID,
|
||||
vtxShaderCode.c_str(),
|
||||
fragShaderCode.c_str());
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
INFO("OpenGL ES: Failed to create the GEOMETRY ZERO DST ALPHA shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryZeroDstAlphaProgram();
|
||||
return error;
|
||||
}
|
||||
|
||||
glLinkProgram(OGLRef.programGeometryZeroDstAlphaID);
|
||||
if (!this->ValidateShaderProgramLink(OGLRef.programGeometryZeroDstAlphaID))
|
||||
{
|
||||
INFO("OpenGL ES: Failed to link the GEOMETRY ZERO DST ALPHA shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyGeometryZeroDstAlphaProgram();
|
||||
return OGLERROR_SHADER_CREATE_ERROR;
|
||||
}
|
||||
|
||||
glValidateProgram(OGLRef.programGeometryZeroDstAlphaID);
|
||||
glUseProgram(OGLRef.programGeometryZeroDstAlphaID);
|
||||
|
||||
const GLint uniformTexGColor = glGetUniformLocation(OGLRef.programGeometryZeroDstAlphaID, "texInFragColor");
|
||||
glUniform1i(uniformTexGColor, OGLTextureUnitID_GColor);
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::CreateEdgeMarkProgram(const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString)
|
||||
{
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
if ( (vtxShaderCString == NULL) || (fragShaderCString == NULL) )
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
std::stringstream shaderHeader;
|
||||
shaderHeader << "#version 300 es\n";
|
||||
shaderHeader << "precision highp float;\n";
|
||||
shaderHeader << "precision highp int;\n";
|
||||
shaderHeader << "\n";
|
||||
shaderHeader << "#define FRAMEBUFFER_SIZE_X " << this->_framebufferWidth << ".0 \n";
|
||||
shaderHeader << "#define FRAMEBUFFER_SIZE_Y " << this->_framebufferHeight << ".0 \n";
|
||||
shaderHeader << "\n";
|
||||
|
||||
std::stringstream vsHeader;
|
||||
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
|
||||
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
|
||||
|
||||
std::stringstream fsHeader;
|
||||
fsHeader << "#define OUT_COLOR layout (location = 0) out\n";
|
||||
|
||||
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vtxShaderCString);
|
||||
std::string fragShaderCode = shaderHeader.str() + fsHeader.str() + std::string(fragShaderCString);
|
||||
|
||||
error = this->ShaderProgramCreate(OGLRef.vertexEdgeMarkShaderID,
|
||||
OGLRef.fragmentEdgeMarkShaderID,
|
||||
OGLRef.programEdgeMarkID,
|
||||
vtxShaderCode.c_str(),
|
||||
fragShaderCode.c_str());
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
INFO("OpenGL ES: Failed to create the EDGE MARK shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyEdgeMarkProgram();
|
||||
return error;
|
||||
}
|
||||
|
||||
glLinkProgram(OGLRef.programEdgeMarkID);
|
||||
if (!this->ValidateShaderProgramLink(OGLRef.programEdgeMarkID))
|
||||
{
|
||||
INFO("OpenGL ES: Failed to link the EDGE MARK shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyEdgeMarkProgram();
|
||||
return OGLERROR_SHADER_CREATE_ERROR;
|
||||
}
|
||||
|
||||
glValidateProgram(OGLRef.programEdgeMarkID);
|
||||
glUseProgram(OGLRef.programEdgeMarkID);
|
||||
|
||||
const GLuint uniformBlockRenderStates = glGetUniformBlockIndex(OGLRef.programEdgeMarkID, "RenderStates");
|
||||
glUniformBlockBinding(OGLRef.programEdgeMarkID, uniformBlockRenderStates, OGLBindingPointID_RenderStates);
|
||||
|
||||
const GLint uniformTexGDepth = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInFragDepth");
|
||||
const GLint uniformTexGPolyID = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInPolyID");
|
||||
glUniform1i(uniformTexGDepth, OGLTextureUnitID_DepthStencil);
|
||||
glUniform1i(uniformTexGPolyID, OGLTextureUnitID_GPolyID);
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::CreateFogProgram(const OGLFogProgramKey fogProgramKey, const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString)
|
||||
{
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
if (vtxShaderCString == NULL)
|
||||
{
|
||||
INFO("OpenGL ES: The FOG vertex shader is unavailable.\n");
|
||||
error = OGLERROR_VERTEX_SHADER_PROGRAM_LOAD_ERROR;
|
||||
return error;
|
||||
}
|
||||
else if (fragShaderCString == NULL)
|
||||
{
|
||||
INFO("OpenGL ES: The FOG fragment shader is unavailable.\n");
|
||||
error = OGLERROR_FRAGMENT_SHADER_PROGRAM_LOAD_ERROR;
|
||||
return error;
|
||||
}
|
||||
|
||||
const s32 fogOffset = fogProgramKey.offset;
|
||||
const GLfloat fogOffsetf = (GLfloat)fogOffset / 32767.0f;
|
||||
const s32 fogStep = 0x0400 >> fogProgramKey.shift;
|
||||
|
||||
std::stringstream shaderHeader;
|
||||
shaderHeader << "#version 300 es\n";
|
||||
shaderHeader << "precision highp float;\n";
|
||||
shaderHeader << "precision highp int;\n";
|
||||
shaderHeader << "\n";
|
||||
|
||||
std::stringstream vsHeader;
|
||||
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
|
||||
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
|
||||
|
||||
std::stringstream fsHeader;
|
||||
fsHeader << "#define FOG_OFFSET " << fogOffset << "\n";
|
||||
fsHeader << "#define FOG_OFFSETF " << fogOffsetf << (((fogOffsetf == 0.0f) || (fogOffsetf == 1.0f)) ? ".0" : "") << "\n";
|
||||
fsHeader << "#define FOG_STEP " << fogStep << "\n";
|
||||
fsHeader << "\n";
|
||||
fsHeader << "#define OUT_COLOR layout (location = 0) out\n";
|
||||
|
||||
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vtxShaderCString);
|
||||
std::string fragShaderCode = shaderHeader.str() + fsHeader.str() + std::string(fragShaderCString);
|
||||
|
||||
OGLFogShaderID shaderID;
|
||||
shaderID.program = 0;
|
||||
shaderID.fragShader = 0;
|
||||
|
||||
error = this->ShaderProgramCreate(OGLRef.vertexFogShaderID,
|
||||
shaderID.fragShader,
|
||||
shaderID.program,
|
||||
vtxShaderCode.c_str(),
|
||||
fragShaderCode.c_str());
|
||||
|
||||
this->_fogProgramMap[fogProgramKey.key] = shaderID;
|
||||
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
INFO("OpenGL ES: Failed to create the FOG shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyFogProgram(fogProgramKey);
|
||||
return error;
|
||||
}
|
||||
|
||||
glLinkProgram(shaderID.program);
|
||||
if (!this->ValidateShaderProgramLink(shaderID.program))
|
||||
{
|
||||
INFO("OpenGL ES: Failed to link the FOG shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyFogProgram(fogProgramKey);
|
||||
return OGLERROR_SHADER_CREATE_ERROR;
|
||||
}
|
||||
|
||||
glValidateProgram(shaderID.program);
|
||||
glUseProgram(shaderID.program);
|
||||
|
||||
const GLuint uniformBlockRenderStates = glGetUniformBlockIndex(shaderID.program, "RenderStates");
|
||||
glUniformBlockBinding(shaderID.program, uniformBlockRenderStates, OGLBindingPointID_RenderStates);
|
||||
|
||||
const GLint uniformTexGDepth = glGetUniformLocation(shaderID.program, "texInFragDepth");
|
||||
const GLint uniformTexGFog = glGetUniformLocation(shaderID.program, "texInFogAttributes");
|
||||
const GLint uniformTexFogDensityTable = glGetUniformLocation(shaderID.program, "texFogDensityTable");
|
||||
glUniform1i(uniformTexGDepth, OGLTextureUnitID_DepthStencil);
|
||||
glUniform1i(uniformTexGFog, OGLTextureUnitID_FogAttr);
|
||||
glUniform1i(uniformTexFogDensityTable, OGLTextureUnitID_LookupTable);
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
||||
|
||||
Render3DError OpenGLESRenderer_3_0::CreateFramebufferOutput6665Program(const char *vtxShaderCString, const char *fragShaderCString)
|
||||
{
|
||||
Render3DError error = OGLERROR_NOERR;
|
||||
OGLRenderRef &OGLRef = *this->ref;
|
||||
|
||||
if ( (vtxShaderCString == NULL) || (fragShaderCString == NULL) )
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
std::stringstream shaderHeader;
|
||||
shaderHeader << "#version 300 es\n";
|
||||
shaderHeader << "precision highp float;\n";
|
||||
shaderHeader << "precision highp int;\n";
|
||||
shaderHeader << "\n";
|
||||
shaderHeader << "#define FRAMEBUFFER_SIZE_X " << this->_framebufferWidth << ".0 \n";
|
||||
shaderHeader << "#define FRAMEBUFFER_SIZE_Y " << this->_framebufferHeight << ".0 \n";
|
||||
shaderHeader << "\n";
|
||||
|
||||
std::stringstream vsHeader;
|
||||
vsHeader << "#define IN_VTX_POSITION layout (location = " << OGLVertexAttributeID_Position << ") in\n";
|
||||
vsHeader << "#define IN_VTX_TEXCOORD0 layout (location = " << OGLVertexAttributeID_TexCoord0 << ") in\n";
|
||||
vsHeader << "#define IN_VTX_COLOR layout (location = " << OGLVertexAttributeID_Color << ") in\n";
|
||||
|
||||
std::stringstream fsHeader;
|
||||
fsHeader << "#define OUT_COLOR layout (location = " << (OGL_WORKING_ATTACHMENT_ID - GL_COLOR_ATTACHMENT0) << ") out\n";
|
||||
|
||||
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vtxShaderCString);
|
||||
std::string fragShaderCode = shaderHeader.str() + fsHeader.str() + std::string(fragShaderCString);
|
||||
|
||||
error = this->ShaderProgramCreate(OGLRef.vertexFramebufferOutput6665ShaderID,
|
||||
OGLRef.fragmentFramebufferRGBA6665OutputShaderID,
|
||||
OGLRef.programFramebufferRGBA6665OutputID,
|
||||
vtxShaderCode.c_str(),
|
||||
fragShaderCode.c_str());
|
||||
if (error != OGLERROR_NOERR)
|
||||
{
|
||||
INFO("OpenGL ES: Failed to create the FRAMEBUFFER OUTPUT RGBA6665 shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyFramebufferOutput6665Programs();
|
||||
return error;
|
||||
}
|
||||
|
||||
glLinkProgram(OGLRef.programFramebufferRGBA6665OutputID);
|
||||
if (!this->ValidateShaderProgramLink(OGLRef.programFramebufferRGBA6665OutputID))
|
||||
{
|
||||
INFO("OpenGL ES: Failed to link the FRAMEBUFFER OUTPUT RGBA6665 shader program.\n");
|
||||
glUseProgram(0);
|
||||
this->DestroyFramebufferOutput6665Programs();
|
||||
return OGLERROR_SHADER_CREATE_ERROR;
|
||||
}
|
||||
|
||||
glValidateProgram(OGLRef.programFramebufferRGBA6665OutputID);
|
||||
glUseProgram(OGLRef.programFramebufferRGBA6665OutputID);
|
||||
|
||||
const GLint uniformTexGColor = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID, "texInFragColor");
|
||||
glUniform1i(uniformTexGColor, OGLTextureUnitID_GColor);
|
||||
|
||||
return OGLERROR_NOERR;
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2024 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OGLRENDER_ES3_H
|
||||
#define OGLRENDER_ES3_H
|
||||
|
||||
#include "OGLRender_3_2.h"
|
||||
|
||||
// A port that wants to use the OpenGL ES renderer must assign the two following functions
|
||||
// to OGLLoadEntryPoints_ES_3_0_Func and OGLCreateRenderer_ES_3_0_Func, respectively.
|
||||
//
|
||||
// In addition, the port must add the following GPU3DInterface objects to core3DList:
|
||||
// - gpu3Dgl_ES_3_0: Selects the OpenGL ES 3.0 renderer, and returns an error if it is
|
||||
// not available on the host system.
|
||||
//
|
||||
// Finally, the port must call GPU->Set3DRendererByID() and pass in the index where
|
||||
// gpu3Dgl_ES_3_0 exists in core3DList so that the emulator can create the appropriate
|
||||
// OpenGLRenderer object.
|
||||
//
|
||||
// Example code:
|
||||
// OGLLoadEntryPoints_ES_3_0_Func = &OGLLoadEntryPoints_ES_3_0;
|
||||
// OGLCreateRenderer_ES_3_0_Func = &OGLCreateRenderer_ES_3_0;
|
||||
// GPU3DInterface *core3DList[] = { &gpu3DNull, &gpu3DRasterize, &gpu3Dgl_ES_3_0, NULL };
|
||||
// GPU->Set3DRendererByID(2);
|
||||
|
||||
void OGLLoadEntryPoints_ES_3_0();
|
||||
void OGLCreateRenderer_ES_3_0(OpenGLRenderer **rendererPtr);
|
||||
|
||||
class OpenGLESRenderer_3_0 : public OpenGLRenderer_3_2
|
||||
{
|
||||
protected:
|
||||
virtual Render3DError CreateGeometryPrograms();
|
||||
virtual Render3DError CreateClearImageProgram(const char *vsCString, const char *fsCString);
|
||||
virtual Render3DError CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual Render3DError CreateEdgeMarkProgram(const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString);
|
||||
virtual Render3DError CreateFramebufferOutput6665Program(const char *vtxShaderCString, const char *fragShaderCString);
|
||||
|
||||
public:
|
||||
OpenGLESRenderer_3_0();
|
||||
|
||||
virtual Render3DError InitExtensions();
|
||||
};
|
||||
|
||||
#endif // OGLRENDER_ES3_H
|
|
@ -1,3 +0,0 @@
|
|||
#ifndef __GNUC__
|
||||
#pragma pack(pop)
|
||||
#endif
|
|
@ -1,375 +0,0 @@
|
|||
/*
|
||||
Copyright 2007 Guillaume Duhamel
|
||||
Copyright 2007-2017 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ROMReader.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_LIBZZIP
|
||||
#include <zzip/zzip.h>
|
||||
#endif
|
||||
|
||||
#include "utils/xstring.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define stat(...) _stat(__VA_ARGS__)
|
||||
#define S_IFMT _S_IFMT
|
||||
#define S_IFREG _S_IFREG
|
||||
#endif
|
||||
|
||||
ROMReader_struct * ROMReaderInit(char ** filename)
|
||||
{
|
||||
#ifdef HAVE_LIBZ
|
||||
if(!strcasecmp(".gz", *filename + (strlen(*filename) - 3)))
|
||||
{
|
||||
(*filename)[strlen(*filename) - 3] = '\0';
|
||||
return &GZIPROMReader;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_LIBZZIP
|
||||
if (!strcasecmp(".zip", *filename + (strlen(*filename) - 4)))
|
||||
{
|
||||
(*filename)[strlen(*filename) - 4] = '\0';
|
||||
return &ZIPROMReader;
|
||||
}
|
||||
#endif
|
||||
return &STDROMReader;
|
||||
}
|
||||
|
||||
void * STDROMReaderInit(const char * filename);
|
||||
void STDROMReaderDeInit(void *);
|
||||
u32 STDROMReaderSize(void *);
|
||||
int STDROMReaderSeek(void *, int, int);
|
||||
int STDROMReaderRead(void *, void *, u32);
|
||||
int STDROMReaderWrite(void *, void *, u32);
|
||||
|
||||
ROMReader_struct STDROMReader =
|
||||
{
|
||||
ROMREADER_STD,
|
||||
"Standard ROM Reader",
|
||||
STDROMReaderInit,
|
||||
STDROMReaderDeInit,
|
||||
STDROMReaderSize,
|
||||
STDROMReaderSeek,
|
||||
STDROMReaderRead,
|
||||
STDROMReaderWrite
|
||||
};
|
||||
|
||||
struct STDROMReaderData
|
||||
{
|
||||
FILE* file;
|
||||
long pos;
|
||||
};
|
||||
|
||||
void* STDROMReaderInit(const char* filename)
|
||||
{
|
||||
#ifndef _MSC_VER
|
||||
struct stat sb;
|
||||
if (stat(filename, &sb) == -1)
|
||||
return 0;
|
||||
|
||||
if ((sb.st_mode & S_IFMT) != S_IFREG)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
FILE* inf = _wfopen(mbstowcs((std::string)filename).c_str(),L"rb");
|
||||
#else
|
||||
FILE* inf = fopen(filename, "rb");
|
||||
#endif
|
||||
|
||||
if(!inf) return NULL;
|
||||
|
||||
STDROMReaderData* ret = new STDROMReaderData();
|
||||
ret->file = inf;
|
||||
ret->pos = 0;
|
||||
return (void*)ret;
|
||||
}
|
||||
|
||||
|
||||
void STDROMReaderDeInit(void * file)
|
||||
{
|
||||
if (!file) return ;
|
||||
fclose(((STDROMReaderData*)file)->file);
|
||||
delete ((STDROMReaderData*)file);
|
||||
}
|
||||
|
||||
u32 STDROMReaderSize(void * file)
|
||||
{
|
||||
u32 size;
|
||||
|
||||
if (!file) return 0;
|
||||
|
||||
FILE* inf = ((STDROMReaderData*)file)->file;
|
||||
|
||||
fseek(inf, 0, SEEK_END);
|
||||
size = ftell(inf);
|
||||
fseek(inf, ((STDROMReaderData*)file)->pos, SEEK_SET);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int STDROMReaderSeek(void * file, int offset, int whence)
|
||||
{
|
||||
//not normal fseek return value meanings. awesome.
|
||||
if (!file) return 0;
|
||||
if(whence == SEEK_SET && offset == ((STDROMReaderData*)file)->pos)
|
||||
return 1;
|
||||
fseek(((STDROMReaderData*)file)->file, offset, whence);
|
||||
((STDROMReaderData*)file)->pos = ftell(((STDROMReaderData*)file)->file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int STDROMReaderRead(void * file, void * buffer, u32 size)
|
||||
{
|
||||
if (!file) return 0;
|
||||
int read = fread(buffer, 1, size, ((STDROMReaderData*)file)->file);
|
||||
((STDROMReaderData*)file)->pos += read;
|
||||
return read;
|
||||
}
|
||||
|
||||
int STDROMReaderWrite(void *, void *, u32)
|
||||
{
|
||||
//not supported, for now
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
void * GZIPROMReaderInit(const char * filename);
|
||||
void GZIPROMReaderDeInit(void *);
|
||||
u32 GZIPROMReaderSize(void *);
|
||||
int GZIPROMReaderSeek(void *, int, int);
|
||||
int GZIPROMReaderRead(void *, void *, u32);
|
||||
int GZIPROMReaderWrite(void *, void *, u32);
|
||||
|
||||
ROMReader_struct GZIPROMReader =
|
||||
{
|
||||
ROMREADER_GZIP,
|
||||
"Gzip ROM Reader",
|
||||
GZIPROMReaderInit,
|
||||
GZIPROMReaderDeInit,
|
||||
GZIPROMReaderSize,
|
||||
GZIPROMReaderSeek,
|
||||
GZIPROMReaderRead,
|
||||
GZIPROMReaderWrite
|
||||
};
|
||||
|
||||
void * GZIPROMReaderInit(const char * filename)
|
||||
{
|
||||
return (void*)gzopen(filename, "rb");
|
||||
}
|
||||
|
||||
void GZIPROMReaderDeInit(void * file)
|
||||
{
|
||||
gzclose((gzFile)file);
|
||||
}
|
||||
|
||||
u32 GZIPROMReaderSize(void * file)
|
||||
{
|
||||
char useless[1024];
|
||||
u32 size = 0;
|
||||
|
||||
/* FIXME this function should first save the current
|
||||
* position and restore it after size calculation */
|
||||
gzrewind((gzFile)file);
|
||||
while (gzeof ((gzFile)file) == 0)
|
||||
size += gzread((gzFile)file, useless, 1024);
|
||||
gzrewind((gzFile)file);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int GZIPROMReaderSeek(void * file, int offset, int whence)
|
||||
{
|
||||
return gzseek((gzFile)file, offset, whence);
|
||||
}
|
||||
|
||||
int GZIPROMReaderRead(void * file, void * buffer, u32 size)
|
||||
{
|
||||
return gzread((gzFile)file, buffer, size);
|
||||
}
|
||||
|
||||
int GZIPROMReaderWrite(void *, void *, u32)
|
||||
{
|
||||
//not supported, ever
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBZZIP
|
||||
void * ZIPROMReaderInit(const char * filename);
|
||||
void ZIPROMReaderDeInit(void *);
|
||||
u32 ZIPROMReaderSize(void *);
|
||||
int ZIPROMReaderSeek(void *, int, int);
|
||||
int ZIPROMReaderRead(void *, void *, u32);
|
||||
int ZIPROMReaderWrite(void *, void *, u32);
|
||||
|
||||
ROMReader_struct ZIPROMReader =
|
||||
{
|
||||
ROMREADER_ZIP,
|
||||
"Zip ROM Reader",
|
||||
ZIPROMReaderInit,
|
||||
ZIPROMReaderDeInit,
|
||||
ZIPROMReaderSize,
|
||||
ZIPROMReaderSeek,
|
||||
ZIPROMReaderRead,
|
||||
ZIPROMReaderWrite
|
||||
};
|
||||
|
||||
void * ZIPROMReaderInit(const char * filename)
|
||||
{
|
||||
ZZIP_DIR * dir = zzip_opendir(filename);
|
||||
ZZIP_DIRENT * dirent = zzip_readdir(dir);
|
||||
if (dir != NULL)
|
||||
{
|
||||
char *tmp1;
|
||||
char tmp2[1024];
|
||||
|
||||
memset(tmp2,0,sizeof(tmp2));
|
||||
tmp1 = strndup(filename, strlen(filename) - 4);
|
||||
sprintf(tmp2, "%s/%s", tmp1, dirent->d_name);
|
||||
free(tmp1);
|
||||
return zzip_fopen(tmp2, "rb");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ZIPROMReaderDeInit(void * file)
|
||||
{
|
||||
zzip_close((ZZIP_FILE*)file);
|
||||
}
|
||||
|
||||
u32 ZIPROMReaderSize(void * file)
|
||||
{
|
||||
u32 size;
|
||||
|
||||
zzip_seek((ZZIP_FILE*)file, 0, SEEK_END);
|
||||
size = zzip_tell((ZZIP_FILE*)file);
|
||||
zzip_seek((ZZIP_FILE*)file, 0, SEEK_SET);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int ZIPROMReaderSeek(void * file, int offset, int whence)
|
||||
{
|
||||
return zzip_seek((ZZIP_FILE*)file, offset, whence);
|
||||
}
|
||||
|
||||
int ZIPROMReaderRead(void * file, void * buffer, u32 size)
|
||||
{
|
||||
#ifdef ZZIP_OLD_READ
|
||||
return zzip_read((ZZIP_FILE*)file, (char *) buffer, size);
|
||||
#else
|
||||
return zzip_read((ZZIP_FILE*)file, buffer, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
int ZIPROMReaderWrite(void *, void *, u32)
|
||||
{
|
||||
//not supported ever
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct {
|
||||
void* buf;
|
||||
int len;
|
||||
int pos;
|
||||
} mem;
|
||||
|
||||
void * MemROMReaderInit(const char * filename)
|
||||
{
|
||||
return NULL; //dummy
|
||||
}
|
||||
|
||||
void MemROMReaderDeInit(void *)
|
||||
{
|
||||
//nothing to do
|
||||
}
|
||||
u32 MemROMReaderSize(void *)
|
||||
{
|
||||
return (u32)mem.len;
|
||||
}
|
||||
int MemROMReaderSeek(void * file, int offset, int whence)
|
||||
{
|
||||
switch(whence) {
|
||||
case SEEK_SET:
|
||||
mem.pos = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
mem.pos += offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
mem.pos = mem.len + offset;
|
||||
break;
|
||||
}
|
||||
return mem.pos;
|
||||
}
|
||||
|
||||
int MemROMReaderRead(void * file, void * buffer, u32 size)
|
||||
{
|
||||
if(mem.pos<0) return 0;
|
||||
|
||||
int todo = (int)size;
|
||||
int remain = mem.len - mem.pos;
|
||||
if(remain<todo)
|
||||
todo = remain;
|
||||
|
||||
if(todo<=0)
|
||||
return 0;
|
||||
else if(todo==1) *(u8*)buffer = ((u8*)mem.buf)[mem.pos];
|
||||
else memcpy(buffer,(u8*)mem.buf + mem.pos, todo);
|
||||
mem.pos += todo;
|
||||
return todo;
|
||||
}
|
||||
|
||||
int MemROMReaderWrite(void * file, void * buffer, u32 size)
|
||||
{
|
||||
if(mem.pos<0) return 0;
|
||||
|
||||
int todo = (int)size;
|
||||
int remain = mem.len - mem.pos;
|
||||
if(remain<todo)
|
||||
todo = remain;
|
||||
|
||||
if (todo == 1) ((u8*)mem.buf)[mem.pos] = *(u8*)buffer;
|
||||
else memcpy((u8*)mem.buf + mem.pos,buffer, todo);
|
||||
mem.pos += todo;
|
||||
return todo;
|
||||
}
|
||||
|
||||
static ROMReader_struct MemROMReader =
|
||||
{
|
||||
ROMREADER_MEM,
|
||||
"Memory ROM Reader",
|
||||
MemROMReaderInit,
|
||||
MemROMReaderDeInit,
|
||||
MemROMReaderSize,
|
||||
MemROMReaderSeek,
|
||||
MemROMReaderRead,
|
||||
MemROMReaderWrite,
|
||||
};
|
||||
|
||||
ROMReader_struct * MemROMReaderRead_TrueInit(void* buf, int length)
|
||||
{
|
||||
mem.buf = buf;
|
||||
mem.len = length;
|
||||
mem.pos = 0;
|
||||
return &MemROMReader;
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2007 Guillaume Duhamel
|
||||
Copyright (C) 2007-2022 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ROMREADER_H_
|
||||
#define _ROMREADER_H_
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define ROMREADER_DEFAULT -1
|
||||
#define ROMREADER_STD 0
|
||||
#define ROMREADER_GZIP 1
|
||||
#define ROMREADER_ZIP 2
|
||||
#define ROMREADER_MEM 3
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int id;
|
||||
const char * Name;
|
||||
void * (*Init)(const char * filename);
|
||||
void (*DeInit)(void * file);
|
||||
u32 (*Size)(void * file);
|
||||
int (*Seek)(void * file, int offset, int whence);
|
||||
int (*Read)(void * file, void * buffer, u32 size);
|
||||
int (*Write)(void * file, void * buffer, u32 size);
|
||||
} ROMReader_struct;
|
||||
|
||||
extern ROMReader_struct STDROMReader;
|
||||
#ifdef HAVE_LIBZ
|
||||
extern ROMReader_struct GZIPROMReader;
|
||||
#endif
|
||||
#ifdef HAVE_LIBZZIP
|
||||
extern ROMReader_struct ZIPROMReader;
|
||||
#endif
|
||||
|
||||
ROMReader_struct * ROMReaderInit(char ** filename);
|
||||
ROMReader_struct * MemROMReaderRead_TrueInit(void* buf, int length);
|
||||
|
||||
#endif // _ROMREADER_H_
|
2124
desmume/src/SPU.cpp
2124
desmume/src/SPU.cpp
File diff suppressed because it is too large
Load Diff
|
@ -1,305 +0,0 @@
|
|||
/*
|
||||
Copyright 2006 Theo Berkau
|
||||
Copyright (C) 2006-2015 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SPU_H
|
||||
#define SPU_H
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "matrix.h"
|
||||
#include "metaspu/metaspu.h"
|
||||
|
||||
class EMUFILE;
|
||||
|
||||
#define SNDCORE_DEFAULT -1
|
||||
#define SNDCORE_DUMMY 0
|
||||
|
||||
#define CHANSTAT_STOPPED 0
|
||||
#define CHANSTAT_PLAY 1
|
||||
|
||||
#define SPUINTERPOLATION_TAPS 4 // Must be at least 4 for Catmull-Rom interpolation
|
||||
|
||||
//who made these static? theyre used in multiple places.
|
||||
FORCEINLINE s32 spumuldiv7(s32 val, u8 multiplier) {
|
||||
assert(multiplier <= 127);
|
||||
return (multiplier == 127) ? val : ((val * multiplier) >> 7);
|
||||
}
|
||||
|
||||
enum SPUInterpolationMode
|
||||
{
|
||||
SPUInterpolation_None = 0,
|
||||
SPUInterpolation_Linear = 1,
|
||||
SPUInterpolation_Cosine = 2,
|
||||
SPUInterpolation_CatmullRom = 3
|
||||
};
|
||||
|
||||
struct SoundInterface_struct
|
||||
{
|
||||
int id;
|
||||
const char *Name;
|
||||
int (*Init)(int buffersize);
|
||||
void (*DeInit)();
|
||||
void (*UpdateAudio)(s16 *buffer, u32 num_samples);
|
||||
u32 (*GetAudioSpace)();
|
||||
void (*MuteAudio)();
|
||||
void (*UnMuteAudio)();
|
||||
void (*SetVolume)(int volume);
|
||||
void (*ClearBuffer)();
|
||||
void (*FetchSamples)(s16 *sampleBuffer, size_t sampleCount, ESynchMode synchMode, ISynchronizingAudioBuffer *theSynchronizer);
|
||||
size_t (*PostProcessSamples)(s16 *postProcessBuffer, size_t requestedSampleCount, ESynchMode synchMode, ISynchronizingAudioBuffer *theSynchronizer);
|
||||
};
|
||||
|
||||
extern SoundInterface_struct SNDDummy;
|
||||
extern SoundInterface_struct SNDFile;
|
||||
extern int SPU_currentCoreNum;
|
||||
|
||||
struct channel_struct
|
||||
{
|
||||
channel_struct() : num(0),
|
||||
vol(0),
|
||||
volumeDiv(0),
|
||||
hold(0),
|
||||
pan(0),
|
||||
waveduty(0),
|
||||
repeat(0),
|
||||
format(0),
|
||||
keyon(0),
|
||||
status(0),
|
||||
pcm16bOffs(0),
|
||||
addr(0),
|
||||
timer(0),
|
||||
loopstart(0),
|
||||
length(0),
|
||||
totlength(0),
|
||||
totlength_shifted(0),
|
||||
sampcntFrac(0),
|
||||
sampcntInt(0),
|
||||
sampincFrac(0),
|
||||
sampincInt(0),
|
||||
loop_pcm16b(0),
|
||||
index(0),
|
||||
loop_index(0),
|
||||
x(0)
|
||||
{}
|
||||
u32 num;
|
||||
u8 vol;
|
||||
u8 volumeDiv;
|
||||
u8 hold;
|
||||
u8 pan;
|
||||
u8 waveduty;
|
||||
u8 repeat;
|
||||
u8 format;
|
||||
u8 keyon;
|
||||
u8 status;
|
||||
u8 pcm16bOffs;
|
||||
u32 addr;
|
||||
u16 timer;
|
||||
u16 loopstart;
|
||||
u32 length;
|
||||
u32 totlength;
|
||||
s32 totlength_shifted;
|
||||
u32 sampcntFrac;
|
||||
s32 sampcntInt;
|
||||
u32 sampincFrac;
|
||||
u32 sampincInt;
|
||||
s16 pcm16b[SPUINTERPOLATION_TAPS];
|
||||
// ADPCM specific
|
||||
s16 loop_pcm16b;
|
||||
s32 index;
|
||||
int loop_index;
|
||||
// PSG noise
|
||||
u16 x;
|
||||
};
|
||||
|
||||
class SPUFifo
|
||||
{
|
||||
public:
|
||||
SPUFifo();
|
||||
void enqueue(s16 val);
|
||||
s16 dequeue();
|
||||
s16 buffer[16];
|
||||
s32 head,tail,size;
|
||||
void save(EMUFILE &fp);
|
||||
bool load(EMUFILE &fp);
|
||||
void reset();
|
||||
};
|
||||
|
||||
class SPU_struct
|
||||
{
|
||||
public:
|
||||
SPU_struct(int buffersize);
|
||||
u32 bufpos;
|
||||
u32 buflength;
|
||||
s32 *sndbuf;
|
||||
s32 lastdata; //the last sample that a channel generated
|
||||
s16 *outbuf;
|
||||
u32 bufsize;
|
||||
channel_struct channels[16];
|
||||
|
||||
//registers
|
||||
struct REGS {
|
||||
REGS()
|
||||
: mastervol(0)
|
||||
, ctl_left(0)
|
||||
, ctl_right(0)
|
||||
, ctl_ch1bypass(0)
|
||||
, ctl_ch3bypass(0)
|
||||
, masteren(0)
|
||||
, soundbias(0)
|
||||
{}
|
||||
|
||||
u8 mastervol;
|
||||
u8 ctl_left, ctl_right;
|
||||
u8 ctl_ch1bypass, ctl_ch3bypass;
|
||||
u8 masteren;
|
||||
u16 soundbias;
|
||||
|
||||
enum LeftOutputMode
|
||||
{
|
||||
LOM_LEFT_MIXER=0, LOM_CH1=1, LOM_CH3=2, LOM_CH1_PLUS_CH3=3
|
||||
};
|
||||
|
||||
enum RightOutputMode
|
||||
{
|
||||
ROM_RIGHT_MIXER=0, ROM_CH1=1, ROM_CH3=2, ROM_CH1_PLUS_CH3=3
|
||||
};
|
||||
|
||||
struct CAP {
|
||||
CAP()
|
||||
: add(0), source(0), oneshot(0), bits8(0), active(0), dad(0), len(0)
|
||||
{}
|
||||
u8 add, source, oneshot, bits8, active;
|
||||
u32 dad;
|
||||
u16 len;
|
||||
struct Runtime {
|
||||
Runtime()
|
||||
: running(0), curdad(0), maxdad(0)
|
||||
{}
|
||||
u8 running;
|
||||
u32 curdad;
|
||||
u32 maxdad;
|
||||
u32 sampcntFrac;
|
||||
u32 sampcntInt;
|
||||
SPUFifo fifo;
|
||||
} runtime;
|
||||
} cap[2];
|
||||
} regs;
|
||||
|
||||
void reset();
|
||||
~SPU_struct();
|
||||
void KeyOff(int channel);
|
||||
void KeyOn(int channel);
|
||||
void KeyProbe(int channel);
|
||||
void ProbeCapture(int which);
|
||||
void WriteByte(u32 addr, u8 val);
|
||||
void WriteWord(u32 addr, u16 val);
|
||||
void WriteLong(u32 addr, u32 val);
|
||||
u8 ReadByte(u32 addr);
|
||||
u16 ReadWord(u32 addr);
|
||||
u32 ReadLong(u32 addr);
|
||||
bool isSPU(u32 addr) { return ((addr >= 0x04000400) && (addr < 0x04000520)); }
|
||||
|
||||
//kills all channels but leaves SPU otherwise running normally
|
||||
void ShutUp();
|
||||
};
|
||||
|
||||
extern SPU_struct *SPU_core, *SPU_user;
|
||||
extern int spu_core_samples;
|
||||
|
||||
int SPU_ChangeSoundCore(int coreid, int newBufferSizeBytes);
|
||||
SoundInterface_struct *SPU_SoundCore();
|
||||
|
||||
void SPU_ReInit(bool fakeBoot = false);
|
||||
int SPU_Init(int coreid, int newBufferSizeBytes);
|
||||
void SPU_Pause(int pause);
|
||||
void SPU_SetVolume(int newVolume);
|
||||
void SPU_SetSynchMode(int mode, int method);
|
||||
void SPU_ClearOutputBuffer(void);
|
||||
void SPU_Reset(void);
|
||||
void SPU_DeInit(void);
|
||||
void SPU_KeyOn(int channel);
|
||||
static FORCEINLINE void SPU_WriteByte(u32 addr, u8 val)
|
||||
{
|
||||
addr &= 0xFFF;
|
||||
|
||||
SPU_core->WriteByte(addr,val);
|
||||
if(SPU_user)
|
||||
SPU_user->WriteByte(addr,val);
|
||||
}
|
||||
static FORCEINLINE void SPU_WriteWord(u32 addr, u16 val)
|
||||
{
|
||||
addr &= 0xFFF;
|
||||
|
||||
SPU_core->WriteWord(addr,val);
|
||||
if(SPU_user)
|
||||
SPU_user->WriteWord(addr,val);
|
||||
}
|
||||
static FORCEINLINE void SPU_WriteLong(u32 addr, u32 val)
|
||||
{
|
||||
addr &= 0xFFF;
|
||||
|
||||
SPU_core->WriteLong(addr,val);
|
||||
if(SPU_user)
|
||||
SPU_user->WriteLong(addr,val);
|
||||
}
|
||||
static FORCEINLINE u8 SPU_ReadByte(u32 addr) { return SPU_core->ReadByte(addr & 0x0FFF); }
|
||||
static FORCEINLINE u16 SPU_ReadWord(u32 addr) { return SPU_core->ReadWord(addr & 0x0FFF); }
|
||||
static FORCEINLINE u32 SPU_ReadLong(u32 addr) { return SPU_core->ReadLong(addr & 0x0FFF); }
|
||||
void SPU_Emulate_core(void);
|
||||
void SPU_Emulate_user(bool mix = true);
|
||||
void SPU_DefaultFetchSamples(s16 *sampleBuffer, size_t sampleCount, ESynchMode synchMode, ISynchronizingAudioBuffer *theSynchronizer);
|
||||
size_t SPU_DefaultPostProcessSamples(s16 *postProcessBuffer, size_t requestedSampleCount, ESynchMode synchMode, ISynchronizingAudioBuffer *theSynchronizer);
|
||||
|
||||
void spu_savestate(EMUFILE &os);
|
||||
bool spu_loadstate(EMUFILE &is, int size);
|
||||
|
||||
enum WAVMode
|
||||
{
|
||||
WAVMODE_ANY = -1,
|
||||
WAVMODE_CORE = 0,
|
||||
WAVMODE_USER = 1
|
||||
};
|
||||
|
||||
class WavWriter
|
||||
{
|
||||
public:
|
||||
WavWriter();
|
||||
bool open(const std::string & fname);
|
||||
void close();
|
||||
void update(void* soundData, int numSamples);
|
||||
bool isRecording() const;
|
||||
WAVMode mode;
|
||||
private:
|
||||
FILE *spufp;
|
||||
};
|
||||
|
||||
void WAV_End();
|
||||
bool WAV_Begin(const char* fname, WAVMode mode=WAVMODE_CORE);
|
||||
bool WAV_IsRecording(WAVMode mode=WAVMODE_ANY);
|
||||
void WAV_WavSoundUpdate(void* soundData, int numSamples, WAVMode mode=WAVMODE_CORE);
|
||||
|
||||
// we should make this configurable eventually
|
||||
// but at least defining it somewhere is probably a step in the right direction
|
||||
#define DESMUME_SAMPLE_RATE 44100
|
||||
//#define DESMUME_SAMPLE_RATE 48000
|
||||
|
||||
#endif
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2010-2015 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot1.h"
|
||||
|
||||
class Slot1_None : public ISlot1Interface
|
||||
{
|
||||
public:
|
||||
virtual Slot1Info const* info()
|
||||
{
|
||||
static Slot1InfoSimple info("None","Slot1 no-card emulation", 0xFF);
|
||||
return &info;
|
||||
}
|
||||
|
||||
//pretty much every access to the card should just be ignored and reading HIGH-Z off the GC bus.
|
||||
//so, nothing really to do here
|
||||
//(notably, it results in a 0xFFFFFFFF card ID)
|
||||
|
||||
};
|
||||
|
||||
ISlot1Interface* construct_Slot1_None() { return new Slot1_None(); }
|
|
@ -1,236 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2010-2021 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "slot1comp_protocol.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "../slot1.h"
|
||||
#include "../NDSSystem.h"
|
||||
#include "../emufile.h"
|
||||
|
||||
class Slot1_R4 : public ISlot1Interface, public ISlot1Comp_Protocol_Client
|
||||
{
|
||||
private:
|
||||
EMUFILE *img;
|
||||
Slot1Comp_Protocol protocol;
|
||||
u32 write_count;
|
||||
u32 write_enabled;
|
||||
|
||||
public:
|
||||
Slot1_R4()
|
||||
: img(NULL)
|
||||
, write_count(0)
|
||||
, write_enabled(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Slot1Info const* info()
|
||||
{
|
||||
static Slot1InfoSimple info("R4", "Slot1 R4 emulation", 0x03);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
img = slot1_GetFatImage();
|
||||
|
||||
if(!img)
|
||||
INFO("slot1 fat not successfully mounted\n");
|
||||
|
||||
protocol.reset(this);
|
||||
protocol.chipId = 0xFC2;
|
||||
protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0);
|
||||
}
|
||||
|
||||
//called when the emulator disconnects the device
|
||||
virtual void disconnect()
|
||||
{
|
||||
img = NULL;
|
||||
}
|
||||
|
||||
//called when the emulator shuts down, or when the device disappears from existence
|
||||
virtual void shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual void write_command(u8 PROCNUM, GC_Command command)
|
||||
{
|
||||
protocol.write_command(command);
|
||||
}
|
||||
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
|
||||
{
|
||||
protocol.write_GCDATAIN(PROCNUM, val);
|
||||
}
|
||||
virtual u32 read_GCDATAIN(u8 PROCNUM)
|
||||
{
|
||||
return protocol.read_GCDATAIN(PROCNUM);
|
||||
}
|
||||
|
||||
virtual void slot1client_startOperation(eSlot1Operation theOperation)
|
||||
{
|
||||
if (theOperation != eSlot1Operation_Unknown)
|
||||
return;
|
||||
|
||||
u32 address;
|
||||
int cmd = protocol.command.bytes[0];
|
||||
switch(cmd)
|
||||
{
|
||||
case 0xB0:
|
||||
break;
|
||||
case 0xB9:
|
||||
case 0xBA:
|
||||
address = (protocol.command.bytes[1] << 24) | (protocol.command.bytes[2] << 16) | (protocol.command.bytes[3] << 8) | protocol.command.bytes[4];
|
||||
img->fseek(address,SEEK_SET);
|
||||
break;
|
||||
case 0xBB:
|
||||
write_enabled = 1;
|
||||
write_count = 0x80;
|
||||
//passthrough on purpose?
|
||||
case 0xBC:
|
||||
address = (protocol.command.bytes[1] << 24) | (protocol.command.bytes[2] << 16) | (protocol.command.bytes[3] << 8) | protocol.command.bytes[4];
|
||||
img->fseek(address,SEEK_SET);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual u32 slot1client_read_GCDATAIN(eSlot1Operation theOperation)
|
||||
{
|
||||
if (theOperation != eSlot1Operation_Unknown)
|
||||
return 0;
|
||||
|
||||
u32 val = 0;
|
||||
int cmd = protocol.command.bytes[0];
|
||||
switch (cmd)
|
||||
{
|
||||
case 0xB0:
|
||||
val = (img != NULL) ? 0x1F4 : 0x1F2;
|
||||
break;
|
||||
case 0xB9:
|
||||
val = (rand() % 100) ? (img) ? 0x1F4 : 0x1F2 : 0;
|
||||
break;
|
||||
case 0xBB:
|
||||
case 0xBC:
|
||||
val = 0;
|
||||
break;
|
||||
case 0xBA:
|
||||
//INFO("Read from sd at sector %08X at adr %08X ",card.address/512,ftell(img));
|
||||
img->read_32LE(val);
|
||||
//INFO("val %08X\n",val);
|
||||
break;
|
||||
default:
|
||||
val = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void slot1client_write_GCDATAIN(eSlot1Operation theOperation, u32 val)
|
||||
{
|
||||
if (theOperation != eSlot1Operation_Unknown)
|
||||
return;
|
||||
|
||||
int cmd = protocol.command.bytes[0];
|
||||
switch (cmd)
|
||||
{
|
||||
case 0xBB:
|
||||
{
|
||||
if (write_count && write_enabled)
|
||||
{
|
||||
img->write_32LE(val);
|
||||
img->fflush();
|
||||
write_count--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void post_fakeboot(int PROCNUM)
|
||||
{
|
||||
// The BIOS leaves the card in NORMAL mode
|
||||
protocol.mode = eCardMode_NORMAL;
|
||||
}
|
||||
|
||||
void write32_GCDATAIN(u32 val)
|
||||
{
|
||||
//bool log = false;
|
||||
|
||||
//last_write_count = write_count;
|
||||
|
||||
//can someone tell me ... what the hell is this doing, anyway?
|
||||
//seems odd to use card.command[4] for this... isnt it part of the address?
|
||||
if (protocol.command.bytes[4])
|
||||
{
|
||||
// transfer is done
|
||||
//are you SURE this is logical? there doesnt seem to be any way for the card to signal that
|
||||
T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF);
|
||||
|
||||
MMU_GC_endTransfer(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int cmd = protocol.command.bytes[0];
|
||||
switch (cmd)
|
||||
{
|
||||
case 0xBB:
|
||||
{
|
||||
if (write_count && write_enabled)
|
||||
{
|
||||
img->write_32LE(val);
|
||||
img->fflush();
|
||||
write_count--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (write_count == 0)
|
||||
{
|
||||
write_enabled = 0;
|
||||
|
||||
//transfer is done
|
||||
|
||||
//are you SURE this is logical? there doesnt seem to be any way for the card to signal that
|
||||
T1WriteLong(MMU.MMU_MEM[0][0x40], 0x1A4,val & 0x7F7FFFFF);
|
||||
|
||||
//but isnt this a different IRQ? IREQ_MC perhaps
|
||||
MMU_GC_endTransfer(0);
|
||||
}
|
||||
|
||||
/*if(log)
|
||||
{
|
||||
INFO("WRITE CARD command: %02X%02X%02X%02X%02X%02X%02X%02X\t",
|
||||
card.command[0], card.command[1], card.command[2], card.command[3],
|
||||
card.command[4], card.command[5], card.command[6], card.command[7]);
|
||||
INFO("FROM: %08X\t", NDS_ARM9.instruct_adr);
|
||||
INFO("VAL: %08X\n", val);
|
||||
}*/
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ISlot1Interface* construct_Slot1_R4() { return new Slot1_R4(); }
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2013-2015 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot1.h"
|
||||
#include "../NDSSystem.h"
|
||||
|
||||
class Slot1_Retail_Auto : public ISlot1Interface
|
||||
{
|
||||
private:
|
||||
ISlot1Interface *mSelectedImplementation;
|
||||
|
||||
public:
|
||||
Slot1_Retail_Auto()
|
||||
: mSelectedImplementation(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Slot1Info const* info()
|
||||
{
|
||||
static Slot1InfoSimple info("Retail (Auto)","Slot1 Retail (auto-selection) card emulation", 0xFE);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
|
||||
NDS_SLOT1_TYPE selection = NDS_SLOT1_RETAIL_MCROM;
|
||||
|
||||
//check game ID in core emulator and select right implementation
|
||||
//gamehack: definitely not a game hack, just a lazy way of selecting the right equipment for the game
|
||||
if(gameInfo.IsCode("UOR") || // WarioWare - D.I.Y. (U)(E)(EUR) / Made in Ore (J)
|
||||
gameInfo.IsCode("UXBP") || // Jam with the Band (EUR)
|
||||
gameInfo.IsCode("AXBJ") // Daigassou! Band-Brothers DX (J)
|
||||
)
|
||||
selection = NDS_SLOT1_RETAIL_NAND;
|
||||
|
||||
slot1_selected_type = selection;
|
||||
mSelectedImplementation = slot1_List[selection];
|
||||
mSelectedImplementation->connect();
|
||||
printf("Slot1 auto-selected device type: %s\n",mSelectedImplementation->info()->name());
|
||||
}
|
||||
|
||||
virtual void disconnect()
|
||||
{
|
||||
if(mSelectedImplementation) mSelectedImplementation->disconnect();
|
||||
mSelectedImplementation = NULL;
|
||||
}
|
||||
|
||||
virtual void write_command(u8 PROCNUM, GC_Command command)
|
||||
{
|
||||
mSelectedImplementation->write_command(PROCNUM, command);
|
||||
}
|
||||
|
||||
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
|
||||
{
|
||||
mSelectedImplementation->write_GCDATAIN(PROCNUM, val);
|
||||
}
|
||||
|
||||
virtual u32 read_GCDATAIN(u8 PROCNUM)
|
||||
{
|
||||
return mSelectedImplementation->read_GCDATAIN(PROCNUM);
|
||||
}
|
||||
|
||||
virtual u8 auxspi_transaction(int PROCNUM, u8 value)
|
||||
{
|
||||
return mSelectedImplementation->auxspi_transaction(PROCNUM, value);
|
||||
}
|
||||
|
||||
virtual void auxspi_reset(int PROCNUM)
|
||||
{
|
||||
mSelectedImplementation->auxspi_reset(PROCNUM);
|
||||
}
|
||||
|
||||
virtual void post_fakeboot(int PROCNUM)
|
||||
{
|
||||
mSelectedImplementation->post_fakeboot(PROCNUM);
|
||||
}
|
||||
|
||||
virtual void savestate(EMUFILE &os)
|
||||
{
|
||||
mSelectedImplementation->savestate(os);
|
||||
}
|
||||
|
||||
virtual void loadstate(EMUFILE &is)
|
||||
{
|
||||
mSelectedImplementation->loadstate(is);
|
||||
}
|
||||
};
|
||||
|
||||
ISlot1Interface* construct_Slot1_Retail_Auto() { return new Slot1_Retail_Auto(); }
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2010-2021 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "slot1comp_mc.h"
|
||||
#include "slot1comp_rom.h"
|
||||
#include "slot1comp_protocol.h"
|
||||
|
||||
#include "../slot1.h"
|
||||
#include "../NDSSystem.h"
|
||||
|
||||
//quick architecture overview:
|
||||
//MCROM receives GC bus commands from MMU.cpp
|
||||
//those are passed on to the protocol component for parsing
|
||||
//protocol calls back into MCROM via ISlot1Comp_Protocol_Client interface for things the protocol doesnt know about (the contents of the rom, chiefly)
|
||||
//MCROM utilizes the rom component for address logic and delivering data
|
||||
|
||||
class Slot1_Retail_MCROM : public ISlot1Interface, public ISlot1Comp_Protocol_Client
|
||||
{
|
||||
private:
|
||||
Slot1Comp_Protocol protocol;
|
||||
Slot1Comp_Rom rom;
|
||||
|
||||
public:
|
||||
|
||||
virtual Slot1Info const* info()
|
||||
{
|
||||
static Slot1InfoSimple info("Retail MC+ROM", "Slot1 Retail MC+ROM (standard) card emulation", 0x01);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
protocol.reset(this);
|
||||
protocol.chipId = gameInfo.chipID;
|
||||
protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0);
|
||||
g_Slot1Comp_MC.connect();
|
||||
}
|
||||
|
||||
virtual u8 auxspi_transaction(int PROCNUM, u8 value)
|
||||
{
|
||||
return g_Slot1Comp_MC.auxspi_transaction(PROCNUM,value);
|
||||
}
|
||||
|
||||
virtual void auxspi_reset(int PROCNUM)
|
||||
{
|
||||
g_Slot1Comp_MC.auxspi_reset(PROCNUM);
|
||||
}
|
||||
|
||||
virtual void write_command(u8 PROCNUM, GC_Command command)
|
||||
{
|
||||
protocol.write_command(command);
|
||||
}
|
||||
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
|
||||
{
|
||||
protocol.write_GCDATAIN(PROCNUM, val);
|
||||
}
|
||||
virtual u32 read_GCDATAIN(u8 PROCNUM)
|
||||
{
|
||||
return protocol.read_GCDATAIN(PROCNUM);
|
||||
}
|
||||
|
||||
virtual void slot1client_startOperation(eSlot1Operation theOperation)
|
||||
{
|
||||
rom.start(theOperation,protocol.address);
|
||||
}
|
||||
|
||||
virtual void post_fakeboot(int PROCNUM)
|
||||
{
|
||||
// The BIOS leaves the card in NORMAL mode
|
||||
protocol.mode = eCardMode_NORMAL;
|
||||
}
|
||||
|
||||
virtual void savestate(EMUFILE &os)
|
||||
{
|
||||
protocol.savestate(os);
|
||||
rom.savestate(os);
|
||||
}
|
||||
|
||||
virtual void loadstate(EMUFILE &is)
|
||||
{
|
||||
protocol.loadstate(is);
|
||||
rom.loadstate(is);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
u32 slot1client_read_GCDATAIN(eSlot1Operation operation)
|
||||
{
|
||||
return rom.read();
|
||||
}
|
||||
};
|
||||
|
||||
ISlot1Interface* construct_Slot1_Retail_MCROM() { return new Slot1_Retail_MCROM(); }
|
|
@ -1,214 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2013-2021 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//This module implements a device which is capable of building a nitro FS on the fly
|
||||
//(and REBUILDING it! -- Q: under what conditions?)
|
||||
//so that you can test your homebrew games and patches without having to rebuild the ROM and restart it.
|
||||
//Q. can it handle resized files?
|
||||
|
||||
#include "slot1comp_mc.h"
|
||||
#include "slot1comp_rom.h"
|
||||
#include "slot1comp_protocol.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
#include "../slot1.h"
|
||||
#include "../path.h"
|
||||
#include "../NDSSystem.h"
|
||||
#include "../utils/fsnitro.h"
|
||||
|
||||
class Slot1_Retail_DEBUG : public ISlot1Interface, public ISlot1Comp_Protocol_Client
|
||||
{
|
||||
private:
|
||||
Slot1Comp_Protocol protocol;
|
||||
Slot1Comp_Rom rom;
|
||||
FILE *fpROM;
|
||||
FS_NITRO *fs;
|
||||
u16 curr_file_id;
|
||||
std::string pathData;
|
||||
|
||||
public:
|
||||
|
||||
virtual Slot1Info const* info()
|
||||
{
|
||||
static Slot1InfoSimple info("Retail DEBUG","Slot1 Retail (standard) card emulation + FS Nitro DEBUG", 0x04);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
protocol.reset(this);
|
||||
protocol.chipId = gameInfo.chipID;
|
||||
protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0);
|
||||
|
||||
curr_file_id = 0xFFFF;
|
||||
fpROM = NULL;
|
||||
fs = NULL;
|
||||
|
||||
pathData = path.getpath(path.SLOT1D) + path.GetRomNameWithoutExtension();
|
||||
printf("Path to Slot1 data: %s\n", pathData.c_str());
|
||||
|
||||
fs = new FS_NITRO();
|
||||
fs->rebuildFAT(pathData);
|
||||
}
|
||||
|
||||
virtual u8 auxspi_transaction(int PROCNUM, u8 value)
|
||||
{
|
||||
return g_Slot1Comp_MC.auxspi_transaction(PROCNUM,value);
|
||||
}
|
||||
|
||||
virtual void auxspi_reset(int PROCNUM)
|
||||
{
|
||||
g_Slot1Comp_MC.auxspi_reset(PROCNUM);
|
||||
}
|
||||
|
||||
virtual void write_command(u8 PROCNUM, GC_Command command)
|
||||
{
|
||||
protocol.write_command(command);
|
||||
}
|
||||
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
|
||||
{
|
||||
protocol.write_GCDATAIN(PROCNUM, val);
|
||||
}
|
||||
virtual u32 read_GCDATAIN(u8 PROCNUM)
|
||||
{
|
||||
return protocol.read_GCDATAIN(PROCNUM);
|
||||
}
|
||||
|
||||
virtual void post_fakeboot(int PROCNUM)
|
||||
{
|
||||
// The BIOS leaves the card in NORMAL mode
|
||||
protocol.mode = eCardMode_NORMAL;
|
||||
}
|
||||
|
||||
virtual void savestate(EMUFILE &os)
|
||||
{
|
||||
protocol.savestate(os);
|
||||
rom.savestate(os);
|
||||
}
|
||||
|
||||
virtual void loadstate(EMUFILE &is)
|
||||
{
|
||||
protocol.loadstate(is);
|
||||
rom.loadstate(is);
|
||||
}
|
||||
|
||||
virtual void slot1client_startOperation(eSlot1Operation theOperation)
|
||||
{
|
||||
if (protocol.operation == eSlot1Operation_B7_Read)
|
||||
{
|
||||
u16 file_id = 0xFFFF; u32 offset = 0;
|
||||
bool bFromFile = false;
|
||||
|
||||
if (fs && fs->isFAT(protocol.address))
|
||||
{
|
||||
fs->rebuildFAT(protocol.address, protocol.length, pathData);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fs && fs->getFileIdByAddr(protocol.address, file_id, offset))
|
||||
{
|
||||
if (file_id != curr_file_id)
|
||||
{
|
||||
std::string tmp = fs->getFullPathByFileID(file_id);
|
||||
printf("%04X:[%08X, ofs %08X] %s\n", file_id, protocol.address, offset, tmp.c_str());
|
||||
|
||||
if (fpROM)
|
||||
{
|
||||
fclose(fpROM);
|
||||
fpROM = NULL;
|
||||
}
|
||||
tmp = pathData + tmp;
|
||||
|
||||
fpROM = fopen(tmp.c_str(), "rb");
|
||||
if (fpROM)
|
||||
{
|
||||
bFromFile = true;
|
||||
printf("\t * found at disk, offset %08X\n", offset);
|
||||
if (fseek(fpROM, offset, SEEK_SET) != 0)
|
||||
{
|
||||
printf("\t\t - ERROR seek file position\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fpROM)
|
||||
{
|
||||
bFromFile = true;
|
||||
if (ftell(fpROM) != offset)
|
||||
{
|
||||
printf("\t * new file seek %08Xh\n", offset);
|
||||
fseek(fpROM, offset, SEEK_SET);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!bFromFile && fpROM)
|
||||
{
|
||||
fclose(fpROM);
|
||||
fpROM = NULL;
|
||||
}
|
||||
|
||||
curr_file_id = file_id;
|
||||
}
|
||||
rom.start(theOperation, protocol.address);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
u32 slot1client_read_GCDATAIN(eSlot1Operation operation)
|
||||
{
|
||||
if (protocol.operation == eSlot1Operation_B7_Read)
|
||||
{
|
||||
|
||||
u32 address = rom.getAddress();
|
||||
|
||||
if (fs && fs->isFAT(address))
|
||||
{
|
||||
u32 res = fs->getFATRecord(address);
|
||||
if (res != 0xFFFFFFFF)
|
||||
{
|
||||
rom.incAddress();
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (fpROM)
|
||||
{
|
||||
u32 data = 0;
|
||||
u32 readed = fread(&data, 1, 4, fpROM);
|
||||
if (readed)
|
||||
{
|
||||
rom.incAddress();
|
||||
if (readed < 4)
|
||||
data |= ((u32)0xFFFFFFFF << (readed * 8));
|
||||
return data;
|
||||
}
|
||||
|
||||
fclose(fpROM);
|
||||
fpROM = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return rom.read();
|
||||
}
|
||||
};
|
||||
|
||||
ISlot1Interface* construct_Slot1_Retail_DEBUG() { return new Slot1_Retail_DEBUG(); }
|
|
@ -1,327 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2010-2021 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Games with NAND Flash:
|
||||
// Ore/WarioWare D.I.Y. - chip: SAMSUNG 004
|
||||
// KLC2811ANB-P204
|
||||
// NTR-UORE-0
|
||||
// - 128Mbit
|
||||
|
||||
#include "slot1comp_rom.h"
|
||||
#include "slot1comp_protocol.h"
|
||||
|
||||
#include "../slot1.h"
|
||||
#include "../NDSSystem.h"
|
||||
#include "../emufile.h"
|
||||
|
||||
//quick architecture overview:
|
||||
//NAND receives GC bus commands from MMU.cpp
|
||||
//those are passed on to the protocol component for parsing
|
||||
//protocol calls back into NAND via ISlot1Comp_Protocol_Client interface for things the protocol doesn't know about (the contents of the rom, chiefly)
|
||||
//NAND utilizes the rom component for address logic and delivering data.
|
||||
//it also processes some commands itself which aren't rom-related (the NANDy stuff)
|
||||
|
||||
class Slot1_Retail_NAND : public ISlot1Interface, public ISlot1Comp_Protocol_Client
|
||||
{
|
||||
private:
|
||||
u32 subAdr;
|
||||
|
||||
Slot1Comp_Protocol protocol;
|
||||
Slot1Comp_Rom rom;
|
||||
|
||||
u32 mode;
|
||||
u32 handle_save;
|
||||
|
||||
//current NAND read/write start position
|
||||
//when this is changed, the read/write cursor will be reset to it
|
||||
//when it is set to the same value, the read/write cursor will NOT be reset
|
||||
//(this is since some value must necessarily come in on the protocol address, so the 'current save_start' is used as a special 'dont change' value
|
||||
u32 save_start;
|
||||
|
||||
//current NAND read/write cursor
|
||||
u32 save_adr;
|
||||
|
||||
public:
|
||||
virtual Slot1Info const* info()
|
||||
{
|
||||
static Slot1InfoSimple info("Retail NAND","Slot1 retail NAND card emulation", 0x02);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
protocol.reset(this);
|
||||
protocol.chipId = gameInfo.chipID;
|
||||
protocol.gameCode = T1ReadLong((u8*)gameInfo.header.gameCode,0);
|
||||
|
||||
save_adr = 0;
|
||||
handle_save = 0;
|
||||
mode = 0;
|
||||
subAdr = T1ReadWord(gameInfo.header.reserved2, 0x6) << 17;
|
||||
}
|
||||
|
||||
virtual void write_command(u8 PROCNUM, GC_Command command)
|
||||
{
|
||||
protocol.write_command(command);
|
||||
}
|
||||
|
||||
virtual void write_GCDATAIN(u8 PROCNUM, u32 val)
|
||||
{
|
||||
protocol.write_GCDATAIN(PROCNUM, val);
|
||||
}
|
||||
virtual u32 read_GCDATAIN(u8 PROCNUM)
|
||||
{
|
||||
return protocol.read_GCDATAIN(PROCNUM);
|
||||
}
|
||||
|
||||
virtual void slot1client_startOperation(eSlot1Operation theOperation)
|
||||
{
|
||||
//INFO("Start command: %02X%02X%02X%02X%02X%02X%02X%02X\t",
|
||||
// protocol.command.bytes[0], protocol.command.bytes[1], protocol.command.bytes[2], protocol.command.bytes[3],
|
||||
// protocol.command.bytes[4], protocol.command.bytes[5], protocol.command.bytes[6], protocol.command.bytes[7]);
|
||||
//INFO("FROM: %08X\n", NDS_ARM9.instruct_adr);
|
||||
|
||||
u32 addressFromProtocol = (protocol.command.bytes[1] << 24) | (protocol.command.bytes[2] << 16) | (protocol.command.bytes[3] << 8) | protocol.command.bytes[4];
|
||||
|
||||
//pass the normal rom operations along to the rom component
|
||||
switch (theOperation)
|
||||
{
|
||||
case eSlot1Operation_00_ReadHeader_Unencrypted:
|
||||
rom.start(theOperation, addressFromProtocol);
|
||||
return;
|
||||
|
||||
case eSlot1Operation_2x_SecureAreaLoad:
|
||||
rom.start(theOperation, protocol.address);
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//handle special commands ourselves
|
||||
int cmd = protocol.command.bytes[0];
|
||||
switch(cmd)
|
||||
{
|
||||
// Nand Init
|
||||
case 0x94:
|
||||
mode = cmd;
|
||||
break;
|
||||
|
||||
// Nand Error?
|
||||
case 0xD6:
|
||||
break;
|
||||
|
||||
//Nand Write Page
|
||||
case 0x81:
|
||||
mode = cmd;
|
||||
if(addressFromProtocol != save_start)
|
||||
{
|
||||
save_start = addressFromProtocol;
|
||||
save_adr = (addressFromProtocol & gameInfo.mask) - subAdr;
|
||||
}
|
||||
handle_save = 1;
|
||||
break;
|
||||
|
||||
case 0x84: //Write disable
|
||||
case 0x85: //Write enable
|
||||
mode = cmd;
|
||||
break;
|
||||
case 0x8B:
|
||||
mode = cmd;
|
||||
handle_save = 0;
|
||||
MMU_new.backupDevice.flushBackup();
|
||||
break;
|
||||
|
||||
//Start read mode
|
||||
case 0xB7:
|
||||
if (handle_save)
|
||||
{
|
||||
mode = cmd;
|
||||
if(addressFromProtocol != save_start)
|
||||
{
|
||||
save_start = addressFromProtocol;
|
||||
save_adr = (addressFromProtocol & gameInfo.mask) - subAdr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rom.start(theOperation, addressFromProtocol);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB2: //Set save position
|
||||
mode = cmd;
|
||||
save_start = addressFromProtocol;
|
||||
//cursor resets regardless of whether save_start changed, that's what makes this special.
|
||||
//the cursor could be reset to the beginning of the previous save_start region
|
||||
save_adr = (addressFromProtocol & gameInfo.mask) - subAdr;
|
||||
handle_save = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual u32 slot1client_read_GCDATAIN(eSlot1Operation operation)
|
||||
{
|
||||
//pass the normal rom operations along to the rom component
|
||||
switch(operation)
|
||||
{
|
||||
case eSlot1Operation_00_ReadHeader_Unencrypted:
|
||||
case eSlot1Operation_2x_SecureAreaLoad:
|
||||
//case eSlot1Operation_B7_Read:
|
||||
return rom.read();
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//handle special commands ourselves
|
||||
int cmd = protocol.command.bytes[0];
|
||||
int val = 0;
|
||||
switch(cmd)
|
||||
{
|
||||
// Nand Init?
|
||||
case 0x94:
|
||||
val = 0;
|
||||
mode = 0;
|
||||
break;
|
||||
|
||||
//Rom/Save Read
|
||||
case 0xB7:
|
||||
{
|
||||
if(handle_save)
|
||||
{
|
||||
MMU_new.backupDevice.ensure(save_adr+4, (u8)0);
|
||||
|
||||
val = MMU_new.backupDevice.readLong(save_adr, 0);
|
||||
|
||||
save_adr += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = rom.read();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Nand Status?
|
||||
case 0xD6:
|
||||
//0x80 == busy
|
||||
//0x40 == ??
|
||||
//0x20 == ready?
|
||||
//0x10 == write enabled?
|
||||
switch (mode)
|
||||
{
|
||||
case 0x84: //Write disable
|
||||
val = 0x20202020;
|
||||
break;
|
||||
case 0x85: //Write enable
|
||||
val = 0x20202020 | 0x10101010;
|
||||
break;
|
||||
case 0x8B:
|
||||
val = 0x60606060 | 0x10101010;
|
||||
break;
|
||||
case 0xB2: //Set save position
|
||||
val = 0x20202020;
|
||||
break;
|
||||
default:
|
||||
val = 0x60606060; //0x20 == ready
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
virtual void slot1client_write_GCDATAIN(eSlot1Operation operation, u32 val)
|
||||
{
|
||||
//pass the normal rom operations along to the rom component
|
||||
switch(operation)
|
||||
{
|
||||
case eSlot1Operation_00_ReadHeader_Unencrypted:
|
||||
case eSlot1Operation_B7_Read:
|
||||
case eSlot1Operation_2x_SecureAreaLoad:
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//handle special commands ourselves
|
||||
int cmd = protocol.command.bytes[0];
|
||||
u32 value = val;
|
||||
u32 adr = save_adr;
|
||||
switch(cmd)
|
||||
{
|
||||
case 0x81: //Nand Write
|
||||
|
||||
MMU_new.backupDevice.ensure(adr+4, (u8)0);
|
||||
MMU_new.backupDevice.writeLong(adr, val);
|
||||
|
||||
save_adr += 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void post_fakeboot(int PROCNUM)
|
||||
{
|
||||
// The BIOS leaves the card in NORMAL mode
|
||||
protocol.mode = eCardMode_NORMAL;
|
||||
}
|
||||
|
||||
virtual void savestate(EMUFILE &os)
|
||||
{
|
||||
s32 version = 0;
|
||||
|
||||
protocol.savestate(os);
|
||||
rom.savestate(os);
|
||||
|
||||
os.write_32LE(version);
|
||||
|
||||
os.write_32LE(mode);
|
||||
os.write_32LE(handle_save);
|
||||
os.write_32LE(save_adr);
|
||||
os.write_32LE(save_start);
|
||||
os.write_32LE(subAdr);
|
||||
}
|
||||
|
||||
virtual void loadstate(EMUFILE &is)
|
||||
{
|
||||
s32 version = 0;
|
||||
|
||||
protocol.loadstate(is);
|
||||
rom.loadstate(is);
|
||||
|
||||
is.read_32LE(version);
|
||||
|
||||
// version 0
|
||||
if (version >= 0)
|
||||
{
|
||||
is.read_32LE(mode);
|
||||
is.read_32LE(handle_save);
|
||||
is.read_32LE(save_adr);
|
||||
is.read_32LE(save_start);
|
||||
is.read_32LE(subAdr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
ISlot1Interface* construct_Slot1_Retail_NAND() { return new Slot1_Retail_NAND(); }
|
||||
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2013-2017 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//this file contains the components used for emulating standard gamecard "MC" devices (eeprom, fram, flash)
|
||||
//this is largely done by accessing the BackupDevice resources in the core emulator
|
||||
|
||||
#include "slot1comp_mc.h"
|
||||
|
||||
#include "../MMU.h"
|
||||
#include "../NDSSystem.h"
|
||||
|
||||
Slot1Comp_MC g_Slot1Comp_MC;
|
||||
|
||||
u8 Slot1Comp_MC::auxspi_transaction(int PROCNUM, u8 value)
|
||||
{
|
||||
return MMU_new.backupDevice.data_command(value, PROCNUM);
|
||||
}
|
||||
|
||||
void Slot1Comp_MC::auxspi_reset(int PROCNUM)
|
||||
{
|
||||
MMU_new.backupDevice.reset_command();
|
||||
}
|
||||
|
||||
void Slot1Comp_MC::connect()
|
||||
{
|
||||
//gamehack: not really a game hack
|
||||
if(gameInfo.IsCode("AXBJ"))
|
||||
MMU_new.backupDevice.uninitializedValue = 0x00; // Daigassou! Band Brothers DX (JP)
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2013-2015 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//this file contains the components used for emulating standard gamecard "MC" devices (eeprom, fram, flash)
|
||||
|
||||
#ifndef _SLOT1COMP_MC_H
|
||||
#define _SLOT1COMP_MC_H
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
class Slot1Comp_MC
|
||||
{
|
||||
public:
|
||||
u8 auxspi_transaction(int PROCNUM, u8 value);
|
||||
void auxspi_reset(int PROCNUM);
|
||||
void connect();
|
||||
};
|
||||
|
||||
extern Slot1Comp_MC g_Slot1Comp_MC;
|
||||
|
||||
#endif
|
|
@ -1,262 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2012-2021 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "slot1comp_protocol.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../armcpu.h"
|
||||
#include "../encrypt.h"
|
||||
#include "../emufile.h"
|
||||
#include "../utils/decrypt/decrypt.h"
|
||||
|
||||
static _KEY1 key1((const u8*)arm7_key);
|
||||
|
||||
void Slot1Comp_Protocol::reset(ISlot1Comp_Protocol_Client* theClient)
|
||||
{
|
||||
this->client = theClient;
|
||||
|
||||
//we have to initialize this to something.. lets use dummy.
|
||||
//(need to clean this up...)
|
||||
memcpy(&command,"\x9F\0\0\0\0\0\0\0",8);
|
||||
operation = eSlot1Operation_9F_Dummy;
|
||||
|
||||
length = 0;
|
||||
delay = 0;
|
||||
mode = eCardMode_RAW;
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::write_command_RAW(GC_Command theCommand)
|
||||
{
|
||||
int cmd = theCommand.bytes[0];
|
||||
if(cmd == 0x9F)
|
||||
{
|
||||
operation = eSlot1Operation_9F_Dummy;
|
||||
length = 0x2000;
|
||||
}
|
||||
if(cmd == 0x90)
|
||||
{
|
||||
operation = eSlot1Operation_90_ChipID;
|
||||
length = 4;
|
||||
//we handle this operation ourselves
|
||||
}
|
||||
if(cmd == 0x3C)
|
||||
{
|
||||
//switch to KEY1
|
||||
length = 0;
|
||||
mode = eCardMode_KEY1;
|
||||
|
||||
//defer initialization of KEY1 until we know we need it, just to save some CPU time.
|
||||
//TODO - some information about these parameters
|
||||
//level == 2
|
||||
//modulo == 8
|
||||
key1.init(gameCode, 2, 0x08);
|
||||
GCLOG("[GC] KEY1 ACTIVATED\n");
|
||||
}
|
||||
if(cmd == 0x00)
|
||||
{
|
||||
operation = eSlot1Operation_00_ReadHeader_Unencrypted;
|
||||
client->slot1client_startOperation(operation);
|
||||
}
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::write_command_KEY1(GC_Command theCommand)
|
||||
{
|
||||
//decrypt the KEY1-format command
|
||||
u32 temp[2];
|
||||
theCommand.toCryptoBuffer(temp);
|
||||
key1.decrypt(temp);
|
||||
theCommand.fromCryptoBuffer(temp);
|
||||
GCLOG("[GC] (key1-decrypted):"); theCommand.print();
|
||||
|
||||
//and process it:
|
||||
int cmd = theCommand.bytes[0];
|
||||
switch(cmd&0xF0)
|
||||
{
|
||||
case 0x10:
|
||||
operation = eSlot1Operation_1x_ChipID;
|
||||
delay = 0x910, length = 4;
|
||||
//we handle this operation ourselves
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
operation = eSlot1Operation_2x_SecureAreaLoad;
|
||||
delay = 0x910, length = 0x11A8;
|
||||
|
||||
//TODO - more endian-safe way of doing this (theres examples in R4)
|
||||
{
|
||||
#ifdef MSB_FIRST
|
||||
u64 cmd64 = *(u64*)theCommand.bytes;
|
||||
#else
|
||||
u64 cmd64 = bswap64(*(u64*)theCommand.bytes);
|
||||
#endif
|
||||
//todo - parse into blocknumber
|
||||
u32 blocknumber = (cmd64>>44)&0xFFFF;
|
||||
if(blocknumber<4||blocknumber>7)
|
||||
printf("SLOT1 WARNING: INVALID BLOCKNUMBER FOR \"Get Secure Area Block\": 0x%04X\n",blocknumber);
|
||||
address = blocknumber*0x1000;
|
||||
}
|
||||
client->slot1client_startOperation(operation);
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
//switch to KEY2
|
||||
delay = 0x910, length = 0;
|
||||
//well.. not really... yet.
|
||||
GCLOG("[GC] KEY2 ACTIVATED\n");
|
||||
break;
|
||||
|
||||
case 0x60:
|
||||
//KEY2 disable? any info?
|
||||
break;
|
||||
|
||||
case 0xA0:
|
||||
delay = 0x910, length = 0;
|
||||
mode = eCardMode_NORMAL;
|
||||
GCLOG("[GC] NORMAL MODE ACTIVATED\n");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::write_command_NORMAL(GC_Command theCommand)
|
||||
{
|
||||
switch(command.bytes[0])
|
||||
{
|
||||
case 0xB7:
|
||||
{
|
||||
operation = eSlot1Operation_B7_Read;
|
||||
|
||||
//TODO - more endian-safe way of doing this (theres examples in R4)
|
||||
#ifdef MSB_FIRST
|
||||
u64 cmd64 = *(u64*)theCommand.bytes;
|
||||
#else
|
||||
u64 cmd64 = bswap64(*(u64*)theCommand.bytes);
|
||||
#endif
|
||||
address = (u32)((cmd64 >> 24));
|
||||
length = 0x200;
|
||||
|
||||
client->slot1client_startOperation(operation);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xB8:
|
||||
operation = eSlot1Operation_B8_ChipID;
|
||||
delay = 0, length = 4;
|
||||
//we handle this operation ourselves
|
||||
break;
|
||||
|
||||
default:
|
||||
operation = eSlot1Operation_Unknown;
|
||||
client->slot1client_startOperation(operation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::write_command(GC_Command theCommand)
|
||||
{
|
||||
this->command = theCommand;
|
||||
|
||||
//unrecognized commands will do something depending on the current state of the card
|
||||
delay = 0;
|
||||
length = 0;
|
||||
address = 0;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case eCardMode_RAW:
|
||||
write_command_RAW(theCommand);
|
||||
break;
|
||||
|
||||
case eCardMode_KEY1:
|
||||
write_command_KEY1(theCommand);
|
||||
break;
|
||||
|
||||
case eCardMode_NORMAL:
|
||||
write_command_NORMAL(theCommand);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::write_GCDATAIN(u8 PROCNUM, u32 val)
|
||||
{
|
||||
switch(operation)
|
||||
{
|
||||
case eSlot1Operation_Unknown:
|
||||
client->slot1client_write_GCDATAIN(operation,val);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
u32 Slot1Comp_Protocol::read_GCDATAIN(u8 PROCNUM)
|
||||
{
|
||||
switch(operation)
|
||||
{
|
||||
default:
|
||||
return client->slot1client_read_GCDATAIN(operation);
|
||||
|
||||
case eSlot1Operation_9F_Dummy:
|
||||
return 0xFFFFFFFF;
|
||||
|
||||
case eSlot1Operation_1x_ChipID:
|
||||
return chipId;
|
||||
|
||||
case eSlot1Operation_90_ChipID:
|
||||
case eSlot1Operation_B8_ChipID:
|
||||
|
||||
//Most games continuously compare the current chipId with the value in
|
||||
//stored in memory at boot-up, probably to know if the card was removed.
|
||||
|
||||
//staff of kings verifies this (it also uses the arm7 IRQ 20 to detect card ejects)
|
||||
return chipId;
|
||||
}
|
||||
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::savestate(EMUFILE &os)
|
||||
{
|
||||
s32 version = 0;
|
||||
os.write_32LE(version);
|
||||
os.write_32LE((s32)mode);
|
||||
os.write_32LE((s32)operation);
|
||||
os.fwrite(command.bytes,8);
|
||||
os.write_32LE(address);
|
||||
os.write_32LE(length);
|
||||
os.write_32LE(delay);
|
||||
os.write_32LE(chipId);
|
||||
os.write_32LE(gameCode);
|
||||
}
|
||||
|
||||
void Slot1Comp_Protocol::loadstate(EMUFILE &is)
|
||||
{
|
||||
s32 version = is.read_s32LE();
|
||||
mode = (eCardMode)is.read_s32LE();
|
||||
operation = (eSlot1Operation)is.read_s32LE();
|
||||
is.fread(command.bytes,8);
|
||||
is.read_32LE(address);
|
||||
is.read_32LE(length);
|
||||
is.read_32LE(delay);
|
||||
is.read_32LE(chipId);
|
||||
is.read_32LE(gameCode);
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2013-2021 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//this file contains the components used for emulating standard gamecard protocol.
|
||||
//this largely means the complex boot-up process.
|
||||
//i think there's no reason why proprietary cards couldn't speak any protocol they wish, as long as they didn't mind being unbootable.
|
||||
//TODO - could this be refactored into a base class? that's probably more reasonable. but we've gone with this modular mix-in architecture so... not yet.
|
||||
|
||||
#ifndef _SLOT1COMP_PROTOCOL_H
|
||||
#define _SLOT1COMP_PROTOCOL_H
|
||||
|
||||
#include "../types.h"
|
||||
#include "../MMU.h"
|
||||
|
||||
class EMUFILE;
|
||||
|
||||
enum eSlot1Operation
|
||||
{
|
||||
//----------
|
||||
//RAW mode operations
|
||||
//before encrypted communications can be established, some values from the rom header must be read.
|
||||
//this is the only way to read the header, actually, since the only reading commands available to games (after KEY2 mode is set) are
|
||||
eSlot1Operation_00_ReadHeader_Unencrypted,
|
||||
//it's not clear why this exists
|
||||
eSlot1Operation_9F_Dummy,
|
||||
eSlot1Operation_90_ChipID,
|
||||
//----------
|
||||
|
||||
//----------
|
||||
//KEY1 mode operations
|
||||
eSlot1Operation_1x_ChipID,
|
||||
eSlot1Operation_2x_SecureAreaLoad,
|
||||
//----------
|
||||
|
||||
//----------
|
||||
//NORMAL mode operations
|
||||
//the main rom data reading command
|
||||
eSlot1Operation_B7_Read,
|
||||
eSlot1Operation_B8_ChipID,
|
||||
//----------
|
||||
|
||||
eSlot1Operation_Unknown
|
||||
};
|
||||
|
||||
class ISlot1Comp_Protocol_Client
|
||||
{
|
||||
public:
|
||||
virtual void slot1client_startOperation(eSlot1Operation theOperation) {}
|
||||
virtual u32 slot1client_read_GCDATAIN(eSlot1Operation theOperation) = 0;
|
||||
virtual void slot1client_write_GCDATAIN(eSlot1Operation theOperation, u32 val) {}
|
||||
};
|
||||
|
||||
|
||||
class Slot1Comp_Protocol
|
||||
{
|
||||
public:
|
||||
|
||||
void savestate(EMUFILE &os);
|
||||
void loadstate(EMUFILE &is);
|
||||
|
||||
//set some kind of protocol/hardware reset state
|
||||
void reset(ISlot1Comp_Protocol_Client* theClient);
|
||||
|
||||
//signals from the GC bus
|
||||
void write_command(GC_Command theCommand);
|
||||
void write_GCDATAIN(u8 PROCNUM, u32 val);
|
||||
u32 read_GCDATAIN(u8 PROCNUM);
|
||||
|
||||
//helpers for write_command()
|
||||
void write_command_RAW(GC_Command theCommand);
|
||||
void write_command_KEY1(GC_Command theCommand);
|
||||
void write_command_NORMAL(GC_Command theCommand);
|
||||
|
||||
//operations not related to obscurities of the protocol or otherwise unknown are passed through to the client here
|
||||
ISlot1Comp_Protocol_Client* client;
|
||||
|
||||
//--state--
|
||||
|
||||
//the major operational mode. the protocol shifts modes and interprets commands into operations differently depending on the mode
|
||||
eCardMode mode;
|
||||
|
||||
//the current operational state
|
||||
eSlot1Operation operation;
|
||||
|
||||
//the command we're currently crunching on
|
||||
GC_Command command;
|
||||
|
||||
//most operations are defined in terms of returning a series of bytes
|
||||
//the meaning of these varies by operation. they are provided publicly as a service to clients
|
||||
u32 address;
|
||||
s32 length, delay; //the expected length and delay of this state
|
||||
|
||||
//chipId which should be returned by the various chipId commands
|
||||
u32 chipId;
|
||||
|
||||
//gameCode used by the protocol KEY1 crypto
|
||||
u32 gameCode;
|
||||
};
|
||||
|
||||
#endif //_SLOT1COMP_PROTOCOL_H
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2010-2021 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "slot1comp_rom.h"
|
||||
|
||||
#include "../NDSSystem.h"
|
||||
#include "../emufile.h"
|
||||
|
||||
|
||||
void Slot1Comp_Rom::start(eSlot1Operation operation, u32 addr)
|
||||
{
|
||||
this->_operation = operation;
|
||||
this->_address = addr;
|
||||
}
|
||||
|
||||
u32 Slot1Comp_Rom::read()
|
||||
{
|
||||
switch(this->_operation)
|
||||
{
|
||||
case eSlot1Operation_00_ReadHeader_Unencrypted:
|
||||
{
|
||||
u32 ret = gameInfo.readROM(this->_address);
|
||||
this->_address = (this->_address + 4) & 0xFFF;
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case eSlot1Operation_2x_SecureAreaLoad:
|
||||
{
|
||||
//see B7 for details
|
||||
|
||||
//zero 15-sep-2014 - this is meaningless. newer mask is actually reasonable
|
||||
//address &= gameInfo.mask; //sanity check
|
||||
u32 secureAreaAddress = (this->_address - 0x4000);
|
||||
secureAreaAddress &= 0x3FFF; //memory safe sanity test
|
||||
u32 ret = LE_TO_LOCAL_32(*(u32*)(gameInfo.secureArea + secureAreaAddress));
|
||||
this->_address = (this->_address&~0xFFF) + ((this->_address+4)&0xFFF);
|
||||
return ret;
|
||||
}
|
||||
|
||||
case eSlot1Operation_B7_Read:
|
||||
{
|
||||
//TODO - check about non-4-byte aligned addresses
|
||||
|
||||
//it seems that etrian odyssey 3 doesnt work unless we mask this to cart size.
|
||||
//but, a thought: does the internal rom address counter register wrap around? we may be making a mistake by keeping the extra precision
|
||||
//but there is no test case yet
|
||||
this->_address &= gameInfo.mask;
|
||||
|
||||
//feature of retail carts:
|
||||
//B7 "Can be used only for addresses 8000h and up, smaller addresses will be silently redirected to address `8000h+(addr AND 1FFh)`"
|
||||
if(CommonSettings.RetailCardProtection8000)
|
||||
if(this->_address < 0x8000)
|
||||
this->_address = (0x8000 + (this->_address & 0x1FF));
|
||||
|
||||
//1. as a sanity measure for funny-sized roms (homebrew and perhaps truncated retail roms) we need to protect ourselves by returning 0xFF for things still out of range.
|
||||
//2. this isnt right, unless someone documents otherwise:
|
||||
//if (address > gameInfo.header.endROMoffset)
|
||||
// ... the cart hardware doesnt know anything about the rom header. if it has a totally bogus endROMoffset, the cart will probably work just fine. and, the +4 is missing anyway:
|
||||
//3. this is better: it just allows us to read 0xFF anywhere we dont have rom data. forget what the header says
|
||||
//note: we allow the reading to proceed anyway, because the readROM method is built to allow jaggedy reads off the end of the rom to support trimmed roms
|
||||
if(this->_address+4 > gameInfo.romsize)
|
||||
{
|
||||
DEBUG_Notify.ReadBeyondEndOfCart(this->_address,gameInfo.romsize);
|
||||
}
|
||||
|
||||
//actually read from the ROM provider
|
||||
u32 ret = gameInfo.readROM(this->_address);
|
||||
|
||||
//"However, the datastream wraps to the begin of the current 4K block when address+length crosses a 4K boundary (1000h bytes)"
|
||||
this->_address = (this->_address&~0xFFF) + ((this->_address+4)&0xFFF);
|
||||
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
|
||||
} //switch(operation)
|
||||
} //Slot1Comp_Rom::read()
|
||||
|
||||
u32 Slot1Comp_Rom::getAddress()
|
||||
{
|
||||
return this->_address & gameInfo.mask;
|
||||
} //Slot1Comp_Rom::getAddress()
|
||||
|
||||
u32 Slot1Comp_Rom::incAddress()
|
||||
{
|
||||
this->_address &= gameInfo.mask;
|
||||
this->_address = (this->_address&~0xFFF) + ((this->_address+4)&0xFFF);
|
||||
return this->_address;
|
||||
}
|
||||
|
||||
|
||||
void Slot1Comp_Rom::savestate(EMUFILE &os)
|
||||
{
|
||||
s32 version = 0;
|
||||
os.write_32LE(version);
|
||||
os.write_32LE((s32)this->_operation);
|
||||
os.write_32LE(this->_address);
|
||||
}
|
||||
|
||||
void Slot1Comp_Rom::loadstate(EMUFILE &is)
|
||||
{
|
||||
s32 version = is.read_s32LE();
|
||||
this->_operation = (eSlot1Operation)is.read_s32LE();
|
||||
this->_address = is.read_u32LE();
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2010-2021 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//this file contains the components used for emulating standard gamecard ROMs
|
||||
//this is largely done by accessing the rom provided in the core emulator
|
||||
|
||||
#ifndef _SLOT1COMP_ROM_H
|
||||
#define _SLOT1COMP_ROM_H
|
||||
|
||||
#include "slot1comp_protocol.h"
|
||||
#include "../types.h"
|
||||
|
||||
class EMUFILE;
|
||||
|
||||
class Slot1Comp_Rom
|
||||
{
|
||||
public:
|
||||
void start(eSlot1Operation operation, u32 addr);
|
||||
u32 read();
|
||||
u32 getAddress();
|
||||
u32 incAddress();
|
||||
|
||||
void savestate(EMUFILE &os);
|
||||
void loadstate(EMUFILE &is);
|
||||
|
||||
private:
|
||||
u32 _address;
|
||||
eSlot1Operation _operation;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2013-2015 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../slot2.h"
|
||||
|
||||
class Slot2_Auto : public ISlot2Interface
|
||||
{
|
||||
private:
|
||||
ISlot2Interface *mSelectedImplementation;
|
||||
|
||||
public:
|
||||
Slot2_Auto()
|
||||
: mSelectedImplementation(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("Auto","Slot2 (auto-selection) device emulation", 0xFE);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
slot2_selected_type = slot2_DetermineType();
|
||||
mSelectedImplementation = slot2_List[slot2_selected_type];
|
||||
mSelectedImplementation->connect();
|
||||
printf("Slot2 auto-selected device type: %s (0x%02X)\n", mSelectedImplementation->info()->name(), mSelectedImplementation->info()->id());
|
||||
}
|
||||
|
||||
virtual void disconnect()
|
||||
{
|
||||
if(mSelectedImplementation) mSelectedImplementation->disconnect();
|
||||
mSelectedImplementation = NULL;
|
||||
}
|
||||
|
||||
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val) { mSelectedImplementation->writeByte(PROCNUM, addr, val); }
|
||||
virtual void writeWord(u8 PROCNUM, u32 addr, u16 val) { mSelectedImplementation->writeWord(PROCNUM, addr, val); }
|
||||
virtual void writeLong(u8 PROCNUM, u32 addr, u32 val) { mSelectedImplementation->writeLong(PROCNUM, addr, val); }
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr) { return mSelectedImplementation->readByte(PROCNUM, addr); }
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr) { return mSelectedImplementation->readWord(PROCNUM, addr); }
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr) { return mSelectedImplementation->readLong(PROCNUM, addr); }
|
||||
|
||||
virtual void savestate(EMUFILE &os)
|
||||
{
|
||||
mSelectedImplementation->savestate(os);
|
||||
}
|
||||
|
||||
virtual void loadstate(EMUFILE &is)
|
||||
{
|
||||
mSelectedImplementation->loadstate(is);
|
||||
}
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_Auto() { return new Slot2_Auto(); }
|
|
@ -1,196 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 CrazyMax
|
||||
Copyright (C) 2009-2017 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot2.h"
|
||||
#include "../emufile.h"
|
||||
#include "../mem.h"
|
||||
|
||||
#if 0
|
||||
#define EXPINFO(...) INFO(__VA_ARGS__)
|
||||
#else
|
||||
#define EXPINFO(...)
|
||||
#endif
|
||||
|
||||
#define EXPANSION_MEMORY_SIZE (8 * 1024 * 1024)
|
||||
|
||||
static u8 header_0x00B0[] =
|
||||
{ 0xFF, 0xFF, 0x96, 0x00, //this 0x96 is strange. it can't be read from the pak when it boots, it must appear later
|
||||
0x00, 0x24, 0x24, 0x24,
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x7F
|
||||
};
|
||||
|
||||
class Slot2_ExpansionPak : public ISlot2Interface
|
||||
{
|
||||
private:
|
||||
u8 *expMemory;
|
||||
bool ext_ram_lock;
|
||||
public:
|
||||
|
||||
Slot2_ExpansionPak()
|
||||
{
|
||||
expMemory = NULL;
|
||||
ext_ram_lock = true;
|
||||
}
|
||||
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("Memory Expansion Pak", "Official RAM expansion for Opera browser", 0x05);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
if (expMemory == NULL)
|
||||
{
|
||||
expMemory = new u8[EXPANSION_MEMORY_SIZE];
|
||||
}
|
||||
memset(expMemory, 0xFF, EXPANSION_MEMORY_SIZE);
|
||||
ext_ram_lock = true;
|
||||
}
|
||||
|
||||
virtual void disconnect()
|
||||
{
|
||||
delete[] expMemory;
|
||||
expMemory = NULL;
|
||||
}
|
||||
|
||||
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val)
|
||||
{
|
||||
if (ext_ram_lock) return;
|
||||
|
||||
if (addr >= 0x09000000)
|
||||
{
|
||||
u32 offs = (addr - 0x09000000);
|
||||
if (offs >= EXPANSION_MEMORY_SIZE) return;
|
||||
T1WriteByte(expMemory, offs, val);
|
||||
}
|
||||
EXPINFO("ExpMemory: write 08 at 0x%08X = 0x%02X\n", addr, val);
|
||||
}
|
||||
virtual void writeWord(u8 PROCNUM, u32 addr, u16 val)
|
||||
{
|
||||
if (addr == 0x08240000)
|
||||
{
|
||||
if (val == 0)
|
||||
ext_ram_lock = true;
|
||||
else
|
||||
if (val == 1)
|
||||
ext_ram_lock = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ext_ram_lock) return;
|
||||
|
||||
if (addr >= 0x09000000)
|
||||
{
|
||||
u32 offs = (addr - 0x09000000);
|
||||
if (offs >= EXPANSION_MEMORY_SIZE) return;
|
||||
T1WriteWord(expMemory, offs, val);
|
||||
}
|
||||
EXPINFO("ExpMemory: write 16 at 0x%08X = 0x%04X\n", addr, val);
|
||||
}
|
||||
virtual void writeLong(u8 PROCNUM, u32 addr, u32 val)
|
||||
{
|
||||
if (ext_ram_lock) return;
|
||||
|
||||
if (addr >= 0x09000000)
|
||||
{
|
||||
u32 offs = (addr - 0x09000000);
|
||||
if (offs >= EXPANSION_MEMORY_SIZE) return;
|
||||
T1WriteLong(expMemory, offs, val);
|
||||
}
|
||||
EXPINFO("ExpMemory: write 32 at 0x%08X = 0x%08X\n", addr, val);
|
||||
}
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
EXPINFO("ExpMemory: read 08 at 0x%08X\n", addr);
|
||||
|
||||
if ((addr >= 0x080000B0) && (addr < 0x080000C0))
|
||||
return T1ReadByte(header_0x00B0, (addr - 0x080000B0));
|
||||
|
||||
if (addr >= 0x09000000)
|
||||
{
|
||||
u32 offs = (addr - 0x09000000);
|
||||
if (offs >= EXPANSION_MEMORY_SIZE) return (0xFF);
|
||||
return T1ReadByte(expMemory, offs);
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
EXPINFO("ExpMemory: read 16 at 0x%08X\n", addr);
|
||||
|
||||
if ((addr >= 0x080000B0) && (addr < 0x080000C0))
|
||||
return T1ReadWord(header_0x00B0, (addr - 0x080000B0));
|
||||
|
||||
if (addr == 0x0801FFFC) return 0x7FFF;
|
||||
if (addr == 0x08240002) return 0; //this can't be 0xFFFF. dunno why, we just guessed 0
|
||||
|
||||
if (addr >= 0x09000000)
|
||||
{
|
||||
u32 offs = (addr - 0x09000000);
|
||||
if (offs >= EXPANSION_MEMORY_SIZE) return (0xFFFF);
|
||||
return T1ReadWord(expMemory, offs);
|
||||
}
|
||||
|
||||
return 0xFFFF;
|
||||
}
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
EXPINFO("ExpMemory: read 32 at 0x%08X\n", addr);
|
||||
|
||||
if((addr >= 0x080000B0) && (addr < 0x080000C0))
|
||||
return T1ReadLong(header_0x00B0, (addr - 0x080000B0));
|
||||
|
||||
if (addr >= 0x09000000)
|
||||
{
|
||||
u32 offs = (addr - 0x09000000);
|
||||
if (offs >= EXPANSION_MEMORY_SIZE) return 0xFFFFFFFF;
|
||||
return T1ReadLong(expMemory, offs);
|
||||
}
|
||||
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
virtual void savestate(EMUFILE &os)
|
||||
{
|
||||
s32 version = 0;
|
||||
EMUFILE_MEMORY ram = EMUFILE_MEMORY(expMemory, EXPANSION_MEMORY_SIZE);
|
||||
os.write_32LE(version);
|
||||
os.write_bool32(ext_ram_lock);
|
||||
os.write_MemoryStream(ram);
|
||||
}
|
||||
|
||||
virtual void loadstate(EMUFILE &is)
|
||||
{
|
||||
EMUFILE_MEMORY ram = EMUFILE_MEMORY();
|
||||
|
||||
s32 version = is.read_s32LE();
|
||||
|
||||
if (version >= 0)
|
||||
{
|
||||
is.read_bool32(ext_ram_lock);
|
||||
is.read_MemoryStream(ram);
|
||||
memcpy(expMemory, ram.buf(), std::min(EXPANSION_MEMORY_SIZE, ram.size()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_ExpansionPak() { return new Slot2_ExpansionPak(); }
|
|
@ -1,466 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 CrazyMax
|
||||
Copyright (C) 2009-2021 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot2.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../debug.h"
|
||||
#include "../NDSSystem.h"
|
||||
#include "../path.h"
|
||||
#include "../emufile.h"
|
||||
|
||||
#define EEPROM 0x52504545
|
||||
#define SRAM_ 0x4D415253
|
||||
#define FLASH 0x53414C46
|
||||
#define FLASH1M_ 0x5F4D3148
|
||||
#define SIIRTC_V 0x52494953
|
||||
|
||||
static const char *saveTypes[] = {
|
||||
"EEPROM",
|
||||
"SRAM",
|
||||
"FLASH",
|
||||
"FLASH1M",
|
||||
"SIIRTC_V",
|
||||
};
|
||||
|
||||
class Slot2_GbaCart : public ISlot2Interface
|
||||
{
|
||||
private:
|
||||
EMUFILE* fROM;
|
||||
EMUFILE* fSRAM;
|
||||
u32 romSize;
|
||||
u32 sramSize;
|
||||
u32 saveType;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 size;
|
||||
u8 state;
|
||||
u8 cmd;
|
||||
u8 idDevice;
|
||||
u8 idManufacturer;
|
||||
u8 bank;
|
||||
} gbaFlash;
|
||||
|
||||
u32 readRom(const u32 pos, const u8 size)
|
||||
{
|
||||
if (!fROM) return 0xFFFFFFFF;
|
||||
|
||||
fROM->fseek(pos, SEEK_SET);
|
||||
|
||||
u32 data = 0xFFFFFFFF;
|
||||
u32 readed = fROM->fread(&data, size);
|
||||
return data;
|
||||
}
|
||||
|
||||
u32 readSRAM(const u32 pos, const u8 size)
|
||||
{
|
||||
if (!fSRAM)
|
||||
return 0xFFFFFFFF;
|
||||
|
||||
fSRAM->fseek(pos, SEEK_SET);
|
||||
|
||||
u32 data = 0xFFFFFFFF;
|
||||
u32 readed = fSRAM->fread(&data, size);
|
||||
return data;
|
||||
}
|
||||
|
||||
void writeSRAM(const u32 pos, const u8 *data, u32 size)
|
||||
{
|
||||
if (!fSRAM)
|
||||
return;
|
||||
|
||||
fSRAM->fseek(pos, SEEK_SET);
|
||||
|
||||
u32 writed = size;
|
||||
fSRAM->fwrite(data, size);
|
||||
fSRAM->fflush();
|
||||
}
|
||||
|
||||
|
||||
u32 scanSaveTypeGBA()
|
||||
{
|
||||
if (!fROM) return 0xFF;
|
||||
|
||||
fROM->fseek(0, SEEK_SET);
|
||||
int size = fROM->size();
|
||||
|
||||
int lastpct=1;
|
||||
|
||||
int len = fROM->size();
|
||||
for(;;)
|
||||
{
|
||||
u32 romType = 0;
|
||||
u32 readed = fROM->fread(&romType, 4);
|
||||
|
||||
int pos = fROM->ftell();
|
||||
int currPct = pos*100/(size-1);
|
||||
for(int i=lastpct;i<currPct;i++)
|
||||
{
|
||||
if(i%10==0)
|
||||
printf(" %d%%\n",i/10*10);
|
||||
else printf(".");
|
||||
lastpct = currPct;
|
||||
}
|
||||
|
||||
if (readed < 4)
|
||||
break;
|
||||
|
||||
if(pos >= len)
|
||||
break;
|
||||
|
||||
|
||||
switch (romType)
|
||||
{
|
||||
case EEPROM:
|
||||
return 1;
|
||||
case SRAM_:
|
||||
return 2;
|
||||
case FLASH:
|
||||
{
|
||||
u32 tmp = fROM->read_u32LE();
|
||||
return ((tmp == FLASH1M_)?3:5);
|
||||
}
|
||||
case SIIRTC_V:
|
||||
return 4;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void gbaWriteFlash(u32 adr, u8 val)
|
||||
{
|
||||
if (!fSRAM) return;
|
||||
switch (gbaFlash.state)
|
||||
{
|
||||
case 0:
|
||||
if (adr == 0x0A005555)
|
||||
{
|
||||
if (val == 0xF0)
|
||||
{
|
||||
//INFO("GBAgame: Flash: reset\n");
|
||||
gbaFlash.state = 0;
|
||||
gbaFlash.cmd = 0;
|
||||
return;
|
||||
}
|
||||
if (val == 0xAA)
|
||||
{
|
||||
gbaFlash.state = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (adr == 0x0A000000)
|
||||
{
|
||||
if (gbaFlash.cmd == 0xB0)
|
||||
{
|
||||
gbaFlash.bank = val;
|
||||
gbaFlash.cmd = 0;
|
||||
//INFO("GBAgame: Flash: change bank %i\n", val);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if ( (adr == 0x0A002AAA) && (val == 0x55) )
|
||||
{
|
||||
gbaFlash.state = 2;
|
||||
return;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
case 2:
|
||||
if (adr == 0x0A005555)
|
||||
{
|
||||
//INFO("GBAgame: Flash: send command flash 0x%02X\n", val);
|
||||
switch (val)
|
||||
{
|
||||
case 0x80: // Erase
|
||||
gbaFlash.state = 0x80;
|
||||
break;
|
||||
|
||||
case 0x90: // Chip Identification
|
||||
gbaFlash.state = 0x90;
|
||||
break;
|
||||
|
||||
case 0xA0: // Write
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
}
|
||||
gbaFlash.cmd = val;
|
||||
return;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
|
||||
// erase
|
||||
case 0x80:
|
||||
if ( (adr == 0x0A005555) && (val == 0xAA) )
|
||||
{
|
||||
gbaFlash.state = 0x81;
|
||||
return;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
|
||||
case 0x81:
|
||||
if ( (adr == 0x0A002AAA) && (val == 0x55) )
|
||||
{
|
||||
gbaFlash.state = 0x82;
|
||||
return;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
|
||||
case 0x82:
|
||||
if (val == 0x30)
|
||||
{
|
||||
u32 ofs = (adr & 0x0000F000) + (0x10000 * gbaFlash.bank);
|
||||
//INFO("GBAgame: Flash: erase from 0x%08X to 0x%08X\n", ofs + 0x0A000000, ofs + 0x0A001000);
|
||||
u8 *tmp = new u8[0x1000];
|
||||
memset(tmp, 0xFF, 0x1000);
|
||||
writeSRAM(ofs, tmp, 0x1000);
|
||||
delete [] tmp;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
gbaFlash.cmd = 0;
|
||||
return;
|
||||
|
||||
// Chip Identification
|
||||
case 0x90:
|
||||
if ( (adr == 0x0A005555) && (val == 0xAA) )
|
||||
{
|
||||
gbaFlash.state = 0x91;
|
||||
return;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
|
||||
case 0x91:
|
||||
if ( (adr == 0x0A002AAA) && (val == 0x55) )
|
||||
{
|
||||
gbaFlash.state = 0x92;
|
||||
return;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
break;
|
||||
|
||||
case 0x92:
|
||||
gbaFlash.state = 0;
|
||||
gbaFlash.cmd = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (gbaFlash.cmd == 0xA0) // write
|
||||
{
|
||||
writeSRAM((adr & 0x1FFFF) + (0x10000 * gbaFlash.bank), &val, 1);
|
||||
gbaFlash.state = 0;
|
||||
gbaFlash.cmd = 0;
|
||||
return;
|
||||
}
|
||||
INFO("GBAgame: Flash: write unknown atn 0x%08X = 0x%02X\n", adr, val);
|
||||
}
|
||||
|
||||
u8 gbaReadFlash(u32 adr)
|
||||
{
|
||||
if (!fSRAM) return 0xFF;
|
||||
if (gbaFlash.cmd == 0)
|
||||
return readSRAM((adr & 0x1FFFF) + (0x10000 * gbaFlash.bank), 1);
|
||||
|
||||
//INFO("GBAgame: flash read at 0x%08X\n", adr);
|
||||
|
||||
switch (gbaFlash.cmd)
|
||||
{
|
||||
case 0x90: // Chip Identification
|
||||
if (adr == 0x0A000000) return gbaFlash.idManufacturer;
|
||||
if (adr == 0x0A000001) return gbaFlash.idDevice;
|
||||
break;
|
||||
|
||||
case 0xF0: //
|
||||
gbaFlash.state = 0;
|
||||
gbaFlash.cmd = 0;
|
||||
break;
|
||||
|
||||
case 0xB0: // Bank switching
|
||||
break;
|
||||
|
||||
default:
|
||||
INFO("GBAgame: Flash: read - unknown command at 0x%08X = 0x%02X\n", adr, gbaFlash.cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
delete fROM; fROM = NULL;
|
||||
delete fSRAM; fSRAM = NULL;
|
||||
romSize = 0;
|
||||
sramSize = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
Slot2_GbaCart()
|
||||
: fROM(NULL)
|
||||
, fSRAM(NULL)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("GBA Cartridge", "GBA cartridge in slot", 0x03);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
Close();
|
||||
romSize = 0;
|
||||
sramSize = 0;
|
||||
|
||||
if (gameInfo.romsize == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (GBACartridge_RomPath.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcasecmp(GBACartridge_RomPath.c_str(), "self"))
|
||||
{
|
||||
GBACartridge_RomPath = path.path;
|
||||
GBACartridge_SRAMPath = Path::GetFileNameWithoutExt(GBACartridge_RomPath) + "." + GBA_SRAM_FILE_EXT;
|
||||
}
|
||||
|
||||
printf("GBASlot opening ROM: %s\n", GBACartridge_RomPath.c_str());
|
||||
EMUFILE_FILE *inf = new EMUFILE_FILE(GBACartridge_RomPath, "rb");
|
||||
fROM = inf;
|
||||
if (fROM->fail())
|
||||
{
|
||||
printf(" - Failed\n");
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
inf->EnablePositionCache();
|
||||
|
||||
romSize = fROM->size();
|
||||
printf(" - Success (%u bytes)\n", romSize);
|
||||
|
||||
// Load the GBA cartridge SRAM.
|
||||
inf = new EMUFILE_FILE(GBACartridge_SRAMPath, "rb+");
|
||||
fSRAM = inf;
|
||||
if(fSRAM->fail())
|
||||
{
|
||||
delete fSRAM;
|
||||
fSRAM = NULL;
|
||||
printf("GBASlot did not load associated SRAM.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
inf->EnablePositionCache();
|
||||
sramSize = fSRAM->size();
|
||||
printf("Scanning GBA rom to ID save type\n");
|
||||
saveType = scanSaveTypeGBA();
|
||||
printf("\nGBASlot found SRAM (%s - %u bytes) at:\n%s\n", (saveType == 0xFF)?"Unknown":saveTypes[saveType], sramSize, GBACartridge_SRAMPath.c_str());
|
||||
gbaFlash.size = sramSize;
|
||||
if (gbaFlash.size <= (64 * 1024))
|
||||
{
|
||||
gbaFlash.idDevice = 0x1B;
|
||||
gbaFlash.idManufacturer = 0x32;
|
||||
}
|
||||
else
|
||||
{
|
||||
gbaFlash.idDevice = 0x09;
|
||||
gbaFlash.idManufacturer = 0xC2;
|
||||
}
|
||||
gbaFlash.state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void disconnect()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val)
|
||||
{
|
||||
if ((addr >= 0x0A000000) && (addr < 0x0A010000))
|
||||
{
|
||||
switch (saveType)
|
||||
{
|
||||
case 3: // Flash
|
||||
case 5:
|
||||
gbaWriteFlash(addr, val);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
if (addr < 0x0A000000)
|
||||
return (u8)readRom(addr - 0x08000000, 1);
|
||||
|
||||
if (addr < 0x0A010000)
|
||||
{
|
||||
if ((saveType == 3) || (saveType == 5))
|
||||
return gbaReadFlash(addr);
|
||||
|
||||
return (u8)readSRAM(addr - 0x0A000000, 1);
|
||||
}
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
if (addr < 0x0A000000)
|
||||
return (u16)readRom(addr - 0x08000000, 2);
|
||||
|
||||
if (addr < 0x0A010000)
|
||||
return (u16)readSRAM(addr - 0x0A000000, 2);
|
||||
|
||||
return 0xFFFF;
|
||||
}
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
if (addr < 0x0A000000)
|
||||
return (u32)readRom(addr - 0x08000000, 4);
|
||||
|
||||
if (addr < 0x0A010000)
|
||||
return (u32)readSRAM(addr - 0x0A000000, 4);
|
||||
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_GbaCart() { return new Slot2_GbaCart(); }
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 CrazyMax
|
||||
Copyright (C) 2009-2013 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot2.h"
|
||||
static u8 guitarKeyStatus;
|
||||
|
||||
class Slot2_GuitarGrip : public ISlot2Interface
|
||||
{
|
||||
private:
|
||||
|
||||
public:
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("Guitar Grip", "Guitar Grip for Guitar Hero games", 0x04);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
guitarKeyStatus = 0xFF;
|
||||
}
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
if (addr == 0x0A000000)
|
||||
return guitarKeyStatus;
|
||||
|
||||
return (addr & 1) ? 0xF9 : 0xFF;
|
||||
}
|
||||
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr) { return 0xF9FF; }
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xF9FFF9FF; }
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_GuitarGrip() { return new Slot2_GuitarGrip(); }
|
||||
|
||||
void guitarGrip_setKey(bool green, bool red, bool yellow, bool blue)
|
||||
{
|
||||
const u8 g = (green) ? (1 << 6) : 0;
|
||||
const u8 r = (red) ? (1 << 5) : 0;
|
||||
const u8 y = (yellow) ? (1 << 4) : 0;
|
||||
const u8 b = (blue) ? (1 << 3) : 0;
|
||||
|
||||
guitarKeyStatus = ~(g | r | y | b);
|
||||
}
|
||||
|
||||
void guitarGrip_setKey(u8 theKeys)
|
||||
{
|
||||
guitarKeyStatus = theKeys;
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
//HCV-1000 emulation code adapted from GBE+: https://github.com/shonumi/gbe-plus
|
||||
|
||||
/*
|
||||
Modifications Copyright (C) 2023 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../slot2.h"
|
||||
|
||||
u8 hcv1000_cnt;
|
||||
char hcv1000_data[16];
|
||||
|
||||
class Slot2_HCV1000 : public ISlot2Interface
|
||||
{
|
||||
public:
|
||||
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("Sega Card Reader", "Sega Card Reader(HCV-1000) add-on", 0x09);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual bool init()
|
||||
{
|
||||
hcv1000_cnt = 0;
|
||||
memset(hcv1000_data, 0x5F, 16);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val)
|
||||
{
|
||||
if (addr == 0xA000000) { hcv1000_cnt = (val & 0x83); }
|
||||
}
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
u8 slot_byte = 0xFF;
|
||||
//Reading these cart addresses is for detection
|
||||
if (addr < 0x8020000)
|
||||
{
|
||||
u8 data = 0xF0 | ((addr & 0x1F) >> 1);
|
||||
slot_byte = (addr & 0x1) ? 0xFD : data;
|
||||
}
|
||||
|
||||
//HCV_CNT
|
||||
else if (addr == 0xA000000) { slot_byte = hcv1000_cnt; }
|
||||
|
||||
//HCV_DATA
|
||||
else if ((addr >= 0xA000010) && (addr <= 0xA00001F))
|
||||
{
|
||||
slot_byte = (u8)hcv1000_data[addr & 0xF];
|
||||
}
|
||||
|
||||
return slot_byte;
|
||||
}
|
||||
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr) { return 0xFDFD; };
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xFDFDFDFD; };
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_HCV1000() { return new Slot2_HCV1000(); }
|
||||
|
||||
void HCV1000_setReady()
|
||||
{
|
||||
hcv1000_cnt &= ~0x80;
|
||||
}
|
||||
|
||||
void HCV1000_setBarcode(std::string barcode)
|
||||
{
|
||||
barcode.resize(16, '_');
|
||||
memcpy(hcv1000_data, barcode.c_str(), barcode.length());
|
||||
}
|
|
@ -1,301 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006 Mic
|
||||
Copyright (C) 2009-2017 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../slot2.h"
|
||||
#include "../debug.h"
|
||||
#include "../emufile.h"
|
||||
#include "../path.h"
|
||||
#include "../utils/vfat.h"
|
||||
|
||||
// Set up addresses for GBAMP
|
||||
#define CF_REG_DATA 0x9000000
|
||||
#define CF_REG_ERR 0x9020000
|
||||
#define CF_REG_SEC 0x9040000
|
||||
#define CF_REG_LBA1 0x9060000
|
||||
#define CF_REG_LBA2 0x9080000
|
||||
#define CF_REG_LBA3 0x90A0000
|
||||
#define CF_REG_LBA4 0x90C0000
|
||||
#define CF_REG_CMD 0x90E0000
|
||||
#define CF_REG_STS 0x98C0000
|
||||
|
||||
// CF Card commands
|
||||
#define CF_CMD_LBA 0xE0
|
||||
#define CF_CMD_READ 0x20
|
||||
#define CF_CMD_WRITE 0x30
|
||||
|
||||
static u16 cf_reg_sts,
|
||||
cf_reg_lba1,
|
||||
cf_reg_lba2,
|
||||
cf_reg_lba3,
|
||||
cf_reg_lba4,
|
||||
cf_reg_cmd;
|
||||
static off_t currLBA;
|
||||
|
||||
static const int lfnPos[13] = {1,3,5,7,9,14,16,18,20,22,24,28,30};
|
||||
|
||||
static u32 fileStartLBA,fileEndLBA;
|
||||
static std::string sFlashPath;
|
||||
static BOOL cflashDeviceEnabled = FALSE;
|
||||
|
||||
static EMUFILE* file = NULL;
|
||||
|
||||
// ===========================
|
||||
BOOL inited;
|
||||
|
||||
enum EListCallbackArg {
|
||||
EListCallbackArg_Item, EListCallbackArg_Pop
|
||||
};
|
||||
|
||||
static BOOL cflash_init()
|
||||
{
|
||||
if (inited) return FALSE;
|
||||
BOOL init_good = FALSE;
|
||||
|
||||
CFLASHLOG("CFlash_Mode: %d\n",CFlash_Mode);
|
||||
|
||||
if (CFlash_Mode == ADDON_CFLASH_MODE_RomPath)
|
||||
{
|
||||
sFlashPath = path.RomDirectory;
|
||||
INFO("Using CFlash directory of rom: %s\n", sFlashPath.c_str());
|
||||
}
|
||||
else if(CFlash_Mode == ADDON_CFLASH_MODE_Path)
|
||||
{
|
||||
sFlashPath = CFlash_Path;
|
||||
INFO("Using CFlash directory: %s\n", sFlashPath.c_str());
|
||||
}
|
||||
else if(CFlash_Mode == ADDON_CFLASH_MODE_File)
|
||||
{
|
||||
sFlashPath = CFlash_Path;
|
||||
INFO("Using CFlash disk image file %s\n", sFlashPath.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (sFlashPath == "") return FALSE;
|
||||
|
||||
if(CFlash_IsUsingPath())
|
||||
{
|
||||
cflashDeviceEnabled = FALSE;
|
||||
currLBA = 0;
|
||||
|
||||
fileStartLBA = fileEndLBA = 0xFFFFFFFF;
|
||||
VFAT vfat;
|
||||
bool ret = vfat.build(sFlashPath.c_str(),16); //allocate 16MB extra for writing. this is probably enough for anyone, but maybe it should be configurable.
|
||||
//we could always suggest to users to add a big file to their directory to overwrite (that would cause the image to get padded)
|
||||
|
||||
if(!ret)
|
||||
{
|
||||
CFLASHLOG("FAILED cflash_build_fat\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
file = vfat.detach();
|
||||
|
||||
cf_reg_sts = 0x58; // READY
|
||||
|
||||
cflashDeviceEnabled = TRUE;
|
||||
init_good = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
file = new EMUFILE_FILE(sFlashPath.c_str(),"rb+");
|
||||
if(file->fail())
|
||||
{
|
||||
INFO("Failed to open file %s\n", sFlashPath.c_str());
|
||||
delete file;
|
||||
file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// READY
|
||||
cf_reg_sts = 0x58;
|
||||
|
||||
currLBA = 0;
|
||||
cf_reg_lba1 = cf_reg_lba2 =
|
||||
cf_reg_lba3 = cf_reg_lba4 = 0;
|
||||
|
||||
inited = TRUE;
|
||||
return init_good;
|
||||
}
|
||||
|
||||
static unsigned int cflash_read(unsigned int address)
|
||||
{
|
||||
unsigned int ret_value = 0;
|
||||
size_t elems_read = 0;
|
||||
|
||||
switch (address)
|
||||
{
|
||||
case CF_REG_STS:
|
||||
ret_value = cf_reg_sts;
|
||||
break;
|
||||
|
||||
case CF_REG_DATA:
|
||||
if (cf_reg_cmd == CF_CMD_READ)
|
||||
{
|
||||
if(file)
|
||||
{
|
||||
u8 data[2] = {0,0};
|
||||
file->fseek(currLBA, SEEK_SET);
|
||||
elems_read += file->fread(data,2);
|
||||
ret_value = data[1] << 8 | data[0];
|
||||
}
|
||||
currLBA += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case CF_REG_CMD:
|
||||
break;
|
||||
|
||||
case CF_REG_LBA1:
|
||||
ret_value = cf_reg_lba1;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
static void cflash_write(unsigned int address,unsigned int data)
|
||||
{
|
||||
static u8 sector_data[512];
|
||||
static u32 sector_write_index = 0;
|
||||
|
||||
switch (address)
|
||||
{
|
||||
case CF_REG_STS:
|
||||
cf_reg_sts = data&0xFFFF;
|
||||
break;
|
||||
|
||||
case CF_REG_DATA:
|
||||
if (cf_reg_cmd == CF_CMD_WRITE)
|
||||
{
|
||||
{
|
||||
sector_data[sector_write_index] = (data >> 0) & 0xff;
|
||||
sector_data[sector_write_index + 1] = (data >> 8) & 0xff;
|
||||
|
||||
sector_write_index += 2;
|
||||
|
||||
if (sector_write_index == 512)
|
||||
{
|
||||
CFLASHLOG( "Write sector to %ld\n", currLBA);
|
||||
size_t written = 0;
|
||||
|
||||
if(file)
|
||||
if(currLBA + 512 < file->size())
|
||||
{
|
||||
file->fseek(currLBA,SEEK_SET);
|
||||
|
||||
while(written < 512)
|
||||
{
|
||||
size_t todo = 512-written;
|
||||
file->fwrite(§or_data[written], todo);
|
||||
size_t cur_write = todo;
|
||||
written += cur_write;
|
||||
if ( cur_write == (size_t)-1) break;
|
||||
}
|
||||
}
|
||||
|
||||
CFLASHLOG("Wrote %u bytes\n", written);
|
||||
|
||||
currLBA += 512;
|
||||
sector_write_index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CF_REG_CMD:
|
||||
cf_reg_cmd = data&0xFF;
|
||||
cf_reg_sts = 0x58; // READY
|
||||
break;
|
||||
|
||||
case CF_REG_LBA1:
|
||||
cf_reg_lba1 = data&0xFF;
|
||||
currLBA = (currLBA&0xFFFFFF00)| cf_reg_lba1;
|
||||
break;
|
||||
|
||||
case CF_REG_LBA2:
|
||||
cf_reg_lba2 = data&0xFF;
|
||||
currLBA = (currLBA&0xFFFF00FF)|(cf_reg_lba2<<8);
|
||||
break;
|
||||
|
||||
case CF_REG_LBA3:
|
||||
cf_reg_lba3 = data&0xFF;
|
||||
currLBA = (currLBA&0xFF00FFFF)|(cf_reg_lba3<<16);
|
||||
break;
|
||||
|
||||
case CF_REG_LBA4:
|
||||
cf_reg_lba4 = data&0xFF;
|
||||
|
||||
if ((cf_reg_lba4 & 0xf0) == CF_CMD_LBA)
|
||||
{
|
||||
currLBA = (currLBA&0x00FFFFFF)|((cf_reg_lba4&0x0F)<<24);
|
||||
currLBA *= 512;
|
||||
sector_write_index = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void cflash_close( void)
|
||||
{
|
||||
if (!inited) return;
|
||||
if(file) delete file;
|
||||
cflashDeviceEnabled = FALSE;
|
||||
file = NULL;
|
||||
inited = FALSE;
|
||||
}
|
||||
|
||||
class Slot2_CFlash : public ISlot2Interface
|
||||
{
|
||||
public:
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("MPCF Flash Card Device", "MPCF Flash Card Device", 0x01);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
cflash_close();
|
||||
cflash_init();
|
||||
}
|
||||
virtual void disconnect()
|
||||
{
|
||||
cflash_close();
|
||||
}
|
||||
|
||||
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val) { cflash_write(addr, val); }
|
||||
virtual void writeWord(u8 PROCNUM, u32 addr, u16 val) { cflash_write(addr, val); }
|
||||
virtual void writeLong(u8 PROCNUM, u32 addr, u32 val) { cflash_write(addr, val); }
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr) { return (cflash_read(addr)); }
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr) { return (cflash_read(addr)); }
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr) { return (cflash_read(addr)); }
|
||||
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_CFlash() { return new Slot2_CFlash(); }
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 CrazyMax
|
||||
Copyright (C) 2009-2013 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot2.h"
|
||||
|
||||
class Slot2_None : public ISlot2Interface
|
||||
{
|
||||
public:
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("None", "Slot2 no-device emulation", 0xFF);
|
||||
return &info;
|
||||
}
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_None() { return new Slot2_None(); }
|
|
@ -1,143 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2011-2015 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
this device seems to have a 12bit value (like 20.12 fixed point.. get it?) located at 0x0A000000
|
||||
clockwise = right = increases.
|
||||
it returns the correct little endian bytes through byte reads.
|
||||
through halfword reads, it returns the LSB twice
|
||||
through full word reads, it returns the LSB four times.
|
||||
after that everything is 0x00.
|
||||
if the slot2 timings are wrong, then this device will return glitchy or 0xFF output.
|
||||
so this emulation code will attempt to validate that.
|
||||
arkanoid was setting REG_EXMEMCNT = 0x082F
|
||||
|
||||
the rom returns 0xEFFF for all addresses and should be used to detect this device
|
||||
|
||||
writing any byte to SRAM or writing any halfword/word to rom results in a reset or some kind of recalibrate
|
||||
the resulting value may be 0x000,0x001, or 0xFFF. seems mostly random, though once it is reset, resetting again won't change it.
|
||||
you must wait until the paddle has been moved.
|
||||
|
||||
conclusion:
|
||||
The emulation in all the handling of erroneous cases is not perfect, and some other users of the paddle (do any other games use it?)
|
||||
maybe legally configure the paddle differently, which could be rejected here; in which case this code will need finetuning
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../slot2.h"
|
||||
#include "../NDSSystem.h"
|
||||
|
||||
class Slot2_Paddle : public ISlot2Interface
|
||||
{
|
||||
private:
|
||||
void calibrate() { nds.paddle = 0; }
|
||||
bool Validate(u32 procnum, bool rom)
|
||||
{
|
||||
if(rom)
|
||||
return ValidateSlot2Access(procnum, 0, 0, 0, -1);
|
||||
else
|
||||
return ValidateSlot2Access(procnum, 18, 0, 0, 1);
|
||||
}
|
||||
|
||||
public:
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("Paddle Controller", "Taito Paddle Controller", 0x07);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void writeByte(u8 PROCNUM, u32 addr, u8 val)
|
||||
{
|
||||
if (addr < 0x0A000000)
|
||||
calibrate();
|
||||
}
|
||||
virtual void writeWord(u8 PROCNUM, u32 addr, u16 val)
|
||||
{
|
||||
if (addr < 0x0A000000)
|
||||
calibrate();
|
||||
}
|
||||
virtual void writeLong(u8 PROCNUM, u32 addr, u32 val)
|
||||
{
|
||||
if (addr < 0x0A000000)
|
||||
calibrate();
|
||||
}
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
//printf("paddle: read 08 at 0x%08X\n", addr);
|
||||
if (!Validate(PROCNUM, (addr < 0x0A000000)))
|
||||
return 0xFF;
|
||||
|
||||
if (addr < 0x0A000000)
|
||||
return (addr & 1)?0xFF:0xEF;
|
||||
|
||||
if (addr == 0x0A000000)
|
||||
return (nds.paddle & 0xFF);
|
||||
|
||||
if (addr == 0x0A000001)
|
||||
return ((nds.paddle >> 8) & 0x0F);
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
//printf("paddle: read 16 at 0x%08X\n", addr);
|
||||
if (!Validate(PROCNUM, (addr < 0x0A000000)))
|
||||
return 0xFFFF;
|
||||
|
||||
if (addr < 0x0A000000)
|
||||
return 0xEFFF;
|
||||
|
||||
if (addr == 0x0A000000)
|
||||
{
|
||||
u8 val = (nds.paddle & 0xFF);
|
||||
return (val | (val << 8));
|
||||
}
|
||||
|
||||
return 0x0000;
|
||||
}
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
//printf("paddle: read 32 at 0x%08X\n", addr);
|
||||
if (!Validate(PROCNUM, (addr < 0x0A000000)))
|
||||
return 0xFFFFFFFF;
|
||||
|
||||
if (addr < 0x0A000000)
|
||||
return 0xEFFFEFFF;
|
||||
|
||||
if (addr == 0x0A000000)
|
||||
{
|
||||
u8 val = (nds.paddle & 0xFF);
|
||||
return (val | (val << 8) | (val << 16) | (val << 24));
|
||||
}
|
||||
|
||||
return 0x00000000;
|
||||
}
|
||||
};
|
||||
|
||||
u16 Paddle_GetValue()
|
||||
{
|
||||
return nds.paddle;
|
||||
}
|
||||
|
||||
void Paddle_SetValue(u16 theValue)
|
||||
{
|
||||
nds.paddle = theValue;
|
||||
}
|
||||
|
||||
ISlot2Interface* construct_Slot2_Paddle() { return new Slot2_Paddle(); }
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2013-2015 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot2.h"
|
||||
#include "../NDSSystem.h"
|
||||
|
||||
class Slot2_PassME : public ISlot2Interface
|
||||
{
|
||||
public:
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("PassME", "PassME in GBA slot", 0x08);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
u32 tmp_addr = (addr & 0x07FFFFFF);
|
||||
if (tmp_addr < gameInfo.romsize)
|
||||
return (u8)gameInfo.readROM(tmp_addr);
|
||||
|
||||
return (0xFF);
|
||||
}
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
u32 tmp_addr = (addr & 0x07FFFFFF);
|
||||
if (tmp_addr < gameInfo.romsize)
|
||||
return (u16)gameInfo.readROM(tmp_addr);
|
||||
|
||||
return (0xFFFF);
|
||||
}
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
u32 tmp_addr = (addr & 0x07FFFFFF);
|
||||
if (tmp_addr < gameInfo.romsize)
|
||||
return (u32)gameInfo.readROM(tmp_addr);
|
||||
|
||||
return (0xFFFFFFFF);
|
||||
}
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_PassME() { return new Slot2_PassME(); }
|
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2010-2013 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot2.h"
|
||||
|
||||
static u16 pianoKeyStatus = 0;
|
||||
|
||||
class Slot2_EasyPiano : public ISlot2Interface
|
||||
{
|
||||
public:
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("Piano", "Piano for EasyPiano", 0x06);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
pianoKeyStatus = 0xE7FF;
|
||||
}
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
//printf("piano: read 08 at 0x%08X\n", adr);
|
||||
|
||||
//the actual keyboard output
|
||||
|
||||
//byte:bit
|
||||
//0x09FFFFFE:0 = C
|
||||
//0x09FFFFFE:1 = C#
|
||||
//0x09FFFFFE:2 = D
|
||||
//0x09FFFFFE:3 = D#
|
||||
//0x09FFFFFE:4 = E
|
||||
//0x09FFFFFE:5 = F
|
||||
//0x09FFFFFE:6 = F#
|
||||
//0x09FFFFFE:7 = G
|
||||
//0x09FFFFFF:0 = G#
|
||||
//0x09FFFFFF:1 = A
|
||||
//0x09FFFFFF:2 = A#
|
||||
//0x09FFFFFF:3 = ?
|
||||
//0x09FFFFFF:4 = ?
|
||||
//0x09FFFFFF:5 = B
|
||||
//0x09FFFFFF:6 = hiC
|
||||
//0x09FFFFFF:7 = ?
|
||||
|
||||
//deassert bit if key is pressed
|
||||
|
||||
//LOG("PIANO: %04X\n",pianoKeyStatus);
|
||||
|
||||
if (addr == 0x09FFFFFE) return ((pianoKeyStatus >> 0) & 0xFF);
|
||||
if (addr == 0x09FFFFFF) return ((pianoKeyStatus >> 8) & 0xFF) & ~(0x18);
|
||||
|
||||
return (addr & 1) ? 0xE7 : 0xFF;
|
||||
}
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr)
|
||||
{
|
||||
if (addr != 0x09FFFFFE)
|
||||
return 0xE7FF;
|
||||
|
||||
return readByte(PROCNUM, 0x09FFFFFE) | (readByte(PROCNUM,0x09FFFFFF) << 8);
|
||||
}
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xE7FFE7FF; }
|
||||
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_EasyPiano() { return new Slot2_EasyPiano(); }
|
||||
|
||||
void piano_setKey(bool c, bool cs, bool d, bool ds, bool e, bool f, bool fs, bool g, bool gs, bool a, bool as, bool b, bool hic)
|
||||
{
|
||||
//0x09FFFFFE:0 = C
|
||||
//0x09FFFFFE:1 = C#
|
||||
//0x09FFFFFE:2 = D
|
||||
//0x09FFFFFE:3 = D#
|
||||
//0x09FFFFFE:4 = E
|
||||
//0x09FFFFFE:5 = F
|
||||
//0x09FFFFFE:6 = F#
|
||||
//0x09FFFFFE:7 = G
|
||||
//0x09FFFFFE:0 = G#
|
||||
//0x09FFFFFE:1 = A
|
||||
//0x09FFFFFF:2 = A#
|
||||
//0x09FFFFFF:3 = ?
|
||||
//0x09FFFFFF:4 = ?
|
||||
//0x09FFFFFF:5 = B
|
||||
//0x09FFFFFF:6 = hiC
|
||||
//0x09FFFFFF:7 = ?
|
||||
|
||||
#define BIT_P(N,v) ((v)?(1<<(N)):0)
|
||||
pianoKeyStatus = ~(
|
||||
BIT_P(0,c) |
|
||||
BIT_P(1,cs) |
|
||||
BIT_P(2,d) |
|
||||
BIT_P(3,ds) |
|
||||
BIT_P(4,e) |
|
||||
BIT_P(5,f) |
|
||||
BIT_P(6,fs) |
|
||||
BIT_P(7,g) |
|
||||
BIT_P(8,gs) |
|
||||
BIT_P(9,a) |
|
||||
BIT_P(10,as) |
|
||||
BIT_P(13,b) |
|
||||
BIT_P(14,hic)
|
||||
);
|
||||
}
|
||||
|
||||
void piano_setKey(u16 theKeys)
|
||||
{
|
||||
pianoKeyStatus = theKeys;
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009 CrazyMax
|
||||
Copyright (C) 2009-2013 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../slot2.h"
|
||||
|
||||
void (*FeedbackON)(bool enable) = NULL;
|
||||
|
||||
class Slot2_RumblePak : public ISlot2Interface
|
||||
{
|
||||
private:
|
||||
u16 old_val_rumble;
|
||||
|
||||
public:
|
||||
virtual Slot2Info const* info()
|
||||
{
|
||||
static Slot2InfoSimple info("Rumble Pak", "NDS Rumble Pak (need joystick with Feedback)", 0x02);
|
||||
return &info;
|
||||
}
|
||||
|
||||
virtual void connect()
|
||||
{
|
||||
old_val_rumble = 0;
|
||||
if (!FeedbackON) return;
|
||||
FeedbackON(false);
|
||||
}
|
||||
|
||||
virtual void disconnect()
|
||||
{
|
||||
FeedbackON(false);
|
||||
}
|
||||
|
||||
virtual void writeWord(u8 PROCNUM, u32 addr, u16 val)
|
||||
{
|
||||
if (!FeedbackON) return;
|
||||
if (old_val_rumble == val) return;
|
||||
|
||||
old_val_rumble = val;
|
||||
if ((addr == 0x08000000) || (addr == 0x08001000))
|
||||
FeedbackON(val);
|
||||
}
|
||||
|
||||
virtual u8 readByte(u8 PROCNUM, u32 addr) { return (addr & 1)?0xFF:0xFD; };
|
||||
virtual u16 readWord(u8 PROCNUM, u32 addr) { return 0xFFFD; };
|
||||
virtual u32 readLong(u8 PROCNUM, u32 addr) { return 0xFFFDFFFD; };
|
||||
};
|
||||
|
||||
ISlot2Interface* construct_Slot2_RumblePak() { return new Slot2_RumblePak(); }
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,82 +0,0 @@
|
|||
/* Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2011 Loren Merritt
|
||||
Copyright (C) 2012-2013 DeSmuME team
|
||||
|
||||
This file 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ARM_JIT
|
||||
#define ARM_JIT
|
||||
|
||||
#include "types.h"
|
||||
#ifndef _MSC_VER
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
typedef u32 (FASTCALL* ArmOpCompiled)();
|
||||
|
||||
void arm_jit_reset(bool enable, bool suppress_msg = false);
|
||||
void arm_jit_close();
|
||||
void arm_jit_sync();
|
||||
template<int PROCNUM> u32 arm_jit_compile();
|
||||
|
||||
//#define MAPPED_JIT_FUNCS: to define or not to define?
|
||||
//* x86 windows seems faster with NON-DEFINED
|
||||
//* x64 windows seems faster with DEFINED
|
||||
//* x86 windows seems to have problems without DEFINED when desmume is built as a dll due to the
|
||||
// ~300 MB .bss section created by the 256MB non-mapped compiled_funcs table
|
||||
// (when loaded as a dll into a busy process, that much contiguous address space is hard to find. No big deal when starting up a process)
|
||||
//In principle, mapped compiled_funcs should be faster because it avoids some bit shifting logic to look it up from the memory map, right,
|
||||
//but I guess it doesn't always work out that way.
|
||||
//
|
||||
//So here's my proposed policy. NON-DEFINED is dangerous due to the huge .bss section, so it should be the default
|
||||
//The build system should #define JIT_FUNCS_FLAT to make the flat array
|
||||
#ifndef JIT_FUNCS_FLAT
|
||||
#define MAPPED_JIT_FUNCS
|
||||
#endif
|
||||
|
||||
#ifdef MAPPED_JIT_FUNCS
|
||||
struct JIT_struct
|
||||
{
|
||||
// only include the memory types that code can execute from
|
||||
uintptr_t MAIN_MEM[16*1024*1024/2];
|
||||
uintptr_t SWIRAM[0x8000/2];
|
||||
uintptr_t ARM9_ITCM[0x8000/2];
|
||||
uintptr_t ARM9_LCDC[0xA4000/2];
|
||||
uintptr_t ARM9_BIOS[0x8000/2];
|
||||
uintptr_t ARM7_BIOS[0x4000/2];
|
||||
uintptr_t ARM7_ERAM[0x10000/2];
|
||||
uintptr_t ARM7_WIRAM[0x10000/2];
|
||||
uintptr_t ARM7_WRAM[0x40000/2];
|
||||
|
||||
static uintptr_t *JIT_MEM[2][0x4000];
|
||||
};
|
||||
extern CACHE_ALIGN JIT_struct JIT;
|
||||
#define JIT_COMPILED_FUNC(adr, PROCNUM) JIT.JIT_MEM[PROCNUM][((adr)&0x0FFFC000)>>14][((adr)&0x00003FFE)>>1]
|
||||
#define JIT_COMPILED_FUNC_PREMASKED(adr, PROCNUM, ofs) JIT.JIT_MEM[PROCNUM][(adr)>>14][(((adr)&0x00003FFE)>>1)+ofs]
|
||||
#define JIT_COMPILED_FUNC_KNOWNBANK(adr, bank, mask, ofs) JIT.bank[(((adr)&(mask))>>1)+ofs]
|
||||
#define JIT_MAPPED(adr, PROCNUM) JIT.JIT_MEM[PROCNUM][(adr)>>14]
|
||||
#else
|
||||
// actually an array of function pointers, but they fit in 32bit address space, so might as well save memory
|
||||
extern uintptr_t compiled_funcs[];
|
||||
// there isn't anything mapped between 07000000 and 0EFFFFFF, so we can mask off bit 27 and get away with a smaller array
|
||||
#define JIT_COMPILED_FUNC(adr, PROCNUM) compiled_funcs[((adr) & 0x07FFFFFE) >> 1]
|
||||
#define JIT_COMPILED_FUNC_PREMASKED(adr, PROCNUM, ofs) JIT_COMPILED_FUNC(adr+(ofs<<1), PROCNUM)
|
||||
#define JIT_COMPILED_FUNC_KNOWNBANK(adr, bank, mask, ofs) JIT_COMPILED_FUNC(adr+(ofs<<1), PROCNUM)
|
||||
#define JIT_MAPPED(adr, PROCNUM) true
|
||||
#endif
|
||||
|
||||
extern u32 saveBlockSizeJIT;
|
||||
|
||||
#endif
|
|
@ -1,776 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2009-2021 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "armcpu.h"
|
||||
#include "instructions.h"
|
||||
#include "cp15.h"
|
||||
#include "bios.h"
|
||||
#include "debug.h"
|
||||
#include "NDSSystem.h"
|
||||
#include "MMU_timing.h"
|
||||
#include "utils/bits.h"
|
||||
#ifdef HAVE_LUA
|
||||
#include "lua-engine.h"
|
||||
#endif
|
||||
#ifdef TARGET_INTERFACE
|
||||
#include "frontend/interface/interface.h"
|
||||
#endif
|
||||
#ifdef HAVE_JIT
|
||||
#include "arm_jit.h"
|
||||
#endif
|
||||
|
||||
template<u32> static u32 armcpu_prefetch();
|
||||
|
||||
FORCEINLINE u32 armcpu_prefetch(armcpu_t *armcpu) {
|
||||
if(armcpu->proc_ID==0) return armcpu_prefetch<0>();
|
||||
else return armcpu_prefetch<1>();
|
||||
}
|
||||
|
||||
armcpu_t NDS_ARM7;
|
||||
armcpu_t NDS_ARM9;
|
||||
|
||||
#define SWAP(a, b, c) do \
|
||||
{ \
|
||||
c=a; \
|
||||
a=b; \
|
||||
b=c; \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#define STALLED_CYCLE_COUNT 10
|
||||
|
||||
static void
|
||||
stall_cpu( void *instance) {
|
||||
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||
printf("STALL\n");
|
||||
armcpu->stalled = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
unstall_cpu( void *instance) {
|
||||
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||
printf("UNSTALL\n");
|
||||
armcpu->stalled = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
install_post_exec_fn( void *instance,
|
||||
void (*ex_fn)( void *, u32 adr, int thumb),
|
||||
void *fn_data) {
|
||||
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||
|
||||
armcpu->post_ex_fn = ex_fn;
|
||||
armcpu->post_ex_fn_data = fn_data;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_post_exec_fn( void *instance) {
|
||||
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||
|
||||
armcpu->post_ex_fn = NULL;
|
||||
}
|
||||
|
||||
static u32 read_cpu_reg( void *instance, u32 reg_num)
|
||||
{
|
||||
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||
|
||||
if ( reg_num <= 14) {
|
||||
return armcpu->R[reg_num];
|
||||
}
|
||||
else if ( reg_num == 15) {
|
||||
return armcpu->instruct_adr;
|
||||
}
|
||||
else if ( reg_num == 16) {
|
||||
//CPSR
|
||||
return armcpu->CPSR.val;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
set_cpu_reg( void *instance, u32 reg_num, u32 value) {
|
||||
armcpu_t *armcpu = (armcpu_t *)instance;
|
||||
|
||||
if ( reg_num <= 14) {
|
||||
armcpu->R[reg_num] = value;
|
||||
}
|
||||
else if ( reg_num == 15) {
|
||||
armcpu->next_instruction = value;
|
||||
}
|
||||
else if ( reg_num == 16) {
|
||||
/* FIXME: setting the CPSR */
|
||||
}
|
||||
}
|
||||
|
||||
int armcpu_new( armcpu_t *armcpu, u32 id)
|
||||
{
|
||||
armcpu->proc_ID = id;
|
||||
armcpu->stalled = 0;
|
||||
|
||||
armcpu->base_mem_if.prefetch32 = NULL;
|
||||
armcpu->base_mem_if.prefetch16 = NULL;
|
||||
armcpu->base_mem_if.read8 = NULL;
|
||||
armcpu->base_mem_if.read16 = NULL;
|
||||
armcpu->base_mem_if.read32 = NULL;
|
||||
armcpu->base_mem_if.write8 = NULL;
|
||||
armcpu->base_mem_if.write16 = NULL;
|
||||
armcpu->base_mem_if.write32 = NULL;
|
||||
armcpu->base_mem_if.data = NULL;
|
||||
|
||||
armcpu_SetControlInterface(armcpu, &arm_default_ctrl_iface);
|
||||
armcpu_SetControlInterfaceData(armcpu, armcpu);
|
||||
armcpu_SetCurrentMemoryInterface(armcpu, NULL);
|
||||
armcpu_SetCurrentMemoryInterfaceData(armcpu, NULL);
|
||||
|
||||
armcpu->post_ex_fn = NULL;
|
||||
armcpu->post_ex_fn_data = NULL;
|
||||
|
||||
armcpu->breakPoints = new std::vector<u32>;
|
||||
|
||||
armcpu_init(armcpu, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void armcpu_SetControlInterface(armcpu_t *armcpu, const armcpu_ctrl_iface *theControlInterface)
|
||||
{
|
||||
armcpu->ctrl_iface = *theControlInterface;
|
||||
}
|
||||
|
||||
armcpu_ctrl_iface* armcpu_GetControlInterface(armcpu_t *armcpu)
|
||||
{
|
||||
return &armcpu->ctrl_iface;
|
||||
}
|
||||
|
||||
void armcpu_SetControlInterfaceData(armcpu_t *armcpu, void *theData)
|
||||
{
|
||||
armcpu->ctrl_iface.data = theData;
|
||||
}
|
||||
|
||||
void* armcpu_GetControlInterfaceData(const armcpu_t *armcpu)
|
||||
{
|
||||
return armcpu->ctrl_iface.data;
|
||||
}
|
||||
|
||||
void armcpu_SetCurrentMemoryInterface(armcpu_t *armcpu, armcpu_memory_iface *theMemoryInterface)
|
||||
{
|
||||
armcpu->mem_if = theMemoryInterface;
|
||||
}
|
||||
|
||||
armcpu_memory_iface* armcpu_GetCurrentMemoryInterface(const armcpu_t *armcpu)
|
||||
{
|
||||
return armcpu->mem_if;
|
||||
}
|
||||
|
||||
void armcpu_SetCurrentMemoryInterfaceData(armcpu_t *armcpu, void *theData)
|
||||
{
|
||||
if (armcpu->mem_if != NULL)
|
||||
{
|
||||
armcpu->mem_if->data = theData;
|
||||
}
|
||||
}
|
||||
|
||||
void* armcpu_GetCurrentMemoryInterfaceData(const armcpu_t *armcpu)
|
||||
{
|
||||
return (armcpu->mem_if != NULL) ? armcpu->mem_if->data : NULL;
|
||||
}
|
||||
|
||||
void armcpu_SetBaseMemoryInterface(armcpu_t *armcpu, const armcpu_memory_iface *theMemInterface)
|
||||
{
|
||||
armcpu->base_mem_if = *theMemInterface;
|
||||
}
|
||||
|
||||
armcpu_memory_iface* armcpu_GetBaseMemoryInterface(armcpu_t *armcpu)
|
||||
{
|
||||
return &armcpu->base_mem_if;
|
||||
}
|
||||
|
||||
void armcpu_SetBaseMemoryInterfaceData(armcpu_t *armcpu, void *theData)
|
||||
{
|
||||
armcpu->base_mem_if.data = theData;
|
||||
}
|
||||
|
||||
void* armcpu_GetBaseMemoryInterfaceData(const armcpu_t *armcpu)
|
||||
{
|
||||
return armcpu->base_mem_if.data;
|
||||
}
|
||||
|
||||
void armcpu_ResetMemoryInterfaceToBase(armcpu_t *armcpu)
|
||||
{
|
||||
armcpu_SetCurrentMemoryInterface(armcpu, armcpu_GetBaseMemoryInterface(armcpu));
|
||||
armcpu_SetCurrentMemoryInterfaceData(armcpu, armcpu_GetBaseMemoryInterfaceData(armcpu));
|
||||
}
|
||||
|
||||
//call this whenever CPSR is changed (other than CNVZQ or T flags); interrupts may need to be unleashed
|
||||
void armcpu_changeCPSR()
|
||||
{
|
||||
//but all it does is give them a chance to unleash by forcing an immediate reschedule
|
||||
//TODO - we could actually set CPSR through here and look for a change in the I bit
|
||||
//that would be a little optimization as well as a safety measure if we prevented setting CPSR directly
|
||||
NDS_Reschedule();
|
||||
}
|
||||
|
||||
void armcpu_init(armcpu_t *armcpu, u32 adr)
|
||||
{
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
memcpy(&armcpu->cond_table[0], &arm_cond_table[0], sizeof(arm_cond_table));
|
||||
#endif
|
||||
|
||||
armcpu->LDTBit = (armcpu->proc_ID==0); //set ARMv5 style bit--different for each processor
|
||||
armcpu->intVector = 0xFFFF0000 * (armcpu->proc_ID==0);
|
||||
armcpu->freeze = CPU_FREEZE_NONE;
|
||||
armcpu->intrWaitARM_state = 0;
|
||||
|
||||
//#ifdef GDB_STUB
|
||||
// armcpu->irq_flag = 0;
|
||||
//#endif
|
||||
|
||||
for(int i = 0; i < 16; ++i)
|
||||
armcpu->R[i] = 0;
|
||||
|
||||
armcpu->CPSR.val = armcpu->SPSR.val = SYS;
|
||||
|
||||
armcpu->R13_usr = armcpu->R14_usr = 0;
|
||||
armcpu->R13_svc = armcpu->R14_svc = 0;
|
||||
armcpu->R13_abt = armcpu->R14_abt = 0;
|
||||
armcpu->R13_und = armcpu->R14_und = 0;
|
||||
armcpu->R13_irq = armcpu->R14_irq = 0;
|
||||
armcpu->R8_fiq = armcpu->R9_fiq = armcpu->R10_fiq = armcpu->R11_fiq = armcpu->R12_fiq = armcpu->R13_fiq = armcpu->R14_fiq = 0;
|
||||
|
||||
armcpu->SPSR_svc.val = armcpu->SPSR_abt.val = armcpu->SPSR_und.val = armcpu->SPSR_irq.val = armcpu->SPSR_fiq.val = 0;
|
||||
|
||||
//#ifdef GDB_STUB
|
||||
// armcpu->instruct_adr = adr;
|
||||
// armcpu->R[15] = adr + 8;
|
||||
//#else
|
||||
//armcpu->R[15] = adr;
|
||||
//#endif
|
||||
|
||||
//do something sensible when booting up to a thumb address
|
||||
armcpu->next_instruction = adr & ~1;
|
||||
armcpu->CPSR.bits.T = BIT0(adr);
|
||||
|
||||
//#ifndef GDB_STUB
|
||||
armcpu_prefetch(armcpu);
|
||||
//#endif
|
||||
}
|
||||
|
||||
u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode)
|
||||
{
|
||||
u32 oldmode = armcpu->CPSR.bits.mode;
|
||||
|
||||
switch(oldmode)
|
||||
{
|
||||
case USR :
|
||||
case SYS :
|
||||
armcpu->R13_usr = armcpu->R[13];
|
||||
armcpu->R14_usr = armcpu->R[14];
|
||||
break;
|
||||
|
||||
case FIQ :
|
||||
{
|
||||
u32 tmp;
|
||||
SWAP(armcpu->R[8], armcpu->R8_fiq, tmp);
|
||||
SWAP(armcpu->R[9], armcpu->R9_fiq, tmp);
|
||||
SWAP(armcpu->R[10], armcpu->R10_fiq, tmp);
|
||||
SWAP(armcpu->R[11], armcpu->R11_fiq, tmp);
|
||||
SWAP(armcpu->R[12], armcpu->R12_fiq, tmp);
|
||||
armcpu->R13_fiq = armcpu->R[13];
|
||||
armcpu->R14_fiq = armcpu->R[14];
|
||||
armcpu->SPSR_fiq = armcpu->SPSR;
|
||||
break;
|
||||
}
|
||||
case IRQ :
|
||||
armcpu->R13_irq = armcpu->R[13];
|
||||
armcpu->R14_irq = armcpu->R[14];
|
||||
armcpu->SPSR_irq = armcpu->SPSR;
|
||||
break;
|
||||
|
||||
case SVC :
|
||||
armcpu->R13_svc = armcpu->R[13];
|
||||
armcpu->R14_svc = armcpu->R[14];
|
||||
armcpu->SPSR_svc = armcpu->SPSR;
|
||||
break;
|
||||
|
||||
case ABT :
|
||||
armcpu->R13_abt = armcpu->R[13];
|
||||
armcpu->R14_abt = armcpu->R[14];
|
||||
armcpu->SPSR_abt = armcpu->SPSR;
|
||||
break;
|
||||
|
||||
case UND :
|
||||
armcpu->R13_und = armcpu->R[13];
|
||||
armcpu->R14_und = armcpu->R[14];
|
||||
armcpu->SPSR_und = armcpu->SPSR;
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case USR :
|
||||
case SYS :
|
||||
armcpu->R[13] = armcpu->R13_usr;
|
||||
armcpu->R[14] = armcpu->R14_usr;
|
||||
//SPSR = CPSR;
|
||||
break;
|
||||
|
||||
case FIQ :
|
||||
{
|
||||
u32 tmp;
|
||||
SWAP(armcpu->R[8], armcpu->R8_fiq, tmp);
|
||||
SWAP(armcpu->R[9], armcpu->R9_fiq, tmp);
|
||||
SWAP(armcpu->R[10], armcpu->R10_fiq, tmp);
|
||||
SWAP(armcpu->R[11], armcpu->R11_fiq, tmp);
|
||||
SWAP(armcpu->R[12], armcpu->R12_fiq, tmp);
|
||||
armcpu->R[13] = armcpu->R13_fiq;
|
||||
armcpu->R[14] = armcpu->R14_fiq;
|
||||
armcpu->SPSR = armcpu->SPSR_fiq;
|
||||
break;
|
||||
}
|
||||
|
||||
case IRQ :
|
||||
armcpu->R[13] = armcpu->R13_irq;
|
||||
armcpu->R[14] = armcpu->R14_irq;
|
||||
armcpu->SPSR = armcpu->SPSR_irq;
|
||||
break;
|
||||
|
||||
case SVC :
|
||||
armcpu->R[13] = armcpu->R13_svc;
|
||||
armcpu->R[14] = armcpu->R14_svc;
|
||||
armcpu->SPSR = armcpu->SPSR_svc;
|
||||
break;
|
||||
|
||||
case ABT :
|
||||
armcpu->R[13] = armcpu->R13_abt;
|
||||
armcpu->R[14] = armcpu->R14_abt;
|
||||
armcpu->SPSR = armcpu->SPSR_abt;
|
||||
break;
|
||||
|
||||
case UND :
|
||||
armcpu->R[13] = armcpu->R13_und;
|
||||
armcpu->R[14] = armcpu->R14_und;
|
||||
armcpu->SPSR = armcpu->SPSR_und;
|
||||
break;
|
||||
|
||||
default :
|
||||
printf("switchMode: WRONG mode %02X\n",mode);
|
||||
break;
|
||||
}
|
||||
|
||||
armcpu->CPSR.bits.mode = mode & 0x1F;
|
||||
armcpu_changeCPSR();
|
||||
return oldmode;
|
||||
}
|
||||
|
||||
u32 armcpu_Wait4IRQ(armcpu_t *cpu)
|
||||
{
|
||||
cpu->freeze = (CPU_FREEZE_WAIT_IRQ | CPU_FREEZE_IE_IF);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<u32 PROCNUM>
|
||||
FORCEINLINE static u32 armcpu_prefetch()
|
||||
{
|
||||
armcpu_t* const armcpu = &ARMPROC;
|
||||
//#ifdef GDB_STUB
|
||||
// u32 temp_instruction;
|
||||
//#endif
|
||||
u32 curInstruction = armcpu->next_instruction;
|
||||
|
||||
if(armcpu->CPSR.bits.T == 0)
|
||||
{
|
||||
//#ifdef GDB_STUB
|
||||
// temp_instruction =
|
||||
// armcpu->mem_if->prefetch32( armcpu->mem_if->data,
|
||||
// armcpu->next_instruction);
|
||||
//
|
||||
// if ( !armcpu->stalled) {
|
||||
// armcpu->instruction = temp_instruction;
|
||||
// armcpu->instruct_adr = armcpu->next_instruction;
|
||||
// armcpu->next_instruction += 4;
|
||||
// armcpu->R[15] = armcpu->next_instruction + 4;
|
||||
// }
|
||||
//#else
|
||||
curInstruction &= 0xFFFFFFFC; //please don't change this to 0x0FFFFFFC -- the NDS will happily run on 0xF******* addresses all day long
|
||||
//please note that we must setup R[15] before reading the instruction since there is a protection
|
||||
//which prevents PC > 0x3FFF from reading the bios region
|
||||
armcpu->instruct_adr = curInstruction;
|
||||
armcpu->next_instruction = curInstruction + 4;
|
||||
armcpu->R[15] = curInstruction + 8;
|
||||
armcpu->instruction = _MMU_read32<PROCNUM, MMU_AT_CODE>(curInstruction);
|
||||
//#endif
|
||||
|
||||
return MMU_codeFetchCycles<PROCNUM,32>(curInstruction);
|
||||
}
|
||||
|
||||
//#ifdef GDB_STUB
|
||||
// temp_instruction =
|
||||
// armcpu->mem_if->prefetch16( armcpu->mem_if->data,
|
||||
// armcpu->next_instruction);
|
||||
//
|
||||
// if ( !armcpu->stalled) {
|
||||
// armcpu->instruction = temp_instruction;
|
||||
// armcpu->instruct_adr = armcpu->next_instruction;
|
||||
// armcpu->next_instruction = armcpu->next_instruction + 2;
|
||||
// armcpu->R[15] = armcpu->next_instruction + 2;
|
||||
// }
|
||||
//#else
|
||||
curInstruction &= 0xFFFFFFFE; //please don't change this to 0x0FFFFFFE -- the NDS will happily run on 0xF******* addresses all day long
|
||||
//please note that we must setup R[15] before reading the instruction since there is a protection
|
||||
//which prevents PC > 0x3FFF from reading the bios region
|
||||
armcpu->instruct_adr = curInstruction;
|
||||
armcpu->next_instruction = curInstruction + 2;
|
||||
armcpu->R[15] = curInstruction + 4;
|
||||
armcpu->instruction = _MMU_read16<PROCNUM, MMU_AT_CODE>(curInstruction);
|
||||
//#endif
|
||||
|
||||
if(PROCNUM==0)
|
||||
{
|
||||
// arm9 fetches 2 instructions at a time in thumb mode
|
||||
if(!(curInstruction == armcpu->instruct_adr + 2 && (curInstruction & 2)))
|
||||
return MMU_codeFetchCycles<PROCNUM,32>(curInstruction);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return MMU_codeFetchCycles<PROCNUM,16>(curInstruction);
|
||||
}
|
||||
|
||||
#if 0 /* not used */
|
||||
static BOOL FASTCALL test_EQ(Status_Reg CPSR) { return ( CPSR.bits.Z); }
|
||||
static BOOL FASTCALL test_NE(Status_Reg CPSR) { return (!CPSR.bits.Z); }
|
||||
static BOOL FASTCALL test_CS(Status_Reg CPSR) { return ( CPSR.bits.C); }
|
||||
static BOOL FASTCALL test_CC(Status_Reg CPSR) { return (!CPSR.bits.C); }
|
||||
static BOOL FASTCALL test_MI(Status_Reg CPSR) { return ( CPSR.bits.N); }
|
||||
static BOOL FASTCALL test_PL(Status_Reg CPSR) { return (!CPSR.bits.N); }
|
||||
static BOOL FASTCALL test_VS(Status_Reg CPSR) { return ( CPSR.bits.V); }
|
||||
static BOOL FASTCALL test_VC(Status_Reg CPSR) { return (!CPSR.bits.V); }
|
||||
static BOOL FASTCALL test_HI(Status_Reg CPSR) { return (CPSR.bits.C) && (!CPSR.bits.Z); }
|
||||
static BOOL FASTCALL test_LS(Status_Reg CPSR) { return (CPSR.bits.Z) || (!CPSR.bits.C); }
|
||||
static BOOL FASTCALL test_GE(Status_Reg CPSR) { return (CPSR.bits.N==CPSR.bits.V); }
|
||||
static BOOL FASTCALL test_LT(Status_Reg CPSR) { return (CPSR.bits.N!=CPSR.bits.V); }
|
||||
static BOOL FASTCALL test_GT(Status_Reg CPSR) { return (!CPSR.bits.Z) && (CPSR.bits.N==CPSR.bits.V); }
|
||||
static BOOL FASTCALL test_LE(Status_Reg CPSR) { return ( CPSR.bits.Z) || (CPSR.bits.N!=CPSR.bits.V); }
|
||||
static BOOL FASTCALL test_AL(Status_Reg CPSR) { return 1; }
|
||||
|
||||
static BOOL (FASTCALL* test_conditions[])(Status_Reg CPSR)= {
|
||||
test_EQ , test_NE ,
|
||||
test_CS , test_CC ,
|
||||
test_MI , test_PL ,
|
||||
test_VS , test_VC ,
|
||||
test_HI , test_LS ,
|
||||
test_GE , test_LT ,
|
||||
test_GT , test_LE ,
|
||||
test_AL
|
||||
};
|
||||
#define TEST_COND2(cond, CPSR) \
|
||||
(cond<15&&test_conditions[cond](CPSR))
|
||||
#endif
|
||||
|
||||
//TODO - merge with armcpu_irqException?
|
||||
//http://www.ethernut.de/en/documents/arm-exceptions.html
|
||||
//http://docs.google.com/viewer?a=v&q=cache:V4ht1YkxprMJ:www.cs.nctu.edu.tw/~wjtsai/EmbeddedSystemDesign/Ch3-1.pdf+arm+exception+handling&hl=en&gl=us&pid=bl&srcid=ADGEEShx9VTHbUhWdDOrTVRzLkcCsVfJiijncNDkkgkrlJkLa7D0LCpO8fQ_hhU3DTcgZh9rcZWWQq4TYhhCovJ625h41M0ZUX3WGasyzWQFxYzDCB-VS6bsUmpoJnRxAc-bdkD0qmsu&sig=AHIEtbR9VHvDOCRmZFQDUVwy53iJDjoSPQ
|
||||
void armcpu_exception(armcpu_t *cpu, u32 number)
|
||||
{
|
||||
Mode cpumode = USR;
|
||||
switch(number)
|
||||
{
|
||||
case EXCEPTION_RESET: cpumode = SVC; break;
|
||||
case EXCEPTION_UNDEFINED_INSTRUCTION: cpumode = UND; break;
|
||||
case EXCEPTION_SWI: cpumode = SVC; break;
|
||||
case EXCEPTION_PREFETCH_ABORT: cpumode = ABT; break;
|
||||
case EXCEPTION_DATA_ABORT: cpumode = ABT; break;
|
||||
case EXCEPTION_RESERVED_0x14: emu_halt(EMUHALT_REASON_ARM_RESERVED_0X14_EXCEPTION, (cpu->proc_ID == ARMCPU_ARM9) ? NDSErrorTag_ARM9 : NDSErrorTag_ARM7); break;
|
||||
case EXCEPTION_IRQ: cpumode = IRQ; break;
|
||||
case EXCEPTION_FAST_IRQ: cpumode = FIQ; break;
|
||||
}
|
||||
|
||||
Status_Reg tmp = cpu->CPSR;
|
||||
armcpu_switchMode(cpu, cpumode); //enter new mode
|
||||
cpu->R[14] = cpu->next_instruction;
|
||||
cpu->SPSR = tmp; //save old CPSR as new SPSR
|
||||
cpu->CPSR.bits.T = 0; //handle as ARM32 code
|
||||
cpu->CPSR.bits.I = 1;
|
||||
armcpu_changeCPSR();
|
||||
cpu->R[15] = cpu->intVector + number;
|
||||
cpu->next_instruction = cpu->R[15];
|
||||
printf("armcpu_exception!\n");
|
||||
//extern bool dolog;
|
||||
//dolog=true;
|
||||
|
||||
//HOW DOES THIS WORTK WITHOUT A PREFETCH, LIKE IRQ BELOW?
|
||||
//I REALLY WISH WE DIDNT PREFETCH BEFORE EXECUTING
|
||||
}
|
||||
|
||||
BOOL armcpu_irqException(armcpu_t *armcpu)
|
||||
{
|
||||
Status_Reg tmp;
|
||||
|
||||
//TODO - remove GDB specific code
|
||||
//#ifdef GDB_STUB
|
||||
// armcpu->irq_flag = 0;
|
||||
//#endif
|
||||
|
||||
tmp = armcpu->CPSR;
|
||||
armcpu_switchMode(armcpu, IRQ);
|
||||
|
||||
//TODO - remove GDB specific code
|
||||
//#ifdef GDB_STUB
|
||||
// armcpu->R[14] = armcpu->next_instruction + 4;
|
||||
//#else
|
||||
armcpu->R[14] = armcpu->instruct_adr + 4;
|
||||
//#endif
|
||||
armcpu->SPSR = tmp;
|
||||
armcpu->CPSR.bits.T = 0;
|
||||
armcpu->CPSR.bits.I = 1;
|
||||
armcpu->next_instruction = armcpu->intVector + 0x18;
|
||||
armcpu->freeze &= ~CPU_FREEZE_IRQ_IE_IF;
|
||||
|
||||
//must retain invariant of having next instruction to be executed prefetched
|
||||
//(yucky)
|
||||
armcpu_prefetch(armcpu);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//TODO - remove GDB specific code
|
||||
//BOOL
|
||||
//armcpu_flagIrq( armcpu_t *armcpu) {
|
||||
// if(armcpu->CPSR.bits.I) return FALSE;
|
||||
//
|
||||
// armcpu->waitIRQ = 0;
|
||||
//
|
||||
//#ifdef GDB_STUB
|
||||
// armcpu->irq_flag = 1;
|
||||
//#endif
|
||||
//
|
||||
// return TRUE;
|
||||
//}
|
||||
|
||||
u32 TRAPUNDEF(armcpu_t* cpu)
|
||||
{
|
||||
INFO("ARM%c: Undefined instruction: 0x%08X PC=0x%08X\n", cpu->proc_ID?'7':'9', cpu->instruction, cpu->instruct_adr);
|
||||
|
||||
if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9)))
|
||||
{
|
||||
armcpu_exception(&NDS_ARM9,EXCEPTION_UNDEFINED_INSTRUCTION);
|
||||
return 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
emu_halt(EMUHALT_REASON_ARM_UNDEFINED_INSTRUCTION_EXCEPTION, (cpu->proc_ID == ARMCPU_ARM9) ? NDSErrorTag_ARM9 : NDSErrorTag_ARM7);
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
//BOOL
|
||||
//armcpu_flagIrq( armcpu_t *armcpu) {
|
||||
// if(armcpu->CPSR.bits.I) return FALSE;
|
||||
//
|
||||
// armcpu->waitIRQ = 0;
|
||||
//
|
||||
//#ifdef GDB_STUB
|
||||
// armcpu->irq_flag = 1;
|
||||
//#endif
|
||||
//
|
||||
// return TRUE;
|
||||
//}
|
||||
|
||||
template<int PROCNUM>
|
||||
u32 armcpu_exec()
|
||||
{
|
||||
// Usually, fetching and executing are processed parallelly.
|
||||
// So this function stores the cycles of each process to
|
||||
// the variables below, and returns appropriate cycle count.
|
||||
u32 cFetch = 0;
|
||||
u32 cExecute = 0;
|
||||
|
||||
//this assert is annoying. but sometimes it is handy.
|
||||
//assert(ARMPROC.instruct_adr!=0x00000000);
|
||||
//#ifdef DEVELOPER
|
||||
#if 0
|
||||
if ((((ARMPROC.instruct_adr & 0x0F000000) == 0x0F000000) && (PROCNUM == 0)) ||
|
||||
(((ARMPROC.instruct_adr & 0x0F000000) == 0x00000000) && (PROCNUM == 1)))
|
||||
{
|
||||
switch (ARMPROC.instruct_adr & 0xFFFF)
|
||||
{
|
||||
case 0x00000000:
|
||||
printf("BIOS%c: Reset!!!\n", PROCNUM?'7':'9');
|
||||
emu_halt();
|
||||
break;
|
||||
case 0x00000004:
|
||||
printf("BIOS%c: Undefined instruction\n", PROCNUM?'7':'9');
|
||||
//emu_halt();
|
||||
break;
|
||||
case 0x00000008:
|
||||
//printf("BIOS%c: SWI\n", PROCNUM?'7':'9');
|
||||
break;
|
||||
case 0x0000000C:
|
||||
printf("BIOS%c: Prefetch Abort!!!\n", PROCNUM?'7':'9');
|
||||
//emu_halt();
|
||||
break;
|
||||
case 0x00000010:
|
||||
//printf("BIOS%c: Data Abort!!!\n", PROCNUM?'7':'9');
|
||||
//emu_halt();
|
||||
break;
|
||||
case 0x00000014:
|
||||
printf("BIOS%c: Reserved!!!\n", PROCNUM?'7':'9');
|
||||
break;
|
||||
case 0x00000018:
|
||||
//printf("BIOS%c: IRQ\n", PROCNUM?'7':'9');
|
||||
break;
|
||||
case 0x0000001C:
|
||||
printf("BIOS%c: Fast IRQ\n", PROCNUM?'7':'9');
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 //#ifdef GDB_STUB
|
||||
if (ARMPROC.stalled) {
|
||||
return STALLED_CYCLE_COUNT;
|
||||
}
|
||||
|
||||
/* check for interrupts */
|
||||
if (ARMPROC.irq_flag) {
|
||||
armcpu_irqException(&ARMPROC);
|
||||
}
|
||||
|
||||
cFetch = armcpu_prefetch(&ARMPROC);
|
||||
|
||||
if (ARMPROC.stalled) {
|
||||
return MMU_fetchExecuteCycles<PROCNUM>(cExecute, cFetch);
|
||||
}
|
||||
#endif
|
||||
|
||||
//cFetch = armcpu_prefetch(&ARMPROC);
|
||||
|
||||
//printf("%d: %08X\n",PROCNUM,ARMPROC.instruct_adr);
|
||||
|
||||
if(ARMPROC.CPSR.bits.T == 0)
|
||||
{
|
||||
if(
|
||||
CONDITION(ARMPROC.instruction) == 0x0E //fast path for unconditional instructions
|
||||
|| (TEST_COND(CONDITION(ARMPROC.instruction), CODE(ARMPROC.instruction), ARMPROC.CPSR)) //handles any condition
|
||||
)
|
||||
{
|
||||
#ifdef HAVE_LUA
|
||||
CallRegisteredLuaMemHook(ARMPROC.instruct_adr, 4, ARMPROC.instruction, LUAMEMHOOK_EXEC); // should report even if condition=false?
|
||||
#endif
|
||||
#ifdef TARGET_INTERFACE
|
||||
call_registered_interface_mem_hook(ARMPROC.instruct_adr, 4, HOOK_EXEC);
|
||||
#endif
|
||||
#ifdef DEVELOPER
|
||||
DEBUG_statistics.instructionHits[PROCNUM].arm[INSTRUCTION_INDEX(ARMPROC.instruction)]++;
|
||||
#endif
|
||||
cExecute = arm_instructions_set[PROCNUM][INSTRUCTION_INDEX(ARMPROC.instruction)](ARMPROC.instruction);
|
||||
}
|
||||
else
|
||||
cExecute = 1; // If condition=false: 1S cycle
|
||||
#ifdef GDB_STUB
|
||||
if ( ARMPROC.post_ex_fn != NULL) {
|
||||
/* call the external post execute function */
|
||||
ARMPROC.post_ex_fn(ARMPROC.post_ex_fn_data, ARMPROC.instruct_adr, 0);
|
||||
}
|
||||
ARMPROC.mem_if->prefetch32( ARMPROC.mem_if->data, ARMPROC.next_instruction);
|
||||
#endif
|
||||
cFetch = armcpu_prefetch<PROCNUM>();
|
||||
return MMU_fetchExecuteCycles<PROCNUM>(cExecute, cFetch);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LUA
|
||||
CallRegisteredLuaMemHook(ARMPROC.instruct_adr, 2, ARMPROC.instruction, LUAMEMHOOK_EXEC);
|
||||
#endif
|
||||
#ifdef TARGET_INTERFACE
|
||||
call_registered_interface_mem_hook(ARMPROC.instruct_adr, 2, HOOK_EXEC);
|
||||
#endif
|
||||
#ifdef DEVELOPER
|
||||
DEBUG_statistics.instructionHits[PROCNUM].thumb[ARMPROC.instruction>>6]++;
|
||||
#endif
|
||||
cExecute = thumb_instructions_set[PROCNUM][ARMPROC.instruction>>6](ARMPROC.instruction);
|
||||
|
||||
#ifdef GDB_STUB
|
||||
if ( ARMPROC.post_ex_fn != NULL) {
|
||||
/* call the external post execute function */
|
||||
ARMPROC.post_ex_fn( ARMPROC.post_ex_fn_data, ARMPROC.instruct_adr, 1);
|
||||
}
|
||||
ARMPROC.mem_if->prefetch32( ARMPROC.mem_if->data, ARMPROC.next_instruction);
|
||||
#endif
|
||||
cFetch = armcpu_prefetch<PROCNUM>();
|
||||
return MMU_fetchExecuteCycles<PROCNUM>(cExecute, cFetch);
|
||||
}
|
||||
|
||||
//these templates needed to be instantiated manually
|
||||
template u32 armcpu_exec<0>();
|
||||
template u32 armcpu_exec<1>();
|
||||
|
||||
#ifdef HAVE_JIT
|
||||
void arm_jit_sync()
|
||||
{
|
||||
NDS_ARM7.next_instruction = NDS_ARM7.instruct_adr;
|
||||
NDS_ARM9.next_instruction = NDS_ARM9.instruct_adr;
|
||||
armcpu_prefetch<0>();
|
||||
armcpu_prefetch<1>();
|
||||
}
|
||||
|
||||
template<int PROCNUM, bool jit>
|
||||
u32 armcpu_exec()
|
||||
{
|
||||
if (jit)
|
||||
{
|
||||
ARMPROC.instruct_adr &= ARMPROC.CPSR.bits.T?0xFFFFFFFE:0xFFFFFFFC;
|
||||
ArmOpCompiled f = (ArmOpCompiled)JIT_COMPILED_FUNC(ARMPROC.instruct_adr, PROCNUM);
|
||||
return f ? f() : arm_jit_compile<PROCNUM>();
|
||||
}
|
||||
|
||||
return armcpu_exec<PROCNUM>();
|
||||
}
|
||||
|
||||
template u32 armcpu_exec<0,false>();
|
||||
template u32 armcpu_exec<0,true>();
|
||||
template u32 armcpu_exec<1,false>();
|
||||
template u32 armcpu_exec<1,true>();
|
||||
#endif
|
||||
|
||||
void setIF(int PROCNUM, u32 flag)
|
||||
{
|
||||
//don't set generated bits!!!
|
||||
assert(!(flag&0x00200000));
|
||||
|
||||
MMU.reg_IF_bits[PROCNUM] |= flag;
|
||||
|
||||
NDS_Reschedule();
|
||||
}
|
||||
|
||||
const armcpu_ctrl_iface arm_default_ctrl_iface = {
|
||||
stall_cpu,
|
||||
unstall_cpu,
|
||||
read_cpu_reg,
|
||||
set_cpu_reg,
|
||||
install_post_exec_fn,
|
||||
remove_post_exec_fn,
|
||||
NULL
|
||||
};
|
|
@ -1,366 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2021 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DESMUME_ARMCPU_H
|
||||
#define DESMUME_ARMCPU_H
|
||||
|
||||
//half of this stuff is arm cpu internals
|
||||
//half is public API
|
||||
//really a mess
|
||||
|
||||
#include "types.h"
|
||||
#include "MMU.h"
|
||||
|
||||
#define CONDITION(i) ((i)>>28)
|
||||
#define REG_POS(i,n) (((i)>>n)&0xF)
|
||||
#define CODE(i) (((i)>>25)&0x7)
|
||||
#define OPCODE(i) (((i)>>21)&0xF)
|
||||
#define SIGNEBIT(i) (((i)>>20)&1)
|
||||
|
||||
#define EXCEPTION_RESET 0x00
|
||||
#define EXCEPTION_UNDEFINED_INSTRUCTION 0x04
|
||||
#define EXCEPTION_SWI 0x08
|
||||
#define EXCEPTION_PREFETCH_ABORT 0x0C
|
||||
#define EXCEPTION_DATA_ABORT 0x10
|
||||
#define EXCEPTION_RESERVED_0x14 0x14
|
||||
#define EXCEPTION_IRQ 0x18
|
||||
#define EXCEPTION_FAST_IRQ 0x1C
|
||||
|
||||
|
||||
#define CPU_FREEZE_NONE 0x00
|
||||
#define CPU_FREEZE_WAIT_IRQ 0x01 //waiting for some IRQ to happen, any IRQ
|
||||
#define CPU_FREEZE_IE_IF 0x02 //waiting for IE&IF to signal something (probably edge triggered on IRQ too)
|
||||
#define CPU_FREEZE_IRQ_IE_IF (CPU_FREEZE_WAIT_IRQ|CPU_FREEZE_IE_IF)
|
||||
#define CPU_FREEZE_OVERCLOCK_HACK 0x04
|
||||
|
||||
#define INSTRUCTION_INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF))
|
||||
|
||||
inline u32 ROR(u32 i, u32 j) { return ((((u32)(i))>>(j)) | (((u32)(i))<<(32-(j)))); }
|
||||
|
||||
template<typename T>
|
||||
inline T UNSIGNED_OVERFLOW(T a,T b,T c) { return BIT31(((a)&(b)) | (((a)|(b))&(~c))); }
|
||||
|
||||
template<typename T>
|
||||
inline T UNSIGNED_UNDERFLOW(T a,T b,T c) { return BIT31(((~a)&(b)) | (((~a)|(b))&(c))); }
|
||||
|
||||
template<typename T>
|
||||
inline T SIGNED_OVERFLOW(T a,T b,T c) { return BIT31(((a)&(b)&(~c)) | ((~a)&(~(b))&(c))); }
|
||||
|
||||
template<typename T>
|
||||
inline T SIGNED_UNDERFLOW(T a,T b,T c) { return BIT31(((a)&(~(b))&(~c)) | ((~a)&(b)&(c))); }
|
||||
|
||||
#if !defined(bswap32)
|
||||
#define bswap32(val) \
|
||||
( (val << 24) & 0xFF000000) | \
|
||||
( (val << 8) & 0x00FF0000) | \
|
||||
( (val >> 8) & 0x0000FF00) | \
|
||||
( (val >> 24) & 0x000000FF)
|
||||
#endif
|
||||
|
||||
#if !defined(bswap64)
|
||||
#define bswap64(x) \
|
||||
( (x << 56) & 0xff00000000000000ULL ) | \
|
||||
( (x << 40) & 0x00ff000000000000ULL ) | \
|
||||
( (x << 24) & 0x0000ff0000000000ULL ) | \
|
||||
( (x << 8) & 0x000000ff00000000ULL ) | \
|
||||
( (x >> 8) & 0x00000000ff000000ULL ) | \
|
||||
( (x >> 24) & 0x0000000000ff0000ULL ) | \
|
||||
( (x >> 40) & 0x000000000000ff00ULL ) | \
|
||||
( (x >> 56) & 0x00000000000000ffULL )
|
||||
#endif
|
||||
|
||||
// ============================= CPRS flags funcs
|
||||
inline bool CarryFrom(s32 left, s32 right)
|
||||
{
|
||||
u32 res = (0xFFFFFFFFU - (u32)left);
|
||||
|
||||
return ((u32)right > res);
|
||||
}
|
||||
|
||||
inline bool BorrowFrom(s32 left, s32 right)
|
||||
{
|
||||
return ((u32)right > (u32)left);
|
||||
}
|
||||
|
||||
inline bool OverflowFromADD(s32 alu_out, s32 left, s32 right)
|
||||
{
|
||||
return ((left >= 0 && right >= 0) || (left < 0 && right < 0))
|
||||
&& ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
|
||||
}
|
||||
|
||||
inline bool OverflowFromSUB(s32 alu_out, s32 left, s32 right)
|
||||
{
|
||||
return ((left < 0 && right >= 0) || (left >= 0 && right < 0))
|
||||
&& ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
|
||||
}
|
||||
|
||||
//zero 15-feb-2009 - these werent getting used and they were getting in my way
|
||||
//#define EQ 0x0
|
||||
//#define NE 0x1
|
||||
//#define CS 0x2
|
||||
//#define CC 0x3
|
||||
//#define MI 0x4
|
||||
//#define PL 0x5
|
||||
//#define VS 0x6
|
||||
//#define VC 0x7
|
||||
//#define HI 0x8
|
||||
//#define LS 0x9
|
||||
//#define GE 0xA
|
||||
//#define LT 0xB
|
||||
//#define GT 0xC
|
||||
//#define LE 0xD
|
||||
//#define AL 0xE
|
||||
|
||||
static const u8 arm_cond_table[16*16] = {
|
||||
// N=0, Z=0, C=0, V=0
|
||||
0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF, // 0x00
|
||||
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20, // 0x00
|
||||
// N=0, Z=0, C=0, V=1
|
||||
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x00, // 0x10
|
||||
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||
// N=0, Z=0, C=1, V=0
|
||||
0x00,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF, // 0x20
|
||||
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
|
||||
// N=0, Z=0, C=1, V=1
|
||||
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00, // 0x30
|
||||
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||
// N=0, Z=1, C=0, V=0
|
||||
0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF, // 0x40
|
||||
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
|
||||
// N=0, Z=1, C=0, V=1
|
||||
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x00, // 0x50
|
||||
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||
// N=0, Z=1, C=1, V=0
|
||||
0xFF,0x00,0xFF,0x00,0x00,0xFF,0x00,0xFF, // 0x60
|
||||
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
|
||||
// N=0, Z=1, C=1, V=1
|
||||
0xFF,0x00,0xFF,0x00,0x00,0xFF,0xFF,0x00, // 0x70
|
||||
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||
// N=1, Z=0, C=0, V=0
|
||||
0x00,0xFF,0x00,0xFF,0xFF,0x00,0x00,0xFF, // 0x80
|
||||
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||
// N=1, Z=0, C=0, V=1
|
||||
0x00,0xFF,0x00,0xFF,0xFF,0x00,0xFF,0x00, // 0x90
|
||||
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20,
|
||||
// N=1, Z=0, C=1, V=0
|
||||
0x00,0xFF,0xFF,0x00,0xFF,0x00,0x00,0xFF, // 0xA0
|
||||
0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||
// N=1, Z=0, C=1, V=1
|
||||
0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x00, // 0xB0
|
||||
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20,
|
||||
// N=1, Z=1, C=0, V=0
|
||||
0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF, // 0xC0
|
||||
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||
// N=1, Z=1, C=0, V=1
|
||||
0xFF,0x00,0x00,0xFF,0xFF,0x00,0xFF,0x00, // 0xD0
|
||||
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20,
|
||||
// N=1, Z=1, C=1, V=0
|
||||
0xFF,0x00,0xFF,0x00,0xFF,0x00,0x00,0xFF, // 0xE0
|
||||
0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20,
|
||||
// N=1, Z=1, C=1, V=1
|
||||
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00, // 0xF0
|
||||
0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20
|
||||
};
|
||||
|
||||
#define TEST_COND(cond, inst, CPSR) ((arm_cond_table[((CPSR.val >> 24) & 0xf0)|(cond)]) & (1 << (inst)))
|
||||
|
||||
|
||||
enum Mode
|
||||
{
|
||||
USR = 0x10,
|
||||
FIQ = 0x11,
|
||||
IRQ = 0x12,
|
||||
SVC = 0x13,
|
||||
ABT = 0x17,
|
||||
UND = 0x1B,
|
||||
SYS = 0x1F
|
||||
};
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
#ifdef MSB_FIRST
|
||||
u32 N : 1,
|
||||
Z : 1,
|
||||
C : 1,
|
||||
V : 1,
|
||||
Q : 1,
|
||||
RAZ : 19,
|
||||
I : 1,
|
||||
F : 1,
|
||||
T : 1,
|
||||
mode : 5;
|
||||
#else
|
||||
u32 mode : 5,
|
||||
T : 1,
|
||||
F : 1,
|
||||
I : 1,
|
||||
RAZ : 19,
|
||||
Q : 1,
|
||||
V : 1,
|
||||
C : 1,
|
||||
Z : 1,
|
||||
N : 1;
|
||||
#endif
|
||||
} bits;
|
||||
u32 val;
|
||||
} Status_Reg;
|
||||
|
||||
/**
|
||||
* The control interface to a CPU
|
||||
*/
|
||||
struct armcpu_ctrl_iface
|
||||
{
|
||||
/** stall the processor */
|
||||
void (*stall)( void *instance);
|
||||
|
||||
/** unstall the processor */
|
||||
void (*unstall)( void *instance);
|
||||
|
||||
/** read a register value */
|
||||
u32 (*read_reg)( void *instance, u32 reg_num);
|
||||
|
||||
/** set a register value */
|
||||
void (*set_reg)( void *instance, u32 reg_num, u32 value);
|
||||
|
||||
/** install the post execute function */
|
||||
void (*install_post_ex_fn)( void *instance,
|
||||
void (*fn)( void *, u32 adr, int thumb),
|
||||
void *fn_data);
|
||||
|
||||
/** remove the post execute function */
|
||||
void (*remove_post_ex_fn)( void *instance);
|
||||
|
||||
/** the private data passed to all interface functions */
|
||||
void *data;
|
||||
};
|
||||
|
||||
|
||||
typedef void* armcp_t;
|
||||
|
||||
struct armcpu_t
|
||||
{
|
||||
u32 proc_ID;
|
||||
u32 instruction; //4
|
||||
u32 instruct_adr; //8
|
||||
u32 next_instruction; //12
|
||||
|
||||
u32 R[16]; //16
|
||||
Status_Reg CPSR; //80
|
||||
Status_Reg SPSR;
|
||||
|
||||
u32 R13_usr, R14_usr;
|
||||
u32 R13_svc, R14_svc;
|
||||
u32 R13_abt, R14_abt;
|
||||
u32 R13_und, R14_und;
|
||||
u32 R13_irq, R14_irq;
|
||||
u32 R8_fiq, R9_fiq, R10_fiq, R11_fiq, R12_fiq, R13_fiq, R14_fiq;
|
||||
Status_Reg SPSR_svc, SPSR_abt, SPSR_und, SPSR_irq, SPSR_fiq;
|
||||
|
||||
u32 intVector;
|
||||
u8 LDTBit; //1 : ARMv5 style 0 : non ARMv5 (earlier)
|
||||
|
||||
u32 freeze;
|
||||
//BOOL waitIRQ;
|
||||
//BOOL halt_IE_and_IF;
|
||||
|
||||
u8 intrWaitARM_state;
|
||||
|
||||
BOOL BIOS_loaded;
|
||||
|
||||
u32 (* *swi_tab)();
|
||||
|
||||
// flag indicating if the processor is stalled (for debugging)
|
||||
int stalled;
|
||||
|
||||
#if defined(_M_X64) || defined(__x86_64__)
|
||||
u8 cond_table[16*16];
|
||||
#endif
|
||||
|
||||
/** there is a pending irq for the cpu */
|
||||
int irq_flag;
|
||||
|
||||
/** the post executed function (if installed) */
|
||||
void (*post_ex_fn)( void *, u32 adr, int thumb);
|
||||
|
||||
/** data for the post executed function */
|
||||
void *post_ex_fn_data;
|
||||
|
||||
/** the memory interface */
|
||||
armcpu_memory_iface *mem_if; // This is the memory interface currently in use.
|
||||
armcpu_memory_iface base_mem_if; // This is the CPU's base memory interface.
|
||||
|
||||
/** the ctrl interface */
|
||||
armcpu_ctrl_iface ctrl_iface;
|
||||
|
||||
// debugging stuff
|
||||
u32 runToRetTmp;
|
||||
bool runToRet;
|
||||
u32 stepOverBreak;
|
||||
std::vector<u32> *breakPoints;
|
||||
bool debugStep;
|
||||
};
|
||||
|
||||
void armcpu_SetControlInterface(armcpu_t *armcpu, const armcpu_ctrl_iface *theCtrlInterface);
|
||||
armcpu_ctrl_iface* armcpu_GetControlInterface(armcpu_t *armcpu);
|
||||
void armcpu_SetControlInterfaceData(armcpu_t *armcpu, void *theData);
|
||||
void* armcpu_GetControlInterfaceData(const armcpu_t *armcpu);
|
||||
|
||||
void armcpu_SetCurrentMemoryInterface(armcpu_t *armcpu, armcpu_memory_iface *theMemInterface);
|
||||
armcpu_memory_iface* armcpu_GetCurrentMemoryInterface(const armcpu_t *armcpu);
|
||||
void armcpu_SetCurrentMemoryInterfaceData(armcpu_t *armcpu, void *theData);
|
||||
void* armcpu_GetCurrentMemoryInterfaceData(const armcpu_t *armcpu);
|
||||
|
||||
void armcpu_SetBaseMemoryInterface(armcpu_t *armcpu, const armcpu_memory_iface *theMemInterface);
|
||||
armcpu_memory_iface* armcpu_GetBaseMemoryInterface(armcpu_t *armcpu);
|
||||
void armcpu_SetBaseMemoryInterfaceData(armcpu_t *armcpu, void *theData);
|
||||
void* armcpu_GetBaseMemoryInterfaceData(const armcpu_t *armcpu);
|
||||
|
||||
void armcpu_ResetMemoryInterfaceToBase(armcpu_t *armcpu);
|
||||
|
||||
void armcpu_changeCPSR();
|
||||
|
||||
int armcpu_new( armcpu_t *armcpu, u32 id);
|
||||
void armcpu_init(armcpu_t *armcpu, u32 adr);
|
||||
u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode);
|
||||
|
||||
|
||||
BOOL armcpu_irqException(armcpu_t *armcpu);
|
||||
BOOL armcpu_flagIrq( armcpu_t *armcpu);
|
||||
void armcpu_exception(armcpu_t *cpu, u32 number);
|
||||
u32 TRAPUNDEF(armcpu_t* cpu);
|
||||
u32 armcpu_Wait4IRQ(armcpu_t *cpu);
|
||||
|
||||
extern armcpu_t NDS_ARM7;
|
||||
extern armcpu_t NDS_ARM9;
|
||||
extern const armcpu_ctrl_iface arm_default_ctrl_iface;
|
||||
|
||||
template<int PROCNUM> u32 armcpu_exec();
|
||||
#ifdef HAVE_JIT
|
||||
template<int PROCNUM, bool jit> u32 armcpu_exec();
|
||||
#endif
|
||||
|
||||
void setIF(int PROCNUM, u32 flag);
|
||||
|
||||
static INLINE void NDS_makeIrq(int PROCNUM, u32 num)
|
||||
{
|
||||
setIF(PROCNUM,1<<num);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2006 yopyop
|
||||
Copyright (C) 2006-2015 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef BIOS_H
|
||||
#define BIOS_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
extern u32 (* ARM_swi_tab[2][32])();
|
||||
extern const char* ARM_swi_names[2][32];
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,329 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009-2024 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "types.h"
|
||||
|
||||
#define CHEAT_VERSION_MAJOR 2
|
||||
#define CHEAT_VERSION_MINOR 0
|
||||
#define MAX_XX_CODE 1024
|
||||
#define CHEAT_FILE_MIN_FGETS_BUFFER 32768
|
||||
|
||||
#define CHEAT_TYPE_EMPTY 0xFF
|
||||
#define CHEAT_TYPE_INTERNAL 0
|
||||
#define CHEAT_TYPE_AR 1
|
||||
#define CHEAT_TYPE_CODEBREAKER 2
|
||||
|
||||
enum CheatSystemError
|
||||
{
|
||||
CheatSystemError_NoError = 0,
|
||||
CheatSystemError_FileOpenFailed = 1,
|
||||
CheatSystemError_FileFormatInvalid = 2,
|
||||
CheatSystemError_GameNotFound = 3,
|
||||
CheatSystemError_LoadEntryError = 4,
|
||||
CheatSystemError_FileSaveFailed = 5,
|
||||
CheatSystemError_FileDoesNotExist = 6
|
||||
};
|
||||
|
||||
struct CHEATS_LIST
|
||||
{
|
||||
CHEATS_LIST()
|
||||
{
|
||||
memset(this,0,sizeof(*this));
|
||||
type = CHEAT_TYPE_EMPTY;
|
||||
}
|
||||
u8 type;
|
||||
u8 enabled;
|
||||
// TODO
|
||||
u8 freezeType; // 0 - normal freeze
|
||||
// 1 - can decrease
|
||||
// 2 - can increase
|
||||
u32 code[MAX_XX_CODE][2];
|
||||
|
||||
union
|
||||
{
|
||||
char description[1024];
|
||||
|
||||
struct
|
||||
{
|
||||
char descriptionMajor[512];
|
||||
char descriptionMinor[512];
|
||||
};
|
||||
};
|
||||
|
||||
u32 num;
|
||||
u8 size;
|
||||
};
|
||||
|
||||
class CHEATS
|
||||
{
|
||||
private:
|
||||
std::vector<CHEATS_LIST> _list;
|
||||
u8 _filename[MAX_PATH];
|
||||
size_t _currentGet;
|
||||
|
||||
char *clearCode(char *s);
|
||||
|
||||
public:
|
||||
CHEATS()
|
||||
: _currentGet(0)
|
||||
{
|
||||
memset(_filename, 0, sizeof(_filename));
|
||||
}
|
||||
~CHEATS() {}
|
||||
|
||||
void clear();
|
||||
void init(const char *thePath);
|
||||
const char* getFilePath() const;
|
||||
void setFilePath(const char *thePath);
|
||||
|
||||
size_t addItem(const CHEATS_LIST &srcCheat);
|
||||
bool add(u8 size, u32 address, u32 val, char *description, bool enabled);
|
||||
bool add(u8 size, u32 address, u32 val, char *description, u8 enabled);
|
||||
|
||||
bool updateItemAtIndex(const CHEATS_LIST &srcCheat, const size_t pos);
|
||||
bool update(u8 size, u32 address, u32 val, char *description, bool enabled, const size_t pos);
|
||||
bool update(u8 size, u32 address, u32 val, char *description, u8 enabled, const size_t pos);
|
||||
|
||||
bool move(size_t srcPos, size_t dstPos);
|
||||
|
||||
size_t add_AR_Direct(const CHEATS_LIST &srcCheat);
|
||||
bool add_AR(char *code, char *description, bool enabled);
|
||||
bool add_AR(char *code, char *description, u8 enabled);
|
||||
|
||||
bool update_AR(char *code, char *description, bool enabled, const size_t pos);
|
||||
bool update_AR(char *code, char *description, u8 enabled, const size_t pos);
|
||||
|
||||
bool add_CB(char *code, char *description, bool enabled);
|
||||
bool add_CB(char *code, char *description, u8 enabled);
|
||||
|
||||
bool update_CB(char *code, char *description, bool enabled, const size_t pos);
|
||||
bool update_CB(char *code, char *description, u8 enabled, const size_t pos);
|
||||
|
||||
bool remove(const size_t pos);
|
||||
|
||||
void toggle(bool enabled, const size_t pos);
|
||||
void toggle(u8 enablbed, const size_t pos);
|
||||
|
||||
void getListReset();
|
||||
bool getList(CHEATS_LIST *cheat);
|
||||
CHEATS_LIST* getListPtr();
|
||||
bool copyItemFromIndex(const size_t pos, CHEATS_LIST &outCheatItem);
|
||||
CHEATS_LIST* getItemPtrAtIndex(const size_t pos) const;
|
||||
size_t getListSize() const;
|
||||
size_t getActiveCount() const;
|
||||
void setDescription(const char *description, const size_t pos);
|
||||
bool save();
|
||||
bool load();
|
||||
bool process(int targetType) const;
|
||||
|
||||
static void JitNeedsReset();
|
||||
static bool ResetJitIfNeeded();
|
||||
|
||||
template<size_t LENGTH> static bool DirectWrite(const int targetProc, const u32 targetAddress, u32 newValue);
|
||||
static bool DirectWrite(const size_t newValueLength, const int targetProc, const u32 targetAddress, u32 newValue);
|
||||
|
||||
static bool ARparser(const CHEATS_LIST &cheat);
|
||||
|
||||
static void StringFromXXCode(const CHEATS_LIST &srcCheatItem, char *outCStringBuffer);
|
||||
static bool XXCodeFromString(const std::string codeString, CHEATS_LIST &outCheatItem);
|
||||
static bool XXCodeFromString(const char *codeString, CHEATS_LIST &outCheatItem);
|
||||
};
|
||||
|
||||
class CHEATSEARCH
|
||||
{
|
||||
private:
|
||||
u8 *_statMem;
|
||||
u8 *_mem;
|
||||
u32 _amount;
|
||||
u32 _lastRecord;
|
||||
|
||||
u32 _type;
|
||||
u32 _size;
|
||||
u32 _sign;
|
||||
|
||||
public:
|
||||
CHEATSEARCH()
|
||||
: _statMem(0), _mem(0), _amount(0), _lastRecord(0), _type(0), _size(0), _sign(0)
|
||||
{}
|
||||
~CHEATSEARCH() { this->close(); }
|
||||
bool start(u8 type, u8 size, u8 sign);
|
||||
void close();
|
||||
u32 search(u32 val);
|
||||
u32 search(u8 comp);
|
||||
u32 getAmount();
|
||||
bool getList(u32 *address, u32 *curVal);
|
||||
void getListReset();
|
||||
};
|
||||
|
||||
#define CHEATDB_OFFSET_FILE_DESCRIPTION 0x00000010
|
||||
#define CHEATDB_FILEOFFSET_FIRST_FAT_ENTRY 0x00000100
|
||||
|
||||
enum CheatDBFileFormat
|
||||
{
|
||||
CheatDBFileFormat_Undefined = 0,
|
||||
CheatDBFileFormat_R4 = 1,
|
||||
CheatDBFileFormat_Unknown = 65535
|
||||
};
|
||||
|
||||
// This struct maps to the FAT entries in the R4 cheat database file.
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
typedef struct FAT_R4
|
||||
{
|
||||
u8 serial[4];
|
||||
u32 CRC;
|
||||
u64 addr;
|
||||
} FAT_R4;
|
||||
#pragma pack(pop)
|
||||
|
||||
// Wrapper for a single entry in a memory block that contains data read from a cheat database file.
|
||||
// This struct also maintains the hierarchical relationships between entries.
|
||||
struct CheatDBEntry
|
||||
{
|
||||
u8 *base; // Pointer to the entry's base location in memory.
|
||||
char *name; // Pointer to the entry's name string.
|
||||
char *note; // Pointer to the entry's note string.
|
||||
u32 *codeLength; // Pointer to the entry's 32-bit code length in bytes. This value is NULL if the entry is a directory.
|
||||
u32 *codeData; // Pointer to the entry's code data, provided in pairs of 32-bit values. This value is NULL if the entry is a directory.
|
||||
|
||||
CheatDBEntry *parent;
|
||||
std::vector<CheatDBEntry> child;
|
||||
};
|
||||
typedef struct CheatDBEntry CheatDBEntry;
|
||||
|
||||
class CheatDBGame
|
||||
{
|
||||
protected:
|
||||
u32 _baseOffset; // This offset is relative to the file head.
|
||||
u32 _firstEntryOffset; // This offset is relative to the file head.
|
||||
u32 _encryptOffset; // This offset is relative to the memory address of this->_entryDataRawPtr.
|
||||
|
||||
u32 _rawDataSize;
|
||||
u32 _workingDataSize;
|
||||
u32 _crc;
|
||||
u32 _entryCount;
|
||||
|
||||
std::string _title;
|
||||
char _serial[4 + 1];
|
||||
|
||||
u8 *_entryDataRawPtr;
|
||||
u8 *_entryData;
|
||||
CheatDBEntry _entryRoot;
|
||||
u32 _cheatItemCount;
|
||||
|
||||
void _UpdateDirectoryParents(CheatDBEntry &directory);
|
||||
bool _CreateCheatItemFromCheatEntry(const CheatDBEntry &inEntry, const bool isHierarchical, CHEATS_LIST &outCheatItem);
|
||||
size_t _DirectoryAddCheatsFlat(const CheatDBEntry &directory, const bool isHierarchical, size_t cheatIndex, CHEATS_LIST *outCheatsList);
|
||||
|
||||
public:
|
||||
CheatDBGame();
|
||||
CheatDBGame(const u32 encryptOffset, const FAT_R4 &fat, const u32 rawDataSize);
|
||||
CheatDBGame(FILE *fp, const bool isEncrypted, const u32 encryptOffset, const FAT_R4 &fat, const u32 rawDataSize, u8 (&workingBuffer)[1024]);
|
||||
~CheatDBGame();
|
||||
|
||||
void SetInitialProperties(const u32 rawDataSize, const u32 encryptOffset, const FAT_R4 &fat);
|
||||
void LoadPropertiesFromFile(FILE *fp, const bool isEncrypted, u8 (&workingBuffer)[1024]);
|
||||
|
||||
u32 GetBaseOffset() const;
|
||||
u32 GetFirstEntryOffset() const;
|
||||
u32 GetEncryptOffset() const;
|
||||
u32 GetRawDataSize() const;
|
||||
u32 GetWorkingDataSize() const;
|
||||
u32 GetCRC() const;
|
||||
u32 GetEntryCount() const;
|
||||
u32 GetCheatItemCount() const;
|
||||
const char* GetTitle() const;
|
||||
const char* GetSerial() const;
|
||||
|
||||
const CheatDBEntry& GetEntryRoot() const;
|
||||
const u8* GetEntryRawData() const;
|
||||
bool IsEntryDataLoaded() const;
|
||||
|
||||
u8* LoadEntryData(FILE *fp, const bool isEncrypted);
|
||||
size_t ParseEntriesToCheatsListFlat(CHEATS_LIST *outCheatsList);
|
||||
};
|
||||
|
||||
typedef std::vector<CheatDBGame> CheatDBGameList;
|
||||
|
||||
class CheatDBFile
|
||||
{
|
||||
protected:
|
||||
std::string _path;
|
||||
std::string _description;
|
||||
std::string _formatString;
|
||||
|
||||
CheatDBFileFormat _format;
|
||||
bool _isEncrypted;
|
||||
size_t _size;
|
||||
|
||||
FILE *_fp;
|
||||
|
||||
CheatDBGame _ReadGame(const u32 encryptOffset, const FAT_R4 &fat, const u32 gameDataSize, u8 (&workingBuffer)[1024]);
|
||||
|
||||
public:
|
||||
CheatDBFile();
|
||||
~CheatDBFile();
|
||||
|
||||
static void R4Decrypt(u8 *buf, const size_t len, u64 n);
|
||||
static bool ReadToBuffer(FILE *fp, const size_t fileOffset, const bool isEncrypted, const size_t encryptOffset, const size_t requestedSize, u8 *outBuffer);
|
||||
|
||||
FILE* GetFilePtr() const;
|
||||
bool IsEncrypted() const;
|
||||
const char* GetDescription() const;
|
||||
CheatDBFileFormat GetFormat() const;
|
||||
const char* GetFormatString() const;
|
||||
|
||||
CheatSystemError OpenFile(const char *filePath);
|
||||
void CloseFile();
|
||||
|
||||
u32 LoadGameList(const char *gameCode, const u32 gameDatabaseCRC, CheatDBGameList &outList);
|
||||
};
|
||||
|
||||
class CHEATSEXPORT
|
||||
{
|
||||
private:
|
||||
CheatDBFile _dbFile;
|
||||
CheatDBGameList _tempGameList;
|
||||
CheatDBGame *_selectedDbGame;
|
||||
CHEATS_LIST *_cheats;
|
||||
CheatSystemError _lastError;
|
||||
|
||||
public:
|
||||
CHEATSEXPORT();
|
||||
~CHEATSEXPORT();
|
||||
|
||||
bool load(const char *path);
|
||||
void close();
|
||||
|
||||
CHEATS_LIST *getCheats() const;
|
||||
size_t getCheatsNum() const;
|
||||
const char* getGameTitle() const;
|
||||
const char* getDescription() const;
|
||||
CheatSystemError getErrorCode() const;
|
||||
};
|
||||
|
||||
CheatDBGame* GetCheatDBGameEntryFromList(const CheatDBGameList &gameList, const char *gameCode, const u32 gameDatabaseCRC);
|
||||
void CheatItemGenerateDescriptionHierarchical(const char *itemName, const char *itemNote, CHEATS_LIST &outCheatItem);
|
||||
void CheatItemGenerateDescriptionFlat(const char *folderName, const char *folderNote, const char *itemName, const char *itemNote, CHEATS_LIST &outCheatItem);
|
||||
|
||||
extern CHEATS *cheats;
|
||||
extern CHEATSEARCH *cheatSearch;
|
|
@ -1,634 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2009-2017 DeSmuME team
|
||||
|
||||
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//windows note: make sure this file gets compiled with _cdecl
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdio.h>
|
||||
#include "commandline.h"
|
||||
#include "types.h"
|
||||
#include "movie.h"
|
||||
#include "rtc.h"
|
||||
#include "slot1.h"
|
||||
#include "slot2.h"
|
||||
#include "NDSSystem.h"
|
||||
#include "utils/datetime.h"
|
||||
#include "utils/xstring.h"
|
||||
#include <compat/getopt.h>
|
||||
//#include "frontend/modules/mGetOpt.h" //to test with this, make sure global `optind` is initialized to 1
|
||||
|
||||
#define printerror(...) fprintf(stderr, __VA_ARGS__)
|
||||
|
||||
int _scanline_filter_a = 0, _scanline_filter_b = 2, _scanline_filter_c = 2, _scanline_filter_d = 4;
|
||||
int _commandline_linux_nojoy = 0;
|
||||
|
||||
CommandLine::CommandLine()
|
||||
: is_cflash_configured(false)
|
||||
, _load_to_memory(-1)
|
||||
, _play_movie_file(0)
|
||||
, _record_movie_file(0)
|
||||
, _cflash_image(0)
|
||||
, _cflash_path(0)
|
||||
, _gbaslot_rom(0)
|
||||
, _bios_arm9(NULL)
|
||||
, _bios_arm7(NULL)
|
||||
, _bios_swi(0)
|
||||
, _fw_path(NULL)
|
||||
, _fw_boot(0)
|
||||
, _spu_sync_mode(-1)
|
||||
, _spu_sync_method(-1)
|
||||
, _spu_advanced(0)
|
||||
, _num_cores(-1)
|
||||
, _rigorous_timing(0)
|
||||
, _advanced_timing(-1)
|
||||
, _gamehacks(-1)
|
||||
, _texture_deposterize(-1)
|
||||
, _texture_smooth(-1)
|
||||
, _slot1(NULL)
|
||||
, _slot1_fat_dir(NULL)
|
||||
, _slot1_fat_dir_type(false)
|
||||
, _slot1_no8000prot(0)
|
||||
#ifdef HAVE_JIT
|
||||
, _cpu_mode(-1)
|
||||
, _jit_size(-1)
|
||||
#endif
|
||||
, _console_type(NULL)
|
||||
, _advanscene_import(NULL)
|
||||
, load_slot(-1)
|
||||
, arm9_gdb_port(0)
|
||||
, arm7_gdb_port(0)
|
||||
, start_paused(FALSE)
|
||||
, autodetect_method(-1)
|
||||
, render3d(COMMANDLINE_RENDER3D_DEFAULT)
|
||||
, texture_upscale(-1)
|
||||
, gpu_resolution_multiplier(-1)
|
||||
, language(1) //english by default
|
||||
, disable_sound(0)
|
||||
, disable_limiter(0)
|
||||
, windowed_fullscreen(0)
|
||||
, frameskip(0)
|
||||
, horizontal(0)
|
||||
, scale(1.0)
|
||||
, _rtc_day(-1)
|
||||
, _rtc_hour(-1)
|
||||
{
|
||||
}
|
||||
|
||||
CommandLine::~CommandLine()
|
||||
{
|
||||
}
|
||||
|
||||
static char mytoupper(char c) { return ::toupper(c); }
|
||||
|
||||
static std::string strtoupper(const std::string& str)
|
||||
{
|
||||
std::string ret = str;
|
||||
std::transform(ret.begin(), ret.end(), ret.begin(), ::mytoupper);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define ENDL "\n"
|
||||
static const char* help_string = \
|
||||
"Arguments affecting overall emulator behaviour: (`user settings`):" ENDL
|
||||
" --num-cores N Override numcores detection and use this many" ENDL
|
||||
" --spu-synch Use SPU synch (crackles; helps streams; default ON)" ENDL
|
||||
" --spu-method N Select SPU synch method: 0:N, 1:Z, 2:P; default 0" ENDL
|
||||
" --3d-render [SW|AUTOGL|GL|OLDGL]" ENDL
|
||||
" Select 3d renderer; default SW" ENDL
|
||||
" --3d-texture-deposterize-enable" ENDL
|
||||
" Enables texture deposterization." ENDL
|
||||
" --3d-texture-upscale [1|2|4]" ENDL
|
||||
" Automatically upscales textures by the specified" ENDL
|
||||
" amount; 1:No scaling (default), 2:2x upscaling," ENDL
|
||||
" 4:4x upscaling" ENDL
|
||||
" --3d-texture-smoothing-enable" ENDL
|
||||
" Enables smooth texture sampling while rendering." ENDL
|
||||
#ifdef HOST_WINDOWS
|
||||
" --gpu-resolution-multiplier N" ENDL
|
||||
" Increases the resolution of GPU rendering by this" ENDL
|
||||
" multipler; 1:256x192 (default), 2:512x384," ENDL
|
||||
" 3:768x576, 4:1024x768, 5:1280x960" ENDL
|
||||
" --windowed-fullscreen" ENDL
|
||||
" Launches in windowed fullscreen (same as alt+enter)" ENDL
|
||||
#else
|
||||
" --scale N scale factor for window; default 1.0" ENDL
|
||||
" --horizontal display touch screen to the right; default OFF" ENDL
|
||||
" --nojoy Disables joystick support" ENDL
|
||||
#endif
|
||||
" --disable-sound Disables the sound output" ENDL
|
||||
" --disable-limiter Disables the 60fps limiter" ENDL
|
||||
" --rtc-day D Override RTC day, 0=Sunday, 6=Saturday" ENDL
|
||||
" --rtc-hour H Override RTC hour, 0=midnight, 23=an hour before" ENDL
|
||||
" --frameskip N Set frameskip to N; default 0" ENDL
|
||||
ENDL
|
||||
"Arguments affecting overall emulation parameters (`sync settings`): " ENDL
|
||||
#ifdef HAVE_JIT
|
||||
" --jit-enable Formerly --cpu-mode; default OFF" ENDL
|
||||
" --jit-size N JIT block size 1-100; 1:accurate 100:fast (default)" ENDL
|
||||
#endif
|
||||
" --advanced-timing Use advanced bus-level timing; default ON" ENDL
|
||||
" --rigorous-timing Use more realistic component timings; default OFF" ENDL
|
||||
" --gamehacks Use game-specific hacks; default ON" ENDL
|
||||
" --spu-advanced Enable advanced SPU capture functions (reverb)" ENDL
|
||||
" --backupmem-db Use DB for autodetecting backup memory type" ENDL
|
||||
ENDL
|
||||
"Arguments affecting the emulated requipment:" ENDL
|
||||
" --console-type [FAT|LITE|IQUE|DEBUG|DSI]" ENDL
|
||||
" Select basic console type; default FAT" ENDL
|
||||
" --bios-arm9 BIN_FILE Uses the ARM9 BIOS provided at the specified path" ENDL
|
||||
" --bios-arm7 BIN_FILE Uses the ARM7 BIOS provided at the specified path" ENDL
|
||||
" --firmware-path BIN_FILE Uses the firmware provided at the specified path" ENDL
|
||||
" --firmware-boot 0|1 Boot from firmware" ENDL
|
||||
" --bios-swi Uses SWI from the provided bios files (else HLE)" ENDL
|
||||
" --lang N Firmware language (can affect game translations)" ENDL
|
||||
" 0 = Japanese, 1 = English (default), 2 = French" ENDL
|
||||
" 3 = German, 4 = Italian, 5 = Spanish" ENDL
|
||||
ENDL
|
||||
"Arguments affecting contents of SLOT-1:" ENDL
|
||||
" --slot1 [RETAIL|RETAILAUTO|R4|RETAILNAND|RETAILMCDROM|RETAILDEBUG]" ENDL
|
||||
" Device type to be used SLOT-1; default RETAILAUTO" ENDL
|
||||
" --preload-rom precache ROM to RAM instead of streaming from disk" ENDL
|
||||
" --slot1-fat-dir DIR Directory to mount for SLOT-1 flash cards" ENDL
|
||||
" --slot1_no8000prot Disables retail card copy protection <8000 feature" ENDL
|
||||
ENDL
|
||||
"Arguments affecting contents of SLOT-2:" ENDL
|
||||
" --cflash-image IMG_FILE Mounts cflash in SLOT-2 with specified image file" ENDL
|
||||
" --cflash-path DIR Mounts cflash in SLOT-2 with FS rooted at DIR" ENDL
|
||||
" --gbaslot-rom GBA_FILE Mounts GBA specified rom in SLOT-2" ENDL
|
||||
ENDL
|
||||
"Commands taking place after ROM is loaded: (be sure to specify a ROM!)" ENDL
|
||||
" --start-paused emulation should start paused" ENDL
|
||||
" --load-slot N loads savestate from slot N (0-9)" ENDL
|
||||
" --play-movie DSM_FILE automatically plays movie" ENDL
|
||||
" --record-movie DSM_FILE begin recording a movie" ENDL
|
||||
ENDL
|
||||
"Arguments affecting video filters:" ENDL
|
||||
" --scanline-filter-a N Fadeout intensity (N/16) (topleft) (default 0)" ENDL
|
||||
" --scanline-filter-b N Fadeout intensity (N/16) (topright) (default 2)" ENDL
|
||||
" --scanline-filter-c N Fadeout intensity (N/16) (bottomleft) (default 2)" ENDL
|
||||
" --scanline-filter-d N Fadeout intensity (N/16) (bottomright) (default 4)" ENDL
|
||||
ENDL
|
||||
#ifdef GDB_STUB
|
||||
"Arguments affecting debugging features:" ENDL
|
||||
" --arm9gdb PORTNUM Enable the ARM9 GDB stub on the given port" ENDL
|
||||
" --arm7gdb PORTNUM Enable the ARM7 GDB stub on the given port" ENDL
|
||||
ENDL
|
||||
#endif
|
||||
"Utility commands which occur in place of emulation:" ENDL
|
||||
" --advanscene-import PATH Import advanscene, dump .ddb, and exit" ENDL
|
||||
ENDL
|
||||
"These arguments may be reorganized/renamed in the future." ENDL ENDL
|
||||
;
|
||||
|
||||
//https://github.com/mono/mono/blob/b7a308f660de8174b64697a422abfc7315d07b8c/eglib/test/driver.c
|
||||
|
||||
#define OPT_NUMCORES 1
|
||||
#define OPT_SPU_METHOD 2
|
||||
#define OPT_3D_RENDER 3
|
||||
#define OPT_3D_TEXTURE_UPSCALE 81
|
||||
#define OPT_GPU_RESOLUTION_MULTIPLIER 82
|
||||
#define OPT_FRAMESKIP 83
|
||||
#define OPT_SCALE 84
|
||||
#define OPT_JIT_SIZE 100
|
||||
|
||||
#define OPT_CONSOLE_TYPE 200
|
||||
#define OPT_ARM9 201
|
||||
#define OPT_ARM7 202
|
||||
#define OPT_LANGUAGE 203
|
||||
#define OPT_FIRMPATH 204
|
||||
#define OPT_FIRMBOOT 205
|
||||
|
||||
#define OPT_SLOT1 300
|
||||
#define OPT_SLOT1_FAT_DIR 301
|
||||
|
||||
#define OPT_LOAD_SLOT 400
|
||||
#define OPT_PLAY_MOVIE 410
|
||||
#define OPT_RECORD_MOVIE 411
|
||||
|
||||
#define OPT_SLOT2_CFLASH_IMAGE 500
|
||||
#define OPT_SLOT2_CFLASH_DIR 501
|
||||
#define OPT_SLOT2_GBAGAME 502
|
||||
|
||||
#define OPT_SCANLINES_A 600
|
||||
#define OPT_SCANLINES_B 601
|
||||
#define OPT_SCANLINES_C 602
|
||||
#define OPT_SCANLINES_D 603
|
||||
|
||||
#define OPT_ARM9GDB 700
|
||||
#define OPT_ARM7GDB 701
|
||||
|
||||
#define OPT_RTC_DAY 800
|
||||
#define OPT_RTC_HOUR 801
|
||||
|
||||
#define OPT_ADVANSCENE 900
|
||||
|
||||
bool CommandLine::parse(int argc,char **argv)
|
||||
{
|
||||
//closest thing to a portable main() we have, I guess.
|
||||
srand((unsigned)time(nullptr));
|
||||
|
||||
std::string _render3d;
|
||||
|
||||
int opt_help = 0;
|
||||
int option_index = 0;
|
||||
for(;;)
|
||||
{
|
||||
//libretro-common's optional argument is not supported presently
|
||||
static struct option long_options[] =
|
||||
{
|
||||
//stuff
|
||||
{ "help", no_argument, &opt_help, 1 },
|
||||
|
||||
//user settings
|
||||
{ "num-cores", required_argument, NULL, OPT_NUMCORES },
|
||||
{ "spu-synch", no_argument, &_spu_sync_mode, 1 },
|
||||
{ "spu-method", required_argument, NULL, OPT_SPU_METHOD },
|
||||
{ "3d-render", required_argument, NULL, OPT_3D_RENDER },
|
||||
{ "3d-texture-deposterize-enable", no_argument, &_texture_deposterize, 1 },
|
||||
{ "3d-texture-upscale", required_argument, NULL, OPT_3D_TEXTURE_UPSCALE },
|
||||
{ "3d-texture-smoothing-enable", no_argument, &_texture_smooth, 1 },
|
||||
#ifdef HOST_WINDOWS
|
||||
{ "gpu-resolution-multiplier", required_argument, NULL, OPT_GPU_RESOLUTION_MULTIPLIER },
|
||||
{ "windowed-fullscreen", no_argument, &windowed_fullscreen, 1 },
|
||||
#else
|
||||
{ "nojoy", no_argument, &_commandline_linux_nojoy, 1},
|
||||
{ "horizontal", no_argument, &horizontal, 1},
|
||||
{ "scale", required_argument, NULL, OPT_SCALE},
|
||||
#endif
|
||||
{ "frameskip", required_argument, NULL, OPT_FRAMESKIP},
|
||||
{ "disable-sound", no_argument, &disable_sound, 1},
|
||||
{ "disable-limiter", no_argument, &disable_limiter, 1},
|
||||
{ "rtc-day", required_argument, NULL, OPT_RTC_DAY},
|
||||
{ "rtc-hour", required_argument, NULL, OPT_RTC_HOUR},
|
||||
|
||||
//sync settings
|
||||
#ifdef HAVE_JIT
|
||||
{ "jit-enable", no_argument, &_cpu_mode, 1},
|
||||
{ "jit-size", required_argument, NULL, OPT_JIT_SIZE },
|
||||
#endif
|
||||
{ "rigorous-timing", no_argument, &_rigorous_timing, 1},
|
||||
{ "advanced-timing", no_argument, &_advanced_timing, 1},
|
||||
{ "gamehacks", no_argument, &_gamehacks, 1},
|
||||
{ "spu-advanced", no_argument, &_spu_advanced, 1},
|
||||
{ "backupmem-db", no_argument, &autodetect_method, 1},
|
||||
|
||||
//system equipment
|
||||
{ "console-type", required_argument, NULL, OPT_CONSOLE_TYPE },
|
||||
{ "bios-arm9", required_argument, NULL, OPT_ARM9},
|
||||
{ "bios-arm7", required_argument, NULL, OPT_ARM7},
|
||||
{ "bios-swi", no_argument, &_bios_swi, 1},
|
||||
{ "firmware-path", required_argument, NULL, OPT_FIRMPATH},
|
||||
{ "firmware-boot", required_argument, NULL, OPT_FIRMBOOT},
|
||||
{ "lang", required_argument, NULL, OPT_LANGUAGE},
|
||||
|
||||
//slot-1 contents
|
||||
{ "slot1", required_argument, NULL, OPT_SLOT1},
|
||||
{ "preload-rom", no_argument, &_load_to_memory, 1},
|
||||
{ "slot1-fat-dir", required_argument, NULL, OPT_SLOT1_FAT_DIR},
|
||||
//and other slot-1 option
|
||||
{ "slot1-no8000prot", no_argument, &_slot1_no8000prot, 1},
|
||||
|
||||
//slot-2 contents
|
||||
{ "cflash-image", required_argument, NULL, OPT_SLOT2_CFLASH_IMAGE},
|
||||
{ "cflash-path", required_argument, NULL, OPT_SLOT2_CFLASH_DIR},
|
||||
{ "gbaslot-rom", required_argument, NULL, OPT_SLOT2_GBAGAME},
|
||||
|
||||
//commands
|
||||
{ "start-paused", no_argument, &start_paused, 1},
|
||||
{ "load-slot", required_argument, NULL, OPT_LOAD_SLOT},
|
||||
{ "play-movie", required_argument, NULL, OPT_PLAY_MOVIE},
|
||||
{ "record-movie", required_argument, NULL, OPT_RECORD_MOVIE},
|
||||
|
||||
//video filters
|
||||
{ "scanline-filter-a", required_argument, NULL, OPT_SCANLINES_A},
|
||||
{ "scanline-filter-b", required_argument, NULL, OPT_SCANLINES_B},
|
||||
{ "scanline-filter-c", required_argument, NULL, OPT_SCANLINES_C},
|
||||
{ "scanline-filter-d", required_argument, NULL, OPT_SCANLINES_D},
|
||||
|
||||
//debugging
|
||||
#ifdef GDB_STUB
|
||||
{ "arm9gdb", required_argument, NULL, OPT_ARM9GDB},
|
||||
{ "arm7gdb", required_argument, NULL, OPT_ARM7GDB},
|
||||
#endif
|
||||
|
||||
//utilities
|
||||
{ "advanscene-import", required_argument, NULL, OPT_ADVANSCENE},
|
||||
|
||||
{0,0,0,0}
|
||||
};
|
||||
|
||||
int c = getopt_long(argc,argv,"",long_options,&option_index);
|
||||
if(c == -1) break;
|
||||
if(c == '?')
|
||||
break;
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case 0: break;
|
||||
|
||||
//user settings
|
||||
case OPT_NUMCORES: _num_cores = atoi(optarg); break;
|
||||
case OPT_SPU_METHOD: _spu_sync_method = atoi(optarg); break;
|
||||
case OPT_3D_RENDER: _render3d = optarg; break;
|
||||
case OPT_3D_TEXTURE_UPSCALE: texture_upscale = atoi(optarg); break;
|
||||
case OPT_GPU_RESOLUTION_MULTIPLIER: gpu_resolution_multiplier = atoi(optarg); break;
|
||||
case OPT_SCALE: scale = atof(optarg); break;
|
||||
case OPT_FRAMESKIP: frameskip = atoi(optarg); break;
|
||||
|
||||
//RTC settings
|
||||
case OPT_RTC_DAY: _rtc_day = atoi(optarg); break;
|
||||
case OPT_RTC_HOUR: _rtc_hour = atoi(optarg); break;
|
||||
|
||||
//sync settings
|
||||
#ifdef HAVE_JIT
|
||||
case OPT_JIT_SIZE: _jit_size = atoi(optarg); break;
|
||||
#endif
|
||||
|
||||
//system equipment
|
||||
case OPT_CONSOLE_TYPE: console_type = optarg; break;
|
||||
case OPT_ARM9: _bios_arm9 = strdup(optarg); break;
|
||||
case OPT_ARM7: _bios_arm7 = strdup(optarg); break;
|
||||
case OPT_FIRMPATH: _fw_path = strdup(optarg); break;
|
||||
case OPT_FIRMBOOT: _fw_boot = atoi(optarg); break;
|
||||
|
||||
//slot-1 contents
|
||||
case OPT_SLOT1: slot1 = strtoupper(optarg); break;
|
||||
case OPT_SLOT1_FAT_DIR: slot1_fat_dir = optarg; break;
|
||||
|
||||
//slot-2 contents
|
||||
case OPT_SLOT2_CFLASH_IMAGE: cflash_image = optarg; break;
|
||||
case OPT_SLOT2_CFLASH_DIR: _cflash_path = optarg; break;
|
||||
case OPT_SLOT2_GBAGAME: _gbaslot_rom = optarg; break;
|
||||
|
||||
//commands
|
||||
case OPT_LOAD_SLOT: load_slot = atoi(optarg); break;
|
||||
case OPT_PLAY_MOVIE: play_movie_file = optarg; break;
|
||||
case OPT_RECORD_MOVIE: record_movie_file = optarg; break;
|
||||
|
||||
//video filters
|
||||
case OPT_SCANLINES_A: _scanline_filter_a = atoi(optarg); break;
|
||||
case OPT_SCANLINES_B: _scanline_filter_b = atoi(optarg); break;
|
||||
case OPT_SCANLINES_C: _scanline_filter_c = atoi(optarg); break;
|
||||
case OPT_SCANLINES_D: _scanline_filter_d = atoi(optarg); break;
|
||||
|
||||
//debugging
|
||||
case OPT_ARM9GDB: arm9_gdb_port = atoi(optarg); break;
|
||||
case OPT_ARM7GDB: arm7_gdb_port = atoi(optarg); break;
|
||||
|
||||
//utilities
|
||||
case OPT_ADVANSCENE: CommonSettings.run_advanscene_import = optarg; break;
|
||||
case OPT_LANGUAGE: language = atoi(optarg); break;
|
||||
}
|
||||
} //arg parsing loop
|
||||
|
||||
if(opt_help)
|
||||
{
|
||||
printf("%s",help_string);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(_load_to_memory != -1) CommonSettings.loadToMemory = (_load_to_memory == 1)?true:false;
|
||||
if(_num_cores != -1) CommonSettings.num_cores = _num_cores;
|
||||
if(_rigorous_timing) CommonSettings.rigorous_timing = true;
|
||||
if(_advanced_timing != -1) CommonSettings.advanced_timing = _advanced_timing==1;
|
||||
if(_gamehacks != -1) CommonSettings.gamehacks.en = _gamehacks==1;
|
||||
|
||||
#ifdef HAVE_JIT
|
||||
if(_cpu_mode != -1) CommonSettings.use_jit = (_cpu_mode==1);
|
||||
if(_jit_size != -1)
|
||||
{
|
||||
if ((_jit_size < 1) || (_jit_size > 100))
|
||||
CommonSettings.jit_max_block_size = 100;
|
||||
else
|
||||
CommonSettings.jit_max_block_size = _jit_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
//process console type
|
||||
CommonSettings.DebugConsole = false;
|
||||
CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_FAT;
|
||||
console_type = strtoupper(console_type);
|
||||
if(console_type == "") {}
|
||||
else if(console_type == "FAT") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_FAT;
|
||||
else if(console_type == "LITE") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_LITE;
|
||||
else if(console_type == "IQUE") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_IQUE;
|
||||
else if(console_type == "DSI") CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_DSI;
|
||||
else if(console_type == "DEBUG")
|
||||
{
|
||||
CommonSettings.ConsoleType = NDS_CONSOLE_TYPE_FAT;
|
||||
CommonSettings.DebugConsole = true;
|
||||
}
|
||||
|
||||
//process 3d renderer
|
||||
_render3d = strtoupper(_render3d);
|
||||
if(_render3d == "NONE") render3d = COMMANDLINE_RENDER3D_NONE;
|
||||
else if(_render3d == "SW") render3d = COMMANDLINE_RENDER3D_SW;
|
||||
else if(_render3d == "OLDGL") render3d = COMMANDLINE_RENDER3D_OLDGL;
|
||||
else if(_render3d == "AUTOGL") render3d = COMMANDLINE_RENDER3D_AUTOGL;
|
||||
else if(_render3d == "GL") render3d = COMMANDLINE_RENDER3D_GL;
|
||||
|
||||
if (_texture_deposterize != -1) CommonSettings.GFX3D_Renderer_TextureDeposterize = (_texture_deposterize == 1);
|
||||
if (_texture_smooth != -1) CommonSettings.GFX3D_Renderer_TextureSmoothing = (_texture_smooth == 1);
|
||||
|
||||
if (autodetect_method != -1)
|
||||
CommonSettings.autodetectBackupMethod = autodetect_method;
|
||||
|
||||
//TODO NOT MAX PRIORITY! change ARM9BIOS etc to be a std::string
|
||||
if(_bios_arm9) { CommonSettings.UseExtBIOS = true; strcpy(CommonSettings.ARM9BIOS,_bios_arm9); }
|
||||
if(_bios_arm7) { CommonSettings.UseExtBIOS = true; strcpy(CommonSettings.ARM7BIOS,_bios_arm7); }
|
||||
#ifndef HOST_WINDOWS
|
||||
if(_fw_path) { CommonSettings.UseExtFirmware = true; CommonSettings.UseExtFirmwareSettings = true; strcpy(CommonSettings.ExtFirmwarePath,_fw_path); }
|
||||
#endif
|
||||
if(_fw_boot) CommonSettings.BootFromFirmware = true;
|
||||
if(_bios_swi) CommonSettings.SWIFromBIOS = true;
|
||||
if(_slot1_no8000prot) CommonSettings.RetailCardProtection8000 = false;
|
||||
if(_spu_sync_mode != -1) CommonSettings.SPU_sync_mode = _spu_sync_mode;
|
||||
if(_spu_sync_method != -1) CommonSettings.SPU_sync_method = _spu_sync_method;
|
||||
if(_spu_advanced) CommonSettings.spu_advanced = true;
|
||||
|
||||
free(_bios_arm9);
|
||||
free(_bios_arm7);
|
||||
_bios_arm9 = _bios_arm7 = NULL;
|
||||
|
||||
//remaining argument should be an NDS file, and nothing more
|
||||
int remain = argc-optind;
|
||||
if(remain==1)
|
||||
nds_file = argv[optind];
|
||||
else if(remain>1) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandLine::validate()
|
||||
{
|
||||
if(slot1 != "")
|
||||
{
|
||||
if(slot1 != "R4" && slot1 != "RETAIL" && slot1 != "NONE" && slot1 != "RETAILNAND") {
|
||||
printerror("Invalid slot1 device specified.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_load_to_memory < -1 || _load_to_memory > 1) {
|
||||
printerror("Invalid parameter (0 - stream from disk, 1 - from RAM)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_spu_sync_mode < -1 || _spu_sync_mode > 1) {
|
||||
printerror("Invalid parameter\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_spu_sync_method < -1 || _spu_sync_method > 2) {
|
||||
printerror("Invalid parameter\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (load_slot < -1 || load_slot > 10) {
|
||||
printerror("I only know how to load from slots 0-10; -1 means 'do not load savegame' and is default\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(play_movie_file != "" && record_movie_file != "") {
|
||||
printerror("Cannot both play and record a movie.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(record_movie_file != "" && load_slot != -1) {
|
||||
printerror("Cannot both record a movie and load a savestate.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(cflash_path != "" && cflash_image != "") {
|
||||
printerror("Cannot specify both cflash-image and cflash-path.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if((_bios_arm9 && !_bios_arm7) || (_bios_arm7 && !_bios_arm9)) {
|
||||
printerror("If either bios-arm7 or bios-arm9 are specified, both must be.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(_bios_swi && (!_bios_arm7 || !_bios_arm9)) {
|
||||
printerror("If either bios-swi is used, bios-arm9 and bios-arm7 must be specified.\n");
|
||||
}
|
||||
|
||||
if(_fw_boot && (!_fw_path)) {
|
||||
printerror("If either firmware boot is used, firmware path must be specified.\n");
|
||||
}
|
||||
|
||||
if((_cflash_image && _gbaslot_rom) || (_cflash_path && _gbaslot_rom)) {
|
||||
printerror("Cannot specify both cflash and gbaslot rom (both occupy SLOT-2)\n");
|
||||
}
|
||||
|
||||
if (autodetect_method < -1 || autodetect_method > 1) {
|
||||
printerror("Invalid autodetect save method (0 - internal, 1 - from database)\n");
|
||||
}
|
||||
|
||||
if ( (texture_upscale != -1) && (texture_upscale != 1) && (texture_upscale != 2) && (texture_upscale != 4) ) {
|
||||
printerror("Invalid texture upscaling value [1|2|4]. Ignoring command line setting.\n");
|
||||
texture_upscale = -1;
|
||||
}
|
||||
|
||||
if ( (gpu_resolution_multiplier != -1) && ((gpu_resolution_multiplier < 1) || (gpu_resolution_multiplier > 5)) ) {
|
||||
printerror("Invalid GPU resolution multiplier [1..5]. Ignoring command line setting.\n");
|
||||
gpu_resolution_multiplier = -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_JIT
|
||||
if (_cpu_mode < -1 || _cpu_mode > 1) {
|
||||
printerror("Invalid cpu mode emulation (0 - interpreter, 1 - dynarec)\n");
|
||||
}
|
||||
if (_jit_size < -1 && (_jit_size == 0 || _jit_size > 100)) {
|
||||
printerror("Invalid jit block size [1..100]. set to 100\n");
|
||||
}
|
||||
#endif
|
||||
if (_rtc_day < -1 || _rtc_day > 6) {
|
||||
printerror("Invalid rtc day override, valid values are from 0 to 6");
|
||||
return false;
|
||||
}
|
||||
if (_rtc_hour < -1 || _rtc_hour > 23) {
|
||||
printerror("Invalid rtc day override, valid values are from 0 to 23");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CommandLine::errorHelp(const char* binName)
|
||||
{
|
||||
printerror("%s",help_string);
|
||||
}
|
||||
|
||||
void CommandLine::process_movieCommands()
|
||||
{
|
||||
if(play_movie_file != "")
|
||||
{
|
||||
FCEUI_LoadMovie(play_movie_file.c_str(),true,false,-1);
|
||||
}
|
||||
else if(record_movie_file != "")
|
||||
{
|
||||
FCEUI_SaveMovie(record_movie_file.c_str(), L"", START_BLANK, NULL, FCEUI_MovieGetRTCDefault());
|
||||
}
|
||||
}
|
||||
|
||||
void CommandLine::process_addonCommands()
|
||||
{
|
||||
if (cflash_image != "")
|
||||
{
|
||||
CFlash_Mode = ADDON_CFLASH_MODE_File;
|
||||
CFlash_Path = cflash_image;
|
||||
is_cflash_configured = true;
|
||||
}
|
||||
if (cflash_path != "")
|
||||
{
|
||||
CFlash_Mode = ADDON_CFLASH_MODE_Path;
|
||||
CFlash_Path = cflash_path;
|
||||
is_cflash_configured = true;
|
||||
}
|
||||
|
||||
if(slot1_fat_dir != "")
|
||||
slot1_SetFatDir(slot1_fat_dir);
|
||||
|
||||
if(slot1 == "RETAIL")
|
||||
slot1_Change(NDS_SLOT1_RETAIL_AUTO);
|
||||
else if(slot1 == "RETAILAUTO")
|
||||
slot1_Change(NDS_SLOT1_RETAIL_AUTO);
|
||||
else if(slot1 == "R4")
|
||||
slot1_Change(NDS_SLOT1_R4);
|
||||
else if(slot1 == "RETAILNAND")
|
||||
slot1_Change(NDS_SLOT1_RETAIL_NAND);
|
||||
else if(slot1 == "RETAILMCROM")
|
||||
slot1_Change(NDS_SLOT1_RETAIL_MCROM);
|
||||
else if(slot1 == "RETAILDEBUG")
|
||||
slot1_Change(NDS_SLOT1_RETAIL_DEBUG);
|
||||
|
||||
if (_rtc_day != -1 || _rtc_hour != -1) {
|
||||
DateTime now = DateTime::get_Now();
|
||||
int cur_day = now.get_DayOfWeek();
|
||||
int cur_hour = now.get_Hour();
|
||||
int cur_total = cur_day * 24 + cur_hour;
|
||||
int day = (_rtc_day != -1 ? _rtc_day : cur_day);
|
||||
int hour = (_rtc_hour != -1 ? _rtc_hour : cur_hour);
|
||||
int total = day * 24 + hour;
|
||||
int diff = total - cur_total;
|
||||
if (diff < 0)
|
||||
diff += 24 * 7;
|
||||
rtcHourOverride = diff;
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue