22 Commits

Author SHA1 Message Date
C.W. Betts 42d9266038 HAVE_STATIC_CODE_BUFFER has issues if built/linked on a newer version of macOS.
Don't use it for now.
2021-01-26 00:08:31 -07:00
C.W. Betts 2a0611cd32 Port the rest of the Obj-C files used by the OpenEmu core to ARC. 2021-01-24 20:38:06 -07:00
C.W. Betts e8d3c6ca76 Add Apple Silicon support. 2021-01-24 20:12:31 -07:00
clobber e47e9dc66a Bump version for sparkle updater. Core is still 0.9.11 2019-12-26 21:19:33 -07:00
Daniele Cattaneo aee471fb3f Hide some less-important modes from next/lastDisplayMode: actions as a UI simplification 2019-11-17 20:00:15 +01:00
Daniele Cattaneo 514109a0ac Use the provided display buffer hint if possible. 2019-11-17 20:00:15 +01:00
Daniele Cattaneo 1e8fcbc37f Implement screen gap options 2019-11-17 20:00:15 +01:00
Daniele Cattaneo c43aeebecd Implement screen rotation options 2019-11-17 20:00:15 +01:00
Daniele Cattaneo 9ec2347451 Implement screen ordering options for dual-screen mode 2019-11-17 20:00:15 +01:00
Daniele Cattaneo 20b0744e2a Implement horizontal screen layout 2019-11-17 20:00:15 +01:00
Daniele Cattaneo 7d5ac35ada Refactor the display mode state tracking to make it easier to implement additional display options. 2019-11-17 20:00:15 +01:00
Daniele Cattaneo 43bdc01a64 Fix files with mixed spaces/tabs indentation. 2019-11-17 14:56:03 +01:00
clobber a5c6d11348 Bump version for sparkle updater. Core is still 0.9.11 2019-10-30 23:46:06 -05:00
Stuart Carnie 464b72b64b fix: Stubbed Core Audio implementations for OpenEmu core 2019-10-30 18:24:01 -07:00
clobber 94f13711c6 Bump version for sparkle updater. Core is still 0.9.11 2018-11-26 12:38:08 -06:00
clobber d1c1d702a1 Add display mode change support 2018-11-26 12:37:31 -06:00
clobber 9ccda03447 Use ARC in core implementation 2018-11-26 12:29:16 -06:00
clobber f7d0113d53 Use newer API in core implementation 2018-11-25 23:39:23 -06:00
clobber 71cff21815 Set deployment target 2018-11-25 23:19:26 -06:00
clobber 77be2fd8b6 Add correct Bundle Identifier 2018-11-25 22:11:39 -06:00
clobber 0eabcaabcd Initial check-in of DeSmuME 0.9.11 2018-11-25 22:06:36 -06:00
clobber 2f122a79ff Update .gitignore 2018-11-25 21:27:13 -06:00
511 changed files with 294681 additions and 12 deletions
+14 -12
View File
@@ -1,6 +1,18 @@
# Xcode
.DS_Store
*/build/*
# Xcode
## User settings
xcuserdata/
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
*.xcscmblueprint
*.xccheckout
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
build/
DerivedData/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
@@ -9,13 +21,3 @@
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
profile
*.moved-aside
DerivedData
.idea/
*.hmap
*.xccheckout
#CocoaPods
Pods
+47
View File
@@ -0,0 +1,47 @@
Original author
---------------
yopyop
Current team
------------
Guillaume Duhamel
Normmatt
Riccardo Magliocchetti
CrazyMax
zeromus
rogerman
Luigi__
Contributors
------------
Bernat Muñoz (shash)
Allustar
amponzi
Anthony Molinaro
ape
Damien Nozay (damdoum)
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
+339
View File
@@ -0,0 +1,339 @@
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
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
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
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
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
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
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
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
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
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
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
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
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
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
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
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
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
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 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.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
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
Public License instead of this License.
+875
View File
@@ -0,0 +1,875 @@
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.
+97
View File
@@ -0,0 +1,97 @@
DeSmuME
_________________________________________
Copyright (C) 2006 yopyop
Copyright (C) 2006-2015 DeSmuME team
Last Updated: March 28, 2015
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 port
* 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: http://wiki.desmume.org/index.php?title=Main_Page
This is the main Wiki page that contains all of our official documentation.
* Manuals: http://wiki.desmume.org/index.php?title=Manual
The manuals contain detailed information about how to operate DeSmuME for each
port.
* FAQ: http://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:
http://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: http://desmume.org
Public Forum: http://forums.desmume.org
Developer Chat: irc://irc.freenode.net/desmume
Bug Reports: http://sourceforge.net/p/desmume/bugs
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 <http://www.gnu.org/licenses/>.
* See the GNU General Public License details in COPYING.
+3782
View File
File diff suppressed because it is too large Load Diff
+31
View File
@@ -0,0 +1,31 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2009 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 DISASSEMBLER_H
#define DISASSEMBLER_H
#include "types.h"
typedef char* (* DisasmOpFunc)(u32 adr, u32 i, char * txt);
extern const DisasmOpFunc des_arm_instructions_set[4096];
extern const DisasmOpFunc des_thumb_instructions_set[1024];
#endif
Executable
+328
View File
@@ -0,0 +1,328 @@
/*
Copyright 2006 yopyop
Copyright 2007 shash
Copyright 2007-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 "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"
// ========================================================= 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++;
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.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, val);
}
// ========================================================= DISP FIFO
DISP_FIFO disp_fifo;
void DISP_FIFOinit()
{
memset(&disp_fifo, 0, sizeof(DISP_FIFO));
}
void DISP_FIFOsend(u32 val)
{
//INFO("DISP_FIFO send value 0x%08X (head 0x%06X, tail 0x%06X)\n", val, disp_fifo.head, disp_fifo.tail);
disp_fifo.buf[disp_fifo.tail] = val;
disp_fifo.tail++;
if (disp_fifo.tail > 0x5FFF)
disp_fifo.tail = 0;
}
u32 DISP_FIFOrecv()
{
//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 > 0x5FFF)
disp_fifo.head = 0;
return (val);
}
Executable
+91
View File
@@ -0,0 +1,91 @@
/*
Copyright 2006 yopyop
Copyright 2007 shash
Copyright 2007-2011 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"
//=================================================== 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;
extern void GFX_PIPEclear();
extern void GFX_FIFOclear();
extern void GFX_FIFOsend(u8 cmd, u32 param);
extern BOOL GFX_PIPErecv(u8 *cmd, u32 *param);
extern void GFX_FIFOcnt(u32 val);
//=================================================== Display memory FIFO
typedef struct
{
u32 buf[0x6000]; // 256x192 32K color
u32 head; // head
u32 tail; // tail
} DISP_FIFO;
extern DISP_FIFO disp_fifo;
extern void DISP_FIFOinit();
extern void DISP_FIFOsend(u32 val);
extern u32 DISP_FIFOrecv();
#endif
Executable
+2760
View File
File diff suppressed because it is too large Load Diff
Executable
+923
View File
@@ -0,0 +1,923 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 Theo Berkau
Copyright (C) 2007 shash
Copyright (C) 2009-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 GPU_H
#define GPU_H
#include <stdio.h>
#include <iosfwd>
#include "types.h"
class EMUFILE;
struct MMU_struct;
//#undef FORCEINLINE
//#define FORCEINLINE
void gpu_savestate(EMUFILE* os);
bool gpu_loadstate(EMUFILE* is, int size);
/*******************************************************************************
this structure is for display control,
it holds flags for general display
*******************************************************************************/
#ifdef WORDS_BIGENDIAN
struct _DISPCNT
{
/* 7*/ u8 ForceBlank:1; // A+B:
/* 6*/ u8 OBJ_BMP_mapping:1; // A+B: 0=2D (128KB), 1=1D (128..256KB)
/* 5*/ u8 OBJ_BMP_2D_dim:1; // A+B: 0=128x512, 1=256x256 pixels
/* 4*/ u8 OBJ_Tile_mapping:1;// A+B: 0=2D (32KB), 1=1D (32..256KB)
/* 3*/ u8 BG0_3D:1; // A : 0=2D, 1=3D
/* 0*/ u8 BG_Mode:3; // A+B:
/*15*/ u8 WinOBJ_Enable:1; // A+B: 0=disable, 1=Enable
/*14*/ u8 Win1_Enable:1; // A+B: 0=disable, 1=Enable
/*13*/ u8 Win0_Enable:1; // A+B: 0=disable, 1=Enable
/*12*/ u8 OBJ_Enable:1; // A+B: 0=disable, 1=Enable
/*11*/ u8 BG3_Enable:1; // A+B: 0=disable, 1=Enable
/*10*/ u8 BG2_Enable:1; // A+B: 0=disable, 1=Enable
/* 9*/ u8 BG1_Enable:1; // A+B: 0=disable, 1=Enable
/* 8*/ u8 BG0_Enable:1; // A+B: 0=disable, 1=Enable
/*23*/ u8 OBJ_HBlank_process:1; // A+B: OBJ processed during HBlank (GBA bit5)
/*22*/ u8 OBJ_BMP_1D_Bound:1; // A :
/*20*/ u8 OBJ_Tile_1D_Bound:2; // A+B:
/*18*/ u8 VRAM_Block:2; // A : VRAM block (0..3=A..D)
/*16*/ u8 DisplayMode:2; // A+B: coreA(0..3) coreB(0..1) GBA(Green Swap)
// 0=off (white screen)
// 1=on (normal BG & OBJ layers)
// 2=VRAM display (coreA only)
// 3=RAM display (coreA only, DMA transfers)
/*31*/ u8 ExOBJPalette_Enable:1; // A+B: 0=disable, 1=Enable OBJ extended Palette
/*30*/ u8 ExBGxPalette_Enable:1; // A+B: 0=disable, 1=Enable BG extended Palette
/*27*/ u8 ScreenBase_Block:3; // A : Screen Base (64K step)
/*24*/ u8 CharacBase_Block:3; // A : Character Base (64K step)
};
#else
struct _DISPCNT
{
/* 0*/ u8 BG_Mode:3; // A+B:
/* 3*/ u8 BG0_3D:1; // A : 0=2D, 1=3D
/* 4*/ u8 OBJ_Tile_mapping:1; // A+B: 0=2D (32KB), 1=1D (32..256KB)
/* 5*/ u8 OBJ_BMP_2D_dim:1; // A+B: 0=128x512, 1=256x256 pixels
/* 6*/ u8 OBJ_BMP_mapping:1; // A+B: 0=2D (128KB), 1=1D (128..256KB)
// 7-15 same as GBA
/* 7*/ u8 ForceBlank:1; // A+B:
/* 8*/ u8 BG0_Enable:1; // A+B: 0=disable, 1=Enable
/* 9*/ u8 BG1_Enable:1; // A+B: 0=disable, 1=Enable
/*10*/ u8 BG2_Enable:1; // A+B: 0=disable, 1=Enable
/*11*/ u8 BG3_Enable:1; // A+B: 0=disable, 1=Enable
/*12*/ u8 OBJ_Enable:1; // A+B: 0=disable, 1=Enable
/*13*/ u8 Win0_Enable:1; // A+B: 0=disable, 1=Enable
/*14*/ u8 Win1_Enable:1; // A+B: 0=disable, 1=Enable
/*15*/ u8 WinOBJ_Enable:1; // A+B: 0=disable, 1=Enable
/*16*/ u8 DisplayMode:2; // A+B: coreA(0..3) coreB(0..1) GBA(Green Swap)
// 0=off (white screen)
// 1=on (normal BG & OBJ layers)
// 2=VRAM display (coreA only)
// 3=RAM display (coreA only, DMA transfers)
/*18*/ u8 VRAM_Block:2; // A : VRAM block (0..3=A..D)
/*20*/ u8 OBJ_Tile_1D_Bound:2; // A+B:
/*22*/ u8 OBJ_BMP_1D_Bound:1; // A :
/*23*/ u8 OBJ_HBlank_process:1; // A+B: OBJ processed during HBlank (GBA bit5)
/*24*/ u8 CharacBase_Block:3; // A : Character Base (64K step)
/*27*/ u8 ScreenBase_Block:3; // A : Screen Base (64K step)
/*30*/ u8 ExBGxPalette_Enable:1; // A+B: 0=disable, 1=Enable BG extended Palette
/*31*/ u8 ExOBJPalette_Enable:1; // A+B: 0=disable, 1=Enable OBJ extended Palette
};
#endif
typedef union
{
struct _DISPCNT bits;
u32 val;
} DISPCNT;
#define BGxENABLED(cnt,num) ((num<8)? ((cnt.val>>8) & num):0)
enum BlendFunc
{
NoBlend, Blend, Increase, Decrease
};
/*******************************************************************************
this structure is for display control of a specific layer,
there are 4 background layers
their priority indicate which one to draw on top of the other
some flags indicate special drawing mode, size, FX
*******************************************************************************/
#ifdef WORDS_BIGENDIAN
struct _BGxCNT
{
/* 7*/ u8 Palette_256:1; // 0=16x16, 1=1*256 palette
/* 6*/ u8 Mosaic_Enable:1; // 0=disable, 1=Enable mosaic
/* 2*/ u8 CharacBase_Block:4; // individual character base offset (n*16KB)
/* 0*/ u8 Priority:2; // 0..3=high..low
/*14*/ u8 ScreenSize:2; // text : 256x256 512x256 256x512 512x512
// x/rot/s : 128x128 256x256 512x512 1024x1024
// bmp : 128x128 256x256 512x256 512x512
// large : 512x1024 1024x512 - -
/*13*/ u8 PaletteSet_Wrap:1; // BG0 extended palette set 0=set0, 1=set2
// BG1 extended palette set 0=set1, 1=set3
// BG2 overflow area wraparound 0=off, 1=wrap
// BG3 overflow area wraparound 0=off, 1=wrap
/* 8*/ u8 ScreenBase_Block:5; // individual screen base offset (text n*2KB, BMP n*16KB)
};
#else
struct _BGxCNT
{
/* 0*/ u8 Priority:2; // 0..3=high..low
/* 2*/ u8 CharacBase_Block:4; // individual character base offset (n*16KB)
/* 6*/ u8 Mosaic_Enable:1; // 0=disable, 1=Enable mosaic
/* 7*/ u8 Palette_256:1; // 0=16x16, 1=1*256 palette
/* 8*/ u8 ScreenBase_Block:5; // individual screen base offset (text n*2KB, BMP n*16KB)
/*13*/ u8 PaletteSet_Wrap:1; // BG0 extended palette set 0=set0, 1=set2
// BG1 extended palette set 0=set1, 1=set3
// BG2 overflow area wraparound 0=off, 1=wrap
// BG3 overflow area wraparound 0=off, 1=wrap
/*14*/ u8 ScreenSize:2; // text : 256x256 512x256 256x512 512x512
// x/rot/s : 128x128 256x256 512x512 1024x1024
// bmp : 128x128 256x256 512x256 512x512
// large : 512x1024 1024x512 - -
};
#endif
typedef union
{
struct _BGxCNT bits;
u16 val;
} BGxCNT;
/*******************************************************************************
this structure is for background offset
*******************************************************************************/
typedef struct {
u16 BGxHOFS;
u16 BGxVOFS;
} BGxOFS;
/*******************************************************************************
this structure is for rotoscale parameters
*******************************************************************************/
typedef struct {
s16 BGxPA;
s16 BGxPB;
s16 BGxPC;
s16 BGxPD;
s32 BGxX;
s32 BGxY;
} BGxPARMS;
/*******************************************************************************
these structures are for window description,
windows are square regions and can "subclass"
background layers or object layers (i.e window controls the layers)
screen
|
+-- Window0/Window1/OBJwindow/OutOfWindows
|
+-- BG0/BG1/BG2/BG3/OBJ
*******************************************************************************/
typedef union {
struct {
u8 end:8;
u8 start:8;
} bits ;
u16 val;
} WINxDIM;
#ifdef WORDS_BIGENDIAN
typedef struct {
/* 6*/ u8 :2;
/* 5*/ u8 WINx_Effect_Enable:1;
/* 4*/ u8 WINx_OBJ_Enable:1;
/* 3*/ u8 WINx_BG3_Enable:1;
/* 2*/ u8 WINx_BG2_Enable:1;
/* 1*/ u8 WINx_BG1_Enable:1;
/* 0*/ u8 WINx_BG0_Enable:1;
} WINxBIT;
#else
typedef struct {
/* 0*/ u8 WINx_BG0_Enable:1;
/* 1*/ u8 WINx_BG1_Enable:1;
/* 2*/ u8 WINx_BG2_Enable:1;
/* 3*/ u8 WINx_BG3_Enable:1;
/* 4*/ u8 WINx_OBJ_Enable:1;
/* 5*/ u8 WINx_Effect_Enable:1;
/* 6*/ u8 :2;
} WINxBIT;
#endif
#ifdef WORDS_BIGENDIAN
typedef union {
struct {
WINxBIT win0;
WINxBIT win1;
} bits;
struct {
u8 :3;
u8 win0_en:5;
u8 :3;
u8 win1_en:5;
} packed_bits;
struct {
u8 low;
u8 high;
} bytes;
u16 val ;
} WINxCNT ;
#else
typedef union {
struct {
WINxBIT win0;
WINxBIT win1;
} bits;
struct {
u8 win0_en:5;
u8 :3;
u8 win1_en:5;
u8 :3;
} packed_bits;
struct {
u8 low;
u8 high;
} bytes;
u16 val ;
} WINxCNT ;
#endif
/*
typedef struct {
WINxDIM WIN0H;
WINxDIM WIN1H;
WINxDIM WIN0V;
WINxDIM WIN1V;
WINxCNT WININ;
WINxCNT WINOUT;
} WINCNT;
*/
/*******************************************************************************
this structure is for miscellanous settings
//TODO: needs further description
*******************************************************************************/
typedef struct {
u16 MOSAIC;
u16 unused1;
u16 unused2;//BLDCNT;
u16 unused3;//BLDALPHA;
u16 unused4;//BLDY;
u16 unused5;
/*
u16 unused6;
u16 unused7;
u16 unused8;
u16 unused9;
*/
} MISCCNT;
/*******************************************************************************
this structure is for 3D settings
*******************************************************************************/
struct _DISP3DCNT
{
/* 0*/ u8 EnableTexMapping:1; //
/* 1*/ u8 PolygonShading:1; // 0=Toon Shading, 1=Highlight Shading
/* 2*/ u8 EnableAlphaTest:1; // see ALPHA_TEST_REF
/* 3*/ u8 EnableAlphaBlending:1; // see various Alpha values
/* 4*/ u8 EnableAntiAliasing:1; //
/* 5*/ u8 EnableEdgeMarking:1; // see EDGE_COLOR
/* 6*/ u8 FogOnlyAlpha:1; // 0=Alpha and Color, 1=Only Alpha (see FOG_COLOR)
/* 7*/ u8 EnableFog:1; // Fog Master Enable
/* 8*/ u8 FogShiftSHR:4; // 0..10 SHR-Divider (see FOG_OFFSET)
/*12*/ u8 AckColorBufferUnderflow:1; // Color Buffer RDLINES Underflow (0=None, 1=Underflow/Acknowledge)
/*13*/ u8 AckVertexRAMOverflow:1; // Polygon/Vertex RAM Overflow (0=None, 1=Overflow/Acknowledge)
/*14*/ u8 RearPlaneMode:1; // 0=Blank, 1=Bitmap
/*15*/ u8 :1;
/*16*/ u16 :16;
};
typedef union
{
struct _DISP3DCNT bits;
u32 val;
} DISP3DCNT;
/*******************************************************************************
this structure is for capture control (core A only)
source:
http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode
*******************************************************************************/
struct DISPCAPCNT
{
enum CAPX {
_128, _256
} capx;
u32 val;
BOOL enabled;
u8 EVA;
u8 EVB;
u8 writeBlock;
u8 writeOffset;
u16 capy;
u8 srcA;
u8 srcB;
u8 readBlock;
u8 readOffset;
u8 capSrc;
} ;
/*******************************************************************************
this structure holds everything and should be mapped to
* core A : 0x04000000
* core B : 0x04001000
*******************************************************************************/
typedef struct _reg_dispx {
DISPCNT dispx_DISPCNT; // 0x0400x000
u16 dispA_DISPSTAT; // 0x04000004
u16 dispx_VCOUNT; // 0x0400x006
BGxCNT dispx_BGxCNT[4]; // 0x0400x008
BGxOFS dispx_BGxOFS[4]; // 0x0400x010
BGxPARMS dispx_BG2PARMS; // 0x0400x020
BGxPARMS dispx_BG3PARMS; // 0x0400x030
u8 filler[12]; // 0x0400x040
MISCCNT dispx_MISC; // 0x0400x04C
DISP3DCNT dispA_DISP3DCNT; // 0x04000060
DISPCAPCNT dispA_DISPCAPCNT; // 0x04000064
u32 dispA_DISPMMEMFIFO; // 0x04000068
} REG_DISPx ;
typedef BOOL (*fun_gl_Begin) (int screen);
typedef void (*fun_gl_End) (int screen);
// the GUI should use this function prior to all gl calls
// if call to beg succeeds opengl draw
void register_gl_fun(fun_gl_Begin beg,fun_gl_End end);
#define GPU_MAIN 0
#define GPU_SUB 1
/* human readable bitmask names */
#define ADDRESS_STEP_512B 0x00200
#define ADDRESS_STEP_1KB 0x00400
#define ADDRESS_STEP_2KB 0x00800
#define ADDRESS_STEP_4KB 0x01000
#define ADDRESS_STEP_8KB 0x02000
#define ADDRESS_STEP_16KB 0x04000
#define ADDRESS_STEP_32KB 0x08000
#define ADDRESS_STEP_64KB 0x10000
#define ADDRESS_STEP_128KB 0x20000
#define ADDRESS_STEP_256KB 0x40000
#define ADDRESS_STEP_512KB 0x80000
#define ADDRESS_MASK_256KB (ADDRESS_STEP_256KB-1)
#ifdef WORDS_BIGENDIAN
struct _TILEENTRY
{
/*14*/ unsigned Palette:4;
/*13*/ unsigned VFlip:1; // VERTICAL FLIP (top<-->bottom)
/*12*/ unsigned HFlip:1; // HORIZONTAL FLIP (left<-->right)
/* 0*/ unsigned TileNum:10;
};
#else
struct _TILEENTRY
{
/* 0*/ unsigned TileNum:10;
/*12*/ unsigned HFlip:1; // HORIZONTAL FLIP (left<-->right)
/*13*/ unsigned VFlip:1; // VERTICAL FLIP (top<-->bottom)
/*14*/ unsigned Palette:4;
};
#endif
typedef union
{
struct _TILEENTRY bits;
u16 val;
} TILEENTRY;
struct _ROTOCOORD
{
u32 Fraction:8;
s32 Integer:20;
u32 pad:4;
};
typedef union
{
struct _ROTOCOORD bits;
s32 val;
} ROTOCOORD;
/*
this structure is for color representation,
it holds 5 meaningful bits per color channel (red,green,blue)
and 1 meaningful bit for alpha representation
this bit can be unused or used for special FX
*/
struct _COLOR { // abgr x555
#ifdef WORDS_BIGENDIAN
unsigned alpha:1; // sometimes it is unused (pad)
unsigned blue:5;
unsigned green:5;
unsigned red:5;
#else
unsigned red:5;
unsigned green:5;
unsigned blue:5;
unsigned alpha:1; // sometimes it is unused (pad)
#endif
};
struct _COLORx { // abgr x555
unsigned bgr:15;
unsigned alpha:1; // sometimes it is unused (pad)
};
typedef union
{
struct _COLOR bits;
struct _COLORx bitx;
u16 val;
} COLOR;
struct _COLOR32 { // ARGB
unsigned :3;
unsigned blue:5;
unsigned :3;
unsigned green:5;
unsigned :3;
unsigned red:5;
unsigned :7;
unsigned alpha:1; // sometimes it is unused (pad)
};
typedef union
{
struct _COLOR32 bits;
u32 val;
} COLOR32;
#define COLOR_16_32(w,i) \
/* doesnt matter who's 16bit who's 32bit */ \
i.bits.red = w.bits.red; \
i.bits.green = w.bits.green; \
i.bits.blue = w.bits.blue; \
i.bits.alpha = w.bits.alpha;
// (00: Normal, 01: Transparent, 10: Object window, 11: Bitmap)
enum GPU_OBJ_MODE
{
GPU_OBJ_MODE_Normal = 0,
GPU_OBJ_MODE_Transparent = 1,
GPU_OBJ_MODE_Window = 2,
GPU_OBJ_MODE_Bitmap = 3
};
struct _OAM_
{
//attr0
u8 Y;
u8 RotScale;
u8 Mode;
u8 Mosaic;
u8 Depth;
u8 Shape;
//att1
s16 X;
u8 RotScalIndex;
u8 HFlip, VFlip;
u8 Size;
//attr2
u16 TileIndex;
u8 Priority;
u8 PaletteIndex;
//attr3
u16 attr3;
};
void SlurpOAM(_OAM_* oam_output, void* oam_buffer, int oam_index);
u16 SlurpOAMAffineParam(void* oam_buffer, int oam_index);
typedef struct
{
s16 x;
s16 y;
} size;
#define NB_PRIORITIES 4
#define NB_BG 4
//this structure holds information for rendering.
typedef struct
{
u8 PixelsX[256];
u8 BGs[NB_BG], nbBGs;
u8 pad[1];
u16 nbPixelsX;
//256+8:
u8 pad2[248];
//things were slower when i organized this struct this way. whatever.
//u8 PixelsX[256];
//int BGs[NB_BG], nbBGs;
//int nbPixelsX;
////<-- 256 + 24
//u8 pad2[256-24];
} itemsForPriority_t;
#define MMU_ABG 0x06000000
#define MMU_BBG 0x06200000
#define MMU_AOBJ 0x06400000
#define MMU_BOBJ 0x06600000
#define MMU_LCDC 0x06800000
extern CACHE_ALIGN u8 gpuBlendTable555[17][17][32][32];
enum BGType {
BGType_Invalid=0, BGType_Text=1, BGType_Affine=2, BGType_Large8bpp=3,
BGType_AffineExt=4, BGType_AffineExt_256x16=5, BGType_AffineExt_256x1=6, BGType_AffineExt_Direct=7
};
extern const BGType GPU_mode2type[8][4];
struct GPU
{
GPU()
: debug(false)
{}
// some structs are becoming redundant
// some functions too (no need to recopy some vars as it is done by MMU)
REG_DISPx * dispx_st;
//this indicates whether this gpu is handling debug tools
bool debug;
_BGxCNT & bgcnt(int num) { return (dispx_st)->dispx_BGxCNT[num].bits; }
_DISPCNT & dispCnt() { return dispx_st->dispx_DISPCNT.bits; }
template<bool MOSAIC> void modeRender(int layer);
DISPCAPCNT dispCapCnt;
BOOL LayersEnable[5];
itemsForPriority_t itemsForPriority[NB_PRIORITIES];
#define BGBmpBB BG_bmp_ram
#define BGChBB BG_tile_ram
u32 BG_bmp_large_ram[4];
u32 BG_bmp_ram[4];
u32 BG_tile_ram[4];
u32 BG_map_ram[4];
u8 BGExtPalSlot[4];
u32 BGSize[4][2];
BGType BGTypes[4];
struct MosaicColor {
u16 bg[4][256];
struct Obj {
u16 color;
u8 alpha, opaque;
} obj[256];
} mosaicColors;
u8 sprNum[256];
u8 h_win[2][256];
const u8 *curr_win[2];
void update_winh(int WIN_NUM);
bool need_update_winh[2];
template<int WIN_NUM> void setup_windows();
u8 core;
u8 dispMode;
u8 vramBlock;
u8 *VRAMaddr;
//FIFO fifo;
u8 bgPrio[5];
BOOL bg0HasHighestPrio;
void * oam;
u32 sprMem;
u8 sprBoundary;
u8 sprBMPBoundary;
u8 sprBMPMode;
u32 sprEnable;
u8 WIN0H0;
u8 WIN0H1;
u8 WIN0V0;
u8 WIN0V1;
u8 WIN1H0;
u8 WIN1H1;
u8 WIN1V0;
u8 WIN1V1;
u8 WININ0;
bool WININ0_SPECIAL;
u8 WININ1;
bool WININ1_SPECIAL;
u8 WINOUT;
bool WINOUT_SPECIAL;
u8 WINOBJ;
bool WINOBJ_SPECIAL;
u8 WIN0_ENABLED;
u8 WIN1_ENABLED;
u8 WINOBJ_ENABLED;
u16 BLDCNT;
u8 BLDALPHA_EVA;
u8 BLDALPHA_EVB;
u8 BLDY_EVY;
u16 *currentFadeInColors, *currentFadeOutColors;
bool blend2[8];
CACHE_ALIGN u16 tempScanlineBuffer[256];
u8 *tempScanline;
u8 MasterBrightMode;
u32 MasterBrightFactor;
CACHE_ALIGN u8 bgPixels[1024]; //yes indeed, this is oversized. map debug tools try to write to it
u32 currLine;
u8 currBgNum;
bool blend1;
u8* currDst;
u8* _3dColorLine;
static struct MosaicLookup {
struct TableEntry {
u8 begin, trunc;
} table[16][256];
MosaicLookup() {
for(int m=0;m<16;m++)
for(int i=0;i<256;i++) {
int mosaic = m+1;
TableEntry &te = table[m][i];
te.begin = (i%mosaic==0);
te.trunc = i/mosaic*mosaic;
}
}
TableEntry *width, *height;
int widthValue, heightValue;
} mosaicLookup;
bool curr_mosaic_enabled;
u16 blend(u16 colA, u16 colB);
template<bool BACKDROP, BlendFunc FUNC, bool WINDOW>
FORCEINLINE FASTCALL bool _master_setFinalBGColor(u16 &color, const u32 x);
template<BlendFunc FUNC, bool WINDOW>
FORCEINLINE FASTCALL void _master_setFinal3dColor(int dstX, int srcX);
int setFinalColorBck_funcNum;
int bgFunc;
int setFinalColor3d_funcNum;
int setFinalColorSpr_funcNum;
//Final3DColFunct setFinalColor3D;
enum SpriteRenderMode {
SPRITE_1D, SPRITE_2D
} spriteRenderMode;
template<GPU::SpriteRenderMode MODE>
void _spriteRender(u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab);
inline void spriteRender(u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab)
{
if(spriteRenderMode == SPRITE_1D)
_spriteRender<SPRITE_1D>(dst,dst_alpha,typeTab, prioTab);
else
_spriteRender<SPRITE_2D>(dst,dst_alpha,typeTab, prioTab);
}
void setFinalColor3d(int dstX, int srcX);
template<bool BACKDROP, int FUNCNUM> void setFinalColorBG(u16 color, const u32 x);
template<bool MOSAIC, bool BACKDROP> FORCEINLINE void __setFinalColorBck(u16 color, const u32 x, const int opaque);
template<bool MOSAIC, bool BACKDROP, int FUNCNUM> FORCEINLINE void ___setFinalColorBck(u16 color, const u32 x, const int opaque);
void setAffineStart(int layer, int xy, u32 val);
void setAffineStartWord(int layer, int xy, u16 val, int word);
u32 getAffineStart(int layer, int xy);
void refreshAffineStartRegs(const int num, const int xy);
struct AffineInfo {
AffineInfo() : x(0), y(0) {}
u32 x, y;
} affineInfo[2];
void renderline_checkWindows(u16 x, bool &draw, bool &effect) const;
// check whether (x,y) is within the rectangle (including wraparounds)
template<int WIN_NUM>
u8 withinRect(u16 x) const;
void setBLDALPHA(u16 val)
{
BLDALPHA_EVA = (val&0x1f) > 16 ? 16 : (val&0x1f);
BLDALPHA_EVB = ((val>>8)&0x1f) > 16 ? 16 : ((val>>8)&0x1f);
updateBLDALPHA();
}
void setBLDALPHA_EVA(u8 val)
{
BLDALPHA_EVA = (val&0x1f) > 16 ? 16 : (val&0x1f);
updateBLDALPHA();
}
void setBLDALPHA_EVB(u8 val)
{
BLDALPHA_EVB = (val&0x1f) > 16 ? 16 : (val&0x1f);
updateBLDALPHA();
}
u32 getHOFS(int bg);
u32 getVOFS(int bg);
typedef u8 TBlendTable[32][32];
TBlendTable *blendTable;
void updateBLDALPHA()
{
blendTable = (TBlendTable*)&gpuBlendTable555[BLDALPHA_EVA][BLDALPHA_EVB][0][0];
}
};
#if 0
// normally should have same addresses
static void REG_DISPx_pack_test(GPU * gpu)
{
REG_DISPx * r = gpu->dispx_st;
printf ("%08x %02x\n", (u32)r, (u32)(&r->dispx_DISPCNT) - (u32)r);
printf ("\t%02x\n", (u32)(&r->dispA_DISPSTAT) - (u32)r);
printf ("\t%02x\n", (u32)(&r->dispx_VCOUNT) - (u32)r);
printf ("\t%02x\n", (u32)(&r->dispx_BGxCNT[0]) - (u32)r);
printf ("\t%02x\n", (u32)(&r->dispx_BGxOFS[0]) - (u32)r);
printf ("\t%02x\n", (u32)(&r->dispx_BG2PARMS) - (u32)r);
printf ("\t%02x\n", (u32)(&r->dispx_BG3PARMS) - (u32)r);
// printf ("\t%02x\n", (u32)(&r->dispx_WINCNT) - (u32)r);
printf ("\t%02x\n", (u32)(&r->dispx_MISC) - (u32)r);
printf ("\t%02x\n", (u32)(&r->dispA_DISP3DCNT) - (u32)r);
printf ("\t%02x\n", (u32)(&r->dispA_DISPCAPCNT) - (u32)r);
printf ("\t%02x\n", (u32)(&r->dispA_DISPMMEMFIFO) - (u32)r);
}
#endif
CACHE_ALIGN extern u8 GPU_screen[4*256*192];
GPU * GPU_Init(u8 l);
void GPU_Reset(GPU *g, u8 l);
void GPU_DeInit(GPU *);
//these are functions used by debug tools which want to render layers etc outside the context of the emulation
namespace GPU_EXT
{
void textBG(GPU * gpu, u8 num, u8 * DST); //Draw text based background
void rotBG(GPU * gpu, u8 num, u8 * DST);
void extRotBG(GPU * gpu, u8 num, u8 * DST);
};
void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab);
void sprite2D(GPU * gpu, u16 l, u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab);
extern const size sprSizeTab[4][4];
typedef struct {
GPU * gpu;
u16 offset;
} NDS_Screen;
extern NDS_Screen MainScreen;
extern NDS_Screen SubScreen;
int Screen_Init();
void Screen_Reset(void);
void Screen_DeInit(void);
extern MMU_struct MMU;
void GPU_setVideoProp(GPU *, u32 p);
void GPU_setBGProp(GPU *, u16 num, u16 p);
void GPU_setBLDCNT(GPU *gpu, u16 v) ;
void GPU_setBLDY(GPU *gpu, u16 v) ;
void GPU_setMOSAIC(GPU *gpu, u16 v) ;
void GPU_remove(GPU *, u8 num);
void GPU_addBack(GPU *, u8 num);
int GPU_ChangeGraphicsCore(int coreid);
void GPU_set_DISPCAPCNT(u32 val) ;
void GPU_RenderLine(NDS_Screen * screen, u16 l, bool skip = false) ;
void GPU_setMasterBrightness (GPU *gpu, u16 val);
inline void GPU_setWIN0_H(GPU* gpu, u16 val) { gpu->WIN0H0 = val >> 8; gpu->WIN0H1 = val&0xFF; gpu->need_update_winh[0] = true; }
inline void GPU_setWIN0_H0(GPU* gpu, u8 val) { gpu->WIN0H0 = val; gpu->need_update_winh[0] = true; }
inline void GPU_setWIN0_H1(GPU* gpu, u8 val) { gpu->WIN0H1 = val; gpu->need_update_winh[0] = true; }
inline void GPU_setWIN0_V(GPU* gpu, u16 val) { gpu->WIN0V0 = val >> 8; gpu->WIN0V1 = val&0xFF;}
inline void GPU_setWIN0_V0(GPU* gpu, u8 val) { gpu->WIN0V0 = val; }
inline void GPU_setWIN0_V1(GPU* gpu, u8 val) { gpu->WIN0V1 = val; }
inline void GPU_setWIN1_H(GPU* gpu, u16 val) {gpu->WIN1H0 = val >> 8; gpu->WIN1H1 = val&0xFF; gpu->need_update_winh[1] = true; }
inline void GPU_setWIN1_H0(GPU* gpu, u8 val) { gpu->WIN1H0 = val; gpu->need_update_winh[1] = true; }
inline void GPU_setWIN1_H1(GPU* gpu, u8 val) { gpu->WIN1H1 = val; gpu->need_update_winh[1] = true; }
inline void GPU_setWIN1_V(GPU* gpu, u16 val) { gpu->WIN1V0 = val >> 8; gpu->WIN1V1 = val&0xFF; }
inline void GPU_setWIN1_V0(GPU* gpu, u8 val) { gpu->WIN1V0 = val; }
inline void GPU_setWIN1_V1(GPU* gpu, u8 val) { gpu->WIN1V1 = val; }
inline void GPU_setWININ(GPU* gpu, u16 val) {
gpu->WININ0=val&0x1F;
gpu->WININ0_SPECIAL=((val>>5)&1)!=0;
gpu->WININ1=(val>>8)&0x1F;
gpu->WININ1_SPECIAL=((val>>13)&1)!=0;
}
inline void GPU_setWININ0(GPU* gpu, u8 val) { gpu->WININ0 = val&0x1F; gpu->WININ0_SPECIAL = (val>>5)&1; }
inline void GPU_setWININ1(GPU* gpu, u8 val) { gpu->WININ1 = val&0x1F; gpu->WININ1_SPECIAL = (val>>5)&1; }
inline void GPU_setWINOUT16(GPU* gpu, u16 val) {
gpu->WINOUT=val&0x1F;
gpu->WINOUT_SPECIAL=((val>>5)&1)!=0;
gpu->WINOBJ=(val>>8)&0x1F;
gpu->WINOBJ_SPECIAL=((val>>13)&1)!=0;
}
inline void GPU_setWINOUT(GPU* gpu, u8 val) { gpu->WINOUT = val&0x1F; gpu->WINOUT_SPECIAL = (val>>5)&1; }
inline void GPU_setWINOBJ(GPU* gpu, u8 val) { gpu->WINOBJ = val&0x1F; gpu->WINOBJ_SPECIAL = (val>>5)&1; }
// Blending
void SetupFinalPixelBlitter (GPU *gpu);
#define GPU_setBLDCNT_LOW(gpu, val) {gpu->BLDCNT = (gpu->BLDCNT&0xFF00) | (val); SetupFinalPixelBlitter (gpu);}
#define GPU_setBLDCNT_HIGH(gpu, val) {gpu->BLDCNT = (gpu->BLDCNT&0xFF) | (val<<8); SetupFinalPixelBlitter (gpu);}
#define GPU_setBLDCNT(gpu, val) {gpu->BLDCNT = (val); SetupFinalPixelBlitter (gpu);}
#define GPU_setBLDY_EVY(gpu, val) {gpu->BLDY_EVY = ((val)&0x1f) > 16 ? 16 : ((val)&0x1f);}
//these arent needed right now since the values get poked into memory via default mmu handling and dispx_st
//#define GPU_setBGxHOFS(bg, gpu, val) gpu->dispx_st->dispx_BGxOFS[bg].BGxHOFS = ((val) & 0x1FF)
//#define GPU_setBGxVOFS(bg, gpu, val) gpu->dispx_st->dispx_BGxOFS[bg].BGxVOFS = ((val) & 0x1FF)
void gpu_SetRotateScreen(u16 angle);
//#undef FORCEINLINE
//#define FORCEINLINE __forceinline
#endif
+750
View File
@@ -0,0 +1,750 @@
/*
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/>.
*/
#include "GPU_osd.h"
#include "driver.h"
#include "GPU.h"
#include "mem.h"
#include <string.h> //mem funcs
#include <stdarg.h> //va_start, etc
#include <sstream>
#include <stdio.h>
#include <time.h>
#include <glib.h>
#include "debug.h"
#include "aggdraw.h"
#include "movie.h"
#include "rtc.h"
#include "NDSSystem.h"
#include "mic.h"
#include "saves.h"
bool HudEditorMode = false;
OSDCLASS *osd = NULL;
HudStruct Hud;
//contains a timer to be used for well-timed hud components
static s64 hudTimer;
static void SetHudDummy (HudCoordinates *hud)
{
hud->x=666;
hud->y=666;
}
static bool IsHudDummy (HudCoordinates *hud)
{
return (hud->x == 666 && hud->y == 666);
}
template<typename T>
static T calcY(T y) // alters a GUI element y coordinate as necessary to obey swapScreens and singleScreen settings
{
if(osd->singleScreen)
{
if(y >= 192)
y -= 192;
if(osd->swapScreens)
y += 192;
}
else if(osd->swapScreens)
{
if(y >= 192)
y -= 192;
else
y += 192;
}
return y;
}
void EditHud(s32 x, s32 y, HudStruct *hudstruct) {
u32 i = 0;
while (!IsHudDummy(&hudstruct->hud(i))) {
HudCoordinates &hud = hudstruct->hud(i);
//reset
if(!hud.clicked) {
hud.storedx=0;
hud.storedy=0;
}
if((x >= hud.x && x <= hud.x + hud.xsize) &&
(calcY(y) >= calcY(hud.y) && calcY(y) <= calcY(hud.y) + hud.ysize) && !hudstruct->clicked ) {
hud.clicked=1;
hud.storedx = x - hud.x;
hud.storedy = y - hud.y;
}
if(hud.clicked) {
hud.x = x - hud.storedx;
hud.y = y - hud.storedy;
}
//sanity checks
if(hud.x < 0) hud.x = 0;
if(hud.y < 0) hud.y = 0;
if(hud.x > 245)hud.x = 245; //margins
if(hud.y > 384-16)hud.y = 384-16;
if(hud.clicked)
{
hudstruct->clicked = true;
break;//prevent items from grouping together
}
i++;
}
}
void HudClickRelease(HudStruct *hudstruct) {
u32 i = 0;
while (!IsHudDummy(&hudstruct->hud(i))) {
HudCoordinates &hud = hudstruct->hud(i);
hud.clicked=0;
i++;
}
hudstruct->clicked = false;
}
void HudStruct::reset()
{
FpsDisplay.x=0;
FpsDisplay.y=5;
FpsDisplay.xsize=166;
FpsDisplay.ysize=10;
FrameCounter.x=0;
FrameCounter.y=25;
FrameCounter.xsize=60;
FrameCounter.ysize=10;
InputDisplay.x=0;
InputDisplay.y=45;
InputDisplay.xsize=220;
InputDisplay.ysize=10;
GraphicalInputDisplay.x=8;
GraphicalInputDisplay.y=328;
GraphicalInputDisplay.xsize=102;
GraphicalInputDisplay.ysize=50;
LagFrameCounter.x=0;
LagFrameCounter.y=65;
LagFrameCounter.xsize=30;
LagFrameCounter.ysize=10;
Microphone.x=0;
Microphone.y=85;
Microphone.xsize=20;
Microphone.ysize=10;
RTCDisplay.x=0;
RTCDisplay.y=105;
RTCDisplay.xsize=220;
RTCDisplay.ysize=10;
SavestateSlots.x = 8;
SavestateSlots.y = 160;
SavestateSlots.xsize = 240;
SavestateSlots.ysize = 24;
SetHudDummy(&Dummy);
clicked = false;
}
static void joyFill(int n) {
bool pressedForGame = NDS_getFinalUserInput().buttons.array[n];
bool physicallyPressed = NDS_getRawUserInput().buttons.array[n];
if(pressedForGame && physicallyPressed)
aggDraw.hud->fillColor(0,0,0,255);
else if(pressedForGame)
aggDraw.hud->fillColor(255,0,0,255);
else if(physicallyPressed)
aggDraw.hud->fillColor(0,255,0,255);
else
aggDraw.hud->fillColor(255,255,255,255);
}
static void joyEllipse(double ex, double ey, int xc, int yc, int x, int y, double ratio, double rad, int button) {
joyFill(button);
aggDraw.hud->lineWidth(rad);
aggDraw.hud->ellipse(x+((xc*ex)*ratio), y+((yc*ey)*ratio), rad*ratio, rad*ratio);
}
static void joyRoundedRect(double x1, double y1, int x2, int y2, int alpha1, int alpha2, int button)
{
bool pressedForGame = NDS_getFinalUserInput().buttons.array[button];
bool physicallyPressed = NDS_getRawUserInput().buttons.array[button];
if(pressedForGame && physicallyPressed)
aggDraw.hud->fillLinearGradient(x1,y1,x2,y2,agg::rgba8(0,0,0,alpha1), agg::rgba8(0,0,0,alpha2));
else if(pressedForGame)
aggDraw.hud->fillLinearGradient(x1,y1,x2,y2,agg::rgba8(255,0,0,alpha1), agg::rgba8(255,0,0,alpha2));
else if(physicallyPressed)
aggDraw.hud->fillLinearGradient(x1,y1,x2,y2,agg::rgba8(0,255,0,alpha1), agg::rgba8(0,255,0,alpha2));
else
return; //aggDraw.hud->fillLinearGradient(x1,y1,x2,y2,agg::rgba8(255,255,255,alpha1), agg::rgba8(255,255,255,alpha2));
aggDraw.hud->roundedRect(x1,y1,x2,y2,1);
}
static void drawPad(double x, double y, double ratio) {
// you might notice black/red/green colors used to show what buttons are pressed.
// the logic is roughly:
// RED == PAST (the button was held last frame)
// GREEN == FUTURE (the button is physically held now)
// BLACK == PRESENT (the button was held last frame and is still physically held now)
// aligning to odd half-pixel boundaries prevents agg2d from blurring thin straight lines
x = floor(x) + 0.5;
y = floor(calcY(y)) + 0.5;
double xc = 41 - 0.5;
double yc = 20 - 0.5;
aggDraw.hud->lineColor(128,128,128,255);
aggDraw.hud->fillLinearGradient(x, y, x+(xc*ratio), y+(yc*ratio), agg::rgba8(222,222,222,128), agg::rgba8(255,255,255,255));
aggDraw.hud->roundedRect (x, y, floor(x+(xc*ratio))+0.5, floor(y+(yc*ratio))+0.5, 1);
double screenLeft = x+(xc*.25*ratio);
double screenTop = y+(yc*.1*ratio);
double screenRight = x+(xc*.745*ratio);
double screenBottom = y+(yc*.845*ratio);
aggDraw.hud->fillLinearGradient(screenLeft, screenTop, screenRight, screenBottom, agg::rgba8(128,128,128,128), agg::rgba8(255,255,255,255));
aggDraw.hud->roundedRect (screenLeft, screenTop, screenRight, screenBottom, 1);
joyEllipse(.89,.45,xc,yc,x,y,ratio,1,6);//B
joyEllipse(.89,.22,xc,yc,x,y,ratio,1,3);//X
joyEllipse(.83,.34,xc,yc,x,y,ratio,1,4);//Y
joyEllipse(.95,.34,xc,yc,x,y,ratio,1,5);//A
joyEllipse(.82,.716,xc,yc,x,y,ratio,.5,7);//Start
joyEllipse(.82,.842,xc,yc,x,y,ratio,.5,8);//Select
double dpadPoints [][2] = {
{.04,.33}, // top-left corner of left button
{.08,.33},
{.08,.24}, // top-left corner of up button
{.13,.24}, // top-right corner of up button
{.13,.33},
{.17,.33}, // top-right corner of right button
{.17,.43}, // bottom-right corner of right button
{.13,.43},
{.13,.516}, // bottom-right corner of down button
{.08,.516}, // bottom-left corner of down button
{.08,.43},
{.04,.43}, // bottom-left corner of left button
};
static const int numdpadPoints = sizeof(dpadPoints)/sizeof(dpadPoints[0]);
for(int i = 0; i < numdpadPoints; i++)
{
dpadPoints[i][0] = x+(xc*(dpadPoints[i][0]+.01)*ratio);
dpadPoints[i][1] = y+(yc*(dpadPoints[i][1]+.00)*ratio);
}
// dpad outline
aggDraw.hud->fillColor(255,255,255,200);
aggDraw.hud->polygon((double*)dpadPoints, numdpadPoints);
aggDraw.hud->noLine();
// left
joyRoundedRect(dpadPoints[0][0], dpadPoints[0][1], dpadPoints[7][0], dpadPoints[7][1], 255, 0, 11);
// right
joyRoundedRect(dpadPoints[1][0], dpadPoints[1][1], dpadPoints[6][0], dpadPoints[6][1], 0, 255, 12);
// up
joyRoundedRect(dpadPoints[2][0], dpadPoints[2][1], dpadPoints[7][0], dpadPoints[7][1], 255, 0, 9);
// right
joyRoundedRect(dpadPoints[1][0], dpadPoints[1][1], dpadPoints[8][0], dpadPoints[8][1], 0, 255, 10);
// left shoulder
joyRoundedRect(x+(xc*.00*ratio), y+(yc*.00*ratio), x+(xc*.15*ratio), y+(yc*.07*ratio), 255, 200, 2);
// right shoulder
joyRoundedRect(x+(xc*.85*ratio), y+(yc*.00*ratio), x+(xc*1.0*ratio), y+(yc*.07*ratio), 200, 255, 1);
// lid...
joyRoundedRect(x+(xc*.4*ratio), y+(yc*.96*ratio), x+(xc*0.6*ratio), y+(yc*1.0*ratio), 200, 200, 13);
// touch pad
{
BOOL gameTouchOn = nds.isTouch;
double gameTouchX = screenLeft+1 + (nds.scr_touchX * 0.0625) * (screenRight - screenLeft - 2) / 256.0;
double gameTouchY = screenTop+1 + (nds.scr_touchY * 0.0625) * (screenBottom - screenTop - 2) / 192.0;
bool physicalTouchOn = NDS_getRawUserInput().touch.isTouch;
double physicalTouchX = screenLeft+1 + (NDS_getRawUserInput().touch.touchX * 0.0625) * (screenRight - screenLeft - 2) / 256.0;
double physicalTouchY = screenTop+1 + (NDS_getRawUserInput().touch.touchY * 0.0625) * (screenBottom - screenTop - 2) / 192.0;
if(gameTouchOn && physicalTouchOn && gameTouchX == physicalTouchX && gameTouchY == physicalTouchY)
{
aggDraw.hud->fillColor(0,0,0,255);
aggDraw.hud->ellipse(gameTouchX, gameTouchY, ratio*0.37, ratio*0.37);
}
else
{
if(physicalTouchOn)
{
aggDraw.hud->fillColor(0,0,0,128);
aggDraw.hud->ellipse(physicalTouchX, physicalTouchY, ratio*0.5, ratio*0.5);
aggDraw.hud->fillColor(0,255,0,255);
aggDraw.hud->ellipse(physicalTouchX, physicalTouchY, ratio*0.37, ratio*0.37);
}
if(gameTouchOn)
{
aggDraw.hud->fillColor(255,0,0,255);
aggDraw.hud->ellipse(gameTouchX, gameTouchY, ratio*0.37, ratio*0.37);
}
}
}
}
struct TouchInfo{
u16 X;
u16 Y;
};
static int touchalpha[8]= {31, 63, 95, 127, 159, 191, 223, 255};
static TouchInfo temptouch;
static const bool touchshadow = false;//true; // sorry, it's cool but also distracting and looks cleaner with it off. maybe if it drew line segments between touch points instead of isolated crosses...
static std::vector<TouchInfo> touch (8);
static void TextualInputDisplay() {
// drawing the whole string at once looks ugly
// (because of variable width font and the "shadow" appearing over blank space)
// and can't give us the color-coded effects we want anyway (see drawPad for info)
const UserButtons& gameButtons = NDS_getFinalUserInput().buttons;
const UserButtons& physicalButtons = NDS_getRawUserInput().buttons;
double x = Hud.InputDisplay.x;
// from order FRLDUTSBAYXWEG where G is 0
static const char* buttonChars = "<^>vABXYLRSsgf";
static const int buttonIndex [14] = {11,9,12,10,5,6,3,4,2,1,7,8,0,13};
for(int i = 0; i < 14; i++, x+=11.0)
{
bool pressedForGame = gameButtons.array[buttonIndex[i]];
bool physicallyPressed = physicalButtons.array[buttonIndex[i]];
if(pressedForGame && physicallyPressed)
aggDraw.hud->lineColor(255,255,255,255);
else if(pressedForGame)
aggDraw.hud->lineColor(255,48,48,255);
else if(physicallyPressed)
aggDraw.hud->lineColor(0,192,0,255);
else
continue;
// cast from char to std::string is a bit awkward
std::string str(buttonChars+i, 2);
str[1] = '\0';
aggDraw.hud->renderTextDropshadowed(x, calcY(Hud.InputDisplay.y), str);
}
// touch pad
{
char str [32];
BOOL gameTouchOn = nds.isTouch;
int gameTouchX = nds.adc_touchX >> 4;
int gameTouchY = nds.adc_touchY >> 4;
bool physicalTouchOn = NDS_getRawUserInput().touch.isTouch;
int physicalTouchX = NDS_getRawUserInput().touch.touchX >> 4;
int physicalTouchY = NDS_getRawUserInput().touch.touchY >> 4;
if(gameTouchOn && physicalTouchOn && gameTouchX == physicalTouchX && gameTouchY == physicalTouchY)
{
sprintf(str, "%d,%d", gameTouchX, gameTouchY);
aggDraw.hud->lineColor(255,255,255,255);
aggDraw.hud->renderTextDropshadowed(x, calcY(Hud.InputDisplay.y), str);
}
else
{
if(gameTouchOn)
{
sprintf(str, "%d,%d", gameTouchX, gameTouchY);
aggDraw.hud->lineColor(255,48,48,255);
aggDraw.hud->renderTextDropshadowed(x, calcY(Hud.InputDisplay.y)-(physicalTouchOn?8:0), str);
}
if(physicalTouchOn)
{
sprintf(str, "%d,%d", physicalTouchX, physicalTouchY);
aggDraw.hud->lineColor(0,192,0,255);
aggDraw.hud->renderTextDropshadowed(x, calcY(Hud.InputDisplay.y)+(gameTouchOn?8:0), str);
}
}
}
}
static void TouchDisplay() {
// note: calcY should not be used in this function.
aggDraw.hud->lineWidth(1.0);
temptouch.X = NDS_getRawUserInput().touch.touchX >> 4;
temptouch.Y = NDS_getRawUserInput().touch.touchY >> 4;
if(touchshadow) {
touch.push_back(temptouch);
if(touch.size() > 8) touch.erase(touch.begin());
for (int i = 0; i < 8; i++) {
temptouch = touch[i];
if(temptouch.X != 0 || temptouch.Y != 0) {
aggDraw.hud->lineColor(0, 255, 0, touchalpha[i]);
aggDraw.hud->line(temptouch.X - 256, temptouch.Y + 192, temptouch.X + 256, temptouch.Y + 192); //horiz
aggDraw.hud->line(temptouch.X, temptouch.Y - 256, temptouch.X, temptouch.Y + 384); //vert
aggDraw.hud->fillColor(0, 0, 0, touchalpha[i]);
aggDraw.hud->rectangle(temptouch.X-1, temptouch.Y + 192-1, temptouch.X+1, temptouch.Y + 192+1);
}
}
}
else
if(NDS_getRawUserInput().touch.isTouch) {
aggDraw.hud->lineColor(0, 255, 0, 128);
aggDraw.hud->line(temptouch.X - 256, temptouch.Y + 192, temptouch.X + 256, temptouch.Y + 192); //horiz
aggDraw.hud->line(temptouch.X, temptouch.Y - 256, temptouch.X, temptouch.Y + 384); //vert
}
if(nds.isTouch)
{
temptouch.X = nds.scr_touchX / 16;
temptouch.Y = nds.scr_touchY / 16;
aggDraw.hud->lineColor(255, 0, 0, 128);
aggDraw.hud->line(temptouch.X - 256, temptouch.Y + 192, temptouch.X + 256, temptouch.Y + 192); //horiz
aggDraw.hud->line(temptouch.X, temptouch.Y - 256, temptouch.X, temptouch.Y + 384); //vert
}
}
static int previousslot = 0;
static char number[10];
static s64 slotTimer=0;
static void DrawStateSlots(){
const int yloc = calcY(Hud.SavestateSlots.y); //160
const int xloc = Hud.SavestateSlots.x; //8
s64 fadecounter = 512 - (hudTimer-slotTimer)/4; //change constant to alter fade speed
if(fadecounter < 1) fadecounter = 0;
if(fadecounter>255) fadecounter = 255;
int alpha = (int)fadecounter;
if(HudEditorMode)
alpha = 255;
if(alpha!=0)
{
aggDraw.hud->lineWidth(1.0);
aggDraw.hud->lineColor(0, 0, 0, alpha);
aggDraw.hud->fillColor(255, 255, 255, alpha);
for ( int i = 0, xpos=0; i < 10; xpos=xpos+24) {
int yheight=0;
aggDraw.hud->fillLinearGradient(xloc + xpos, yloc - yheight, xloc + 22 + xpos, yloc + 20 + yheight+20, agg::rgba8(100,200,255,alpha), agg::rgba8(255,255,255,0));
if(lastSaveState == i) {
yheight = 5;
aggDraw.hud->fillLinearGradient(xloc + xpos, yloc - yheight, 22 + xloc + xpos, yloc + 20 + yheight+20, agg::rgba8(100,255,255,alpha), agg::rgba8(255,255,255,0));
}
aggDraw.hud->rectangle(xloc + xpos , yloc - yheight, xloc + 22 + xpos , yloc + 20 + yheight);
snprintf(number, 10, "%d", i);
aggDraw.hud->renderText(xloc + 1 + xpos + 4, yloc+4, std::string(number));
i++;
}
}
if(lastSaveState != previousslot)
slotTimer = hudTimer;
previousslot = lastSaveState;
}
static void DrawEditableElementIndicators()
{
u32 i = 0;
while (!IsHudDummy(&Hud.hud(i))) {
HudCoordinates &hud = Hud.hud(i);
aggDraw.hud->fillColor(0,0,0,0);
aggDraw.hud->lineColor(0,0,0,64);
aggDraw.hud->lineWidth(2.0);
aggDraw.hud->rectangle(hud.x,calcY(hud.y),hud.x+hud.xsize+1.0,calcY(hud.y)+hud.ysize+1.0);
aggDraw.hud->lineColor(255,hud.clicked?127:255,0,255);
aggDraw.hud->lineWidth(1.0);
aggDraw.hud->rectangle(hud.x-0.5,calcY(hud.y)-0.5,hud.x+hud.xsize+0.5,calcY(hud.y)+hud.ysize+0.5);
i++;
}
}
void DrawHUD()
{
GTimeVal time;
g_get_current_time(&time);
hudTimer = ((s64)time.tv_sec * 1000) + ((s64)time.tv_usec/1000);
if (HudEditorMode)
{
DrawEditableElementIndicators();
}
if (CommonSettings.hud.ShowInputDisplay)
{
TextualInputDisplay();
TouchDisplay();
}
if (CommonSettings.hud.FpsDisplay)
{
osd->addFixed(Hud.FpsDisplay.x, Hud.FpsDisplay.y, "Fps:%02d/%02d (%02d%%/%02d%%)%s", Hud.fps, Hud.fps3d, Hud.cpuload[0], Hud.cpuload[1], driver->EMU_IsEmulationPaused() ? " (paused)" : "");
}
if (CommonSettings.hud.FrameCounterDisplay)
{
if(movieMode == MOVIEMODE_RECORD)
osd->addFixed(Hud.FrameCounter.x, Hud.FrameCounter.y, "%d",currFrameCounter);
else if (movieMode == MOVIEMODE_PLAY)
osd->addFixed(Hud.FrameCounter.x, Hud.FrameCounter.y, "%d/%d",currFrameCounter,currMovieData.records.size());
else if (movieMode == MOVIEMODE_FINISHED)
osd->addFixed(Hud.FrameCounter.x, Hud.FrameCounter.y, "%d/%d (finished)",currFrameCounter,currMovieData.records.size());
else
osd->addFixed(Hud.FrameCounter.x, Hud.FrameCounter.y, "%d (no movie)",currFrameCounter);
}
if (CommonSettings.hud.ShowLagFrameCounter)
{
osd->addFixed(Hud.LagFrameCounter.x, Hud.LagFrameCounter.y, "%d",TotalLagFrames);
}
if (CommonSettings.hud.ShowGraphicalInputDisplay)
{
drawPad(Hud.GraphicalInputDisplay.x, Hud.GraphicalInputDisplay.y, 2.5);
}
#if defined(WIN32) && !defined(DESMUME_QT)
if (CommonSettings.hud.ShowMicrophone)
{
osd->addFixed(Hud.Microphone.x, Hud.Microphone.y, "%03d [%07d]",MicDisplay, Hud.cpuloopIterationCount);
}
#endif
if (CommonSettings.hud.ShowRTC)
{
DateTime tm = rtcGetTime();
static const char *wday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
osd->addFixed(Hud.RTCDisplay.x, Hud.RTCDisplay.y, "%04d-%03s-%02d %s %02d:%02d:%02d", tm.get_Year(), DateTime::GetNameOfMonth(tm.get_Month()), tm.get_Day(), wday[tm.get_DayOfWeek()%7], tm.get_Hour(), tm.get_Minute(), tm.get_Second());
}
DrawStateSlots();
}
OSDCLASS::OSDCLASS(u8 core)
{
memset(name,0,7);
mode=core;
offset=0;
lastLineText=0;
lineText_x = 5;
lineText_y = 120;
lineText_color = AggColor(255, 255, 255);
for (int i=0; i < OSD_MAX_LINES+1; i++)
{
lineText[i] = new char[1024];
memset(lineText[i], 0, 1024);
lineTimer[i] = 0;
lineColor[i] = lineText_color;
}
rotAngle = 0;
singleScreen = false;
swapScreens = false;
needUpdate = false;
if (core==0)
strcpy(name,"Core A");
else
if (core==1)
strcpy(name,"Core B");
else
{
strcpy(name,"Main");
mode=255;
}
//border(false);
LOG("OSD_Init (%s)\n",name);
}
OSDCLASS::~OSDCLASS()
{
LOG("OSD_Deinit (%s)\n",name);
for (int i=0; i < OSD_MAX_LINES+1; i++)
{
if (lineText[i])
delete [] lineText[i];
lineText[i] = NULL;
}
}
void OSDCLASS::setOffset(u16 ofs)
{
offset=ofs;
}
void OSDCLASS::setRotate(u16 angle)
{
rotAngle = angle;
}
void OSDCLASS::clear()
{
needUpdate=false;
}
bool OSDCLASS::checkTimers()
{
if (lastLineText == 0) return false;
time_t tmp_time = time(NULL);
for (int i=0; i < lastLineText; i++)
{
if (tmp_time > (lineTimer[i] + OSD_TIMER_SECS) )
{
if (i < lastLineText)
{
for (int j=i; j < lastLineText; j++)
{
strcpy(lineText[j], lineText[j+1]);
lineTimer[j] = lineTimer[j+1];
lineColor[j] = lineColor[j+1];
}
}
lineTimer[lastLineText] = 0;
lastLineText--;
if (lastLineText == 0) return false;
}
}
return true;
}
void OSDCLASS::update()
{
if ( (!needUpdate) && (!lastLineText) ) return; // don't update if buffer empty (speed up)
if (lastLineText)
{
if (checkTimers())
{
for (int i=0; i < lastLineText; i++)
{
aggDraw.hud->lineColor(lineColor[i]);
aggDraw.hud->renderTextDropshadowed(lineText_x,lineText_y+(i*16),lineText[i]);
}
}
else
{
if (!needUpdate) return;
}
}
}
void OSDCLASS::setListCoord(u16 x, u16 y)
{
lineText_x = x;
lineText_y = y;
}
void OSDCLASS::setLineColor(u8 r=255, u8 g=255, u8 b=255)
{
lineText_color = AggColor(r,g,b);
}
void OSDCLASS::addLine(const char *fmt, ...)
{
va_list list;
if (lastLineText > OSD_MAX_LINES) lastLineText = OSD_MAX_LINES;
if (lastLineText == OSD_MAX_LINES) // full
{
lastLineText--;
for (int j=0; j < lastLineText; j++)
{
strcpy(lineText[j], lineText[j+1]);
lineTimer[j] = lineTimer[j+1];
lineColor[j] = lineColor[j+1];
}
}
va_start(list,fmt);
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
_vsnprintf(lineText[lastLineText],1023,fmt,list);
#else
vsnprintf(lineText[lastLineText],1023,fmt,list);
#endif
va_end(list);
lineColor[lastLineText] = lineText_color;
lineTimer[lastLineText] = time(NULL);
needUpdate = true;
lastLineText++;
}
void OSDCLASS::addFixed(u16 x, u16 y, const char *fmt, ...)
{
va_list list;
char msg[1024];
va_start(list,fmt);
vsnprintf(msg,1023,fmt,list);
va_end(list);
aggDraw.hud->lineColor(255,255,255);
aggDraw.hud->renderTextDropshadowed(x,calcY(y),msg);
needUpdate = true;
}
void OSDCLASS::border(bool enabled)
{
//render51.setTextBoxBorder(enabled);
}
Executable
+141
View File
@@ -0,0 +1,141 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2008-2012 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_OSD_
#define __GPU_OSD_
#include "types.h"
#ifdef HAVE_LIBAGG
#include <stdlib.h>
#include <time.h>
#include "aggdraw.h"
#define OSD_MAX_LINES 4
#define OSD_TIMER_SECS 2
struct HudCoordinates{
int x;
int y;
int xsize;
int ysize;
int storedx;
int storedy;
int clicked;
};
struct HudStruct
{
public:
HudStruct()
{
resetTransient();
}
void resetTransient()
{
fps = 0;
fps3d = 0;
cpuload[0] = cpuload[1] = 0;
cpuloopIterationCount = 0;
clicked = false;
}
HudCoordinates SavestateSlots;
HudCoordinates FpsDisplay;
HudCoordinates FrameCounter;
HudCoordinates InputDisplay;
HudCoordinates GraphicalInputDisplay;
HudCoordinates LagFrameCounter;
HudCoordinates Microphone;
HudCoordinates RTCDisplay;
HudCoordinates Dummy;
HudCoordinates &hud(int i) { return ((HudCoordinates*)this)[i]; }
void reset();
int fps, fps3d, cpuload[2], cpuloopIterationCount;
bool clicked;
};
void EditHud(s32 x, s32 y, HudStruct *hudstruct);
void HudClickRelease(HudStruct *hudstruct);
void DrawHUD();
extern HudStruct Hud;
extern bool HudEditorMode;
class OSDCLASS
{
private:
u64 offset;
u8 mode;
u16 rotAngle;
u16 lineText_x;
u16 lineText_y;
AggColor lineText_color;
u8 lastLineText;
char *lineText[OSD_MAX_LINES+1];
time_t lineTimer[OSD_MAX_LINES+1];
AggColor lineColor[OSD_MAX_LINES+1];
bool needUpdate;
bool checkTimers();
public:
char name[7]; // for debuging
bool singleScreen;
bool swapScreens;
OSDCLASS(u8 core);
~OSDCLASS();
void setOffset(u16 ofs);
void setRotate(u16 angle);
void update();
void clear();
void setListCoord(u16 x, u16 y);
void setLineColor(u8 r, u8 b, u8 g);
void addLine(const char *fmt, ...);
void addFixed(u16 x, u16 y, const char *fmt, ...);
void border(bool enabled);
};
extern OSDCLASS *osd;
#else /* HAVE_LIBAGG */
void DrawHUD();
class OSDCLASS {
public:
OSDCLASS(u8 core);
~OSDCLASS();
void update();
void clear();
void setLineColor(u8 r, u8 b, u8 g);
void addLine(const char *fmt, ...);
};
extern OSDCLASS *osd;
#endif
#endif
+30
View File
@@ -0,0 +1,30 @@
/*
Copyright (C) 2010 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 "types.h"
#include "GPU_osd.h"
OSDCLASS *osd;
OSDCLASS::OSDCLASS(u8 core) {}
OSDCLASS::~OSDCLASS() {}
void OSDCLASS::update() {}
void OSDCLASS::clear() {}
void OSDCLASS::setLineColor(u8 r, u8 b, u8 g) {}
void OSDCLASS::addLine(const char *fmt, ...) {}
void DrawHUD() {}
Executable
+5751
View File
File diff suppressed because it is too large Load Diff
Executable
+963
View File
@@ -0,0 +1,963 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2007 shash
Copyright (C) 2007-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 MMU_H
#define MMU_H
#include "debug.h"
#include "firmware.h"
#include "mc.h"
#include "mem.h"
#ifdef HAVE_LUA
#include "lua-engine.h"
#endif
#ifdef HAVE_JIT
#include "arm_jit.h"
#endif
#define ARMCPU_ARM7 1
#define ARMCPU_ARM9 0
#define ARMPROC (PROCNUM ? NDS_ARM7:NDS_ARM9)
class EMUFILE;
typedef const u8 TWaitState;
enum EDMAMode
{
EDMAMode_Immediate = 0,
EDMAMode_VBlank = 1,
EDMAMode_HBlank = 2,
EDMAMode_HStart = 3,
EDMAMode_MemDisplay = 4,
EDMAMode_Card = 5,
EDMAMode_GBASlot = 6,
EDMAMode_GXFifo = 7,
EDMAMode7_Wifi = 8,
EDMAMode7_GBASlot = 9,
};
enum EDMABitWidth
{
EDMABitWidth_16 = 0,
EDMABitWidth_32 = 1
};
enum EDMASourceUpdate
{
EDMASourceUpdate_Increment = 0,
EDMASourceUpdate_Decrement = 1,
EDMASourceUpdate_Fixed = 2,
EDMASourceUpdate_Invalid = 3,
};
enum EDMADestinationUpdate
{
EDMADestinationUpdate_Increment = 0,
EDMADestinationUpdate_Decrement = 1,
EDMADestinationUpdate_Fixed = 2,
EDMADestinationUpdate_IncrementReload = 3,
};
//TODO
//n.b. this may be a bad idea, for complex registers like the dma control register.
//we need to know exactly what part was written to, instead of assuming all 32bits were written.
class TRegister_32
{
public:
virtual u32 read32() = 0;
virtual void write32(const u32 val) = 0;
void write(const int size, const u32 adr, const u32 val) {
if(size==32) write32(val);
else {
const u32 offset = adr&3;
if(size==8) {
printf("WARNING! 8BIT DMA ACCESS\n");
u32 mask = 0xFF<<(offset<<3);
write32((read32()&~mask)|(val<<(offset<<3)));
}
else if(size==16) {
u32 mask = 0xFFFF<<(offset<<3);
write32((read32()&~mask)|(val<<(offset<<3)));
}
}
}
u32 read(const int size, const u32 adr)
{
if(size==32) return read32();
else {
const u32 offset = adr&3;
if(size==8) { printf("WARNING! 8BIT DMA ACCESS\n"); return (read32()>>(offset<<3))&0xFF; }
else return (read32()>>(offset<<3))&0xFFFF;
}
}
};
struct TGXSTAT : public TRegister_32
{
TGXSTAT() {
gxfifo_irq = se = tr = tb = sb = 0;
fifo_empty = true;
fifo_low = false;
}
u8 tb; //test busy
u8 tr; //test result
u8 se; //stack error
u8 sb; //stack busy
u8 gxfifo_irq; //irq configuration
bool fifo_empty, fifo_low;
virtual u32 read32();
virtual void write32(const u32 val);
void savestate(EMUFILE *f);
bool loadstate(EMUFILE *f);
};
void triggerDma(EDMAMode mode);
class DivController
{
public:
DivController()
: mode(0), busy(0)
{}
void exec();
u8 mode, busy, div0;
u16 read16() { return mode|(busy<<15)|(div0<<14); }
void write16(u16 val) {
mode = val&3;
//todo - do we clear the div0 flag here or is that strictly done by the divider unit?
}
void savestate(EMUFILE* os);
bool loadstate(EMUFILE* is, int version);
};
class SqrtController
{
public:
SqrtController()
: mode(0), busy(0)
{}
void exec();
u8 mode, busy;
u16 read16() { return mode|(busy<<15); }
void write16(u16 val) { mode = val&1; }
void savestate(EMUFILE* os);
bool loadstate(EMUFILE* is, int version);
};
class DmaController
{
public:
u8 enable, irq, repeatMode, _startmode;
u8 userEnable;
u32 wordcount;
EDMAMode startmode;
EDMABitWidth bitWidth;
EDMASourceUpdate sar;
EDMADestinationUpdate dar;
u32 saddr, daddr;
u32 saddr_user, daddr_user;
//indicates whether the dma needs to be checked for triggering
BOOL dmaCheck;
//indicates whether the dma right now is logically running
//(though for now we copy all the data when it triggers)
BOOL running;
BOOL paused;
//this flag will sometimes be set when a start condition is triggered
//other conditions may be automatically triggered based on scanning conditions
BOOL triggered;
u64 nextEvent;
int procnum, chan;
void savestate(EMUFILE *f);
bool loadstate(EMUFILE *f);
void exec();
template<int PROCNUM> void doCopy();
void doPause();
void doStop();
void doSchedule();
void tryTrigger(EDMAMode mode);
DmaController() :
enable(0), irq(0), repeatMode(0), _startmode(0),
wordcount(0), startmode(EDMAMode_Immediate),
bitWidth(EDMABitWidth_16),
sar(EDMASourceUpdate_Increment), dar(EDMADestinationUpdate_Increment),
//if saddr isnt cleared then rings of fate will trigger copy protection
//by inspecting dma3 saddr when it boots
saddr(0), daddr(0),
saddr_user(0), daddr_user(0),
dmaCheck(FALSE),
running(FALSE),
paused(FALSE),
triggered(FALSE),
nextEvent(0),
sad(&saddr_user),
dad(&daddr_user)
{
sad.controller = this;
dad.controller = this;
ctrl.controller = this;
regs[0] = &sad;
regs[1] = &dad;
regs[2] = &ctrl;
}
class AddressRegister : public TRegister_32 {
public:
//we pass in a pointer to the controller here so we can alert it if anything changes
DmaController* controller;
u32 * const ptr;
AddressRegister(u32* _ptr)
: ptr(_ptr)
{}
virtual u32 read32() {
return *ptr;
}
virtual void write32(const u32 val) {
*ptr = val;
}
};
class ControlRegister : public TRegister_32 {
public:
//we pass in a pointer to the controller here so we can alert it if anything changes
DmaController* controller;
ControlRegister() {}
virtual u32 read32() {
return controller->read32();
}
virtual void write32(const u32 val) {
return controller->write32(val);
}
};
AddressRegister sad, dad;
ControlRegister ctrl;
TRegister_32* regs[3];
void write32(const u32 val);
u32 read32();
};
enum eCardMode
{
//when the GC system is first booted up, the protocol is in raw mode
eCardMode_RAW = 0,
//an intermediate stage during the protocol bootup process. commands are KEY1 encrypted.
eCardMode_KEY1,
//an intermediate stage during the protocol bootup process. commands are KEY1 encrypted, while replies are KEY2 encrypted
eCardMode_KEY2,
//the final stage of the protocol bootup process. "main data load" mode. commands are KEY2 encrypted, and replies are KEY2 encrypted.
//optionally, according to some flag we havent designed yet but should probably go in GCBUS_Controller, the whole KEY2 part can be bypassed
//(this is typical when skipping the firmware boot process)
eCardMode_NORMAL,
//help fix to 32bit
eCardMode_Pad = 0xFFFFFFFF
};
//#define GCLOG(...) printf(__VA_ARGS__);
#define GCLOG(...)
void MMU_GC_endTransfer(u32 PROCNUM);
struct GC_Command
{
u8 bytes[8];
void print();
void toCryptoBuffer(u32 buf[2]);
void fromCryptoBuffer(u32 buf[2]);
};
//should rather be known as GCBUS controller, or somesuch
struct GCBUS_Controller
{
int transfer_count;
eCardMode mode; //probably only one of these
};
#define DUP2(x) x, x
#define DUP4(x) x, x, x, x
#define DUP8(x) x, x, x, x, x, x, x, x
#define DUP16(x) x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x
struct MMU_struct
{
//ARM9 mem
u8 ARM9_ITCM[0x8000];
u8 ARM9_DTCM[0x4000];
//u8 MAIN_MEM[4*1024*1024]; //expanded from 4MB to 8MB to support debug consoles
//u8 MAIN_MEM[8*1024*1024]; //expanded from 8MB to 16MB to support dsi
u8 MAIN_MEM[16*1024*1024]; //expanded from 8MB to 16MB to support dsi
u8 ARM9_REG[0x1000000]; //this variable is evil and should be removed by correctly emulating all registers.
u8 ARM9_BIOS[0x8000];
u8 ARM9_VMEM[0x800];
#include "PACKED.h"
struct {
u8 ARM9_LCD[0xA4000];
//an extra 128KB for blank memory, directly after arm9_lcd, so that
//we can easily map things to the end of arm9_lcd to represent
//an unmapped state
u8 blank_memory[0x20000];
};
#include "PACKED_END.h"
u8 ARM9_OAM[0x800];
u8* ExtPal[2][4];
u8* ObjExtPal[2][2];
struct TextureInfo {
u8* texPalSlot[6];
u8* textureSlotAddr[4];
} texInfo;
//ARM7 mem
u8 ARM7_BIOS[0x4000];
u8 ARM7_ERAM[0x10000]; //64KB of exclusive WRAM
u8 ARM7_REG[0x10000];
u8 ARM7_WIRAM[0x10000]; //WIFI ram
// VRAM mapping
u8 VRAM_MAP[4][32];
u32 LCD_VRAM_ADDR[10];
u8 LCDCenable[10];
//32KB of shared WRAM - can be switched between ARM7 & ARM9 in two blocks
u8 SWIRAM[0x8000];
//Unused ram
u8 UNUSED_RAM[4];
//this is here so that we can trap glitchy emulator code
//which is accessing offsets 5,6,7 of unused ram due to unaligned accesses
//(also since the emulator doesn't prevent unaligned accesses)
u8 MORE_UNUSED_RAM[4];
static u8 * MMU_MEM[2][256];
static u32 MMU_MASK[2][256];
u8 ARM9_RW_MODE;
u32 DTCMRegion;
u32 ITCMRegion;
u16 timer[2][4];
s32 timerMODE[2][4];
u32 timerON[2][4];
u32 timerRUN[2][4];
u16 timerReload[2][4];
u32 reg_IME[2];
u32 reg_IE[2];
//these are the user-controlled IF bits. some IF bits are generated as necessary from hardware conditions
u32 reg_IF_bits[2];
//these flags are set occasionally to indicate that an irq should have entered the pipeline, and processing will be deferred a tiny bit to help emulate things
u32 reg_IF_pending[2];
u32 reg_DISP3DCNT_bits;
template<int PROCNUM> u32 gen_IF();
BOOL divRunning;
s64 divResult;
s64 divMod;
u64 divCycles;
BOOL sqrtRunning;
u32 sqrtResult;
u64 sqrtCycles;
u16 SPI_CNT;
u16 SPI_CMD;
u16 AUX_SPI_CNT;
//u16 AUX_SPI_CMD; //zero 20-aug-2013 - this seems pointless
u8 WRAMCNT;
u64 gfx3dCycles;
u8 powerMan_CntReg;
BOOL powerMan_CntRegWritten;
u8 powerMan_Reg[5];
fw_memory_chip fw;
GCBUS_Controller dscard[2];
};
//everything in here is derived from libnds behaviours. no hardware tests yet
class DSI_TSC
{
public:
DSI_TSC();
void reset_command();
u16 write16(u16 val);
bool save_state(EMUFILE* os);
bool load_state(EMUFILE* is);
private:
u16 read16();
u8 reg_selection;
u8 read_flag;
s32 state;
s32 readcount;
//registers[0] contains the current page.
//we are going to go ahead and save these out in case we want to change the way this is emulated in the future..
//we may want to poke registers in here at more convenient times and have the TSC dumbly pluck them out,
//rather than generate the values on the fly
u8 registers[0x80];
};
//this contains things which can't be memzeroed because they are smarter classes
struct MMU_struct_new
{
MMU_struct_new() ;
BackupDevice backupDevice;
DmaController dma[2][4];
TGXSTAT gxstat;
SqrtController sqrt;
DivController div;
DSI_TSC dsi_tsc;
void write_dma(const int proc, const int size, const u32 adr, const u32 val);
u32 read_dma(const int proc, const int size, const u32 adr);
bool is_dma(const u32 adr);
};
extern MMU_struct MMU;
extern MMU_struct_new MMU_new;
struct armcpu_memory_iface
{
/** the 32 bit instruction prefetch */
u32 FASTCALL (*prefetch32)( void *data, u32 adr);
/** the 16 bit instruction prefetch */
u16 FASTCALL (*prefetch16)( void *data, u32 adr);
/** read 8 bit data value */
u8 FASTCALL (*read8)( void *data, u32 adr);
/** read 16 bit data value */
u16 FASTCALL (*read16)( void *data, u32 adr);
/** read 32 bit data value */
u32 FASTCALL (*read32)( void *data, u32 adr);
/** write 8 bit data value */
void FASTCALL (*write8)( void *data, u32 adr, u8 val);
/** write 16 bit data value */
void FASTCALL (*write16)( void *data, u32 adr, u16 val);
/** write 32 bit data value */
void FASTCALL (*write32)( void *data, u32 adr, u32 val);
void *data;
};
void MMU_Init(void);
void MMU_DeInit(void);
void MMU_Reset( void);
void print_memory_profiling( void);
// Memory reading/writing (old)
u8 FASTCALL MMU_read8(u32 proc, u32 adr);
u16 FASTCALL MMU_read16(u32 proc, u32 adr);
u32 FASTCALL MMU_read32(u32 proc, u32 adr);
void FASTCALL MMU_write8(u32 proc, u32 adr, u8 val);
void FASTCALL MMU_write16(u32 proc, u32 adr, u16 val);
void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val);
//template<int PROCNUM> void FASTCALL MMU_doDMA(u32 num);
//The base ARM memory interfaces
extern const armcpu_memory_iface arm9_base_memory_iface;
extern const armcpu_memory_iface arm7_base_memory_iface;
extern const armcpu_memory_iface arm9_direct_memory_iface;
#define VRAM_BANKS 9
#define VRAM_BANK_A 0
#define VRAM_BANK_B 1
#define VRAM_BANK_C 2
#define VRAM_BANK_D 3
#define VRAM_BANK_E 4
#define VRAM_BANK_F 5
#define VRAM_BANK_G 6
#define VRAM_BANK_H 7
#define VRAM_BANK_I 8
#define VRAM_PAGE_ABG 0
#define VRAM_PAGE_BBG 128
#define VRAM_PAGE_AOBJ 256
#define VRAM_PAGE_BOBJ 384
struct VramConfiguration {
enum Purpose {
OFF, INVALID, ABG, BBG, AOBJ, BOBJ, LCDC, ARM7, TEX, TEXPAL, ABGEXTPAL, BBGEXTPAL, AOBJEXTPAL, BOBJEXTPAL
};
struct BankInfo {
Purpose purpose;
int ofs;
} banks[VRAM_BANKS];
inline void clear() {
for(int i=0;i<VRAM_BANKS;i++) {
banks[i].ofs = 0;
banks[i].purpose = OFF;
}
}
std::string describePurpose(Purpose p);
std::string describe();
};
extern VramConfiguration vramConfiguration;
#define VRAM_ARM9_PAGES 512
extern u8 vram_arm9_map[VRAM_ARM9_PAGES];
FORCEINLINE void* MMU_gpu_map(u32 vram_addr)
{
//this is supposed to map a single gpu vram address to emulator host memory
//but it returns a pointer to some zero memory in case of accesses to unmapped memory.
//this correctly handles the case with tile accesses to unmapped memory.
//it could also potentially go through a different LUT than vram_arm9_map in case we discover
//that it needs to be set up with different or no mirroring
//(I think it is a reasonable possibility that only the cpu has the nutty mirroring rules)
//
//if this system isn't used, Fantasy Aquarium displays garbage in the first ingame screen
//due to it storing 0x0F0F or somesuch in screen memory which points to a ridiculously big tile
//which should contain all 0 pixels
u32 vram_page = (vram_addr>>14)&(VRAM_ARM9_PAGES-1);
u32 ofs = vram_addr & 0x3FFF;
vram_page = vram_arm9_map[vram_page];
//blank pages are handled by the extra 16KB of blank memory at the end of ARM9_LCD
//and the fact that blank pages are mapped to appear at that location
return MMU.ARM9_LCD + (vram_page<<14) + ofs;
}
template<int PROCNUM, MMU_ACCESS_TYPE AT> u8 _MMU_read08(u32 addr);
template<int PROCNUM, MMU_ACCESS_TYPE AT> u16 _MMU_read16(u32 addr);
template<int PROCNUM, MMU_ACCESS_TYPE AT> u32 _MMU_read32(u32 addr);
template<int PROCNUM, MMU_ACCESS_TYPE AT> void _MMU_write08(u32 addr, u8 val);
template<int PROCNUM, MMU_ACCESS_TYPE AT> void _MMU_write16(u32 addr, u16 val);
template<int PROCNUM, MMU_ACCESS_TYPE AT> void _MMU_write32(u32 addr, u32 val);
template<int PROCNUM> FORCEINLINE u8 _MMU_read08(u32 addr) { return _MMU_read08<PROCNUM, MMU_AT_DATA>(addr); }
template<int PROCNUM> FORCEINLINE u16 _MMU_read16(u32 addr) { return _MMU_read16<PROCNUM, MMU_AT_DATA>(addr); }
template<int PROCNUM> FORCEINLINE u32 _MMU_read32(u32 addr) { return _MMU_read32<PROCNUM, MMU_AT_DATA>(addr); }
template<int PROCNUM> FORCEINLINE void _MMU_write08(u32 addr, u8 val) { _MMU_write08<PROCNUM, MMU_AT_DATA>(addr,val); }
template<int PROCNUM> FORCEINLINE void _MMU_write16(u32 addr, u16 val) { _MMU_write16<PROCNUM, MMU_AT_DATA>(addr,val); }
template<int PROCNUM> FORCEINLINE void _MMU_write32(u32 addr, u32 val) { _MMU_write32<PROCNUM, MMU_AT_DATA>(addr,val); }
void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val);
void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val);
void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val);
u8 FASTCALL _MMU_ARM9_read08(u32 adr);
u16 FASTCALL _MMU_ARM9_read16(u32 adr);
u32 FASTCALL _MMU_ARM9_read32(u32 adr);
void FASTCALL _MMU_ARM7_write08(u32 adr, u8 val);
void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val);
void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val);
u8 FASTCALL _MMU_ARM7_read08(u32 adr);
u16 FASTCALL _MMU_ARM7_read16(u32 adr);
u32 FASTCALL _MMU_ARM7_read32(u32 adr);
extern u32 partie;
extern u32 _MMU_MAIN_MEM_MASK;
extern u32 _MMU_MAIN_MEM_MASK16;
extern u32 _MMU_MAIN_MEM_MASK32;
void SetupMMU(bool debugConsole, bool dsi);
FORCEINLINE void CheckMemoryDebugEvent(EDEBUG_EVENT event, const MMU_ACCESS_TYPE type, const u32 procnum, const u32 addr, const u32 size, const u32 val)
{
//TODO - ugh work out a better prefetch event system
if(type == MMU_AT_CODE && event == DEBUG_EVENT_READ)
event = DEBUG_EVENT_EXECUTE;
if(CheckDebugEvent(event))
{
DebugEventData.memAccessType = type;
DebugEventData.procnum = procnum;
DebugEventData.addr = addr;
DebugEventData.size = size;
DebugEventData.val = val;
HandleDebugEvent(event);
}
}
//ALERT!!!!!!!!!!!!!!
//the following inline functions dont do the 0x0FFFFFFF mask.
//this may result in some unexpected behavior
FORCEINLINE u8 _MMU_read08(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr)
{
CheckMemoryDebugEvent(DEBUG_EVENT_READ,AT,PROCNUM,addr,8,0);
//special handling to un-protect the ARM7 bios during debug reading
if(PROCNUM == ARMCPU_ARM7 && AT == MMU_AT_DEBUG && addr<0x00004000)
{
return T1ReadByte(MMU.ARM7_BIOS, addr);
}
//special handling for DMA: read 0 from TCM
if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA)
{
if(addr<0x02000000) return 0; //itcm
if((addr&(~0x3FFF)) == MMU.DTCMRegion) return 0; //dtcm
}
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(addr, 1, /*FIXME*/ 0, LUAMEMHOOK_READ);
#endif
if(PROCNUM==ARMCPU_ARM9)
if((addr&(~0x3FFF)) == MMU.DTCMRegion)
{
//Returns data from DTCM (ARM9 only)
return T1ReadByte(MMU.ARM9_DTCM, addr & 0x3FFF);
}
if ( (addr & 0x0F000000) == 0x02000000)
return T1ReadByte( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK);
if(PROCNUM==ARMCPU_ARM9) return _MMU_ARM9_read08(addr);
else return _MMU_ARM7_read08(addr);
}
FORCEINLINE u16 _MMU_read16(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr)
{
CheckMemoryDebugEvent(DEBUG_EVENT_READ,AT,PROCNUM,addr,16,0);
//special handling to un-protect the ARM7 bios during debug reading
if(PROCNUM == ARMCPU_ARM7 && AT == MMU_AT_DEBUG && addr<0x00004000)
{
return T1ReadWord_guaranteedAligned(MMU.ARM7_BIOS, addr);
}
//special handling for DMA: read 0 from TCM
if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA)
{
if(addr<0x02000000) return 0; //itcm
if((addr&(~0x3FFF)) == MMU.DTCMRegion) return 0; //dtcm
}
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(addr, 2, /*FIXME*/ 0, LUAMEMHOOK_READ);
#endif
//special handling for execution from arm9, since we spend so much time in there
if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_CODE)
{
if ((addr & 0x0F000000) == 0x02000000)
return T1ReadWord_guaranteedAligned( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK16);
if(addr<0x02000000)
return T1ReadWord_guaranteedAligned(MMU.ARM9_ITCM, addr&0x7FFE);
goto dunno;
}
if(PROCNUM==ARMCPU_ARM9)
if((addr&(~0x3FFF)) == MMU.DTCMRegion)
{
//Returns data from DTCM (ARM9 only)
return T1ReadWord_guaranteedAligned(MMU.ARM9_DTCM, addr & 0x3FFE);
}
if ( (addr & 0x0F000000) == 0x02000000)
return T1ReadWord_guaranteedAligned( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK16);
dunno:
if(PROCNUM==ARMCPU_ARM9) return _MMU_ARM9_read16(addr);
else return _MMU_ARM7_read16(addr);
}
FORCEINLINE u32 _MMU_read32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr)
{
CheckMemoryDebugEvent(DEBUG_EVENT_READ,AT,PROCNUM,addr,32,0);
//special handling to un-protect the ARM7 bios during debug reading
if(PROCNUM == ARMCPU_ARM7 && AT == MMU_AT_DEBUG && addr<0x00004000)
{
return T1ReadLong_guaranteedAligned(MMU.ARM7_BIOS, addr);
}
//special handling for DMA: read 0 from TCM
if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA)
{
if(addr<0x02000000) return 0; //itcm
if((addr&(~0x3FFF)) == MMU.DTCMRegion) return 0; //dtcm
}
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(addr, 4, /*FIXME*/ 0, LUAMEMHOOK_READ);
#endif
//special handling for execution from arm9, since we spend so much time in there
if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_CODE)
{
if ( (addr & 0x0F000000) == 0x02000000)
return T1ReadLong_guaranteedAligned( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK32);
if(addr<0x02000000)
return T1ReadLong_guaranteedAligned(MMU.ARM9_ITCM, addr&0x7FFC);
//what happens when we execute from DTCM? nocash makes it look like we get 0xFFFFFFFF but i can't seem to verify it
//historically, desmume would fall through to its old memory map struct
//which would return unused memory (0)
//it seems the hardware returns 0 or something benign because in actuality 0xFFFFFFFF is an undefined opcode
//and we know our handling for that is solid
goto dunno;
}
//special handling for execution from arm7. try reading from main memory first
if(PROCNUM==ARMCPU_ARM7)
{
if ( (addr & 0x0F000000) == 0x02000000)
return T1ReadLong_guaranteedAligned( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK32);
}
//for other arm9 cases, we have to check from dtcm first because it is patched on top of the main memory range
if(PROCNUM==ARMCPU_ARM9)
{
if((addr&(~0x3FFF)) == MMU.DTCMRegion)
{
//Returns data from DTCM (ARM9 only)
return T1ReadLong_guaranteedAligned(MMU.ARM9_DTCM, addr & 0x3FFC);
}
if ( (addr & 0x0F000000) == 0x02000000)
return T1ReadLong_guaranteedAligned( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK32);
}
dunno:
if(PROCNUM==ARMCPU_ARM9) return _MMU_ARM9_read32(addr);
else return _MMU_ARM7_read32(addr);
}
FORCEINLINE void _MMU_write08(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u8 val)
{
CheckMemoryDebugEvent(DEBUG_EVENT_WRITE,AT,PROCNUM,addr,8,val);
//special handling for DMA: discard writes to TCM
if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA)
{
if(addr<0x02000000) return; //itcm
if((addr&(~0x3FFF)) == MMU.DTCMRegion) return; //dtcm
}
if(PROCNUM==ARMCPU_ARM9)
if((addr&(~0x3FFF)) == MMU.DTCMRegion)
{
T1WriteByte(MMU.ARM9_DTCM, addr & 0x3FFF, val);
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE);
#endif
return;
}
if ( (addr & 0x0F000000) == 0x02000000) {
#ifdef HAVE_JIT
JIT_COMPILED_FUNC_KNOWNBANK(addr, MAIN_MEM, _MMU_MAIN_MEM_MASK, 0) = 0;
#endif
T1WriteByte( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK, val);
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE);
#endif
return;
}
if(PROCNUM==ARMCPU_ARM9) _MMU_ARM9_write08(addr,val);
else _MMU_ARM7_write08(addr,val);
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE);
#endif
}
FORCEINLINE void _MMU_write16(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u16 val)
{
CheckMemoryDebugEvent(DEBUG_EVENT_WRITE,AT,PROCNUM,addr,16,val);
//special handling for DMA: discard writes to TCM
if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA)
{
if(addr<0x02000000) return; //itcm
if((addr&(~0x3FFF)) == MMU.DTCMRegion) return; //dtcm
}
if(PROCNUM==ARMCPU_ARM9)
if((addr&(~0x3FFF)) == MMU.DTCMRegion)
{
T1WriteWord(MMU.ARM9_DTCM, addr & 0x3FFE, val);
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(addr, 2, val, LUAMEMHOOK_WRITE);
#endif
return;
}
if ( (addr & 0x0F000000) == 0x02000000) {
#ifdef HAVE_JIT
JIT_COMPILED_FUNC_KNOWNBANK(addr, MAIN_MEM, _MMU_MAIN_MEM_MASK16, 0) = 0;
#endif
T1WriteWord( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK16, val);
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(addr, 2, val, LUAMEMHOOK_WRITE);
#endif
return;
}
if(PROCNUM==ARMCPU_ARM9) _MMU_ARM9_write16(addr,val);
else _MMU_ARM7_write16(addr,val);
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(addr, 2, val, LUAMEMHOOK_WRITE);
#endif
}
FORCEINLINE void _MMU_write32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u32 val)
{
CheckMemoryDebugEvent(DEBUG_EVENT_WRITE,AT,PROCNUM,addr,32,val);
//special handling for DMA: discard writes to TCM
if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA)
{
if(addr<0x02000000) return; //itcm
if((addr&(~0x3FFF)) == MMU.DTCMRegion) return; //dtcm
}
if(PROCNUM==ARMCPU_ARM9)
if((addr&(~0x3FFF)) == MMU.DTCMRegion)
{
T1WriteLong(MMU.ARM9_DTCM, addr & 0x3FFC, val);
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(addr, 4, val, LUAMEMHOOK_WRITE);
#endif
return;
}
if ( (addr & 0x0F000000) == 0x02000000) {
#ifdef HAVE_JIT
JIT_COMPILED_FUNC_KNOWNBANK(addr, MAIN_MEM, _MMU_MAIN_MEM_MASK32, 0) = 0;
JIT_COMPILED_FUNC_KNOWNBANK(addr, MAIN_MEM, _MMU_MAIN_MEM_MASK32, 1) = 0;
#endif
T1WriteLong( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK32, val);
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(addr, 4, val, LUAMEMHOOK_WRITE);
#endif
return;
}
if(PROCNUM==ARMCPU_ARM9) _MMU_ARM9_write32(addr,val);
else _MMU_ARM7_write32(addr,val);
#ifdef HAVE_LUA
CallRegisteredLuaMemHook(addr, 4, val, LUAMEMHOOK_WRITE);
#endif
}
//#ifdef MMU_ENABLE_ACL
// void FASTCALL MMU_write8_acl(u32 proc, u32 adr, u8 val);
// void FASTCALL MMU_write16_acl(u32 proc, u32 adr, u16 val);
// void FASTCALL MMU_write32_acl(u32 proc, u32 adr, u32 val);
// u8 FASTCALL MMU_read8_acl(u32 proc, u32 adr, u32 access);
// u16 FASTCALL MMU_read16_acl(u32 proc, u32 adr, u32 access);
// u32 FASTCALL MMU_read32_acl(u32 proc, u32 adr, u32 access);
//#else
// #define MMU_write8_acl(proc, adr, val) _MMU_write08<proc>(adr, val)
// #define MMU_write16_acl(proc, adr, val) _MMU_write16<proc>(adr, val)
// #define MMU_write32_acl(proc, adr, val) _MMU_write32<proc>(adr, val)
// #define MMU_read8_acl(proc,adr,access) _MMU_read08<proc>(adr)
// #define MMU_read16_acl(proc,adr,access) ((access==CP15_ACCESS_EXECUTE)?_MMU_read16<proc,MMU_AT_CODE>(adr):_MMU_read16<proc,MMU_AT_DATA>(adr))
// #define MMU_read32_acl(proc,adr,access) ((access==CP15_ACCESS_EXECUTE)?_MMU_read32<proc,MMU_AT_CODE>(adr):_MMU_read32<proc,MMU_AT_DATA>(adr))
//#endif
// Use this macros for reading/writing, so the GDB stub isn't broken
#ifdef GDB_STUB
#define READ32(a,b) cpu->mem_if->read32(a,(b) & 0xFFFFFFFC)
#define WRITE32(a,b,c) cpu->mem_if->write32(a,(b) & 0xFFFFFFFC,c)
#define READ16(a,b) cpu->mem_if->read16(a,(b) & 0xFFFFFFFE)
#define WRITE16(a,b,c) cpu->mem_if->write16(a,(b) & 0xFFFFFFFE,c)
#define READ8(a,b) cpu->mem_if->read8(a,b)
#define WRITE8(a,b,c) cpu->mem_if->write8(a,b,c)
#else
#define READ32(a,b) _MMU_read32<PROCNUM>((b) & 0xFFFFFFFC)
#define WRITE32(a,b,c) _MMU_write32<PROCNUM>((b) & 0xFFFFFFFC,c)
#define READ16(a,b) _MMU_read16<PROCNUM>((b) & 0xFFFFFFFE)
#define WRITE16(a,b,c) _MMU_write16<PROCNUM>((b) & 0xFFFFFFFE,c)
#define READ8(a,b) _MMU_read08<PROCNUM>(b)
#define WRITE8(a,b,c) _MMU_write08<PROCNUM>(b, c)
#endif
template<int PROCNUM, MMU_ACCESS_TYPE AT>
FORCEINLINE u8 _MMU_read08(u32 addr) { return _MMU_read08(PROCNUM, AT, addr); }
template<int PROCNUM, MMU_ACCESS_TYPE AT>
FORCEINLINE u16 _MMU_read16(u32 addr) { return _MMU_read16(PROCNUM, AT, addr); }
template<int PROCNUM, MMU_ACCESS_TYPE AT>
FORCEINLINE u32 _MMU_read32(u32 addr) { return _MMU_read32(PROCNUM, AT, addr); }
template<int PROCNUM, MMU_ACCESS_TYPE AT>
FORCEINLINE void _MMU_write08(u32 addr, u8 val) { _MMU_write08(PROCNUM, AT, addr, val); }
template<int PROCNUM, MMU_ACCESS_TYPE AT>
FORCEINLINE void _MMU_write16(u32 addr, u16 val) { _MMU_write16(PROCNUM, AT, addr, val); }
template<int PROCNUM, MMU_ACCESS_TYPE AT>
FORCEINLINE void _MMU_write32(u32 addr, u32 val) { _MMU_write32(PROCNUM, AT, addr, val); }
void FASTCALL MMU_DumpMemBlock(u8 proc, u32 address, u32 size, u8 *buffer);
#endif
+459
View File
@@ -0,0 +1,459 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2007 shash
Copyright (C) 2007-2011 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"
////////////////////////////////////////////////////////////////
// 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)
{
write32le(m_cacheCache, os);
for(int i = 0; i < NUMBLOCKS; i++)
{
for(int j = 0; j < ASSOCIATIVITY; j++)
write32le(m_blocks[i].tag[j],os);
write32le(m_blocks[i].nextWay,os);
}
}
bool loadstate(EMUFILE* is, int version)
{
read32le(&m_cacheCache, is);
for(int i = 0; i < NUMBLOCKS; i++)
{
for(int j = 0; j < ASSOCIATIVITY; j++)
read32le(&m_blocks[i].tag[j],is);
read32le(&m_blocks[i].nextWay,is);
}
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)(~0 << TAGSHIFT) };
enum { BLOCKMASK = ((u32)~0 >> (32 - TAGSHIFT)) & (u32)(~0 << 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)
{
write32le(m_lastAddress,os);
}
bool loadstate(EMUFILE* is, int version)
{
read32le(&m_lastAddress,is);
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
+206
View File
@@ -0,0 +1,206 @@
include $(top_srcdir)/src/desmume.mk
AM_CPPFLAGS += $(SDL_CFLAGS) $(GTHREAD_CFLAGS) $(X_CFLAGS) $(ALSA_CFLAGS) $(LIBAGG_CFLAGS) $(LIBSOUNDTOUCH_CFLAGS)
EXTRA_DIST = build.bat instruction_tabdef.inc thumb_tabdef.inc fs-linux.cpp fs-windows.cpp cocoa
if HAVE_GDB_STUB
SUBDIRS = . gdbstub $(UI_DIR)
else
SUBDIRS = . $(UI_DIR)
endif
DIST_SUBDIRS = . gdbstub cli gtk gtk-glade
noinst_LIBRARIES = libdesmume.a
libdesmume_a_SOURCES = \
armcpu.cpp armcpu.h \
arm_instructions.cpp \
agg2d.h agg2d.inl \
bios.cpp bios.h bits.h cp15.cpp cp15.h \
commandline.h commandline.cpp \
common.cpp common.h \
debug.cpp debug.h \
Disassembler.cpp Disassembler.h \
emufile.h emufile.cpp emufile_types.h encrypt.h encrypt.cpp FIFO.cpp FIFO.h \
firmware.cpp firmware.h GPU.cpp GPU.h \
fs.h \
GPU_osd.h \
instructions.h \
mem.h mc.cpp mc.h \
path.cpp path.h \
readwrite.cpp readwrite.h \
wifi.cpp wifi.h \
mic.h \
MMU.cpp MMU.h MMU_timing.h NDSSystem.cpp NDSSystem.h registers.h \
OGLRender.h OGLRender_3_2.h \
ROMReader.cpp ROMReader.h \
render3D.cpp render3D.h \
rtc.cpp rtc.h \
saves.cpp saves.h \
slot1.cpp slot1.h \
slot2.cpp slot2.h \
SPU.cpp SPU.h \
matrix.cpp matrix.h \
gfx3d.cpp gfx3d.h \
thumb_instructions.cpp types.h \
movie.cpp movie.h \
PACKED.h PACKED_END.h \
utils/advanscene.cpp utils/advanscene.h \
utils/datetime.cpp utils/datetime.h \
utils/ConvertUTF.c utils/ConvertUTF.h utils/guid.cpp utils/guid.h \
utils/emufat.cpp utils/emufat.h utils/emufat_types.h \
utils/fsnitro.cpp utils/fsnitro.h \
utils/md5.cpp utils/md5.h utils/valuearray.h utils/xstring.cpp utils/xstring.h \
utils/decrypt/crc.cpp utils/decrypt/crc.h utils/decrypt/decrypt.cpp \
utils/decrypt/decrypt.h utils/decrypt/header.cpp utils/decrypt/header.h \
utils/task.cpp utils/task.h \
utils/vfat.h utils/vfat.cpp \
utils/dlditool.cpp \
utils/libfat/bit_ops.h \
utils/libfat/cache.cpp \
utils/libfat/cache.h \
utils/libfat/common.h \
utils/libfat/directory.cpp \
utils/libfat/directory.h \
utils/libfat/disc.cpp \
utils/libfat/disc.h \
utils/libfat/disc_io.h \
utils/libfat/fat.h \
utils/libfat/fatdir.cpp \
utils/libfat/fatdir.h \
utils/libfat/fatfile.cpp \
utils/libfat/fatfile.h \
utils/libfat/filetime.cpp \
utils/libfat/filetime.h \
utils/libfat/file_allocation_table.cpp \
utils/libfat/file_allocation_table.h \
utils/libfat/libfat.cpp \
utils/libfat/libfat_pc.h \
utils/libfat/libfat_public_api.cpp \
utils/libfat/libfat_public_api.h \
utils/libfat/lock.cpp \
utils/libfat/lock.h \
utils/libfat/mem_allocate.h \
utils/libfat/partition.cpp \
utils/libfat/partition.h \
utils/tinyxml/tinystr.cpp \
utils/tinyxml/tinystr.h \
utils/tinyxml/tinyxml.cpp \
utils/tinyxml/tinyxml.h \
utils/tinyxml/tinyxmlerror.cpp \
utils/tinyxml/tinyxmlparser.cpp \
utils/glcorearb.h \
addons/slot2_auto.cpp addons/slot2_mpcf.cpp addons/slot2_paddle.cpp addons/slot2_gbagame.cpp addons/slot2_none.cpp addons/slot2_rumblepak.cpp addons/slot2_guitarGrip.cpp addons/slot2_expMemory.cpp addons/slot2_piano.cpp addons/slot2_passme.cpp addons/slot1_none.cpp addons/slot1_r4.cpp addons/slot1_retail_nand.cpp addons/slot1_retail_auto.cpp addons/slot1_retail_mcrom.cpp addons/slot1_retail_mcrom_debug.cpp addons/slot1comp_mc.cpp addons/slot1comp_mc.h addons/slot1comp_rom.h addons/slot1comp_rom.cpp addons/slot1comp_protocol.h addons/slot1comp_protocol.cpp \
cheatSystem.cpp cheatSystem.h \
texcache.cpp texcache.h rasterize.cpp rasterize.h \
metaspu/metaspu.cpp metaspu/metaspu.h \
filter/2xsai.cpp filter/bilinear.cpp filter/epx.cpp filter/filter.h \
filter/hq2x.cpp filter/hq2x.h filter/hq4x.cpp filter/hq4x.dat filter/hq4x.h \
filter/interp.h filter/lq2x.cpp filter/lq2x.h filter/scanline.cpp \
filter/videofilter.cpp filter/videofilter.h \
filter/xbrz.cpp filter/xbrz.h \
version.cpp version.h \
desmume_config.cpp desmume_config.h
if HAVE_JIT
libdesmume_a_SOURCES += \
arm_jit.cpp arm_jit.h instruction_attributes.h \
utils/AsmJit/AsmJit.h \
utils/AsmJit/Config.h \
utils/AsmJit/core.h \
utils/AsmJit/x86.h \
utils/AsmJit/core/apibegin.h \
utils/AsmJit/core/apiend.h \
utils/AsmJit/core/assembler.cpp \
utils/AsmJit/core/assembler.h \
utils/AsmJit/core/assert.cpp \
utils/AsmJit/core/assert.h \
utils/AsmJit/core/buffer.cpp \
utils/AsmJit/core/buffer.h \
utils/AsmJit/core/build.h \
utils/AsmJit/core/compiler.cpp \
utils/AsmJit/core/compiler.h \
utils/AsmJit/core/compilercontext.cpp \
utils/AsmJit/core/compilercontext.h \
utils/AsmJit/core/compilerfunc.cpp \
utils/AsmJit/core/compilerfunc.h \
utils/AsmJit/core/compileritem.cpp \
utils/AsmJit/core/compileritem.h \
utils/AsmJit/core/context.cpp \
utils/AsmJit/core/context.h \
utils/AsmJit/core/cpuinfo.cpp \
utils/AsmJit/core/cpuinfo.h \
utils/AsmJit/core/defs.cpp \
utils/AsmJit/core/defs.h \
utils/AsmJit/core/func.cpp \
utils/AsmJit/core/func.h \
utils/AsmJit/core/intutil.h \
utils/AsmJit/core/lock.h \
utils/AsmJit/core/logger.cpp \
utils/AsmJit/core/logger.h \
utils/AsmJit/core/memorymanager.cpp \
utils/AsmJit/core/memorymanager.h \
utils/AsmJit/core/memorymarker.cpp \
utils/AsmJit/core/memorymarker.h \
utils/AsmJit/core/operand.cpp \
utils/AsmJit/core/operand.h \
utils/AsmJit/core/podvector.h \
utils/AsmJit/core/stringbuilder.cpp \
utils/AsmJit/core/stringbuilder.h \
utils/AsmJit/core/stringutil.cpp \
utils/AsmJit/core/stringutil.h \
utils/AsmJit/core/virtualmemory.cpp \
utils/AsmJit/core/virtualmemory.h \
utils/AsmJit/core/zonememory.cpp \
utils/AsmJit/core/zonememory.h \
utils/AsmJit/x86/x86assembler.cpp \
utils/AsmJit/x86/x86assembler.h \
utils/AsmJit/x86/x86compiler.cpp \
utils/AsmJit/x86/x86compiler.h \
utils/AsmJit/x86/x86compilercontext.cpp \
utils/AsmJit/x86/x86compilercontext.h \
utils/AsmJit/x86/x86compilerfunc.cpp \
utils/AsmJit/x86/x86compilerfunc.h \
utils/AsmJit/x86/x86compileritem.cpp \
utils/AsmJit/x86/x86compileritem.h \
utils/AsmJit/x86/x86cpuinfo.cpp \
utils/AsmJit/x86/x86cpuinfo.h \
utils/AsmJit/x86/x86defs.cpp \
utils/AsmJit/x86/x86defs.h \
utils/AsmJit/x86/x86func.cpp \
utils/AsmJit/x86/x86func.h \
utils/AsmJit/x86/x86operand.cpp \
utils/AsmJit/x86/x86operand.h \
utils/AsmJit/x86/x86util.cpp \
utils/AsmJit/x86/x86util.h
endif
if HAVE_GL
libdesmume_a_SOURCES += OGLRender.cpp OGLRender_3_2.cpp
endif
if HAVE_OPENAL
libdesmume_a_SOURCES += mic_openal.cpp
else
if HAVE_ALSA
libdesmume_a_SOURCES += mic_alsa.cpp
else
libdesmume_a_SOURCES += mic.cpp
endif
endif
if HAVE_LIBSOUNDTOUCH
libdesmume_a_SOURCES += metaspu/SndOut.cpp metaspu/SndOut.h metaspu/Timestretcher.cpp
endif
if HAVE_LIBAGG
libdesmume_a_SOURCES += aggdraw.cpp aggdraw.h GPU_osd.cpp
else
libdesmume_a_SOURCES += GPU_osd_stub.cpp
endif
if HAVE_LUA
AM_CPPFLAGS += $(LUA_CFLAGS)
libdesmume_a_SOURCES += lua-engine.cpp
endif
if HAVE_GDB_STUB
libdesmume_a_SOURCES += gdbstub.h
endif
libdesmume_a_LIBADD = fs-$(desmume_arch).$(OBJEXT)
+2942
View File
File diff suppressed because it is too large Load Diff
+649
View File
@@ -0,0 +1,649 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2008-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 NDSSYSTEM_H
#define NDSSYSTEM_H
#include <string.h>
#include <string>
#include "types.h"
class BaseDriver;
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<int> 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 BaseDriver *driver;
extern CFIRMWARE *firmware;
#define DSGBA_LOADER_SIZE 512
enum
{
ROM_NDS = 0,
ROM_DSGBA
};
//#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();
void emu_halt();
extern u64 nds_timer;
void NDS_Reschedule();
void NDS_RescheduleGXFIFO(u32 cost);
void NDS_RescheduleDMA();
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_LIE = 0x63,
NDS_CONSOLE_TYPE_DSI = 0xFE
};
struct NDSSystem
{
s32 wifiCycle;
s32 cycles;
u64 timerCycle[2][4];
u32 VCount;
u32 old;
//raw adc touch coords for old NDS
u16 adc_touchX;
u16 adc_touchY;
s32 adc_jitterctr;
BOOL stylusJitter;
//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 pad;
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 isInVblank() const { return VCount >= 192; }
bool isIn3dVblank() const { return VCount >= 192 && VCount<215; }
};
/** /brief A touchscreen calibration point.
*/
struct NDS_fw_touchscreen_cal {
u16 adc_x;
u16 adc_y;
u8 screen_x;
u8 screen_y;
};
#define MAX_FW_NICKNAME_LENGTH 10
#define MAX_FW_MESSAGE_LENGTH 26
struct NDS_fw_config_data
{
NDS_CONSOLE_TYPE ds_type;
u8 fav_colour;
u8 birth_month;
u8 birth_day;
u16 nickname[MAX_FW_NICKNAME_LENGTH];
u8 nickname_len;
u16 message[MAX_FW_MESSAGE_LENGTH];
u8 message_len;
u8 language;
//touchscreen calibration
NDS_fw_touchscreen_cal touch_cal[2];
};
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
{
FILE *fROM;
u8 *romdata;
u32 romsize;
u32 cardSize;
u32 mask;
u32 crc;
u32 chipID;
u32 lastReadPos;
u32 romType;
u32 headerOffset;
char ROMserial[20];
char ROMname[20];
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),
romdata(NULL),
crc(0),
chipID(0x00000FC2),
romsize(0),
cardSize(0),
mask(0),
lastReadPos(0xFFFFFFFF),
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 loadROM(std::string fname, u32 type = ROM_NDS);
void closeROM();
u32 readROM(u32 pos);
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;
struct UserButtons : buttonstruct<bool>
{
};
struct UserTouch
{
u16 touchX;
u16 touchY;
bool isTouch;
};
struct UserMicrophone
{
u32 micButtonPressed;
};
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_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_Zelda_Shadow_Depth_Hack(0)
, GFX3D_Renderer_Multisample(false)
, GFX3D_TXTHack(false)
, jit_max_block_size(100)
, loadToMemory(false)
, UseExtBIOS(false)
, SWIFromBIOS(false)
, PatchSWI3(false)
, UseExtFirmware(false)
, UseExtFirmwareSettings(false)
, BootFromFirmware(false)
, DebugConsole(false)
, EnsataEmulation(false)
, cheatsDisable(false)
, rigorous_timing(false)
, advanced_timing(true)
, micMode(InternalNoise)
, spuInterpolationMode(1)
, manualBackupType(0)
, autodetectBackupMethod(0)
, spu_captureMuted(false)
, spu_advanced(false)
, StylusPressure(50)
, ConsoleType(NDS_CONSOLE_TYPE_FAT)
, StylusJitter(false)
, backupSave(false)
, SPU_sync_mode(0)
, SPU_sync_method(0)
{
strcpy(ARM9BIOS, "biosnds9.bin");
strcpy(ARM7BIOS, "biosnds7.bin");
strcpy(Firmware, "firmware.bin");
/* WIFI mode: adhoc = 0, infrastructure = 1 */
wifi.mode = 1;
wifi.infraBridgeAdapter = 0;
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_Zelda_Shadow_Depth_Hack;
bool GFX3D_Renderer_Multisample;
bool GFX3D_TXTHack;
bool loadToMemory;
bool UseExtBIOS;
char ARM9BIOS[256];
char ARM7BIOS[256];
bool SWIFromBIOS;
bool PatchSWI3;
bool UseExtFirmware;
bool UseExtFirmwareSettings;
char Firmware[256];
bool BootFromFirmware;
NDS_fw_config_data fw_config;
NDS_CONSOLE_TYPE ConsoleType;
bool DebugConsole;
bool EnsataEmulation;
bool cheatsDisable;
int num_cores;
bool single_core() { return num_cores==1; }
bool rigorous_timing;
int StylusPressure;
bool StylusJitter;
bool dispLayers[2][5];
FAST_ALIGN bool advanced_timing;
bool use_jit;
u32 jit_max_block_size;
struct _Wifi {
int mode;
int infraBridgeAdapter;
} wifi;
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;
void MovieSRAM();
void ClearAutoHold(void);
bool ValidateSlot2Access(u32 procnum, u32 demandSRAMSpeed, u32 demand1stROMSpeed, u32 demand2ndROMSpeed, int clockbits);
//MUSTANG
//extern ADVANsCEne advsc;
#endif
+2896
View File
File diff suppressed because it is too large Load Diff
+610
View File
@@ -0,0 +1,610 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 shash
Copyright (C) 2008-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 OGLRENDER_H
#define OGLRENDER_H
#include <queue>
#include <set>
#include <string>
#include "render3D.h"
#include "types.h"
#ifndef OGLRENDER_3_2_H
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <GL/gl.h>
#include <GL/glext.h>
#define OGLEXT(procPtr, func) procPtr func = NULL;
#define INITOGLEXT(procPtr, func) func = (procPtr)wglGetProcAddress(#func);
#define EXTERNOGLEXT(procPtr, func) extern procPtr func;
#elif defined(__APPLE__)
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
// Ignore dynamic linking on Apple OS
#define OGLEXT(procPtr, func)
#define INITOGLEXT(procPtr, func)
#define EXTERNOGLEXT(procPtr, func)
// We're not exactly committing to OpenGL 3.2 Core Profile just yet, so redefine APPLE
// extensions as a temporary measure.
#if defined(GL_APPLE_vertex_array_object) && !defined(GL_ARB_vertex_array_object)
#define glGenVertexArrays(n, ids) glGenVertexArraysAPPLE(n, ids)
#define glBindVertexArray(id) glBindVertexArrayAPPLE(id)
#define glDeleteVertexArrays(n, ids) glDeleteVertexArraysAPPLE(n, ids)
#endif
#else
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glx.h>
/* This is a workaround needed to compile against nvidia GL headers */
#ifndef GL_ALPHA_BLEND_EQUATION_ATI
#undef GL_VERSION_1_3
#endif
#define OGLEXT(procPtr, func) procPtr func = NULL;
#define INITOGLEXT(procPtr, func) func = (procPtr)glXGetProcAddress((const GLubyte *) #func);
#define EXTERNOGLEXT(procPtr, func) extern procPtr func;
#endif
// Check minimum OpenGL header version
#if !defined(GL_VERSION_2_1)
#if defined(GL_VERSION_2_0)
#warning Using OpenGL v2.0 headers with v2.1 overrides. Some features will be disabled.
#if !defined(GL_ARB_framebuffer_object)
// Overrides for GL_EXT_framebuffer_blit
#if !defined(GL_EXT_framebuffer_blit)
#define GL_READ_FRAMEBUFFER_EXT GL_FRAMEBUFFER_EXT
#define GL_DRAW_FRAMEBUFFER_EXT GL_FRAMEBUFFER_EXT
#define glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter)
#endif
// Overrides for GL_EXT_framebuffer_multisample
#if !defined(GL_EXT_framebuffer_multisample)
#define GL_MAX_SAMPLES_EXT 0
#define glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height)
#endif
// Overrides for GL_ARB_pixel_buffer_object
#if !defined(GL_PIXEL_PACK_BUFFER) && defined(GL_PIXEL_PACK_BUFFER_ARB)
#define GL_PIXEL_PACK_BUFFER GL_PIXEL_PACK_BUFFER_ARB
#endif
#endif
#else
#error OpenGL requires v2.1 headers or later.
#endif
#endif
// Textures
#if !defined(GLX_H)
EXTERNOGLEXT(PFNGLACTIVETEXTUREPROC, glActiveTexture) // Core in v1.3
EXTERNOGLEXT(PFNGLACTIVETEXTUREARBPROC, glActiveTextureARB)
#endif
// Blending
EXTERNOGLEXT(PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate) // Core in v1.4
EXTERNOGLEXT(PFNGLBLENDEQUATIONSEPARATEPROC, glBlendEquationSeparate) // Core in v2.0
EXTERNOGLEXT(PFNGLBLENDFUNCSEPARATEEXTPROC, glBlendFuncSeparateEXT)
EXTERNOGLEXT(PFNGLBLENDEQUATIONSEPARATEEXTPROC, glBlendEquationSeparateEXT)
// Shaders
EXTERNOGLEXT(PFNGLCREATESHADERPROC, glCreateShader) // Core in v2.0
EXTERNOGLEXT(PFNGLSHADERSOURCEPROC, glShaderSource) // Core in v2.0
EXTERNOGLEXT(PFNGLCOMPILESHADERPROC, glCompileShader) // Core in v2.0
EXTERNOGLEXT(PFNGLCREATEPROGRAMPROC, glCreateProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLATTACHSHADERPROC, glAttachShader) // Core in v2.0
EXTERNOGLEXT(PFNGLDETACHSHADERPROC, glDetachShader) // Core in v2.0
EXTERNOGLEXT(PFNGLLINKPROGRAMPROC, glLinkProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLUSEPROGRAMPROC, glUseProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETSHADERIVPROC, glGetShaderiv) // Core in v2.0
EXTERNOGLEXT(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog) // Core in v2.0
EXTERNOGLEXT(PFNGLDELETESHADERPROC, glDeleteShader) // Core in v2.0
EXTERNOGLEXT(PFNGLDELETEPROGRAMPROC, glDeleteProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETPROGRAMIVPROC, glGetProgramiv) // Core in v2.0
EXTERNOGLEXT(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog) // Core in v2.0
EXTERNOGLEXT(PFNGLVALIDATEPROGRAMPROC, glValidateProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1IPROC, glUniform1i) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1IVPROC, glUniform1iv) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1FPROC, glUniform1f) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM2FPROC, glUniform2f) // Core in v2.0
EXTERNOGLEXT(PFNGLDRAWBUFFERSPROC, glDrawBuffers) // Core in v2.0
// Generic vertex attributes
EXTERNOGLEXT(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation) // Core in v2.0
EXTERNOGLEXT(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray) // Core in v2.0
EXTERNOGLEXT(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray) // Core in v2.0
EXTERNOGLEXT(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer) // Core in v2.0
// VAO
EXTERNOGLEXT(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays)
EXTERNOGLEXT(PFNGLDELETEVERTEXARRAYSPROC, glDeleteVertexArrays)
EXTERNOGLEXT(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray)
// VBO and PBO
EXTERNOGLEXT(PFNGLGENBUFFERSARBPROC, glGenBuffersARB)
EXTERNOGLEXT(PFNGLDELETEBUFFERSARBPROC, glDeleteBuffersARB)
EXTERNOGLEXT(PFNGLBINDBUFFERARBPROC, glBindBufferARB)
EXTERNOGLEXT(PFNGLBUFFERDATAARBPROC, glBufferDataARB)
EXTERNOGLEXT(PFNGLBUFFERSUBDATAARBPROC, glBufferSubDataARB)
EXTERNOGLEXT(PFNGLMAPBUFFERARBPROC, glMapBufferARB)
EXTERNOGLEXT(PFNGLUNMAPBUFFERARBPROC, glUnmapBufferARB)
EXTERNOGLEXT(PFNGLGENBUFFERSPROC, glGenBuffers) // Core in v1.5
EXTERNOGLEXT(PFNGLDELETEBUFFERSPROC, glDeleteBuffers) // Core in v1.5
EXTERNOGLEXT(PFNGLBINDBUFFERPROC, glBindBuffer) // Core in v1.5
EXTERNOGLEXT(PFNGLBUFFERDATAPROC, glBufferData) // Core in v1.5
EXTERNOGLEXT(PFNGLBUFFERSUBDATAPROC, glBufferSubData) // Core in v1.5
EXTERNOGLEXT(PFNGLMAPBUFFERPROC, glMapBuffer) // Core in v1.5
EXTERNOGLEXT(PFNGLUNMAPBUFFERPROC, glUnmapBuffer) // Core in v1.5
// FBO
EXTERNOGLEXT(PFNGLGENFRAMEBUFFERSEXTPROC, glGenFramebuffersEXT)
EXTERNOGLEXT(PFNGLBINDFRAMEBUFFEREXTPROC, glBindFramebufferEXT)
EXTERNOGLEXT(PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC, glFramebufferRenderbufferEXT)
EXTERNOGLEXT(PFNGLFRAMEBUFFERTEXTURE2DEXTPROC, glFramebufferTexture2DEXT)
EXTERNOGLEXT(PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC, glCheckFramebufferStatusEXT)
EXTERNOGLEXT(PFNGLDELETEFRAMEBUFFERSEXTPROC, glDeleteFramebuffersEXT)
EXTERNOGLEXT(PFNGLBLITFRAMEBUFFEREXTPROC, glBlitFramebufferEXT)
// Multisampled FBO
EXTERNOGLEXT(PFNGLGENRENDERBUFFERSEXTPROC, glGenRenderbuffersEXT)
EXTERNOGLEXT(PFNGLBINDRENDERBUFFEREXTPROC, glBindRenderbufferEXT)
EXTERNOGLEXT(PFNGLRENDERBUFFERSTORAGEEXTPROC, glRenderbufferStorageEXT)
EXTERNOGLEXT(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC, glRenderbufferStorageMultisampleEXT)
EXTERNOGLEXT(PFNGLDELETERENDERBUFFERSEXTPROC, glDeleteRenderbuffersEXT)
#else // OGLRENDER_3_2_H
// Basic Functions
EXTERNOGLEXT(PFNGLGETSTRINGIPROC, glGetStringi) // Core in v3.0
// Textures
#if !defined(GLX_H)
EXTERNOGLEXT(PFNGLACTIVETEXTUREPROC, glActiveTexture) // Core in v1.3
#endif
// Blending
EXTERNOGLEXT(PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate) // Core in v1.4
EXTERNOGLEXT(PFNGLBLENDEQUATIONSEPARATEPROC, glBlendEquationSeparate) // Core in v2.0
// Shaders
EXTERNOGLEXT(PFNGLCREATESHADERPROC, glCreateShader) // Core in v2.0
EXTERNOGLEXT(PFNGLSHADERSOURCEPROC, glShaderSource) // Core in v2.0
EXTERNOGLEXT(PFNGLCOMPILESHADERPROC, glCompileShader) // Core in v2.0
EXTERNOGLEXT(PFNGLCREATEPROGRAMPROC, glCreateProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLATTACHSHADERPROC, glAttachShader) // Core in v2.0
EXTERNOGLEXT(PFNGLDETACHSHADERPROC, glDetachShader) // Core in v2.0
EXTERNOGLEXT(PFNGLLINKPROGRAMPROC, glLinkProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLUSEPROGRAMPROC, glUseProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETSHADERIVPROC, glGetShaderiv) // Core in v2.0
EXTERNOGLEXT(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog) // Core in v2.0
EXTERNOGLEXT(PFNGLDELETESHADERPROC, glDeleteShader) // Core in v2.0
EXTERNOGLEXT(PFNGLDELETEPROGRAMPROC, glDeleteProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETPROGRAMIVPROC, glGetProgramiv) // Core in v2.0
EXTERNOGLEXT(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog) // Core in v2.0
EXTERNOGLEXT(PFNGLVALIDATEPROGRAMPROC, glValidateProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1IPROC, glUniform1i) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1IVPROC, glUniform1iv) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1FPROC, glUniform1f) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM2FPROC, glUniform2f) // Core in v2.0
EXTERNOGLEXT(PFNGLDRAWBUFFERSPROC, glDrawBuffers) // Core in v2.0
// Generic vertex attributes
EXTERNOGLEXT(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation) // Core in v2.0
EXTERNOGLEXT(PFNGLBINDFRAGDATALOCATIONPROC, glBindFragDataLocation) // Core in v3.0
EXTERNOGLEXT(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray) // Core in v2.0
EXTERNOGLEXT(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray) // Core in v2.0
EXTERNOGLEXT(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer) // Core in v2.0
// VAO
EXTERNOGLEXT(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays) // Core in v3.0
EXTERNOGLEXT(PFNGLDELETEVERTEXARRAYSPROC, glDeleteVertexArrays) // Core in v3.0
EXTERNOGLEXT(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray) // Core in v3.0
// VBO and PBO
EXTERNOGLEXT(PFNGLGENBUFFERSPROC, glGenBuffers) // Core in v1.5
EXTERNOGLEXT(PFNGLDELETEBUFFERSPROC, glDeleteBuffers) // Core in v1.5
EXTERNOGLEXT(PFNGLBINDBUFFERPROC, glBindBuffer) // Core in v1.5
EXTERNOGLEXT(PFNGLBUFFERDATAPROC, glBufferData) // Core in v1.5
EXTERNOGLEXT(PFNGLBUFFERSUBDATAPROC, glBufferSubData) // Core in v1.5
EXTERNOGLEXT(PFNGLMAPBUFFERPROC, glMapBuffer) // Core in v1.5
EXTERNOGLEXT(PFNGLUNMAPBUFFERPROC, glUnmapBuffer) // Core in v1.5
// FBO
EXTERNOGLEXT(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers) // Core in v3.0
EXTERNOGLEXT(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer) // Core in v3.0
EXTERNOGLEXT(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer) // Core in v3.0
EXTERNOGLEXT(PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D) // Core in v3.0
EXTERNOGLEXT(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus) // Core in v3.0
EXTERNOGLEXT(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers) // Core in v3.0
EXTERNOGLEXT(PFNGLBLITFRAMEBUFFERPROC, glBlitFramebuffer) // Core in v3.0
EXTERNOGLEXT(PFNGLDRAWBUFFERSPROC, glDrawBuffers) // Core in v2.0
// Multisampled FBO
EXTERNOGLEXT(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers) // Core in v3.0
EXTERNOGLEXT(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer) // Core in v3.0
EXTERNOGLEXT(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage) // Core in v3.0
EXTERNOGLEXT(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC, glRenderbufferStorageMultisample) // Core in v3.0
EXTERNOGLEXT(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers) // Core in v3.0
#endif // OGLRENDER_3_2_H
// Define the minimum required OpenGL version for the driver to support
#define OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MAJOR 1
#define OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MINOR 2
#define OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_REVISION 0
#define OGLRENDER_MAX_MULTISAMPLES 16
#define OGLRENDER_VERT_INDEX_BUFFER_COUNT 131072
enum OGLVertexAttributeID
{
OGLVertexAttributeID_Position = 0,
OGLVertexAttributeID_TexCoord0 = 8,
OGLVertexAttributeID_Color = 3,
};
enum OGLTextureUnitID
{
// Main textures will always be on texture unit 0.
OGLTextureUnitID_ToonTable = 1,
OGLTextureUnitID_ClearImage
};
enum OGLErrorCode
{
OGLERROR_NOERR = RENDER3DERROR_NOERR,
OGLERROR_FEATURE_UNSUPPORTED,
OGLERROR_VBO_UNSUPPORTED,
OGLERROR_PBO_UNSUPPORTED,
OGLERROR_SHADER_UNSUPPORTED,
OGLERROR_VAO_UNSUPPORTED,
OGLERROR_FBO_UNSUPPORTED,
OGLERROR_MULTISAMPLED_FBO_UNSUPPORTED,
OGLERROR_VERTEX_SHADER_PROGRAM_LOAD_ERROR,
OGLERROR_FRAGMENT_SHADER_PROGRAM_LOAD_ERROR,
OGLERROR_SHADER_CREATE_ERROR,
OGLERROR_FBO_CREATE_ERROR
};
struct OGLRenderRef
{
// OpenGL Feature Support
GLint stateTexMirroredRepeat;
// VBO
GLuint vboVertexID;
GLuint iboIndexID;
// PBO
GLuint pboRenderDataID[2];
// FBO
GLuint texClearImageColorID;
GLuint texClearImageDepthStencilID;
GLuint rboFragColorID;
GLuint rboFragDepthStencilID;
GLuint rboMSFragColorID;
GLuint rboMSFragDepthStencilID;
GLuint fboClearImageID;
GLuint fboMSIntermediateRenderID;
GLuint fboRenderID;
GLuint selectedRenderingFBO;
// Shader states
GLuint vertexShaderID;
GLuint fragmentShaderID;
GLuint shaderProgram;
GLint uniformTexScale;
GLint uniformStateToonShadingMode;
GLint uniformStateEnableAlphaTest;
GLint uniformStateUseWDepth;
GLint uniformStateAlphaTestRef;
GLint uniformPolyMode;
GLint uniformPolyAlpha;
GLint uniformPolyID;
GLint uniformPolyEnableTexture;
GLuint texToonTableID;
// VAO
GLuint vaoMainStatesID;
// Textures
std::queue<GLuint> freeTextureIDs;
// Client-side Buffers
GLfloat *color4fBuffer;
CACHE_ALIGN GLushort vertIndexBuffer[OGLRENDER_VERT_INDEX_BUFFER_COUNT];
};
struct GFX3D_State;
struct VERTLIST;
struct POLYLIST;
struct INDEXLIST;
struct POLY;
class TexCacheItem;
class OpenGLRenderer;
extern GPU3DInterface gpu3Dgl;
extern GPU3DInterface gpu3DglOld;
extern GPU3DInterface gpu3Dgl_3_2;
//This is called by OGLRender whenever it initializes.
//Platforms, please be sure to set this up.
//return true if you successfully init.
extern bool (*oglrender_init)();
//This is called by OGLRender before it uses opengl.
//return true if youre OK with using opengl
extern bool (*oglrender_beginOpenGL)();
//This is called by OGLRender after it is done using opengl.
extern void (*oglrender_endOpenGL)();
// These functions need to be assigned by ports that support using an
// OpenGL 3.2 Core Profile context. The OGLRender_3_2.cpp file includes
// the corresponding functions to assign to each function pointer.
//
// If any of these functions are unassigned, then one of the legacy OpenGL
// renderers will be used instead.
extern void (*OGLLoadEntryPoints_3_2_Func)();
extern void (*OGLCreateRenderer_3_2_Func)(OpenGLRenderer **rendererPtr);
FORCEINLINE u32 BGRA8888_32_To_RGBA6665_32(const u32 srcPix);
FORCEINLINE u32 BGRA8888_32Rev_To_RGBA6665_32Rev(const u32 srcPix);
bool IsVersionSupported(unsigned int checkVersionMajor, unsigned int checkVersionMinor, unsigned int checkVersionRevision);
class OpenGLRenderer : public Render3D
{
private:
// Driver's OpenGL Version
unsigned int versionMajor;
unsigned int versionMinor;
unsigned int versionRevision;
protected:
// OpenGL-specific References
OGLRenderRef *ref;
// OpenGL Feature Support
bool isVBOSupported;
bool isPBOSupported;
bool isFBOSupported;
bool isMultisampledFBOSupported;
bool isShaderSupported;
bool isVAOSupported;
// Textures
TexCacheItem *currTexture;
CACHE_ALIGN u32 GPU_screen3D[2][GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT * sizeof(u32)];
bool gpuScreen3DHasNewData[2];
size_t doubleBufferIndex;
u8 clearImageStencilValue;
// OpenGL-specific methods
virtual Render3DError CreateVBOs() = 0;
virtual void DestroyVBOs() = 0;
virtual Render3DError CreatePBOs() = 0;
virtual void DestroyPBOs() = 0;
virtual Render3DError CreateFBOs() = 0;
virtual void DestroyFBOs() = 0;
virtual Render3DError CreateMultisampledFBO() = 0;
virtual void DestroyMultisampledFBO() = 0;
virtual Render3DError CreateShaders(const std::string *vertexShaderProgram, const std::string *fragmentShaderProgram) = 0;
virtual void DestroyShaders() = 0;
virtual Render3DError CreateVAOs() = 0;
virtual void DestroyVAOs() = 0;
virtual Render3DError InitTextures() = 0;
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet) = 0;
virtual Render3DError InitTables() = 0;
virtual Render3DError LoadShaderPrograms(std::string *outVertexShaderProgram, std::string *outFragmentShaderProgram) = 0;
virtual Render3DError SetupShaderIO() = 0;
virtual Render3DError CreateToonTable() = 0;
virtual Render3DError DestroyToonTable() = 0;
virtual Render3DError UploadToonTable(const u16 *toonTableBuffer) = 0;
virtual Render3DError UploadClearImage(const u16 *clearImageColor16Buffer, const u32 *clearImageDepthStencilBuffer) = 0;
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet) = 0;
virtual Render3DError ExpandFreeTextures() = 0;
virtual Render3DError SetupVertices(const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, GLushort *outIndexBuffer, size_t *outIndexCount) = 0;
virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount) = 0;
virtual Render3DError DisableVertexAttributes() = 0;
virtual Render3DError SelectRenderingFramebuffer() = 0;
virtual Render3DError DownsampleFBO() = 0;
virtual Render3DError ReadBackPixels() = 0;
// Base rendering methods
virtual Render3DError BeginRender(const GFX3D_State *renderState) = 0;
virtual Render3DError PreRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList) = 0;
virtual Render3DError DoRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList) = 0;
virtual Render3DError PostRender() = 0;
virtual Render3DError EndRender(const u64 frameCount) = 0;
virtual Render3DError UpdateClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthStencilBuffer) = 0;
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer) = 0;
virtual Render3DError ClearUsingImage() const = 0;
virtual Render3DError ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearStencil) const = 0;
virtual Render3DError SetupPolygon(const POLY *thePoly) = 0;
virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing) = 0;
virtual Render3DError SetupViewport(const u32 viewportValue) = 0;
public:
OpenGLRenderer();
virtual ~OpenGLRenderer() {};
virtual Render3DError InitExtensions() = 0;
virtual Render3DError Reset() = 0;
virtual Render3DError RenderFinish() = 0;
virtual Render3DError DeleteTexture(const TexCacheItem *item) = 0;
bool IsExtensionPresent(const std::set<std::string> *oglExtensionSet, const std::string extensionName) const;
bool ValidateShaderCompile(GLuint theShader) const;
bool ValidateShaderProgramLink(GLuint theProgram) const;
void GetVersion(unsigned int *major, unsigned int *minor, unsigned int *revision) const;
void SetVersion(unsigned int major, unsigned int minor, unsigned int revision);
void ConvertFramebuffer(const u32 *__restrict srcBuffer, u32 *dstBuffer);
};
class OpenGLRenderer_1_2 : public OpenGLRenderer
{
protected:
// OpenGL-specific methods
virtual Render3DError CreateVBOs();
virtual void DestroyVBOs();
virtual Render3DError CreatePBOs();
virtual void DestroyPBOs();
virtual Render3DError CreateFBOs();
virtual void DestroyFBOs();
virtual Render3DError CreateMultisampledFBO();
virtual void DestroyMultisampledFBO();
virtual Render3DError CreateShaders(const std::string *vertexShaderProgram, const std::string *fragmentShaderProgram);
virtual void DestroyShaders();
virtual Render3DError CreateVAOs();
virtual void DestroyVAOs();
virtual Render3DError InitTextures();
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet);
virtual Render3DError InitTables();
virtual Render3DError LoadShaderPrograms(std::string *outVertexShaderProgram, std::string *outFragmentShaderProgram);
virtual Render3DError SetupShaderIO();
virtual Render3DError CreateToonTable();
virtual Render3DError DestroyToonTable();
virtual Render3DError UploadToonTable(const u16 *toonTableBuffer);
virtual Render3DError UploadClearImage(const u16 *clearImageColor16Buffer, const u32 *clearImageDepthStencilBuffer);
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
virtual Render3DError ExpandFreeTextures();
virtual Render3DError SetupVertices(const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, GLushort *outIndexBuffer, size_t *outIndexCount);
virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount);
virtual Render3DError DisableVertexAttributes();
virtual Render3DError SelectRenderingFramebuffer();
virtual Render3DError DownsampleFBO();
virtual Render3DError ReadBackPixels();
// Base rendering methods
virtual Render3DError BeginRender(const GFX3D_State *renderState);
virtual Render3DError PreRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError DoRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError PostRender();
virtual Render3DError EndRender(const u64 frameCount);
virtual Render3DError UpdateClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthStencilBuffer);
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);
virtual Render3DError ClearUsingImage() const;
virtual Render3DError ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearStencil) const;
virtual Render3DError SetupPolygon(const POLY *thePoly);
virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing);
virtual Render3DError SetupViewport(const u32 viewportValue);
public:
OpenGLRenderer_1_2();
~OpenGLRenderer_1_2();
virtual Render3DError InitExtensions();
virtual Render3DError Reset();
virtual Render3DError RenderFinish();
virtual Render3DError DeleteTexture(const TexCacheItem *item);
};
class OpenGLRenderer_1_3 : public OpenGLRenderer_1_2
{
protected:
virtual Render3DError UploadToonTable(const u16 *toonTableBuffer);
virtual Render3DError UploadClearImage(const u16 *clearImageColor16Buffer, const u32 *clearImageDepthStencilBuffer);
};
class OpenGLRenderer_1_4 : public OpenGLRenderer_1_3
{
protected:
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet);
};
class OpenGLRenderer_1_5 : public OpenGLRenderer_1_4
{
protected:
virtual Render3DError CreateVBOs();
virtual void DestroyVBOs();
virtual Render3DError CreatePBOs();
virtual void DestroyPBOs();
virtual Render3DError CreateVAOs();
virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount);
virtual Render3DError DisableVertexAttributes();
virtual Render3DError ReadBackPixels();
public:
~OpenGLRenderer_1_5();
virtual Render3DError RenderFinish();
};
class OpenGLRenderer_2_0 : public OpenGLRenderer_1_5
{
protected:
virtual Render3DError InitExtensions();
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet);
virtual Render3DError SetupVertices(const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, GLushort *outIndexBuffer, size_t *outIndexCount);
virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount);
virtual Render3DError DisableVertexAttributes();
virtual Render3DError BeginRender(const GFX3D_State *renderState);
virtual Render3DError PreRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError SetupPolygon(const POLY *thePoly);
virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing);
};
class OpenGLRenderer_2_1 : public OpenGLRenderer_2_0
{
protected:
virtual Render3DError ReadBackPixels();
public:
virtual Render3DError RenderFinish();
};
#endif
+550
View File
@@ -0,0 +1,550 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 shash
Copyright (C) 2008-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 "OGLRender_3_2.h"
#include <stdlib.h>
#include <string.h>
#include "debug.h"
#include "gfx3d.h"
#include "NDSSystem.h"
#include "texcache.h"
//------------------------------------------------------------
// Basic Functions
OGLEXT(PFNGLGETSTRINGIPROC, glGetStringi) // Core in v3.0
// Shaders
OGLEXT(PFNGLBINDFRAGDATALOCATIONPROC, glBindFragDataLocation) // Core in v3.0
// FBO
OGLEXT(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers) // Core in v3.0
OGLEXT(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer) // Core in v3.0
OGLEXT(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer) // Core in v3.0
OGLEXT(PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D) // Core in v3.0
OGLEXT(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus) // Core in v3.0
OGLEXT(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers) // Core in v3.0
OGLEXT(PFNGLBLITFRAMEBUFFERPROC, glBlitFramebuffer) // Core in v3.0
OGLEXT(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers) // Core in v3.0
OGLEXT(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer) // Core in v3.0
OGLEXT(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage) // Core in v3.0
OGLEXT(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC, glRenderbufferStorageMultisample) // Core in v3.0
OGLEXT(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers) // Core in v3.0
void OGLLoadEntryPoints_3_2()
{
// Basic Functions
INITOGLEXT(PFNGLGETSTRINGIPROC, glGetStringi)
// Shaders
INITOGLEXT(PFNGLBINDFRAGDATALOCATIONPROC, glBindFragDataLocation)
// FBO
INITOGLEXT(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers) // Promote to core version
INITOGLEXT(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer) // Promote to core version
INITOGLEXT(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer) // Promote to core version
INITOGLEXT(PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D) // Promote to core version
INITOGLEXT(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus) // Promote to core version
INITOGLEXT(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers) // Promote to core version
INITOGLEXT(PFNGLBLITFRAMEBUFFERPROC, glBlitFramebuffer) // Promote to core version
INITOGLEXT(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers) // Promote to core version
INITOGLEXT(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer) // Promote to core version
INITOGLEXT(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage) // Promote to core version
INITOGLEXT(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC, glRenderbufferStorageMultisample) // Promote to core version
INITOGLEXT(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers) // Promote to core version
}
// Vertex Shader GLSL 1.50
static const char *vertexShader_150 = {"\
#version 150 \n\
\n\
in vec4 inPosition; \n\
in vec2 inTexCoord0; \n\
in vec3 inColor; \n\
\n\
uniform float polyAlpha; \n\
uniform vec2 texScale; \n\
\n\
out vec4 vtxPosition; \n\
out vec2 vtxTexCoord; \n\
out vec4 vtxColor; \n\
\n\
void main() \n\
{ \n\
mat2 texScaleMtx = mat2( vec2(texScale.x, 0.0), \n\
vec2( 0.0, texScale.y)); \n\
\n\
vtxPosition = inPosition; \n\
vtxTexCoord = texScaleMtx * inTexCoord0; \n\
vtxColor = vec4(inColor * 4.0, polyAlpha); \n\
\n\
gl_Position = vtxPosition; \n\
} \n\
"};
// Fragment Shader GLSL 1.50
static const char *fragmentShader_150 = {"\
#version 150 \n\
\n\
in vec4 vtxPosition; \n\
in vec2 vtxTexCoord; \n\
in vec4 vtxColor; \n\
\n\
uniform sampler2D texMainRender; \n\
uniform sampler1D texToonTable; \n\
\n\
uniform int stateToonShadingMode; \n\
uniform bool stateEnableAlphaTest; \n\
uniform bool stateUseWDepth; \n\
uniform float stateAlphaTestRef; \n\
\n\
uniform int polyMode; \n\
uniform int polyID; \n\
\n\
uniform bool polyEnableTexture; \n\
\n\
out vec4 outFragColor; \n\
\n\
void main() \n\
{ \n\
vec4 mainTexColor = (polyEnableTexture) ? texture(texMainRender, vtxTexCoord) : vec4(1.0, 1.0, 1.0, 1.0); \n\
vec4 tempFragColor = mainTexColor; \n\
\n\
if(polyMode == 0) \n\
{ \n\
tempFragColor = vtxColor * mainTexColor; \n\
} \n\
else if(polyMode == 1) \n\
{ \n\
tempFragColor.rgb = (polyEnableTexture) ? (mainTexColor.rgb * mainTexColor.a) + (vtxColor.rgb * (1.0 - mainTexColor.a)) : vtxColor.rgb; \n\
tempFragColor.a = vtxColor.a; \n\
} \n\
else if(polyMode == 2) \n\
{ \n\
vec3 toonColor = vec3(texture(texToonTable, vtxColor.r).rgb); \n\
tempFragColor.rgb = (stateToonShadingMode == 0) ? mainTexColor.rgb * toonColor.rgb : min((mainTexColor.rgb * vtxColor.rgb) + toonColor.rgb, 1.0); \n\
tempFragColor.a = mainTexColor.a * vtxColor.a; \n\
} \n\
else if(polyMode == 3) \n\
{ \n\
if (polyID != 0) \n\
{ \n\
tempFragColor = vtxColor; \n\
} \n\
} \n\
\n\
if (tempFragColor.a == 0.0 || (stateEnableAlphaTest && tempFragColor.a < stateAlphaTestRef)) \n\
{ \n\
discard; \n\
} \n\
\n\
float vertW = (vtxPosition.w == 0.0) ? 0.00000001 : vtxPosition.w; \n\
gl_FragDepth = (stateUseWDepth) ? vtxPosition.w/4096.0 : clamp((vtxPosition.z/vertW) * 0.5 + 0.5, 0.0, 1.0); \n\
outFragColor = tempFragColor; \n\
} \n\
"};
void OGLCreateRenderer_3_2(OpenGLRenderer **rendererPtr)
{
if (IsVersionSupported(3, 2, 0))
{
*rendererPtr = new OpenGLRenderer_3_2;
(*rendererPtr)->SetVersion(3, 2, 0);
}
}
OpenGLRenderer_3_2::~OpenGLRenderer_3_2()
{
glFinish();
DestroyVAOs();
DestroyFBOs();
DestroyMultisampledFBO();
}
Render3DError OpenGLRenderer_3_2::InitExtensions()
{
Render3DError error = OGLERROR_NOERR;
OGLRenderRef &OGLRef = *this->ref;
// Get OpenGL extensions
std::set<std::string> oglExtensionSet;
this->GetExtensionSet(&oglExtensionSet);
// Initialize OpenGL
this->InitTables();
// Load and create shaders. Return on any error, since v3.2 Core Profile makes shaders mandatory.
this->isShaderSupported = true;
std::string vertexShaderProgram;
std::string fragmentShaderProgram;
error = this->LoadShaderPrograms(&vertexShaderProgram, &fragmentShaderProgram);
if (error != OGLERROR_NOERR)
{
this->isShaderSupported = false;
return error;
}
error = this->CreateShaders(&vertexShaderProgram, &fragmentShaderProgram);
if (error != OGLERROR_NOERR)
{
this->isShaderSupported = false;
return error;
}
this->CreateToonTable();
this->isVBOSupported = true;
this->CreateVBOs();
this->isPBOSupported = true;
this->CreatePBOs();
this->isVAOSupported = true;
this->CreateVAOs();
// Load and create FBOs. Return on any error, since v3.2 Core Profile makes FBOs mandatory.
this->isFBOSupported = true;
error = this->CreateFBOs();
if (error != OGLERROR_NOERR)
{
OGLRef.fboRenderID = 0;
this->isFBOSupported = false;
return error;
}
this->isMultisampledFBOSupported = true;
error = this->CreateMultisampledFBO();
if (error != OGLERROR_NOERR)
{
OGLRef.selectedRenderingFBO = 0;
this->isMultisampledFBOSupported = false;
if (error == OGLERROR_FBO_CREATE_ERROR)
{
// Return on OGLERROR_FBO_CREATE_ERROR, since a v3.0 driver should be able to
// support FBOs.
return error;
}
}
this->InitTextures();
this->InitFinalRenderStates(&oglExtensionSet); // This must be done last
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::CreateFBOs()
{
OGLRenderRef &OGLRef = *this->ref;
// Set up FBO render targets
glGenTextures(1, &OGLRef.texClearImageColorID);
glGenTextures(1, &OGLRef.texClearImageDepthStencilID);
glBindTexture(GL_TEXTURE_2D, OGLRef.texClearImageColorID);
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_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glBindTexture(GL_TEXTURE_2D, OGLRef.texClearImageDepthStencilID);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
// Set up FBOs
glGenFramebuffers(1, &OGLRef.fboClearImageID);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboClearImageID);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OGLRef.texClearImageColorID, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, OGLRef.texClearImageDepthStencilID, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
INFO("OpenGL: Failed to created FBOs. Some emulation features will be disabled.\n");
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &OGLRef.fboClearImageID);
glDeleteTextures(1, &OGLRef.texClearImageColorID);
glDeleteTextures(1, &OGLRef.texClearImageDepthStencilID);
return OGLERROR_FBO_CREATE_ERROR;
}
// Set up final output FBO
glGenRenderbuffers(1, &OGLRef.rboFragColorID);
glGenRenderbuffers(1, &OGLRef.rboFragDepthStencilID);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboFragColorID);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboFragDepthStencilID);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT);
glGenFramebuffers(1, &OGLRef.fboRenderID);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, OGLRef.rboFragColorID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, OGLRef.rboFragDepthStencilID);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
INFO("OpenGL: Failed to created FBOs. Some emulation features will be disabled.\n");
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &OGLRef.fboClearImageID);
glDeleteTextures(1, &OGLRef.texClearImageColorID);
glDeleteTextures(1, &OGLRef.texClearImageDepthStencilID);
glDeleteFramebuffers(1, &OGLRef.fboRenderID);
glDeleteRenderbuffers(1, &OGLRef.rboFragColorID);
glDeleteRenderbuffers(1, &OGLRef.rboFragDepthStencilID);
OGLRef.fboRenderID = 0;
return OGLERROR_FBO_CREATE_ERROR;
}
glReadBuffer(GL_COLOR_ATTACHMENT0);
INFO("OpenGL: Successfully created FBOs.\n");
return OGLERROR_NOERR;
}
void OpenGLRenderer_3_2::DestroyFBOs()
{
if (!this->isFBOSupported)
{
return;
}
OGLRenderRef &OGLRef = *this->ref;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &OGLRef.fboClearImageID);
glDeleteTextures(1, &OGLRef.texClearImageColorID);
glDeleteTextures(1, &OGLRef.texClearImageDepthStencilID);
glDeleteFramebuffers(1, &OGLRef.fboRenderID);
glDeleteRenderbuffers(1, &OGLRef.rboFragColorID);
glDeleteRenderbuffers(1, &OGLRef.rboFragDepthStencilID);
this->isFBOSupported = false;
}
Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO()
{
// Check the maximum number of samples that the GPU supports and use that.
// Since our target resolution is only 256x192 pixels, using the most samples
// possible is the best thing to do.
GLint maxSamples = 0;
glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
if (maxSamples < 2)
{
INFO("OpenGL: GPU does not support at least 2x multisampled FBOs. Multisample antialiasing will be disabled.\n");
return OGLERROR_FEATURE_UNSUPPORTED;
}
else if (maxSamples > OGLRENDER_MAX_MULTISAMPLES)
{
maxSamples = OGLRENDER_MAX_MULTISAMPLES;
}
OGLRenderRef &OGLRef = *this->ref;
// Set up FBO render targets
glGenRenderbuffers(1, &OGLRef.rboMSFragColorID);
glGenRenderbuffers(1, &OGLRef.rboMSFragDepthStencilID);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSFragColorID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSFragDepthStencilID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_DEPTH24_STENCIL8, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT);
// Set up multisampled rendering FBO
glGenFramebuffers(1, &OGLRef.fboMSIntermediateRenderID);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, OGLRef.rboMSFragColorID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, OGLRef.rboMSFragDepthStencilID);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &OGLRef.fboMSIntermediateRenderID);
glDeleteRenderbuffers(1, &OGLRef.rboMSFragColorID);
glDeleteRenderbuffers(1, &OGLRef.rboMSFragDepthStencilID);
INFO("OpenGL: Failed to create multisampled FBO. Multisample antialiasing will be disabled.\n");
return OGLERROR_FBO_CREATE_ERROR;
}
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID);
INFO("OpenGL: Successfully created multisampled FBO.\n");
return OGLERROR_NOERR;
}
void OpenGLRenderer_3_2::DestroyMultisampledFBO()
{
if (!this->isMultisampledFBOSupported)
{
return;
}
OGLRenderRef &OGLRef = *this->ref;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &OGLRef.fboMSIntermediateRenderID);
glDeleteRenderbuffers(1, &OGLRef.rboMSFragColorID);
glDeleteRenderbuffers(1, &OGLRef.rboMSFragDepthStencilID);
this->isMultisampledFBOSupported = false;
}
Render3DError OpenGLRenderer_3_2::CreateVAOs()
{
OGLRenderRef &OGLRef = *this->ref;
glGenVertexArrays(1, &OGLRef.vaoMainStatesID);
glBindVertexArray(OGLRef.vaoMainStatesID);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboVertexID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboIndexID);
glEnableVertexAttribArray(OGLVertexAttributeID_Position);
glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
glEnableVertexAttribArray(OGLVertexAttributeID_Color);
glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, coord));
glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, texcoord));
glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VERT), (const GLvoid *)offsetof(VERT, color));
glBindVertexArray(0);
return OGLERROR_NOERR;
}
void OpenGLRenderer_3_2::DestroyVAOs()
{
if (!this->isVAOSupported)
{
return;
}
glBindVertexArray(0);
glDeleteVertexArrays(1, &this->ref->vaoMainStatesID);
this->isVAOSupported = false;
}
Render3DError OpenGLRenderer_3_2::LoadShaderPrograms(std::string *outVertexShaderProgram, std::string *outFragmentShaderProgram)
{
*outVertexShaderProgram = std::string(vertexShader_150);
*outFragmentShaderProgram = std::string(fragmentShader_150);
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::SetupShaderIO()
{
OGLRenderRef &OGLRef = *this->ref;
glBindAttribLocation(OGLRef.shaderProgram, OGLVertexAttributeID_Position, "inPosition");
glBindAttribLocation(OGLRef.shaderProgram, OGLVertexAttributeID_TexCoord0, "inTexCoord0");
glBindAttribLocation(OGLRef.shaderProgram, OGLVertexAttributeID_Color, "inColor");
glBindFragDataLocation(OGLRef.shaderProgram, 0, "outFragColor");
return OGLERROR_NOERR;
}
void OpenGLRenderer_3_2::GetExtensionSet(std::set<std::string> *oglExtensionSet)
{
GLint extensionCount = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
for (size_t i = 0; i < extensionCount; i++)
{
std::string extensionName = std::string((const char *)glGetStringi(GL_EXTENSIONS, i));
oglExtensionSet->insert(extensionName);
}
}
Render3DError OpenGLRenderer_3_2::EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount)
{
OGLRenderRef &OGLRef = *this->ref;
glBindVertexArray(OGLRef.vaoMainStatesID);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VERT) * vertList->count, vertList);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, vertIndexCount * sizeof(GLushort), indexBuffer);
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::DisableVertexAttributes()
{
glBindVertexArray(0);
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::SelectRenderingFramebuffer()
{
OGLRenderRef &OGLRef = *this->ref;
static const GLenum drawDirect[1] = {GL_COLOR_ATTACHMENT0};
OGLRef.selectedRenderingFBO = (CommonSettings.GFX3D_Renderer_Multisample) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID;
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO);
glDrawBuffers(1, &drawDirect[0]);
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::DownsampleFBO()
{
OGLRenderRef &OGLRef = *this->ref;
if (OGLRef.selectedRenderingFBO != OGLRef.fboMSIntermediateRenderID)
{
return OGLERROR_NOERR;
}
glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.selectedRenderingFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderID);
glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID);
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::ClearUsingImage() const
{
OGLRenderRef &OGLRef = *this->ref;
glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboClearImageID);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.selectedRenderingFBO);
glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO);
return OGLERROR_NOERR;
}
+86
View File
@@ -0,0 +1,86 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 shash
Copyright (C) 2008-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/>.
*/
#ifndef OGLRENDER_3_2_H
#define OGLRENDER_3_2_H
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <GL/gl.h>
#include <GL/glcorearb.h>
#define OGLEXT(procPtr, func) procPtr func = NULL;
#define INITOGLEXT(procPtr, func) func = (procPtr)wglGetProcAddress(#func);
#define EXTERNOGLEXT(procPtr, func) extern procPtr func;
#elif defined(__APPLE__)
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
// Ignore dynamic linking on Apple OS
#define OGLEXT(procPtr, func)
#define INITOGLEXT(procPtr, func)
#define EXTERNOGLEXT(procPtr, func)
#else
#include <GL/gl.h>
#include <GL/glx.h>
#include "utils/glcorearb.h"
#define OGLEXT(procPtr, func) procPtr func = NULL;
#define INITOGLEXT(procPtr, func) func = (procPtr)glXGetProcAddress((const GLubyte *) #func);
#define EXTERNOGLEXT(procPtr, func) extern procPtr func;
#endif
// Check minimum OpenGL header version
#if !defined(GL_VERSION_3_2)
#error OpenGL requires v3.2 headers or later.
#endif
#include "OGLRender.h"
void OGLLoadEntryPoints_3_2();
void OGLCreateRenderer_3_2(OpenGLRenderer **rendererPtr);
class OpenGLRenderer_3_2 : public OpenGLRenderer_2_1
{
protected:
virtual Render3DError InitExtensions();
virtual Render3DError CreateFBOs();
virtual void DestroyFBOs();
virtual Render3DError CreateMultisampledFBO();
virtual void DestroyMultisampledFBO();
virtual Render3DError CreateVAOs();
virtual void DestroyVAOs();
virtual Render3DError LoadShaderPrograms(std::string *outVertexShaderProgram, std::string *outFragmentShaderProgram);
virtual Render3DError SetupShaderIO();
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount);
virtual Render3DError DisableVertexAttributes();
virtual Render3DError SelectRenderingFramebuffer();
virtual Render3DError DownsampleFBO();
virtual Render3DError ClearUsingImage() const;
public:
~OpenGLRenderer_3_2();
};
#endif
Executable
+12
View File
@@ -0,0 +1,12 @@
#ifndef __GNUC__
#pragma pack(push, 1)
#pragma warning(disable : 4103)
#endif
#ifndef __PACKED
#ifdef __GNUC__
#define __PACKED __attribute__((__packed__))
#else
#define __PACKED
#endif
#endif
+3
View File
@@ -0,0 +1,3 @@
#ifndef __GNUC__
#pragma pack(pop)
#endif
+235
View File
@@ -0,0 +1,235 @@
/*
Copyright 2007 Guillaume Duhamel
Copyright 2007-2012 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
#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);
ROMReader_struct STDROMReader =
{
ROMREADER_STD,
"Standard ROM Reader",
STDROMReaderInit,
STDROMReaderDeInit,
STDROMReaderSize,
STDROMReaderSeek,
STDROMReaderRead
};
void * STDROMReaderInit(const char * filename)
{
#ifdef WIN32
struct _stat sb;
#else
struct stat sb;
#endif
if (stat(filename, &sb) == -1)
return 0;
if ((sb.st_mode & S_IFMT) != S_IFREG)
return 0;
return (void *) fopen(filename, "rb");
}
void STDROMReaderDeInit(void * file)
{
if (!file) return ;
fclose((FILE*)file);
}
u32 STDROMReaderSize(void * file)
{
u32 size;
if (!file) return 0 ;
fseek((FILE*)file, 0, SEEK_END);
size = ftell((FILE*)file);
fseek((FILE*)file, 0, SEEK_SET);
return size;
}
int STDROMReaderSeek(void * file, int offset, int whence)
{
if (!file) return 0 ;
return fseek((FILE*)file, offset, whence);
}
int STDROMReaderRead(void * file, void * buffer, u32 size)
{
if (!file) return 0 ;
return fread(buffer, 1, size, (FILE*)file);
}
#ifdef HAVE_LIBZ
void * GZIPROMReaderInit(const char * filename);
void GZIPROMReaderDeInit(void *);
u32 GZIPROMReaderSize(void *);
int GZIPROMReaderSeek(void *, int, int);
int GZIPROMReaderRead(void *, void *, u32);
ROMReader_struct GZIPROMReader =
{
ROMREADER_GZIP,
"Gzip ROM Reader",
GZIPROMReaderInit,
GZIPROMReaderDeInit,
GZIPROMReaderSize,
GZIPROMReaderSeek,
GZIPROMReaderRead
};
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);
}
#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);
ROMReader_struct ZIPROMReader =
{
ROMREADER_ZIP,
"Zip ROM Reader",
ZIPROMReaderInit,
ZIPROMReaderDeInit,
ZIPROMReaderSize,
ZIPROMReaderSeek,
ZIPROMReaderRead
};
void * ZIPROMReaderInit(const char * filename)
{
ZZIP_DIR * dir = zzip_opendir(filename);
ZZIP_DIRENT * dirent = zzip_readdir(dir);
if (dir != NULL)
{
char tmp1[1024];
char tmp2[1024];
memset(tmp1,0,sizeof(tmp1));
memset(tmp2,0,sizeof(tmp2));
strncpy(tmp1, filename, strlen(filename) - 4);
sprintf(tmp2, "%s/%s", tmp1, dirent->d_name);
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
}
#endif
+50
View File
@@ -0,0 +1,50 @@
/*
Copyright (C) 2007 Guillaume Duhamel
Copyright (C) 2007 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/>.
*/
#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
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);
} 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);
Executable
+2073
View File
File diff suppressed because it is too large Load Diff
Executable
+303
View File
@@ -0,0 +1,303 @@
/*
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
//who made these static? theyre used in multiple places.
FORCEINLINE u32 sputrunc(float f) { return u32floor(f); }
FORCEINLINE u32 sputrunc(double d) { return u32floor(d); }
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
};
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),
addr(0),
timer(0),
loopstart(0),
length(0),
totlength(0),
double_totlength_shifted(0.0),
sampcnt(0.0),
sampinc(0.0),
lastsampcnt(0),
pcm16b(0),
pcm16b_last(0),
loop_pcm16b(0),
index(0),
loop_index(0),
x(0),
psgnoise_last(0)
{}
u32 num;
u8 vol;
u8 volumeDiv;
u8 hold;
u8 pan;
u8 waveduty;
u8 repeat;
u8 format;
u8 keyon;
u8 status;
u32 addr;
u16 timer;
u16 loopstart;
u32 length;
u32 totlength;
double double_totlength_shifted;
double sampcnt;
double sampinc;
// ADPCM specific
u32 lastsampcnt;
s16 pcm16b, pcm16b_last;
s16 loop_pcm16b;
int index;
int loop_index;
u16 x;
s16 psgnoise_last;
};
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;
double sampcnt;
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 buffersize);
SoundInterface_struct *SPU_SoundCore();
void SPU_ReInit(bool fakeBoot = false);
int SPU_Init(int coreid, int buffersize);
void SPU_Pause(int pause);
void SPU_SetVolume(int volume);
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
+35
View File
@@ -0,0 +1,35 @@
/*
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(); }
+242
View File
@@ -0,0 +1,242 @@
/*
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 "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;
}
//called once when the emulator starts up, or when the device springs into existence
virtual bool init()
{
//strange to do this here but we need to make sure its done at some point
srand(time(NULL));
return true;
}
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 operation)
{
if(operation != 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 operation)
{
if(operation != eSlot1Operation_Unknown)
return 0;
u32 val;
int cmd = protocol.command.bytes[0];
switch(cmd)
{
case 0xB0:
val = (img) ? 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->fread(&val, 4);
//INFO("val %08X\n",val);
break;
default:
val = 0;
break;
}
return val;
}
void slot1client_write_GCDATAIN(eSlot1Operation operation, u32 val)
{
if(operation != eSlot1Operation_Unknown)
return;
int cmd = protocol.command.bytes[0];
switch(cmd)
{
case 0xBB:
{
if(write_count && write_enabled)
{
img->fwrite(&val, 4);
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->fwrite(&val, 4);
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(); }
+102
View File
@@ -0,0 +1,102 @@
/*
Copyright (C) 2013-2105 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
if ((memcmp(gameInfo.header.gameCode, "UOR", 3) == 0) || // WarioWare - D.I.Y. (U)(E)(EUR) / Made in Ore (J)
(memcmp(gameInfo.header.gameCode, "UXBP", 4) == 0) // Jam with the Band (EUR)
)
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(); }
+107
View File
@@ -0,0 +1,107 @@
/*
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 "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 operation)
{
rom.start(operation,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(); }
+220
View File
@@ -0,0 +1,220 @@
/*
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 "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"
//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_DEBUG : public ISlot1Interface, public ISlot1Comp_Protocol_Client
{
private:
Slot1Comp_Protocol protocol;
Slot1Comp_Rom rom;
FILE *fpROM;
FS_NITRO *fs;
u16 curr_file_id;
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;
if (!CommonSettings.loadToMemory)
{
printf("NitroFS: change load type to \"Load to RAM\"\n");
return;
}
pathData = path.getpath(path.SLOT1D) + path.GetRomNameWithoutExtension();
printf("Path to Slot1 data: %s\n", pathData.c_str());
fs = new FS_NITRO(gameInfo.romdata);
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 operation)
{
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)
{
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(operation, 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(); }
+318
View File
@@ -0,0 +1,318 @@
/*
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/>.
*/
// 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 operation)
{
//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(operation)
{
case eSlot1Operation_00_ReadHeader_Unencrypted:
rom.start(operation,addressFromProtocol);
return;
case eSlot1Operation_2x_SecureAreaLoad:
rom.start(operation,protocol.address);
return;
}
//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(operation, 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();
}
//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;
}
//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->write32le(version);
os->write32le(mode);
os->write32le(handle_save);
os->write32le(save_adr);
os->write32le(save_start);
os->write32le(subAdr);
}
virtual void loadstate(EMUFILE* is)
{
s32 version = 0;
protocol.loadstate(is);
rom.loadstate(is);
is->read32le(&version);
// version 0
if (version >= 0)
{
is->read32le(&mode);
is->read32le(&handle_save);
is->read32le(&save_adr);
is->read32le(&save_start);
is->read32le(&subAdr);
}
}
};
ISlot1Interface* construct_Slot1_Retail_NAND() { return new Slot1_Retail_NAND(); }
+41
View File
@@ -0,0 +1,41 @@
/*
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)
//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()
{
if(!memcmp(gameInfo.header.gameCode,"AXBJ", 4)) MMU_new.backupDevice.uninitializedValue = 0x00; // Daigassou! Band Brothers DX (JP)
}
+35
View File
@@ -0,0 +1,35 @@
/*
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
+256
View File
@@ -0,0 +1,256 @@
/*
Copyright (C) 2012-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 "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* client)
{
this->client = client;
//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 command)
{
int cmd = command.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 command)
{
//decrypt the KEY1-format command
u32 temp[2];
command.toCryptoBuffer(temp);
key1.decrypt(temp);
command.fromCryptoBuffer(temp);
GCLOG("[GC] (key1-decrypted):"); command.print();
//and process it:
int cmd = command.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 LOCAL_LE
u64 cmd64 = bswap64(*(u64*)command.bytes);
#else
u64 cmd64 = *(u64*)command.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 command)
{
switch(command.bytes[0])
{
case 0xB7:
{
operation = eSlot1Operation_B7_Read;
//TODO - more endian-safe way of doing this (theres examples in R4)
#ifdef LOCAL_LE
u64 cmd64 = bswap64(*(u64*)command.bytes);
#else
u64 cmd64 = *(u64*)command.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 command)
{
this->command = command;
//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(command);
break;
case eCardMode_KEY1:
write_command_KEY1(command);
break;
case eCardMode_NORMAL:
write_command_NORMAL(command);
break;
}
}
void Slot1Comp_Protocol::write_GCDATAIN(u8 PROCNUM, u32 val)
{
switch(operation)
{
case eSlot1Operation_Unknown:
client->slot1client_write_GCDATAIN(operation,val);
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->write32le(version);
os->write32le((s32)mode);
os->write32le((s32)operation);
os->fwrite(command.bytes,8);
os->write32le(address);
os->write32le(length);
os->write32le(delay);
os->write32le(chipId);
os->write32le(gameCode);
}
void Slot1Comp_Protocol::loadstate(EMUFILE* is)
{
s32 version = is->read32le();
mode = (eCardMode)is->read32le();
operation = (eSlot1Operation)is->read32le();
is->fread(command.bytes,8);
address = is->read32le();
length = is->read32le();
delay = is->read32le();
chipId = is->read32le();
gameCode = is->read32le();
}
+114
View File
@@ -0,0 +1,114 @@
/*
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 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 operation) {}
virtual u32 slot1client_read_GCDATAIN(eSlot1Operation operation) = 0;
virtual void slot1client_write_GCDATAIN(eSlot1Operation operation, 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* client);
//signals from the GC bus
void write_command(GC_Command command);
void write_GCDATAIN(u8 PROCNUM, u32 val);
u32 read_GCDATAIN(u8 PROCNUM);
//helpers for write_command()
void write_command_RAW(GC_Command command);
void write_command_KEY1(GC_Command command);
void write_command_NORMAL(GC_Command command);
//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
+122
View File
@@ -0,0 +1,122 @@
/*
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 "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(operation)
{
case eSlot1Operation_00_ReadHeader_Unencrypted:
{
u32 ret = gameInfo.readROM(address);
address = (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 = (address - 0x4000);
secureAreaAddress &= 0x3FFF; //memory safe sanity test
u32 ret = LE_TO_LOCAL_32(*(u32*)(gameInfo.secureArea + secureAreaAddress));
address = (address&~0xFFF) + ((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
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(address < 0x8000)
address = (0x8000 + (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
if(address+4 > gameInfo.romsize)
{
DEBUG_Notify.ReadBeyondEndOfCart(address,gameInfo.romsize);
return 0xFFFFFFFF;
}
//actually read from the ROM provider
u32 ret = gameInfo.readROM(address);
//"However, the datastream wraps to the begin of the current 4K block when address+length crosses a 4K boundary (1000h bytes)"
address = (address&~0xFFF) + ((address+4)&0xFFF);
return ret;
}
break;
default:
return 0;
} //switch(operation)
} //Slot1Comp_Rom::read()
u32 Slot1Comp_Rom::getAddress()
{
return address & gameInfo.mask;
} //Slot1Comp_Rom::getAddress()
u32 Slot1Comp_Rom::incAddress()
{
address &= gameInfo.mask;
address = (address&~0xFFF) + ((address+4)&0xFFF);
return address;
}
void Slot1Comp_Rom::savestate(EMUFILE* os)
{
s32 version = 0;
os->write32le(version);
os->write32le((s32)operation);
os->write32le(address);
}
void Slot1Comp_Rom::loadstate(EMUFILE* is)
{
s32 version = is->read32le();
operation = (eSlot1Operation)is->read32le();
address = is->read32le();
}
+45
View File
@@ -0,0 +1,45 @@
/*
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/>.
*/
//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
+72
View File
@@ -0,0 +1,72 @@
/*
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(); }
+198
View File
@@ -0,0 +1,198 @@
/*
Copyright (C) 2009 CrazyMax
Copyright (C) 2009-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 "../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 = new EMUFILE_MEMORY(expMemory, EXPANSION_MEMORY_SIZE);
os->write32le(version);
os->write32le((u32)ext_ram_lock);
os->writeMemoryStream(ram);
delete ram;
}
virtual void loadstate(EMUFILE* is)
{
EMUFILE_MEMORY *ram = new EMUFILE_MEMORY();
s32 version = is->read32le();
if (version >= 0)
{
is->read32le((u32*)&ext_ram_lock);
is->readMemoryStream(ram);
memcpy(expMemory, ram->buf(), std::min(EXPANSION_MEMORY_SIZE, ram->size()));
}
delete ram;
}
};
ISlot2Interface* construct_Slot2_ExpansionPak() { return new Slot2_ExpansionPak(); }
+464
View File
@@ -0,0 +1,464 @@
/*
Copyright (C) 2009 CrazyMax
Copyright (C) 2009-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 <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 tmp;
u32 readed = fROM->fread(&tmp, 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 (tmp)
{
case EEPROM:
return 1;
case SRAM_:
return 2;
case FLASH:
{
u32 tmp = fROM->read32le();
return ((tmp == FLASH1M_)?3:5);
}
case SIIRTC_V:
return 4;
}
}
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");
inf->EnablePositionCache();
fROM = inf;
if (fROM->fail())
{
printf(" - Failed\n");
Close();
return;
}
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(); }
+52
View File
@@ -0,0 +1,52 @@
/*
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 = 0;
}
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)
{
guitarKeyStatus = 0 | (green << 6) | (red << 5) | (yellow << 4) | (blue << 3);
}
+301
View File
@@ -0,0 +1,301 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006 Mic
Copyright (C) 2009-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 <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];
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(&sector_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(); }
+31
View File
@@ -0,0 +1,31 @@
/*
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(); }
+143
View File
@@ -0,0 +1,143 @@
/*
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(); }
+56
View File
@@ -0,0 +1,56 @@
/*
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(); }
+117
View File
@@ -0,0 +1,117 @@
/*
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 = 0;
}
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&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)
;
}
+62
View File
@@ -0,0 +1,62 @@
/*
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(); }
Executable
+932
View File
@@ -0,0 +1,932 @@
//----------------------------------------------------------------------------
// Agg2D - Version 1.0
// Based on Anti-Grain Geometry
// Copyright (C) 2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//
// 25 Jan 2007 - Ported to AGG 2.4 Jerry Evans (jerry@novadsp.com)
// 11 Jul 2009 - significant refactors for introduction to desmume
//
//----------------------------------------------------------------------------
#ifndef AGG2D_INCLUDED
#define AGG2D_INCLUDED
//we're not using vector fonts right now.
//#define AGG2D_USE_VECTORFONTS
#ifdef AGG2D_USE_VECTORFONTS
#if defined(UNDER_CE) || not defined(WIN32)
#define AGG2D_USE_FREETYPE
#endif
#endif
#ifdef _MSC_VER
#pragma warning(disable: 4786)
#endif
// JME
#include "agg_basics.h"
#include "agg_math_stroke.h"
#include "agg_trans_affine.h"
#include "agg_trans_viewport.h"
#include "agg_path_storage.h"
#include "agg_conv_stroke.h"
#include "agg_conv_transform.h"
#include "agg_conv_curve.h"
#include "agg_rendering_buffer.h"
#include "agg_renderer_base.h"
#include "agg_renderer_scanline.h"
#include "agg_span_gradient.h"
#include "agg_span_image_filter_rgba.h"
//+ JME
#include "agg_span_allocator.h"
#include "agg_span_converter.h"
#include "agg_span_interpolator_linear.h"
#include "agg_rasterizer_scanline_aa.h"
#include "agg_gamma_functions.h"
#include "agg_scanline_u.h"
#include "agg_bezier_arc.h"
#include "agg_rounded_rect.h"
#include "agg_font_cache_manager.h"
#include "agg_glyph_raster_bin.h"
#include "agg_renderer_raster_text.h"
#include "agg_embedded_raster_fonts.h"
#include <string>
#ifdef AGG2D_USE_VECTORFONTS
#ifdef AGG2D_USE_FREETYPE
#ifndef WIN32
#include "agg_font_freetype.h"
#else
#include "../font_freetype/agg_font_freetype.h"
#endif
#else
#include "../font_win32_tt/agg_font_win32_tt.h"
#endif
#endif
#include "agg_pixfmt_rgba.h"
//+ JME
#include "agg_image_accessors.h"
#define AGG2D_TEMPLATE template<typename PixFormatSet>
#define AGG2D_TEMPLATE_WITH_IMAGE template<typename PixFormatSet, typename ImagePixFormatSet>
#define AGG2D_TEMPLATE_ARG <PixFormatSet>
#define AGG2D_IMAGE_TEMPLATE template<typename ImagePixFormatSet>
#define AGG2D_IMAGE_TEMPLATE_ARG <ImagePixFormatSet>
#define TIMAGE Agg2DBase :: Image AGG2D_IMAGE_TEMPLATE_ARG
template<typename Main, typename Pre, typename SG>
class PixFormatSetDeclaration
{
public:
typedef Main PixFormat;
typedef Pre PixFormatPre;
typedef SG SpanGenerator;
};
class Agg2DBase
{
public:
// JME
//typedef agg::rect Rect;
typedef agg::rect_i Rect;
typedef agg::rect_d RectD;
typedef agg::trans_affine Affine;
enum LineJoin
{
JOIN_MITER = agg::miter_join,
JOIN_ROUND = agg::round_join,
JOIN_BEVEL = agg::bevel_join
};
enum LineCap
{
CAP_BUTT = agg::butt_cap,
CAP_SQUARE = agg::square_cap,
CAP_ROUND = agg::round_cap
};
enum TextAlignment
{
AlignLeft,
AlignRight,
AlignCenter,
AlignBaseline,
AlignTop = AlignRight,
AlignBottom = AlignLeft
};
enum DrawPathFlag
{
FillOnly,
StrokeOnly,
FillAndStroke,
FillWithLineColor
};
enum ViewportOption
{
Anisotropic,
XMinYMin,
XMidYMin,
XMaxYMin,
XMinYMid,
XMidYMid,
XMaxYMid,
XMinYMax,
XMidYMax,
XMaxYMax
};
enum WindowFitLogic
{
WindowFitLogic_meet,
WindowFitLogic_slice
};
struct Transformations
{
double affineMatrix[6];
};
AGG2D_IMAGE_TEMPLATE struct Image
{
agg::rendering_buffer renBuf;
Image(const agg::rendering_buffer& srcBuf)
: renBuf(srcBuf)
{}
Image(unsigned char* buf, unsigned width, unsigned height, int stride) :
renBuf(buf, width, height, stride) {}
void attach(unsigned char* buf, unsigned width, unsigned height, int stride)
{
renBuf.attach(buf, width, height, stride);
}
int width() const { return renBuf.width(); }
int height() const { return renBuf.height(); }
AGG2D_TEMPLATE void premultiply()
{
typename PixFormatSet::PixFormat pixf(renBuf);
pixf.premultiply();
}
AGG2D_TEMPLATE void demultiply()
{
typename PixFormatSet::PixFormat pixf(renBuf);
pixf.demultiply();
}
};
enum ImageFilter
{
NoFilter,
Bilinear,
Hanning,
Hermite,
Quadric,
Bicubic,
Catrom,
Spline16,
Spline36,
Blackman144
};
enum ImageResample
{
NoResample,
ResampleAlways,
ResampleOnZoomOut
};
enum FontCacheType
{
RasterFontCache,
VectorFontCache
};
enum BlendMode
{
BlendAlpha = agg::end_of_comp_op_e,
BlendClear = agg::comp_op_clear,
BlendSrc = agg::comp_op_src,
BlendDst = agg::comp_op_dst,
BlendSrcOver = agg::comp_op_src_over,
BlendDstOver = agg::comp_op_dst_over,
BlendSrcIn = agg::comp_op_src_in,
BlendDstIn = agg::comp_op_dst_in,
BlendSrcOut = agg::comp_op_src_out,
BlendDstOut = agg::comp_op_dst_out,
BlendSrcAtop = agg::comp_op_src_atop,
BlendDstAtop = agg::comp_op_dst_atop,
BlendXor = agg::comp_op_xor,
BlendAdd = agg::comp_op_plus,
BlendSub = agg::comp_op_minus,
BlendMultiply = agg::comp_op_multiply,
BlendScreen = agg::comp_op_screen,
BlendOverlay = agg::comp_op_overlay,
BlendDarken = agg::comp_op_darken,
BlendLighten = agg::comp_op_lighten,
BlendColorDodge = agg::comp_op_color_dodge,
BlendColorBurn = agg::comp_op_color_burn,
BlendHardLight = agg::comp_op_hard_light,
BlendSoftLight = agg::comp_op_soft_light,
BlendDifference = agg::comp_op_difference,
BlendExclusion = agg::comp_op_exclusion,
BlendContrast = agg::comp_op_contrast
};
enum Direction
{
CW, CCW
};
};
template<typename,typename> class Agg2DRenderer;
template<typename PixFormatSet> class Agg2D : public Agg2DBase
{
public:
typedef typename PixFormatSet::PixFormat PixFormat;
typedef Image<PixFormatSet> MyImage;
typedef agg::order_bgra ComponentOrder; // Platform dependent!
typedef agg::rgba8 ColorType;
typedef agg::blender_rgba<ColorType, ComponentOrder> Blender;
typedef agg::comp_op_adaptor_rgba<ColorType, ComponentOrder> BlenderComp;
typedef agg::blender_rgba_pre<ColorType, ComponentOrder> BlenderPre;
typedef agg::comp_op_adaptor_rgba_pre<ColorType, ComponentOrder> BlenderCompPre;
// JME
//typedef agg::pixel_formats_rgba<Blender, agg::pixel32_type> PixFormat;
//typedef agg::pixfmt_bgra32 PixFormat;
// JME
//typedef agg::pixfmt_custom_blend_rgba<BlenderComp,> PixFormatComp;
typedef agg::pixfmt_custom_blend_rgba<BlenderComp,agg::rendering_buffer> PixFormatComp;
// JME
//typedef agg::pixel_formats_rgba<BlenderPre, agg::pixel32_type> PixFormatPre;
typedef typename PixFormatSet::PixFormatPre PixFormatPre;
// JME
//typedef agg::pixfmt_custom_blend_rgba<BlenderCompPre> PixFormatCompPre;
typedef agg::pixfmt_custom_blend_rgba<BlenderCompPre,agg::rendering_buffer> PixFormatCompPre;
typedef agg::renderer_base<PixFormat> RendererBase;
typedef agg::renderer_base<PixFormatComp> RendererBaseComp;
typedef agg::renderer_base<PixFormatPre> RendererBasePre;
typedef agg::renderer_base<PixFormatCompPre> RendererBaseCompPre;
typedef agg::renderer_scanline_aa_solid<RendererBase> RendererSolid;
typedef agg::renderer_scanline_aa_solid<RendererBaseComp> RendererSolidComp;
typedef agg::span_allocator<ColorType> SpanAllocator;
typedef agg::pod_auto_array<ColorType, 256> GradientArray;
typedef agg::span_gradient<ColorType, agg::span_interpolator_linear<>, agg::gradient_x, GradientArray> LinearGradientSpan;
typedef agg::span_gradient<ColorType, agg::span_interpolator_linear<>, agg::gradient_circle, GradientArray> RadialGradientSpan;
#ifdef AGG2D_USE_VECTORFONTS
#ifdef AGG2D_USE_FREETYPE
typedef agg::font_engine_freetype_int32 FontEngine;
#else
typedef agg::font_engine_win32_tt_int32 FontEngine;
#endif
typedef agg::font_cache_manager<FontEngine> FontCacheManager;
typedef FontCacheManager::gray8_adaptor_type FontRasterizer;
typedef FontCacheManager::gray8_scanline_type FontScanline;
#endif
typedef agg::conv_curve<agg::path_storage> ConvCurve;
typedef agg::conv_stroke<ConvCurve> ConvStroke;
typedef agg::conv_transform<ConvCurve> PathTransform;
typedef agg::conv_transform<ConvStroke> StrokeTransform;
enum Gradient
{
Solid,
Linear,
Radial
};
public:
template<typename,typename> friend class Agg2DRenderer;
typedef ColorType Color;
struct State
{
RectD m_clipBox;
BlendMode m_blendMode;
BlendMode m_imageBlendMode;
Color m_imageBlendColor;
double m_masterAlpha;
double m_antiAliasGamma;
const agg::int8u* m_font;
Color m_fillColor;
Color m_lineColor;
GradientArray m_fillGradient;
GradientArray m_lineGradient;
LineCap m_lineCap;
LineJoin m_lineJoin;
Gradient m_fillGradientFlag;
Gradient m_lineGradientFlag;
agg::trans_affine m_fillGradientMatrix;
agg::trans_affine m_lineGradientMatrix;
double m_fillGradientD1;
double m_lineGradientD1;
double m_fillGradientD2;
double m_lineGradientD2;
double m_textAngle;
TextAlignment m_textAlignX;
TextAlignment m_textAlignY;
bool m_textHints;
double m_fontHeight;
double m_fontAscent;
double m_fontDescent;
FontCacheType m_fontCacheType;
double m_lineWidth;
bool m_evenOddFlag;
agg::trans_affine m_transform;
agg::trans_affine m_affine;
};
~Agg2D();
Agg2D();
// Setup
//-----------------------
void attach(unsigned char* buf, unsigned width, unsigned height, int stride);
void attach(MyImage& img);
void clipBox(double x1, double y1, double x2, double y2);
RectD clipBox() const;
void clearAll(Color c);
void clearAll(unsigned r, unsigned g, unsigned b, unsigned a = 255);
void clearClipBox(Color c);
void clearClipBox(unsigned r, unsigned g, unsigned b, unsigned a = 255);
unsigned width() const { return m_rbuf.width(); }
unsigned height() const { return m_rbuf.height(); }
unsigned stride() const { return m_rbuf.stride(); }
// Conversions
//-----------------------
void worldToScreen(double& x, double& y) const;
void screenToWorld(double& x, double& y) const;
double worldToScreen(double scalar) const;
double screenToWorld(double scalar) const;
void alignPoint(double& x, double& y) const;
bool inBox(double worldX, double worldY) const;
// General Attributes
//-----------------------
void blendMode(BlendMode m);
BlendMode blendMode() const;
void imageBlendMode(BlendMode m);
BlendMode imageBlendMode() const;
void imageBlendColor(Color c);
void imageBlendColor(unsigned r, unsigned g, unsigned b, unsigned a = 255);
Color imageBlendColor() const;
void masterAlpha(double a);
double masterAlpha() const;
void antiAliasGamma(double g);
double antiAliasGamma() const;
void font(const agg::int8u* font) { m_font = font; }
const agg::int8u* font() { return m_font; }
void fillColor(Color c);
void fillColor(unsigned r, unsigned g, unsigned b, unsigned a = 255);
void noFill();
void lineColor(Color c);
void lineColor(unsigned r, unsigned g, unsigned b, unsigned a = 255);
void noLine();
Color fillColor() const;
Color lineColor() const;
void fillLinearGradient(double x1, double y1, double x2, double y2, Color c1, Color c2, double profile=1.0);
void lineLinearGradient(double x1, double y1, double x2, double y2, Color c1, Color c2, double profile=1.0);
void fillRadialGradient(double x, double y, double r, Color c1, Color c2, double profile=1.0);
void lineRadialGradient(double x, double y, double r, Color c1, Color c2, double profile=1.0);
void fillRadialGradient(double x, double y, double r, Color c1, Color c2, Color c3);
void lineRadialGradient(double x, double y, double r, Color c1, Color c2, Color c3);
void fillRadialGradient(double x, double y, double r);
void lineRadialGradient(double x, double y, double r);
void lineWidth(double w);
double lineWidth() const;
void lineCap(LineCap cap);
LineCap lineCap() const;
void lineJoin(LineJoin join);
LineJoin lineJoin() const;
void fillEvenOdd(bool evenOddFlag);
bool fillEvenOdd() const;
// Transformations
//-----------------------
Transformations transformations() const;
void transformations(const Transformations& tr);
const Affine& affine() const;
void affine(const Affine&);
void resetTransformations();
void matrix(const Affine& tr);
void matrix(const Transformations& tr);
void rotate(double angle);
void rotate(double angle, double cx, double cy);
void scale(double s);
void scale(double sx, double sy);
void skew(double sx, double sy);
void translate(double x, double y);
void parallelogram(double x1, double y1, double x2, double y2, const double* para);
void viewport(double worldX1, double worldY1, double worldX2, double worldY2,
double screenX1, double screenY1, double screenX2, double screenY2,
ViewportOption opt=XMidYMid, WindowFitLogic fl = WindowFitLogic_meet);
// Basic Shapes
//-----------------------
void line(double x1, double y1, double x2, double y2);
void triangle(double x1, double y1, double x2, double y2, double x3, double y3);
void rectangle(double x1, double y1, double x2, double y2);
void roundedRect(double x1, double y1, double x2, double y2, double r);
void roundedRect(double x1, double y1, double x2, double y2, double rx, double ry);
void roundedRect(double x1, double y1, double x2, double y2,
double rxBottom, double ryBottom,
double rxTop, double ryTop);
void ellipse(double cx, double cy, double rx, double ry);
void arc(double cx, double cy, double rx, double ry, double start, double sweep);
void star(double cx, double cy, double r1, double r2, double startAngle, int numRays);
void curve(double x1, double y1, double x2, double y2, double x3, double y3);
void curve(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4);
void polygon(double* xy, int numPoints);
void polyline(double* xy, int numPoints);
// Text
//-----------------------
#ifdef AGG2D_USE_VECTORFONTS
void flipText(bool flip);
void font(const char* fileName, double height,
bool bold = false,
bool italic = false,
FontCacheType ch = RasterFontCache,
double angle = 0.0);
double fontHeight() const;
double fontAscent() const;
void textAlignment(TextAlignment alignX, TextAlignment alignY);
bool textHints() const;
void textHints(bool hints);
double textWidth(const char* str, unsigned int len);
double textWidth(const wchar_t* str, unsigned int len);
void text(double x, double y, const char* str, unsigned int len, bool roundOff=false, double dx=0.0, double dy=0.0);
void text(double x, double y, const wchar_t* str, unsigned int len, bool roundOff=false, double dx=0.0, double dy=0.0);
double textWidth(const char* str);
void text(double x, double y, const char* str, bool roundOff=false, double dx=0.0, double dy=0.0);
#endif
// Path commands
//-----------------------
void resetPath();
void moveTo(double x, double y);
void moveRel(double dx, double dy);
void lineTo(double x, double y);
void lineRel(double dx, double dy);
void horLineTo(double x);
void horLineRel(double dx);
void verLineTo(double y);
void verLineRel(double dy);
void arcTo(double rx, double ry,
double angle,
bool largeArcFlag,
bool sweepFlag,
double x, double y);
void arcRel(double rx, double ry,
double angle,
bool largeArcFlag,
bool sweepFlag,
double dx, double dy);
void quadricCurveTo(double xCtrl, double yCtrl,
double xTo, double yTo);
void quadricCurveRel(double dxCtrl, double dyCtrl,
double dxTo, double dyTo);
void quadricCurveTo(double xTo, double yTo);
void quadricCurveRel(double dxTo, double dyTo);
void cubicCurveTo(double xCtrl1, double yCtrl1,
double xCtrl2, double yCtrl2,
double xTo, double yTo);
void cubicCurveRel(double dxCtrl1, double dyCtrl1,
double dxCtrl2, double dyCtrl2,
double dxTo, double dyTo);
void cubicCurveTo(double xCtrl2, double yCtrl2,
double xTo, double yTo);
void cubicCurveRel(double xCtrl2, double yCtrl2,
double xTo, double yTo);
void addEllipse(double cx, double cy, double rx, double ry, Direction dir);
void closePolygon();
void drawPath(DrawPathFlag flag = FillAndStroke);
void drawPathNoTransform(DrawPathFlag flag = FillAndStroke);
// Image Transformations
//-----------------------
void imageFilter(ImageFilter f);
ImageFilter imageFilter() const;
void imageResample(ImageResample f);
ImageResample imageResample() const;
//---------
//if anyone can figure out how to put these in the .inl file, theyre more than welcome to. I couldnt declare them correctly to match
//the .h file declaration
AGG2D_IMAGE_TEMPLATE void transformImage(const TIMAGE& img,
int imgX1, int imgY1, int imgX2, int imgY2,
double dstX1, double dstY1, double dstX2, double dstY2)
{
resetPath();
moveTo(dstX1, dstY1);
lineTo(dstX2, dstY1);
lineTo(dstX2, dstY2);
lineTo(dstX1, dstY2);
closePolygon();
double parallelogram[6] = { dstX1, dstY1, dstX2, dstY1, dstX2, dstY2 };
renderImage <typename ImagePixFormatSet::ImagePixFormat> (img, imgX1, imgY1, imgX2, imgY2, parallelogram);
}
AGG2D_IMAGE_TEMPLATE void transformImage(const TIMAGE& img,
double dstX1, double dstY1, double dstX2, double dstY2)
{
resetPath();
moveTo(dstX1, dstY1);
lineTo(dstX2, dstY1);
lineTo(dstX2, dstY2);
lineTo(dstX1, dstY2);
closePolygon();
double parallelogram[6] = { dstX1, dstY1, dstX2, dstY1, dstX2, dstY2 };
renderImage(img, 0, 0, img.renBuf.width(), img.renBuf.height(), parallelogram);
}
AGG2D_IMAGE_TEMPLATE void transformImage(const TIMAGE& img,
int imgX1, int imgY1, int imgX2, int imgY2,
const double* parallelogram)
{
resetPath();
moveTo(parallelogram[0], parallelogram[1]);
lineTo(parallelogram[2], parallelogram[3]);
lineTo(parallelogram[4], parallelogram[5]);
lineTo(parallelogram[0] + parallelogram[4] - parallelogram[2],
parallelogram[1] + parallelogram[5] - parallelogram[3]);
closePolygon();
renderImage(img, imgX1, imgY1, imgX2, imgY2, parallelogram);
}
AGG2D_IMAGE_TEMPLATE void transformImage(const TIMAGE& img, const double* parallelogram)
{
resetPath();
moveTo(parallelogram[0], parallelogram[1]);
lineTo(parallelogram[2], parallelogram[3]);
lineTo(parallelogram[4], parallelogram[5]);
lineTo(parallelogram[0] + parallelogram[4] - parallelogram[2],
parallelogram[1] + parallelogram[5] - parallelogram[3]);
closePolygon();
renderImage(img, 0, 0, img.renBuf.width(), img.renBuf.height(), parallelogram);
}
AGG2D_IMAGE_TEMPLATE void transformImagePath(const TIMAGE& img,
int imgX1, int imgY1, int imgX2, int imgY2,
double dstX1, double dstY1, double dstX2, double dstY2)
{
double parallelogram[6] = { dstX1, dstY1, dstX2, dstY1, dstX2, dstY2 };
renderImage(img, imgX1, imgY1, imgX2, imgY2, parallelogram);
}
AGG2D_IMAGE_TEMPLATE void transformImagePath(const TIMAGE& img,
double dstX1, double dstY1, double dstX2, double dstY2)
{
double parallelogram[6] = { dstX1, dstY1, dstX2, dstY1, dstX2, dstY2 };
renderImage(img, 0, 0, img.renBuf.width(), img.renBuf.height(), parallelogram);
}
AGG2D_IMAGE_TEMPLATE void transformImagePath(const TIMAGE& img,
int imgX1, int imgY1, int imgX2, int imgY2,
const double* parallelogram)
{
renderImage(img, imgX1, imgY1, imgX2, imgY2, parallelogram);
}
AGG2D_IMAGE_TEMPLATE void transformImagePath(const TIMAGE& img, const double* parallelogram)
{
renderImage(img, 0, 0, img.renBuf.width(), img.renBuf.height(), parallelogram);
}
// Image Blending (no transformations available)
AGG2D_IMAGE_TEMPLATE void blendImage(TIMAGE& img,
int imgX1, int imgY1, int imgX2, int imgY2,
double dstX, double dstY, unsigned alpha=255)
{
worldToScreen(dstX, dstY);
PixFormat pixF(img.renBuf);
// JME
//agg::rect r(imgX1, imgY1, imgX2, imgY2);
Rect r(imgX1, imgY1, imgX2, imgY2);
if(m_blendMode == BlendAlpha)
{
m_renBasePre.blend_from(pixF, &r, int(dstX)-imgX1, int(dstY)-imgY1, alpha);
}
else
{
m_renBaseCompPre.blend_from(pixF, &r, int(dstX)-imgX1, int(dstY)-imgY1, alpha);
}
}
void renderText(double dstX, double dstY, const std::string& str)
{
worldToScreen(dstX, dstY);
PixFormat pixF(m_rbuf);
//Rect r(imgX1, imgY1, imgX2, imgY2);
typedef agg::glyph_raster_bin<agg::rgba8> glyph_gen;
glyph_gen glyph(0);
if(m_blendMode == BlendAlpha)
{
typedef agg::renderer_base<PixFormatPre> ren_base;
agg::renderer_raster_htext_solid<ren_base, glyph_gen> rt(m_renBasePre,glyph);
rt.color(m_lineColor);
glyph.font(m_font);
rt.render_text(dstX, dstY, str.c_str(), true); //flipy
}
else
{
typedef agg::renderer_base<PixFormatCompPre> ren_base;
agg::renderer_raster_htext_solid<ren_base, glyph_gen> rt(m_renBaseCompPre,glyph);
rt.color(m_lineColor);
glyph.font(m_font);
rt.render_text(dstX, dstY, str.c_str(), true); //flipy
}
}
AGG2D_IMAGE_TEMPLATE void blendImage(TIMAGE& img, double dstX, double dstY, unsigned alpha=255)
{
worldToScreen(dstX, dstY);
PixFormat pixF(img.renBuf);
m_renBasePre.blend_from(pixF, 0, int(dstX), int(dstY), alpha);
if(m_blendMode == BlendAlpha)
{
m_renBasePre.blend_from(pixF, 0, int(dstX), int(dstY), alpha);
}
else
{
m_renBaseCompPre.blend_from(pixF, 0, int(dstX), int(dstY), alpha);
}
}
// Copy image directly, together with alpha-channel
AGG2D_IMAGE_TEMPLATE void copyImage(TIMAGE& img,
int imgX1, int imgY1, int imgX2, int imgY2,
double dstX, double dstY)
{
worldToScreen(dstX, dstY);
// JME
//agg::rect r(imgX1, imgY1, imgX2, imgY2);
Rect r(imgX1, imgY1, imgX2, imgY2);
m_renBase.copy_from(img.renBuf, &r, int(dstX)-imgX1, int(dstY)-imgY1);
}
AGG2D_IMAGE_TEMPLATE void copyImage(TIMAGE& img, double dstX, double dstY)
{
worldToScreen(dstX, dstY);
m_renBase.copy_from(img.renBuf, 0, int(dstX), int(dstY));
}
// State
//-----------------------
void saveStateTo(State& st);
void restoreStateFrom(const State& st);
// Auxiliary
//-----------------------
static double pi() { return agg::pi; }
static double deg2Rad(double v) { return v * agg::pi / 180.0; }
static double rad2Deg(double v) { return v * 180.0 / agg::pi; }
PixFormat & pixFormat() { return m_pixFormat; }
agg::rendering_buffer & buf() { return m_rbuf; }
private:
void render(bool fillColor);
#ifdef AGG2D_USE_VECTORFONTS
#if !defined( UNDER_CE )
void render(FontRasterizer& ras, FontScanline& sl);
#endif
#endif
void addLine(double x1, double y1, double x2, double y2);
void updateRasterizerGamma();
AGG2D_IMAGE_TEMPLATE void renderImage(const TIMAGE& img, int x1, int y1, int x2, int y2, const double* parl)
{
agg::trans_affine mtx((double)x1,
(double)y1,
(double)x2,
(double)y2,
parl);
mtx *= m_transform;
mtx.invert();
m_rasterizer.reset();
m_rasterizer.add_path(m_pathTransform);
typedef agg::span_interpolator_linear<agg::trans_affine> Interpolator;
Interpolator interpolator(mtx);
if(m_blendMode == BlendAlpha)
{
// JME audit -
Agg2DRenderer<PixFormatSet,ImagePixFormatSet>::renderImage(*this, img, m_renBasePre, interpolator);
}
else
{
Agg2DRenderer<PixFormatSet,ImagePixFormatSet>::renderImage(*this, img, m_renBaseCompPre, interpolator);
}
}
void updateTransformations();
agg::rendering_buffer m_rbuf;
PixFormat m_pixFormat;
PixFormatComp m_pixFormatComp;
PixFormatPre m_pixFormatPre;
PixFormatCompPre m_pixFormatCompPre;
RendererBase m_renBase;
RendererBaseComp m_renBaseComp;
RendererBasePre m_renBasePre;
RendererBaseCompPre m_renBaseCompPre;
RendererSolid m_renSolid;
RendererSolidComp m_renSolidComp;
SpanAllocator m_allocator;
RectD m_clipBox;
BlendMode m_blendMode;
BlendMode m_imageBlendMode;
Color m_imageBlendColor;
agg::scanline_u8 m_scanline;
agg::rasterizer_scanline_aa<> m_rasterizer;
double m_masterAlpha;
double m_antiAliasGamma;
const agg::int8u* m_font;
Color m_fillColor;
Color m_lineColor;
GradientArray m_fillGradient;
GradientArray m_lineGradient;
LineCap m_lineCap;
LineJoin m_lineJoin;
Gradient m_fillGradientFlag;
Gradient m_lineGradientFlag;
agg::trans_affine m_fillGradientMatrix;
agg::trans_affine m_lineGradientMatrix;
double m_fillGradientD1;
double m_lineGradientD1;
double m_fillGradientD2;
double m_lineGradientD2;
double m_textAngle;
TextAlignment m_textAlignX;
TextAlignment m_textAlignY;
bool m_textHints;
double m_fontHeight;
double m_fontAscent;
double m_fontDescent;
FontCacheType m_fontCacheType;
ImageFilter m_imageFilter;
ImageResample m_imageResample;
agg::image_filter_lut m_imageFilterLut;
agg::span_interpolator_linear<> m_fillGradientInterpolator;
agg::span_interpolator_linear<> m_lineGradientInterpolator;
agg::gradient_x m_linearGradientFunction;
agg::gradient_circle m_radialGradientFunction;
double m_lineWidth;
bool m_evenOddFlag;
double m_start_x;
double m_start_y;
agg::path_storage m_path;
agg::trans_affine m_transform;
agg::trans_affine m_viewport;
agg::trans_affine m_affine;
ConvCurve m_convCurve;
ConvStroke m_convStroke;
PathTransform m_pathTransform;
StrokeTransform m_strokeTransform;
#ifdef AGG2D_USE_VECTORFONTS
#ifndef AGG2D_USE_FREETYPE
HDC m_fontDC;
#endif
FontEngine m_fontEngine;
FontCacheManager m_fontCacheManager;
#endif
};
#include "agg2d.inl"
#endif
Executable
+1979
View File
File diff suppressed because it is too large Load Diff
+591
View File
@@ -0,0 +1,591 @@
/*
The MIT License
Copyright (C) 2009-2010 DeSmuME team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <map>
#include "GPU.h"
#include "NDSSystem.h"
#include "aggdraw.h"
#include "agg_renderer_base.h"
#include "agg_renderer_primitives.h"
#include "agg_renderer_scanline.h"
#include "agg_bounding_rect.h"
#include "agg_trans_affine.h"
#include "agg_path_storage.h"
#include "agg_color_rgba.h"
#include "agg_rasterizer_scanline_aa.h"
#include "agg_scanline_u.h"
#include "agg_renderer_scanline.h"
#include "agg_scanline_p.h"
//raster text
#include "agg_glyph_raster_bin.h"
#include "agg_embedded_raster_fonts.h"
#include "agg_renderer_raster_text.h"
#include "ctrl/agg_bezier_ctrl.h"
#include "platform/agg_platform_support.h"
#include "agg_pattern_filters_rgba.h"
#include "agg_renderer_outline_image.h"
#include "agg_rasterizer_outline_aa.h"
#include "agg_image_accessors.h"
#include "agg_span_interpolator_linear.h"
#include "agg_span_image_filter_rgb.h"
#include "agg_span_image_filter_rgba.h"
#include "agg_span_image_filter_gray.h"
#include "agg_span_allocator.h"
typedef std::map<std::string, const agg::int8u*> TAgg_Font_Table;
static TAgg_Font_Table font_table;
font_type fonts_list[] =
{
{ agg::gse4x6, "gse4x6" },
{ agg::gse4x8, "gse4x8" },
{ agg::gse5x7, "gse5x7" },
{ agg::gse5x9, "gse5x9" },
{ agg::gse6x9, "gse6x9" },
{ agg::gse6x12, "gse6x12" },
{ agg::gse7x11, "gse7x11" },
{ agg::gse7x11_bold, "gse7x11_bold" },
{ agg::gse7x15, "gse7x15" },
{ agg::gse7x15_bold, "gse7x15_bold" },
{ agg::gse8x16, "gse8x16" },
{ agg::gse8x16_bold, "gse8x16_bold" },
{ agg::mcs11_prop, "mcs11_prop" },
{ agg::mcs11_prop_condensed, "mcs11_prop_condensed" },
{ agg::mcs12_prop, "mcs12_prop" },
{ agg::mcs13_prop, "mcs13_prop" },
{ agg::mcs5x10_mono, "mcs5x10_mono" },
{ agg::mcs5x11_mono, "mcs5x11_mono" },
{ agg::mcs6x10_mono, "mcs6x10_mono" },
{ agg::mcs6x11_mono, "mcs6x11_mono" },
{ agg::mcs7x12_mono_high, "mcs7x12_mono_high" },
{ agg::mcs7x12_mono_low, "mcs7x12_mono_low" },
{ agg::verdana12, "verdana12" },
{ agg::verdana12_bold, "verdana12_bold" },
{ agg::verdana13, "verdana13" },
{ agg::verdana13_bold, "verdana13_bold" },
{ agg::verdana14, "verdana14" },
{ agg::verdana14_bold, "verdana14_bold" },
{ agg::verdana16, "verdana16" },
{ agg::verdana16_bold, "verdana16_bold" },
{ agg::verdana17, "verdana17" },
{ agg::verdana17_bold, "verdana17_bold" },
{ agg::verdana18, "verdana18" },
{ agg::verdana18_bold, "verdana18_bold" },
};
int font_Nums = ARRAY_SIZE(fonts_list);
const agg::int8u* AggDrawTarget::lookupFont(const std::string& name)
{
TAgg_Font_Table::iterator it(font_table.find(name));
if(it == font_table.end()) return NULL;
else return it->second;
}
static void Agg_init_fonts()
{
for(u32 i=0;i<font_Nums;i++)
font_table[fonts_list[i].name] = fonts_list[i].font;
}
AggDraw_Desmume aggDraw;
#if defined(WIN32) || defined(HOST_LINUX)
T_AGG_RGBA agg_targetScreen(0, 256, 384, 1024);
#else
T_AGG_RGB555 agg_targetScreen(0, 256, 384, 1512);
#endif
static u32 luaBuffer[256*192*2];
T_AGG_RGBA agg_targetLua((u8*)luaBuffer, 256, 384, 1024);
static u32 hudBuffer[256*192*2];
T_AGG_RGBA agg_targetHud((u8*)hudBuffer, 256, 384, 1024);
static AggDrawTarget* targets[] = {
&agg_targetScreen,
&agg_targetHud,
&agg_targetLua,
};
void Agg_init()
{
Agg_init_fonts();
aggDraw.screen = targets[0];
aggDraw.hud = targets[1];
aggDraw.lua = targets[2];
aggDraw.target = targets[0];
//if we're single core, we don't want to waste time compositing
//and the more clever compositing isnt supported in non-windows
#ifdef WIN32
if(CommonSettings.single_core())
aggDraw.hud = &agg_targetScreen;
#else
aggDraw.hud = &agg_targetScreen;
#endif
aggDraw.hud->setFont("verdana18_bold");
}
void AggDraw_Desmume::setTarget(AggTarget newTarget)
{
target = targets[newTarget];
}
////temporary, just for testing the lib
//void AGGDraw() {
////
// aggDraw.setTarget(AggTarget_Screen);
//
//// aggDraw.target->clear();
////
//// aggDraw.target->clipBox(0,0,255,383);
////
// aggDraw.target->lineColor(0, 0, 255, 128);
// aggDraw.target->fillColor(0, 0, 255, 128);
//// //aggDraw.target->noFill();
// aggDraw.target->lineWidth(1.0);
// aggDraw.target->roundedRect(10,30,256-10,192-10,4);
////
//// aggDraw.target->setFont("verdana18_bold");
//// aggDraw.target->renderText(60,60, "testing testing testing");
////
//// // Gradients (Aqua Buttons)
//// //=======================================
////// m_graphics.font("Verdana", 20.0, false, false, TAGG2D::VectorFontCache);
//// double xb1 = 10;
//// double yb1 = 80;
//// double xb2 = xb1 + 150;
//// double yb2 = yb1 + 36;
////
//// aggDraw.target->fillColor(0,50,180,180);
//// aggDraw.target->lineColor(0,0,80, 255);
//// aggDraw.target->lineWidth(1.0);
//// aggDraw.target->roundedRect(xb1, yb1, xb2, yb2, 12, 18);
////
//// aggDraw.target->lineColor(0,0,0,0);
//// aggDraw.target->fillLinearGradient(xb1, yb1, xb1, yb1+30,
//// agg::rgba8(100,200,255,255),
//// agg::rgba8(255,255,255,0));
//// aggDraw.target->roundedRect(xb1+3, yb1+2.5, xb2-3, yb1+30, 9, 18, 1, 1);
////
//// aggDraw.target->fillColor(0,0,50, 200);
//// aggDraw.target->noLine();
/////* m_graphics.textAlignment(TAGG2D::AlignCenter, TAGG2D::AlignCenter);
//// m_graphics.text((xb1 + xb2) / 2.0, (yb1 + yb2) / 2.0, "Aqua Button", true, 0.0, 0.0);
////*/
//// aggDraw.target->fillLinearGradient(xb1, yb2-20, xb1, yb2-3,
//// agg::rgba8(0, 0, 255,0),
//// agg::rgba8(100,255,255,255));
//// aggDraw.target->roundedRect(xb1+3, yb2-20, xb2-3, yb2-2, 1, 1, 9, 18);
////
//// // Basic Shapes -- Ellipse
//// //===========================================
//// aggDraw.target->lineWidth(3.5);
//// aggDraw.target->lineColor(20, 80, 80);
//// aggDraw.target->fillColor(200, 255, 80, 200);
//// aggDraw.target->ellipse(150, 200, 50, 90);
////
//// // Paths
//// //===========================================
//// aggDraw.target->resetPath();
//// aggDraw.target->fillColor(255, 0, 0, 100);
//// aggDraw.target->lineColor(0, 0, 255, 100);
//// aggDraw.target->lineWidth(2);
//// aggDraw.target->moveTo(300/2, 200/2);
//// aggDraw.target->horLineRel(-150/2);
//// aggDraw.target->arcRel(150/2, 150/2, 0, 1, 0, 150/2, -150/2);
//// aggDraw.target->closePolygon();
//// aggDraw.target->drawPath();
////
//// aggDraw.target->resetPath();
//// aggDraw.target->fillColor(255, 255, 0, 100);
//// aggDraw.target->lineColor(0, 0, 255, 100);
//// aggDraw.target->lineWidth(2);
//// aggDraw.target->moveTo(275/2, 175/2);
//// aggDraw.target->verLineRel(-150/2);
//// aggDraw.target->arcRel(150/2, 150/2, 0, 0, 0, -150/2, 150/2);
//// aggDraw.target->closePolygon();
//// aggDraw.target->drawPath();
////
//// aggDraw.target->resetPath();
//// aggDraw.target->noFill();
//// aggDraw.target->lineColor(127, 0, 0);
//// aggDraw.target->lineWidth(5);
//// aggDraw.target->moveTo(600/2, 350/2);
//// aggDraw.target->lineRel(50/2, -25/2);
//// aggDraw.target->arcRel(25/2, 25/2, aggDraw.target->deg2Rad(-30), 0, 1, 50/2, -25/2);
//// aggDraw.target->lineRel(50/2, -25/2);
//// aggDraw.target->arcRel(25/2, 50/2, aggDraw.target->deg2Rad(-30), 0, 1, 50/2, -25/2);
//// aggDraw.target->lineRel(50/2, -25/2);
//// aggDraw.target->arcRel(25/2, 75/2, aggDraw.target->deg2Rad(-30), 0, 1, 50/2, -25/2);
//// aggDraw.target->lineRel(50, -25);
//// aggDraw.target->arcRel(25/2, 100/2, aggDraw.target->deg2Rad(-30), 0, 1, 50/2, -25/2);
//// aggDraw.target->lineRel(50/2, -25/2);
//// aggDraw.target->drawPath();
//}
////
//
////========================
////testing stufff
//
//int width = 256;
//int height = 384;
//
//Agg2D m_graphics;
//
//void AGGDraw(unsigned char * buffer)
// {
// m_graphics.attach(buffer,
// 256,
// 384,
// 512);
//
// m_graphics.clearAll(255, 255, 255);
// //m_graphics.clearAll(0, 0, 0);
//
// //m_graphics.blendMode(TAGG2D::BlendSub);
// //m_graphics.blendMode(TAGG2D::BlendAdd);
//
// m_graphics.antiAliasGamma(1.4);
//
// // Set flipText(true) if you have the Y axis upside down.
// //m_graphics.flipText(true);
//
//
// // ClipBox.
// //m_graphics.clipBox(50, 50, rbuf_window().width() - 50, rbuf_window().height() - 50);
//
// // Transfornations - Rotate around (300,300) to 5 degree
// //m_graphics.translate(-300, -300);
// //m_graphics.rotate(TAGG2D::deg2Rad(5.0));
// //m_graphics.translate(300, 300);
//
// // Viewport - set 0,0,600,600 to the actual window size
// // preserving aspect ratio and placing the viewport in the center.
// // To ignore aspect ratio use TAGG2D::Anisotropic
// // Note that the viewport just adds transformations to the current
// // affine matrix. So that, set the viewport *after* all transformations!
// m_graphics.viewport(0, 0, 600, 600,
// 0, 0, width, height,
// //TAGG2D::Anisotropic);
// TAGG2D::XMidYMid);
//
//
// // Rounded Rect
// m_graphics.lineColor(0, 0, 0);
// m_graphics.noFill();
// m_graphics.roundedRect(0.5, 0.5, 600-0.5, 600-0.5, 20.0);
///*
//
// // Reglar Text
// m_graphics.font("Times New Roman", 14.0, false, false);
// m_graphics.fillColor(0, 0, 0);
// m_graphics.noLine();
// m_graphics.text(100, 20, "Regular Raster Text -- Fast, but can't be rotated");
//
// // Outlined Text
// m_graphics.font("Times New Roman", 50.0, false, false, TAGG2D::VectorFontCache);
// m_graphics.lineColor(50, 0, 0);
// m_graphics.fillColor(180, 200, 100);
// m_graphics.lineWidth(1.0);
// m_graphics.text(100.5, 50.5, "Outlined Text");
//
// // Text Alignment
// m_graphics.line(250.5-150, 150.5, 250.5+150, 150.5);
// m_graphics.line(250.5, 150.5-20, 250.5, 150.5+20);
// m_graphics.line(250.5-150, 200.5, 250.5+150, 200.5);
// m_graphics.line(250.5, 200.5-20, 250.5, 200.5+20);
// m_graphics.line(250.5-150, 250.5, 250.5+150, 250.5);
// m_graphics.line(250.5, 250.5-20, 250.5, 250.5+20);
// m_graphics.line(250.5-150, 300.5, 250.5+150, 300.5);
// m_graphics.line(250.5, 300.5-20, 250.5, 300.5+20);
// m_graphics.line(250.5-150, 350.5, 250.5+150, 350.5);
// m_graphics.line(250.5, 350.5-20, 250.5, 350.5+20);
// m_graphics.line(250.5-150, 400.5, 250.5+150, 400.5);
// m_graphics.line(250.5, 400.5-20, 250.5, 400.5+20);
// m_graphics.line(250.5-150, 450.5, 250.5+150, 450.5);
// m_graphics.line(250.5, 450.5-20, 250.5, 450.5+20);
// m_graphics.line(250.5-150, 500.5, 250.5+150, 500.5);
// m_graphics.line(250.5, 500.5-20, 250.5, 500.5+20);
// m_graphics.line(250.5-150, 550.5, 250.5+150, 550.5);
// m_graphics.line(250.5, 550.5-20, 250.5, 550.5+20);
//*/
///*
// m_graphics.fillColor(100, 50, 50);
// m_graphics.noLine();
// //m_graphics.textHints(false);
// m_graphics.font("Times New Roman", 40.0, false, false, TAGG2D::VectorFontCache);
//
// m_graphics.textAlignment(TAGG2D::AlignLeft, TAGG2D::AlignBottom);
// m_graphics.text(250.0, 150.0, "Left-Bottom", true, 0, 0);
//
// m_graphics.textAlignment(TAGG2D::AlignCenter, TAGG2D::AlignBottom);
// m_graphics.text(250.0, 200.0, "Center-Bottom", true, 0, 0);
//
// m_graphics.textAlignment(TAGG2D::AlignRight, TAGG2D::AlignBottom);
// m_graphics.text(250.0, 250.0, "Right-Bottom", true, 0, 0);
//
// m_graphics.textAlignment(TAGG2D::AlignLeft, TAGG2D::AlignCenter);
// m_graphics.text(250.0, 300.0, "Left-Center", true, 0, 0);
//
// m_graphics.textAlignment(TAGG2D::AlignCenter, TAGG2D::AlignCenter);
// m_graphics.text(250.0, 350.0, "Center-Center", true, 0, 0);
//
// m_graphics.textAlignment(TAGG2D::AlignRight, TAGG2D::AlignCenter);
// m_graphics.text(250.0, 400.0, "Right-Center", true, 0, 0);
//
// m_graphics.textAlignment(TAGG2D::AlignLeft, TAGG2D::AlignTop);
// m_graphics.text(250.0, 450.0, "Left-Top", true, 0, 0);
//
// m_graphics.textAlignment(TAGG2D::AlignCenter, TAGG2D::AlignTop);
// m_graphics.text(250.0, 500.0, "Center-Top", true, 0, 0);
//
// m_graphics.textAlignment(TAGG2D::AlignRight, TAGG2D::AlignTop);
// m_graphics.text(250.0, 550.0, "Right-Top", true, 0, 0);
//
//*/
// // Gradients (Aqua Buttons)
// //=======================================
// m_graphics.font("Verdana", 20.0, false, false, TAGG2D::VectorFontCache);
// double xb1 = 400;
// double yb1 = 80;
// double xb2 = xb1 + 150;
// double yb2 = yb1 + 36;
//
// m_graphics.fillColor(TAGG2D::Color(0,50,180,180));
// m_graphics.lineColor(TAGG2D::Color(0,0,80, 255));
// m_graphics.lineWidth(1.0);
// m_graphics.roundedRect(xb1, yb1, xb2, yb2, 12, 18);
//
// m_graphics.lineColor(TAGG2D::Color(0,0,0,0));
// m_graphics.fillLinearGradient(xb1, yb1, xb1, yb1+30,
// TAGG2D::Color(100,200,255,255),
// TAGG2D::Color(255,255,255,0));
// m_graphics.roundedRect(xb1+3, yb1+2.5, xb2-3, yb1+30, 9, 18, 1, 1);
//
// m_graphics.fillColor(TAGG2D::Color(0,0,50, 200));
// m_graphics.noLine();
///* m_graphics.textAlignment(TAGG2D::AlignCenter, TAGG2D::AlignCenter);
// m_graphics.text((xb1 + xb2) / 2.0, (yb1 + yb2) / 2.0, "Aqua Button", true, 0.0, 0.0);
//*/
// m_graphics.fillLinearGradient(xb1, yb2-20, xb1, yb2-3,
// TAGG2D::Color(0, 0, 255,0),
// TAGG2D::Color(100,255,255,255));
// m_graphics.roundedRect(xb1+3, yb2-20, xb2-3, yb2-2, 1, 1, 9, 18);
//
//
// // Aqua Button Pressed
// xb1 = 400;
// yb1 = 30;
// xb2 = xb1 + 150;
// yb2 = yb1 + 36;
//
// m_graphics.fillColor(TAGG2D::Color(0,50,180,180));
// m_graphics.lineColor(TAGG2D::Color(0,0,0, 255));
// m_graphics.lineWidth(2.0);
// m_graphics.roundedRect(xb1, yb1, xb2, yb2, 12, 18);
//
// m_graphics.lineColor(TAGG2D::Color(0,0,0,0));
// m_graphics.fillLinearGradient(xb1, yb1+2, xb1, yb1+25,
// TAGG2D::Color(60, 160,255,255),
// TAGG2D::Color(100,255,255,0));
// m_graphics.roundedRect(xb1+3, yb1+2.5, xb2-3, yb1+30, 9, 18, 1, 1);
//
// m_graphics.fillColor(TAGG2D::Color(0,0,50, 255));
// m_graphics.noLine();
///* m_graphics.textAlignment(TAGG2D::AlignCenter, TAGG2D::AlignCenter);
// m_graphics.text((xb1 + xb2) / 2.0, (yb1 + yb2) / 2.0, "Aqua Pressed", 0.0, 0.0);
//*/
// m_graphics.fillLinearGradient(xb1, yb2-25, xb1, yb2-5,
// TAGG2D::Color(0, 180,255,0),
// TAGG2D::Color(0, 200,255,255));
// m_graphics.roundedRect(xb1+3, yb2-25, xb2-3, yb2-2, 1, 1, 9, 18);
//
//
//
//
// // Basic Shapes -- Ellipse
// //===========================================
// m_graphics.lineWidth(3.5);
// m_graphics.lineColor(20, 80, 80);
// m_graphics.fillColor(200, 255, 80, 200);
// m_graphics.ellipse(450, 200, 50, 90);
//
//
// // Paths
// //===========================================
// m_graphics.resetPath();
// m_graphics.fillColor(255, 0, 0, 100);
// m_graphics.lineColor(0, 0, 255, 100);
// m_graphics.lineWidth(2);
// m_graphics.moveTo(300/2, 200/2);
// m_graphics.horLineRel(-150/2);
// m_graphics.arcRel(150/2, 150/2, 0, 1, 0, 150/2, -150/2);
// m_graphics.closePolygon();
// m_graphics.drawPath();
//
// m_graphics.resetPath();
// m_graphics.fillColor(255, 255, 0, 100);
// m_graphics.lineColor(0, 0, 255, 100);
// m_graphics.lineWidth(2);
// m_graphics.moveTo(275/2, 175/2);
// m_graphics.verLineRel(-150/2);
// m_graphics.arcRel(150/2, 150/2, 0, 0, 0, -150/2, 150/2);
// m_graphics.closePolygon();
// m_graphics.drawPath();
//
//
// m_graphics.resetPath();
// m_graphics.noFill();
// m_graphics.lineColor(127, 0, 0);
// m_graphics.lineWidth(5);
// m_graphics.moveTo(600/2, 350/2);
// m_graphics.lineRel(50/2, -25/2);
// m_graphics.arcRel(25/2, 25/2, TAGG2D::deg2Rad(-30), 0, 1, 50/2, -25/2);
// m_graphics.lineRel(50/2, -25/2);
// m_graphics.arcRel(25/2, 50/2, TAGG2D::deg2Rad(-30), 0, 1, 50/2, -25/2);
// m_graphics.lineRel(50/2, -25/2);
// m_graphics.arcRel(25/2, 75/2, TAGG2D::deg2Rad(-30), 0, 1, 50/2, -25/2);
// m_graphics.lineRel(50, -25);
// m_graphics.arcRel(25/2, 100/2, TAGG2D::deg2Rad(-30), 0, 1, 50/2, -25/2);
// m_graphics.lineRel(50/2, -25/2);
// m_graphics.drawPath();
//
//
// // Master Alpha. From now on everything will be translucent
// //===========================================
// m_graphics.masterAlpha(0.85);
//
//
// // Image Transformations
// //===========================================
///* TAGG2D::Image img(rbuf_img(0).buf(),
// rbuf_img(0).width(),
// rbuf_img(0).height(),
// rbuf_img(0).stride());
// m_graphics.imageFilter(TAGG2D::Bilinear);
//
// //m_graphics.imageResample(TAGG2D::NoResample);
// //m_graphics.imageResample(TAGG2D::ResampleAlways);
// m_graphics.imageResample(TAGG2D::ResampleOnZoomOut);
//
// // Set the initial image blending operation as BlendDst, that actually
// // does nothing.
// //-----------------
// m_graphics.imageBlendMode(TAGG2D::BlendDst);
//
//
// // Transform the whole image to the destination rectangle
// //-----------------
// //m_graphics.transformImage(img, 450, 200, 595, 350);
//
// // Transform the rectangular part of the image to the destination rectangle
// //-----------------
// //m_graphics.transformImage(img, 60, 60, img.width()-60, img.height()-60,
// // 450, 200, 595, 350);
//
// // Transform the whole image to the destination parallelogram
// //-----------------
// //double parl[6] = { 450, 200, 595, 220, 575, 350 };
// //m_graphics.transformImage(img, parl);
//
// // Transform the rectangular part of the image to the destination parallelogram
// //-----------------
// //double parl[6] = { 450, 200, 595, 220, 575, 350 };
// //m_graphics.transformImage(img, 60, 60, img.width()-60, img.height()-60, parl);
//
// // Transform image to the destination path. The scale is determined by a rectangle
// //-----------------
// //m_graphics.resetPath();
// //m_graphics.moveTo(450, 200);
// //m_graphics.cubicCurveTo(595, 220, 575, 350, 595, 350);
// //m_graphics.lineTo(470, 340);
// //m_graphics.transformImagePath(img, 450, 200, 595, 350);
//
//
// // Transform image to the destination path.
// // The scale is determined by a rectangle
// //-----------------
// m_graphics.resetPath();
// m_graphics.moveTo(450, 200);
// m_graphics.cubicCurveTo(595, 220, 575, 350, 595, 350);
// m_graphics.lineTo(470, 340);
// m_graphics.transformImagePath(img, 60, 60, img.width()-60, img.height()-60,
// 450, 200, 595, 350);
//
// // Transform image to the destination path.
// // The transformation is determined by a parallelogram
// //m_graphics.resetPath();
// //m_graphics.moveTo(450, 200);
// //m_graphics.cubicCurveTo(595, 220, 575, 350, 595, 350);
// //m_graphics.lineTo(470, 340);
// //double parl[6] = { 450, 200, 595, 220, 575, 350 };
// //m_graphics.transformImagePath(img, parl);
//
// // Transform the rectangular part of the image to the destination path.
// // The transformation is determined by a parallelogram
// //m_graphics.resetPath();
// //m_graphics.moveTo(450, 200);
// //m_graphics.cubicCurveTo(595, 220, 575, 350, 595, 350);
// //m_graphics.lineTo(470, 340);
// //double parl[6] = { 450, 200, 595, 220, 575, 350 };
// //m_graphics.transformImagePath(img, 60, 60, img.width()-60, img.height()-60, parl);
//*/
//
// // Add/Sub/Contrast Blending Modes
// m_graphics.noLine();
// m_graphics.fillColor(70, 70, 0);
// m_graphics.blendMode(TAGG2D::BlendAdd);
// m_graphics.ellipse(500, 280, 20, 40);
//
// m_graphics.fillColor(255, 255, 255);
// m_graphics.blendMode(TAGG2D::BlendContrast);
// m_graphics.ellipse(500+40, 280, 20, 40);
//
//
//
// // Radial gradient.
// m_graphics.blendMode(TAGG2D::BlendAlpha);
// m_graphics.fillRadialGradient(400, 500, 40,
// TAGG2D::Color(255, 255, 0, 0),
// TAGG2D::Color(0, 0, 127),
// TAGG2D::Color(0, 255, 0, 0));
// m_graphics.ellipse(400, 500, 40, 40);
//
// }
//
Executable
+674
View File
@@ -0,0 +1,674 @@
/*
The MIT License
Copyright (C) 2009-2010 DeSmuME team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
//This file contains code designed to be used by hud and lua systems in any emulator
#ifndef _AGGDRAW_H_
#define _AGGDRAW_H_
#include "agg_color_rgba.h"
#include "agg_rendering_buffer.h"
#include "agg_renderer_base.h"
#include "agg_renderer_primitives.h"
#include "agg_renderer_scanline.h"
#include "agg_bounding_rect.h"
#include "agg_renderer_mclip.h"
#include "agg_renderer_outline_aa.h"
#include "agg_renderer_markers.h"
#include "agg_pixfmt_rgb.h"
#include "agg_pixfmt_rgba.h"
#include "agg_pixfmt_rgb_packed.h"
#include "agg2d.h"
typedef agg::rgba8 AggColor;
namespace agg
{
//NOTE - these blenders are necessary to change the rgb order from the defaults, which are incorrect for us
//this custom blender does more correct blending math than the default
//which is necessary or else drawing transparent pixels on (31,31,31) will yield (30,30,30)
struct my_blender_rgb555_pre
{
typedef rgba8 color_type;
typedef color_type::value_type value_type;
typedef color_type::calc_type calc_type;
typedef int16u pixel_type;
static AGG_INLINE void blend_pix(pixel_type* p,
unsigned cr, unsigned cg, unsigned cb,
unsigned alpha,
unsigned cover)
{
//not sure whether this is right...
alpha = color_type::base_mask - alpha;
pixel_type rgb = *p;
calc_type b = (rgb >> 10) & 31;
calc_type g = (rgb >> 5) & 31;
calc_type r = (rgb ) & 31;
b = ((b+1)*(alpha+1) + (cb)*(cover)-1)>>8;
g = ((g+1)*(alpha+1) + (cg)*(cover)-1)>>8;
r = ((r+1)*(alpha+1) + (cr)*(cover)-1)>>8;
*p = (b<<10)|(g<<5)|r;
}
static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
{
return (pixel_type)(((b & 0xF8) << 7) |
((g & 0xF8) << 2) |
(r >> 3) | 0x8000);
}
static AGG_INLINE color_type make_color(pixel_type p)
{
return color_type((p << 3) & 0xF8,
(p >> 2) & 0xF8,
(p >> 7) & 0xF8);
}
};
struct my_blender_rgb555
{
typedef rgba8 color_type;
typedef color_type::value_type value_type;
typedef color_type::calc_type calc_type;
typedef int16u pixel_type;
static AGG_INLINE void blend_pix(pixel_type* p,
unsigned cr, unsigned cg, unsigned cb,
unsigned alpha,
unsigned)
{
pixel_type rgb = *p;
calc_type b = (rgb >> 7) & 0xF8;
calc_type g = (rgb >> 2) & 0xF8;
calc_type r = (rgb << 3) & 0xF8;
*p = (pixel_type)
(((((cb - b) * alpha + (b << 8)) >> 1) & 0x7C00) |
((((cg - g) * alpha + (g << 8)) >> 6) & 0x03E0) |
(((cr - r) * alpha + (r << 8)) >> 11) | 0x8000);
}
static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b)
{
return (pixel_type)(((b & 0xF8) << 7) |
((g & 0xF8) << 2) |
(r >> 3) | 0x8000);
}
static AGG_INLINE color_type make_color(pixel_type p)
{
return color_type((p << 3) & 0xF8,
(p >> 2) & 0xF8,
(p >> 7) & 0xF8);
}
};
//this is a prototype span generator which should be able to generate 8888 and 555 spans
//it would be used in agg2d.inl renderImage()
//but it isn't being used yet.
//this will need to be completed before we can use 555 as a source imge
template<class Order> class span_simple_blur_rgb24
{
public:
//--------------------------------------------------------------------
typedef rgba8 color_type;
//--------------------------------------------------------------------
span_simple_blur_rgb24() : m_source_image(0) {}
//--------------------------------------------------------------------
span_simple_blur_rgb24(const rendering_buffer& src) :
m_source_image(&src) {}
//--------------------------------------------------------------------
void source_image(const rendering_buffer& src) { m_source_image = &src; }
const rendering_buffer& source_image() const { return *m_source_image; }
//--------------------------------------------------------------------
void prepare() {}
//--------------------------------------------------------------------
void generate(color_type* span, int x, int y, int len)
{
if(y < 1 || y >= int(m_source_image->height() - 1))
{
do
{
*span++ = rgba8(0,0,0,0);
}
while(--len);
return;
}
do
{
int color[4];
color[0] = color[1] = color[2] = color[3] = 0;
if(x > 0 && x < int(m_source_image->width()-1))
{
int i = 3;
do
{
const int8u* ptr = m_source_image->row_ptr(y - i + 2) + (x - 1) * 3;
color[0] += *ptr++;
color[1] += *ptr++;
color[2] += *ptr++;
color[3] += 255;
color[0] += *ptr++;
color[1] += *ptr++;
color[2] += *ptr++;
color[3] += 255;
color[0] += *ptr++;
color[1] += *ptr++;
color[2] += *ptr++;
color[3] += 255;
}
while(--i);
color[0] /= 9;
color[1] /= 9;
color[2] /= 9;
color[3] /= 9;
}
*span++ = rgba8(color[Order::R], color[Order::G], color[Order::B], color[3]);
++x;
}
while(--len);
}
private:
const rendering_buffer* m_source_image;
};
typedef pixfmt_alpha_blend_rgb_packed<my_blender_rgb555_pre, rendering_buffer> my_pixfmt_rgb555_pre; //----pixfmt_rgb555_pre
typedef pixfmt_alpha_blend_rgb_packed<my_blender_rgb555, rendering_buffer> my_pixfmt_rgb555; //----pixfmt_rgb555_pre
}
typedef PixFormatSetDeclaration<agg::my_pixfmt_rgb555,agg::my_pixfmt_rgb555_pre,agg::span_simple_blur_rgb24<agg::order_rgba> > T_AGG_PF_RGB555;
typedef PixFormatSetDeclaration<agg::pixfmt_bgra32,agg::pixfmt_bgra32_pre,agg::span_simple_blur_rgb24<agg::order_rgba> > T_AGG_PF_RGBA;
class AggDrawTarget
{
public:
AggDrawTarget()
: empty(true)
{
}
protected:
void dirty() { empty = false; }
void undirty() { empty = true; }
public:
bool empty;
virtual void clear() = 0;
virtual agg::rendering_buffer & buf() = 0;
//returns an image for this target. you must provide the pixel type, but if it is wrong,
//then you have just created trouble for yourself
AGG2D_IMAGE_TEMPLATE TIMAGE image() { return TIMAGE(buf()); }
// Setup
virtual void attach(unsigned char* buf, unsigned width, unsigned height, int stride) = 0;
// virtual void attach(Agg2DBase::Image& img) {attach(img);};
virtual void clipBox(double x1, double y1, double x2, double y2) = 0;
virtual Agg2DBase::RectD clipBox() const = 0;
virtual void clearAll(AggColor c) = 0;
virtual void clearAll(unsigned r, unsigned g, unsigned b, unsigned a = 255) = 0;
virtual void clearClipBox(AggColor c) = 0;
virtual void clearClipBox(unsigned r, unsigned g, unsigned b, unsigned a = 255) = 0;
// virtual unsigned width() const { return Agg2DBase::m_rbuf.width(); }
// virtual unsigned height() const { return Agg2DBase::m_rbuf.height(); }
// Conversions
virtual void worldToScreen(double& x, double& y) const = 0;
virtual void screenToWorld(double& x, double& y) const = 0;
virtual double worldToScreen(double scalar) const = 0;
virtual double screenToWorld(double scalar) const = 0;
virtual void alignPoint(double& x, double& y) const = 0;
virtual bool inBox(double worldX, double worldY) const = 0;
// General Attributes
virtual void blendMode(Agg2DBase::BlendMode m) = 0;
virtual Agg2DBase::BlendMode blendMode() = 0;
virtual void imageBlendMode(Agg2DBase::BlendMode m) = 0;
virtual Agg2DBase::BlendMode imageBlendMode() = 0;
virtual void imageBlendColor(AggColor c) = 0;
virtual void imageBlendColor(unsigned r, unsigned g, unsigned b, unsigned a = 255) = 0;
virtual AggColor imageBlendColor() = 0;
virtual void masterAlpha(double a) = 0;
virtual double masterAlpha() = 0;
virtual void antiAliasGamma(double g) = 0;
virtual double antiAliasGamma() = 0;
// virtual void font(const agg::int8u* font) { m_font = font; }
// const agg::int8u* font() { return m_font; }
virtual void fillColor(AggColor c) = 0;
virtual void fillColor(unsigned r, unsigned g, unsigned b, unsigned a = 255) = 0;
virtual void noFill() = 0;
virtual void lineColor(AggColor c) = 0;
virtual void lineColor(unsigned r, unsigned g, unsigned b, unsigned a = 255) = 0;
virtual void noLine() = 0;
virtual void transformImage(const Agg2DBase::Image<T_AGG_PF_RGBA> &img, double dstX1, double dstY1, double dstX2, double dstY2) = 0;
//virtual void transformImage(const Agg2DBase::Image<T_AGG_PF_RGB555> &img, double dstX1, double dstY1, double dstX2, double dstY2) = 0;
virtual AggColor fillColor() = 0;
virtual AggColor lineColor() = 0;
virtual void fillLinearGradient(double x1, double y1, double x2, double y2, AggColor c1, AggColor c2, double profile=1.0) = 0;
virtual void lineLinearGradient(double x1, double y1, double x2, double y2, AggColor c1, AggColor c2, double profile=1.0) = 0;
virtual void fillRadialGradient(double x, double y, double r, AggColor c1, AggColor c2, double profile=1.0) = 0;
virtual void lineRadialGradient(double x, double y, double r, AggColor c1, AggColor c2, double profile=1.0) = 0;
virtual void fillRadialGradient(double x, double y, double r, AggColor c1, AggColor c2, AggColor c3) = 0;
virtual void lineRadialGradient(double x, double y, double r, AggColor c1, AggColor c2, AggColor c3) = 0;
virtual void fillRadialGradient(double x, double y, double r) = 0;
virtual void lineRadialGradient(double x, double y, double r) = 0;
virtual void lineWidth(double w) = 0;
virtual double lineWidth() = 0;
virtual void lineCap(Agg2DBase::LineCap cap) = 0;
virtual Agg2DBase::LineCap lineCap() = 0;
virtual void lineJoin(Agg2DBase::LineJoin join) = 0;
virtual Agg2DBase::LineJoin lineJoin() = 0;
virtual void fillEvenOdd(bool evenOddFlag) = 0;
virtual bool fillEvenOdd() = 0;
// Transformations
virtual Agg2DBase::Transformations transformations() = 0;
virtual void transformations(const Agg2DBase::Transformations& tr) = 0;
virtual const Agg2DBase::Affine& affine() = 0;
// virtual void affine(const Agg2DBase::Affine&) = 0;
virtual void resetTransformations() = 0;
virtual void matrix(const Agg2DBase::Affine& tr) = 0;
virtual void matrix(const Agg2DBase::Transformations& tr) = 0;
virtual void rotate(double angle) = 0;
virtual void rotate(double angle, double cx, double cy) = 0;
virtual void scale(double s) = 0;
virtual void scale(double sx, double sy) = 0;
virtual void skew(double sx, double sy) = 0;
virtual void translate(double x, double y) = 0;
virtual void parallelogram(double x1, double y1, double x2, double y2, const double* para) = 0;
virtual void viewport(double worldX1, double worldY1, double worldX2, double worldY2, double screenX1, double screenY1, double screenX2, double screenY2, Agg2DBase::ViewportOption opt=Agg2DBase::XMidYMid, Agg2DBase::WindowFitLogic fl = Agg2DBase::WindowFitLogic_meet) = 0;
// Basic Shapes
virtual void line(double x1, double y1, double x2, double y2) = 0;
virtual void triangle(double x1, double y1, double x2, double y2, double x3, double y3) = 0;
virtual void rectangle(double x1, double y1, double x2, double y2) = 0;
virtual void roundedRect(double x1, double y1, double x2, double y2, double r) = 0;
virtual void roundedRect(double x1, double y1, double x2, double y2, double rx, double ry) = 0;
virtual void roundedRect(double x1, double y1, double x2, double y2, double rxBottom, double ryBottom, double rxTop, double ryTop) = 0;
virtual void ellipse(double cx, double cy, double rx, double ry) = 0;
virtual void arc(double cx, double cy, double rx, double ry, double start, double sweep) = 0;
virtual void star(double cx, double cy, double r1, double r2, double startAngle, int numRays) = 0;
virtual void curve(double x1, double y1, double x2, double y2, double x3, double y3) = 0;
virtual void curve(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) = 0;
virtual void polygon(double* xy, int numPoints) = 0;
virtual void polyline(double* xy, int numPoints) = 0;
// Path commands
virtual void resetPath() = 0;
virtual void moveTo(double x, double y)= 0;
virtual void moveRel(double dx, double dy) = 0;
virtual void lineTo(double x, double y) = 0;
virtual void lineRel(double dx, double dy) = 0;
virtual void horLineTo(double x) = 0;
virtual void horLineRel(double dx) = 0;
virtual void verLineTo(double y) = 0;
virtual void verLineRel(double dy) = 0;
virtual void arcTo(double rx, double ry,double angle, bool largeArcFlag,bool sweepFlag,double x, double y) = 0;
virtual void arcRel(double rx, double ry,double angle, bool largeArcFlag,bool sweepFlag,double dx, double dy) = 0;
virtual void quadricCurveTo(double xCtrl, double yCtrl,double xTo, double yTo) = 0;
virtual void quadricCurveRel(double dxCtrl, double dyCtrl,double dxTo, double dyTo) = 0;
virtual void quadricCurveTo(double xTo, double yTo) = 0;
virtual void quadricCurveRel(double dxTo, double dyTo) = 0;
virtual void cubicCurveTo(double xCtrl1, double yCtrl1,double xCtrl2, double yCtrl2,double xTo, double yTo) = 0;
virtual void cubicCurveRel(double dxCtrl1, double dyCtrl1,double dxCtrl2, double dyCtrl2,double dxTo, double dyTo) = 0;
virtual void cubicCurveTo(double xCtrl2, double yCtrl2,double xTo, double yTo) = 0;
virtual void cubicCurveRel(double xCtrl2, double yCtrl2,double xTo, double yTo) = 0;
virtual void addEllipse(double cx, double cy, double rx, double ry, Agg2DBase::Direction dir) = 0;
virtual void closePolygon() = 0;
virtual void drawPath(Agg2DBase::DrawPathFlag flag = Agg2DBase::FillAndStroke) = 0;
// virtual void drawPathNoTransform(Agg2DBase::DrawPathFlag flag = Agg2DBase::FillAndStroke) = 0;
// Image Transformations
virtual void imageFilter(Agg2DBase::ImageFilter f) = 0;
virtual Agg2DBase::ImageFilter imageFilter() = 0;
virtual void imageResample(Agg2DBase::ImageResample f) = 0;
virtual Agg2DBase::ImageResample imageResample() = 0;
static const agg::int8u* lookupFont(const std::string& name);
virtual void setFont(const std::string& name) = 0;
virtual void renderText(double dstX, double dstY, const std::string& str) = 0;
virtual void renderTextDropshadowed(double dstX, double dstY, const std::string& str)
{
AggColor lineColorOld = lineColor();
if(lineColorOld.r+lineColorOld.g+lineColorOld.b<192)
lineColor(255-lineColorOld.r,255-lineColorOld.g,255-lineColorOld.b);
else
lineColor(0,0,0);
renderText(dstX-1,dstY-1,str);
renderText(dstX,dstY-1,str);
renderText(dstX+1,dstY-1,str);
renderText(dstX-1,dstY,str);
renderText(dstX+1,dstY,str);
renderText(dstX-1,dstY+1,str);
renderText(dstX,dstY+1,str);
renderText(dstX+1,dstY+1,str);
lineColor(lineColorOld);
renderText(dstX,dstY,str);
}
// Auxiliary
virtual double pi() { return agg::pi; }
virtual double deg2Rad(double v) { return v * agg::pi / 180.0; }
virtual double rad2Deg(double v) { return v * 180.0 / agg::pi; }
};
template<typename PixFormatSet>
class AggDrawTargetImplementation : public AggDrawTarget, public Agg2D<PixFormatSet>
{
public:
typedef typename PixFormatSet::PixFormat pixfmt;
typedef typename pixfmt::color_type color_type;
typedef Agg2D<PixFormatSet> BASE;
AggDrawTargetImplementation(agg::int8u* buf, int width, int height, int stride)
{
BASE::attach(buf,width,height,stride);
BASE::viewport(0, 0, width-1, height-1, 0, 0, width-1, height-1, TAGG2D::Anisotropic);
}
virtual void clear() {
if(!empty)
{
BASE::clearAll(0,0,0,0);
undirty();
}
}
virtual agg::rendering_buffer & buf() { dirty(); return BASE::buf(); } // buf() might not always require calling dirty()
typename BASE::MyImage image() { return BASE::MyImage(buf()); }
// Setup
virtual void attach(unsigned char* buf, unsigned width, unsigned height, int stride) {BASE::attach(buf, width, height, stride);};
// virtual void attach(Agg2DBase::Image& img) {attach(img);};
virtual void clipBox(double x1, double y1, double x2, double y2) { BASE::clipBox(x1,y1,x2,y2); }
virtual Agg2DBase::RectD clipBox() const {return BASE::clipBox();};
virtual void clearAll(AggColor c) {BASE::clearAll(c);};
virtual void clearAll(unsigned r, unsigned g, unsigned b, unsigned a = 255) {BASE::clearAll(r, g, b, a);};
virtual void clearClipBox(AggColor c) {BASE::clearClipBox(c);};
virtual void clearClipBox(unsigned r, unsigned g, unsigned b, unsigned a = 255) {BASE::clearClipBox(r, g, b, a);};
// virtual unsigned width() const { return Agg2DBase::m_rbuf.width(); }
// virtual unsigned height() const { return Agg2DBase::m_rbuf.height(); }
// Conversions
virtual void worldToScreen(double& x, double& y) const {BASE::worldToScreen(x, y);};
virtual void screenToWorld(double& x, double& y) const {BASE::screenToWorld(x, y);};
virtual double worldToScreen(double scalar) const {return BASE::worldToScreen(scalar);};
virtual double screenToWorld(double scalar) const {return BASE::screenToWorld(scalar);};
virtual void alignPoint(double& x, double& y) const {BASE::alignPoint(x, y);};
virtual bool inBox(double worldX, double worldY) const {return BASE::inBox(worldX, worldY);};
// General Attributes
virtual void blendMode(Agg2DBase::BlendMode m) {BASE::blendMode(m);};
virtual Agg2DBase::BlendMode blendMode() {return BASE::blendMode();};
virtual void imageBlendMode(Agg2DBase::BlendMode m) {BASE::imageBlendMode(m);};
virtual Agg2DBase::BlendMode imageBlendMode() {return BASE::imageBlendMode();};
virtual void imageBlendColor(AggColor c) {BASE::imageBlendColor(c);};
virtual void imageBlendColor(unsigned r, unsigned g, unsigned b, unsigned a = 255) {BASE::imageBlendColor(r, g, b, a);};
virtual AggColor imageBlendColor() {return BASE::imageBlendColor();};
virtual void masterAlpha(double a) {BASE::masterAlpha(a);};
virtual double masterAlpha() {return BASE::masterAlpha();};
virtual void antiAliasGamma(double g) {BASE::antiAliasGamma(g);};
virtual double antiAliasGamma() {return BASE::antiAliasGamma();};
// virtual void font(const agg::int8u* font) { m_font = font; }
// const agg::int8u* font() { return m_font; }
virtual void fillColor(AggColor c) {BASE::fillColor(c);};
virtual void fillColor(unsigned r, unsigned g, unsigned b, unsigned a = 255) {BASE::fillColor(r,g,b,a);};
virtual void noFill() {BASE::noFill();};
virtual void lineColor(AggColor c) {BASE::lineColor(c);};
virtual void lineColor(unsigned r, unsigned g, unsigned b, unsigned a = 255) {BASE::lineColor(r,g,b,a);};
virtual void noLine() {BASE::noLine();};
virtual AggColor fillColor() {return BASE::fillColor();};
virtual AggColor lineColor() {return BASE::lineColor();};
virtual void fillLinearGradient(double x1, double y1, double x2, double y2, AggColor c1, AggColor c2, double profile=1.0) {dirty(); BASE::fillLinearGradient(x1, y1, x2, y2, c1, c2, profile);};
virtual void lineLinearGradient(double x1, double y1, double x2, double y2, AggColor c1, AggColor c2, double profile=1.0) {dirty(); BASE::lineLinearGradient(x1, y1, x2, y2, c1, c2, profile);};
virtual void fillRadialGradient(double x, double y, double r, AggColor c1, AggColor c2, double profile=1.0) {dirty(); BASE::fillRadialGradient(x, y, r, c1, c2, profile);};
virtual void lineRadialGradient(double x, double y, double r, AggColor c1, AggColor c2, double profile=1.0) {dirty(); BASE::lineRadialGradient(x, y, r, c1, c2, profile);};
virtual void fillRadialGradient(double x, double y, double r, AggColor c1, AggColor c2, AggColor c3) {dirty(); BASE::fillRadialGradient(x, y, r, c1, c2, c3);};
virtual void lineRadialGradient(double x, double y, double r, AggColor c1, AggColor c2, AggColor c3) {dirty(); BASE::lineRadialGradient(x, y, r, c1, c2, c3);};
virtual void fillRadialGradient(double x, double y, double r) {dirty(); BASE::fillRadialGradient(x, y, r);};
virtual void lineRadialGradient(double x, double y, double r) {dirty(); BASE::lineRadialGradient(x, y, r);};
virtual void lineWidth(double w) {BASE::lineWidth(w);};
virtual double lineWidth() {return BASE::lineWidth();};
virtual void lineCap(Agg2DBase::LineCap cap) {BASE::lineCap(cap);};
virtual Agg2DBase::LineCap lineCap() {return BASE::lineCap();};
virtual void lineJoin(Agg2DBase::LineJoin join) {BASE::lineJoin(join);};
virtual Agg2DBase::LineJoin lineJoin() {return BASE::lineJoin();};
virtual void fillEvenOdd(bool evenOddFlag) {BASE::fillEvenOdd(evenOddFlag);};
virtual bool fillEvenOdd() {return BASE::fillEvenOdd();};
virtual void transformImage(const Agg2DBase::Image<T_AGG_PF_RGBA>& img, double dstX1, double dstY1, double dstX2, double dstY2) { BASE::transformImage(img,dstX1,dstY1,dstX2,dstY2); }
//virtual void transformImage(const Agg2DBase::Image<T_AGG_PF_RGB555> &img, double dstX1, double dstY1, double dstX2, double dstY2) { BASE::transformImage(img,dstX1,dstY1,dstX2,dstY2); }
// Transformations
virtual Agg2DBase::Transformations transformations() {return BASE::transformations();};
virtual void transformations(const Agg2DBase::Transformations& tr) {BASE::transformations(tr);};
virtual const Agg2DBase::Affine& affine() {return BASE::affine();};
// virtual void affine(const Agg2DBase::Affine&) {BASE::affine();};
virtual void resetTransformations() {BASE::resetTransformations();};
virtual void matrix(const Agg2DBase::Affine& tr) {BASE::matrix(tr);};
virtual void matrix(const Agg2DBase::Transformations& tr) {BASE::matrix(tr);};
virtual void rotate(double angle) {BASE::rotate(angle);};
virtual void rotate(double angle, double cx, double cy) {BASE::rotate(angle, cx, cy);};
virtual void scale(double s) {BASE::scale(s);};
virtual void scale(double sx, double sy) {BASE::scale(sx, sy);};
virtual void skew(double sx, double sy) {BASE::skew(sx, sy);};
virtual void translate(double x, double y) {BASE::translate(x, y);};
virtual void parallelogram(double x1, double y1, double x2, double y2, const double* para) {BASE::parallelogram(x1, y1, x2, y2, para);};
virtual void viewport(double worldX1, double worldY1, double worldX2, double worldY2, double screenX1, double screenY1, double screenX2, double screenY2, Agg2DBase::ViewportOption opt=Agg2DBase::XMidYMid, Agg2DBase::WindowFitLogic fl = Agg2DBase::WindowFitLogic_meet) {BASE::viewport(worldX1, worldY1, worldX2, worldY2, screenX1, screenY1, screenX2, screenY2, opt, fl);};
// Basic Shapes
virtual void line(double x1, double y1, double x2, double y2) {dirty(); BASE::line(x1, y1, x2, y2);};
virtual void triangle(double x1, double y1, double x2, double y2, double x3, double y3) {dirty(); BASE::triangle(x1, y1, x2, y2, x3, y3);};
virtual void rectangle(double x1, double y1, double x2, double y2) {dirty(); BASE::rectangle(x1, y1, x2, y2);};
virtual void roundedRect(double x1, double y1, double x2, double y2, double r) { dirty(); BASE::roundedRect(x1,y1,x2,y2,r); }
virtual void roundedRect(double x1, double y1, double x2, double y2, double rx, double ry) { dirty(); BASE::roundedRect(x1,y1,x2,y2,rx,ry); }
virtual void roundedRect(double x1, double y1, double x2, double y2,double rx_bottom, double ry_bottom,double rx_top,double ry_top) { dirty(); BASE::roundedRect(x1,y1,x2,y2,rx_bottom,ry_bottom,rx_top,ry_top); }
virtual void ellipse(double cx, double cy, double rx, double ry) {dirty(); BASE::ellipse(cx, cy, rx, ry);}
virtual void arc(double cx, double cy, double rx, double ry, double start, double sweep) {dirty(); BASE::arc(cx, cy, rx, ry, start, sweep);};
virtual void star(double cx, double cy, double r1, double r2, double startAngle, int numRays) {dirty(); BASE::star(cx, cy, r1, r2, startAngle, numRays);};
virtual void curve(double x1, double y1, double x2, double y2, double x3, double y3) {dirty(); BASE::curve(x1, y1, x2, y2, x3, y3);};
virtual void curve(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) {dirty(); BASE::curve(x1, y1, x2, y2, x3, y3, x4, y4);};
virtual void polygon(double* xy, int numPoints) {dirty(); BASE::polygon(xy, numPoints);};
virtual void polyline(double* xy, int numPoints) {dirty(); BASE::polyline(xy, numPoints);};
virtual void setFont(const std::string& name) { BASE::font(lookupFont(name)); }
virtual void renderText(double dstX, double dstY, const std::string& str) {
dirty();
int height = BASE::font()[0];
int base = BASE::font()[1];
int offset = height-base*2;
BASE::renderText(dstX, dstY + offset, str);
}
// Path commands
virtual void resetPath() {BASE::resetPath();};
virtual void moveTo(double x, double y) {BASE::moveTo(x, y);}
virtual void moveRel(double dx, double dy) {BASE::moveRel(dx,dy);};
virtual void lineTo(double x, double y) {BASE::lineTo(x, y);};
virtual void lineRel(double dx, double dy) {BASE::lineRel(dx, dy);};
virtual void horLineTo(double x) {BASE::horLineTo(x);};
virtual void horLineRel(double dx) {BASE::horLineRel(dx);};
virtual void verLineTo(double y) {BASE::verLineTo(y);};
virtual void verLineRel(double dy) {BASE::verLineRel(dy);};
virtual void arcTo(double rx, double ry, double angle, bool largeArcFlag, bool sweepFlag, double x, double y) {BASE::arcTo(rx, ry, angle, largeArcFlag, sweepFlag, x, y);};
virtual void arcRel(double rx, double ry, double angle, bool largeArcFlag, bool sweepFlag, double dx, double dy) {BASE::arcRel(rx, ry, angle, largeArcFlag, sweepFlag, dx, dy);};
virtual void quadricCurveTo(double xCtrl, double yCtrl, double xTo, double yTo) {BASE::quadricCurveTo(xCtrl, yCtrl, xTo, yTo);};
virtual void quadricCurveRel(double dxCtrl, double dyCtrl, double dxTo, double dyTo) {BASE::quadricCurveRel(dxCtrl, dyCtrl, dxTo, dyTo);};
virtual void quadricCurveTo(double xTo, double yTo) {BASE::quadricCurveTo(xTo, yTo);};
virtual void quadricCurveRel(double dxTo, double dyTo) {BASE::quadricCurveRel(dxTo, dyTo);};
virtual void cubicCurveTo(double xCtrl1, double yCtrl1, double xCtrl2, double yCtrl2, double xTo, double yTo) {BASE::cubicCurveTo(xCtrl1, yCtrl1, xCtrl2, yCtrl2, xTo, yTo);};
virtual void cubicCurveRel(double dxCtrl1, double dyCtrl1, double dxCtrl2, double dyCtrl2, double dxTo, double dyTo) {BASE::cubicCurveRel(dxCtrl1, dyCtrl1, dxCtrl2, dyCtrl2, dxTo, dyTo);};
virtual void cubicCurveTo(double xCtrl2, double yCtrl2, double xTo, double yTo) {BASE::cubicCurveTo(xCtrl2, yCtrl2, xTo, yTo);};
virtual void cubicCurveRel(double xCtrl2, double yCtrl2, double xTo, double yTo) {BASE::cubicCurveRel(xCtrl2, yCtrl2, xTo, yTo);};
virtual void addEllipse(double cx, double cy, double rx, double ry, Agg2DBase::Direction dir) {BASE::addEllipse(cx, cy, rx, ry, dir);};
virtual void closePolygon() {BASE::closePolygon();};
virtual void drawPath(Agg2DBase::DrawPathFlag flag = Agg2DBase::FillAndStroke) {dirty(); BASE::drawPath(flag);};
// virtual void drawPathNoTransform(DrawPathFlag flag = FillAndStroke) {dirty(); BASE::drawPathNoTransform(flag);};
// Image Transformations
virtual void imageFilter(Agg2DBase::ImageFilter f) {BASE::imageFilter(f);};
virtual Agg2DBase::ImageFilter imageFilter() {return BASE::imageFilter();};
virtual void imageResample(Agg2DBase::ImageResample f) {BASE::imageResample(f);};
virtual Agg2DBase::ImageResample imageResample() {return BASE::imageResample();};
// Auxiliary
virtual double pi() { return agg::pi; }
virtual double deg2Rad(double v) { return v * agg::pi / 180.0; }
virtual double rad2Deg(double v) { return v * 180.0 / agg::pi; }
};
//the main aggdraw targets for different pixel formats
typedef AggDrawTargetImplementation<T_AGG_PF_RGB555> T_AGG_RGB555;
typedef AggDrawTargetImplementation<T_AGG_PF_RGBA> T_AGG_RGBA;
class AggDraw
{
public:
AggDraw()
: target(NULL)
{}
AggDrawTarget *target;
};
enum AggTarget
{
AggTarget_Screen = 0,
AggTarget_Hud = 1,
AggTarget_Lua = 2,
};
//specialized instance for desmume; should eventually move to another file
class AggDraw_Desmume : public AggDraw
{
public:
void setTarget(AggTarget newTarget);
//void composite(void* dest);
AggDrawTarget *screen, *hud, *lua;
};
extern AggDraw_Desmume aggDraw;
void Agg_init();
struct font_type
{
const agg::int8u* font;
const char* name;
};
extern font_type fonts_list[];
extern int font_Nums;
#endif
+6295
View File
File diff suppressed because it is too large Load Diff
+4461
View File
File diff suppressed because it is too large Load Diff
Executable
+70
View File
@@ -0,0 +1,70 @@
/* 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();
#if defined(HOST_WINDOWS) || defined(DESMUME_COCOA)
#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
Executable
+785
View File
@@ -0,0 +1,785 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2009-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 <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <algorithm>
#include "armcpu.h"
#include "common.h"
#include "instructions.h"
#include "cp15.h"
#include "bios.h"
#include "debug.h"
#include "Disassembler.h"
#include "NDSSystem.h"
#include "MMU_timing.h"
#ifdef HAVE_LUA
#include "lua-engine.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(&arm_default_ctrl_iface);
armcpu->SetControlInterfaceData(armcpu);
armcpu->SetCurrentMemoryInterface(NULL);
armcpu->SetCurrentMemoryInterfaceData(NULL);
armcpu->post_ex_fn = NULL;
armcpu->post_ex_fn_data = NULL;
armcpu_init(armcpu, 0);
return 0;
}
void armcpu_t::SetControlInterface(const armcpu_ctrl_iface *theControlInterface)
{
this->ctrl_iface = *theControlInterface;
}
armcpu_ctrl_iface* armcpu_t::GetControlInterface()
{
return &this->ctrl_iface;
}
void armcpu_t::SetControlInterfaceData(void *theData)
{
this->ctrl_iface.data = theData;
}
void* armcpu_t::GetControlInterfaceData()
{
return this->ctrl_iface.data;
}
void armcpu_t::SetCurrentMemoryInterface(armcpu_memory_iface *theMemoryInterface)
{
this->mem_if = theMemoryInterface;
}
armcpu_memory_iface* armcpu_t::GetCurrentMemoryInterface()
{
return this->mem_if;
}
void armcpu_t::SetCurrentMemoryInterfaceData(void *theData)
{
if (this->mem_if != NULL)
{
this->mem_if->data = theData;
}
}
void* armcpu_t::GetCurrentMemoryInterfaceData()
{
return (this->mem_if != NULL) ? this->mem_if->data : NULL;
}
void armcpu_t::SetBaseMemoryInterface(const armcpu_memory_iface *theMemInterface)
{
this->base_mem_if = *theMemInterface;
}
armcpu_memory_iface* armcpu_t::GetBaseMemoryInterface()
{
return &this->base_mem_if;
}
void armcpu_t::SetBaseMemoryInterfaceData(void *theData)
{
this->base_mem_if.data = theData;
}
void* armcpu_t::GetBaseMemoryInterfaceData()
{
return this->base_mem_if.data;
}
void armcpu_t::ResetMemoryInterfaceToBase()
{
this->SetCurrentMemoryInterface(this->GetBaseMemoryInterface());
this->SetCurrentMemoryInterfaceData(this->GetBaseMemoryInterfaceData());
}
//call this whenever CPSR is changed (other than CNVZQ or T flags); interrupts may need to be unleashed
void armcpu_t::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->waitIRQ = FALSE;
armcpu->halt_IE_and_IF = FALSE;
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->waitIRQ = TRUE;
cpu->halt_IE_and_IF = TRUE;
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(); 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;
cpu->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->waitIRQ = 0;
//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 (%s) PC=0x%08X\n", cpu->proc_ID?'7':'9', cpu->instruction, decodeIntruction(false, 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();
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 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 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();
}
char* decodeIntruction(bool thumb_mode, u32 instr)
{
char txt[20] = {0};
u32 tmp = 0;
if (thumb_mode == true)
{
tmp = (instr >> 6);
strcpy(txt, intToBin((u16)tmp)+6);
}
else
{
tmp = ((instr >> 16) & 0x0FF0) | ((instr >> 4) & 0x0F);
strcpy(txt, intToBin((u32)tmp)+20);
}
return strdup(txt);
}
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
};
Executable
+352
View File
@@ -0,0 +1,352 @@
/*
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 ARM_CPU
#define ARM_CPU
#include "types.h"
#include "bits.h"
#include "MMU.h"
#define CODE(i) (((i)>>25)&0x7)
#define OPCODE(i) (((i)>>21)&0xF)
#define SIGNEBIT(i) BIT_N(i,20)
#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 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
};
#ifdef WORDS_BIGENDIAN
typedef union
{
struct
{
u32 N : 1,
Z : 1,
C : 1,
V : 1,
Q : 1,
RAZ : 19,
I : 1,
F : 1,
T : 1,
mode : 5;
} bits;
u32 val;
} Status_Reg;
#else
typedef union
{
struct
{
u32 mode : 5,
T : 1,
F : 1,
I : 1,
RAZ : 19,
Q : 1,
V : 1,
C : 1,
Z : 1,
N : 1;
} bits;
u32 val;
} Status_Reg;
#endif
/**
* 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;
void SetControlInterface(const armcpu_ctrl_iface *theCtrlInterface);
armcpu_ctrl_iface* GetControlInterface();
void SetControlInterfaceData(void *theData);
void* GetControlInterfaceData();
void SetCurrentMemoryInterface(armcpu_memory_iface *theMemInterface);
armcpu_memory_iface* GetCurrentMemoryInterface();
void SetCurrentMemoryInterfaceData(void *theData);
void* GetCurrentMemoryInterfaceData();
void SetBaseMemoryInterface(const armcpu_memory_iface *theMemInterface);
armcpu_memory_iface* GetBaseMemoryInterface();
void SetBaseMemoryInterfaceData(void *theData);
void* GetBaseMemoryInterfaceData();
void ResetMemoryInterfaceToBase();
void changeCPSR();
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)
BOOL waitIRQ;
BOOL halt_IE_and_IF; //the cpu is halted, waiting for IE&IF to signal something
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;
};
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);
char* decodeIntruction(bool thumb_mode, u32 instr);
static INLINE void NDS_makeIrq(int PROCNUM, u32 num)
{
setIF(PROCNUM,1<<num);
}
#endif
Executable
+1293
View File
File diff suppressed because it is too large Load Diff
Executable
+28
View File
@@ -0,0 +1,28 @@
/*
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
Executable
+44
View File
@@ -0,0 +1,44 @@
#ifndef BITS_H
#define BITS_H
#define BIT(n) (1<<(n))
#define BIT_N(i,n) (((i)>>(n))&1)
#define BIT0(i) ((i)&1)
#define BIT1(i) BIT_N(i,1)
#define BIT2(i) BIT_N(i,2)
#define BIT3(i) BIT_N(i,3)
#define BIT4(i) BIT_N(i,4)
#define BIT5(i) BIT_N(i,5)
#define BIT6(i) BIT_N(i,6)
#define BIT7(i) BIT_N(i,7)
#define BIT8(i) BIT_N(i,8)
#define BIT9(i) BIT_N(i,9)
#define BIT10(i) BIT_N(i,10)
#define BIT11(i) BIT_N(i,11)
#define BIT12(i) BIT_N(i,12)
#define BIT13(i) BIT_N(i,13)
#define BIT14(i) BIT_N(i,14)
#define BIT15(i) BIT_N(i,15)
#define BIT16(i) BIT_N(i,16)
#define BIT17(i) BIT_N(i,17)
#define BIT18(i) BIT_N(i,18)
#define BIT19(i) BIT_N(i,19)
#define BIT20(i) BIT_N(i,20)
#define BIT21(i) BIT_N(i,21)
#define BIT22(i) BIT_N(i,22)
#define BIT23(i) BIT_N(i,23)
#define BIT24(i) BIT_N(i,24)
#define BIT25(i) BIT_N(i,25)
#define BIT26(i) BIT_N(i,26)
#define BIT27(i) BIT_N(i,27)
#define BIT28(i) BIT_N(i,28)
#define BIT29(i) BIT_N(i,29)
#define BIT30(i) BIT_N(i,30)
#define BIT31(i) ((i)>>31)
#define CONDITION(i) (i)>>28
#define REG_POS(i,n) (((i)>>n)&0xF)
#endif
Executable
+4
View File
@@ -0,0 +1,4 @@
configure
make clean
make
pause
+1445
View File
File diff suppressed because it is too large Load Diff
+198
View File
@@ -0,0 +1,198 @@
/*
Copyright (C) 2009-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 <stdlib.h>
#include <string.h>
#include <string>
#include <vector>
#include "types.h"
#define CHEAT_VERSION_MAJOR 2
#define CHEAT_VERSION_MINOR 0
#define MAX_CHEAT_LIST 100
#define MAX_XX_CODE 1024
#define CHEAT_FILE_MIN_FGETS_BUFFER 32768
#define CHEAT_DB_GAME_TITLE_SIZE 256
struct CHEATS_LIST
{
CHEATS_LIST()
{
memset(this,0,sizeof(*this));
type = 0xFF;
}
u8 type; // 0 - internal cheat system
// 1 - Action Replay
// 2 - Codebreakers
BOOL enabled;
// TODO
u8 freezeType; // 0 - normal freeze
// 1 - can decrease
// 2 - can increase
u32 code[MAX_XX_CODE][2];
char description[1024];
int num;
u8 size;
};
class CHEATS
{
private:
std::vector<CHEATS_LIST> list;
u8 filename[MAX_PATH];
u32 currentGet;
void clear();
void ARparser(CHEATS_LIST& cheat);
char *clearCode(char *s);
public:
CHEATS()
: currentGet(0)
{
memset(filename, 0, sizeof(filename));
}
~CHEATS() {}
void init(char *path);
BOOL add(u8 size, u32 address, u32 val, char *description, BOOL enabled);
BOOL update(u8 size, u32 address, u32 val, char *description, BOOL enabled, u32 pos);
BOOL add_AR(char *code, char *description, BOOL enabled);
BOOL update_AR(char *code, char *description, BOOL enabled, u32 pos);
BOOL add_AR_Direct(CHEATS_LIST cheat);
BOOL add_CB(char *code, char *description, BOOL enabled);
BOOL update_CB(char *code, char *description, BOOL enabled, u32 pos);
BOOL remove(u32 pos);
void getListReset();
BOOL getList(CHEATS_LIST *cheat);
CHEATS_LIST* getListPtr();
BOOL get(CHEATS_LIST *cheat, u32 pos);
CHEATS_LIST* getItemByIndex(const u32 pos);
u32 getSize();
size_t getActiveCount();
void setDescription(const char *description, u32 pos);
BOOL save();
BOOL load();
void process();
void getXXcodeString(CHEATS_LIST cheat, char *res_buf);
static BOOL XXCodeFromString(CHEATS_LIST *cheatItem, const std::string codeString);
static BOOL XXCodeFromString(CHEATS_LIST *cheatItem, const char *codeString);
};
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() { close(); }
BOOL start(u8 type, u8 size, u8 sign);
BOOL close();
u32 search(u32 val);
u32 search(u8 comp);
u32 getAmount();
BOOL getList(u32 *address, u32 *curVal);
void getListReset();
};
enum CHEATS_DB_TYPE
{
CHEATS_DB_R4 = 0
};
#pragma pack(push)
#pragma pack(1)
typedef struct FAT_R4
{
u8 serial[4];
u32 CRC;
u64 addr;
} FAT_R4;
#pragma pack(pop)
class CHEATSEXPORT
{
private:
CHEATS_DB_TYPE type;
bool encrypted;
FILE *fp;
u32 fsize;
u32 dataSize;
u32 encOffset;
FAT_R4 fat;
bool search();
bool getCodes();
void R4decrypt(u8 *buf, u32 len, u32 n);
u32 numCheats;
CHEATS_LIST *cheats;
u8 error; // 0 - no errors
// 1 - open failed/file not found
// 2 - file format is wrong (no valid header ID)
// 3 - cheat not found in database
// 4 - export error from database
public:
CHEATSEXPORT() :
fp(NULL),
fsize(0),
dataSize(0),
encOffset(0),
type(CHEATS_DB_R4),
encrypted(false),
numCheats(0),
cheats(0),
CRC(0),
error(0)
{
memset(date, 0, sizeof(date));
gametitle = (u8 *)malloc(CHEAT_DB_GAME_TITLE_SIZE);
memset(gametitle, 0, CHEAT_DB_GAME_TITLE_SIZE);
}
~CHEATSEXPORT()
{
free(gametitle);
gametitle = NULL;
}
u8 *gametitle;
u8 date[17];
u32 CRC;
bool load(char *path);
void close();
CHEATS_LIST *getCheats();
u32 getCheatsNum();
u8 getErrorCode() { return error; }
};
extern CHEATS *cheats;
extern CHEATSEARCH *cheatSearch;
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0440"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "AB796CA415CDCBA200C59155"
BuildableName = "DeSmuME.app"
BlueprintName = "DeSmuME (OS X App)"
ReferencedContainer = "container:DeSmuME (Latest).xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "AB796CA415CDCBA200C59155"
BuildableName = "DeSmuME.app"
BlueprintName = "DeSmuME (OS X App)"
ReferencedContainer = "container:DeSmuME (Latest).xcodeproj">
</BuildableReference>
</MacroExpansion>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "AB796CA415CDCBA200C59155"
BuildableName = "DeSmuME.app"
BlueprintName = "DeSmuME (OS X App)"
ReferencedContainer = "container:DeSmuME (Latest).xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "AB796CA415CDCBA200C59155"
BuildableName = "DeSmuME.app"
BlueprintName = "DeSmuME (OS X App)"
ReferencedContainer = "container:DeSmuME (Latest).xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "ABB3C6461501BC6D00E0C22E"
BuildableName = "DeSmuME.oecoreplugin"
BlueprintName = "DeSmuME (OpenEmu Plug-in)"
ReferencedContainer = "container:DeSmuME (Latest).xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
File diff suppressed because it is too large Load Diff
+264
View File
@@ -0,0 +1,264 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="DeSmuME Cocoa" />
<Option platforms="Mac;" />
<Option pch_mode="2" />
<Option default_target="Cocoa X86" />
<Option compiler="gcc" />
<Option show_notes="0">
<notes>
<![CDATA[DeSmuME
Note that when building DeSmuME with this Code::Blocks project, compatibility may be worse than when building with the XCode project.
Cocoa Port
DeSmuME 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.
DeSmuME 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 DeSmuME; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA]]>
</notes>
</Option>
<Build>
<Target title="Cocoa X86">
<Option platforms="Mac;" />
<Option output="build/codeblocks/DeSmuME.app/Contents/MacOS/DeSmuME" prefix_auto="0" extension_auto="0" />
<Option working_dir="build/codeblocks/DeSmuME.app/Contents/MacOS" />
<Option object_output="build/codeblocks/x86" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-march=pentium-m" />
<Add option="-msse2" />
<Add option="-DDESMUME_COCOA" />
<Add option="-DHAVE_LIBZ" />
<Add option="-DHAVE_OPENGL" />
</Compiler>
<ExtraCommands>
<Add after="cp DeSmuME.app/Contents/MacOS/DeSmuME DeSmuME.app/Contents/MacOS/DeSmuME_x86" />
</ExtraCommands>
</Target>
<Target title="Cocoa PPC">
<Option platforms="Mac;" />
<Option output="build/codeblocks/DeSmuME.app/Contents/MacOS/DeSmuME" prefix_auto="0" extension_auto="0" />
<Option working_dir="build/codeblocks/DeSmuME.app/Contents/MacOS" />
<Option object_output="build/codeblocks/ppc" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-arch ppc" />
<Add option="-DDESMUME_COCOA" />
<Add option="-DHAVE_LIBZ" />
<Add option="-DHAVE_OPENGL" />
</Compiler>
<Linker>
<Add option="-arch ppc" />
</Linker>
<ExtraCommands>
<Add after="cp DeSmuME.app/Contents/MacOS/DeSmuME DeSmuME.app/Contents/MacOS/DeSmuME_ppc" />
</ExtraCommands>
</Target>
</Build>
<VirtualTargets>
<Add alias="Cocoa Universal" targets="Cocoa X86;Cocoa PPC;" />
</VirtualTargets>
<Compiler>
<Add option="-fexpensive-optimizations" />
<Add option="-O3" />
<Add option="-fpascal-strings -fasm-blocks" />
<Add option="-DDESMUME_OBJ_C" />
</Compiler>
<Linker>
<Add option="-framework Cocoa" />
<Add option="-framework OpenGL" />
<Add option="-framework AudioUnit" />
<Add option="-lz" />
</Linker>
<ExtraCommands>
<Add after="./makeapp.sh" />
<Mode after="always" />
</ExtraCommands>
<Unit filename="../ARM9.h" />
<Unit filename="../Disassembler.cpp" />
<Unit filename="../Disassembler.h" />
<Unit filename="../FIFO.cpp" />
<Unit filename="../FIFO.h" />
<Unit filename="../GPU.cpp" />
<Unit filename="../GPU.h" />
<Unit filename="../GPU_osd.cpp" />
<Unit filename="../GPU_osd.h" />
<Unit filename="../MMU.cpp" />
<Unit filename="../MMU.h" />
<Unit filename="../NDSSystem.cpp" />
<Unit filename="../NDSSystem.h" />
<Unit filename="../OGLRender.cpp" />
<Unit filename="../OGLRender.h" />
<Unit filename="../PACKED.h" />
<Unit filename="../PACKED_END.h" />
<Unit filename="../ROMReader.cpp" />
<Unit filename="../ROMReader.h" />
<Unit filename="../SPU.cpp" />
<Unit filename="../SPU.h" />
<Unit filename="../addons.cpp" />
<Unit filename="../addons.h" />
<Unit filename="../addons/compactFlash.cpp" />
<Unit filename="../addons/gbagame.cpp" />
<Unit filename="../addons/none.cpp" />
<Unit filename="../addons/rumblepak.cpp" />
<Unit filename="../arm_instructions.cpp" />
<Unit filename="../arm_instructions.h" />
<Unit filename="../armcpu.cpp" />
<Unit filename="../armcpu.h" />
<Unit filename="../bios.cpp" />
<Unit filename="../bios.h" />
<Unit filename="../bits.h" />
<Unit filename="../cflash.cpp" />
<Unit filename="../cflash.h" />
<Unit filename="../cheatSystem.cpp" />
<Unit filename="../cheatSystem.h" />
<Unit filename="English.strings" />
<Unit filename="Japanese.strings" />
<Unit filename="about.m">
<Option compile="1" />
<Option link="1" />
</Unit>
<Unit filename="cocoa_util.m">
<Option compile="1" />
<Option link="1" />
</Unit>
<Unit filename="dialogs/rom_info.h" />
<Unit filename="dialogs/rom_info.m">
<Option compile="1" />
<Option link="1" />
</Unit>
<Unit filename="dialogs/speed_limit_selection_window.h" />
<Unit filename="dialogs/speed_limit_selection_window.m">
<Option compile="1" />
<Option link="1" />
</Unit>
<Unit filename="globals.h" />
<Unit filename="input.h" />
<Unit filename="input.m">
<Option compile="1" />
<Option link="1" />
</Unit>
<Unit filename="main.m">
<Option compile="1" />
<Option link="1" />
</Unit>
<Unit filename="main_window.h" />
<Unit filename="main_window.m">
<Option compile="1" />
<Option link="1" />
</Unit>
<Unit filename="nds_control.h" />
<Unit filename="nds_control.mm">
<Option compile="1" />
<Option link="1" />
</Unit>
<Unit filename="preferences.h" />
<Unit filename="preferences.m">
<Option compile="1" />
<Option link="1" />
</Unit>
<Unit filename="screen_state.h" />
<Unit filename="screen_state.m">
<Option compile="1" />
<Option link="1" />
</Unit>
<Unit filename="screenshot.h" />
<Unit filename="screenshot.m">
<Option compile="1" />
<Option link="1" />
</Unit>
<Unit filename="sndOSX.h" />
<Unit filename="sndOSX.mm">
<Option compile="1" />
<Option link="1" />
</Unit>
<Unit filename="video_output_view.h" />
<Unit filename="video_output_view.m">
<Option compile="1" />
<Option link="1" />
</Unit>
<Unit filename="../common.cpp" />
<Unit filename="../common.h" />
<Unit filename="../cp15.cpp" />
<Unit filename="../cp15.h" />
<Unit filename="../ctrlssdl.h" />
<Unit filename="../debug.cpp" />
<Unit filename="../debug.h" />
<Unit filename="../dscard.h" />
<Unit filename="../fat.h" />
<Unit filename="../fs-linux.cpp" />
<Unit filename="../fs.h" />
<Unit filename="../gdbstub.h" />
<Unit filename="../gfx3d.cpp" />
<Unit filename="../gfx3d.h" />
<Unit filename="../matrix.cpp" />
<Unit filename="../matrix.h" />
<Unit filename="../mc.cpp" />
<Unit filename="../mc.h" />
<Unit filename="../mem.h" />
<Unit filename="../memorystream.h" />
<Unit filename="../mic.cpp" />
<Unit filename="../mic.h" />
<Unit filename="../movie.cpp" />
<Unit filename="../movie.h" />
<Unit filename="../readwrite.cpp" />
<Unit filename="../readwrite.h" />
<Unit filename="../registers.h" />
<Unit filename="../render3D.cpp" />
<Unit filename="../render3D.h" />
<Unit filename="../rtc.cpp" />
<Unit filename="../rtc.h" />
<Unit filename="../saves.cpp" />
<Unit filename="../saves.h" />
<Unit filename="../shaders.h" />
<Unit filename="../softrender.cpp" />
<Unit filename="../softrender.h" />
<Unit filename="../softrender_config.h" />
<Unit filename="../softrender_desmumefont.h" />
<Unit filename="../softrender_v3sysfont.h" />
<Unit filename="../texcache.cpp" />
<Unit filename="../texcache.h" />
<Unit filename="../thumb_instructions.cpp" />
<Unit filename="../thumb_instructions.h" />
<Unit filename="../types.h" />
<Unit filename="../utils/ConvertUTF.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="../utils/ConvertUTF.h" />
<Unit filename="../utils/decrypt/crc.cpp" />
<Unit filename="../utils/decrypt/crc.h" />
<Unit filename="../utils/decrypt/decrypt.cpp" />
<Unit filename="../utils/decrypt/decrypt.h" />
<Unit filename="../utils/decrypt/header.cpp" />
<Unit filename="../utils/decrypt/header.h" />
<Unit filename="../utils/guid.cpp" />
<Unit filename="../utils/guid.h" />
<Unit filename="../utils/md5.cpp" />
<Unit filename="../utils/md5.h" />
<Unit filename="../utils/valuearray.h" />
<Unit filename="../utils/xstring.cpp" />
<Unit filename="../utils/xstring.h" />
<Unit filename="../wifi.cpp" />
<Unit filename="../wifi.h" />
<Extensions>
<code_completion />
<envvars />
<debugger />
</Extensions>
</Project>
</CodeBlocks_project_file>
+32
View File
@@ -0,0 +1,32 @@
/*
Copyright (C) 2011 Roger Manuel
Copyright (C) 2012 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/>.
*/
#ifdef __OBJC__
#define OBJ_C
#endif
#define HOST_DARWIN
#define DESMUME_COCOA
#define HAVE_OPENGL
#define HAVE_LIBZ
#if defined(__i386__) || defined(__x86_64__)
#define HAVE_JIT
#endif
#define PORT_VERSION "Cocoa"
+768
View File
@@ -0,0 +1,768 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CommandTagList</key>
<array>
<string>Up</string>
<string>Down</string>
<string>Left</string>
<string>Right</string>
<string>A</string>
<string>B</string>
<string>X</string>
<string>Y</string>
<string>L</string>
<string>R</string>
<string>Start</string>
<string>Select</string>
<string>Touch</string>
<string>Microphone</string>
<string>Lid</string>
<string>Debug</string>
<string>Guitar Grip: Green</string>
<string>Guitar Grip: Red</string>
<string>Guitar Grip: Yellow</string>
<string>Guitar Grip: Blue</string>
<string>Piano: C</string>
<string>Piano: C#</string>
<string>Piano: D</string>
<string>Piano: D#</string>
<string>Piano: E</string>
<string>Piano: F</string>
<string>Piano: F#</string>
<string>Piano: G</string>
<string>Piano: G#</string>
<string>Piano: A</string>
<string>Piano: A#</string>
<string>Piano: B</string>
<string>Piano: High C</string>
<string>Paddle</string>
<string>Autohold - Set</string>
<string>Autohold - Clear</string>
<string>Execute/Pause</string>
<string>Frame Advance</string>
<string>Frame Jump</string>
<string>Reset</string>
<string>Mute/Unmute</string>
<string>Load State Slot</string>
<string>Save State Slot</string>
<string>Copy Screen</string>
<string>Rotate Display Left</string>
<string>Rotate Display Right</string>
<string>Toggle All Displays</string>
<string>Set Speed</string>
<string>Enable/Disable Speed Limiter</string>
<string>Enable/Disable Auto Frame Skip</string>
<string>Enable/Disable Cheats</string>
<string>Enable/Disable GPU State</string>
</array>
<key>DefaultInputProfiles</key>
<array>
<dict>
<key>Name</key>
<string>Default</string>
<key>IsDefaultType</key>
<true/>
<key>Mappings</key>
<dict>
<key>Up</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: Up Arrow</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>126</string>
<key>elementName</key>
<string>Up Arrow</string>
<key>intValue1</key>
<false/>
</dict>
</array>
<key>Down</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: Down Arrow</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>125</string>
<key>elementName</key>
<string>Down Arrow</string>
<key>intValue1</key>
<false/>
</dict>
</array>
<key>Left</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: Left Arrow</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>123</string>
<key>elementName</key>
<string>Left Arrow</string>
<key>intValue1</key>
<false/>
</dict>
</array>
<key>Right</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: Right Arrow</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>124</string>
<key>elementName</key>
<string>Right Arrow</string>
<key>intValue1</key>
<false/>
</dict>
</array>
<key>A</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: X</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>7</string>
<key>elementName</key>
<string>X</string>
<key>intValue1</key>
<false/>
</dict>
</array>
<key>B</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: Z</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>6</string>
<key>elementName</key>
<string>Z</string>
<key>intValue1</key>
<false/>
</dict>
</array>
<key>X</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: S</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>1</string>
<key>elementName</key>
<string>S</string>
<key>intValue1</key>
<false/>
</dict>
</array>
<key>Y</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: A</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>0</string>
<key>elementName</key>
<string>A</string>
<key>intValue1</key>
<false/>
</dict>
</array>
<key>L</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: Q</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>12</string>
<key>elementName</key>
<string>Q</string>
<key>intValue1</key>
<false/>
</dict>
</array>
<key>R</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: W</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>13</string>
<key>elementName</key>
<string>W</string>
<key>intValue1</key>
<false/>
</dict>
</array>
<key>Start</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: Return</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>36</string>
<key>elementName</key>
<string>Return</string>
<key>intValue1</key>
<false/>
</dict>
</array>
<key>Select</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: Tab</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>48</string>
<key>elementName</key>
<string>Tab</string>
<key>intValue1</key>
<false/>
</dict>
</array>
<key>Touch</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Mouse: Primary Button</string>
<key>deviceCode</key>
<string>NSEventMouse</string>
<key>deviceName</key>
<string>Mouse</string>
<key>elementCode</key>
<string>0</string>
<key>elementName</key>
<string>Primary Button</string>
<key>inputSettingsSummary</key>
<string>Use Device Coordinates</string>
<key>useInputForIntCoord</key>
<true/>
</dict>
</array>
<key>Microphone</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: ` (Accent)</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>50</string>
<key>elementName</key>
<string>` (Accent)</string>
<key>inputSettingsSummary</key>
<string>Internal Noise Samples</string>
<key>intValue1</key>
<integer>1</integer>
<key>floatValue0</key>
<real>250</real>
</dict>
</array>
<key>Lid</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: Delete (Backspace)</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>51</string>
<key>elementName</key>
<string>Delete (Backspace)</string>
</dict>
</array>
<key>Debug</key>
<array/>
<key>Guitar Grip: Green</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: E</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>14</string>
<key>elementName</key>
<string>E</string>
</dict>
</array>
<key>Guitar Grip: Red</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: R</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>15</string>
<key>elementName</key>
<string>R</string>
</dict>
</array>
<key>Guitar Grip: Yellow</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: T</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>17</string>
<key>elementName</key>
<string>T</string>
</dict>
</array>
<key>Guitar Grip: Blue</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: Y</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>16</string>
<key>elementName</key>
<string>Y</string>
</dict>
</array>
<key>Piano: C</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: C</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>8</string>
<key>elementName</key>
<string>C</string>
</dict>
</array>
<key>Piano: C#</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: F</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>3</string>
<key>elementName</key>
<string>F</string>
</dict>
</array>
<key>Piano: D</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: V</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>9</string>
<key>elementName</key>
<string>V</string>
</dict>
</array>
<key>Piano: D#</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: G</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>5</string>
<key>elementName</key>
<string>G</string>
</dict>
</array>
<key>Piano: E</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: B</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>11</string>
<key>elementName</key>
<string>B</string>
</dict>
</array>
<key>Piano: F</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: N</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>45</string>
<key>elementName</key>
<string>N</string>
</dict>
</array>
<key>Piano: F#</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: J</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>38</string>
<key>elementName</key>
<string>J</string>
</dict>
</array>
<key>Piano: G</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: M</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>46</string>
<key>elementName</key>
<string>M</string>
</dict>
</array>
<key>Piano: G#</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: K</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>40</string>
<key>elementName</key>
<string>K</string>
</dict>
</array>
<key>Piano: A</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: , (Comma)</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>43</string>
<key>elementName</key>
<string>, (Comma)</string>
</dict>
</array>
<key>Piano: A#</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: L</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>37</string>
<key>elementName</key>
<string>L</string>
</dict>
</array>
<key>Piano: B</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: . (Period)</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>47</string>
<key>elementName</key>
<string>. (Period)</string>
</dict>
</array>
<key>Piano: High C</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: /</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>44</string>
<key>elementName</key>
<string>/</string>
</dict>
</array>
<key>Paddle</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: O</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>31</string>
<key>elementName</key>
<string>O</string>
<key>isInputAnalog</key>
<false/>
<key>inputSettingsSummary</key>
<string>Paddle Adjust: -5</string>
<key>intValue1</key>
<integer>-5</integer>
</dict>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: P</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>35</string>
<key>elementName</key>
<string>P</string>
<key>isInputAnalog</key>
<false/>
<key>inputSettingsSummary</key>
<string>Paddle Adjust: +5</string>
<key>intValue1</key>
<integer>5</integer>
</dict>
</array>
<key>Autohold - Set</key>
<array/>
<key>Autohold - Clear</key>
<array/>
<key>HUD</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: H</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>4</string>
<key>elementName</key>
<string>H</string>
</dict>
</array>
<key>Execute/Pause</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: Forward Delete</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>117</string>
<key>elementName</key>
<string>Forward Delete</string>
</dict>
</array>
<key>Frame Advance</key>
<array/>
<key>Frame Jump</key>
<array/>
<key>Reset</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: Page Down</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>121</string>
<key>elementName</key>
<string>Page Down</string>
</dict>
</array>
<key>Mute/Unmute</key>
<array/>
<key>Load State Slot</key>
<array/>
<key>Save State Slot</key>
<array/>
<key>Copy Screen</key>
<array/>
<key>Rotate Display Left</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: [</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>33</string>
<key>elementName</key>
<string>[</string>
<key>intValue0</key>
<integer>-90</integer>
</dict>
</array>
<key>Rotate Display Right</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: ]</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>30</string>
<key>elementName</key>
<string>]</string>
<key>intValue0</key>
<integer>90</integer>
</dict>
</array>
<key>Toggle All Displays</key>
<array/>
<key>Set Speed</key>
<array>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: - (Dash)</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>27</string>
<key>elementName</key>
<string>- (Dash)</string>
<key>inputSettingsSummary</key>
<string>0.50x Speed</string>
<key>floatValue0</key>
<real>0.5</real>
</dict>
<dict>
<key>deviceInfoSummary</key>
<string>Keyboard: =</string>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>24</string>
<key>elementName</key>
<string>=</string>
<key>inputSettingsSummary</key>
<string>2.00x Speed</string>
<key>floatValue0</key>
<integer>2</integer>
</dict>
</array>
<key>Enable/Disable Speed Limiter</key>
<array/>
<key>Enable/Disable Auto Frame Skip</key>
<array/>
<key>Enable/Disable Cheats</key>
<array/>
<key>Enable/Disable GPU State</key>
<array/>
</dict>
</dict>
</array>
</dict>
</plist>
+746
View File
@@ -0,0 +1,746 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Advanscene_AutoDetectRomSaveType</key>
<true/>
<key>CoreControl_EnableAutoFrameSkip</key>
<true/>
<key>CoreControl_EnableCheats</key>
<true/>
<key>CoreControl_EnableSpeedLimit</key>
<true/>
<key>CoreControl_SpeedScalar</key>
<real>1</real>
<key>Debug_GDBStubEnableARM9</key>
<false/>
<key>Debug_GDBStubEnableARM7</key>
<false/>
<key>Debug_GDBStubPortARM9</key>
<integer>20000</integer>
<key>Debug_GDBStubPortARM7</key>
<integer>20001</integer>
<key>DisplayView_Deposterize</key>
<false/>
<key>DisplayView_FiltersPreferGPU</key>
<true/>
<key>DisplayView_Mode</key>
<integer>2</integer>
<key>DisplayView_OutputFilter</key>
<integer>1</integer>
<key>DisplayView_Rotation</key>
<integer>0</integer>
<key>DisplayView_ShowHUD</key>
<true/>
<key>DisplayView_ShowStatusBar</key>
<true/>
<key>DisplayView_Size</key>
<integer>100</integer>
<key>DisplayView_UseBilinearOutput</key>
<true/>
<key>DisplayView_UseVerticalSync</key>
<false/>
<key>DisplayView_VideoFilter</key>
<integer>0</integer>
<key>DisplayViewCombo_Gap</key>
<integer>0</integer>
<key>DisplayViewCombo_Order</key>
<integer>0</integer>
<key>DisplayViewCombo_Orientation</key>
<integer>0</integer>
<key>Emulation_AdvancedBusLevelTiming</key>
<true/>
<key>Emulation_BIOSEmulateSWI</key>
<true/>
<key>Emulation_BIOSPatchDelayLoopSWI</key>
<false/>
<key>Emulation_CPUEmulationEngine</key>
<integer>0</integer>
<key>Emulation_EmulateEnsata</key>
<false/>
<key>Emulation_FirmwareBoot</key>
<false/>
<key>Emulation_MaxJITBlockSize</key>
<integer>12</integer>
<key>Emulation_RigorousTiming</key>
<false/>
<key>Emulation_UseDebugConsole</key>
<false/>
<key>Emulation_UseExternalBIOSImages</key>
<false/>
<key>Emulation_UseExternalFirmwareImage</key>
<false/>
<key>EmulationSlot1_DeviceType</key>
<integer>1</integer>
<key>FirmwareConfig_Birthday</key>
<date>2011-06-23T07:00:00Z</date>
<key>FirmwareConfig_FavoriteColor</key>
<integer>7</integer>
<key>FirmwareConfig_Language</key>
<integer>1</integer>
<key>FirmwareConfig_Message</key>
<string>DeSmuME makes you happy!</string>
<key>FirmwareConfig_Nickname</key>
<string>DeSmuME</string>
<key>General_AppFirstTimeRun</key>
<dict/>
<key>General_AutoloadROMOption</key>
<integer>10000</integer>
<key>General_DisplayWindowRestorableStates</key>
<array/>
<key>General_DoNotAskMigrate</key>
<false/>
<key>General_ExecuteROMOnLoad</key>
<true/>
<key>General_StreamLoadRomData</key>
<true/>
<key>General_WillRestoreDisplayWindows</key>
<true/>
<key>HUD_FrameCounter</key>
<false/>
<key>HUD_FramesPerSecond</key>
<false/>
<key>HUD_GraphicalInput</key>
<false/>
<key>HUD_Input</key>
<false/>
<key>HUD_LagCounter</key>
<false/>
<key>HUD_Microphone</key>
<false/>
<key>HUD_RealTimeClock</key>
<false/>
<key>Input_AudioInputMode</key>
<integer>1</integer>
<key>Input_ControllerMappings</key>
<dict>
<key>Up</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>126</string>
<key>elementName</key>
<string>Up Arrow</string>
</dict>
</array>
<key>Down</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>125</string>
<key>elementName</key>
<string>Down Arrow</string>
</dict>
</array>
<key>Left</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>123</string>
<key>elementName</key>
<string>Left Arrow</string>
</dict>
</array>
<key>Right</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>124</string>
<key>elementName</key>
<string>Right Arrow</string>
</dict>
</array>
<key>A</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>7</string>
<key>elementName</key>
<string>X</string>
</dict>
</array>
<key>B</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>6</string>
<key>elementName</key>
<string>Z</string>
</dict>
</array>
<key>X</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>1</string>
<key>elementName</key>
<string>S</string>
</dict>
</array>
<key>Y</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>0</string>
<key>elementName</key>
<string>A</string>
</dict>
</array>
<key>L</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>12</string>
<key>elementName</key>
<string>Q</string>
</dict>
</array>
<key>R</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>13</string>
<key>elementName</key>
<string>W</string>
</dict>
</array>
<key>Start</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>36</string>
<key>elementName</key>
<string>Return</string>
</dict>
</array>
<key>Select</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>48</string>
<key>elementName</key>
<string>Tab</string>
</dict>
</array>
<key>Touch</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventMouse</string>
<key>deviceName</key>
<string>Mouse</string>
<key>elementCode</key>
<string>0</string>
<key>elementName</key>
<string>Primary Button</string>
<key>useInputForIntCoord</key>
<true/>
</dict>
</array>
<key>Microphone</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>50</string>
<key>elementName</key>
<string>` (Accent)</string>
<key>intValue1</key>
<integer>1</integer>
</dict>
</array>
<key>Lid</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>51</string>
<key>elementName</key>
<string>Delete (Backspace)</string>
</dict>
</array>
<key>Debug</key>
<array/>
<key>Guitar Grip: Green</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>14</string>
<key>elementName</key>
<string>E</string>
</dict>
</array>
<key>Guitar Grip: Red</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>15</string>
<key>elementName</key>
<string>R</string>
</dict>
</array>
<key>Guitar Grip: Yellow</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>17</string>
<key>elementName</key>
<string>T</string>
</dict>
</array>
<key>Guitar Grip: Blue</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>16</string>
<key>elementName</key>
<string>Y</string>
</dict>
</array>
<key>Piano: C</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>8</string>
<key>elementName</key>
<string>C</string>
</dict>
</array>
<key>Piano: C#</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>3</string>
<key>elementName</key>
<string>F</string>
</dict>
</array>
<key>Piano: D</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>9</string>
<key>elementName</key>
<string>V</string>
</dict>
</array>
<key>Piano: D#</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>5</string>
<key>elementName</key>
<string>G</string>
</dict>
</array>
<key>Piano: E</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>11</string>
<key>elementName</key>
<string>B</string>
</dict>
</array>
<key>Piano: F</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>45</string>
<key>elementName</key>
<string>N</string>
</dict>
</array>
<key>Piano: F#</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>38</string>
<key>elementName</key>
<string>J</string>
</dict>
</array>
<key>Piano: G</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>46</string>
<key>elementName</key>
<string>M</string>
</dict>
</array>
<key>Piano: G#</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>40</string>
<key>elementName</key>
<string>K</string>
</dict>
</array>
<key>Piano: A</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>43</string>
<key>elementName</key>
<string>, (Comma)</string>
</dict>
</array>
<key>Piano: A#</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>37</string>
<key>elementName</key>
<string>L</string>
</dict>
</array>
<key>Piano: B</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>47</string>
<key>elementName</key>
<string>. (Period)</string>
</dict>
</array>
<key>Piano: High C</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>44</string>
<key>elementName</key>
<string>/</string>
</dict>
</array>
<key>Paddle</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>31</string>
<key>elementName</key>
<string>O</string>
<key>intValue1</key>
<integer>-5</integer>
<key>isInputAnalog</key>
<false/>
</dict>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>35</string>
<key>elementName</key>
<string>P</string>
<key>intValue1</key>
<integer>5</integer>
<key>isInputAnalog</key>
<false/>
</dict>
</array>
<key>Autohold - Set</key>
<array/>
<key>Autohold - Clear</key>
<array/>
<key>HUD</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>4</string>
<key>elementName</key>
<string>H</string>
</dict>
</array>
<key>Execute/Pause</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>117</string>
<key>elementName</key>
<string>Forward Delete</string>
</dict>
</array>
<key>Frame Advance</key>
<array/>
<key>Frame Jump</key>
<array/>
<key>Reset</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>121</string>
<key>elementName</key>
<string>Page Down</string>
</dict>
</array>
<key>Mute/Unmute</key>
<array/>
<key>Load State Slot</key>
<array/>
<key>Save State Slot</key>
<array/>
<key>Copy Screen</key>
<array/>
<key>Rotate Display Left</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>33</string>
<key>elementName</key>
<string>[</string>
<key>intValue0</key>
<integer>-90</integer>
</dict>
</array>
<key>Rotate Display Right</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>30</string>
<key>elementName</key>
<string>]</string>
<key>intValue0</key>
<integer>90</integer>
</dict>
</array>
<key>Toggle All Displays</key>
<array/>
<key>Set Speed</key>
<array>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>27</string>
<key>elementName</key>
<string>- (Dash)</string>
<key>floatValue0</key>
<string>0.5</string>
</dict>
<dict>
<key>deviceCode</key>
<string>NSEventKeyboard</string>
<key>deviceName</key>
<string>Keyboard</string>
<key>elementCode</key>
<string>24</string>
<key>elementName</key>
<string>=</string>
<key>floatValue0</key>
<integer>2</integer>
</dict>
</array>
<key>Enable/Disable Speed Limiter</key>
<array/>
<key>Enable/Disable Auto Frame Skip</key>
<array/>
<key>Enable/Disable Cheats</key>
<array/>
<key>Enable/Disable GPU State</key>
<array/>
</dict>
<key>Input_SavedDeviceProperties</key>
<dict/>
<key>Input_SavedProfiles</key>
<array/>
<key>Microphone_HardwareMicMute</key>
<false/>
<key>Render3D_DepthComparisonThreshold</key>
<integer>0</integer>
<key>Render3D_EdgeMarking</key>
<true/>
<key>Render3D_Fog</key>
<true/>
<key>Render3D_FragmentSamplingHack</key>
<false/>
<key>Render3D_HighPrecisionColorInterpolation</key>
<true/>
<key>Render3D_LineHack</key>
<true/>
<key>Render3D_Multisample</key>
<false/>
<key>Render3D_RenderingEngine</key>
<integer>1</integer>
<key>Render3D_Textures</key>
<true/>
<key>Render3D_Threads</key>
<integer>0</integer>
<key>RomInfoPanel_SectionViewState</key>
<dict/>
<key>Slot2_GBA_CartridgePath</key>
<string></string>
<key>Slot2_GBA_SRAMPath</key>
<string></string>
<key>Slot2_LoadedDevice</key>
<integer>1</integer>
<key>Slot2_MPCF_DirectoryPath</key>
<string></string>
<key>Slot2_MPCF_DiskImagePath</key>
<string></string>
<key>Slot2_MPCF_PathOption</key>
<integer>0</integer>
<key>Sound_AudioOutputEngine</key>
<integer>58325</integer>
<key>Sound_Volume</key>
<integer>100</integer>
<key>SPU_AdvancedLogic</key>
<true/>
<key>SPU_InterpolationMode</key>
<integer>2</integer>
<key>SPU_SyncMethod</key>
<integer>0</integer>
<key>SPU_SyncMode</key>
<integer>1</integer>
</dict>
</plist>
+39
View File
@@ -0,0 +1,39 @@
(*
Copyright (C) 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/>.
*)
display dialog "Are you sure that you want to delete DeSmuME's preferences?" buttons {"Cancel", "Delete"} default button "Delete" cancel button "Cancel" with title "Delete DeSmuME Preferences"
try
set userDefaultsPath to ((path to "pref" as text) & "org.desmume.DeSmuME.plist")
set isUserDefaultsDeleted to false
tell application "Finder"
if exists file userDefaultsPath then
set isUserDefaultsDeleted to true
delete file userDefaultsPath
end if
if isUserDefaultsDeleted then
display dialog "The preference files have been moved to the Trash." buttons {"OK"} default button {"OK"}
else
display dialog "No preference files were found." buttons {"OK"} default button {"OK"}
end if
end tell
on error errorMsg
display dialog errorMsg
end try
+536
View File
@@ -0,0 +1,536 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>VersionStrings</key>
<array>
<string>0.9.6</string>
<string>0.9.7</string>
<string>0.9.8</string>
<string>0.9.9</string>
<string>0.9.10</string>
<string>0.9.11</string>
</array>
<key>PortStrings</key>
<dict>
<key>0.9.6</key>
<array>
<string>GTK</string>
</array>
<key>0.9.7</key>
<array>
<string>Cocoa</string>
</array>
<key>0.9.8</key>
<array>
<string>Cocoa</string>
<string>OpenEmu</string>
</array>
<key>0.9.9</key>
<array>
<string>Cocoa</string>
<string>OpenEmu</string>
</array>
<key>0.9.10</key>
<array>
<string>Cocoa</string>
<string>OpenEmu</string>
</array>
<key>0.9.11</key>
<array>
<string>Cocoa</string>
<string>OpenEmu</string>
</array>
</dict>
<key>DefaultPaths</key>
<dict>
<key>0.9.6</key>
<dict>
<key>GTK</key>
<dict>
<key>ROM Save</key>
<string>~/.config/desmume</string>
<key>Cheat</key>
<string>~/.config/desmume</string>
<key>Save State</key>
<string>~/.config/desmume</string>
</dict>
</dict>
<key>0.9.7</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>${WITHROM}</string>
<key>Save State</key>
<string>${APPSUPPORT}</string>
</dict>
</dict>
<key>0.9.8</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>${APPSUPPORT}</string>
<key>Cheat</key>
<string>${APPSUPPORT}</string>
<key>Firmware Configuration</key>
<string>${APPSUPPORT}</string>
<key>Save State</key>
<string>${APPSUPPORT}</string>
</dict>
<key>OpenEmu</key>
<dict>
<key>ROM Save</key>
<string>${OPENEMU}</string>
<key>Save State</key>
<string>${OPENEMU}</string>
</dict>
</dict>
<key>0.9.9</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>${APPSUPPORT}</string>
<key>Cheat</key>
<string>${APPSUPPORT}</string>
<key>Firmware Configuration</key>
<string>${APPSUPPORT}</string>
<key>Save State</key>
<string>${APPSUPPORT}</string>
</dict>
<key>OpenEmu</key>
<dict>
<key>ROM Save</key>
<string>${OPENEMU}</string>
<key>Save State</key>
<string>${OPENEMU}</string>
</dict>
</dict>
<key>0.9.10</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>${APPSUPPORT}</string>
<key>Cheat</key>
<string>${APPSUPPORT}</string>
<key>Firmware Configuration</key>
<string>${APPSUPPORT}</string>
<key>Save State</key>
<string>${APPSUPPORT}</string>
</dict>
<key>OpenEmu</key>
<dict>
<key>ROM Save</key>
<string>${OPENEMU}</string>
<key>Save State</key>
<string>${OPENEMU}</string>
</dict>
</dict>
<key>0.9.11</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>${APPSUPPORT}</string>
<key>Cheat</key>
<string>${APPSUPPORT}</string>
<key>Firmware Configuration</key>
<string>${APPSUPPORT}</string>
<key>Save State</key>
<string>${APPSUPPORT}</string>
</dict>
<key>OpenEmu</key>
<dict>
<key>ROM Save</key>
<string>${OPENEMU}</string>
<key>Save State</key>
<string>${OPENEMU}</string>
</dict>
</dict>
</dict>
<key>DirectoryNames</key>
<dict>
<key>0.9.6</key>
<dict>
<key>GTK</key>
<dict>
<key>ROM Save</key>
<string>Battery</string>
<key>Cheat</key>
<string>Cheats</string>
<key>Firmware Configuration</key>
<string>Battery</string>
<key>Lua Script</key>
<string>Lua</string>
<key>Video</key>
<string>AviFiles</string>
<key>R4 Format</key>
<string>R4format</string>
<key>ROM</key>
<string>Roms</string>
<key>Save State</key>
<string>States</string>
<key>Screenshot</key>
<string>Screenshots</string>
<key>Sound Sample</key>
<string>SoundSamples</string>
</dict>
</dict>
<key>0.9.7</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>Battery</string>
<key>Cheat</key>
<string>Cheats</string>
<key>Firmware Configuration</key>
<string>Battery</string>
<key>Lua Script</key>
<string>Lua</string>
<key>Video</key>
<string>AviFiles</string>
<key>R4 Format</key>
<string>R4format</string>
<key>ROM</key>
<string>Roms</string>
<key>Save State</key>
<string>States</string>
<key>Screenshot</key>
<string>Screenshots</string>
<key>Sound Sample</key>
<string>SoundSamples</string>
</dict>
</dict>
<key>0.9.8</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>Battery</string>
<key>Cheat</key>
<string>Cheats</string>
<key>Firmware Configuration</key>
<string>Battery</string>
<key>Lua Script</key>
<string>Lua</string>
<key>Video</key>
<string>AviFiles</string>
<key>R4 Format</key>
<string>R4format</string>
<key>ROM</key>
<string>Roms</string>
<key>Save State</key>
<string>States</string>
<key>Screenshot</key>
<string>Screenshots</string>
<key>Sound Sample</key>
<string>SoundSamples</string>
</dict>
</dict>
<key>0.9.9</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>Battery</string>
<key>Cheat</key>
<string>Cheats</string>
<key>Firmware Configuration</key>
<string>Battery</string>
<key>Lua Script</key>
<string>Lua</string>
<key>Video</key>
<string>AviFiles</string>
<key>R4 Format</key>
<string>R4format</string>
<key>ROM</key>
<string>Roms</string>
<key>Save State</key>
<string>States</string>
<key>Screenshot</key>
<string>Screenshots</string>
<key>Sound Sample</key>
<string>SoundSamples</string>
</dict>
</dict>
<key>0.9.10</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>Battery</string>
<key>Cheat</key>
<string>Cheats</string>
<key>Firmware Configuration</key>
<string>Battery</string>
<key>Lua Script</key>
<string>Lua</string>
<key>Video</key>
<string>AviFiles</string>
<key>R4 Format</key>
<string>R4format</string>
<key>ROM</key>
<string>Roms</string>
<key>Save State</key>
<string>States</string>
<key>Screenshot</key>
<string>Screenshots</string>
<key>Sound Sample</key>
<string>SoundSamples</string>
</dict>
</dict>
<key>0.9.11</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>Battery</string>
<key>Cheat</key>
<string>Cheats</string>
<key>Firmware Configuration</key>
<string>Battery</string>
<key>Lua Script</key>
<string>Lua</string>
<key>Video</key>
<string>AviFiles</string>
<key>R4 Format</key>
<string>R4format</string>
<key>ROM</key>
<string>Roms</string>
<key>Save State</key>
<string>States</string>
<key>Screenshot</key>
<string>Screenshots</string>
<key>Sound Sample</key>
<string>SoundSamples</string>
</dict>
</dict>
</dict>
<key>FileExtensionByTypes</key>
<dict>
<key>0.9.6</key>
<dict>
<key>GTK</key>
<dict>
<key>ROM Save</key>
<string>dsv</string>
<key>Cheat</key>
<string>dct</string>
<key>Firmware Configuration</key>
<string>dfc</string>
<key>Lua Script</key>
<string>lua</string>
<key>Save State</key>
<string>dst</string>
<key>ROM</key>
<string>nds</string>
</dict>
</dict>
<key>0.9.7</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>dsv</string>
<key>Cheat</key>
<string>dct</string>
<key>Firmware Configuration</key>
<string>dfc</string>
<key>Lua Script</key>
<string>lua</string>
<key>Save State</key>
<string>dst</string>
<key>ROM</key>
<string>nds</string>
</dict>
</dict>
<key>0.9.8</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>dsv</string>
<key>Cheat</key>
<string>dct</string>
<key>Firmware Configuration</key>
<string>dfc</string>
<key>Lua Script</key>
<string>lua</string>
<key>Save State</key>
<string>dst</string>
<key>ROM</key>
<string>nds</string>
</dict>
</dict>
<key>0.9.9</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>dsv</string>
<key>Cheat</key>
<string>dct</string>
<key>Firmware Configuration</key>
<string>dfc</string>
<key>Lua Script</key>
<string>lua</string>
<key>Save State</key>
<string>dst</string>
<key>ROM</key>
<string>nds</string>
</dict>
</dict>
<key>0.9.10</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>dsv</string>
<key>Cheat</key>
<string>dct</string>
<key>Firmware Configuration</key>
<string>dfc</string>
<key>Lua Script</key>
<string>lua</string>
<key>Save State</key>
<string>dst</string>
<key>ROM</key>
<string>nds</string>
</dict>
</dict>
<key>0.9.11</key>
<dict>
<key>Cocoa</key>
<dict>
<key>ROM Save</key>
<string>dsv</string>
<key>Cheat</key>
<string>dct</string>
<key>Firmware Configuration</key>
<string>dfc</string>
<key>Lua Script</key>
<string>lua</string>
<key>Save State</key>
<string>dst</string>
<key>ROM</key>
<string>nds</string>
</dict>
</dict>
</dict>
<key>FileTypeByExtensions</key>
<dict>
<key>0.9.6</key>
<dict>
<key>GTK</key>
<dict>
<key>dsv</key>
<string>ROM Save</string>
<key>dct</key>
<string>Cheat</string>
<key>dfc</key>
<string>Firmware Configuration</string>
<key>lua</key>
<string>Lua Script</string>
<key>dst</key>
<string>Save State</string>
<key>nds</key>
<string>ROM</string>
</dict>
</dict>
<key>0.9.7</key>
<dict>
<key>Cocoa</key>
<dict>
<key>dsv</key>
<string>ROM Save</string>
<key>dct</key>
<string>Cheat</string>
<key>dfc</key>
<string>Firmware Configuration</string>
<key>lua</key>
<string>Lua Script</string>
<key>dst</key>
<string>Save State</string>
<key>nds</key>
<string>ROM</string>
</dict>
</dict>
<key>0.9.8</key>
<dict>
<key>Cocoa</key>
<dict>
<key>dsv</key>
<string>ROM Save</string>
<key>dct</key>
<string>Cheat</string>
<key>dfc</key>
<string>Firmware Configuration</string>
<key>lua</key>
<string>Lua Script</string>
<key>dst</key>
<string>Save State</string>
<key>nds</key>
<string>ROM</string>
</dict>
</dict>
<key>0.9.9</key>
<dict>
<key>Cocoa</key>
<dict>
<key>dsv</key>
<string>ROM Save</string>
<key>dct</key>
<string>Cheat</string>
<key>dfc</key>
<string>Firmware Configuration</string>
<key>lua</key>
<string>Lua Script</string>
<key>dst</key>
<string>Save State</string>
<key>nds</key>
<string>ROM</string>
</dict>
</dict>
<key>0.9.10</key>
<dict>
<key>Cocoa</key>
<dict>
<key>dsv</key>
<string>ROM Save</string>
<key>dct</key>
<string>Cheat</string>
<key>dfc</key>
<string>Firmware Configuration</string>
<key>lua</key>
<string>Lua Script</string>
<key>dst</key>
<string>Save State</string>
<key>nds</key>
<string>ROM</string>
</dict>
</dict>
<key>0.9.11</key>
<dict>
<key>Cocoa</key>
<dict>
<key>dsv</key>
<string>ROM Save</string>
<key>dct</key>
<string>Cheat</string>
<key>dfc</key>
<string>Firmware Configuration</string>
<key>lua</key>
<string>Lua Script</string>
<key>dst</key>
<string>Save State</string>
<key>nds</key>
<string>ROM</string>
</dict>
</dict>
</dict>
</dict>
</plist>
+474
View File
@@ -0,0 +1,474 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>nds</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_NintendoDS_ROM.icns</string>
<key>CFBundleTypeName</key>
<string>Nintendo DS ROM</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.nintendo.rom.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>ds.gba</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_NintendoGBA_ROM.icns</string>
<key>CFBundleTypeName</key>
<string>Gameboy Advance ROM</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.nintendo.rom.gba</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dst</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_SaveState.icns</string>
<key>CFBundleTypeName</key>
<string>DeSmuME Save State</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.desmume.savestate</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dsv</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_ROMSave.icns</string>
<key>CFBundleTypeName</key>
<string>DeSmuME ROM Save</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.desmume.romsave</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dfc</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_FirmwareConfig.icns</string>
<key>CFBundleTypeName</key>
<string>DeSmuME Firmware Configuration</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.desmume.firmwareconfig</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dct</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_ROMCheats.icns</string>
<key>CFBundleTypeName</key>
<string>DeSmuME ROM Cheats</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.desmume.romcheats</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>sav</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_NoGBA_ROMSave.icns</string>
<key>CFBundleTypeName</key>
<string>No$GBA ROM Save</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>de.emubase.nocash.romsave.gba</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>duc</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_ActionReplaySave.icns</string>
<key>CFBundleTypeName</key>
<string>Action Replay Save</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.codejunkies.actionreplay.save.nintendo.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>bin</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_HWImage_NDS.icns</string>
<key>CFBundleTypeName</key>
<string>Nintendo DS Hardware Image</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.nintendo.hwimage.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>xml</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_ADVANsCEneDatabase.icns</string>
<key>CFBundleTypeName</key>
<string>ADVANsCEne Database</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.advanscene.database.nintendo.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dat</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_R4CheatDatabase.icns</string>
<key>CFBundleTypeName</key>
<string>R4 Cheats Database</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>net.gbatemp.cheats.database.nintendo.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleIconFile</key>
<string>AppIcon_DeSmuME</string>
<key>CFBundleIdentifier</key>
<string>org.desmume.DeSmuME</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>v0.9.11 (Debug)</string>
<key>CFBundleSignature</key>
<string>DSmM</string>
<key>CFBundleVersion</key>
<string>0.9.11</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.entertainment</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright ©2007-2015 DeSmuME Team. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>DeSmuME Save State</string>
<key>UTTypeIconFile</key>
<string>AppIcon_SaveState.icns</string>
<key>UTTypeIdentifier</key>
<string>com.desmume.savestate</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dst</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>DeSmuME ROM Save</string>
<key>UTTypeIconFile</key>
<string>AppIcon_ROMSave.icns</string>
<key>UTTypeIdentifier</key>
<string>com.desmume.romsave</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dsv</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>DeSmuME Firmware Configuration</string>
<key>UTTypeIconFile</key>
<string>AppIcon_FirmwareConfig.icns</string>
<key>UTTypeIdentifier</key>
<string>com.desmume.firmwareconfig</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dfc</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>DeSmuME ROM Cheats</string>
<key>UTTypeIconFile</key>
<string>AppIcon_ROMCheats.icns</string>
<key>UTTypeIdentifier</key>
<string>com.desmume.romcheats</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dct</string>
</array>
</dict>
</dict>
</array>
<key>UTImportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Nintendo DS ROM</string>
<key>UTTypeIconFile</key>
<string>AppIcon_NintendoDS_ROM.icns</string>
<key>UTTypeIdentifier</key>
<string>com.nintendo.rom.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>nds</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Gameboy Advance ROM</string>
<key>UTTypeIconFile</key>
<string>AppIcon_NintendoGBA_ROM.icns</string>
<key>UTTypeIdentifier</key>
<string>com.nintendo.rom.gba</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>ds.gba</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>No$GBA ROM Save</string>
<key>UTTypeIconFile</key>
<string>AppIcon_NoGBA_ROMSave.icns</string>
<key>UTTypeIdentifier</key>
<string>de.emubase.nocash.romsave.gba</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>sav</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Action Replay Save</string>
<key>UTTypeIconFile</key>
<string>AppIcon_ActionReplaySave.icns</string>
<key>UTTypeIdentifier</key>
<string>com.codejunkies.actionreplay.save.nintendo.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>duc</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Nintendo DS Hardware Image</string>
<key>UTTypeIconFile</key>
<string>AppIcon_HWImage_NDS.icns</string>
<key>UTTypeIdentifier</key>
<string>com.nintendo.hwimage.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>bin</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.xml</string>
</array>
<key>UTTypeDescription</key>
<string>ADVANsCEne Database</string>
<key>UTTypeIconFile</key>
<string>AppIcon_ADVANsCEneDatabase.icns</string>
<key>UTTypeIdentifier</key>
<string>com.advanscene.database.nintendo.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>xml</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>R4 Cheats Database</string>
<key>UTTypeIconFile</key>
<string>AppIcon_R4CheatDatabase.icns</string>
<key>UTTypeIdentifier</key>
<string>net.gbatemp.cheats.database.nintendo.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dat</string>
</array>
</dict>
</dict>
</array>
</dict>
</plist>
+474
View File
@@ -0,0 +1,474 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>nds</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_NintendoDS_ROM.icns</string>
<key>CFBundleTypeName</key>
<string>Nintendo DS ROM</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.nintendo.rom.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>ds.gba</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_NintendoGBA_ROM.icns</string>
<key>CFBundleTypeName</key>
<string>Gameboy Advance ROM</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.nintendo.rom.gba</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dst</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_SaveState.icns</string>
<key>CFBundleTypeName</key>
<string>DeSmuME Save State</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.desmume.savestate</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dsv</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_ROMSave.icns</string>
<key>CFBundleTypeName</key>
<string>DeSmuME ROM Save</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.desmume.romsave</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dfc</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_FirmwareConfig.icns</string>
<key>CFBundleTypeName</key>
<string>DeSmuME Firmware Configuration</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.desmume.firmwareconfig</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dct</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_ROMCheats.icns</string>
<key>CFBundleTypeName</key>
<string>DeSmuME ROM Cheats</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.desmume.romcheats</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>sav</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_NoGBA_ROMSave.icns</string>
<key>CFBundleTypeName</key>
<string>No$GBA ROM Save</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>de.emubase.nocash.romsave.gba</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>duc</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_ActionReplaySave.icns</string>
<key>CFBundleTypeName</key>
<string>Action Replay Save</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.codejunkies.actionreplay.save.nintendo.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>bin</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_HWImage_NDS.icns</string>
<key>CFBundleTypeName</key>
<string>Nintendo DS Hardware Image</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.nintendo.hwimage.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>xml</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_ADVANsCEneDatabase.icns</string>
<key>CFBundleTypeName</key>
<string>ADVANsCEne Database</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.advanscene.database.nintendo.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>dat</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>AppIcon_R4CheatDatabase.icns</string>
<key>CFBundleTypeName</key>
<string>R4 Cheats Database</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>net.gbatemp.cheats.database.nintendo.ds</string>
</array>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleIconFile</key>
<string>AppIcon_DeSmuME</string>
<key>CFBundleIdentifier</key>
<string>org.desmume.DeSmuME</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>v0.9.11</string>
<key>CFBundleSignature</key>
<string>DSmM</string>
<key>CFBundleVersion</key>
<string>0.9.11</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.entertainment</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright ©2007-2015 DeSmuME Team. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>DeSmuME Save State</string>
<key>UTTypeIconFile</key>
<string>AppIcon_SaveState.icns</string>
<key>UTTypeIdentifier</key>
<string>com.desmume.savestate</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dst</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>DeSmuME ROM Save</string>
<key>UTTypeIconFile</key>
<string>AppIcon_ROMSave.icns</string>
<key>UTTypeIdentifier</key>
<string>com.desmume.romsave</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dsv</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>DeSmuME Firmware Configuration</string>
<key>UTTypeIconFile</key>
<string>AppIcon_FirmwareConfig.icns</string>
<key>UTTypeIdentifier</key>
<string>com.desmume.firmwareconfig</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dfc</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>DeSmuME ROM Cheats</string>
<key>UTTypeIconFile</key>
<string>AppIcon_ROMCheats.icns</string>
<key>UTTypeIdentifier</key>
<string>com.desmume.romcheats</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dct</string>
</array>
</dict>
</dict>
</array>
<key>UTImportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Nintendo DS ROM</string>
<key>UTTypeIconFile</key>
<string>AppIcon_NintendoDS_ROM.icns</string>
<key>UTTypeIdentifier</key>
<string>com.nintendo.rom.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>nds</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Gameboy Advance ROM</string>
<key>UTTypeIconFile</key>
<string>AppIcon_NintendoGBA_ROM.icns</string>
<key>UTTypeIdentifier</key>
<string>com.nintendo.rom.gba</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>ds.gba</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>No$GBA ROM Save</string>
<key>UTTypeIconFile</key>
<string>AppIcon_NoGBA_ROMSave.icns</string>
<key>UTTypeIdentifier</key>
<string>de.emubase.nocash.romsave.gba</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>sav</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Action Replay Save</string>
<key>UTTypeIconFile</key>
<string>AppIcon_ActionReplaySave.icns</string>
<key>UTTypeIdentifier</key>
<string>com.codejunkies.actionreplay.save.nintendo.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>duc</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>Nintendo DS Hardware Image</string>
<key>UTTypeIconFile</key>
<string>AppIcon_HWImage_NDS.icns</string>
<key>UTTypeIdentifier</key>
<string>com.nintendo.hwimage.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>bin</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.xml</string>
</array>
<key>UTTypeDescription</key>
<string>ADVANsCEne Database</string>
<key>UTTypeIconFile</key>
<string>AppIcon_ADVANsCEneDatabase.icns</string>
<key>UTTypeIdentifier</key>
<string>com.advanscene.database.nintendo.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>xml</string>
</array>
</dict>
</dict>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>R4 Cheats Database</string>
<key>UTTypeIconFile</key>
<string>AppIcon_R4CheatDatabase.icns</string>
<key>UTTypeIdentifier</key>
<string>net.gbatemp.cheats.database.nintendo.ds</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>dat</string>
</array>
</dict>
</dict>
</array>
</dict>
</plist>
+202
View File
@@ -0,0 +1,202 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>12</key>
<string>Q</string>
<key>13</key>
<string>W</string>
<key>14</key>
<string>E</string>
<key>15</key>
<string>R</string>
<key>17</key>
<string>T</string>
<key>16</key>
<string>Y</string>
<key>32</key>
<string>U</string>
<key>34</key>
<string>I</string>
<key>31</key>
<string>O</string>
<key>35</key>
<string>P</string>
<key>0</key>
<string>A</string>
<key>1</key>
<string>S</string>
<key>2</key>
<string>D</string>
<key>3</key>
<string>F</string>
<key>5</key>
<string>G</string>
<key>4</key>
<string>H</string>
<key>38</key>
<string>J</string>
<key>40</key>
<string>K</string>
<key>37</key>
<string>L</string>
<key>6</key>
<string>Z</string>
<key>7</key>
<string>X</string>
<key>8</key>
<string>C</string>
<key>9</key>
<string>V</string>
<key>11</key>
<string>B</string>
<key>45</key>
<string>N</string>
<key>46</key>
<string>M</string>
<key>18</key>
<string>1</string>
<key>19</key>
<string>2</string>
<key>20</key>
<string>3</string>
<key>21</key>
<string>4</string>
<key>23</key>
<string>5</string>
<key>22</key>
<string>6</string>
<key>26</key>
<string>7</string>
<key>28</key>
<string>8</string>
<key>25</key>
<string>9</string>
<key>29</key>
<string>0</string>
<key>122</key>
<string>F1</string>
<key>120</key>
<string>F2</string>
<key>99</key>
<string>F3</string>
<key>118</key>
<string>F4</string>
<key>96</key>
<string>F5</string>
<key>97</key>
<string>F6</string>
<key>98</key>
<string>F7</string>
<key>100</key>
<string>F8</string>
<key>101</key>
<string>F9</string>
<key>109</key>
<string>F10</string>
<key>103</key>
<string>F11</string>
<key>111</key>
<string>F12</string>
<key>105</key>
<string>F13</string>
<key>107</key>
<string>F14</string>
<key>113</key>
<string>F15</string>
<key>106</key>
<string>F16</string>
<key>64</key>
<string>F17</string>
<key>79</key>
<string>F18</string>
<key>80</key>
<string>F19</string>
<key>50</key>
<string>` (Accent)</string>
<key>27</key>
<string>- (Dash)</string>
<key>24</key>
<string>=</string>
<key>51</key>
<string>Delete (Backspace)</string>
<key>48</key>
<string>Tab</string>
<key>33</key>
<string>[</string>
<key>30</key>
<string>]</string>
<key>42</key>
<string>\</string>
<key>41</key>
<string>; (Semicolon)</string>
<key>39</key>
<string>&apos; (Quote)</string>
<key>36</key>
<string>Return</string>
<key>43</key>
<string>, (Comma)</string>
<key>47</key>
<string>. (Period)</string>
<key>44</key>
<string>/</string>
<key>49</key>
<string>Space</string>
<key>115</key>
<string>Home</string>
<key>119</key>
<string>End</string>
<key>116</key>
<string>Page Up</string>
<key>121</key>
<string>Page Down</string>
<key>117</key>
<string>Forward Delete</string>
<key>126</key>
<string>Up Arrow</string>
<key>125</key>
<string>Down Arrow</string>
<key>123</key>
<string>Left Arrow</string>
<key>124</key>
<string>Right Arrow</string>
<key>82</key>
<string>NumPad 0</string>
<key>83</key>
<string>NumPad 1</string>
<key>84</key>
<string>NumPad 2</string>
<key>85</key>
<string>NumPad 3</string>
<key>86</key>
<string>NumPad 4</string>
<key>87</key>
<string>NumPad 5</string>
<key>88</key>
<string>NumPad 6</string>
<key>89</key>
<string>NumPad 7</string>
<key>91</key>
<string>NumPad 8</string>
<key>92</key>
<string>NumPad 9</string>
<key>71</key>
<string>NumPad Clear</string>
<key>81</key>
<string>NumPad =</string>
<key>75</key>
<string>NumPad /</string>
<key>67</key>
<string>NumPad *</string>
<key>78</key>
<string>NumPad -</string>
<key>69</key>
<string>NumPad +</string>
<key>65</key>
<string>NumPad .</string>
<key>76</key>
<string>NumPad Enter</string>
<key>53</key>
<string>Escape</string>
</dict>
</plist>
+14
View File
@@ -0,0 +1,14 @@
EXTRA_DIST = cocoa_util.m DeSmuME.cbp globals.h main.mm main_window.h main_window.mm nds_control.h nds_control.mm preferences.mm \
about.m DeSmuME.icns Info.plist InfoPlist.strings input.h input.mm \
makeapp.sh PkgInfo preferences.h screenshot.h screenshot.mm \
screen_state.h screen_state.m sndOSX.h sndOSX.mm video_output_view.h video_output_view.mm \
DeSmuME.xcodeproj/project.pbxproj Rakefile \
dialogs/rom_info.h dialogs/rom_info.m dialogs/speed_limit_selection_window.h dialogs/speed_limit_selection_window.mm \
translations/English.lproj/Localizable.strings translations/English.lproj/MainMenu.nib/classes.nib \
translations/English.lproj/MainMenu.nib/info.nib translations/English.lproj/MainMenu.nib/keyedobjects.nib \
translations/French.lproj/Localizable.strings translations/French.lproj/MainMenu.nib/classes.nib \
translations/French.lproj/MainMenu.nib/info.nib translations/French.lproj/MainMenu.nib/keyedobjects.nib \
translations/Italian.lproj/Localizable.strings translations/Italian.lproj/MainMenu.nib/classes.nib \
translations/Italian.lproj/MainMenu.nib/info.nib translations/Italian.lproj/MainMenu.nib/keyedobjects.nib \
translations/Japanese.lproj/Localizable.strings translations/Japanese.lproj/MainMenu.nib/classes.nib \
translations/Japanese.lproj/MainMenu.nib/info.nib translations/Japanese.lproj/MainMenu.nib/keyedobjects.nib
+6410
View File
File diff suppressed because it is too large Load Diff
+410
View File
@@ -0,0 +1,410 @@
/*
Copyright (C) 2014-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 _OGLDISPLAYOUTPUT_H_
#define _OGLDISPLAYOUTPUT_H_
#ifndef _OGLDISPLAYOUTPUT_3_2_H_
#if defined(__APPLE__)
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
#endif
#endif // _OGLDISPLAYOUTPUT_3_2_H_
#include <set>
#include <string>
#include "../filter/videofilter.h"
class OGLVideoOutput;
enum
{
OutputFilterTypeID_NearestNeighbor = 0,
OutputFilterTypeID_Bilinear = 1,
OutputFilterTypeID_BicubicBSpline = 2,
OutputFilterTypeID_BicubicMitchell = 3,
OutputFilterTypeID_Lanczos2 = 4,
OutputFilterTypeID_Lanczos3 = 5
};
enum ShaderSupportTier
{
ShaderSupport_Unsupported = 0,
ShaderSupport_BottomTier = 1,
ShaderSupport_LowTier = 2,
ShaderSupport_MidTier = 3,
ShaderSupport_HighTier = 4,
ShaderSupport_TopTier = 5,
ShaderSupport_FutureTier = 6,
};
class OGLInfo
{
protected:
GLint _versionMajor;
GLint _versionMinor;
GLint _versionRevision;
ShaderSupportTier _shaderSupport;
bool _useShader150;
bool _isVBOSupported;
bool _isPBOSupported;
bool _isFBOSupported;
public:
OGLInfo();
virtual ~OGLInfo() {};
bool IsUsingShader150();
bool IsVBOSupported();
bool IsPBOSupported();
bool IsShaderSupported();
bool IsFBOSupported();
ShaderSupportTier GetShaderSupport();
virtual void GetExtensionSetOGL(std::set<std::string> *oglExtensionSet) = 0;
virtual bool IsExtensionPresent(const std::set<std::string> &oglExtensionSet, const std::string &extensionName) const = 0;
};
class OGLInfo_Legacy : public OGLInfo
{
public:
OGLInfo_Legacy();
virtual void GetExtensionSetOGL(std::set<std::string> *oglExtensionSet);
virtual bool IsExtensionPresent(const std::set<std::string> &oglExtensionSet, const std::string &extensionName) const;
};
class OGLShaderProgram
{
protected:
GLuint _vertexID;
GLuint _fragmentID;
GLuint _programID;
ShaderSupportTier _shaderSupport;
virtual GLuint LoadShaderOGL(GLenum shaderType, const char *shaderProgram, bool useShader150);
virtual bool LinkOGL();
public:
OGLShaderProgram();
virtual ~OGLShaderProgram();
ShaderSupportTier GetShaderSupport();
void SetShaderSupport(const ShaderSupportTier theTier);
GLuint GetVertexShaderID();
void SetVertexShaderOGL(const char *shaderProgram, bool useShader150);
GLuint GetFragmentShaderID();
void SetFragmentShaderOGL(const char *shaderProgram, bool useShader150);
void SetVertexAndFragmentShaderOGL(const char *vertShaderProgram, const char *fragShaderProgram, bool useShader150);
GLuint GetProgramID();
};
class OGLFilter
{
protected:
OGLShaderProgram *_program;
bool _isVAOPresent;
GLuint _texDstID;
GLint _texCoordBuffer[8];
GLuint _fboID;
GLuint _vaoID;
GLuint _vboVtxID;
GLuint _vboTexCoordID;
GLuint _vboElementID;
GLfloat _scale;
GLsizei _srcWidth;
GLsizei _srcHeight;
GLsizei _dstWidth;
GLsizei _dstHeight;
virtual void OGLFilterInit(GLsizei srcWidth, GLsizei srcHeight, GLfloat scale);
public:
OGLFilter();
OGLFilter(GLsizei srcWidth, GLsizei srcHeight, GLfloat scale);
virtual ~OGLFilter();
static void GetSupport(int vfTypeID, bool *outSupportCPU, bool *outSupportShader);
OGLShaderProgram* GetProgram();
GLuint GetDstTexID();
GLsizei GetSrcWidth();
GLsizei GetSrcHeight();
GLsizei GetDstWidth();
GLsizei GetDstHeight();
void SetSrcSizeOGL(GLsizei w, GLsizei h);
GLfloat GetScale();
void SetScaleOGL(GLfloat scale);
virtual GLuint RunFilterOGL(GLuint srcTexID);
void DownloadDstBufferOGL(uint32_t *dstBuffer, size_t lineOffset, size_t readLineCount);
};
class OGLFilterDeposterize : public OGLFilter
{
protected:
GLuint _texIntermediateID;
public:
OGLFilterDeposterize(GLsizei srcWidth, GLsizei srcHeight, ShaderSupportTier theTier, bool useShader150);
~OGLFilterDeposterize();
virtual GLuint RunFilterOGL(GLuint srcTexID);
};
class OGLVideoLayer
{
protected:
OGLVideoOutput *_output;
GLsizei _viewportWidth;
GLsizei _viewportHeight;
public:
OGLVideoLayer() {};
~OGLVideoLayer() {};
void SetViewportSizeOGL(GLsizei w, GLsizei h)
{
this->_viewportWidth = w;
this->_viewportHeight = h;
};
virtual void ProcessOGL() {};
virtual void RenderOGL() {};
};
class OGLImage
{
protected:
bool _isVAOPresent;
bool _canUseShaderBasedFilters;
bool _canUseShaderOutput;
bool _useShader150;
ShaderSupportTier _shaderSupport;
bool _needUploadVertices;
bool _useDeposterize;
bool _useShaderBasedPixelScaler;
bool _filtersPreferGPU;
int _outputFilter;
VideoFilterTypeID _pixelScaler;
OGLFilter *_filterDeposterize;
OGLFilter *_shaderFilter;
OGLShaderProgram *_finalOutputProgram;
VideoFilter *_vf;
uint32_t *_vfMasterDstBuffer;
double _normalWidth;
double _normalHeight;
GLsizei _viewportWidth;
GLsizei _viewportHeight;
GLubyte *_vtxElementPointer;
GLint _displayTexFilter;
GLuint _texCPUFilterDstID;
GLuint _texLQ2xLUT;
GLuint _texHQ2xLUT;
GLuint _texHQ4xLUT;
GLint _vtxBuffer[8];
GLfloat _texCoordBuffer[8];
GLuint _texVideoInputDataID;
GLuint _texVideoSourceID;
GLuint _texVideoPixelScalerID;
GLuint _texVideoOutputID;
GLuint _vaoMainStatesID;
GLuint _vboVertexID;
GLuint _vboTexCoordID;
GLuint _vboElementID;
GLint _uniformFinalOutputAngleDegrees;
GLint _uniformFinalOutputScalar;
GLint _uniformFinalOutputViewSize;
void UploadHQnxLUTs();
virtual void UploadVerticesOGL();
virtual void UploadTexCoordsOGL();
virtual void UploadTransformationOGL();
void UpdateVertices();
void UpdateTexCoords(GLfloat s, GLfloat t);
public:
OGLImage() {};
OGLImage(OGLInfo *oglInfo, GLsizei imageWidth, GLsizei imageHeight, GLsizei viewportWidth, GLsizei viewportHeight);
virtual ~OGLImage();
bool GetFiltersPreferGPU();
void SetFiltersPreferGPUOGL(bool preferGPU);
bool GetSourceDeposterize();
void SetSourceDeposterize(bool useDeposterize);
bool CanUseShaderBasedFilters();
void GetNormalSize(double *w, double *h);
int GetOutputFilter();
virtual void SetOutputFilterOGL(const int filterID);
int GetPixelScaler();
virtual void SetPixelScalerOGL(const int filterID);
virtual bool SetGPUPixelScalerOGL(const VideoFilterTypeID filterID);
virtual void SetCPUPixelScalerOGL(const VideoFilterTypeID filterID);
virtual void LoadFrameOGL(const uint32_t *frameData, GLint x, GLint y, GLsizei w, GLsizei h);
virtual void ProcessOGL();
virtual void RenderOGL();
};
class OGLDisplayLayer : public OGLVideoLayer
{
protected:
bool _isVAOPresent;
bool _canUseShaderBasedFilters;
bool _canUseShaderOutput;
bool _useShader150;
ShaderSupportTier _shaderSupport;
bool _needUploadVertices;
bool _useDeposterize;
bool _useShaderBasedPixelScaler;
bool _filtersPreferGPU;
int _outputFilter;
VideoFilterTypeID _pixelScaler;
OGLShaderProgram *_finalOutputProgram;
OGLFilter *_filterDeposterize[2];
OGLFilter *_shaderFilter[2];
GLint _displayTexFilter[2];
GLuint _texVideoInputDataID[2];
GLuint _texVideoSourceID[2];
GLuint _texVideoPixelScalerID[2];
GLuint _texVideoOutputID[2];
uint32_t *_vfMasterDstBuffer;
VideoFilter *_vf[2];
VideoFilter *_vfDual;
GLuint _texCPUFilterDstID[2];
int _displayMode;
int _displayOrder;
int _displayOrientation;
double _normalWidth;
double _normalHeight;
GLfloat _gapScalar;
GLfloat _rotation;
GLuint _texLQ2xLUT;
GLuint _texHQ2xLUT;
GLuint _texHQ4xLUT;
GLint vtxBuffer[4 * 8];
GLfloat texCoordBuffer[2 * 8];
size_t _vtxBufferOffset;
GLuint _vaoMainStatesID;
GLuint _vboVertexID;
GLuint _vboTexCoordID;
GLuint _vboElementID;
GLint _uniformFinalOutputAngleDegrees;
GLint _uniformFinalOutputScalar;
GLint _uniformFinalOutputViewSize;
void UploadHQnxLUTs();
virtual void UploadVerticesOGL();
virtual void UploadTexCoordsOGL();
virtual void UploadTransformationOGL();
void UpdateVertices();
void UpdateTexCoords(GLfloat s, GLfloat t);
public:
OGLDisplayLayer() {};
OGLDisplayLayer(OGLVideoOutput *oglVO);
virtual ~OGLDisplayLayer();
bool GetFiltersPreferGPU();
void SetFiltersPreferGPUOGL(bool preferGPU);
int GetMode();
void SetMode(int dispMode);
int GetOrientation();
void SetOrientation(int dispOrientation);
int GetOrder();
void SetOrder(int dispOrder);
GLfloat GetGapScalar();
void SetGapScalar(GLfloat theScalar);
GLfloat GetRotation();
void SetRotation(GLfloat theRotation);
bool GetSourceDeposterize();
void SetSourceDeposterize(bool useDeposterize);
bool CanUseShaderBasedFilters();
void GetNormalSize(double *w, double *h);
int GetOutputFilter();
virtual void SetOutputFilterOGL(const int filterID);
int GetPixelScaler();
virtual void SetPixelScalerOGL(const int filterID);
virtual bool SetGPUPixelScalerOGL(const VideoFilterTypeID filterID);
virtual void SetCPUPixelScalerOGL(const VideoFilterTypeID filterID);
virtual void LoadFrameOGL(const uint16_t *frameData, GLint x, GLint y, GLsizei w, GLsizei h);
virtual void ProcessOGL();
virtual void RenderOGL();
};
class OGLVideoOutput
{
protected:
OGLInfo *_info;
GLsizei _viewportWidth;
GLsizei _viewportHeight;
std::vector<OGLVideoLayer *> *_layerList;
public:
OGLVideoOutput();
~OGLVideoOutput();
virtual void InitLayers();
virtual OGLInfo* GetInfo();
virtual GLsizei GetViewportWidth();
virtual GLsizei GetViewportHeight();
OGLDisplayLayer* GetDisplayLayer();
virtual void ProcessOGL();
virtual void RenderOGL();
virtual void SetViewportSizeOGL(GLsizei w, GLsizei h);
};
OGLInfo* OGLInfoCreate_Legacy();
extern OGLInfo* (*OGLInfoCreate_Func)();
extern void (*glBindVertexArrayDESMUME)(GLuint id);
extern void (*glDeleteVertexArraysDESMUME)(GLsizei n, const GLuint *ids);
extern void (*glGenVertexArraysDESMUME)(GLsizei n, GLuint *ids);
#endif // _OGLDISPLAYOUTPUT_H_
+92
View File
@@ -0,0 +1,92 @@
/*
Copyright (C) 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 "OGLDisplayOutput_3_2.h"
enum OGLVertexAttributeID
{
OGLVertexAttributeID_Position = 0,
OGLVertexAttributeID_TexCoord0 = 8
};
OGLInfo* OGLInfoCreate_3_2()
{
return new OGLInfo_3_2;
}
void glBindVertexArray_3_2(GLuint vaoID)
{
glBindVertexArray(vaoID);
}
void glDeleteVertexArrays_3_2(GLsizei n, const GLuint *vaoIDs)
{
glDeleteVertexArrays(n, vaoIDs);
}
void glGenVertexArrays_3_2(GLsizei n, GLuint *vaoIDs)
{
glGenVertexArrays(n, vaoIDs);
}
OGLInfo_3_2::OGLInfo_3_2()
{
_useShader150 = true;
_isVBOSupported = true;
_isPBOSupported = true;
_isFBOSupported = true;
glBindVertexArrayDESMUME = &glBindVertexArray_3_2;
glDeleteVertexArraysDESMUME = &glDeleteVertexArrays_3_2;
glGenVertexArraysDESMUME = &glGenVertexArrays_3_2;
_shaderSupport = ShaderSupport_MidTier;
if (_versionMajor == 4)
{
if (_versionMinor <= 1)
{
_shaderSupport = ShaderSupport_HighTier;
}
else
{
_shaderSupport = ShaderSupport_TopTier;
}
}
}
void OGLInfo_3_2::GetExtensionSetOGL(std::set<std::string> *oglExtensionSet)
{
GLint extensionCount = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
for (unsigned int i = 0; i < extensionCount; i++)
{
std::string extensionName = std::string((const char *)glGetStringi(GL_EXTENSIONS, i));
oglExtensionSet->insert(extensionName);
}
}
bool OGLInfo_3_2::IsExtensionPresent(const std::set<std::string> &oglExtensionSet, const std::string &extensionName) const
{
if (oglExtensionSet.size() == 0)
{
return false;
}
return (oglExtensionSet.find(extensionName) != oglExtensionSet.end());
}
+39
View File
@@ -0,0 +1,39 @@
/*
Copyright (C) 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 _OGLDISPLAYOUTPUT_3_2_H_
#define _OGLDISPLAYOUTPUT_3_2_H_
#if defined(__APPLE__)
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
#endif
#include "OGLDisplayOutput.h"
class OGLInfo_3_2 : public OGLInfo
{
public:
OGLInfo_3_2();
virtual void GetExtensionSetOGL(std::set<std::string> *oglExtensionSet);
virtual bool IsExtensionPresent(const std::set<std::string> &oglExtensionSet, const std::string &extensionName) const;
};
OGLInfo* OGLInfoCreate_3_2();
#endif
+1
View File
@@ -0,0 +1 @@
APPL????
+203
View File
@@ -0,0 +1,203 @@
require 'tempfile'
require "open3"
# General
indent = ' '
# Compile Options
compile = {
:command => 'g++',
:files => Dir['*.m'] + Dir['*.mm'] + Dir['dialogs/*.m'] + Dir['dialogs/*.mm'] + ([
'MMU', 'SPU', 'emufile', 'fs-linux', 'matrix', 'FIFO', 'NDSSystem', 'arm_instructions', 'cp15', 'mc', 'cheatSystem',
'thumb_instructions', 'GPU', 'OGLRender', 'armcpu', 'gfx3d', 'render3D', 'wifi', 'GPU_osd_stub', 'ROMReader', 'texcache',
'slot1', 'movie',
'bios', 'debug', 'saves', 'readwrite', 'rtc', 'rasterize', 'common', 'mic', 'addons'].map { |core_file| '../' + core_file + '.cpp' } ) +
Dir['../utils/*.c'] + Dir['../utils/*.cpp'] + Dir['../utils/decrypt/*.cpp'] + Dir['../addons/*.cpp'],
:defines => {
:global => ['DESMUME_OBJ_C', 'OBJ_C'],
:cocoa => ['DESMUME_COCOA', 'HAVE_LIBZ', 'HAVE_OPENGL']},
:options => {
:global => [
'arch i386',
'fmessage-length=0',
'pascal-strings',
'fasm-blocks',
'O3',
'mfix-and-continue',
'funroll-loops',
'fstrict-aliasing',
'ftree-vectorize',
'mmacosx-version-min=10.4',
'gdwarf-2'],
:obj_cpp => ['fvisibility-inlines-hidden']
}
}
# Link Options
link = {
:command => 'gcc',
:files => Dir[File.dirname(__FILE__) + '/build/rake/o/*.o'],
:libraries => { :cocoa => ['z', 'stdc++'] },
:frameworks => { :cocoa => ['Cocoa', 'OpenGL', 'AudioUnit'] },
:options => {}
}
# Params
def verbose?
return false unless ENV.include? 'verbose'
return false if ENV['verbose'].downcase == 'false'
return true if ENV['verbose'].downcase == 'true'
raise StandardError, "verbose must be true or false. Type rake help for help"
end
# Compile Step
desc 'Compiles the source files'
task :compile do
puts 'Compiling...'
#create directory to place object files
Dir.mkdir(File.dirname(__FILE__) + '/build') rescue nil
Dir.mkdir(File.dirname(__FILE__) + '/build/rake') rescue nil
Dir.mkdir(File.dirname(__FILE__) + '/build/rake/o') rescue nil
task_options = []
task_options += compile[:options][:global] rescue []
task_options += compile[:options][:cocoa ] rescue []
task_options += compile[:defines][:global].collect { |d| 'D' + d } rescue []
task_options += compile[:defines][:cocoa ].collect { |d| 'D' + d } rescue []
compile[:files].each do |filename|
puts indent + 'Compiling ' + filename
file_options = []
file_options += compile[:options][:obj_c ] rescue [] if filename =~ /.*\.m$/i
file_options += compile[:options][:obj_cpp] rescue [] if filename =~ /.*\.mm$/i
file_options += compile[:defines][:obj_c ].collect { |d| 'D' + d } rescue [] if filename =~ /.*\.m/i
file_options += compile[:defines][:obj_cpp].collect { |d| 'D' + d } rescue [] if filename =~ /.*\.mm/i
command = [compile[:command]]
command << filename
command << '-o ' + File.dirname(__FILE__) + '/build/rake/o/' + File.basename(filename) + '.o'
command << '-c'
command += (file_options + task_options).map { |o| '-' + o }
command = command.join ' '
puts indent*2 + command if verbose?
Open3.popen3(command) do |stdin, stdout, stderr|
stdout.readlines.each do |line|
puts indent*2 + line
end
error = false
stderr.readlines.each do |err|
error = true if err =~ /:\s*error\s*:/i
puts indent*2 + err
end
raise StandardError, "Didn't compile!" if error
end
end
end
# Link Step
desc 'Builds an executable out of the object files'
task :link => :compile do
puts 'Linking...'
Dir.mkdir(File.dirname(__FILE__) + '/build') rescue nil
Dir.mkdir(File.dirname(__FILE__) + '/build/rake') rescue nil
Dir.mkdir(File.dirname(__FILE__) + '/build/rake/DeSmuME.app') rescue nil
Dir.mkdir(File.dirname(__FILE__) + '/build/rake/DeSmuME.app/Contents') rescue nil
Dir.mkdir(File.dirname(__FILE__) + '/build/rake/DeSmuME.app/Contents/MacOS/') rescue nil
command = [link[:command]]
command += link[:files]
command << '-o ' + File.dirname(__FILE__) + '/build/rake/DeSmuME.app/Contents/MacOS/DeSmuME'
command += link[:options ][:global].collect { |o| '-' + o } rescue []
command += link[:options ][:cocoa ].collect { |o| '-' + o } rescue []
command += link[:libraries ][:global].collect { |l| '-l ' + l } rescue []
command += link[:libraries ][:cocoa ].collect { |l| '-l ' + l } rescue []
command += link[:frameworks][:global].collect { |f| '-framework ' + f } rescue []
command += link[:frameworks][:cocoa ].collect { |f| '-framework ' + f } rescue []
command = command.join ' '
puts indent + command if verbose?
Open3.popen3(command) do |stdin, stdout, stderr|
stdout.readlines.each do |line|
puts indent + line
end
raise StandardError, 'Couldn\'t link!' unless stderr.readlines.each do |err|
puts indent + err
end.empty?
end
end
# Build App
desc 'Builds a Cocoa application bundle out of the linked files'
task :build_cocoa_app => :link do
puts 'Building Application Bundle...'
Dir.mkdir(File.dirname(__FILE__) + '/build') rescue nil
Dir.mkdir(File.dirname(__FILE__) + '/build/rake') rescue nil
Dir.mkdir(File.dirname(__FILE__) + '/build/rake/DeSmuME.app') rescue nil
Dir.mkdir(File.dirname(__FILE__) + '/build/rake/DeSmuME.app/Contents') rescue nil
Dir.mkdir(File.dirname(__FILE__) + '/build/rake/DeSmuME.app/Contents/Resources') rescue nil
cp File.dirname(__FILE__) + '../..//Info.plist', File.dirname(__FILE__) + '/build/rake/DeSmuME.app/Contents/Resources/'
cp File.dirname(__FILE__) + '/PkgInfo', File.dirname(__FILE__) + '/build/rake/DeSmuME.app/Contents/Resources/'
cp File.dirname(__FILE__) + '/InfoPlist.strings', File.dirname(__FILE__) + '/build/rake/DeSmuME.app/Contents/Resources/'
cp File.dirname(__FILE__) + '/DeSmuME.icns', File.dirname(__FILE__) + '/build/rake/DeSmuME.app/Contents/Resources/'
system 'cp -r ' + File.dirname(__FILE__) + '/translations/*.lproj ' + File.dirname(__FILE__) + '/build/rake/DeSmuME.app/Contents/Resources/'
end
# Default Step
desc 'Makes the executable from scratch'
task :default => :build_cocoa_app do
puts 'Finished!'
end
# Run Task
desc 'Runs the executable if it exists'
task :run => :build_cocoa_app do
puts 'Running...'
system File.dirname(__FILE__) + '/build/rake/DeSmuME.app/Contents/MacOS/DeSmuME'
puts File.dirname(__FILE__) + '/build/rake/DeSmuME.app/Contents/MacOS/DeSmuME'
end
# Help
desc 'Displays helpful information about this Rakefile'
task :help do
puts ""
puts "Type rake to build the default task, which will make an executable"
puts "Otherwise type rake [taskname] to execute a particular task"
puts "Use rake -T to see what all the tasks are"
puts ""
puts "There are several parameters that you can pass:"
puts "(but don't put spaces around the equal signs though)"
puts " verbose = [true|false] print extra information (default is false)"
puts ""
end
+194
View File
@@ -0,0 +1,194 @@
/*
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/>.
*/
#ifdef __APPLE__
#include <Availability.h>
#include "utilities.h"
#endif // __APPLE__
#include "audiosamplegenerator.h"
#include <math.h>
#include "cocoa_globals.h"
#define NUM_INTERNAL_NOISE_SAMPLES 32
static const uint8_t noiseSample[NUM_INTERNAL_NOISE_SAMPLES] =
{
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0xFF,
0xF4, 0xE1, 0xBF, 0x9A, 0x71, 0x58, 0x5B, 0x5F, 0x62, 0xC2, 0x25, 0x05, 0x01, 0x01, 0x01, 0x01
};
size_t AudioGenerator::generateSampleBlock(size_t sampleCount, uint8_t *outBuffer)
{
if (outBuffer == NULL)
{
return 0;
}
for (uint8_t *i = outBuffer; i < outBuffer + sampleCount; i++)
{
*i = this->generateSample();
}
return sampleCount;
}
uint8_t AudioGenerator::generateSample()
{
return MIC_NULL_SAMPLE_VALUE;
}
AudioSampleBlockGenerator::AudioSampleBlockGenerator(const uint8_t *audioBuffer, const size_t sampleCount)
{
_buffer = (uint8_t *)malloc(sampleCount * sizeof(uint8_t));
_sampleCount = sampleCount;
_samplePosition = 0;
memcpy(_buffer, audioBuffer, _sampleCount * sizeof(uint8_t));
}
AudioSampleBlockGenerator::~AudioSampleBlockGenerator()
{
free(this->_buffer);
this->_buffer = NULL;
}
uint8_t* AudioSampleBlockGenerator::allocate(const size_t sampleCount)
{
if (this->_buffer != NULL)
{
free(this->_buffer);
}
this->_buffer = (uint8_t *)malloc(sampleCount * sizeof(uint8_t));
this->_sampleCount = sampleCount;
this->_samplePosition = 0;
memset(this->_buffer, MIC_NULL_SAMPLE_VALUE, this->_sampleCount * sizeof(uint8_t));
return this->_buffer;
}
uint8_t AudioSampleBlockGenerator::generateSample()
{
if (this->_samplePosition >= this->_sampleCount)
{
this->_samplePosition = 0;
}
return this->_buffer[_samplePosition++];
}
uint8_t* AudioSampleBlockGenerator::getBuffer() const
{
return this->_buffer;
}
size_t AudioSampleBlockGenerator::getSampleCount() const
{
return this->_sampleCount;
}
size_t AudioSampleBlockGenerator::getSamplePosition() const
{
return this->_samplePosition;
}
void AudioSampleBlockGenerator::setSamplePosition(size_t thePosition)
{
this->_samplePosition = thePosition % this->_sampleCount;
}
InternalNoiseGenerator::InternalNoiseGenerator()
{
_buffer = (uint8_t *)malloc(NUM_INTERNAL_NOISE_SAMPLES * sizeof(uint8_t));
_sampleCount = NUM_INTERNAL_NOISE_SAMPLES;
_samplePosition = 0;
memcpy(_buffer, noiseSample, _sampleCount * sizeof(uint8_t));
for (size_t i = 0; i < NUM_INTERNAL_NOISE_SAMPLES; i++)
{
_buffer[i] >>= 1;
}
}
uint8_t WhiteNoiseGenerator::generateSample()
{
#ifdef __APPLE__
#ifdef MAC_OS_X_VERSION_10_7
if (IsOSXVersionSupported(10, 7, 0))
{
return (uint8_t)(arc4random_uniform(0x00000080) & 0x7F);
}
return (uint8_t)((arc4random() % 0x00000080) & 0x7F);
#else
return (uint8_t)((arc4random() % 0x00000080) & 0x7F);
#endif
#else
return (uint8_t)(rand() & 0x7F);
#endif
}
SineWaveGenerator::SineWaveGenerator()
{
_frequency = 250.0;
_sampleRate = MIC_SAMPLE_RATE;
_cyclePosition = 0.0;
};
SineWaveGenerator::SineWaveGenerator(const double freq, const double sampleRate)
{
_frequency = freq;
_sampleRate = sampleRate;
_cyclePosition = 0.0;
}
uint8_t SineWaveGenerator::generateSample()
{
const uint8_t sampleValue = (uint8_t)(63.0 * sin(2.0 * M_PI * this->_cyclePosition)) + MIC_NULL_SAMPLE_VALUE;
this->_cyclePosition += (this->_frequency / this->_sampleRate);
return sampleValue;
}
double SineWaveGenerator::getFrequency() const
{
return this->_frequency;
}
void SineWaveGenerator::setFrequency(double freq)
{
this->_frequency = freq;
}
double SineWaveGenerator::getSampleRate() const
{
return this->_sampleRate;
}
void SineWaveGenerator::setSampleRate(double sampleRate)
{
this->_sampleRate = sampleRate;
}
double SineWaveGenerator::getCyclePosition() const
{
return this->_cyclePosition;
}
void SineWaveGenerator::setCyclePosition(double thePosition)
{
this->_cyclePosition = thePosition;
}
+94
View File
@@ -0,0 +1,94 @@
/*
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/>.
*/
#ifndef _AUDIO_SAMPLE_GENERATOR_
#define _AUDIO_SAMPLE_GENERATOR_
#include <stdint.h>
class AudioGenerator
{
public:
AudioGenerator() {};
virtual ~AudioGenerator() {};
virtual size_t generateSampleBlock(size_t sampleCount, uint8_t *outBuffer);
virtual uint8_t generateSample();
};
class NullGenerator : public AudioGenerator {};
class AudioSampleBlockGenerator : public AudioGenerator
{
protected:
uint8_t *_buffer;
size_t _sampleCount;
size_t _samplePosition;
public:
AudioSampleBlockGenerator()
: _buffer(NULL)
, _sampleCount(0)
, _samplePosition(0)
{};
AudioSampleBlockGenerator(const uint8_t *audioBuffer, const size_t sampleCount);
~AudioSampleBlockGenerator();
uint8_t* allocate(const size_t sampleCount);
uint8_t* getBuffer() const;
size_t getSampleCount() const;
size_t getSamplePosition() const;
void setSamplePosition(size_t thePosition);
virtual uint8_t generateSample();
};
class InternalNoiseGenerator : public AudioSampleBlockGenerator
{
public:
InternalNoiseGenerator();
};
class WhiteNoiseGenerator : public AudioGenerator
{
public:
virtual uint8_t generateSample();
};
class SineWaveGenerator : public AudioGenerator
{
protected:
double _frequency;
double _sampleRate;
double _cyclePosition;
public:
SineWaveGenerator();
SineWaveGenerator(const double freq, const double sampleRate);
double getFrequency() const;
void setFrequency(double freq);
double getSampleRate() const;
void setSampleRate(double sampleRate);
double getCyclePosition() const;
void setCyclePosition(double thePosition);
virtual uint8_t generateSample();
};
#endif // _AUDIO_SAMPLE_GENERATOR_
+33
View File
@@ -0,0 +1,33 @@
# Copyright 2006 Guillaume Duhamel
# Copyright 2006 Lawrence Sebald
# Copyright 2007 Anders Montonen
#
# This file is part of Yabause.
#
# Yabause 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.
#
# Yabause 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 Yabause; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
hdiutil create -megabytes 20 tmp.dmg -layout NONE -fs HFS+ -volname DeSmuME -ov
tmp=`hdid tmp.dmg`
disk=`echo $tmp | cut -f 1 -d\ `
cp -R build/Release/DeSmuME.app /Volumes/DeSmuME/
cp ../../ChangeLog /Volumes/DeSmuME/
cp ../../README /Volumes/DeSmuME/
cp ../../README.MAC /Volumes/DeSmuME/
cp ../../AUTHORS /Volumes/DeSmuME/
cp ../../COPYING /Volumes/DeSmuME/
hdiutil eject $disk
hdiutil convert -format UDZO tmp.dmg -o DeSmuME.dmg
rm tmp.dmg
+92
View File
@@ -0,0 +1,92 @@
/*
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/>.
*/
#import <Foundation/Foundation.h>
#include <pthread.h>
#include <libkern/OSAtomic.h>
@interface CocoaDSGPU : NSObject
{
UInt32 gpuStateFlags;
BOOL isCPUCoreCountAuto;
OSSpinLock spinlockGpuState;
pthread_rwlock_t *rwlockProducer;
}
@property (assign) UInt32 gpuStateFlags;
@property (assign) pthread_rwlock_t *rwlockProducer;
@property (assign) BOOL layerMainGPU;
@property (assign) BOOL layerMainBG0;
@property (assign) BOOL layerMainBG1;
@property (assign) BOOL layerMainBG2;
@property (assign) BOOL layerMainBG3;
@property (assign) BOOL layerMainOBJ;
@property (assign) BOOL layerSubGPU;
@property (assign) BOOL layerSubBG0;
@property (assign) BOOL layerSubBG1;
@property (assign) BOOL layerSubBG2;
@property (assign) BOOL layerSubBG3;
@property (assign) BOOL layerSubOBJ;
@property (assign) NSInteger render3DRenderingEngine;
@property (assign) BOOL render3DHighPrecisionColorInterpolation;
@property (assign) BOOL render3DEdgeMarking;
@property (assign) BOOL render3DFog;
@property (assign) BOOL render3DTextures;
@property (assign) NSUInteger render3DDepthComparisonThreshold;
@property (assign) NSUInteger render3DThreads;
@property (assign) BOOL render3DLineHack;
@property (assign) BOOL render3DMultisample;
@property (assign) BOOL render3DFragmentSamplingHack;
- (BOOL) gpuStateByBit:(const UInt32)stateBit;
- (BOOL) isGPUTypeDisplayed:(const NSInteger)theGpuType;
- (void) hideGPUType:(const NSInteger)theGpuType;
- (void) showGPUType:(const NSInteger)theGpuType;
- (NSString *) render3DRenderingEngineString;
@end
#ifdef __cplusplus
extern "C"
{
#endif
void GPU_FillScreenWithBGRA5551(const uint16_t colorValue);
void SetGPULayerState(const int gpuType, const unsigned int i, const bool state);
bool GetGPULayerState(const int gpuType, const unsigned int i);
void SetGPUDisplayState(const int gpuType, const bool state);
bool GetGPUDisplayState(const int gpuType);
bool OSXOpenGLRendererInit();
bool OSXOpenGLRendererBegin();
void OSXOpenGLRendererEnd();
bool CreateOpenGLRenderer();
void DestroyOpenGLRenderer();
void RequestOpenGLRenderer_3_2(bool request_3_2);
void SetOpenGLRendererFunctions(bool (*initFunction)(),
bool (*beginOGLFunction)(),
void (*endOGLFunction)());
#ifdef __cplusplus
}
#endif
+979
View File
@@ -0,0 +1,979 @@
/*
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/>.
*/
#import "cocoa_GPU.h"
#import "cocoa_globals.h"
#include "utilities.h"
#include "../NDSSystem.h"
#include "../GPU.h"
#include "../rasterize.h"
#ifdef MAC_OS_X_VERSION_10_7
#include "../OGLRender_3_2.h"
#else
#include "../OGLRender.h"
#endif
#include <OpenGL/OpenGL.h>
#undef BOOL
GPU3DInterface *core3DList[] = {
&gpu3DNull,
&gpu3DRasterize,
&gpu3Dgl,
NULL
};
@implementation CocoaDSGPU
@dynamic gpuStateFlags;
@synthesize rwlockProducer;
@dynamic layerMainGPU;
@dynamic layerMainBG0;
@dynamic layerMainBG1;
@dynamic layerMainBG2;
@dynamic layerMainBG3;
@dynamic layerMainOBJ;
@dynamic layerSubGPU;
@dynamic layerSubBG0;
@dynamic layerSubBG1;
@dynamic layerSubBG2;
@dynamic layerSubBG3;
@dynamic layerSubOBJ;
@dynamic render3DRenderingEngine;
@dynamic render3DHighPrecisionColorInterpolation;
@dynamic render3DEdgeMarking;
@dynamic render3DFog;
@dynamic render3DTextures;
@dynamic render3DDepthComparisonThreshold;
@dynamic render3DThreads;
@dynamic render3DLineHack;
@dynamic render3DMultisample;
@dynamic render3DFragmentSamplingHack;
- (id)init
{
self = [super init];
if (self == nil)
{
return self;
}
spinlockGpuState = OS_SPINLOCK_INIT;
rwlockProducer = NULL;
gpuStateFlags = GPUSTATE_MAIN_GPU_MASK |
GPUSTATE_MAIN_BG0_MASK |
GPUSTATE_MAIN_BG1_MASK |
GPUSTATE_MAIN_BG2_MASK |
GPUSTATE_MAIN_BG3_MASK |
GPUSTATE_MAIN_OBJ_MASK |
GPUSTATE_SUB_GPU_MASK |
GPUSTATE_SUB_BG0_MASK |
GPUSTATE_SUB_BG1_MASK |
GPUSTATE_SUB_BG2_MASK |
GPUSTATE_SUB_BG3_MASK |
GPUSTATE_SUB_OBJ_MASK;
isCPUCoreCountAuto = NO;
SetOpenGLRendererFunctions(&OSXOpenGLRendererInit,
&OSXOpenGLRendererBegin,
&OSXOpenGLRendererEnd);
GPU_FillScreenWithBGRA5551(0x8000);
return self;
}
- (void)dealloc
{
NDS_3D_ChangeCore(CORE3DLIST_NULL);
DestroyOpenGLRenderer();
}
- (void) setGpuStateFlags:(UInt32)flags
{
OSSpinLockLock(&spinlockGpuState);
gpuStateFlags = flags;
OSSpinLockUnlock(&spinlockGpuState);
[self setLayerMainGPU:((flags & GPUSTATE_MAIN_GPU_MASK) != 0)];
[self setLayerMainBG0:((flags & GPUSTATE_MAIN_BG0_MASK) != 0)];
[self setLayerMainBG1:((flags & GPUSTATE_MAIN_BG1_MASK) != 0)];
[self setLayerMainBG2:((flags & GPUSTATE_MAIN_BG2_MASK) != 0)];
[self setLayerMainBG3:((flags & GPUSTATE_MAIN_BG3_MASK) != 0)];
[self setLayerMainOBJ:((flags & GPUSTATE_MAIN_OBJ_MASK) != 0)];
[self setLayerSubGPU:((flags & GPUSTATE_SUB_GPU_MASK) != 0)];
[self setLayerSubBG0:((flags & GPUSTATE_SUB_BG0_MASK) != 0)];
[self setLayerSubBG1:((flags & GPUSTATE_SUB_BG1_MASK) != 0)];
[self setLayerSubBG2:((flags & GPUSTATE_SUB_BG2_MASK) != 0)];
[self setLayerSubBG3:((flags & GPUSTATE_SUB_BG3_MASK) != 0)];
[self setLayerSubOBJ:((flags & GPUSTATE_SUB_OBJ_MASK) != 0)];
}
- (UInt32) gpuStateFlags
{
OSSpinLockLock(&spinlockGpuState);
const UInt32 flags = gpuStateFlags;
OSSpinLockUnlock(&spinlockGpuState);
return flags;
}
- (void) setRender3DRenderingEngine:(NSInteger)methodID
{
pthread_rwlock_wrlock(self.rwlockProducer);
NDS_3D_ChangeCore(methodID);
pthread_rwlock_unlock(self.rwlockProducer);
}
- (NSInteger) render3DRenderingEngine
{
pthread_rwlock_rdlock(self.rwlockProducer);
const NSInteger methodID = (NSInteger)cur3DCore;
pthread_rwlock_unlock(self.rwlockProducer);
return methodID;
}
- (void) setRender3DHighPrecisionColorInterpolation:(BOOL)state
{
pthread_rwlock_wrlock(self.rwlockProducer);
CommonSettings.GFX3D_HighResolutionInterpolateColor = state ? true : false;
pthread_rwlock_unlock(self.rwlockProducer);
}
- (BOOL) render3DHighPrecisionColorInterpolation
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL state = CommonSettings.GFX3D_HighResolutionInterpolateColor ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return state;
}
- (void) setRender3DEdgeMarking:(BOOL)state
{
pthread_rwlock_wrlock(self.rwlockProducer);
CommonSettings.GFX3D_EdgeMark = state ? true : false;
pthread_rwlock_unlock(self.rwlockProducer);
}
- (BOOL) render3DEdgeMarking
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL state = CommonSettings.GFX3D_EdgeMark ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return state;
}
- (void) setRender3DFog:(BOOL)state
{
pthread_rwlock_wrlock(self.rwlockProducer);
CommonSettings.GFX3D_Fog = state ? true : false;
pthread_rwlock_unlock(self.rwlockProducer);
}
- (BOOL) render3DFog
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL state = CommonSettings.GFX3D_Fog ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return state;
}
- (void) setRender3DTextures:(BOOL)state
{
pthread_rwlock_wrlock(self.rwlockProducer);
CommonSettings.GFX3D_Texture = state ? true : false;
pthread_rwlock_unlock(self.rwlockProducer);
}
- (BOOL) render3DTextures
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL state = CommonSettings.GFX3D_Texture ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return state;
}
- (void) setRender3DDepthComparisonThreshold:(NSUInteger)threshold
{
pthread_rwlock_wrlock(self.rwlockProducer);
CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack = threshold;
pthread_rwlock_unlock(self.rwlockProducer);
}
- (NSUInteger) render3DDepthComparisonThreshold
{
pthread_rwlock_rdlock(self.rwlockProducer);
const NSUInteger threshold = (NSUInteger)CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack;
pthread_rwlock_unlock(self.rwlockProducer);
return threshold;
}
- (void) setRender3DThreads:(NSUInteger)numberThreads
{
NSUInteger numberCores = [[NSProcessInfo processInfo] activeProcessorCount];
if (numberThreads == 0)
{
isCPUCoreCountAuto = YES;
if (numberCores >= 8)
{
numberCores = 8;
}
else if (numberCores >= 4)
{
numberCores = 4;
}
else if (numberCores >= 2)
{
numberCores = 2;
}
else
{
numberCores = 1;
}
}
else
{
isCPUCoreCountAuto = NO;
numberCores = numberThreads;
}
const NSInteger renderingEngineID = [self render3DRenderingEngine];
pthread_rwlock_wrlock(self.rwlockProducer);
CommonSettings.num_cores = numberCores;
if (renderingEngineID == CORE3DLIST_SWRASTERIZE || renderingEngineID == CORE3DLIST_OPENGL)
{
NDS_3D_ChangeCore(renderingEngineID);
}
pthread_rwlock_unlock(self.rwlockProducer);
}
- (NSUInteger) render3DThreads
{
pthread_rwlock_rdlock(self.rwlockProducer);
const NSUInteger numberThreads = isCPUCoreCountAuto ? 0 : (NSUInteger)CommonSettings.num_cores;
pthread_rwlock_unlock(self.rwlockProducer);
return numberThreads;
}
- (void) setRender3DLineHack:(BOOL)state
{
pthread_rwlock_wrlock(self.rwlockProducer);
CommonSettings.GFX3D_LineHack = state ? true : false;
pthread_rwlock_unlock(self.rwlockProducer);
}
- (BOOL) render3DLineHack
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL state = CommonSettings.GFX3D_LineHack ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return state;
}
- (void) setRender3DMultisample:(BOOL)state
{
pthread_rwlock_wrlock(self.rwlockProducer);
CommonSettings.GFX3D_Renderer_Multisample = state ? true : false;
pthread_rwlock_unlock(self.rwlockProducer);
}
- (BOOL) render3DMultisample
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL state = CommonSettings.GFX3D_Renderer_Multisample ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return state;
}
- (void) setRender3DFragmentSamplingHack:(BOOL)state
{
pthread_rwlock_wrlock(self.rwlockProducer);
CommonSettings.GFX3D_TXTHack = state ? true : false;
pthread_rwlock_unlock(self.rwlockProducer);
}
- (BOOL) render3DFragmentSamplingHack
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL state = CommonSettings.GFX3D_TXTHack ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return state;
}
- (void) setLayerMainGPU:(BOOL)gpuState
{
pthread_rwlock_wrlock(self.rwlockProducer);
SetGPUDisplayState(DS_GPU_TYPE_MAIN, (gpuState) ? true : false);
pthread_rwlock_unlock(self.rwlockProducer);
OSSpinLockLock(&spinlockGpuState);
gpuStateFlags = (gpuState) ? (gpuStateFlags | GPUSTATE_MAIN_GPU_MASK) : (gpuStateFlags & ~GPUSTATE_MAIN_GPU_MASK);
OSSpinLockUnlock(&spinlockGpuState);
}
- (BOOL) layerMainGPU
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL gpuState = GetGPUDisplayState(DS_GPU_TYPE_MAIN) ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return gpuState;
}
- (void) setLayerMainBG0:(BOOL)layerState
{
pthread_rwlock_wrlock(self.rwlockProducer);
SetGPULayerState(DS_GPU_TYPE_MAIN, 0, (layerState) ? true : false);
pthread_rwlock_unlock(self.rwlockProducer);
OSSpinLockLock(&spinlockGpuState);
gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_MAIN_BG0_MASK) : (gpuStateFlags & ~GPUSTATE_MAIN_BG0_MASK);
OSSpinLockUnlock(&spinlockGpuState);
}
- (BOOL) layerMainBG0
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL layerState = GetGPULayerState(DS_GPU_TYPE_MAIN, 0) ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return layerState;
}
- (void) setLayerMainBG1:(BOOL)layerState
{
pthread_rwlock_wrlock(self.rwlockProducer);
SetGPULayerState(DS_GPU_TYPE_MAIN, 1, (layerState) ? true : false);
pthread_rwlock_unlock(self.rwlockProducer);
OSSpinLockLock(&spinlockGpuState);
gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_MAIN_BG1_MASK) : (gpuStateFlags & ~GPUSTATE_MAIN_BG1_MASK);
OSSpinLockUnlock(&spinlockGpuState);
}
- (BOOL) layerMainBG1
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL layerState = GetGPULayerState(DS_GPU_TYPE_MAIN, 1) ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return layerState;
}
- (void) setLayerMainBG2:(BOOL)layerState
{
pthread_rwlock_wrlock(self.rwlockProducer);
SetGPULayerState(DS_GPU_TYPE_MAIN, 2, (layerState) ? true : false);
pthread_rwlock_unlock(self.rwlockProducer);
OSSpinLockLock(&spinlockGpuState);
gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_MAIN_BG2_MASK) : (gpuStateFlags & ~GPUSTATE_MAIN_BG2_MASK);
OSSpinLockUnlock(&spinlockGpuState);
}
- (BOOL) layerMainBG2
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL layerState = GetGPULayerState(DS_GPU_TYPE_MAIN, 2) ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return layerState;
}
- (void) setLayerMainBG3:(BOOL)layerState
{
pthread_rwlock_wrlock(self.rwlockProducer);
SetGPULayerState(DS_GPU_TYPE_MAIN, 3, (layerState) ? true : false);
pthread_rwlock_unlock(self.rwlockProducer);
OSSpinLockLock(&spinlockGpuState);
gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_MAIN_BG3_MASK) : (gpuStateFlags & ~GPUSTATE_MAIN_BG3_MASK);
OSSpinLockUnlock(&spinlockGpuState);
}
- (BOOL) layerMainBG3
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL layerState = GetGPULayerState(DS_GPU_TYPE_MAIN, 3) ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return layerState;
}
- (void) setLayerMainOBJ:(BOOL)layerState
{
pthread_rwlock_wrlock(self.rwlockProducer);
SetGPULayerState(DS_GPU_TYPE_MAIN, 4, (layerState) ? true : false);
pthread_rwlock_unlock(self.rwlockProducer);
OSSpinLockLock(&spinlockGpuState);
gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_MAIN_OBJ_MASK) : (gpuStateFlags & ~GPUSTATE_MAIN_OBJ_MASK);
OSSpinLockUnlock(&spinlockGpuState);
}
- (BOOL) layerMainOBJ
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL layerState = GetGPULayerState(DS_GPU_TYPE_MAIN, 4) ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return layerState;
}
- (void) setLayerSubGPU:(BOOL)gpuState
{
pthread_rwlock_wrlock(self.rwlockProducer);
SetGPUDisplayState(DS_GPU_TYPE_SUB, (gpuState) ? true : false);
pthread_rwlock_unlock(self.rwlockProducer);
OSSpinLockLock(&spinlockGpuState);
gpuStateFlags = (gpuState) ? (gpuStateFlags | GPUSTATE_SUB_GPU_MASK) : (gpuStateFlags & ~GPUSTATE_SUB_GPU_MASK);
OSSpinLockUnlock(&spinlockGpuState);
}
- (BOOL) layerSubGPU
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL gpuState = GetGPUDisplayState(DS_GPU_TYPE_SUB) ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return gpuState;
}
- (void) setLayerSubBG0:(BOOL)layerState
{
pthread_rwlock_wrlock(self.rwlockProducer);
SetGPULayerState(DS_GPU_TYPE_SUB, 0, (layerState) ? true : false);
pthread_rwlock_unlock(self.rwlockProducer);
OSSpinLockLock(&spinlockGpuState);
gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_SUB_BG0_MASK) : (gpuStateFlags & ~GPUSTATE_SUB_BG0_MASK);
OSSpinLockUnlock(&spinlockGpuState);
}
- (BOOL) layerSubBG0
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL layerState = GetGPULayerState(DS_GPU_TYPE_SUB, 0) ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return layerState;
}
- (void) setLayerSubBG1:(BOOL)layerState
{
pthread_rwlock_wrlock(self.rwlockProducer);
SetGPULayerState(DS_GPU_TYPE_SUB, 1, (layerState) ? true : false);
pthread_rwlock_unlock(self.rwlockProducer);
OSSpinLockLock(&spinlockGpuState);
gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_SUB_BG1_MASK) : (gpuStateFlags & ~GPUSTATE_SUB_BG1_MASK);
OSSpinLockUnlock(&spinlockGpuState);
}
- (BOOL) layerSubBG1
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL layerState = GetGPULayerState(DS_GPU_TYPE_SUB, 1) ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return layerState;
}
- (void) setLayerSubBG2:(BOOL)layerState
{
pthread_rwlock_wrlock(self.rwlockProducer);
SetGPULayerState(DS_GPU_TYPE_SUB, 2, (layerState) ? true : false);
pthread_rwlock_unlock(self.rwlockProducer);
OSSpinLockLock(&spinlockGpuState);
gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_SUB_BG2_MASK) : (gpuStateFlags & ~GPUSTATE_SUB_BG2_MASK);
OSSpinLockUnlock(&spinlockGpuState);
}
- (BOOL) layerSubBG2
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL layerState = GetGPULayerState(DS_GPU_TYPE_SUB, 2) ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return layerState;
}
- (void) setLayerSubBG3:(BOOL)layerState
{
pthread_rwlock_wrlock(self.rwlockProducer);
SetGPULayerState(DS_GPU_TYPE_SUB, 3, (layerState) ? true : false);
pthread_rwlock_unlock(self.rwlockProducer);
OSSpinLockLock(&spinlockGpuState);
gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_SUB_BG3_MASK) : (gpuStateFlags & ~GPUSTATE_SUB_BG3_MASK);
OSSpinLockUnlock(&spinlockGpuState);
}
- (BOOL) layerSubBG3
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL layerState = GetGPULayerState(DS_GPU_TYPE_SUB, 3) ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return layerState;
}
- (void) setLayerSubOBJ:(BOOL)layerState
{
pthread_rwlock_wrlock(self.rwlockProducer);
SetGPULayerState(DS_GPU_TYPE_SUB, 4, (layerState) ? true : false);
pthread_rwlock_unlock(self.rwlockProducer);
OSSpinLockLock(&spinlockGpuState);
gpuStateFlags = (layerState) ? (gpuStateFlags | GPUSTATE_SUB_OBJ_MASK) : (gpuStateFlags & ~GPUSTATE_SUB_OBJ_MASK);
OSSpinLockUnlock(&spinlockGpuState);
}
- (BOOL) layerSubOBJ
{
pthread_rwlock_rdlock(self.rwlockProducer);
const BOOL layerState = GetGPULayerState(DS_GPU_TYPE_SUB, 4) ? YES : NO;
pthread_rwlock_unlock(self.rwlockProducer);
return layerState;
}
- (BOOL) gpuStateByBit:(const UInt32)stateBit
{
return ([self gpuStateFlags] & (1 << stateBit)) ? YES : NO;
}
- (BOOL) isGPUTypeDisplayed:(const NSInteger)theGpuType
{
BOOL result = NO;
const UInt32 flags = [self gpuStateFlags];
switch (theGpuType)
{
case DS_GPU_TYPE_MAIN:
if (flags & GPUSTATE_MAIN_GPU_MASK)
{
result = YES;
}
break;
case DS_GPU_TYPE_SUB:
if (flags & GPUSTATE_SUB_GPU_MASK)
{
result = YES;
}
break;
case DS_GPU_TYPE_MAIN_AND_SUB:
if (flags & (GPUSTATE_MAIN_GPU_MASK | GPUSTATE_SUB_GPU_MASK))
{
result = YES;
}
break;
default:
break;
}
return result;
}
- (void) hideGPUType:(const NSInteger)theGpuType
{
UInt32 flags = [self gpuStateFlags];
switch (theGpuType)
{
case DS_GPU_TYPE_MAIN:
flags &= ~GPUSTATE_MAIN_GPU_MASK;
break;
case DS_GPU_TYPE_SUB:
flags &= ~GPUSTATE_SUB_GPU_MASK;
break;
case DS_GPU_TYPE_MAIN_AND_SUB:
flags &= ~GPUSTATE_MAIN_GPU_MASK;
flags &= ~GPUSTATE_SUB_GPU_MASK;
break;
default:
break;
}
[self setGpuStateFlags:flags];
}
- (void) showGPUType:(const NSInteger)theGpuType
{
UInt32 flags = [self gpuStateFlags];
switch (theGpuType)
{
case DS_GPU_TYPE_MAIN:
flags |= GPUSTATE_MAIN_GPU_MASK;
break;
case DS_GPU_TYPE_SUB:
flags |= GPUSTATE_SUB_GPU_MASK;
break;
case DS_GPU_TYPE_MAIN_AND_SUB:
flags |= GPUSTATE_MAIN_GPU_MASK;
flags |= GPUSTATE_SUB_GPU_MASK;
break;
default:
break;
}
[self setGpuStateFlags:flags];
}
- (NSString *) render3DRenderingEngineString
{
NSString *theString = @"Uninitialized";
pthread_rwlock_rdlock(self.rwlockProducer);
if(gpu3D == NULL)
{
pthread_rwlock_unlock(self.rwlockProducer);
return theString;
}
const char *theName = gpu3D->name;
theString = [NSString stringWithCString:theName encoding:NSUTF8StringEncoding];
pthread_rwlock_unlock(self.rwlockProducer);
return theString;
}
@end
void SetGPULayerState(const int gpuType, const unsigned int i, const bool state)
{
GPU *theGpu = NULL;
// Check bounds on the layer index.
if(i > 4)
{
return;
}
switch (gpuType)
{
case DS_GPU_TYPE_SUB:
theGpu = SubScreen.gpu;
break;
case DS_GPU_TYPE_MAIN:
theGpu = MainScreen.gpu;
break;
case DS_GPU_TYPE_MAIN_AND_SUB:
SetGPULayerState(DS_GPU_TYPE_SUB, i, state); // Recursive call
theGpu = MainScreen.gpu;
break;
default:
break;
}
if (theGpu != NULL)
{
if (state)
{
GPU_addBack(theGpu, i);
}
else
{
GPU_remove(theGpu, i);
}
}
}
bool GetGPULayerState(const int gpuType, const unsigned int i)
{
bool theState = false;
// Check bounds on the layer index.
if(i > 4)
{
return theState;
}
switch (gpuType)
{
case DS_GPU_TYPE_SUB:
if (SubScreen.gpu != NULL)
{
theState = CommonSettings.dispLayers[SubScreen.gpu->core][i];
}
break;
case DS_GPU_TYPE_MAIN:
if (MainScreen.gpu != NULL)
{
theState = CommonSettings.dispLayers[MainScreen.gpu->core][i];
}
break;
case DS_GPU_TYPE_MAIN_AND_SUB:
if (SubScreen.gpu != NULL && MainScreen.gpu != NULL)
{
theState = (CommonSettings.dispLayers[SubScreen.gpu->core][i] && CommonSettings.dispLayers[MainScreen.gpu->core][i]);
}
break;
default:
break;
}
return theState;
}
void SetGPUDisplayState(const int gpuType, const bool state)
{
switch (gpuType)
{
case DS_GPU_TYPE_SUB:
CommonSettings.showGpu.sub = state;
break;
case DS_GPU_TYPE_MAIN:
CommonSettings.showGpu.main = state;
break;
case DS_GPU_TYPE_MAIN_AND_SUB:
CommonSettings.showGpu.sub = state;
CommonSettings.showGpu.main = state;
break;
default:
break;
}
}
bool GetGPUDisplayState(const int gpuType)
{
bool theState = false;
switch (gpuType)
{
case DS_GPU_TYPE_SUB:
theState = CommonSettings.showGpu.sub;
break;
case DS_GPU_TYPE_MAIN:
theState = CommonSettings.showGpu.main;
break;
case DS_GPU_TYPE_MAIN_AND_SUB:
theState = (CommonSettings.showGpu.sub && CommonSettings.showGpu.main);
break;
default:
break;
}
return theState;
}
void GPU_FillScreenWithBGRA5551(const uint16_t colorValue)
{
const size_t pixCount = sizeof(GPU_screen) / sizeof(uint16_t);
#ifdef __APPLE__
if (pixCount % 16 == 0)
{
const uint16_t colorValuePattern[] = {colorValue, colorValue, colorValue, colorValue, colorValue, colorValue, colorValue, colorValue};
memset_pattern16(GPU_screen, colorValuePattern, sizeof(GPU_screen));
}
else
#endif
{
for (size_t i = 0; i < pixCount; i++)
{
((uint16_t *)GPU_screen)[i] = colorValue;
}
}
}
CGLContextObj OSXOpenGLRendererContext = NULL;
CGLPBufferObj OSXOpenGLRendererPBuffer = NULL;
bool OSXOpenGLRendererInit()
{
static bool isContextAlreadyCreated = false;
if (!isContextAlreadyCreated)
{
isContextAlreadyCreated = CreateOpenGLRenderer();
}
return true;
}
bool OSXOpenGLRendererBegin()
{
CGLSetCurrentContext(OSXOpenGLRendererContext);
return true;
}
void OSXOpenGLRendererEnd()
{
}
bool CreateOpenGLRenderer()
{
bool result = false;
bool useContext_3_2 = false;
CGLPixelFormatObj cglPixFormat = NULL;
CGLContextObj newContext = NULL;
CGLPBufferObj newPBuffer = NULL;
GLint virtualScreenCount = 0;
CGLPixelFormatAttribute attrs[] = {
kCGLPFAColorSize, (CGLPixelFormatAttribute)24,
kCGLPFAAlphaSize, (CGLPixelFormatAttribute)8,
kCGLPFADepthSize, (CGLPixelFormatAttribute)24,
kCGLPFAStencilSize, (CGLPixelFormatAttribute)8,
kCGLPFAAccelerated,
(CGLPixelFormatAttribute)0, (CGLPixelFormatAttribute)0,
(CGLPixelFormatAttribute)0
};
#ifdef MAC_OS_X_VERSION_10_7
// If we can support a 3.2 Core Profile context, then request that in our
// pixel format attributes.
useContext_3_2 = IsOSXVersionSupported(10, 7, 0);
if (useContext_3_2)
{
attrs[9] = kCGLPFAOpenGLProfile;
attrs[10] = (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core;
}
#endif
CGLChoosePixelFormat(attrs, &cglPixFormat, &virtualScreenCount);
if (cglPixFormat == NULL)
{
// Remove the HW rendering requirement and try again. Note that this will
// result in SW rendering, which will cause a substantial speed hit.
attrs[8] = (CGLPixelFormatAttribute)0;
CGLChoosePixelFormat(attrs, &cglPixFormat, &virtualScreenCount);
if (cglPixFormat == NULL)
{
return result;
}
}
CGLCreateContext(cglPixFormat, NULL, &newContext);
CGLReleasePixelFormat(cglPixFormat);
// Create a PBuffer for legacy contexts since the availability of FBOs
// is not guaranteed.
if (!useContext_3_2)
{
CGLCreatePBuffer(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, GL_TEXTURE_2D, GL_RGBA, 0, &newPBuffer);
if (newPBuffer == NULL)
{
CGLReleaseContext(newContext);
return result;
}
else
{
GLint virtualScreenID = 0;
CGLGetVirtualScreen(newContext, &virtualScreenID);
CGLSetPBuffer(newContext, newPBuffer, 0, 0, virtualScreenID);
}
}
RequestOpenGLRenderer_3_2(useContext_3_2);
OSXOpenGLRendererContext = newContext;
OSXOpenGLRendererPBuffer = newPBuffer;
result = true;
return result;
}
void DestroyOpenGLRenderer()
{
if (OSXOpenGLRendererContext == NULL)
{
return;
}
CGLReleasePBuffer(OSXOpenGLRendererPBuffer);
CGLReleaseContext(OSXOpenGLRendererContext);
OSXOpenGLRendererContext = NULL;
OSXOpenGLRendererPBuffer = NULL;
}
void RequestOpenGLRenderer_3_2(bool request_3_2)
{
#ifdef OGLRENDER_3_2_H
if (request_3_2)
{
OGLLoadEntryPoints_3_2_Func = &OGLLoadEntryPoints_3_2;
OGLCreateRenderer_3_2_Func = &OGLCreateRenderer_3_2;
return;
}
#endif
OGLLoadEntryPoints_3_2_Func = NULL;
OGLCreateRenderer_3_2_Func = NULL;
}
void SetOpenGLRendererFunctions(bool (*initFunction)(),
bool (*beginOGLFunction)(),
void (*endOGLFunction)())
{
oglrender_init = initFunction;
oglrender_beginOpenGL = beginOGLFunction;
oglrender_endOpenGL = endOGLFunction;
}
+172
View File
@@ -0,0 +1,172 @@
/*
Copyright (C) 2011 Roger Manuel
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/>.
*/
#import <Cocoa/Cocoa.h>
#undef BOOL
class CHEATS;
class CHEATS_LIST;
class CHEATSEARCH;
/********************************************************************************************
CocoaDSCheatItem - OBJECTIVE-C CLASS
This is an Objective-C wrapper class for DeSmuME's cheat item struct.
The cheat item data is not freed upon release of this object. This is by design.
Thread Safety:
Assume that all methods are not thread-safe. This was done for performance
reasons. The caller of this class' methods is expected to handle thread safety.
********************************************************************************************/
@interface CocoaDSCheatItem : NSObject
{
CHEATS_LIST *data;
CHEATS_LIST *internalData;
BOOL willAdd;
pthread_mutex_t mutexData;
CocoaDSCheatItem *workingCopy;
CocoaDSCheatItem *__weak parent;
}
@property (assign) CHEATS_LIST *data;
@property (assign) BOOL willAdd;
@property (assign, nonatomic) BOOL enabled;
@property (assign, nonatomic) NSInteger cheatType;
@property (strong, nonatomic) NSImage *cheatTypeIcon;
@property (assign, nonatomic) BOOL isSupportedCheatType;
@property (assign, nonatomic) NSInteger freezeType;
@property (copy, nonatomic) NSString *description;
@property (assign, nonatomic) NSUInteger codeCount;
@property (copy, nonatomic) NSString *code;
@property (assign, nonatomic) UInt8 bytes;
@property (assign, nonatomic) UInt32 memAddress;
@property (copy, nonatomic) NSString *memAddressString;
@property (copy, nonatomic) NSString *memAddressSixDigitString;
@property (assign, nonatomic) SInt64 value;
@property (readonly, strong) CocoaDSCheatItem *workingCopy;
@property (weak) CocoaDSCheatItem *parent;
- (id) initWithCheatData:(CHEATS_LIST *)cheatData;
- (BOOL) retainData;
@property (readonly) char *descriptionCString NS_RETURNS_INNER_POINTER;
- (void) update;
- (CocoaDSCheatItem *) createWorkingCopy;
- (void) destroyWorkingCopy;
- (void) mergeFromWorkingCopy;
- (void) mergeToParent;
- (void) setDataWithDictionary:(NSDictionary *)dataDict;
- (NSDictionary *) dataDictionary;
@property (class, strong) NSImage *iconInternalCheat;
@property (class, strong) NSImage *iconActionReplay;
@property (class, strong) NSImage *iconCodeBreaker;
@end
/********************************************************************************************
CocoaDSCheatManager - OBJECTIVE-C CLASS
This is an Objective-C wrapper class for DeSmuME's cheat list class.
Thread Safety:
All methods are thread-safe.
********************************************************************************************/
@interface CocoaDSCheatManager : NSObject
{
CHEATS *listData;
NSMutableArray *list;
pthread_rwlock_t *rwlockCoreExecute;
BOOL isUsingDummyRWlock;
NSUInteger untitledCount;
NSString *dbTitle;
NSString *dbDate;
}
@property (readonly) CHEATS *listData;
@property (readonly, strong) NSMutableArray *list;
@property (assign) pthread_rwlock_t *rwlockCoreExecute;
@property (assign) NSUInteger untitledCount;
@property (copy) NSString *dbTitle;
@property (copy) NSString *dbDate;
- (id) initWithFileURL:(NSURL *)fileURL;
- (id) initWithListData:(CHEATS *)cheatList;
- (id) initWithFileURL:(NSURL *)fileURL listData:(CHEATS *)cheatList;
- (BOOL) add:(CocoaDSCheatItem *)cheatItem;
- (void) remove:(CocoaDSCheatItem *)cheatItem;
- (BOOL) update:(CocoaDSCheatItem *)cheatItem;
- (BOOL) save;
- (NSUInteger) activeCount;
- (NSMutableArray *) cheatListFromDatabase:(NSURL *)fileURL errorCode:(NSInteger *)error;
- (void) applyInternalCheat:(CocoaDSCheatItem *)cheatItem;
+ (void) setMasterCheatList:(CocoaDSCheatManager *)cheatListManager;
+ (void) applyInternalCheatWithItem:(CocoaDSCheatItem *)cheatItem;
+ (void) applyInternalCheatWithAddress:(UInt32)address value:(UInt32)value bytes:(NSUInteger)bytes;
+ (NSMutableArray *) cheatListWithListObject:(CHEATS *)cheatList;
+ (NSMutableArray *) cheatListWithItemStructArray:(CHEATS_LIST *)cheatItemArray count:(NSUInteger)itemCount;
+ (NSMutableDictionary *) cheatItemWithType:(NSInteger)cheatTypeID description:(NSString *)description;
@end
@interface CocoaDSCheatSearch : NSObject
{
CHEATSEARCH *listData;
NSMutableArray *addressList;
pthread_rwlock_t *rwlockCoreExecute;
BOOL isUsingDummyRWlock;
NSUInteger searchCount;
}
@property (readonly) CHEATSEARCH *listData;
@property (readonly, strong) NSMutableArray<NSDictionary<NSString*,id>*> *addressList;
@property (assign) pthread_rwlock_t *rwlockCoreExecute;
@property (readonly) NSUInteger searchCount;
- (NSUInteger) runExactValueSearch:(NSInteger)value byteSize:(UInt8)byteSize signType:(NSInteger)signType;
- (void) runExactValueSearchOnThread:(id)object;
- (NSUInteger) runComparativeSearch:(NSInteger)typeID byteSize:(UInt8)byteSize signType:(NSInteger)signType;
- (void) runComparativeSearchOnThread:(id)object;
- (void) reset;
+ (NSMutableArray<NSDictionary<NSString*,id>*> *) addressListWithListObject:(CHEATSEARCH *)addressList maxItems:(NSUInteger)maxItemCount;
@end
@interface CocoaDSCheatSearchParams : NSObject
{
NSInteger comparativeSearchType;
NSInteger value;
UInt8 byteSize;
NSInteger signType;
}
@property (assign) NSInteger comparativeSearchType;
@property (assign) NSInteger value;
@property (assign) UInt8 byteSize;
@property (assign) NSInteger signType;
@end
+1342
View File
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More