Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ef91ce464c | |||
| 0ba54f14d3 | |||
| 0a330b490f | |||
| 65e0083de0 | |||
| 6237b9f50e | |||
| ba04dbb4ef |
@@ -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.
|
||||
@@ -0,0 +1,551 @@
|
||||
Version 0.5.1
|
||||
-------------
|
||||
- Build improvements
|
||||
- Increase standards compliance and code quality
|
||||
- Add the SoX Resampler for higher quality (but higher CPU usage) resampling
|
||||
- Add SameBoy's "Modern - Accurate" colour correction
|
||||
|
||||
Version 0.5.0
|
||||
-------------
|
||||
- Initial tagged release after fork from final public revision of Gambatte
|
||||
- Stricter build flags
|
||||
- Removal of stale, bitrotten code
|
||||
- Rearrange and simplify codebase layout
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- 0.4.1 -- 2009-01-10
|
||||
libgambatte:
|
||||
- Fix HqXx filter pitch.
|
||||
- Fix mbc2 not getting a rambank.
|
||||
- Make sure to reset passed pointers when deleted. Fixes potential crash
|
||||
when loading ROM during OAM busy.
|
||||
common:
|
||||
- Substantially improved rate estimation averaging.
|
||||
- RateEst: Add a convenient way of filtering measures that extend beyond
|
||||
a buffer time, and are as such probably invalid.
|
||||
- RateEst: Allow using a custom timestamp in feed().
|
||||
- RateEst: Keep a queue of the last ~100 msec worth of samples and
|
||||
duration, and filter out collective samples that give a pre-estimate
|
||||
that seems way off.
|
||||
- Replace "Game Boy / Game Boy Color emulator" with "Game Boy Color
|
||||
emulator" for now to avoid misleading anyone on the current status.
|
||||
gambatte_qt:
|
||||
- Disable BlitterWidget updates (paintEvents) while not paused.
|
||||
- QGLBlitter: Do a cheap front blit rather than a vsynced flip if audio
|
||||
buffers are low.
|
||||
- Allow BlitterWidgets to opt in to get paintEvents while unpaused. Do so
|
||||
for QGLBlitter since it may need to clear buffers afterwards.
|
||||
- QGLBlitter: Try to blit right after sync in the case of single buffering.
|
||||
- Up default audio buffer latency to 100 ms (some common system audio
|
||||
servers require a lot of buffering to work well).
|
||||
- Adaptively skip BlitterWidget syncs if audio buffer is low, in a manner
|
||||
that should minimize wasted skips in sync to vblank situation, and tries
|
||||
to be non-disturbing. This replaces frame time halving, and blitter
|
||||
specific rescueing.
|
||||
- Clear display buffers in DirectDrawBlitter and Direct3DBlitter in
|
||||
exclusive mode, since blits don't necessarily cover the entire buffers.
|
||||
- DirectDrawBlitter: Make sure that a minimum amount of time has passed
|
||||
between calls to WaitForVerticalBlank, since it can return in the same
|
||||
vblank period twice on a fast system.
|
||||
- DirectDrawBlitter: Support vsync for refresh rate ~= 2x frame rate.
|
||||
- DirectDrawBlitter: Refactor somewhat and get rid of a couple minor
|
||||
potential bugs.
|
||||
- DirectDrawBlitter: Some tweaks to get updates closer to sync time in
|
||||
certain situations.
|
||||
- DirectDrawBlitter: Some tweaks to better support DONOTWAIT.
|
||||
- DirectDrawBlitter: Make only updating during vblank while page flipping
|
||||
optional.
|
||||
- Direct3DBlitter: Some tweaks to get updates closer to sync time in
|
||||
certain situations.
|
||||
- Filter out very short frame times in frame time estimation.
|
||||
- Don't adjust frame time during turbo, but rather skip BlitterWidget
|
||||
syncs to speed up, which avoids vsync limits without disabling vsync.
|
||||
- DirectDrawBlitter: Add triple buffering option.
|
||||
- Direct3DBlitter: Use D3DSWAPEFFECT_DISCARD in non-exclusive mode.
|
||||
- Direct3DBlitter: Allow triple buffering and vblank-only updates in
|
||||
non-excusive mode.
|
||||
- Rename "Page flipping" in Direct3D and DirectDraw blitters to
|
||||
"Exclusive full screen".
|
||||
- Pause audio on win32 titlebar clicks/drags to avoid looping audio due to
|
||||
underruns from blocked timerEvents.
|
||||
- Use wildcards for platform detection to avoid being unnecessarily
|
||||
compiler/architecture specific. Fixes bug 2377772.
|
||||
- Rewrite most of DirectSoundEngine, supporting primary buffer option,
|
||||
making it more robust, correct and hopefully cleaner. Only use part of
|
||||
the primary buffer if the desired buffer size is lower than the
|
||||
primary buffer size.
|
||||
- Direct3DBlitter and DirectDrawBlitter: Force blocking updates when sync
|
||||
to vblank is enabled. Some updates only block if there's a prior
|
||||
unfinished update in progress. This screws up frame time estimation in
|
||||
turn screwing up vsync. To fix this we do a double update (and extra blit)
|
||||
if close to a frame time period has passed since the last update when
|
||||
sync to vblank is enabled. I really should have noticed this earlier as
|
||||
it pretty much breaks vsync adaption completely.
|
||||
- Direct3DBlitter: Use the D3DCREATE_FPU_PRESERVE flag when creating
|
||||
device. Omitting this flag can screw up floating point calculations in
|
||||
other parts of the code. For instance WASAPI cursor timestamps get
|
||||
utterly screwed up here.
|
||||
- Direct3DBlitter: It appears that managed textures are updated before
|
||||
they are unlocked, which screws up redraws, making things appear choppy
|
||||
in some situations. Use a default memory texture and a system memory
|
||||
texture and the UpdateTexure method instead.
|
||||
- DirectSoundEngine: Make use of the sample period limit feature of
|
||||
RateEst, rather than duplicating the feature.
|
||||
- Add polling WASAPI engine with exclusive mode support. Latency and rate
|
||||
estimation is generally better than DirectSound, and in exclusive mode
|
||||
there is less blocking as well as exclusive mode being better than
|
||||
shared mode in the other areas too.
|
||||
- WasapiEngine: Add device selection.
|
||||
- WasapiEngine: Add static isUsable() method. Only listed if isUsable().
|
||||
Default engine if isUsable().
|
||||
- WasapiEngine: Use default device if there's only one device available,
|
||||
since we don't show the combobox anyway.
|
||||
- DirectSoundEngine: Provide the integrated read and status get write
|
||||
method optimization.
|
||||
- XvBlitter: Set NosystemBackground attribute rather than OpaquePaintEvent.
|
||||
Reimplement paintEngine to return NULL as suggested by Qt docs.
|
||||
- X11Blitter: Reimplement paintEngine to return NULL.
|
||||
- AlsaEngine: Make use of sample period limit feature of RateEst. Don't
|
||||
increase estimated sample rate on underrun.
|
||||
- OssEngine: Make use of sample period limit feature of RateEst. Don't
|
||||
increase estimated sample rate on underrun.
|
||||
- Esc exits fullscreen on macx.
|
||||
- Drop OpenAL from default macx binary.
|
||||
- Add some useful but commented build flags for macx to .pro files.
|
||||
|
||||
-- 0.4.0 -- 2008-10-27
|
||||
libgambatte:
|
||||
- less fixed-width type dependencies. don't assume unsigned int > 16 bits
|
||||
- slightly faster sprite mapping
|
||||
- Skip potential high frequency events when they don't matter.
|
||||
- do sprite sorting and cycle calculations pr line as needed instead of all
|
||||
at once
|
||||
- fix broken volume on/off event notification
|
||||
- less int > 16-bits assumptions
|
||||
- more type width dependency fixes
|
||||
- int width deps. Gambatte namespace
|
||||
- wx affects sprite m3 cycles
|
||||
- cache m3 cycles, related refactoring
|
||||
- readjust cgb dma cycles to previously changed m3 timing
|
||||
- clean up goofy lyc calculation.
|
||||
- cgb dma from various areas results in 0xFF being written.
|
||||
- 0xFEA0-0xFEFF not writable when OAM isn't
|
||||
- unusable ioram bits fixes
|
||||
- dmg ioram startup state fixes.
|
||||
- various oamdma accuracy
|
||||
- oamdma bus conflicts with cpu, ppu, cgbdma.
|
||||
- rewritten memory read/write methods.
|
||||
- accurate timing of ppu sprite mapping reads.
|
||||
- fix recent cgb sprite cycles sorting slip up.
|
||||
- preoffset mem pointers.
|
||||
- get rid of unused memory.
|
||||
- save state infrastructure,
|
||||
- clean up video timing code,
|
||||
- use save state for initialization and reset,
|
||||
- do color conversion outside filters
|
||||
- fast rgb32ToUyvy,
|
||||
- add overlooked oamdma event,
|
||||
- adjust subcycle irq timing (shouldn't affect anything),
|
||||
- various refactoring
|
||||
- save savedata before loading state
|
||||
- fix silly initstate ifreg regression
|
||||
- save state selection
|
||||
- save state osd preview snapshots
|
||||
- fix a few potential security holes when loading invalid state
|
||||
- get rid of some undefined behaviour in statesaver
|
||||
- always draw in rgb32, color convert afterwards, too bad for maemo/16-bit
|
||||
depth users
|
||||
- get rid of silly c string stuff
|
||||
- add bitmap font rendering with font based on Bitstream Vera Sans
|
||||
- osd state n saved/loaded text
|
||||
- empty state osd thumbs marked with "Empty" text
|
||||
- adjust thumbnail interpolation weighing slightly
|
||||
- utilize templates for more flexible osd text printing
|
||||
- use grey osd text with black outline for save/load state messages
|
||||
- move state 0 OSD pos to rightmost to match kbd layout
|
||||
- state 1 default on ROM load
|
||||
- support external save state files
|
||||
- missing includes
|
||||
- missing virtual destructor
|
||||
- std::ifstream construction missing binary flag
|
||||
- fix gcc-4.3 compilation
|
||||
- avoid signed overflow in constant (which is both undefined and likely
|
||||
to cause problems on architectures where sizeof(long) != sizeof(int)) in
|
||||
rgb2yuv code.
|
||||
- Fix wrong pitch passed to filter if color conversion is needed.
|
||||
- Fix potential problem with rgb32ToUyvy cache init values on 16-bit systems
|
||||
- Correct unhalttime when resetting counters. Fixes perodic infinite halt
|
||||
issue in Kirby's Star Stacker and probably other games.
|
||||
- Fix LY display disable regression
|
||||
- Use deltas and a running sum to decrease buffer writes in sound emulation
|
||||
sample generation.
|
||||
- Rearrange sound emulation event loop to optimize for high-frequency event
|
||||
units.
|
||||
- Initialize palette arrays to avoid valgrind noise.
|
||||
- Don't do resampling in libgambatte. Update API to reflect this.
|
||||
- No rambanks for ROMs that don't request any.
|
||||
- Route invalid rombank addresses in non-power-of-2 number of rombanks
|
||||
cases to disabled area assuming ceiled power of 2 address bus.
|
||||
- no sprites or sprite mapping busy cycles on first line after display
|
||||
enable. slight cleanup.
|
||||
- small oam accessibility correction.
|
||||
- Tile loading and tile rendering can seemingly get out of sync when
|
||||
modifying scx at a critical time. Another pessimation with little gain in
|
||||
the name of accuracy.
|
||||
- Use a look-up table to do tile byte merging.
|
||||
- Append "_dmg" to save base name when forcing DMG mode, to avoid
|
||||
corrupting CGB save files and vice versa.
|
||||
- saner ly write behaviour
|
||||
- Add adapted and optimized hq3x.
|
||||
- Revert to big f'ing switch hq2x code, as there's less duplication now.
|
||||
Also optimized interpolation functions further. No idea how I missed that
|
||||
initially.
|
||||
- Lower opacity OSD text.
|
||||
gambatte_sdl:
|
||||
- less retarded indenting
|
||||
- saner placement of fill_buffer function
|
||||
- int width deps. Gambatte namespace
|
||||
- Scalebuffer dstpitch aware.
|
||||
- save state selection
|
||||
- add number key slot selection shortcuts
|
||||
- Estimate actual output sample rate in terms of OS timers
|
||||
and derive frame rate from it.
|
||||
- Move AudioData and RingBuffer classes to separate files.
|
||||
- Make underruns slightly less painful, by resetting buffer
|
||||
positions.
|
||||
- Skip resampling when fast-forwarding
|
||||
- Fill available buffer space before waiting for more.
|
||||
- Audio buffer command line options.
|
||||
- Use half video frame sleep time if audio buffer is close to underrun.
|
||||
- Adjust estimated frame time each frame.
|
||||
gambatte_qt:
|
||||
- more likely to build on mac os x
|
||||
- Fix fixed window size issues with various window managers (metacity,
|
||||
xfwm4...)
|
||||
- macx build fixes
|
||||
- hopefully fix opengl clearing issues
|
||||
- Gambatte namespace
|
||||
- Decouple Qt GUI from gambatte.
|
||||
- Lots of cleanups, flexibility added
|
||||
- setting of various properties, frame time, aspect ratio, button events,
|
||||
video sources, sample rates, pauseOnDialogExec, custom menus etc.
|
||||
- Document some interfaces.
|
||||
- Support for setting approximate sound buffer latency.
|
||||
- Use rational math for 100% exact timers (even though the actual system
|
||||
timers are unlikely to be accurate).
|
||||
- Add fast-forward to input settings.
|
||||
- timeGetTime() fallback for win32
|
||||
- Store full screen mode values/text rather than less reliable indexes.
|
||||
- Repaint on xvblitter port changes to avoid color key not getting
|
||||
repainted.
|
||||
- improved ALSA buffer reporting
|
||||
- add sampleRate info to MediaSource::setSampleBuffer.
|
||||
- clarify that "samples" refers to stereo samples
|
||||
- fix 24-bit depth non-shm ximage creation
|
||||
- fix blittercontainer incorrectly using minimumSize for integer scaling
|
||||
- add unrestricted fast bilinear and nearest neighbor sw scaling to
|
||||
x11/qpainter blitter
|
||||
- swscale: remove forgotten static qualifiers
|
||||
- swscale: center linear weighing bias
|
||||
- swscale: exclude iostream
|
||||
- swscale: less bloated
|
||||
- macx fixed/variable window size change issue fixed
|
||||
- macx opengl drawbuffer change issues worked around
|
||||
- add openal engine, default on macx
|
||||
- add macx quartz video mode toggler
|
||||
- multi-head infrastructure
|
||||
- support multiple monitors in macx quartz toggler
|
||||
- more work-arounds for Qt failing to set correct geometry on video mode
|
||||
changes.
|
||||
- more explicit fast-forward button handling, to avoid missed key
|
||||
press/release events on macx
|
||||
- opengl doublebuffer preblitting, try to make actual screen updates as
|
||||
close to right after sync wait is over as possible
|
||||
- add xf86vidmode toggler (xrandrtoggler is default)
|
||||
- x11blitter: check for other supported visuals if the default is
|
||||
unsupported.
|
||||
- temporarily return to original video mode and minimize on full screen
|
||||
alt-tab (except on macx or if there are multiple screens), switch back on
|
||||
focus-in
|
||||
- hide mouse cursor after move timeout, or key/joystick pressed (more sane
|
||||
on macx)
|
||||
- exit fullscreen rather than toggle menubar on macx (note that the menubar
|
||||
will automatically pop-up on macx full screen if the mouse is moved to
|
||||
the top of the primary screen)
|
||||
- add (independent) pause counter for non-client pauses.
|
||||
- reset X11 screen saver on joystick activity
|
||||
- change "turbo"-mode to temporarily set frametime as a way of avoiding
|
||||
vsync issues (for a laugh, check out the video dialog while in
|
||||
fast-forward mode and see "Sync to vertical blank in 65535 and 131070 Hz
|
||||
modes").
|
||||
- fix win32 compilation
|
||||
- refix win32 fullscreen geometry correction
|
||||
- neater win32 BlitterWidget::sync
|
||||
- avoid misleading minimize on fullscreen close
|
||||
- refactor Blitterwidget::sync
|
||||
- directdrawblitter: remove unecessary turbo conditions
|
||||
- gditoggler: add multi-monitor support (win32)
|
||||
- videodialog: save actual hz values for real this time
|
||||
- quartztoggler: avoid potentially reverting to the wrong mode on double
|
||||
setFullMode(false) in multi-head configs
|
||||
- make sure window is within screen after mode change, so Qt doesn't reset
|
||||
it to the primary screen
|
||||
- revert to previous win32 fullscreen geometry correction behaviour so that
|
||||
the geometry gets properly reset after fullscreen
|
||||
- Add directdraw device selection.
|
||||
- directsoundengine: add device selection.
|
||||
- directdrawblitter: only list devices if there are more than 2 devices
|
||||
(including primary)
|
||||
- directdrawblitter: use private static member rather than global friend
|
||||
enumeration callback
|
||||
- capitalization changes
|
||||
- add direct3d9 blitter with support for vsync, bf, page flipping, triple
|
||||
buffering, device selection, multi-head etc. d3d9.dll loaded at runtime
|
||||
- more strict and thorough exclusive mode handling to support d3d fullscreen
|
||||
- work around file open dialog not returning focus properly
|
||||
- gditoggler: use current registry settings for return modes
|
||||
- directsoundengine: set DSBCAPS_GETCURRENTPOSITION2 flag
|
||||
- revert bad macx return from fullscreen on menu-toggle
|
||||
- don't build xf86vidmodetoggler by default
|
||||
- add save state actions to GUI menu
|
||||
- clean up GUI menu creation code
|
||||
- move GUI recent files to submenu
|
||||
- support external save state files
|
||||
- add number key slot selection shortcuts
|
||||
- missing includes
|
||||
- missing virtual destructor
|
||||
- make sure windows path arguments don't use backslashes by using QFileInfo
|
||||
- add Play menu with Pause, Frame Step, Dec/Inc/Reset Frame Rate
|
||||
- Add tab support to input settings dialog.
|
||||
- Add alternate key support to input settings dialog.
|
||||
- Auto-focus to next likely input box after settings key in input dialog.
|
||||
- Add "Play" and "State" input settings dialog tabs.
|
||||
- Avoid using the most convenient keys as forced menu short-cuts, set them
|
||||
as default keys in input settings dialog instead. This unfortunately
|
||||
makes the more useful shortcuts less visible, but it allows remapping
|
||||
the most convenient keyboard keys.
|
||||
- Avoid duplicate joystick axis "press" events by keeping a map of axis
|
||||
states.
|
||||
- Make sure to discard irrelevant/old joystick events.
|
||||
- Don't give MediaSource button events when stopped.
|
||||
- Allow joystick-based button events while paused by using a very
|
||||
low-frequency poll timer.
|
||||
- Make some of the joystick event wrapping stuff less messy.
|
||||
- missing string include
|
||||
- use QString for videoSourceLabel passed to MainWindow constructor
|
||||
- store currently selected scheme as string, since it appears ModelIndex
|
||||
is neither tied to the data it points to nor invalidated by changes.
|
||||
enforce valid state on reject since the list of schemes may have
|
||||
changed.
|
||||
- Direct3DCreate function pointer typedef needs WINAPI macro
|
||||
- disable page flipping dependent checkboxes in constructor to ensure
|
||||
correct start state
|
||||
- add custom sample rate support
|
||||
- change default buffer latency to 67 ms
|
||||
- don't auto-repeat buttons bound to keyboard
|
||||
- use enums for somewhat more robust gambattesource button setup
|
||||
- fix silly "alsa not using default device by default" bug
|
||||
- Only ask for xrandr config once to avoid potential server roundtrips in
|
||||
some xrandr versions.
|
||||
- Make sure xrandr version is >= 1.1 and < 2
|
||||
- Prevent all text editing of input boxes.
|
||||
- Add custom context menu to input boxes.
|
||||
- Update AudioEngine to support sample rate estimation in terms of OS
|
||||
timers.
|
||||
- Implement sample rate estimation in ALSA and OSS audio engines.
|
||||
- AlsaEngine: Revert to using snd_pcm_avail_update for buffer status since
|
||||
snd_pcm_delay may consider external latencies.
|
||||
- AlsaEngine: Use snd_pcm_hw_params_set_buffer_time_near. Don't request a
|
||||
particular number of periods per buffer.
|
||||
- AlsaEngine: Use hw as default custom device string, rather than hw:0,0.
|
||||
- OssEngine: Don't trust GETOSPACE fragment info.
|
||||
- Estimate optimal frame rate based on sample rate estimations.
|
||||
- Extend BlitterWidget to support estimation of vsynced frame rate in terms
|
||||
of OS timers.
|
||||
- Implement vsync frame rate estimation in QGlBlitter, Direct3DBlitter and
|
||||
DirectDrawBlitter.
|
||||
- Use a combination of OS timer sample rate estimation and vsync frame rate
|
||||
estimation to derive resampling ratio for no-frame-duplication vsync.
|
||||
- Change API to reflect MediaSources not being responsible for resampling.
|
||||
- Make sure to parent PaletteDialog list model, so it gets deleted properly.
|
||||
- Various refactoring, small changes and stuff I forgot.
|
||||
- limit vsync frame rate estimation deviation
|
||||
- More averaging in estimation code.
|
||||
- Stricter estimate deviation limit
|
||||
- Adjust estimated frame time each frame.
|
||||
- Use half frame time if audio buffer is close to underrun.
|
||||
- Provide combined audioengine write and status get, to avoid doing
|
||||
potentially expensive operations twice. Utilized in OSS and ALSA engines.
|
||||
- Saner vsync estimate variance protection.
|
||||
- allow dynamically setting samples per frame
|
||||
- Don't bother allowing sources the choice of which output sample rates are
|
||||
selecrable, as it's not really a per source thing at this point. If
|
||||
resampling avoidance is desired, then that should rather be a user option
|
||||
(to depend on the OS for resampling, which is mostly nonsensical for the
|
||||
Game Boy/NES/PSG-system case btw).
|
||||
- Move Qt media framework to a separate subdir
|
||||
- postpone buffered x11 blits to after sync.
|
||||
- Add support for XRandR 1.2 + multi-head
|
||||
- use crtc mode dimensions rather than crtc dimensions when discarding
|
||||
modes since crtc dimensions may be rotated
|
||||
- Fractional bits for intermediate rate estimation averages.
|
||||
- Add RateEst reset method. Initialize RateEst count to 1.
|
||||
- Less refresh rate estimation averaging.
|
||||
- Allow more refresh rate estimation deviation.
|
||||
- Return NULL paintEngine in windows blitters that use the PaintToScreen
|
||||
attribute.
|
||||
- Add checks for things not being initialized in DirectDraw-blitter and
|
||||
QPainterBlitter paintEvents.
|
||||
- Don't reparent blitters (mainly to make a bug in Qt 4.4.3 win less
|
||||
annoying, widgets that do internal reparenting are still affected).
|
||||
- Check for window position less than screen top-left after mode change,
|
||||
before full screen, to avoid Qt moving it to the primary screen.
|
||||
- Add rate estimation to DirectSound engine.
|
||||
- Better underrun detection in DirectSound engine.
|
||||
- Don't duplicate blitter pointer in mainwindow.
|
||||
- Use RateEst.reset rather than re-initing on pause.
|
||||
- Add CoreAudio engine with rate estimation and buffer status support.
|
||||
Default engine on Mac OS X.
|
||||
- 44100 Hz default sample rate on OS X, since OS X tends to resample
|
||||
everything to 44100 Hz.
|
||||
- Get rid of buffer status averaging in OpenAlEngine, since it makes
|
||||
assumptions on usage pattern that shouldn't be made.
|
||||
- Fix CoreAudio engine reporting buffer status in samples rather than
|
||||
frames.
|
||||
- Update SDL_Joystick to SDL-1.2 SVN.
|
||||
- #undef UNICODE in win32/SDL_mmjoystick.c to avoid joystick name mangling.
|
||||
- work around annoying random non-updating OpenGL on Mac OS X after full
|
||||
screen.
|
||||
common/other:
|
||||
- Fix GCC 4.3 warnings about people getting confused by operator precedence
|
||||
by adding parentheses.
|
||||
- Real-time, sophisticated resampling framework with several
|
||||
performance/quality profiles for dynamically generated windowed sinc and
|
||||
CIC chains based on analysis of fourier transforms and optimal cost
|
||||
equations. Fast 2-tap linear as a low quality alternative.
|
||||
- Move non-emulation common code to a common directory to avoid duplication.
|
||||
- Update front-ends to new libgambatte API.
|
||||
- Utilize resampling framework in front-ends. Selectable resamplers.
|
||||
- Improved adaptive sleep class that estimates oversleep.
|
||||
- Various refactoring, small changes and stuff I forgot.
|
||||
- Do per phase normalization to avoid dc fluctuations.
|
||||
- More averaging in estimation code.
|
||||
- Stricter estimate deviation limit
|
||||
- Fractional bits for intermediate rate estimation averages.
|
||||
- Add RateEst reset method. Initialize RateEst count to 1.
|
||||
- Extend ringbuffer.h to support resetting size, and move it to common dir
|
||||
since gambatte_qt/coreaudioengine uses it too now.
|
||||
- Add "force DMG mode" option.
|
||||
- Allow more rate estimation deviation.
|
||||
hwtests:
|
||||
- wx affects sprite m3 cycles.
|
||||
- cgb dma from various areas results in 0xFF being written.
|
||||
- add hwtests for oam dma
|
||||
- m3 cycles wo bg
|
||||
- more oamdma tests
|
||||
- various oamdma accuracy. oamdma bus conflicts with cpu, ppu, cgbdma.
|
||||
- accurate timing of ppu sprite mapping reads.
|
||||
|
||||
-- 0.3.1 -- 2007-10-26 --
|
||||
gambatte_qt:
|
||||
- Enable Joystick POV-Hat events.
|
||||
|
||||
-- 0.3.0 -- 2007-10-26 --
|
||||
libgambatte:
|
||||
- Fix adc/sbc and add_hl_rr hfc calc, sp_plus_n cf/hcf calc and daa thanks
|
||||
to blargg.
|
||||
- document HF2 better
|
||||
- Update sound core according to blargg's findings.
|
||||
- Improve resampling quality and performance.
|
||||
- Fix overlooked "add hl,sp" flag calculation.
|
||||
- fix initial endtime value
|
||||
- check for resampling ratio < 1
|
||||
- Add support for DMG palette customization.
|
||||
gambatte_sdl:
|
||||
- use std::map for parser
|
||||
- Don't bother hashing.
|
||||
- Add input config support.
|
||||
- Add joystick support.
|
||||
- Fix horrid "turbo can affect emulation" bug.
|
||||
- Add sw and yuv overlay scaling.
|
||||
- Use cond/mutex for thread syncing, RAII, refactor.
|
||||
- add option for sample rate choice
|
||||
- Add option to list valid input keys
|
||||
- don't die if audio fails
|
||||
gambatte_qt:
|
||||
- no point in filter being non-static anymore
|
||||
- use std::map for input vectors
|
||||
- remove unused unusedBool
|
||||
- Fix horrid "turbo can affect emulation" bug.
|
||||
- remove some useless optimizations
|
||||
- auto_ptr love.
|
||||
- support joystick hat.
|
||||
- nicer input handling.
|
||||
- Add sound dialog.
|
||||
- Add custom dev choice for oss, alsa engines.
|
||||
- Use rgb if available for xv.
|
||||
- Get rid of BAD_MATCH warnings for setting non-existent xv attributes.
|
||||
- make subblitters private nested classes
|
||||
- add reset action
|
||||
- Add support for DMG palette customization.
|
||||
- Add global buffer option for dsound engine
|
||||
|
||||
-- 0.2.0 -- 2007-09-05 --
|
||||
libgambatte:
|
||||
- fix 64-bit compile and segfault. Thanks to Nach for noticing.
|
||||
- Add zip support. Thanks to Nach for contributing nice, clear code
|
||||
- fix sound ch4 frequency calculation
|
||||
- Several PPU reads timings depend on wx. Thanks to franpa for noticing the
|
||||
corrupt line in The LoZ: Oracle of Seasons.
|
||||
- remove unused doubleSpeed parameter from m3ExtraCycles call
|
||||
gambatte_sdl:
|
||||
- Thread safety, bigger sound buffer
|
||||
- Compile on more platforms. Thanks to Thristian for the find.
|
||||
- actually increment iterator so the loop makes some sense (parser.cpp)
|
||||
gambatte_qt:
|
||||
- fix 64-bit compile. Thanks to Nach.
|
||||
- better license info for x11getprocaddress.cpp
|
||||
- initial joystick support, mostly using SDL's joystick code (separated from
|
||||
the rest of SDL)
|
||||
- use binary search for gb inputs.
|
||||
all:
|
||||
- make sure to use std:: despite sloppy compilers allowing omission. Thanks
|
||||
to blargg for the reminder.
|
||||
- get rid of some valgrind warnings. Thanks to Nach for noticing.
|
||||
hwtests:
|
||||
- add tests for wx effects on PPU read timings.
|
||||
build:
|
||||
- add -Wextra to default compile flags
|
||||
doc:
|
||||
- mention optional zlib dependency
|
||||
- additions to thanks section
|
||||
|
||||
-- 0.1.1 -- 2007-08-29 --
|
||||
libgambatte:
|
||||
- fix integer overflow in color conversion to rgb16
|
||||
- only accept valid filter indexes
|
||||
gambatte_sdl:
|
||||
- print version
|
||||
- print usage
|
||||
- support command line arguments.
|
||||
- add option for starting in full-screen
|
||||
- add option for using video filter
|
||||
gambatte_qt:
|
||||
- clean up obsolete includes.
|
||||
- directdraw: only use alpha if primary surface uses it.
|
||||
- add support for loading rom from porgam argument.
|
||||
- s/"a highly accurate"/"an accuracy-focused"/ in about box
|
||||
- gditoggler: fix unordered video mode listing
|
||||
build:
|
||||
- Support external CPPFLAGS
|
||||
- Use sdl-config
|
||||
doc:
|
||||
- fix silly wording in README about section
|
||||
- s/seperate/separate/
|
||||
- s/Automake/Make/
|
||||
- mention XShm dependency
|
||||
- mention sys/shm.h requirement
|
||||
- document key mapping better
|
||||
- s/"a highly accurate"/"an accuracy-focused"/
|
||||
- add man pages
|
||||
+56
-43
@@ -68,6 +68,7 @@ public:
|
||||
|
||||
- (void)applyCheat:(NSString *)code;
|
||||
|
||||
- (void)loadDisplayModeOptions;
|
||||
- (NSString *)gameInternalName;
|
||||
- (BOOL)gameHasInternalPalette;
|
||||
- (void)loadPalette;
|
||||
@@ -101,7 +102,7 @@ public:
|
||||
|
||||
- (BOOL)loadFileAtPath:(NSString *)path error:(NSError **)error
|
||||
{
|
||||
memset(pad, 0, sizeof(uint32_t) * OEGBButtonCount);
|
||||
memset(pad, 0, sizeof(pad));
|
||||
|
||||
// Set battery save dir
|
||||
NSURL *batterySavesDirectory = [NSURL fileURLWithPath:self.batterySavesDirectoryPath];
|
||||
@@ -127,9 +128,7 @@ public:
|
||||
if (gb.load(path.fileSystemRepresentation) != 0)
|
||||
return NO;
|
||||
|
||||
// Load built-in GBC palette for monochrome games if supported
|
||||
if (!gb.isCgb())
|
||||
[self loadPalette];
|
||||
[self loadDisplayModeOptions];
|
||||
|
||||
return YES;
|
||||
}
|
||||
@@ -330,52 +329,49 @@ const int GBMap[] = {gambatte::InputGetter::UP, gambatte::InputGetter::DOWN, gam
|
||||
|
||||
- (NSArray <NSDictionary <NSString *, id> *> *)displayModes
|
||||
{
|
||||
if (gb.isCgb())
|
||||
return nil;
|
||||
|
||||
if (_availableDisplayModes.count == 0)
|
||||
{
|
||||
_availableDisplayModes = [NSMutableArray array];
|
||||
|
||||
NSArray <NSDictionary <NSString *, id> *> *availableModesWithDefault =
|
||||
@[
|
||||
Option(@"Internal", @"palette"),
|
||||
Option(@"Grayscale", @"palette"),
|
||||
Option(@"Greenscale", @"palette"),
|
||||
Option(@"Pocket", @"palette"),
|
||||
SeparatorItem(),
|
||||
Label(@"GBC Palettes"),
|
||||
Option(@"Blue", @"palette"),
|
||||
Option(@"Dark Blue", @"palette"),
|
||||
Option(@"Green", @"palette"),
|
||||
Option(@"Dark Green", @"palette"),
|
||||
Option(@"Brown", @"palette"),
|
||||
Option(@"Dark Brown", @"palette"),
|
||||
Option(@"Red", @"palette"),
|
||||
Option(@"Yellow", @"palette"),
|
||||
Option(@"Orange", @"palette"),
|
||||
Option(@"Pastel Mix", @"palette"),
|
||||
Option(@"Inverted", @"palette"),
|
||||
// @{ OEGameCoreDisplayModeGroupNameKey : @"Test Menu",
|
||||
// OEGameCoreDisplayModeGroupItemsKey : @[
|
||||
// OptionToggleable(@"Toggle 1", @"toggle1"),
|
||||
// OptionToggleable(@"Toggle 2", @"toggle2"),
|
||||
// SeparatorItem(),
|
||||
// Label(@"Group 1"),
|
||||
// OptionIndented(@"Option 1", @"option"),
|
||||
// OptionIndented(@"Option 2", @"option"),
|
||||
// SeparatorItem(),
|
||||
// Label(@"Group 2"),
|
||||
// OptionIndented(@"Option 3", @"option2"),
|
||||
// OptionIndented(@"Option 4", @"option2"),
|
||||
// ]
|
||||
// },
|
||||
];
|
||||
NSArray <NSDictionary <NSString *, id> *> *availableModesWithDefault;
|
||||
|
||||
if (gb.isCgb())
|
||||
{
|
||||
availableModesWithDefault =
|
||||
@[
|
||||
Label(@"Color Correction"),
|
||||
OptionDefault(@"Default", @"colorCorrection"),
|
||||
Option(@"Modern", @"colorCorrection"),
|
||||
];
|
||||
}
|
||||
else
|
||||
{
|
||||
availableModesWithDefault =
|
||||
@[
|
||||
Option(@"Internal", @"palette"),
|
||||
Option(@"Grayscale", @"palette"),
|
||||
Option(@"Greenscale", @"palette"),
|
||||
Option(@"Pocket", @"palette"),
|
||||
SeparatorItem(),
|
||||
Label(@"GBC Palettes"),
|
||||
Option(@"Blue", @"palette"),
|
||||
Option(@"Dark Blue", @"palette"),
|
||||
Option(@"Green", @"palette"),
|
||||
Option(@"Dark Green", @"palette"),
|
||||
Option(@"Brown", @"palette"),
|
||||
Option(@"Dark Brown", @"palette"),
|
||||
Option(@"Red", @"palette"),
|
||||
Option(@"Yellow", @"palette"),
|
||||
Option(@"Orange", @"palette"),
|
||||
Option(@"Pastel Mix", @"palette"),
|
||||
Option(@"Inverted", @"palette"),
|
||||
];
|
||||
}
|
||||
|
||||
// Deep mutable copy
|
||||
_availableDisplayModes = (NSMutableArray *)CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFArrayRef)availableModesWithDefault, kCFPropertyListMutableContainers));
|
||||
|
||||
if (![self gameHasInternalPalette])
|
||||
if (!gb.isCgb() && ![self gameHasInternalPalette])
|
||||
[_availableDisplayModes removeObjectAtIndex:0];
|
||||
}
|
||||
|
||||
@@ -470,6 +466,8 @@ const int GBMap[] = {gambatte::InputGetter::UP, gambatte::InputGetter::DOWN, gam
|
||||
// Set the new palette
|
||||
if ([displayModePrefKey isEqualToString:@"palette"])
|
||||
[self changePalette:displayMode];
|
||||
else if ([displayModePrefKey isEqualToString:@"colorCorrection"])
|
||||
gb.setCgbColorCorrection([displayMode isEqual:@"Modern"] ? 1 : 0);
|
||||
}
|
||||
|
||||
# pragma mark - Misc Helper Methods
|
||||
@@ -482,7 +480,7 @@ const int GBMap[] = {gambatte::InputGetter::UP, gambatte::InputGetter::DOWN, gam
|
||||
size_t len = resampler->resample(_outSoundBuffer, reinterpret_cast<const int16_t *>(_inSoundBuffer), frames);
|
||||
|
||||
if (len)
|
||||
[[self ringBufferAtIndex:0] write:_outSoundBuffer maxLength:len << 2];
|
||||
[[self audioBufferAtIndex:0] write:_outSoundBuffer maxLength:len << 2];
|
||||
}
|
||||
|
||||
- (void)applyCheat:(NSString *)code
|
||||
@@ -494,6 +492,21 @@ const int GBMap[] = {gambatte::InputGetter::UP, gambatte::InputGetter::DOWN, gam
|
||||
gb.setGameShark(s);
|
||||
}
|
||||
|
||||
- (void)loadDisplayModeOptions
|
||||
{
|
||||
if (gb.isCgb())
|
||||
{
|
||||
// Restore color correction
|
||||
NSString *lastColorCorrection = self.displayModeInfo[@"colorCorrection"] ?: @"Default";
|
||||
[self changeDisplayWithMode:lastColorCorrection];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load built-in GBC palette for monochrome games if supported
|
||||
[self loadPalette];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)gameInternalName
|
||||
{
|
||||
NSString *title = [NSString stringWithUTF8String:gb.romTitle().c_str()];
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
828387BB0E6CDB6500A96E2C /* gameboy.icns in Resources */ = {isa = PBXBuildFile; fileRef = B5F6D8A80E66914F001CA5D3 /* gameboy.icns */; };
|
||||
828387BD0E6CDB6500A96E2C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165FFE840EACC02AAC07 /* InfoPlist.strings */; };
|
||||
828387E20E6CDB6E00A96E2C /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A7FEA54F5311CA2CBB /* Cocoa.framework */; };
|
||||
8F14C4F929FF7217000D080B /* statesaver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8F14C4F829FF7217000D080B /* statesaver.cpp */; };
|
||||
9499B5D81AB242B200276D21 /* chainresampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9499B54E1AB242B200276D21 /* chainresampler.cpp */; };
|
||||
9499B5D91AB242B200276D21 /* i0.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9499B5541AB242B200276D21 /* i0.cpp */; };
|
||||
9499B5DA1AB242B200276D21 /* kaiser50sinc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9499B5561AB242B200276D21 /* kaiser50sinc.cpp */; };
|
||||
@@ -67,7 +68,6 @@
|
||||
9499B5FE1AB242B300276D21 /* length_counter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9499B5BA1AB242B200276D21 /* length_counter.cpp */; };
|
||||
9499B5FF1AB242B300276D21 /* sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9499B5BF1AB242B200276D21 /* sound.cpp */; };
|
||||
9499B6001AB242B300276D21 /* state_osd_elements.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9499B5C11AB242B200276D21 /* state_osd_elements.cpp */; };
|
||||
9499B6011AB242B300276D21 /* statesaver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9499B5C31AB242B200276D21 /* statesaver.cpp */; };
|
||||
9499B6021AB242B300276D21 /* tima.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9499B5C51AB242B200276D21 /* tima.cpp */; };
|
||||
9499B6031AB242B300276D21 /* ly_counter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9499B5C91AB242B200276D21 /* ly_counter.cpp */; };
|
||||
9499B6041AB242B300276D21 /* lyc_irq.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9499B5CB1AB242B200276D21 /* lyc_irq.cpp */; };
|
||||
@@ -113,12 +113,10 @@
|
||||
1058C7A7FEA54F5311CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
828387810E6CDB2200A96E2C /* Gambatte.oecoreplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Gambatte.oecoreplugin; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
828387820E6CDB2200A96E2C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
9499B5431AB242B200276D21 /* adaptivesleep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = adaptivesleep.cpp; sourceTree = "<group>"; };
|
||||
9499B5441AB242B200276D21 /* adaptivesleep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = adaptivesleep.h; sourceTree = "<group>"; };
|
||||
8F14C4F729FF7204000D080B /* memfile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = memfile.h; sourceTree = "<group>"; };
|
||||
8F14C4F829FF7217000D080B /* statesaver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = statesaver.cpp; sourceTree = "<group>"; };
|
||||
9499B5451AB242B200276D21 /* array.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = array.h; sourceTree = "<group>"; };
|
||||
9499B5461AB242B200276D21 /* defined_ptr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = defined_ptr.h; sourceTree = "<group>"; };
|
||||
9499B5471AB242B200276D21 /* rateest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rateest.cpp; sourceTree = "<group>"; };
|
||||
9499B5481AB242B200276D21 /* rateest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rateest.h; sourceTree = "<group>"; };
|
||||
9499B54A1AB242B200276D21 /* resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resampler.h; sourceTree = "<group>"; };
|
||||
9499B54B1AB242B200276D21 /* resamplerinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resamplerinfo.h; sourceTree = "<group>"; };
|
||||
9499B54D1AB242B200276D21 /* blackmansinc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blackmansinc.h; sourceTree = "<group>"; };
|
||||
@@ -145,34 +143,14 @@
|
||||
9499B5621AB242B200276D21 /* u48div.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = u48div.cpp; sourceTree = "<group>"; };
|
||||
9499B5631AB242B200276D21 /* u48div.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = u48div.h; sourceTree = "<group>"; };
|
||||
9499B5641AB242B200276D21 /* upsampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = upsampler.h; sourceTree = "<group>"; };
|
||||
9499B5651AB242B200276D21 /* ringbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ringbuffer.h; sourceTree = "<group>"; };
|
||||
9499B5661AB242B200276D21 /* scoped_ptr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scoped_ptr.h; sourceTree = "<group>"; };
|
||||
9499B5671AB242B200276D21 /* skipsched.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = skipsched.cpp; sourceTree = "<group>"; };
|
||||
9499B5681AB242B200276D21 /* skipsched.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = skipsched.h; sourceTree = "<group>"; };
|
||||
9499B5691AB242B200276D21 /* transfer_ptr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = transfer_ptr.h; sourceTree = "<group>"; };
|
||||
9499B56A1AB242B200276D21 /* uncopyable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uncopyable.h; sourceTree = "<group>"; };
|
||||
9499B56B1AB242B200276D21 /* usec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = usec.h; sourceTree = "<group>"; };
|
||||
9499B56D1AB242B200276D21 /* rgb32conv.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rgb32conv.cpp; sourceTree = "<group>"; };
|
||||
9499B56E1AB242B200276D21 /* rgb32conv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rgb32conv.h; sourceTree = "<group>"; };
|
||||
9499B56F1AB242B200276D21 /* vfilterinfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vfilterinfo.cpp; sourceTree = "<group>"; };
|
||||
9499B5701AB242B200276D21 /* vfilterinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vfilterinfo.h; sourceTree = "<group>"; };
|
||||
9499B5721AB242B200276D21 /* catrom2x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = catrom2x.cpp; sourceTree = "<group>"; };
|
||||
9499B5731AB242B200276D21 /* catrom2x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catrom2x.h; sourceTree = "<group>"; };
|
||||
9499B5741AB242B200276D21 /* catrom3x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = catrom3x.cpp; sourceTree = "<group>"; };
|
||||
9499B5751AB242B200276D21 /* catrom3x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catrom3x.h; sourceTree = "<group>"; };
|
||||
9499B5761AB242B200276D21 /* kreed2xsai.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = kreed2xsai.cpp; sourceTree = "<group>"; };
|
||||
9499B5771AB242B200276D21 /* kreed2xsai.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kreed2xsai.h; sourceTree = "<group>"; };
|
||||
9499B5781AB242B200276D21 /* maxsthq2x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = maxsthq2x.cpp; sourceTree = "<group>"; };
|
||||
9499B5791AB242B200276D21 /* maxsthq2x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = maxsthq2x.h; sourceTree = "<group>"; };
|
||||
9499B57A1AB242B200276D21 /* maxsthq3x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = maxsthq3x.cpp; sourceTree = "<group>"; };
|
||||
9499B57B1AB242B200276D21 /* maxsthq3x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = maxsthq3x.h; sourceTree = "<group>"; };
|
||||
9499B57C1AB242B200276D21 /* videolink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = videolink.h; sourceTree = "<group>"; };
|
||||
9499B57F1AB242B200276D21 /* gambatte.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gambatte.h; sourceTree = "<group>"; };
|
||||
9499B5801AB242B200276D21 /* gbint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gbint.h; sourceTree = "<group>"; };
|
||||
9499B5811AB242B200276D21 /* inputgetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = inputgetter.h; sourceTree = "<group>"; };
|
||||
9499B5821AB242B200276D21 /* loadres.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = loadres.h; sourceTree = "<group>"; };
|
||||
9499B5831AB242B200276D21 /* pakinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pakinfo.h; sourceTree = "<group>"; };
|
||||
9499B5841AB242B200276D21 /* SConstruct */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SConstruct; sourceTree = "<group>"; };
|
||||
9499B5861AB242B200276D21 /* bitmap_font.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bitmap_font.cpp; sourceTree = "<group>"; };
|
||||
9499B5871AB242B200276D21 /* bitmap_font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bitmap_font.h; sourceTree = "<group>"; };
|
||||
9499B5881AB242B200276D21 /* counterdef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = counterdef.h; sourceTree = "<group>"; };
|
||||
@@ -180,13 +158,7 @@
|
||||
9499B58A1AB242B200276D21 /* cpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpu.h; sourceTree = "<group>"; };
|
||||
9499B58C1AB242B200276D21 /* file.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file.cpp; sourceTree = "<group>"; };
|
||||
9499B58D1AB242B200276D21 /* file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file.h; sourceTree = "<group>"; };
|
||||
9499B58E1AB242B200276D21 /* file_zip.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_zip.cpp; sourceTree = "<group>"; };
|
||||
9499B58F1AB242B200276D21 /* stdfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stdfile.h; sourceTree = "<group>"; };
|
||||
9499B5911AB242B200276D21 /* crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypt.h; sourceTree = "<group>"; };
|
||||
9499B5921AB242B200276D21 /* ioapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioapi.c; sourceTree = "<group>"; };
|
||||
9499B5931AB242B200276D21 /* ioapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioapi.h; sourceTree = "<group>"; };
|
||||
9499B5941AB242B200276D21 /* unzip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unzip.c; sourceTree = "<group>"; };
|
||||
9499B5951AB242B200276D21 /* unzip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unzip.h; sourceTree = "<group>"; };
|
||||
9499B5961AB242B200276D21 /* gambatte.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gambatte.cpp; sourceTree = "<group>"; };
|
||||
9499B5971AB242B200276D21 /* initstate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = initstate.cpp; sourceTree = "<group>"; };
|
||||
9499B5981AB242B200276D21 /* initstate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = initstate.h; sourceTree = "<group>"; };
|
||||
@@ -239,7 +211,6 @@
|
||||
9499B5CA1AB242B200276D21 /* ly_counter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ly_counter.h; sourceTree = "<group>"; };
|
||||
9499B5CB1AB242B200276D21 /* lyc_irq.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lyc_irq.cpp; sourceTree = "<group>"; };
|
||||
9499B5CC1AB242B200276D21 /* lyc_irq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lyc_irq.h; sourceTree = "<group>"; };
|
||||
9499B5CD1AB242B200276D21 /* m0_irq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m0_irq.h; sourceTree = "<group>"; };
|
||||
9499B5CE1AB242B200276D21 /* next_m0_time.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = next_m0_time.cpp; sourceTree = "<group>"; };
|
||||
9499B5CF1AB242B200276D21 /* next_m0_time.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = next_m0_time.h; sourceTree = "<group>"; };
|
||||
9499B5D01AB242B200276D21 /* ppu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ppu.cpp; sourceTree = "<group>"; };
|
||||
@@ -313,6 +284,7 @@
|
||||
C6B947DE1364FD0C00A425F0 /* OEGBSystemResponderClient.h */,
|
||||
B5EC4D410E6312DF0046BD93 /* GBGameCore.h */,
|
||||
B5EC4D420E6312DF0046BD93 /* GBGameCore.mm */,
|
||||
8F14C4F829FF7217000D080B /* statesaver.cpp */,
|
||||
);
|
||||
name = Classes;
|
||||
sourceTree = "<group>";
|
||||
@@ -344,26 +316,18 @@
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9499B5421AB242B200276D21 /* common */ = {
|
||||
9499B5421AB242B200276D21 /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9499B5431AB242B200276D21 /* adaptivesleep.cpp */,
|
||||
9499B5441AB242B200276D21 /* adaptivesleep.h */,
|
||||
9499B5451AB242B200276D21 /* array.h */,
|
||||
9499B5461AB242B200276D21 /* defined_ptr.h */,
|
||||
9499B5471AB242B200276D21 /* rateest.cpp */,
|
||||
9499B5481AB242B200276D21 /* rateest.h */,
|
||||
9499B5851AB242B200276D21 /* libgambatte */,
|
||||
9499B5491AB242B200276D21 /* resample */,
|
||||
9499B5651AB242B200276D21 /* ringbuffer.h */,
|
||||
9499B5661AB242B200276D21 /* scoped_ptr.h */,
|
||||
9499B5671AB242B200276D21 /* skipsched.cpp */,
|
||||
9499B5681AB242B200276D21 /* skipsched.h */,
|
||||
9499B5691AB242B200276D21 /* transfer_ptr.h */,
|
||||
9499B56A1AB242B200276D21 /* uncopyable.h */,
|
||||
9499B56B1AB242B200276D21 /* usec.h */,
|
||||
9499B56C1AB242B200276D21 /* videolink */,
|
||||
);
|
||||
path = common;
|
||||
path = src;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9499B5491AB242B200276D21 /* resample */ = {
|
||||
@@ -371,14 +335,6 @@
|
||||
children = (
|
||||
9499B54A1AB242B200276D21 /* resampler.h */,
|
||||
9499B54B1AB242B200276D21 /* resamplerinfo.h */,
|
||||
9499B54C1AB242B200276D21 /* src */,
|
||||
);
|
||||
path = resample;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9499B54C1AB242B200276D21 /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9499B54D1AB242B200276D21 /* blackmansinc.h */,
|
||||
9499B54E1AB242B200276D21 /* chainresampler.cpp */,
|
||||
9499B54F1AB242B200276D21 /* chainresampler.h */,
|
||||
@@ -404,62 +360,10 @@
|
||||
9499B5631AB242B200276D21 /* u48div.h */,
|
||||
9499B5641AB242B200276D21 /* upsampler.h */,
|
||||
);
|
||||
path = src;
|
||||
path = resample;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9499B56C1AB242B200276D21 /* videolink */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9499B56D1AB242B200276D21 /* rgb32conv.cpp */,
|
||||
9499B56E1AB242B200276D21 /* rgb32conv.h */,
|
||||
9499B56F1AB242B200276D21 /* vfilterinfo.cpp */,
|
||||
9499B5701AB242B200276D21 /* vfilterinfo.h */,
|
||||
9499B5711AB242B200276D21 /* vfilters */,
|
||||
9499B57C1AB242B200276D21 /* videolink.h */,
|
||||
);
|
||||
path = videolink;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9499B5711AB242B200276D21 /* vfilters */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9499B5721AB242B200276D21 /* catrom2x.cpp */,
|
||||
9499B5731AB242B200276D21 /* catrom2x.h */,
|
||||
9499B5741AB242B200276D21 /* catrom3x.cpp */,
|
||||
9499B5751AB242B200276D21 /* catrom3x.h */,
|
||||
9499B5761AB242B200276D21 /* kreed2xsai.cpp */,
|
||||
9499B5771AB242B200276D21 /* kreed2xsai.h */,
|
||||
9499B5781AB242B200276D21 /* maxsthq2x.cpp */,
|
||||
9499B5791AB242B200276D21 /* maxsthq2x.h */,
|
||||
9499B57A1AB242B200276D21 /* maxsthq3x.cpp */,
|
||||
9499B57B1AB242B200276D21 /* maxsthq3x.h */,
|
||||
);
|
||||
path = vfilters;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9499B57D1AB242B200276D21 /* libgambatte */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9499B57E1AB242B200276D21 /* include */,
|
||||
9499B5841AB242B200276D21 /* SConstruct */,
|
||||
9499B5851AB242B200276D21 /* src */,
|
||||
);
|
||||
path = libgambatte;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9499B57E1AB242B200276D21 /* include */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9499B57F1AB242B200276D21 /* gambatte.h */,
|
||||
9499B5801AB242B200276D21 /* gbint.h */,
|
||||
9499B5811AB242B200276D21 /* inputgetter.h */,
|
||||
9499B5821AB242B200276D21 /* loadres.h */,
|
||||
9499B5831AB242B200276D21 /* pakinfo.h */,
|
||||
);
|
||||
path = include;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9499B5851AB242B200276D21 /* src */ = {
|
||||
9499B5851AB242B200276D21 /* libgambatte */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9499B5861AB242B200276D21 /* bitmap_font.cpp */,
|
||||
@@ -469,19 +373,24 @@
|
||||
9499B58A1AB242B200276D21 /* cpu.h */,
|
||||
9499B58B1AB242B200276D21 /* file */,
|
||||
9499B5961AB242B200276D21 /* gambatte.cpp */,
|
||||
9499B57F1AB242B200276D21 /* gambatte.h */,
|
||||
9499B5801AB242B200276D21 /* gbint.h */,
|
||||
9499B5971AB242B200276D21 /* initstate.cpp */,
|
||||
9499B5981AB242B200276D21 /* initstate.h */,
|
||||
9499B5811AB242B200276D21 /* inputgetter.h */,
|
||||
9499B5991AB242B200276D21 /* insertion_sort.h */,
|
||||
9499B59A1AB242B200276D21 /* interrupter.cpp */,
|
||||
9499B59B1AB242B200276D21 /* interrupter.h */,
|
||||
9499B59C1AB242B200276D21 /* interruptrequester.cpp */,
|
||||
9499B59D1AB242B200276D21 /* interruptrequester.h */,
|
||||
9499B59E1AB242B200276D21 /* loadres.cpp */,
|
||||
9499B5821AB242B200276D21 /* loadres.h */,
|
||||
9499B59F1AB242B200276D21 /* mem */,
|
||||
9499B5A81AB242B200276D21 /* memory.cpp */,
|
||||
9499B5A91AB242B200276D21 /* memory.h */,
|
||||
9499B5AA1AB242B200276D21 /* minkeeper.h */,
|
||||
9499B5AB1AB242B200276D21 /* osd_element.h */,
|
||||
9499B5831AB242B200276D21 /* pakinfo.h */,
|
||||
9499B5AC1AB242B200276D21 /* savestate.h */,
|
||||
9499B5AD1AB242B200276D21 /* sound */,
|
||||
9499B5BF1AB242B200276D21 /* sound.cpp */,
|
||||
@@ -496,7 +405,7 @@
|
||||
9499B5D41AB242B200276D21 /* video.cpp */,
|
||||
9499B5D51AB242B200276D21 /* video.h */,
|
||||
);
|
||||
path = src;
|
||||
path = libgambatte;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9499B58B1AB242B200276D21 /* file */ = {
|
||||
@@ -504,25 +413,12 @@
|
||||
children = (
|
||||
9499B58C1AB242B200276D21 /* file.cpp */,
|
||||
9499B58D1AB242B200276D21 /* file.h */,
|
||||
9499B58E1AB242B200276D21 /* file_zip.cpp */,
|
||||
8F14C4F729FF7204000D080B /* memfile.h */,
|
||||
9499B58F1AB242B200276D21 /* stdfile.h */,
|
||||
9499B5901AB242B200276D21 /* unzip */,
|
||||
);
|
||||
path = file;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9499B5901AB242B200276D21 /* unzip */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9499B5911AB242B200276D21 /* crypt.h */,
|
||||
9499B5921AB242B200276D21 /* ioapi.c */,
|
||||
9499B5931AB242B200276D21 /* ioapi.h */,
|
||||
9499B5941AB242B200276D21 /* unzip.c */,
|
||||
9499B5951AB242B200276D21 /* unzip.h */,
|
||||
);
|
||||
path = unzip;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9499B59F1AB242B200276D21 /* mem */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -570,7 +466,6 @@
|
||||
9499B5CA1AB242B200276D21 /* ly_counter.h */,
|
||||
9499B5CB1AB242B200276D21 /* lyc_irq.cpp */,
|
||||
9499B5CC1AB242B200276D21 /* lyc_irq.h */,
|
||||
9499B5CD1AB242B200276D21 /* m0_irq.h */,
|
||||
9499B5CE1AB242B200276D21 /* next_m0_time.cpp */,
|
||||
9499B5CF1AB242B200276D21 /* next_m0_time.h */,
|
||||
9499B5D01AB242B200276D21 /* ppu.cpp */,
|
||||
@@ -584,8 +479,7 @@
|
||||
B5A6D9310E617C4900622CCF /* Core */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9499B5421AB242B200276D21 /* common */,
|
||||
9499B57D1AB242B200276D21 /* libgambatte */,
|
||||
9499B5421AB242B200276D21 /* src */,
|
||||
);
|
||||
name = Core;
|
||||
sourceTree = "<group>";
|
||||
@@ -702,7 +596,7 @@
|
||||
9499B5F71AB242B300276D21 /* memory.cpp in Sources */,
|
||||
9499B5FF1AB242B300276D21 /* sound.cpp in Sources */,
|
||||
9499B6001AB242B300276D21 /* state_osd_elements.cpp in Sources */,
|
||||
9499B6011AB242B300276D21 /* statesaver.cpp in Sources */,
|
||||
8F14C4F929FF7217000D080B /* statesaver.cpp in Sources */,
|
||||
9499B6021AB242B300276D21 /* tima.cpp in Sources */,
|
||||
9499B6081AB242B300276D21 /* video.cpp in Sources */,
|
||||
9499B5F31AB242B300276D21 /* cartridge.cpp in Sources */,
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.5.0.689</string>
|
||||
<string>0.5.1</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>OEGameCoreController</string>
|
||||
<key>OEGameCoreClass</key>
|
||||
@@ -41,7 +41,7 @@
|
||||
<key>OEGameCorePlayerCount</key>
|
||||
<string>1</string>
|
||||
<key>OEProjectURL</key>
|
||||
<string>https://github.com/sinamas/gambatte</string>
|
||||
<string>https://gitlab.com/jgemu/gambatte</string>
|
||||
<key>OESystemIdentifiers</key>
|
||||
<array>
|
||||
<string>openemu.system.gb</string>
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
Gambatte JG
|
||||
-----------
|
||||
Gambatte JG is an emulator for the Nintendo Game Boy/Game Boy Color.
|
||||
|
||||
This is a fork of the final public revision of Gambatte.
|
||||
|
||||
This repository lives at https://gitlab.com/jgemu/gambatte
|
||||
|
||||
Compiling
|
||||
---------
|
||||
Make sure you have The Jolly Good API's header files installed. If you did
|
||||
not install them, you will be required to include their path in CXXFLAGS.
|
||||
|
||||
GNU Make's default behaviour for compiling C++ sources is to use g++. If your
|
||||
platform of choice uses an unpatched GNU Make, you will need to override the
|
||||
CXX implicit variable if you wish to use a different compiler.
|
||||
|
||||
Options:
|
||||
USE_VENDORED_SOXR - Set non-zero to use vendored soxr
|
||||
|
||||
Linux:
|
||||
make
|
||||
|
||||
macOS:
|
||||
make
|
||||
|
||||
BSD:
|
||||
gmake
|
||||
|
||||
Windows (MSYS2):
|
||||
make
|
||||
|
||||
The build will be output to "gambatte/". This directory may be used as is
|
||||
locally by copying it to your local "cores" directory, or may be installed
|
||||
system-wide using the "install" target specified in the Makefile.
|
||||
|
||||
Settings
|
||||
--------
|
||||
palette = 0
|
||||
0 = Internal, 1 = Original Green, 2 = GB Pocket, 3 = Blue, 4 = Brown,
|
||||
5 = Dark Blue, 6 = Dark Brown, 7 = Dark Green, 8 = Grayscale, 9 = Green,
|
||||
10 = Inverted, 11 = Orange, 12 = Pastel Mix, 13 = Red, 14 = Yellow
|
||||
|
||||
system = 0
|
||||
0 = Auto (CGB), 1 = DMG, 2 = GBA-CGB
|
||||
|
||||
turbo_rate = 3
|
||||
N = Pulse every N frames
|
||||
|
||||
Copyright
|
||||
---------
|
||||
Gambatte JG (GPL-2.0-or-later)
|
||||
Copyright (c) 2007-2020 Sindre Aamås
|
||||
Copyright (c) 2020-2022 Rupert Carmichael
|
||||
|
||||
SoX Resampler Library (LGPL-2.1-or-later)
|
||||
Copyright (c) 2007-2018 Rob Sykes
|
||||
See source files in deps/soxr/ (https://sourceforge.net/projects/soxr/)
|
||||
@@ -1,52 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#include "adaptivesleep.h"
|
||||
|
||||
static usec_t absdiff(usec_t a, usec_t b) { return a < b ? b - a : a - b; }
|
||||
|
||||
usec_t AdaptiveSleep::sleepUntil(usec_t base, usec_t inc) {
|
||||
usec_t now = getusecs();
|
||||
usec_t diff = now - base;
|
||||
if (diff >= inc)
|
||||
return diff - inc;
|
||||
|
||||
diff = inc - diff;
|
||||
if (diff > oversleep_ + oversleepVar_) {
|
||||
diff -= oversleep_ + oversleepVar_;
|
||||
usecsleep(diff);
|
||||
usec_t const sleepTarget = now + diff;
|
||||
now = getusecs();
|
||||
|
||||
usec_t curOversleep = now - sleepTarget;
|
||||
if (curOversleep > usec_t(-1) / 2)
|
||||
curOversleep = 0;
|
||||
|
||||
oversleepVar_ = (oversleepVar_ * 15 + absdiff(curOversleep, oversleep_) + 8) >> 4;
|
||||
oversleep_ = (oversleep_ * 15 + curOversleep + 8) >> 4;
|
||||
noSleep_ = 60;
|
||||
} else if (--noSleep_ == 0) {
|
||||
noSleep_ = 60;
|
||||
oversleep_ = oversleepVar_ = 0;
|
||||
}
|
||||
|
||||
while (now - base < inc)
|
||||
now = getusecs();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef ADAPTIVE_SLEEP_H
|
||||
#define ADAPTIVE_SLEEP_H
|
||||
|
||||
#include "usec.h"
|
||||
|
||||
class AdaptiveSleep {
|
||||
public:
|
||||
AdaptiveSleep() : oversleep_(0), oversleepVar_(0), noSleep_(60) {}
|
||||
usec_t sleepUntil(usec_t base, usec_t inc);
|
||||
|
||||
private:
|
||||
usec_t oversleep_;
|
||||
usec_t oversleepVar_;
|
||||
unsigned noSleep_;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,91 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#include "rateest.h"
|
||||
#include <cstdlib>
|
||||
|
||||
void RateEst::SumQueue::push(std::ptrdiff_t const samples, usec_t const usecs) {
|
||||
q_.push_back(std::make_pair(samples, usecs));
|
||||
samples_ += samples;
|
||||
usecs_ += usecs;
|
||||
}
|
||||
|
||||
void RateEst::SumQueue::pop() {
|
||||
std::pair<std::ptrdiff_t, usec_t> const &f = q_.front();
|
||||
samples_ -= f.first;
|
||||
usecs_ -= f.second;
|
||||
q_.pop_front();
|
||||
}
|
||||
|
||||
static usec_t sampleUsecs(std::ptrdiff_t samples, long rate) {
|
||||
return usec_t((samples * 1000000.0f) / (rate ? rate : 1) + 0.5f);
|
||||
}
|
||||
|
||||
static long limit(long est, long const reference) {
|
||||
if (est > reference + (reference >> 6))
|
||||
est = reference + (reference >> 6);
|
||||
else if (est < reference - (reference >> 6))
|
||||
est = reference - (reference >> 6);
|
||||
|
||||
return est;
|
||||
}
|
||||
|
||||
RateEst::RateEst(long const nominalSampleRate, std::size_t const maxValidFeedPeriodSamples)
|
||||
: srate_(nominalSampleRate * est_scale)
|
||||
, reference_(srate_)
|
||||
, maxPeriod_(sampleUsecs(maxValidFeedPeriodSamples, nominalSampleRate))
|
||||
, last_(0)
|
||||
, t_(6000)
|
||||
, s_(nominalSampleRate * 6)
|
||||
, st_(s_ * t_)
|
||||
, t2_(t_ * t_)
|
||||
{
|
||||
}
|
||||
|
||||
void RateEst::feed(std::ptrdiff_t samplesIn, usec_t const now) {
|
||||
usec_t usecsIn = now - last_;
|
||||
|
||||
if (last_ && usecsIn < maxPeriod_) {
|
||||
sumq_.push(samplesIn, usecsIn);
|
||||
|
||||
while ((usecsIn = sumq_.usecs()) > 100000) {
|
||||
samplesIn = sumq_.samples();
|
||||
sumq_.pop();
|
||||
|
||||
long const srateIn = long(samplesIn * (1000000.0f * est_scale) / usecsIn);
|
||||
if (std::abs(srateIn - reference_) < reference_ >> 1) {
|
||||
s_ += samplesIn - sumq_.samples() ;
|
||||
t_ += ( usecsIn - sumq_.usecs() ) * 0.001;
|
||||
st_ += s_ * t_;
|
||||
t2_ += t_ * t_;
|
||||
|
||||
long est = long(st_ * (1000.0 * est_scale) / t2_ + 0.5);
|
||||
srate_ = limit((srate_ * 31 + est + 16) >> 5, reference_);
|
||||
|
||||
if (t_ > 8000) {
|
||||
s_ *= 3.0 / 4;
|
||||
t_ *= 3.0 / 4;
|
||||
st_ *= 9.0 / 16;
|
||||
t2_ *= 9.0 / 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
last_ = now;
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef RATEEST_H
|
||||
#define RATEEST_H
|
||||
|
||||
#include "usec.h"
|
||||
#include <cstddef>
|
||||
#include <deque>
|
||||
#include <utility>
|
||||
|
||||
class RateEst {
|
||||
public:
|
||||
RateEst() { *this = RateEst(0, 0); }
|
||||
RateEst(long nominalSampleRate, std::size_t maxValidFeedPeriodSamples);
|
||||
void resetLastFeedTimeStamp() { last_ = 0; }
|
||||
void feed(std::ptrdiff_t samples, usec_t usecsNow = getusecs());
|
||||
long result() const { return (srate_ + est_scale / 2) >> est_lshift; }
|
||||
|
||||
private:
|
||||
class SumQueue {
|
||||
public:
|
||||
SumQueue() : samples_(0), usecs_(0) {}
|
||||
std::ptrdiff_t samples() const { return samples_; }
|
||||
usec_t usecs() const { return usecs_; }
|
||||
void push(std::ptrdiff_t samples, usec_t usecs);
|
||||
void pop();
|
||||
|
||||
private:
|
||||
std::deque< std::pair<std::ptrdiff_t, usec_t> > q_;
|
||||
std::ptrdiff_t samples_;
|
||||
usec_t usecs_;
|
||||
};
|
||||
|
||||
enum { est_lshift = 5 };
|
||||
enum { est_scale = 1 << est_lshift };
|
||||
|
||||
SumQueue sumq_;
|
||||
long srate_;
|
||||
long reference_;
|
||||
usec_t maxPeriod_;
|
||||
usec_t last_;
|
||||
double t_, s_, st_, t2_;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,109 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef RINGBUFFER_H
|
||||
#define RINGBUFFER_H
|
||||
|
||||
#include "array.h"
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
template<typename T>
|
||||
class RingBuffer {
|
||||
public:
|
||||
explicit RingBuffer(std::size_t size = 0)
|
||||
: endpos_(0), rpos_(0), wpos_(0)
|
||||
{
|
||||
reset(size);
|
||||
}
|
||||
|
||||
void reset(std::size_t size);
|
||||
|
||||
void clear() {
|
||||
wpos_ = rpos_ = 0;
|
||||
}
|
||||
|
||||
void fill(T value);
|
||||
void read(T *out, std::size_t num);
|
||||
void write(T const *in, std::size_t num);
|
||||
|
||||
std::size_t avail() const {
|
||||
return (wpos_ < rpos_ ? 0 : endpos_) + rpos_ - wpos_ - 1;
|
||||
}
|
||||
|
||||
std::size_t used() const {
|
||||
return (wpos_ < rpos_ ? endpos_ : 0) + wpos_ - rpos_;
|
||||
}
|
||||
|
||||
std::size_t size() const {
|
||||
return endpos_ - 1;
|
||||
}
|
||||
|
||||
private:
|
||||
Array<T> buf_;
|
||||
std::size_t endpos_;
|
||||
std::size_t rpos_;
|
||||
std::size_t wpos_;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void RingBuffer<T>::reset(std::size_t size) {
|
||||
endpos_ = size + 1;
|
||||
rpos_ = wpos_ = 0;
|
||||
buf_.reset(size ? endpos_ : 0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void RingBuffer<T>::fill(T value) {
|
||||
std::fill(buf_.get(), buf_.get() + buf_.size(), value);
|
||||
rpos_ = 0;
|
||||
wpos_ = endpos_ - 1;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void RingBuffer<T>::read(T *out, std::size_t num) {
|
||||
if (rpos_ + num > endpos_) {
|
||||
std::size_t const n = endpos_ - rpos_;
|
||||
std::memcpy(out, buf_ + rpos_, n * sizeof *out);
|
||||
rpos_ = 0;
|
||||
num -= n;
|
||||
out += n;
|
||||
}
|
||||
|
||||
std::memcpy(out, buf_ + rpos_, num * sizeof *out);
|
||||
if ((rpos_ += num) == endpos_)
|
||||
rpos_ = 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void RingBuffer<T>::write(T const *in, std::size_t num) {
|
||||
if (wpos_ + num > endpos_) {
|
||||
std::size_t const n = endpos_ - wpos_;
|
||||
std::memcpy(buf_ + wpos_, in, n * sizeof *buf_);
|
||||
wpos_ = 0;
|
||||
num -= n;
|
||||
in += n;
|
||||
}
|
||||
|
||||
std::memcpy(buf_ + wpos_, in, num * sizeof *buf_);
|
||||
if ((wpos_ += num) == endpos_)
|
||||
wpos_ = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,35 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#include "skipsched.h"
|
||||
|
||||
bool SkipSched::skipNext(bool skip) {
|
||||
if (skipped_) {
|
||||
if (skipped_ < skippedmax_ / 2)
|
||||
skip = true;
|
||||
else
|
||||
skipped_ = skip = 0;
|
||||
} else if (skip) {
|
||||
skippedmax_ += skippedmax_ / 2 < 8;
|
||||
} else if (skippedmax_ / 2)
|
||||
--skippedmax_;
|
||||
|
||||
skipped_ += skip;
|
||||
|
||||
return skip;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef SKIPSCHED_H
|
||||
#define SKIPSCHED_H
|
||||
|
||||
class SkipSched {
|
||||
public:
|
||||
SkipSched() : skipped_(0), skippedmax_(2 - 1) {}
|
||||
bool skipNext(bool wantskip);
|
||||
|
||||
private:
|
||||
unsigned skipped_;
|
||||
unsigned skippedmax_;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,27 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef USEC_H
|
||||
#define USEC_H
|
||||
|
||||
typedef unsigned long usec_t;
|
||||
|
||||
usec_t getusecs();
|
||||
void usecsleep(usec_t usecs);
|
||||
|
||||
#endif
|
||||
@@ -1,199 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#include "rgb32conv.h"
|
||||
#include "array.h"
|
||||
#include "gbint.h"
|
||||
#include "videolink.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
|
||||
static bool isBigEndian() {
|
||||
union {
|
||||
gambatte::uint_least32_t ul32;
|
||||
unsigned char uc[sizeof(gambatte::uint_least32_t)];
|
||||
} u;
|
||||
u.ul32 = -0x10000;
|
||||
return u.uc[0];
|
||||
}
|
||||
|
||||
class Rgb32ToUyvy {
|
||||
public:
|
||||
Rgb32ToUyvy();
|
||||
void operator()(gambatte::uint_least32_t *d, std::ptrdiff_t dstPitch,
|
||||
gambatte::uint_least32_t const *s, std::ptrdiff_t srcPitch,
|
||||
unsigned w, unsigned h);
|
||||
|
||||
private:
|
||||
struct CacheUnit {
|
||||
gambatte::uint_least32_t rgb32;
|
||||
gambatte::uint_least32_t uyvy;
|
||||
};
|
||||
|
||||
enum { cache_size = 0x100 };
|
||||
enum { cache_mask = cache_size - 1 };
|
||||
CacheUnit cache_[cache_size];
|
||||
};
|
||||
|
||||
Rgb32ToUyvy::Rgb32ToUyvy() {
|
||||
if (isBigEndian()) {
|
||||
CacheUnit c = { 0, 128ul << 24 | 16ul << 16 | 128u << 8 | 16 };
|
||||
std::fill(cache_, cache_ + cache_size, c);
|
||||
} else {
|
||||
CacheUnit c = { 0, 16ul << 24 | 128ul << 16 | 16 << 8 | 128 };
|
||||
std::fill(cache_, cache_ + cache_size, c);
|
||||
}
|
||||
}
|
||||
|
||||
void Rgb32ToUyvy::operator()(gambatte::uint_least32_t *dst,
|
||||
std::ptrdiff_t const dstPitch,
|
||||
gambatte::uint_least32_t const *src,
|
||||
std::ptrdiff_t const srcPitch,
|
||||
unsigned const w,
|
||||
unsigned h)
|
||||
{
|
||||
while (h--) {
|
||||
gambatte::uint_least32_t *d = dst;
|
||||
gambatte::uint_least32_t const *s = src;
|
||||
gambatte::uint_least32_t const *const sEnd = s + w - 1;
|
||||
while (s < sEnd) {
|
||||
if ((cache_[s[0] & cache_mask].rgb32 - s[0]) | (cache_[s[1] & cache_mask].rgb32 - s[1])) {
|
||||
cache_[s[0] & cache_mask].rgb32 = s[0];
|
||||
cache_[s[1] & cache_mask].rgb32 = s[1];
|
||||
|
||||
unsigned long const r = (s[0] >> 16 & 0x000000FF) | (s[1] & 0x00FF0000);
|
||||
unsigned long const g = (s[0] >> 8 & 0x000000FF) | (s[1] << 8 & 0x00FF0000);
|
||||
unsigned long const b = (s[0] & 0x000000FF) | (s[1] << 16 & 0x00FF0000);
|
||||
unsigned long const y = r * 66 + g * 129 + b * 25 + ( 16 * 256u + 128) * 0x00010001ul;
|
||||
unsigned long const u = b * 112 - r * 38 - g * 74 + (128 * 256u + 128) * 0x00010001ul;
|
||||
unsigned long const v = r * 112 - g * 94 - b * 18 + (128 * 256u + 128) * 0x00010001ul;
|
||||
if (isBigEndian()) {
|
||||
d[0] = cache_[s[0] & cache_mask].uyvy = (u << 16 & 0xFF000000)
|
||||
| (y << 8 & 0x00FF0000)
|
||||
| (v & 0x0000FF00)
|
||||
| (y >> 8 & 0x000000FF);
|
||||
d[1] = cache_[s[1] & cache_mask].uyvy = (u & 0xFF000000)
|
||||
| (y >> 8 & 0x00FF0000)
|
||||
| (v >> 16 & 0x0000FF00)
|
||||
| y >> 24 ;
|
||||
} else {
|
||||
d[0] = cache_[s[0] & cache_mask].uyvy = (y << 16 & 0xFF000000)
|
||||
| (v << 8 & 0x00FF0000)
|
||||
| (y & 0x0000FF00)
|
||||
| (u >> 8 & 0x000000FF);
|
||||
d[1] = cache_[s[1] & cache_mask].uyvy = (y & 0xFF000000)
|
||||
| (v >> 8 & 0x00FF0000)
|
||||
| (y >> 16 & 0x0000FF00)
|
||||
| u >> 24 ;
|
||||
}
|
||||
} else {
|
||||
gambatte::uint_least32_t const s0 = s[0], s1 = s[1];
|
||||
d[0] = cache_[s0 & cache_mask].uyvy;
|
||||
d[1] = cache_[s1 & cache_mask].uyvy;
|
||||
}
|
||||
|
||||
s += 2;
|
||||
d += 2;
|
||||
}
|
||||
|
||||
src += srcPitch;
|
||||
dst += dstPitch;
|
||||
}
|
||||
}
|
||||
|
||||
static void rgb32ToRgb16(gambatte::uint_least16_t *d,
|
||||
std::ptrdiff_t const dstPitch,
|
||||
gambatte::uint_least32_t const *s,
|
||||
std::ptrdiff_t const srcPitch,
|
||||
unsigned const w,
|
||||
unsigned h)
|
||||
{
|
||||
do {
|
||||
std::ptrdiff_t i = -static_cast<std::ptrdiff_t>(w);
|
||||
s += w;
|
||||
d += w;
|
||||
|
||||
do {
|
||||
d[i] = (s[i] >> 8 & 0xF800) | (s[i] & 0xFC00) >> 5 | (s[i] & 0xFF) >> 3;
|
||||
} while (++i);
|
||||
|
||||
s += srcPitch - static_cast<std::ptrdiff_t>(w);
|
||||
d += dstPitch - static_cast<std::ptrdiff_t>(w);
|
||||
} while (--h);
|
||||
}
|
||||
|
||||
class Rgb32ToUyvyLink : public VideoLink {
|
||||
public:
|
||||
Rgb32ToUyvyLink(unsigned width, unsigned height)
|
||||
: inbuf_(static_cast<std::size_t>(width) * height)
|
||||
, width_(width)
|
||||
, height_(height)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void * inBuf() const { return inbuf_; }
|
||||
virtual std::ptrdiff_t inPitch() const { return width_; }
|
||||
|
||||
virtual void draw(void *dst, std::ptrdiff_t dstPitch) {
|
||||
rgb32ToUyvy_(static_cast<gambatte::uint_least32_t *>(dst), dstPitch,
|
||||
inbuf_, width_, width_, height_);
|
||||
}
|
||||
|
||||
private:
|
||||
SimpleArray<gambatte::uint_least32_t> const inbuf_;
|
||||
Rgb32ToUyvy rgb32ToUyvy_;
|
||||
unsigned const width_;
|
||||
unsigned const height_;
|
||||
};
|
||||
|
||||
class Rgb32ToRgb16Link : public VideoLink {
|
||||
public:
|
||||
Rgb32ToRgb16Link(unsigned width, unsigned height)
|
||||
: inbuf_(static_cast<std::size_t>(width) * height)
|
||||
, width_(width)
|
||||
, height_(height)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void * inBuf() const { return inbuf_; }
|
||||
virtual std::ptrdiff_t inPitch() const { return width_; }
|
||||
|
||||
virtual void draw(void *dst, std::ptrdiff_t dstPitch) {
|
||||
if (!inbuf_)
|
||||
return;
|
||||
|
||||
rgb32ToRgb16(static_cast<gambatte::uint_least16_t *>(dst), dstPitch,
|
||||
inbuf_, width_, width_, height_);
|
||||
}
|
||||
|
||||
private:
|
||||
SimpleArray<gambatte::uint_least32_t> const inbuf_;
|
||||
unsigned const width_;
|
||||
unsigned const height_;
|
||||
};
|
||||
|
||||
} // anon namespace
|
||||
|
||||
VideoLink * Rgb32Conv::create(PixelFormat pf, unsigned width, unsigned height) {
|
||||
switch (pf) {
|
||||
case RGB16: return new Rgb32ToRgb16Link(width, height);
|
||||
case UYVY: return new Rgb32ToUyvyLink(width, height);
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef RGB32CONV_H
|
||||
#define RGB32CONV_H
|
||||
|
||||
class VideoLink;
|
||||
|
||||
class Rgb32Conv {
|
||||
public:
|
||||
enum PixelFormat { RGB32, RGB16, UYVY };
|
||||
static VideoLink * create(PixelFormat pf, unsigned width, unsigned height);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,48 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#include "vfilterinfo.h"
|
||||
#include "vfilters/catrom2x.h"
|
||||
#include "vfilters/catrom3x.h"
|
||||
#include "vfilters/kreed2xsai.h"
|
||||
#include "vfilters/maxsthq2x.h"
|
||||
#include "vfilters/maxsthq3x.h"
|
||||
|
||||
static VideoLink * createNone() { return 0; }
|
||||
|
||||
template<class T>
|
||||
static VideoLink * createT() { return new T; }
|
||||
|
||||
#define VFINFO(handle, Type) { handle, Type::out_width, Type::out_height, createT<Type> }
|
||||
|
||||
static VfilterInfo const vfinfos[] = {
|
||||
{ "None", VfilterInfo::in_width, VfilterInfo::in_height, createNone },
|
||||
VFINFO("Bicubic Catmull-Rom spline 2x", Catrom2x),
|
||||
VFINFO("Bicubic Catmull-Rom spline 3x", Catrom3x),
|
||||
VFINFO("Kreed's 2xSaI", Kreed2xSaI),
|
||||
VFINFO("MaxSt's hq2x", MaxStHq2x),
|
||||
VFINFO("MaxSt's hq3x", MaxStHq3x),
|
||||
};
|
||||
|
||||
std::size_t VfilterInfo::numVfilters() {
|
||||
return sizeof vfinfos / sizeof vfinfos[0];
|
||||
}
|
||||
|
||||
VfilterInfo const & VfilterInfo::get(std::size_t n) {
|
||||
return vfinfos[n];
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef VFILTERINFO_H
|
||||
#define VFILTERINFO_H
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
class VideoLink;
|
||||
|
||||
struct VfilterInfo {
|
||||
enum { in_width = 160 };
|
||||
enum { in_height = 144 };
|
||||
|
||||
char const *handle;
|
||||
unsigned outWidth;
|
||||
unsigned outHeight;
|
||||
VideoLink * (*create)();
|
||||
|
||||
static VfilterInfo const & get(std::size_t n);
|
||||
static std::size_t numVfilters();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,179 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#include "catrom2x.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
|
||||
enum { in_width = VfilterInfo::in_width };
|
||||
enum { in_height = VfilterInfo::in_height };
|
||||
enum { in_pitch = in_width + 3 };
|
||||
|
||||
struct Colorsum {
|
||||
gambatte::uint_least32_t r, g, b;
|
||||
};
|
||||
|
||||
static void mergeColumns(gambatte::uint_least32_t *dest, Colorsum const *sums) {
|
||||
for (unsigned w = in_width; w--;) {
|
||||
{
|
||||
gambatte::uint_least32_t rsum = sums[1].r;
|
||||
gambatte::uint_least32_t gsum = sums[1].g;
|
||||
gambatte::uint_least32_t bsum = sums[1].b;
|
||||
|
||||
if (rsum >= 0x80000000) rsum = 0;
|
||||
if (gsum >= 0x80000000) gsum = 0;
|
||||
if (bsum >= 0x80000000) bsum = 0;
|
||||
|
||||
rsum <<= 12;
|
||||
rsum += 0x008000;
|
||||
gsum >>= 4;
|
||||
gsum += 0x0080;
|
||||
bsum += 0x0008;
|
||||
bsum >>= 4;
|
||||
|
||||
if (rsum > 0xFF0000) rsum = 0xFF0000;
|
||||
if (gsum > 0x00FF00) gsum = 0x00FF00;
|
||||
if (bsum > 0x0000FF) bsum = 0x0000FF;
|
||||
|
||||
*dest++ = (rsum & 0xFF0000) | (gsum & 0x00FF00) | bsum;
|
||||
}
|
||||
|
||||
{
|
||||
gambatte::uint_least32_t rsum = sums[1].r * 9;
|
||||
gambatte::uint_least32_t gsum = sums[1].g * 9;
|
||||
gambatte::uint_least32_t bsum = sums[1].b * 9;
|
||||
|
||||
rsum -= sums[0].r;
|
||||
gsum -= sums[0].g;
|
||||
bsum -= sums[0].b;
|
||||
|
||||
rsum += sums[2].r * 9;
|
||||
gsum += sums[2].g * 9;
|
||||
bsum += sums[2].b * 9;
|
||||
|
||||
rsum -= sums[3].r;
|
||||
gsum -= sums[3].g;
|
||||
bsum -= sums[3].b;
|
||||
|
||||
if (rsum >= 0x80000000) rsum = 0;
|
||||
if (gsum >= 0x80000000) gsum = 0;
|
||||
if (bsum >= 0x80000000) bsum = 0;
|
||||
|
||||
rsum <<= 8;
|
||||
rsum += 0x008000;
|
||||
gsum >>= 8;
|
||||
gsum += 0x000080;
|
||||
bsum += 0x000080;
|
||||
bsum >>= 8;
|
||||
|
||||
if (rsum > 0xFF0000) rsum = 0xFF0000;
|
||||
if (gsum > 0x00FF00) gsum = 0x00FF00;
|
||||
if (bsum > 0x0000FF) bsum = 0x0000FF;
|
||||
|
||||
*dest++ = (rsum & 0xFF0000) | (gsum & 0x00FF00) | bsum;
|
||||
}
|
||||
|
||||
++sums;
|
||||
}
|
||||
}
|
||||
|
||||
static void filter(gambatte::uint_least32_t *dline,
|
||||
std::ptrdiff_t const pitch,
|
||||
gambatte::uint_least32_t const *sline)
|
||||
{
|
||||
Colorsum sums[in_pitch];
|
||||
for (unsigned h = in_height; h--;) {
|
||||
{
|
||||
gambatte::uint_least32_t const *s = sline;
|
||||
Colorsum *sum = sums;
|
||||
unsigned n = in_pitch;
|
||||
while (n--) {
|
||||
unsigned long pixel = *s;
|
||||
sum->r = pixel >> 12 & 0x000FF0 ;
|
||||
pixel <<= 4;
|
||||
sum->g = pixel & 0x0FF000;
|
||||
sum->b = pixel & 0x000FF0;
|
||||
|
||||
++s;
|
||||
++sum;
|
||||
}
|
||||
}
|
||||
|
||||
mergeColumns(dline, sums);
|
||||
dline += pitch;
|
||||
|
||||
{
|
||||
gambatte::uint_least32_t const *s = sline;
|
||||
Colorsum *sum = sums;
|
||||
unsigned n = in_pitch;
|
||||
while (n--) {
|
||||
unsigned long pixel = *s;
|
||||
unsigned long rsum = (pixel >> 16) * 9;
|
||||
unsigned long gsum = (pixel & 0x00FF00) * 9;
|
||||
unsigned long bsum = (pixel & 0x0000FF) * 9;
|
||||
|
||||
pixel = s[-1 * in_pitch];
|
||||
rsum -= pixel >> 16;
|
||||
gsum -= pixel & 0x00FF00;
|
||||
bsum -= pixel & 0x0000FF;
|
||||
|
||||
pixel = s[1 * in_pitch];
|
||||
rsum += (pixel >> 16) * 9;
|
||||
gsum += (pixel & 0x00FF00) * 9;
|
||||
bsum += (pixel & 0x0000FF) * 9;
|
||||
|
||||
pixel = s[2 * in_pitch];
|
||||
rsum -= pixel >> 16;
|
||||
gsum -= pixel & 0x00FF00;
|
||||
bsum -= pixel & 0x0000FF;
|
||||
|
||||
sum->r = rsum;
|
||||
sum->g = gsum;
|
||||
sum->b = bsum;
|
||||
|
||||
++s;
|
||||
++sum;
|
||||
}
|
||||
}
|
||||
|
||||
mergeColumns(dline, sums);
|
||||
dline += pitch;
|
||||
sline += in_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
} // anon namespace
|
||||
|
||||
Catrom2x::Catrom2x()
|
||||
: buffer_((in_height + 3UL) * in_pitch)
|
||||
{
|
||||
std::fill_n(buffer_.get(), buffer_.size(), 0);
|
||||
}
|
||||
|
||||
void * Catrom2x::inBuf() const {
|
||||
return buffer_ + in_pitch + 1;
|
||||
}
|
||||
|
||||
std::ptrdiff_t Catrom2x::inPitch() const {
|
||||
return in_pitch;
|
||||
}
|
||||
|
||||
void Catrom2x::draw(void *dbuffer, std::ptrdiff_t pitch) {
|
||||
::filter(static_cast<gambatte::uint_least32_t *>(dbuffer), pitch, buffer_ + in_pitch);
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef CATROM2X_H
|
||||
#define CATROM2X_H
|
||||
|
||||
#include "../videolink.h"
|
||||
#include "../vfilterinfo.h"
|
||||
#include "array.h"
|
||||
#include "gbint.h"
|
||||
|
||||
class Catrom2x : public VideoLink {
|
||||
public:
|
||||
enum { out_width = VfilterInfo::in_width * 2 };
|
||||
enum { out_height = VfilterInfo::in_height * 2 };
|
||||
|
||||
Catrom2x();
|
||||
virtual void * inBuf() const;
|
||||
virtual std::ptrdiff_t inPitch() const;
|
||||
virtual void draw(void *dst, std::ptrdiff_t dstpitch);
|
||||
|
||||
private:
|
||||
Array<gambatte::uint_least32_t> const buffer_;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,345 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#include "catrom3x.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
|
||||
enum { in_width = VfilterInfo::in_width };
|
||||
enum { in_height = VfilterInfo::in_height };
|
||||
enum { in_pitch = in_width + 3 };
|
||||
|
||||
struct Colorsum {
|
||||
gambatte::uint_least32_t r, g, b;
|
||||
};
|
||||
|
||||
static void mergeColumns(gambatte::uint_least32_t *dest, Colorsum const *sums) {
|
||||
for (unsigned w = in_width; w--;) {
|
||||
{
|
||||
gambatte::uint_least32_t rsum = sums[1].r;
|
||||
gambatte::uint_least32_t gsum = sums[1].g;
|
||||
gambatte::uint_least32_t bsum = sums[1].b;
|
||||
|
||||
if (rsum >= 0x80000000) {
|
||||
rsum = 0;
|
||||
} else if (rsum > 6869) {
|
||||
rsum = 0xFF0000;
|
||||
} else {
|
||||
rsum *= 607;
|
||||
rsum <<= 2;
|
||||
rsum += 0x008000;
|
||||
rsum &= 0xFF0000;
|
||||
}
|
||||
|
||||
if (gsum >= 0x80000000) {
|
||||
gsum = 0;
|
||||
} else if (gsum > 1758567) {
|
||||
gsum = 0xFF00;
|
||||
} else {
|
||||
gsum *= 607;
|
||||
gsum >>= 14;
|
||||
gsum += 0x000080;
|
||||
gsum &= 0x00FF00;
|
||||
}
|
||||
|
||||
if (bsum >= 0x80000000) {
|
||||
bsum = 0;
|
||||
} else if (bsum > 6869) {
|
||||
bsum = 0xFF;
|
||||
} else {
|
||||
bsum *= 607;
|
||||
bsum += 8192;
|
||||
bsum >>= 14;
|
||||
}
|
||||
|
||||
/*rsum/=27;
|
||||
rsum<<=8;
|
||||
gsum/=27;
|
||||
gsum<<=5;
|
||||
bsum<<=4;
|
||||
bsum+=27;
|
||||
bsum/=54;
|
||||
rsum+=0x008000;
|
||||
gsum+=0x000080;
|
||||
|
||||
if(rsum>0xFF0000) rsum=0xFF0000;
|
||||
if(gsum>0x00FF00) gsum=0x00FF00;
|
||||
if(bsum>0x0000FF) bsum=0x0000FF;*/
|
||||
|
||||
*dest++ = rsum/*&0xFF0000*/ | gsum/*&0x00FF00*/ | bsum;
|
||||
}
|
||||
{
|
||||
gambatte::uint_least32_t rsum = sums[1].r * 21;
|
||||
gambatte::uint_least32_t gsum = sums[1].g * 21;
|
||||
gambatte::uint_least32_t bsum = sums[1].b * 21;
|
||||
|
||||
rsum -= sums[0].r << 1;
|
||||
gsum -= sums[0].g << 1;
|
||||
bsum -= sums[0].b << 1;
|
||||
|
||||
rsum += sums[2].r * 9;
|
||||
gsum += sums[2].g * 9;
|
||||
bsum += sums[2].b * 9;
|
||||
|
||||
rsum -= sums[3].r;
|
||||
gsum -= sums[3].g;
|
||||
bsum -= sums[3].b;
|
||||
|
||||
if (rsum >= 0x80000000) {
|
||||
rsum = 0;
|
||||
} else if (rsum > 185578) {
|
||||
rsum = 0xFF0000;
|
||||
} else {
|
||||
rsum *= 719;
|
||||
rsum >>= 3;
|
||||
rsum += 0x008000;
|
||||
rsum &= 0xFF0000;
|
||||
}
|
||||
|
||||
if (gsum >= 0x80000000) {
|
||||
gsum = 0;
|
||||
} else if (gsum > 47508223) {
|
||||
gsum = 0x00FF00;
|
||||
} else {
|
||||
gsum >>= 8;
|
||||
gsum *= 719;
|
||||
gsum >>= 11;
|
||||
gsum += 0x000080;
|
||||
gsum &= 0x00FF00;
|
||||
}
|
||||
|
||||
if (bsum >= 0x80000000) {
|
||||
bsum = 0;
|
||||
} else if (bsum > 185578) {
|
||||
bsum = 0x0000FF;
|
||||
} else {
|
||||
bsum *= 719;
|
||||
bsum += 0x040000;
|
||||
bsum >>= 19;
|
||||
}
|
||||
|
||||
/*rsum/=729;
|
||||
rsum<<=8;
|
||||
gsum/=729;
|
||||
gsum<<=5;
|
||||
bsum<<=4;
|
||||
bsum+=729;
|
||||
bsum/=1458;
|
||||
rsum+=0x008000;
|
||||
gsum+=0x000080;
|
||||
|
||||
if(rsum>0xFF0000) rsum=0xFF0000;
|
||||
if(gsum>0x00FF00) gsum=0x00FF00;
|
||||
if(bsum>0x0000FF) bsum=0x0000FF;*/
|
||||
|
||||
*dest++ = rsum/*&0xFF0000*/ | gsum/*&0x00FF00*/ | bsum;
|
||||
}
|
||||
{
|
||||
gambatte::uint_least32_t rsum = sums[1].r * 9;
|
||||
gambatte::uint_least32_t gsum = sums[1].g * 9;
|
||||
gambatte::uint_least32_t bsum = sums[1].b * 9;
|
||||
|
||||
rsum -= sums[0].r;
|
||||
gsum -= sums[0].g;
|
||||
bsum -= sums[0].b;
|
||||
|
||||
rsum += sums[2].r * 21;
|
||||
gsum += sums[2].g * 21;
|
||||
bsum += sums[2].b * 21;
|
||||
|
||||
rsum -= sums[3].r << 1;
|
||||
gsum -= sums[3].g << 1;
|
||||
bsum -= sums[3].b << 1;
|
||||
|
||||
if (rsum >= 0x80000000) {
|
||||
rsum = 0;
|
||||
} else if (rsum > 185578) {
|
||||
rsum = 0xFF0000;
|
||||
} else {
|
||||
rsum *= 719;
|
||||
rsum >>= 3;
|
||||
rsum += 0x008000;
|
||||
rsum &= 0xFF0000;
|
||||
}
|
||||
|
||||
if (gsum >= 0x80000000) {
|
||||
gsum = 0;
|
||||
} else if (gsum > 47508223) {
|
||||
gsum = 0xFF00;
|
||||
} else {
|
||||
gsum >>= 8;
|
||||
gsum *= 719;
|
||||
gsum >>= 11;
|
||||
gsum += 0x000080;
|
||||
gsum &= 0x00FF00;
|
||||
}
|
||||
|
||||
if (bsum >= 0x80000000) {
|
||||
bsum = 0;
|
||||
} else if (bsum > 185578) {
|
||||
bsum = 0x0000FF;
|
||||
} else {
|
||||
bsum *= 719;
|
||||
bsum += 0x040000;
|
||||
bsum >>= 19;
|
||||
}
|
||||
|
||||
/*rsum/=729;
|
||||
rsum<<=8;
|
||||
gsum/=729;
|
||||
gsum<<=5;
|
||||
bsum<<=4;
|
||||
bsum+=729;
|
||||
bsum/=1458;
|
||||
rsum+=0x008000;
|
||||
gsum+=0x000080;
|
||||
|
||||
if(rsum>0xFF0000) rsum=0xFF0000;
|
||||
if(gsum>0x00FF00) gsum=0x00FF00;
|
||||
if(bsum>0x0000FF) bsum=0x0000FF;*/
|
||||
|
||||
*dest++ = rsum/*&0xFF0000*/ | gsum/*&0x00FF00*/ | bsum;
|
||||
}
|
||||
|
||||
++sums;
|
||||
}
|
||||
}
|
||||
|
||||
static void filter(gambatte::uint_least32_t *dline,
|
||||
std::ptrdiff_t const pitch,
|
||||
gambatte::uint_least32_t const *sline)
|
||||
{
|
||||
Colorsum sums[in_pitch];
|
||||
for (unsigned h = in_height; h--;) {
|
||||
{
|
||||
gambatte::uint_least32_t const *s = sline;
|
||||
Colorsum *sum = sums;
|
||||
unsigned n = in_pitch;
|
||||
while (n--) {
|
||||
unsigned long const pixel = *s;
|
||||
sum->r = (pixel >> 16) * 27;
|
||||
sum->g = (pixel & 0x00FF00) * 27;
|
||||
sum->b = (pixel & 0x0000FF) * 27;
|
||||
|
||||
++s;
|
||||
++sum;
|
||||
}
|
||||
}
|
||||
|
||||
mergeColumns(dline, sums);
|
||||
dline += pitch;
|
||||
|
||||
{
|
||||
gambatte::uint_least32_t const *s = sline;
|
||||
Colorsum *sum = sums;
|
||||
unsigned n = in_pitch;
|
||||
while (n--) {
|
||||
unsigned long pixel = *s;
|
||||
unsigned long rsum = (pixel >> 16) * 21;
|
||||
unsigned long gsum = (pixel & 0x00FF00) * 21;
|
||||
unsigned long bsum = (pixel & 0x0000FF) * 21;
|
||||
|
||||
pixel = s[-1 * in_pitch];
|
||||
rsum -= (pixel >> 16) << 1;
|
||||
pixel <<= 1;
|
||||
gsum -= pixel & 0x01FE00;
|
||||
bsum -= pixel & 0x0001FE;
|
||||
|
||||
pixel = s[1 * in_pitch];
|
||||
rsum += (pixel >> 16) * 9;
|
||||
gsum += (pixel & 0x00FF00) * 9;
|
||||
bsum += (pixel & 0x0000FF) * 9;
|
||||
|
||||
pixel = s[2 * in_pitch];
|
||||
rsum -= pixel >> 16;
|
||||
gsum -= pixel & 0x00FF00;
|
||||
bsum -= pixel & 0x0000FF;
|
||||
|
||||
sum->r = rsum;
|
||||
sum->g = gsum;
|
||||
sum->b = bsum;
|
||||
|
||||
++s;
|
||||
++sum;
|
||||
}
|
||||
}
|
||||
|
||||
mergeColumns(dline, sums);
|
||||
dline += pitch;
|
||||
|
||||
{
|
||||
gambatte::uint_least32_t const *s = sline;
|
||||
Colorsum *sum = sums;
|
||||
unsigned n = in_pitch;
|
||||
while (n--) {
|
||||
unsigned long pixel = *s;
|
||||
unsigned long rsum = (pixel >> 16) * 9;
|
||||
unsigned long gsum = (pixel & 0x00FF00) * 9;
|
||||
unsigned long bsum = (pixel & 0x0000FF) * 9;
|
||||
|
||||
pixel = s[-1 * in_pitch];
|
||||
rsum -= pixel >> 16;
|
||||
gsum -= pixel & 0x00FF00;
|
||||
bsum -= pixel & 0x0000FF;
|
||||
|
||||
pixel = s[1 * in_pitch];
|
||||
rsum += (pixel >> 16) * 21;
|
||||
gsum += (pixel & 0x00FF00) * 21;
|
||||
bsum += (pixel & 0x0000FF) * 21;
|
||||
|
||||
pixel = s[2 * in_pitch];
|
||||
rsum -= (pixel >> 16) << 1;
|
||||
pixel <<= 1;
|
||||
gsum -= pixel & 0x01FE00;
|
||||
bsum -= pixel & 0x0001FE;
|
||||
|
||||
sum->r = rsum;
|
||||
sum->g = gsum;
|
||||
sum->b = bsum;
|
||||
|
||||
++s;
|
||||
++sum;
|
||||
}
|
||||
}
|
||||
|
||||
mergeColumns(dline, sums);
|
||||
dline += pitch;
|
||||
sline += in_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
} // anon namespace
|
||||
|
||||
Catrom3x::Catrom3x()
|
||||
: buffer_((in_height + 3UL) * in_pitch)
|
||||
{
|
||||
std::fill_n(buffer_.get(), buffer_.size(), 0);
|
||||
}
|
||||
|
||||
void * Catrom3x::inBuf() const {
|
||||
return buffer_ + in_pitch + 1;
|
||||
}
|
||||
|
||||
std::ptrdiff_t Catrom3x::inPitch() const {
|
||||
return in_pitch;
|
||||
}
|
||||
|
||||
void Catrom3x::draw(void *dbuffer, std::ptrdiff_t pitch) {
|
||||
::filter(static_cast<gambatte::uint_least32_t *>(dbuffer), pitch, buffer_ + in_pitch);
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef CATROM3X_H
|
||||
#define CATROM3X_H
|
||||
|
||||
#include "../videolink.h"
|
||||
#include "../vfilterinfo.h"
|
||||
#include "array.h"
|
||||
#include "gbint.h"
|
||||
|
||||
class Catrom3x : public VideoLink {
|
||||
public:
|
||||
enum { out_width = VfilterInfo::in_width * 3 };
|
||||
enum { out_height = VfilterInfo::in_height * 3 };
|
||||
|
||||
Catrom3x();
|
||||
virtual void * inBuf() const;
|
||||
virtual std::ptrdiff_t inPitch() const;
|
||||
virtual void draw(void *dst, std::ptrdiff_t dstpitch);
|
||||
|
||||
private:
|
||||
Array<gambatte::uint_least32_t> const buffer_;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,233 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* Copyright (C) 1999 Derek Liauw Kie Fa (Kreed) *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#include "kreed2xsai.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
|
||||
static int getResult1(unsigned long const a,
|
||||
unsigned long const b,
|
||||
unsigned long const c,
|
||||
unsigned long const d)
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int r = 0;
|
||||
|
||||
if (a == c) ++x;
|
||||
else if (b == c) ++y;
|
||||
|
||||
if (a == d) ++x;
|
||||
else if (b == d) ++y;
|
||||
|
||||
if (x <= 1) ++r;
|
||||
if (y <= 1) --r;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int getResult2(unsigned long const a,
|
||||
unsigned long const b,
|
||||
unsigned long const c,
|
||||
unsigned long const d)
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int r = 0;
|
||||
|
||||
if (a == c) ++x;
|
||||
else if (b == c) ++y;
|
||||
|
||||
if (a == d) ++x;
|
||||
else if (b == d) ++y;
|
||||
|
||||
if (x <= 1) --r;
|
||||
if (y <= 1) ++r;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static unsigned long interpolate(unsigned long a, unsigned long b) {
|
||||
return (a + b - ((a ^ b) & 0x010101)) >> 1;
|
||||
}
|
||||
|
||||
static unsigned long qInterpolate(unsigned long const a,
|
||||
unsigned long const b,
|
||||
unsigned long const c,
|
||||
unsigned long const d)
|
||||
{
|
||||
unsigned long lowBits = ((a & 0x030303)
|
||||
+ (b & 0x030303)
|
||||
+ (c & 0x030303)
|
||||
+ (d & 0x030303)) & 0x030303;
|
||||
return (a + b + c + d - lowBits) >> 2;
|
||||
}
|
||||
|
||||
template<std::ptrdiff_t srcPitch, unsigned width, unsigned height>
|
||||
static void filter(gambatte::uint_least32_t *dstPtr,
|
||||
std::ptrdiff_t const dstPitch,
|
||||
gambatte::uint_least32_t const *srcPtr)
|
||||
{
|
||||
for (unsigned h = height; h--;) {
|
||||
gambatte::uint_least32_t const *bP = srcPtr;
|
||||
gambatte::uint_least32_t *dP = dstPtr;
|
||||
for (unsigned w = width; w--;) {
|
||||
unsigned long colorA, colorB, colorC, colorD,
|
||||
colorE, colorF, colorG, colorH,
|
||||
colorI, colorJ, colorK, colorL,
|
||||
colorM, colorN, colorO/*, colorP*/;
|
||||
|
||||
//---------------------------------------
|
||||
// Map of the pixels: I|E F|J
|
||||
// G|A B|K
|
||||
// H|C D|L
|
||||
// M|N O|P
|
||||
|
||||
colorI = *(bP - srcPitch - 1);
|
||||
colorE = *(bP - srcPitch );
|
||||
colorF = *(bP - srcPitch + 1);
|
||||
colorJ = *(bP - srcPitch + 2);
|
||||
|
||||
colorG = *(bP - 1);
|
||||
colorA = *(bP );
|
||||
colorB = *(bP + 1);
|
||||
colorK = *(bP + 2);
|
||||
|
||||
colorH = *(bP + srcPitch - 1);
|
||||
colorC = *(bP + srcPitch );
|
||||
colorD = *(bP + srcPitch + 1);
|
||||
colorL = *(bP + srcPitch + 2);
|
||||
|
||||
colorM = *(bP + srcPitch * 2 - 1);
|
||||
colorN = *(bP + srcPitch * 2 );
|
||||
colorO = *(bP + srcPitch * 2 + 1);
|
||||
// colorP = *(bP + srcPitch * 2 + 2);
|
||||
|
||||
unsigned long product0, product1, product2;
|
||||
if (colorA == colorD && colorB != colorC) {
|
||||
product0 = (colorA == colorE && colorB == colorL)
|
||||
|| (colorA == colorC && colorA == colorF
|
||||
&& colorB != colorE && colorB == colorJ)
|
||||
? colorA
|
||||
: interpolate(colorA, colorB);
|
||||
product1 = (colorA == colorG && colorC == colorO)
|
||||
|| (colorA == colorB && colorA == colorH
|
||||
&& colorG != colorC && colorC == colorM)
|
||||
? colorA
|
||||
: interpolate(colorA, colorC);
|
||||
product2 = colorA;
|
||||
} else if (colorB == colorC && colorA != colorD) {
|
||||
product0 = (colorB == colorF && colorA == colorH)
|
||||
|| (colorB == colorE && colorB == colorD
|
||||
&& colorA != colorF && colorA == colorI)
|
||||
? colorB
|
||||
: interpolate(colorA, colorB);
|
||||
product1 = (colorC == colorH && colorA == colorF)
|
||||
|| (colorC == colorG && colorC == colorD
|
||||
&& colorA != colorH && colorA == colorI)
|
||||
? colorC
|
||||
: interpolate(colorA, colorC);
|
||||
product2 = colorB;
|
||||
} else if (colorA == colorD && colorB == colorC) {
|
||||
if (colorA == colorB) {
|
||||
product0 = colorA;
|
||||
product1 = colorA;
|
||||
product2 = colorA;
|
||||
} else {
|
||||
product0 = interpolate(colorA, colorB);
|
||||
product1 = interpolate(colorA, colorC);
|
||||
|
||||
int r = 0;
|
||||
r += getResult1(colorA, colorB, colorG, colorE);
|
||||
r += getResult2(colorB, colorA, colorK, colorF);
|
||||
r += getResult2(colorB, colorA, colorH, colorN);
|
||||
r += getResult1(colorA, colorB, colorL, colorO);
|
||||
if (r > 0) {
|
||||
product2 = colorA;
|
||||
} else if (r < 0) {
|
||||
product2 = colorB;
|
||||
} else {
|
||||
product2 = qInterpolate(colorA, colorB, colorC, colorD);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
product2 = qInterpolate(colorA, colorB, colorC, colorD);
|
||||
|
||||
if (colorA == colorC && colorA == colorF
|
||||
&& colorB != colorE && colorB == colorJ) {
|
||||
product0 = colorA;
|
||||
} else if (colorB == colorE && colorB == colorD
|
||||
&& colorA != colorF && colorA == colorI) {
|
||||
product0 = colorB;
|
||||
} else {
|
||||
product0 = interpolate(colorA, colorB);
|
||||
}
|
||||
|
||||
if (colorA == colorB && colorA == colorH
|
||||
&& colorG != colorC && colorC == colorM) {
|
||||
product1 = colorA;
|
||||
} else if (colorC == colorG && colorC == colorD
|
||||
&& colorA != colorH && colorA == colorI) {
|
||||
product1 = colorC;
|
||||
} else {
|
||||
product1 = interpolate(colorA, colorC);
|
||||
}
|
||||
}
|
||||
|
||||
*(dP ) = colorA;
|
||||
*(dP + 1) = product0;
|
||||
*(dP + dstPitch ) = product1;
|
||||
*(dP + dstPitch + 1) = product2;
|
||||
dP += 2;
|
||||
++bP;
|
||||
}
|
||||
|
||||
srcPtr += srcPitch;
|
||||
dstPtr += dstPitch * 2;
|
||||
}
|
||||
}
|
||||
|
||||
enum { in_width = VfilterInfo::in_width };
|
||||
enum { in_height = VfilterInfo::in_height };
|
||||
enum { in_pitch = in_width + 3 };
|
||||
enum { buf_size = (in_height + 3ul) * in_pitch };
|
||||
enum { buf_offset = in_pitch + 1 };
|
||||
|
||||
} // anon namespace
|
||||
|
||||
Kreed2xSaI::Kreed2xSaI()
|
||||
: buffer_(buf_size)
|
||||
{
|
||||
std::fill_n(buffer_.get(), buffer_.size(), 0);
|
||||
}
|
||||
|
||||
void * Kreed2xSaI::inBuf() const {
|
||||
return buffer_ + buf_offset;
|
||||
}
|
||||
|
||||
std::ptrdiff_t Kreed2xSaI::inPitch() const {
|
||||
return in_pitch;
|
||||
}
|
||||
|
||||
void Kreed2xSaI::draw(void *dbuffer, std::ptrdiff_t dpitch) {
|
||||
::filter<in_pitch, in_width, in_height>(static_cast<gambatte::uint_least32_t *>(dbuffer),
|
||||
dpitch, buffer_ + buf_offset);
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef KREED2XSAI_H
|
||||
#define KREED2XSAI_H
|
||||
|
||||
#include "../videolink.h"
|
||||
#include "../vfilterinfo.h"
|
||||
#include "array.h"
|
||||
#include "gbint.h"
|
||||
|
||||
class Kreed2xSaI : public VideoLink {
|
||||
public:
|
||||
enum { out_width = VfilterInfo::in_width * 2 };
|
||||
enum { out_height = VfilterInfo::in_height * 2 };
|
||||
|
||||
Kreed2xSaI();
|
||||
virtual void * inBuf() const;
|
||||
virtual std::ptrdiff_t inPitch() const;
|
||||
virtual void draw(void *dst, std::ptrdiff_t dstpitch);
|
||||
|
||||
private:
|
||||
Array<gambatte::uint_least32_t> const buffer_;
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,41 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef MAXSTHQ2X_H
|
||||
#define MAXSTHQ2X_H
|
||||
|
||||
#include "../videolink.h"
|
||||
#include "../vfilterinfo.h"
|
||||
#include "array.h"
|
||||
#include "gbint.h"
|
||||
|
||||
class MaxStHq2x : public VideoLink {
|
||||
public:
|
||||
enum { out_width = VfilterInfo::in_width * 2 };
|
||||
enum { out_height = VfilterInfo::in_height * 2 };
|
||||
|
||||
MaxStHq2x();
|
||||
virtual void * inBuf() const;
|
||||
virtual std::ptrdiff_t inPitch() const;
|
||||
virtual void draw(void *dst, std::ptrdiff_t dstpitch);
|
||||
|
||||
private:
|
||||
SimpleArray<gambatte::uint_least32_t> const buffer_;
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,41 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef MAXSTHQ3X_H
|
||||
#define MAXSTHQ3X_H
|
||||
|
||||
#include "../videolink.h"
|
||||
#include "../vfilterinfo.h"
|
||||
#include "array.h"
|
||||
#include "gbint.h"
|
||||
|
||||
class MaxStHq3x : public VideoLink {
|
||||
public:
|
||||
enum { out_width = VfilterInfo::in_width * 3 };
|
||||
enum { out_height = VfilterInfo::in_height * 3 };
|
||||
|
||||
MaxStHq3x();
|
||||
virtual void * inBuf() const;
|
||||
virtual std::ptrdiff_t inPitch() const;
|
||||
virtual void draw(void *dst, std::ptrdiff_t dstpitch);
|
||||
|
||||
private:
|
||||
SimpleArray<gambatte::uint_least32_t> const buffer_;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,32 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2009 by Sindre Aamås *
|
||||
* sinamas@users.sourceforge.net *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* 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 version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef VIDEOLINK_H
|
||||
#define VIDEOLINK_H
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
class VideoLink {
|
||||
public:
|
||||
virtual ~VideoLink() {}
|
||||
virtual void * inBuf() const = 0;
|
||||
virtual std::ptrdiff_t inPitch() const = 0;
|
||||
virtual void draw(void *dst, std::ptrdiff_t dstpitch) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
+506
-506
File diff suppressed because it is too large
Load Diff
@@ -1,56 +0,0 @@
|
||||
global_cflags = ARGUMENTS.get('CFLAGS', '-Wall -Wextra -O2 -fomit-frame-pointer')
|
||||
global_cxxflags = ARGUMENTS.get('CXXFLAGS', global_cflags + ' -fno-exceptions -fno-rtti')
|
||||
global_defines = ' -DHAVE_STDINT_H'
|
||||
vars = Variables()
|
||||
vars.Add('CC')
|
||||
vars.Add('CXX')
|
||||
|
||||
env = Environment(CPPPATH = ['src', 'include', '../common'],
|
||||
CFLAGS = global_cflags + global_defines,
|
||||
CXXFLAGS = global_cxxflags + global_defines,
|
||||
variables = vars)
|
||||
|
||||
sourceFiles = Split('''
|
||||
src/bitmap_font.cpp
|
||||
src/cpu.cpp
|
||||
src/gambatte.cpp
|
||||
src/initstate.cpp
|
||||
src/interrupter.cpp
|
||||
src/interruptrequester.cpp
|
||||
src/loadres.cpp
|
||||
src/memory.cpp
|
||||
src/sound.cpp
|
||||
src/state_osd_elements.cpp
|
||||
src/statesaver.cpp
|
||||
src/tima.cpp
|
||||
src/video.cpp
|
||||
src/mem/cartridge.cpp
|
||||
src/mem/memptrs.cpp
|
||||
src/mem/pakinfo.cpp
|
||||
src/mem/rtc.cpp
|
||||
src/sound/channel1.cpp
|
||||
src/sound/channel2.cpp
|
||||
src/sound/channel3.cpp
|
||||
src/sound/channel4.cpp
|
||||
src/sound/duty_unit.cpp
|
||||
src/sound/envelope_unit.cpp
|
||||
src/sound/length_counter.cpp
|
||||
src/video/ly_counter.cpp
|
||||
src/video/lyc_irq.cpp
|
||||
src/video/next_m0_time.cpp
|
||||
src/video/ppu.cpp
|
||||
src/video/sprite_mapper.cpp
|
||||
''')
|
||||
|
||||
conf = env.Configure()
|
||||
|
||||
if conf.CheckHeader('zlib.h'):
|
||||
sourceFiles.append('src/file/unzip/unzip.c')
|
||||
sourceFiles.append('src/file/unzip/ioapi.c')
|
||||
sourceFiles.append('src/file/file_zip.cpp')
|
||||
else:
|
||||
sourceFiles.append('src/file/file.cpp')
|
||||
|
||||
conf.Finish()
|
||||
|
||||
env.Library('gambatte', sourceFiles)
|
||||
@@ -1,222 +0,0 @@
|
||||
/***************************************************************************
|
||||
Copyright (C) 2007 by Nach
|
||||
http://nsrt.edgeemu.com
|
||||
|
||||
Copyright (C) 2007-2011 by sinamas <sinamas at users.sourceforge.net>
|
||||
sinamas@users.sourceforge.net
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
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 version 2 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
version 2 along with this program; if not, write to the
|
||||
Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
***************************************************************************/
|
||||
#include "stdfile.h"
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
|
||||
namespace zlib {
|
||||
#include "unzip/unzip.h"
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class ZipFile : public gambatte::File {
|
||||
private:
|
||||
std::size_t fsize, count;
|
||||
void *zipfile;
|
||||
bool zip_sub_open;
|
||||
|
||||
void zip(const char *filename);
|
||||
|
||||
public:
|
||||
ZipFile(const char *filename);
|
||||
virtual ~ZipFile();
|
||||
virtual void rewind();
|
||||
bool is_open() const;
|
||||
virtual void close();
|
||||
virtual std::size_t size() const { return fsize; };
|
||||
virtual void read(char *buffer, std::size_t amount);
|
||||
std::size_t gcount() const { return count; }
|
||||
virtual bool fail() const { return !is_open(); }
|
||||
};
|
||||
|
||||
using namespace std;
|
||||
using namespace zlib;
|
||||
|
||||
static const unsigned int MAX_FILE_NAME = 512;
|
||||
|
||||
ZipFile::ZipFile(const char *filename) : fsize(0), count(0)
|
||||
{
|
||||
zip(filename);
|
||||
}
|
||||
|
||||
void ZipFile::zip(const char *filename)
|
||||
{
|
||||
zipfile = unzOpen(filename);
|
||||
if (zipfile)
|
||||
{
|
||||
zip_sub_open = false;
|
||||
|
||||
unz_file_info cFileInfo;
|
||||
char ourFile[MAX_FILE_NAME] = { '\n' };
|
||||
|
||||
for (int cFile = unzGoToFirstFile((unzFile)zipfile); cFile == UNZ_OK; cFile = unzGoToNextFile((unzFile)zipfile))
|
||||
{
|
||||
//Temporary char array for file name
|
||||
char cFileName[MAX_FILE_NAME];
|
||||
|
||||
//Gets info on current file, and places it in cFileInfo
|
||||
unzGetCurrentFileInfo((unzFile)zipfile, &cFileInfo, cFileName, MAX_FILE_NAME, 0, 0, 0, 0);
|
||||
|
||||
//Check for largest file which should be the ROM
|
||||
if ((size_t)cFileInfo.uncompressed_size > fsize)
|
||||
{
|
||||
strcpy(ourFile, cFileName);
|
||||
fsize = (size_t)cFileInfo.uncompressed_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (ourFile[0] != '\n')
|
||||
{
|
||||
//Sets current file to the file we liked before
|
||||
unzLocateFile((unzFile)zipfile, ourFile, 1);
|
||||
|
||||
if (unzOpenCurrentFile((unzFile)zipfile) == UNZ_OK)
|
||||
{
|
||||
zip_sub_open = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!zip_sub_open)
|
||||
{
|
||||
unzClose((unzFile)zipfile);
|
||||
zipfile = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ZipFile::~ZipFile()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void ZipFile::rewind()
|
||||
{
|
||||
if (is_open())
|
||||
{
|
||||
unzCloseCurrentFile((unzFile)zipfile);
|
||||
unzOpenCurrentFile((unzFile)zipfile);
|
||||
}
|
||||
}
|
||||
|
||||
bool ZipFile::is_open() const
|
||||
{
|
||||
return(zipfile && zip_sub_open);
|
||||
}
|
||||
|
||||
void ZipFile::close()
|
||||
{
|
||||
if (is_open())
|
||||
{
|
||||
unzOpenCurrentFile((unzFile)zipfile);
|
||||
unzClose((unzFile)zipfile);
|
||||
zipfile = 0;
|
||||
zip_sub_open = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ZipFile::read(char *buffer, size_t amount)
|
||||
{
|
||||
if (is_open())
|
||||
{
|
||||
count = (size_t)unzReadCurrentFile((unzFile)zipfile, buffer, amount);
|
||||
}
|
||||
else
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
class GzFile : public gambatte::File {
|
||||
public:
|
||||
explicit GzFile(char const *filename)
|
||||
: file_(gzopen(filename, "rb"))
|
||||
, fsize_(0)
|
||||
{
|
||||
if (file_) {
|
||||
char buf[256];
|
||||
int ret;
|
||||
|
||||
while ((ret = gzread(file_, buf, sizeof buf)) > 0)
|
||||
fsize_ += ret;
|
||||
|
||||
if (ret < 0) {
|
||||
close();
|
||||
fsize_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
rewind();
|
||||
}
|
||||
|
||||
virtual ~GzFile() { close(); }
|
||||
|
||||
virtual void rewind() {
|
||||
if (file_ && gzrewind(file_) < 0)
|
||||
close();
|
||||
}
|
||||
|
||||
virtual std::size_t size() const { return fsize_; };
|
||||
|
||||
virtual void read(char *buffer, std::size_t amount) {
|
||||
if (file_ && gzread(file_, buffer, amount) < 0)
|
||||
close();
|
||||
}
|
||||
|
||||
virtual bool fail() const { return !file_; }
|
||||
|
||||
private:
|
||||
gzFile file_;
|
||||
std::size_t fsize_;
|
||||
|
||||
GzFile(GzFile const &);
|
||||
GzFile & operator=(GzFile const &);
|
||||
void close();
|
||||
};
|
||||
|
||||
void GzFile::close() {
|
||||
if (file_) {
|
||||
gzclose(file_);
|
||||
file_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Avoid checking magic header values, because there are no values that cannot occur in a GB ROM.
|
||||
transfer_ptr<gambatte::File> gambatte::newFileInstance(std::string const &filepath) {
|
||||
std::size_t const extpos = filepath.rfind('.');
|
||||
|
||||
if (extpos != std::string::npos) {
|
||||
std::string const &ext = filepath.substr(extpos + 1);
|
||||
|
||||
if (ext.length() == 3 && std::tolower(ext[0]) == 'z'
|
||||
&& std::tolower(ext[1]) == 'i' && std::tolower(ext[2]) == 'p') {
|
||||
return transfer_ptr<File>(new ZipFile(filepath.c_str()));
|
||||
}
|
||||
|
||||
if (!ext.empty() && std::tolower(ext[ext.length() - 1]) == 'z')
|
||||
return transfer_ptr<File>(new GzFile(filepath.c_str()));
|
||||
}
|
||||
|
||||
return transfer_ptr<File>(new StdFile(filepath.c_str()));
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
/* crypt.h -- base code for crypt/uncrypt ZIPfile
|
||||
|
||||
|
||||
Version 1.01e, February 12th, 2005
|
||||
|
||||
Copyright (C) 1998-2005 Gilles Vollant
|
||||
|
||||
This code is a modified version of crypting code in Infozip distribution
|
||||
|
||||
The encryption/decryption parts of this source code (as opposed to the
|
||||
non-echoing password parts) were originally written in Europe. The
|
||||
whole source package can be freely distributed, including from the USA.
|
||||
(Prior to January 2000, re-export from the US was a violation of US law.)
|
||||
|
||||
This encryption code is a direct transcription of the algorithm from
|
||||
Roger Schlafly, described by Phil Katz in the file appnote.txt. This
|
||||
file (appnote.txt) is distributed with the PKZIP program (even in the
|
||||
version without encryption capabilities).
|
||||
|
||||
If you don't need crypting in your application, just define symbols
|
||||
NOCRYPT and NOUNCRYPT.
|
||||
|
||||
This code support the "Traditional PKWARE Encryption".
|
||||
|
||||
The new AES encryption added on Zip format by Winzip (see the page
|
||||
http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
|
||||
Encryption is not supported.
|
||||
*/
|
||||
|
||||
#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
|
||||
|
||||
/***********************************************************************
|
||||
* Return the next byte in the pseudo-random sequence
|
||||
*/
|
||||
static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
|
||||
{
|
||||
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
|
||||
* unpredictable manner on 16-bit systems; not a problem
|
||||
* with any known compiler so far, though */
|
||||
|
||||
temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
|
||||
return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Update the encryption keys with the next byte of plain text
|
||||
*/
|
||||
static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
|
||||
{
|
||||
(*(pkeys+0)) = CRC32((*(pkeys+0)), c);
|
||||
(*(pkeys+1)) += (*(pkeys+0)) & 0xff;
|
||||
(*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
|
||||
{
|
||||
register int keyshift = (int)((*(pkeys+1)) >> 24);
|
||||
(*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Initialize the encryption keys and the random header according to
|
||||
* the given password.
|
||||
*/
|
||||
static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
|
||||
{
|
||||
*(pkeys+0) = 305419896L;
|
||||
*(pkeys+1) = 591751049L;
|
||||
*(pkeys+2) = 878082192L;
|
||||
while (*passwd != '\0') {
|
||||
update_keys(pkeys,pcrc_32_tab,(int)*passwd);
|
||||
passwd++;
|
||||
}
|
||||
}
|
||||
|
||||
#define zdecode(pkeys,pcrc_32_tab,c) \
|
||||
(update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
|
||||
|
||||
#define zencode(pkeys,pcrc_32_tab,c,t) \
|
||||
(t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
|
||||
|
||||
#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
|
||||
|
||||
#define RAND_HEAD_LEN 12
|
||||
/* "last resort" source for second part of crypt seed pattern */
|
||||
# ifndef ZCR_SEED2
|
||||
# define ZCR_SEED2 3141592654UL /* use PI as default pattern */
|
||||
# endif
|
||||
|
||||
static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)
|
||||
const char *passwd; /* password string */
|
||||
unsigned char *buf; /* where to write header */
|
||||
int bufSize;
|
||||
unsigned long* pkeys;
|
||||
const unsigned long* pcrc_32_tab;
|
||||
unsigned long crcForCrypting;
|
||||
{
|
||||
int n; /* index in random header */
|
||||
int t; /* temporary */
|
||||
int c; /* random byte */
|
||||
unsigned char header[RAND_HEAD_LEN-2]; /* random header */
|
||||
static unsigned calls = 0; /* ensure different random header each time */
|
||||
|
||||
if (bufSize<RAND_HEAD_LEN)
|
||||
return 0;
|
||||
|
||||
/* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
|
||||
* output of rand() to get less predictability, since rand() is
|
||||
* often poorly implemented.
|
||||
*/
|
||||
if (++calls == 1)
|
||||
{
|
||||
srand((unsigned)(time(NULL) ^ ZCR_SEED2));
|
||||
}
|
||||
init_keys(passwd, pkeys, pcrc_32_tab);
|
||||
for (n = 0; n < RAND_HEAD_LEN-2; n++)
|
||||
{
|
||||
c = (rand() >> 7) & 0xff;
|
||||
header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
|
||||
}
|
||||
/* Encrypt random header (last two bytes is high word of crc) */
|
||||
init_keys(passwd, pkeys, pcrc_32_tab);
|
||||
for (n = 0; n < RAND_HEAD_LEN-2; n++)
|
||||
{
|
||||
buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
|
||||
}
|
||||
buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
|
||||
buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
|
||||
return n;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,177 +0,0 @@
|
||||
/* ioapi.c -- IO base function header for compress/uncompress .zip
|
||||
files using zlib + zip or unzip API
|
||||
|
||||
Version 1.01e, February 12th, 2005
|
||||
|
||||
Copyright (C) 1998-2005 Gilles Vollant
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <zlib.h>
|
||||
#include "ioapi.h"
|
||||
|
||||
|
||||
|
||||
/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
|
||||
|
||||
#ifndef SEEK_CUR
|
||||
#define SEEK_CUR 1
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_END
|
||||
#define SEEK_END 2
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#define SEEK_SET 0
|
||||
#endif
|
||||
|
||||
voidpf ZCALLBACK fopen_file_func OF((
|
||||
voidpf opaque,
|
||||
const char* filename,
|
||||
int mode));
|
||||
|
||||
uLong ZCALLBACK fread_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream,
|
||||
void* buf,
|
||||
uLong size));
|
||||
|
||||
uLong ZCALLBACK fwrite_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream,
|
||||
const void* buf,
|
||||
uLong size));
|
||||
|
||||
long ZCALLBACK ftell_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream));
|
||||
|
||||
long ZCALLBACK fseek_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream,
|
||||
uLong offset,
|
||||
int origin));
|
||||
|
||||
int ZCALLBACK fclose_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream));
|
||||
|
||||
int ZCALLBACK ferror_file_func OF((
|
||||
voidpf opaque,
|
||||
voidpf stream));
|
||||
|
||||
|
||||
voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
|
||||
voidpf opaque;
|
||||
const char* filename;
|
||||
int mode;
|
||||
{
|
||||
FILE* file = NULL;
|
||||
const char* mode_fopen = NULL;
|
||||
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
|
||||
mode_fopen = "rb";
|
||||
else
|
||||
if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
|
||||
mode_fopen = "r+b";
|
||||
else
|
||||
if (mode & ZLIB_FILEFUNC_MODE_CREATE)
|
||||
mode_fopen = "wb";
|
||||
|
||||
if ((filename!=NULL) && (mode_fopen != NULL))
|
||||
file = fopen(filename, mode_fopen);
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
void* buf;
|
||||
uLong size;
|
||||
{
|
||||
uLong ret;
|
||||
ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
const void* buf;
|
||||
uLong size;
|
||||
{
|
||||
uLong ret;
|
||||
ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
long ZCALLBACK ftell_file_func (opaque, stream)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
{
|
||||
long ret;
|
||||
ret = ftell((FILE *)stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
uLong offset;
|
||||
int origin;
|
||||
{
|
||||
int fseek_origin=0;
|
||||
long ret;
|
||||
switch (origin)
|
||||
{
|
||||
case ZLIB_FILEFUNC_SEEK_CUR :
|
||||
fseek_origin = SEEK_CUR;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_END :
|
||||
fseek_origin = SEEK_END;
|
||||
break;
|
||||
case ZLIB_FILEFUNC_SEEK_SET :
|
||||
fseek_origin = SEEK_SET;
|
||||
break;
|
||||
default: return -1;
|
||||
}
|
||||
ret = 0;
|
||||
fseek((FILE *)stream, offset, fseek_origin);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ZCALLBACK fclose_file_func (opaque, stream)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
{
|
||||
int ret;
|
||||
ret = fclose((FILE *)stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ZCALLBACK ferror_file_func (opaque, stream)
|
||||
voidpf opaque;
|
||||
voidpf stream;
|
||||
{
|
||||
int ret;
|
||||
ret = ferror((FILE *)stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void fill_fopen_filefunc (pzlib_filefunc_def)
|
||||
zlib_filefunc_def* pzlib_filefunc_def;
|
||||
{
|
||||
pzlib_filefunc_def->zopen_file = fopen_file_func;
|
||||
pzlib_filefunc_def->zread_file = fread_file_func;
|
||||
pzlib_filefunc_def->zwrite_file = fwrite_file_func;
|
||||
pzlib_filefunc_def->ztell_file = ftell_file_func;
|
||||
pzlib_filefunc_def->zseek_file = fseek_file_func;
|
||||
pzlib_filefunc_def->zclose_file = fclose_file_func;
|
||||
pzlib_filefunc_def->zerror_file = ferror_file_func;
|
||||
pzlib_filefunc_def->opaque = NULL;
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/* ioapi.h -- IO base function header for compress/uncompress .zip
|
||||
files using zlib + zip or unzip API
|
||||
|
||||
Version 1.01e, February 12th, 2005
|
||||
|
||||
Copyright (C) 1998-2005 Gilles Vollant
|
||||
*/
|
||||
|
||||
#ifndef _ZLIBIOAPI_H
|
||||
#define _ZLIBIOAPI_H
|
||||
|
||||
|
||||
#define ZLIB_FILEFUNC_SEEK_CUR (1)
|
||||
#define ZLIB_FILEFUNC_SEEK_END (2)
|
||||
#define ZLIB_FILEFUNC_SEEK_SET (0)
|
||||
|
||||
#define ZLIB_FILEFUNC_MODE_READ (1)
|
||||
#define ZLIB_FILEFUNC_MODE_WRITE (2)
|
||||
#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
|
||||
|
||||
#define ZLIB_FILEFUNC_MODE_EXISTING (4)
|
||||
#define ZLIB_FILEFUNC_MODE_CREATE (8)
|
||||
|
||||
|
||||
#ifndef ZCALLBACK
|
||||
|
||||
#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
|
||||
#define ZCALLBACK CALLBACK
|
||||
#else
|
||||
#define ZCALLBACK
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
|
||||
typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
|
||||
typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
|
||||
typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
|
||||
typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
|
||||
typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
|
||||
typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
|
||||
|
||||
typedef struct zlib_filefunc_def_s
|
||||
{
|
||||
open_file_func zopen_file;
|
||||
read_file_func zread_file;
|
||||
write_file_func zwrite_file;
|
||||
tell_file_func ztell_file;
|
||||
seek_file_func zseek_file;
|
||||
close_file_func zclose_file;
|
||||
testerror_file_func zerror_file;
|
||||
voidpf opaque;
|
||||
} zlib_filefunc_def;
|
||||
|
||||
|
||||
|
||||
void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
|
||||
|
||||
#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))
|
||||
#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
|
||||
#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream))
|
||||
#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode))
|
||||
#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
|
||||
#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,358 +0,0 @@
|
||||
/* unzip.h -- IO for uncompress .zip files using zlib
|
||||
Version 1.01e, February 12th, 2005
|
||||
|
||||
Copyright (C) 1998-2005 Gilles Vollant
|
||||
|
||||
This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
|
||||
WinZip, InfoZip tools and compatible.
|
||||
|
||||
Multi volume ZipFile (span) are not supported.
|
||||
Encryption compatible with pkzip 2.04g only supported
|
||||
Old compressions used by old PKZip 1.x are not supported
|
||||
|
||||
|
||||
I WAIT FEEDBACK at mail info@winimage.com
|
||||
Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
|
||||
|
||||
Condition of use and distribution are the same than zlib :
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/* for more info about .ZIP format, see
|
||||
http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
|
||||
http://www.info-zip.org/pub/infozip/doc/
|
||||
PkWare has also a specification at :
|
||||
ftp://ftp.pkware.com/probdesc.zip
|
||||
*/
|
||||
|
||||
#ifndef _unz_H
|
||||
#define _unz_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef _ZLIB_H
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef OF
|
||||
#define OF(args) args
|
||||
#endif
|
||||
|
||||
#ifndef _ZLIBIOAPI_H
|
||||
#include "ioapi.h"
|
||||
#endif
|
||||
|
||||
#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
|
||||
/* like the STRICT of WIN32, we define a pointer that cannot be converted
|
||||
from (void*) without cast */
|
||||
typedef struct TagunzFile__ { int unused; } unzFile__;
|
||||
typedef unzFile__ *unzFile;
|
||||
#else
|
||||
typedef voidp unzFile;
|
||||
#endif
|
||||
|
||||
|
||||
#define UNZ_OK (0)
|
||||
#define UNZ_END_OF_LIST_OF_FILE (-100)
|
||||
#define UNZ_ERRNO (Z_ERRNO)
|
||||
#define UNZ_EOF (0)
|
||||
#define UNZ_PARAMERROR (-102)
|
||||
#define UNZ_BADZIPFILE (-103)
|
||||
#define UNZ_INTERNALERROR (-104)
|
||||
#define UNZ_CRCERROR (-105)
|
||||
|
||||
/* tm_unz contain date/time info */
|
||||
typedef struct tm_unz_s
|
||||
{
|
||||
uInt tm_sec; /* seconds after the minute - [0,59] */
|
||||
uInt tm_min; /* minutes after the hour - [0,59] */
|
||||
uInt tm_hour; /* hours since midnight - [0,23] */
|
||||
uInt tm_mday; /* day of the month - [1,31] */
|
||||
uInt tm_mon; /* months since January - [0,11] */
|
||||
uInt tm_year; /* years - [1980..2044] */
|
||||
} tm_unz;
|
||||
|
||||
/* unz_global_info structure contain global data about the ZIPfile
|
||||
These data comes from the end of central dir */
|
||||
typedef struct unz_global_info_s
|
||||
{
|
||||
uLong number_entry; /* total number of entries in
|
||||
the central dir on this disk */
|
||||
uLong size_comment; /* size of the global comment of the zipfile */
|
||||
} unz_global_info;
|
||||
|
||||
|
||||
/* unz_file_info contain information about a file in the zipfile */
|
||||
typedef struct unz_file_info_s
|
||||
{
|
||||
uLong version; /* version made by 2 bytes */
|
||||
uLong version_needed; /* version needed to extract 2 bytes */
|
||||
uLong flag; /* general purpose bit flag 2 bytes */
|
||||
uLong compression_method; /* compression method 2 bytes */
|
||||
uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
|
||||
uLong crc; /* crc-32 4 bytes */
|
||||
uLong compressed_size; /* compressed size 4 bytes */
|
||||
uLong uncompressed_size; /* uncompressed size 4 bytes */
|
||||
uLong size_filename; /* filename length 2 bytes */
|
||||
uLong size_file_extra; /* extra field length 2 bytes */
|
||||
uLong size_file_comment; /* file comment length 2 bytes */
|
||||
|
||||
uLong disk_num_start; /* disk number start 2 bytes */
|
||||
uLong internal_fa; /* internal file attributes 2 bytes */
|
||||
uLong external_fa; /* external file attributes 4 bytes */
|
||||
|
||||
tm_unz tmu_date;
|
||||
} unz_file_info;
|
||||
|
||||
extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
|
||||
const char* fileName2,
|
||||
int iCaseSensitivity));
|
||||
/*
|
||||
Compare two filename (fileName1,fileName2).
|
||||
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
|
||||
If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
|
||||
or strcasecmp)
|
||||
If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
|
||||
(like 1 on Unix, 2 on Windows)
|
||||
*/
|
||||
|
||||
|
||||
extern unzFile ZEXPORT unzOpen OF((const char *path));
|
||||
/*
|
||||
Open a Zip file. path contain the full pathname (by example,
|
||||
on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
|
||||
"zlib/zlib113.zip".
|
||||
If the zipfile cannot be opened (file don't exist or in not valid), the
|
||||
return value is NULL.
|
||||
Else, the return value is a unzFile Handle, usable with other function
|
||||
of this unzip package.
|
||||
*/
|
||||
|
||||
extern unzFile ZEXPORT unzOpen2 OF((const char *path,
|
||||
zlib_filefunc_def* pzlib_filefunc_def));
|
||||
/*
|
||||
Open a Zip file, like unzOpen, but provide a set of file low level API
|
||||
for read/write the zip file (see ioapi.h)
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzClose OF((unzFile file));
|
||||
/*
|
||||
Close a ZipFile opened with unzipOpen.
|
||||
If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
|
||||
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
|
||||
return UNZ_OK if there is no problem. */
|
||||
|
||||
extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
|
||||
unz_global_info *pglobal_info));
|
||||
/*
|
||||
Write info about the ZipFile in the *pglobal_info structure.
|
||||
No preparation of the structure is needed
|
||||
return UNZ_OK if there is no problem. */
|
||||
|
||||
|
||||
extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
|
||||
char *szComment,
|
||||
uLong uSizeBuf));
|
||||
/*
|
||||
Get the global comment string of the ZipFile, in the szComment buffer.
|
||||
uSizeBuf is the size of the szComment buffer.
|
||||
return the number of byte copied or an error code <0
|
||||
*/
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
/* Unzip package allow you browse the directory of the zipfile */
|
||||
|
||||
extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
|
||||
/*
|
||||
Set the current file of the zipfile to the first file.
|
||||
return UNZ_OK if there is no problem
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzGoToNextFile OF((unzFile file));
|
||||
/*
|
||||
Set the current file of the zipfile to the next file.
|
||||
return UNZ_OK if there is no problem
|
||||
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzLocateFile OF((unzFile file,
|
||||
const char *szFileName,
|
||||
int iCaseSensitivity));
|
||||
/*
|
||||
Try locate the file szFileName in the zipfile.
|
||||
For the iCaseSensitivity signification, see unzStringFileNameCompare
|
||||
|
||||
return value :
|
||||
UNZ_OK if the file is found. It becomes the current file.
|
||||
UNZ_END_OF_LIST_OF_FILE if the file is not found
|
||||
*/
|
||||
|
||||
|
||||
/* ****************************************** */
|
||||
/* Ryan supplied functions */
|
||||
/* unz_file_info contain information about a file in the zipfile */
|
||||
typedef struct unz_file_pos_s
|
||||
{
|
||||
uLong pos_in_zip_directory; /* offset in zip file directory */
|
||||
uLong num_of_file; /* # of file */
|
||||
} unz_file_pos;
|
||||
|
||||
extern int ZEXPORT unzGetFilePos(
|
||||
unzFile file,
|
||||
unz_file_pos* file_pos);
|
||||
|
||||
extern int ZEXPORT unzGoToFilePos(
|
||||
unzFile file,
|
||||
unz_file_pos* file_pos);
|
||||
|
||||
/* ****************************************** */
|
||||
|
||||
extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
|
||||
unz_file_info *pfile_info,
|
||||
char *szFileName,
|
||||
uLong fileNameBufferSize,
|
||||
void *extraField,
|
||||
uLong extraFieldBufferSize,
|
||||
char *szComment,
|
||||
uLong commentBufferSize));
|
||||
/*
|
||||
Get Info about the current file
|
||||
if pfile_info!=NULL, the *pfile_info structure will contain somes info about
|
||||
the current file
|
||||
if szFileName!=NULL, the filemane string will be copied in szFileName
|
||||
(fileNameBufferSize is the size of the buffer)
|
||||
if extraField!=NULL, the extra field information will be copied in extraField
|
||||
(extraFieldBufferSize is the size of the buffer).
|
||||
This is the Central-header version of the extra field
|
||||
if szComment!=NULL, the comment string of the file will be copied in szComment
|
||||
(commentBufferSize is the size of the buffer)
|
||||
*/
|
||||
|
||||
/***************************************************************************/
|
||||
/* for reading the content of the current zipfile, you can open it, read data
|
||||
from it, and close it (you can close it before reading all the file)
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
|
||||
/*
|
||||
Open for reading data the current file in the zipfile.
|
||||
If there is no error, the return value is UNZ_OK.
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,
|
||||
const char* password));
|
||||
/*
|
||||
Open for reading data the current file in the zipfile.
|
||||
password is a crypting password
|
||||
If there is no error, the return value is UNZ_OK.
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,
|
||||
int* method,
|
||||
int* level,
|
||||
int raw));
|
||||
/*
|
||||
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
|
||||
if raw==1
|
||||
*method will receive method of compression, *level will receive level of
|
||||
compression
|
||||
note : you can set level parameter as NULL (if you did not want known level,
|
||||
but you CANNOT set method parameter as NULL
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,
|
||||
int* method,
|
||||
int* level,
|
||||
int raw,
|
||||
const char* password));
|
||||
/*
|
||||
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
|
||||
if raw==1
|
||||
*method will receive method of compression, *level will receive level of
|
||||
compression
|
||||
note : you can set level parameter as NULL (if you did not want known level,
|
||||
but you CANNOT set method parameter as NULL
|
||||
*/
|
||||
|
||||
|
||||
extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
|
||||
/*
|
||||
Close the file in zip opened with unzOpenCurrentFile
|
||||
Return UNZ_CRCERROR if all the file was read but the CRC is not good
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
|
||||
voidp buf,
|
||||
unsigned len));
|
||||
/*
|
||||
Read bytes from the current file (opened by unzOpenCurrentFile)
|
||||
buf contain buffer where data must be copied
|
||||
len the size of buf.
|
||||
|
||||
return the number of byte copied if somes bytes are copied
|
||||
return 0 if the end of file was reached
|
||||
return <0 with error code if there is an error
|
||||
(UNZ_ERRNO for IO error, or zLib error for uncompress error)
|
||||
*/
|
||||
|
||||
extern z_off_t ZEXPORT unztell OF((unzFile file));
|
||||
/*
|
||||
Give the current position in uncompressed data
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzeof OF((unzFile file));
|
||||
/*
|
||||
return 1 if the end of file was reached, 0 elsewhere
|
||||
*/
|
||||
|
||||
extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
|
||||
voidp buf,
|
||||
unsigned len));
|
||||
/*
|
||||
Read extra field from the current file (opened by unzOpenCurrentFile)
|
||||
This is the local-header version of the extra field (sometimes, there is
|
||||
more info in the local-header version than in the central-header)
|
||||
|
||||
if buf==NULL, it return the size of the local extra field
|
||||
|
||||
if buf!=NULL, len is the size of the buffer, the extra header is copied in
|
||||
buf.
|
||||
the return value is the number of bytes copied in buf, or (if <0)
|
||||
the error code
|
||||
*/
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/* Get the current file offset */
|
||||
extern uLong ZEXPORT unzGetOffset (unzFile file);
|
||||
|
||||
/* Set the current file offset */
|
||||
extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _unz_H */
|
||||
@@ -520,8 +520,8 @@ void CPU::process(unsigned long const cycles) {
|
||||
|
||||
if (mem_.halted()) {
|
||||
if (cycleCounter < mem_.nextEventTime()) {
|
||||
unsigned long cycles = mem_.nextEventTime() - cycleCounter;
|
||||
cycleCounter += cycles + (-cycles & 3);
|
||||
unsigned long cpu_cycles = mem_.nextEventTime() - cycleCounter;
|
||||
cycleCounter += cpu_cycles + (-cpu_cycles & 3);
|
||||
}
|
||||
} else while (cycleCounter < mem_.nextEventTime()) {
|
||||
unsigned char opcode;
|
||||
@@ -614,8 +614,8 @@ void CPU::process(unsigned long const cycles) {
|
||||
PC_READ(opcode_);
|
||||
cycleCounter = mem_.stop(cycleCounter - 4, prefetched_);
|
||||
if (cycleCounter < mem_.nextEventTime()) {
|
||||
unsigned long cycles = mem_.nextEventTime() - cycleCounter;
|
||||
cycleCounter += cycles + (-cycles & 3);
|
||||
unsigned long cpu_cycles = mem_.nextEventTime() - cycleCounter;
|
||||
cycleCounter += cpu_cycles + (-cpu_cycles & 3);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1024,8 +1024,8 @@ void CPU::process(unsigned long const cycles) {
|
||||
prefetched_ = mem_.halt(cycleCounter);
|
||||
cycleCounter += 4 + 4 * !mem_.isCgb();
|
||||
if (cycleCounter < mem_.nextEventTime()) {
|
||||
unsigned long cycles = mem_.nextEventTime() - cycleCounter;
|
||||
cycleCounter += cycles + (-cycles & 3);
|
||||
unsigned long cpu_cycles = mem_.nextEventTime() - cycleCounter;
|
||||
cycleCounter += cpu_cycles + (-cpu_cycles & 3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
class File;
|
||||
|
||||
class CPU {
|
||||
public:
|
||||
CPU();
|
||||
@@ -53,8 +55,8 @@ public:
|
||||
mem_.setOsdElement(osdElement);
|
||||
}
|
||||
|
||||
LoadRes load(std::string const &romfile, bool forceDmg, bool multicartCompat) {
|
||||
return mem_.loadROM(romfile, forceDmg, multicartCompat);
|
||||
LoadRes load(File &file, std::string const &filename, bool forceDmg, bool multicartCompat) {
|
||||
return mem_.loadROM(file, filename, forceDmg, multicartCompat);
|
||||
}
|
||||
|
||||
bool loaded() const { return mem_.loaded(); }
|
||||
@@ -64,6 +66,10 @@ public:
|
||||
std::size_t fillSoundBuffer() { return mem_.fillSoundBuffer(cycleCounter_); }
|
||||
bool isCgb() const { return mem_.isCgb(); }
|
||||
|
||||
void setCgbColorCorrection(int optNum) {
|
||||
mem_.setCgbColorCorrection(optNum);
|
||||
}
|
||||
|
||||
void setDmgPaletteColor(int palNum, int colorNum, unsigned long rgb32) {
|
||||
mem_.setDmgPaletteColor(palNum, colorNum, rgb32);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/***************************************************************************
|
||||
Copyright (C) 2007 by Nach
|
||||
http://nsrt.edgeemu.com
|
||||
|
||||
Copyright (C) 2007-2011 by sinamas <sinamas at users.sourceforge.net>
|
||||
sinamas@users.sourceforge.net
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
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 version 2 for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
version 2 along with this program; if not, write to the
|
||||
Free Software Foundation, Inc.,
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
***************************************************************************/
|
||||
#ifndef GAMBATTE_MEMFILE_H
|
||||
#define GAMBATTE_MEMFILE_H
|
||||
|
||||
#include <string.h>
|
||||
#include "file.h"
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
class MemFile : public File {
|
||||
public:
|
||||
explicit MemFile(const void *data, size_t size)
|
||||
: data_(static_cast<const char*>(data))
|
||||
, size_(size)
|
||||
, offset_(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void read(char *buffer, size_t amount) {
|
||||
size_t remaining = size_ - offset_;
|
||||
size_t bytes_to_read = amount < remaining ? amount : remaining;
|
||||
memcpy(buffer, data_ + offset_, bytes_to_read);
|
||||
offset_ += bytes_to_read;
|
||||
}
|
||||
|
||||
virtual void rewind() { offset_ = 0; }
|
||||
virtual size_t size() const { return size_; };
|
||||
virtual bool fail() const { return false; }
|
||||
|
||||
private:
|
||||
const char *data_;
|
||||
size_t size_;
|
||||
size_t offset_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -16,6 +16,8 @@
|
||||
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include "file/file.h"
|
||||
#include "file/memfile.h"
|
||||
#include "gambatte.h"
|
||||
#include "cpu.h"
|
||||
#include "initstate.h"
|
||||
@@ -96,11 +98,24 @@ void GB::setSaveDir(std::string const &sdir) {
|
||||
p_->cpu.setSaveDir(sdir);
|
||||
}
|
||||
|
||||
LoadRes GB::load(std::string const &romfile, unsigned const flags) {
|
||||
LoadRes GB::load(const void *rom,
|
||||
size_t size,
|
||||
std::string const &filename,
|
||||
unsigned const flags) {
|
||||
MemFile file(rom, size);
|
||||
return load(file, filename, flags);
|
||||
}
|
||||
|
||||
LoadRes GB::load(std::string const &filename, unsigned const flags) {
|
||||
transfer_ptr<File> file = newFileInstance(filename);
|
||||
return load(*file, filename, flags);
|
||||
}
|
||||
|
||||
LoadRes GB::load(File &file, std::string const &filename, unsigned const flags) {
|
||||
if (p_->cpu.loaded())
|
||||
p_->cpu.saveSavedata();
|
||||
|
||||
LoadRes const loadres = p_->cpu.load(romfile,
|
||||
LoadRes const loadres = p_->cpu.load(file, filename,
|
||||
flags & FORCE_DMG,
|
||||
flags & MULTICART_COMPAT);
|
||||
if (loadres == LOADRES_OK) {
|
||||
@@ -131,10 +146,15 @@ void GB::saveSavedata() {
|
||||
p_->cpu.saveSavedata();
|
||||
}
|
||||
|
||||
void GB::setCgbColorCorrection(int optNum) {
|
||||
p_->cpu.setCgbColorCorrection(optNum);
|
||||
}
|
||||
|
||||
void GB::setDmgPaletteColor(int palNum, int colorNum, unsigned long rgb32) {
|
||||
p_->cpu.setDmgPaletteColor(palNum, colorNum, rgb32);
|
||||
}
|
||||
|
||||
//> OpenEmu
|
||||
bool GB::serializeState(std::ostream &stream) {
|
||||
if (p_->cpu.loaded()) {
|
||||
SaveState state;
|
||||
@@ -162,6 +182,7 @@ bool GB::deserializeState(std::istream &stream) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//< OpenEmu
|
||||
bool GB::loadState(std::string const &filepath) {
|
||||
if (p_->cpu.loaded()) {
|
||||
p_->cpu.saveSavedata();
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
class File;
|
||||
|
||||
enum { BG_PALETTE = 0, SP1_PALETTE = 1, SP2_PALETTE = 2 };
|
||||
|
||||
class GB {
|
||||
@@ -52,6 +54,17 @@ public:
|
||||
*/
|
||||
LoadRes load(std::string const &romfile, unsigned flags = 0);
|
||||
|
||||
/**
|
||||
* Load an in-memory ROM image.
|
||||
*
|
||||
* @param rom The ROM image data to load.
|
||||
* @param size The size of the ROM image, in bytes.
|
||||
* @param filename A filename, which is only used for naming save files.
|
||||
* @param flags ORed combination of LoadFlags.
|
||||
* @return 0 on success, negative value on failure.
|
||||
*/
|
||||
LoadRes load(const void *rom, size_t size, std::string const &filename, unsigned flags = 0);
|
||||
|
||||
/**
|
||||
* Emulates until at least 'samples' audio samples are produced in the
|
||||
* supplied audio buffer, or until a video frame has been drawn.
|
||||
@@ -89,6 +102,11 @@ public:
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* @param optNum 0 <= palNum < 1
|
||||
*/
|
||||
void setCgbColorCorrection(int optNum);
|
||||
|
||||
/**
|
||||
* @param palNum 0 <= palNum < 3. One of BG_PALETTE, SP1_PALETTE and SP2_PALETTE.
|
||||
* @param colorNum 0 <= colorNum < 4
|
||||
@@ -113,6 +131,7 @@ public:
|
||||
/** Writes persistent cartridge data to disk. Done implicitly on ROM close. */
|
||||
void saveSavedata();
|
||||
|
||||
//> OpenEmu
|
||||
/** Serializes state data to 'stream'
|
||||
* @return success
|
||||
*/
|
||||
@@ -123,6 +142,7 @@ public:
|
||||
*/
|
||||
bool deserializeState(std::istream &stream);
|
||||
|
||||
//< OpenEmu
|
||||
/**
|
||||
* Saves emulator state to the state slot selected with selectState().
|
||||
* The data will be stored in the directory given by setSaveDir().
|
||||
@@ -191,6 +211,8 @@ public:
|
||||
void setGameShark(std::string const &codes);
|
||||
|
||||
private:
|
||||
LoadRes load(File &file, std::string const &filename, unsigned flags);
|
||||
|
||||
struct Priv;
|
||||
Priv *const p_;
|
||||
|
||||
@@ -19,17 +19,6 @@
|
||||
#ifndef GAMBATTE_INT_H
|
||||
#define GAMBATTE_INT_H
|
||||
|
||||
#ifdef HAVE_CSTDINT
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace gambatte {
|
||||
using std::uint_least32_t;
|
||||
using std::uint_least16_t;
|
||||
}
|
||||
|
||||
#elif defined(HAVE_STDINT_H)
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace gambatte {
|
||||
@@ -37,26 +26,4 @@ using ::uint_least32_t;
|
||||
using ::uint_least16_t;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
namespace gambatte {
|
||||
#ifdef CHAR_LEAST_32
|
||||
typedef unsigned char uint_least32_t;
|
||||
#elif defined(SHORT_LEAST_32)
|
||||
typedef unsigned short uint_least32_t;
|
||||
#elif defined(INT_LEAST_32)
|
||||
typedef unsigned uint_least32_t;
|
||||
#else
|
||||
typedef unsigned long uint_least32_t;
|
||||
#endif
|
||||
|
||||
#ifdef CHAR_LEAST_16
|
||||
typedef unsigned char uint_least16_t;
|
||||
#else
|
||||
typedef unsigned short uint_least16_t;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Executable → Regular
@@ -78,6 +78,8 @@ void Interrupter::setGameShark(std::string const &codes) {
|
||||
gsCodes_.clear();
|
||||
|
||||
for (std::size_t pos = 0; pos < codes.length(); pos += code.length() + 1) {
|
||||
// OpenEmu
|
||||
//code = codes.substr(pos, codes.find(';', pos) - pos);
|
||||
code = codes.substr(pos, codes.find('+', pos) - pos);
|
||||
if (code.length() >= 8) {
|
||||
GsCode gs;
|
||||
@@ -94,6 +96,8 @@ void Interrupter::setGameShark(std::string const &codes) {
|
||||
|
||||
void Interrupter::applyVblankCheats(unsigned long const cc, Memory &memory) {
|
||||
for (std::size_t i = 0, size = gsCodes_.size(); i < size; ++i) {
|
||||
// OpenEmu
|
||||
//if (gsCodes_[i].type == 0x01)
|
||||
if (gsCodes_[i].type == 0x01 || gsCodes_[i].type == 0x91)
|
||||
memory.write(gsCodes_[i].address, gsCodes_[i].value, cc);
|
||||
}
|
||||
@@ -17,10 +17,13 @@
|
||||
//
|
||||
|
||||
#include "cartridge.h"
|
||||
#include "file/file.h"
|
||||
// OpenEmu
|
||||
//#include "file/file.h"
|
||||
#include "../file/file.h"
|
||||
#include "../savestate.h"
|
||||
#include "pakinfo_internal.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
|
||||
@@ -556,12 +559,12 @@ void Cartridge::setSaveDir(std::string const &dir) {
|
||||
saveDir_ += '/';
|
||||
}
|
||||
|
||||
LoadRes Cartridge::loadROM(std::string const &romfile,
|
||||
LoadRes Cartridge::loadROM(File &file,
|
||||
std::string const &filename,
|
||||
bool const forceDmg,
|
||||
bool const multicartCompat)
|
||||
{
|
||||
scoped_ptr<File> const rom(newFileInstance(romfile));
|
||||
if (rom->fail())
|
||||
if (file.fail())
|
||||
return LOADRES_IO_ERROR;
|
||||
|
||||
enum Cartridgetype { type_plain,
|
||||
@@ -577,7 +580,7 @@ LoadRes Cartridge::loadROM(std::string const &romfile,
|
||||
|
||||
{
|
||||
unsigned char header[0x150];
|
||||
rom->read(reinterpret_cast<char *>(header), sizeof header);
|
||||
file.read(reinterpret_cast<char *>(header), sizeof header);
|
||||
|
||||
switch (header[0x0147]) {
|
||||
case 0x00: type = type_plain; break;
|
||||
@@ -634,8 +637,8 @@ LoadRes Cartridge::loadROM(std::string const &romfile,
|
||||
cgb = header[0x0143] >> 7 & (1 ^ forceDmg);
|
||||
}
|
||||
|
||||
std::size_t const filesize = rom->size();
|
||||
rombanks = std::max(pow2ceil(filesize / rombank_size()), 2u);
|
||||
std::size_t const filesize = file.size();
|
||||
rombanks = std::max(pow2ceil(filesize / 0x4000), 2u);
|
||||
|
||||
defaultSaveBasePath_.clear();
|
||||
ggUndoList_.clear();
|
||||
@@ -643,17 +646,17 @@ LoadRes Cartridge::loadROM(std::string const &romfile,
|
||||
memptrs_.reset(rombanks, rambanks, cgb ? 8 : 2);
|
||||
rtc_.set(false, 0);
|
||||
|
||||
rom->rewind();
|
||||
rom->read(reinterpret_cast<char*>(memptrs_.romdata()), filesize / rombank_size() * rombank_size());
|
||||
std::memset(memptrs_.romdata() + filesize / rombank_size() * rombank_size(),
|
||||
file.rewind();
|
||||
file.read(reinterpret_cast<char*>(memptrs_.romdata()), filesize / 0x4000 * 0x4000ul);
|
||||
std::memset(memptrs_.romdata() + filesize / 0x4000 * 0x4000ul,
|
||||
0xFF,
|
||||
(rombanks - filesize / rombank_size()) * rombank_size());
|
||||
enforce8bit(memptrs_.romdata(), rombanks * rombank_size());
|
||||
(rombanks - filesize / 0x4000) * 0x4000ul);
|
||||
enforce8bit(memptrs_.romdata(), rombanks * 0x4000ul);
|
||||
|
||||
if (rom->fail())
|
||||
if (file.fail())
|
||||
return LOADRES_IO_ERROR;
|
||||
|
||||
defaultSaveBasePath_ = stripExtension(romfile);
|
||||
defaultSaveBasePath_ = stripExtension(filename);
|
||||
|
||||
switch (type) {
|
||||
case type_plain: mbc_.reset(new Mbc0(memptrs_)); break;
|
||||
@@ -755,6 +758,8 @@ void Cartridge::setGameGenie(std::string const &codes) {
|
||||
|
||||
std::string code;
|
||||
for (std::size_t pos = 0; pos < codes.length(); pos += code.length() + 1) {
|
||||
// OpenEmu
|
||||
//code = codes.substr(pos, codes.find(';', pos) - pos);
|
||||
code = codes.substr(pos, codes.find('+', pos) - pos);
|
||||
applyGameGenie(code);
|
||||
}
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
class File;
|
||||
|
||||
class Mbc {
|
||||
public:
|
||||
virtual ~Mbc() {}
|
||||
@@ -67,7 +69,7 @@ public:
|
||||
void saveSavedata();
|
||||
std::string const saveBasePath() const;
|
||||
void setSaveDir(std::string const &dir);
|
||||
LoadRes loadROM(std::string const &romfile, bool forceDmg, bool multicartCompat);
|
||||
LoadRes loadROM(File &file, std::string const &filename, bool forceDmg, bool multicartCompat);
|
||||
char const * romTitle() const { return reinterpret_cast<char const *>(memptrs_.romdata() + 0x134); }
|
||||
class PakInfo const pakInfo(bool multicartCompat) const;
|
||||
void setGameGenie(std::string const &codes);
|
||||
@@ -76,7 +78,7 @@ private:
|
||||
struct AddrData {
|
||||
unsigned long addr;
|
||||
unsigned char data;
|
||||
AddrData(unsigned long addr, unsigned data) : addr(addr), data(data) {}
|
||||
AddrData(unsigned long _addr, unsigned _data) : addr(_addr), data(_data) {}
|
||||
};
|
||||
|
||||
MemPtrs memptrs_;
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
enum { flag_multipak = 1, flag_header_checksum_ok = 2, };
|
||||
enum { flag_multipak = 1, flag_header_checksum_ok = 2 };
|
||||
|
||||
static bool isHeaderChecksumOk(unsigned const char header[]) {
|
||||
unsigned csum = 0;
|
||||
@@ -1149,8 +1149,8 @@ void Memory::nontrivial_write(unsigned const p, unsigned const data, unsigned lo
|
||||
ioamhram_[p - mm_oam_begin] = data;
|
||||
}
|
||||
|
||||
LoadRes Memory::loadROM(std::string const &romfile, bool const forceDmg, bool const multicartCompat) {
|
||||
if (LoadRes const fail = cart_.loadROM(romfile, forceDmg, multicartCompat))
|
||||
LoadRes Memory::loadROM(File &file, std::string const &filename, bool const forceDmg, bool const multicartCompat) {
|
||||
if (LoadRes const fail = cart_.loadROM(file, filename, forceDmg, multicartCompat))
|
||||
return fail;
|
||||
|
||||
psg_.init(cart_.isCgb());
|
||||
@@ -28,8 +28,9 @@
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
class InputGetter;
|
||||
class File;
|
||||
class FilterInfo;
|
||||
class InputGetter;
|
||||
|
||||
class Memory {
|
||||
public:
|
||||
@@ -93,7 +94,7 @@ public:
|
||||
|
||||
unsigned long event(unsigned long cycleCounter);
|
||||
unsigned long resetCounters(unsigned long cycleCounter);
|
||||
LoadRes loadROM(std::string const &romfile, bool forceDmg, bool multicartCompat);
|
||||
LoadRes loadROM(File &file, std::string const &filename, bool forceDmg, bool multicartCompat);
|
||||
void setSaveDir(std::string const &dir) { cart_.setSaveDir(dir); }
|
||||
void setInputGetter(InputGetter *getInput) { getInput_ = getInput; }
|
||||
void setEndtime(unsigned long cc, unsigned long inc);
|
||||
@@ -104,6 +105,10 @@ public:
|
||||
lcd_.setVideoBuffer(videoBuf, pitch);
|
||||
}
|
||||
|
||||
void setCgbColorCorrection(int optNum) {
|
||||
lcd_.setCgbColorCorrection(optNum);
|
||||
}
|
||||
|
||||
void setDmgPaletteColor(int palNum, int colorNum, unsigned long rgb32) {
|
||||
lcd_.setDmgPaletteColor(palNum, colorNum, rgb32);
|
||||
}
|
||||
@@ -0,0 +1,448 @@
|
||||
//
|
||||
// Copyright (C) 2008 by sinamas <sinamas at users.sourceforge.net>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation.
|
||||
//
|
||||
// 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 version 2 for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// version 2 along with this program; if not, write to the
|
||||
// Free Software Foundation, Inc.,
|
||||
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include "statesaver.h"
|
||||
#include "savestate.h"
|
||||
#include "array.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace gambatte;
|
||||
|
||||
enum AsciiChar {
|
||||
NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL, BS, TAB, LF, VT, FF, CR, SO, SI,
|
||||
DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB, CAN, EM, SUB, ESC, FS, GS, RS, US,
|
||||
SP, XCL, QOT, HSH, DLR, PRC, AMP, APO, LPA, RPA, AST, PLU, COM, HYP, STP, DIV,
|
||||
NO0, NO1, NO2, NO3, NO4, NO5, NO6, NO7, NO8, NO9, CLN, SCL, LT, EQL, GT, QTN,
|
||||
AT, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O,
|
||||
P, Q, R, S, T, U, V, W, X, Y, Z, LBX, BSL, RBX, CAT, UND,
|
||||
ACN, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o,
|
||||
p, q, r, s, t, u, v, w, x, y, z, LBR, BAR, RBR, TLD, DEL
|
||||
};
|
||||
|
||||
struct Saver {
|
||||
char const *label;
|
||||
void (*save)(std::ofstream &file, SaveState const &state);
|
||||
void (*load)(std::ifstream &file, SaveState &state);
|
||||
std::size_t labelsize;
|
||||
};
|
||||
|
||||
inline bool operator<(Saver const &l, Saver const &r) {
|
||||
return std::strcmp(l.label, r.label) < 0;
|
||||
}
|
||||
|
||||
void put24(std::ofstream &file, unsigned long data) {
|
||||
file.put(data >> 16 & 0xFF);
|
||||
file.put(data >> 8 & 0xFF);
|
||||
file.put(data & 0xFF);
|
||||
}
|
||||
|
||||
void put32(std::ofstream &file, unsigned long data) {
|
||||
file.put(data >> 24 & 0xFF);
|
||||
file.put(data >> 16 & 0xFF);
|
||||
file.put(data >> 8 & 0xFF);
|
||||
file.put(data & 0xFF);
|
||||
}
|
||||
|
||||
void write(std::ofstream &file, unsigned char data) {
|
||||
static char const inf[] = { 0x00, 0x00, 0x01 };
|
||||
file.write(inf, sizeof inf);
|
||||
file.put(data & 0xFF);
|
||||
}
|
||||
|
||||
void write(std::ofstream &file, unsigned short data) {
|
||||
static char const inf[] = { 0x00, 0x00, 0x02 };
|
||||
file.write(inf, sizeof inf);
|
||||
file.put(data >> 8 & 0xFF);
|
||||
file.put(data & 0xFF);
|
||||
}
|
||||
|
||||
void write(std::ofstream &file, unsigned long data) {
|
||||
static char const inf[] = { 0x00, 0x00, 0x04 };
|
||||
file.write(inf, sizeof inf);
|
||||
put32(file, data);
|
||||
}
|
||||
|
||||
void write(std::ofstream &file, unsigned char const *data, std::size_t size) {
|
||||
put24(file, size);
|
||||
file.write(reinterpret_cast<char const *>(data), size);
|
||||
}
|
||||
|
||||
void write(std::ofstream &file, bool const *data, std::size_t size) {
|
||||
put24(file, size);
|
||||
std::for_each(data, data + size,
|
||||
std::bind1st(std::mem_fun(&std::ofstream::put), &file));
|
||||
}
|
||||
|
||||
unsigned long get24(std::ifstream &file) {
|
||||
unsigned long tmp = file.get() & 0xFF;
|
||||
tmp = tmp << 8 | (file.get() & 0xFF);
|
||||
return tmp << 8 | (file.get() & 0xFF);
|
||||
}
|
||||
|
||||
unsigned long read(std::ifstream &file) {
|
||||
unsigned long size = get24(file);
|
||||
if (size > 4) {
|
||||
file.ignore(size - 4);
|
||||
size = 4;
|
||||
}
|
||||
|
||||
unsigned long out = 0;
|
||||
switch (size) {
|
||||
case 4: out = (out | (file.get() & 0xFF)) << 8; // fall through.
|
||||
case 3: out = (out | (file.get() & 0xFF)) << 8; // fall through.
|
||||
case 2: out = (out | (file.get() & 0xFF)) << 8; // fall through.
|
||||
case 1: out = out | (file.get() & 0xFF);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
inline void read(std::ifstream &file, unsigned char &data) {
|
||||
data = read(file) & 0xFF;
|
||||
}
|
||||
|
||||
inline void read(std::ifstream &file, unsigned short &data) {
|
||||
data = read(file) & 0xFFFF;
|
||||
}
|
||||
|
||||
inline void read(std::ifstream &file, unsigned long &data) {
|
||||
data = read(file);
|
||||
}
|
||||
|
||||
void read(std::ifstream &file, unsigned char *buf, std::size_t bufsize) {
|
||||
std::size_t const size = get24(file);
|
||||
std::size_t const minsize = std::min(size, bufsize);
|
||||
file.read(reinterpret_cast<char*>(buf), minsize);
|
||||
file.ignore(size - minsize);
|
||||
|
||||
if (static_cast<unsigned char>(0x100)) {
|
||||
for (std::size_t i = 0; i < minsize; ++i)
|
||||
buf[i] &= 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
void read(std::ifstream &file, bool *buf, std::size_t bufsize) {
|
||||
std::size_t const size = get24(file);
|
||||
std::size_t const minsize = std::min(size, bufsize);
|
||||
for (std::size_t i = 0; i < minsize; ++i)
|
||||
buf[i] = file.get();
|
||||
|
||||
file.ignore(size - minsize);
|
||||
}
|
||||
|
||||
} // anon namespace
|
||||
|
||||
namespace gambatte {
|
||||
|
||||
class SaverList {
|
||||
public:
|
||||
typedef std::vector<Saver> list_t;
|
||||
typedef list_t::const_iterator const_iterator;
|
||||
|
||||
SaverList();
|
||||
const_iterator begin() const { return list.begin(); }
|
||||
const_iterator end() const { return list.end(); }
|
||||
std::size_t maxLabelsize() const { return maxLabelsize_; }
|
||||
|
||||
private:
|
||||
list_t list;
|
||||
std::size_t maxLabelsize_;
|
||||
};
|
||||
|
||||
static void push(SaverList::list_t &list, char const *label,
|
||||
void (*save)(std::ofstream &file, SaveState const &state),
|
||||
void (*load)(std::ifstream &file, SaveState &state),
|
||||
std::size_t labelsize) {
|
||||
Saver saver = { label, save, load, labelsize };
|
||||
list.push_back(saver);
|
||||
}
|
||||
|
||||
SaverList::SaverList()
|
||||
: maxLabelsize_(0)
|
||||
{
|
||||
#define ADD(arg) do { \
|
||||
struct Func { \
|
||||
static void save(std::ofstream &file, SaveState const &state) { write(file, state.arg); } \
|
||||
static void load(std::ifstream &file, SaveState &state) { read(file, state.arg); } \
|
||||
}; \
|
||||
push(list, label, Func::save, Func::load, sizeof label); \
|
||||
} while (0)
|
||||
|
||||
#define ADDPTR(arg) do { \
|
||||
struct Func { \
|
||||
static void save(std::ofstream &file, SaveState const &state) { \
|
||||
write(file, state.arg.get(), state.arg.size()); \
|
||||
} \
|
||||
static void load(std::ifstream &file, SaveState &state) { \
|
||||
read(file, state.arg.ptr, state.arg.size()); \
|
||||
} \
|
||||
}; \
|
||||
push(list, label, Func::save, Func::load, sizeof label); \
|
||||
} while (0)
|
||||
|
||||
#define ADDARRAY(arg) do { \
|
||||
struct Func { \
|
||||
static void save(std::ofstream &file, SaveState const &state) { \
|
||||
write(file, state.arg, sizeof state.arg); \
|
||||
} \
|
||||
static void load(std::ifstream &file, SaveState &state) { \
|
||||
read(file, state.arg, sizeof state.arg); \
|
||||
} \
|
||||
}; \
|
||||
push(list, label, Func::save, Func::load, sizeof label); \
|
||||
} while (0)
|
||||
|
||||
{ static char const label[] = { c,c, NUL }; ADD(cpu.cycleCounter); }
|
||||
{ static char const label[] = { p,c, NUL }; ADD(cpu.pc); }
|
||||
{ static char const label[] = { s,p, NUL }; ADD(cpu.sp); }
|
||||
{ static char const label[] = { a, NUL }; ADD(cpu.a); }
|
||||
{ static char const label[] = { b, NUL }; ADD(cpu.b); }
|
||||
{ static char const label[] = { c, NUL }; ADD(cpu.c); }
|
||||
{ static char const label[] = { d, NUL }; ADD(cpu.d); }
|
||||
{ static char const label[] = { e, NUL }; ADD(cpu.e); }
|
||||
{ static char const label[] = { f, NUL }; ADD(cpu.f); }
|
||||
{ static char const label[] = { h, NUL }; ADD(cpu.h); }
|
||||
{ static char const label[] = { l, NUL }; ADD(cpu.l); }
|
||||
{ static char const label[] = { o,p, NUL }; ADD(cpu.opcode); }
|
||||
{ static char const label[] = { f,e,t,c,h,e,d, NUL }; ADD(cpu.prefetched); }
|
||||
{ static char const label[] = { s,k,i,p, NUL }; ADD(cpu.skip); }
|
||||
{ static char const label[] = { h,a,l,t, NUL }; ADD(mem.halted); }
|
||||
{ static char const label[] = { v,r,a,m, NUL }; ADDPTR(mem.vram); }
|
||||
{ static char const label[] = { s,r,a,m, NUL }; ADDPTR(mem.sram); }
|
||||
{ static char const label[] = { w,r,a,m, NUL }; ADDPTR(mem.wram); }
|
||||
{ static char const label[] = { h,r,a,m, NUL }; ADDPTR(mem.ioamhram); }
|
||||
{ static char const label[] = { l,d,i,v,u,p, NUL }; ADD(mem.divLastUpdate); }
|
||||
{ static char const label[] = { l,t,i,m,a,u,p, NUL }; ADD(mem.timaLastUpdate); }
|
||||
{ static char const label[] = { t,m,a,t,i,m,e, NUL }; ADD(mem.tmatime); }
|
||||
{ static char const label[] = { s,e,r,i,a,l,t, NUL }; ADD(mem.nextSerialtime); }
|
||||
{ static char const label[] = { l,o,d,m,a,u,p, NUL }; ADD(mem.lastOamDmaUpdate); }
|
||||
{ static char const label[] = { m,i,n,i,n,t,t, NUL }; ADD(mem.minIntTime); }
|
||||
{ static char const label[] = { u,n,h,a,l,t,t, NUL }; ADD(mem.unhaltTime); }
|
||||
{ static char const label[] = { r,o,m,b,a,n,k, NUL }; ADD(mem.rombank); }
|
||||
{ static char const label[] = { d,m,a,s,r,c, NUL }; ADD(mem.dmaSource); }
|
||||
{ static char const label[] = { d,m,a,d,s,t, NUL }; ADD(mem.dmaDestination); }
|
||||
{ static char const label[] = { r,a,m,b,a,n,k, NUL }; ADD(mem.rambank); }
|
||||
{ static char const label[] = { o,d,m,a,p,o,s, NUL }; ADD(mem.oamDmaPos); }
|
||||
{ static char const label[] = { h,l,t,h,d,m,a, NUL }; ADD(mem.haltHdmaState); }
|
||||
{ static char const label[] = { i,m,e, NUL }; ADD(mem.IME); }
|
||||
{ static char const label[] = { s,r,a,m,o,n, NUL }; ADD(mem.enableRam); }
|
||||
{ static char const label[] = { r,a,m,b,m,o,d, NUL }; ADD(mem.rambankMode); }
|
||||
{ static char const label[] = { h,d,m,a, NUL }; ADD(mem.hdmaTransfer); }
|
||||
{ static char const label[] = { b,g,p, NUL }; ADDPTR(ppu.bgpData); }
|
||||
{ static char const label[] = { o,b,j,p, NUL }; ADDPTR(ppu.objpData); }
|
||||
{ static char const label[] = { s,p,o,s,b,u,f, NUL }; ADDPTR(ppu.oamReaderBuf); }
|
||||
{ static char const label[] = { s,p,s,z,b,u,f, NUL }; ADDPTR(ppu.oamReaderSzbuf); }
|
||||
{ static char const label[] = { s,p,a,t,t,r, NUL }; ADDARRAY(ppu.spAttribList); }
|
||||
{ static char const label[] = { s,p,b,y,t,e,NO0, NUL }; ADDARRAY(ppu.spByte0List); }
|
||||
{ static char const label[] = { s,p,b,y,t,e,NO1, NUL }; ADDARRAY(ppu.spByte1List); }
|
||||
{ static char const label[] = { v,c,y,c,l,e,s, NUL }; ADD(ppu.videoCycles); }
|
||||
{ static char const label[] = { e,d,M,NO0,t,i,m, NUL }; ADD(ppu.enableDisplayM0Time); }
|
||||
{ static char const label[] = { m,NO0,t,i,m,e, NUL }; ADD(ppu.lastM0Time); }
|
||||
{ static char const label[] = { n,m,NO0,i,r,q, NUL }; ADD(ppu.nextM0Irq); }
|
||||
{ static char const label[] = { b,g,t,w, NUL }; ADD(ppu.tileword); }
|
||||
{ static char const label[] = { b,g,n,t,w, NUL }; ADD(ppu.ntileword); }
|
||||
{ static char const label[] = { w,i,n,y,p,o,s, NUL }; ADD(ppu.winYPos); }
|
||||
{ static char const label[] = { x,p,o,s, NUL }; ADD(ppu.xpos); }
|
||||
{ static char const label[] = { e,n,d,x, NUL }; ADD(ppu.endx); }
|
||||
{ static char const label[] = { p,p,u,r,NO0, NUL }; ADD(ppu.reg0); }
|
||||
{ static char const label[] = { p,p,u,r,NO1, NUL }; ADD(ppu.reg1); }
|
||||
{ static char const label[] = { b,g,a,t,r,b, NUL }; ADD(ppu.attrib); }
|
||||
{ static char const label[] = { b,g,n,a,t,r,b, NUL }; ADD(ppu.nattrib); }
|
||||
{ static char const label[] = { p,p,u,s,t,a,t, NUL }; ADD(ppu.state); }
|
||||
{ static char const label[] = { n,s,p,r,i,t,e, NUL }; ADD(ppu.nextSprite); }
|
||||
{ static char const label[] = { c,s,p,r,i,t,e, NUL }; ADD(ppu.currentSprite); }
|
||||
{ static char const label[] = { l,y,c, NUL }; ADD(ppu.lyc); }
|
||||
{ static char const label[] = { m,NO0,l,y,c, NUL }; ADD(ppu.m0lyc); }
|
||||
{ static char const label[] = { o,l,d,w,y, NUL }; ADD(ppu.oldWy); }
|
||||
{ static char const label[] = { w,i,n,d,r,a,w, NUL }; ADD(ppu.winDrawState); }
|
||||
{ static char const label[] = { w,s,c,x, NUL }; ADD(ppu.wscx); }
|
||||
{ static char const label[] = { w,e,m,a,s,t,r, NUL }; ADD(ppu.weMaster); }
|
||||
{ static char const label[] = { l,c,d,s,i,r,q, NUL }; ADD(ppu.pendingLcdstatIrq); }
|
||||
{ static char const label[] = { s,p,u,c,n,t,r, NUL }; ADD(spu.cycleCounter); }
|
||||
{ static char const label[] = { s,p,u,c,n,t,l, NUL }; ADD(spu.lastUpdate); }
|
||||
{ static char const label[] = { s,w,p,c,n,t,r, NUL }; ADD(spu.ch1.sweep.counter); }
|
||||
{ static char const label[] = { s,w,p,s,h,d,w, NUL }; ADD(spu.ch1.sweep.shadow); }
|
||||
{ static char const label[] = { s,w,p,n,e,g, NUL }; ADD(spu.ch1.sweep.neg); }
|
||||
{ static char const label[] = { d,u,t,NO1,c,t,r, NUL }; ADD(spu.ch1.duty.nextPosUpdate); }
|
||||
{ static char const label[] = { d,u,t,NO1,p,o,s, NUL }; ADD(spu.ch1.duty.pos); }
|
||||
{ static char const label[] = { d,u,t,NO1,h,i, NUL }; ADD(spu.ch1.duty.high); }
|
||||
{ static char const label[] = { e,n,v,NO1,c,t,r, NUL }; ADD(spu.ch1.env.counter); }
|
||||
{ static char const label[] = { e,n,v,NO1,v,o,l, NUL }; ADD(spu.ch1.env.volume); }
|
||||
{ static char const label[] = { l,e,n,NO1,c,t,r, NUL }; ADD(spu.ch1.lcounter.counter); }
|
||||
{ static char const label[] = { l,e,n,NO1,v,a,l, NUL }; ADD(spu.ch1.lcounter.lengthCounter); }
|
||||
{ static char const label[] = { n,r,NO1,NO0, NUL }; ADD(spu.ch1.sweep.nr0); }
|
||||
{ static char const label[] = { n,r,NO1,NO3, NUL }; ADD(spu.ch1.duty.nr3); }
|
||||
{ static char const label[] = { n,r,NO1,NO4, NUL }; ADD(spu.ch1.nr4); }
|
||||
{ static char const label[] = { c,NO1,m,a,s,t,r, NUL }; ADD(spu.ch1.master); }
|
||||
{ static char const label[] = { d,u,t,NO2,c,t,r, NUL }; ADD(spu.ch2.duty.nextPosUpdate); }
|
||||
{ static char const label[] = { d,u,t,NO2,p,o,s, NUL }; ADD(spu.ch2.duty.pos); }
|
||||
{ static char const label[] = { d,u,t,NO2,h,i, NUL }; ADD(spu.ch2.duty.high); }
|
||||
{ static char const label[] = { e,n,v,NO2,c,t,r, NUL }; ADD(spu.ch2.env.counter); }
|
||||
{ static char const label[] = { e,n,v,NO2,v,o,l, NUL }; ADD(spu.ch2.env.volume); }
|
||||
{ static char const label[] = { l,e,n,NO2,c,t,r, NUL }; ADD(spu.ch2.lcounter.counter); }
|
||||
{ static char const label[] = { l,e,n,NO2,v,a,l, NUL }; ADD(spu.ch2.lcounter.lengthCounter); }
|
||||
{ static char const label[] = { n,r,NO2,NO3, NUL }; ADD(spu.ch2.duty.nr3); }
|
||||
{ static char const label[] = { n,r,NO2,NO4, NUL }; ADD(spu.ch2.nr4); }
|
||||
{ static char const label[] = { c,NO2,m,a,s,t,r, NUL }; ADD(spu.ch2.master); }
|
||||
{ static char const label[] = { w,a,v,e,r,a,m, NUL }; ADDPTR(spu.ch3.waveRam); }
|
||||
{ static char const label[] = { l,e,n,NO3,c,t,r, NUL }; ADD(spu.ch3.lcounter.counter); }
|
||||
{ static char const label[] = { l,e,n,NO3,v,a,l, NUL }; ADD(spu.ch3.lcounter.lengthCounter); }
|
||||
{ static char const label[] = { w,a,v,e,c,t,r, NUL }; ADD(spu.ch3.waveCounter); }
|
||||
{ static char const label[] = { l,w,a,v,r,d,t, NUL }; ADD(spu.ch3.lastReadTime); }
|
||||
{ static char const label[] = { w,a,v,e,p,o,s, NUL }; ADD(spu.ch3.wavePos); }
|
||||
{ static char const label[] = { w,a,v,s,m,p,l, NUL }; ADD(spu.ch3.sampleBuf); }
|
||||
{ static char const label[] = { n,r,NO3,NO3, NUL }; ADD(spu.ch3.nr3); }
|
||||
{ static char const label[] = { n,r,NO3,NO4, NUL }; ADD(spu.ch3.nr4); }
|
||||
{ static char const label[] = { c,NO3,m,a,s,t,r, NUL }; ADD(spu.ch3.master); }
|
||||
{ static char const label[] = { l,f,s,r,c,t,r, NUL }; ADD(spu.ch4.lfsr.counter); }
|
||||
{ static char const label[] = { l,f,s,r,r,e,g, NUL }; ADD(spu.ch4.lfsr.reg); }
|
||||
{ static char const label[] = { e,n,v,NO4,c,t,r, NUL }; ADD(spu.ch4.env.counter); }
|
||||
{ static char const label[] = { e,n,v,NO4,v,o,l, NUL }; ADD(spu.ch4.env.volume); }
|
||||
{ static char const label[] = { l,e,n,NO4,c,t,r, NUL }; ADD(spu.ch4.lcounter.counter); }
|
||||
{ static char const label[] = { l,e,n,NO4,v,a,l, NUL }; ADD(spu.ch4.lcounter.lengthCounter); }
|
||||
{ static char const label[] = { n,r,NO4,NO4, NUL }; ADD(spu.ch4.nr4); }
|
||||
{ static char const label[] = { c,NO4,m,a,s,t,r, NUL }; ADD(spu.ch4.master); }
|
||||
{ static char const label[] = { r,t,c,b,a,s,e, NUL }; ADD(rtc.baseTime); }
|
||||
{ static char const label[] = { r,t,c,h,a,l,t, NUL }; ADD(rtc.haltTime); }
|
||||
{ static char const label[] = { r,t,c,d,h, NUL }; ADD(rtc.dataDh); }
|
||||
{ static char const label[] = { r,t,c,d,l, NUL }; ADD(rtc.dataDl); }
|
||||
{ static char const label[] = { r,t,c,h, NUL }; ADD(rtc.dataH); }
|
||||
{ static char const label[] = { r,t,c,m, NUL }; ADD(rtc.dataM); }
|
||||
{ static char const label[] = { r,t,c,s, NUL }; ADD(rtc.dataS); }
|
||||
{ static char const label[] = { r,t,c,l,l,d, NUL }; ADD(rtc.lastLatchData); }
|
||||
|
||||
#undef ADD
|
||||
#undef ADDPTR
|
||||
#undef ADDARRAY
|
||||
|
||||
// sort list for binary search/std::lower_bound use.
|
||||
std::sort(list.begin(), list.end());
|
||||
for (const_iterator it = list.begin(); it != list.end(); ++it)
|
||||
maxLabelsize_ = std::max(maxLabelsize_, it->labelsize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct RgbSum { unsigned long rb, g; };
|
||||
|
||||
void addPairs(RgbSum *const sum, uint_least32_t const *const p) {
|
||||
sum[0].rb += (p[0] & 0xFF00FF) + (p[3] & 0xFF00FF);
|
||||
sum[0].g += (p[0] & 0x00FF00) + (p[3] & 0x00FF00);
|
||||
sum[1].rb += (p[1] & 0xFF00FF) + (p[2] & 0xFF00FF);
|
||||
sum[1].g += (p[1] & 0x00FF00) + (p[2] & 0x00FF00);
|
||||
}
|
||||
|
||||
void blendPairs(RgbSum *const dst, RgbSum const *const sums) {
|
||||
dst->rb = sums[1].rb * 8 + (sums[0].rb - sums[1].rb) * 3;
|
||||
dst->g = sums[1].g * 8 + (sums[0].g - sums[1].g ) * 3;
|
||||
}
|
||||
|
||||
void writeSnapShot(std::ofstream &file, uint_least32_t const *src, std::ptrdiff_t const pitch) {
|
||||
put24(file, src ? StateSaver::ss_width * StateSaver::ss_height * sizeof *src : 0);
|
||||
|
||||
if (src) {
|
||||
uint_least32_t buf[StateSaver::ss_width];
|
||||
|
||||
for (unsigned h = StateSaver::ss_height; h--;) {
|
||||
for (unsigned x = 0; x < StateSaver::ss_width; ++x) {
|
||||
uint_least32_t const *const p = src + x * StateSaver::ss_div;
|
||||
RgbSum sum[] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
|
||||
|
||||
addPairs(sum , p );
|
||||
addPairs(sum + 2, p + pitch );
|
||||
addPairs(sum + 2, p + pitch * 2);
|
||||
addPairs(sum , p + pitch * 3);
|
||||
|
||||
blendPairs(sum, sum);
|
||||
blendPairs(sum + 1, sum + 2);
|
||||
|
||||
blendPairs(sum, sum);
|
||||
|
||||
buf[x] = ((sum[0].rb & 0xFF00FF00) | (sum[0].g & 0x00FF0000)) >> 8;
|
||||
}
|
||||
|
||||
file.write(reinterpret_cast<char const *>(buf), sizeof buf);
|
||||
src += pitch * StateSaver::ss_div;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SaverList list;
|
||||
|
||||
} // anon namespace
|
||||
|
||||
bool StateSaver::saveState(SaveState const &state,
|
||||
uint_least32_t const *const videoBuf,
|
||||
std::ptrdiff_t const pitch, std::string const &filename) {
|
||||
std::ofstream file(filename.c_str(), std::ios_base::binary);
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
{ static char const ver[] = { 0, 1 }; file.write(ver, sizeof ver); }
|
||||
writeSnapShot(file, videoBuf, pitch);
|
||||
|
||||
for (SaverList::const_iterator it = list.begin(); it != list.end(); ++it) {
|
||||
file.write(it->label, it->labelsize);
|
||||
(*it->save)(file, state);
|
||||
}
|
||||
|
||||
return !file.fail();
|
||||
}
|
||||
|
||||
bool StateSaver::loadState(SaveState &state, std::string const &filename) {
|
||||
std::ifstream file(filename.c_str(), std::ios_base::binary);
|
||||
if (!file || file.get() != 0)
|
||||
return false;
|
||||
|
||||
file.ignore();
|
||||
file.ignore(get24(file));
|
||||
|
||||
Array<char> const labelbuf(list.maxLabelsize());
|
||||
Saver const labelbufSaver = { labelbuf, 0, 0, list.maxLabelsize() };
|
||||
SaverList::const_iterator done = list.begin();
|
||||
|
||||
while (file.good() && done != list.end()) {
|
||||
file.getline(labelbuf, list.maxLabelsize(), NUL);
|
||||
|
||||
SaverList::const_iterator it = done;
|
||||
if (std::strcmp(labelbuf, it->label)) {
|
||||
it = std::lower_bound(it + 1, list.end(), labelbufSaver);
|
||||
if (it == list.end() || std::strcmp(labelbuf, it->label)) {
|
||||
file.ignore(get24(file));
|
||||
continue;
|
||||
}
|
||||
} else
|
||||
++done;
|
||||
|
||||
(*it->load)(file, state);
|
||||
}
|
||||
|
||||
state.cpu.cycleCounter &= 0x7FFFFFFF;
|
||||
state.spu.cycleCounter &= 0x7FFFFFFF;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -35,9 +35,11 @@ public:
|
||||
enum { ss_width = 160 >> ss_shift };
|
||||
enum { ss_height = 144 >> ss_shift };
|
||||
|
||||
//> OpenEmu
|
||||
static bool serializeState(SaveState const &state, std::ostream &stream);
|
||||
static bool deserializeState(SaveState &state, std::istream &stream);
|
||||
|
||||
//< OpenEmu
|
||||
static bool saveState(SaveState const &state,
|
||||
uint_least32_t const *videoBuf, std::ptrdiff_t pitch,
|
||||
std::string const &filename);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user