mirror of
https://github.com/FunKey-Project/gpsp_libretro.git
synced 2025-12-12 10:18:51 +01:00
original source from gpsp09-2xb_src.tar.bz2
This commit is contained in:
commit
2823a4c819
340
COPYING.DOC
Normal file
340
COPYING.DOC
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
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.
|
||||||
11
build.txt
Normal file
11
build.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
How to build gpSP for PSP:
|
||||||
|
|
||||||
|
The makefile is in the psp directory, simply go there and type make.
|
||||||
|
make kxploit will build for 1.5 firmware. Be sure to include
|
||||||
|
game_config.txt and gpsp.cfg in the same directory as EBOOT.PBP, as
|
||||||
|
well as gba_bios.bin (not included).
|
||||||
|
|
||||||
|
Dependencies as of v0.6:
|
||||||
|
|
||||||
|
SDL
|
||||||
|
zlib
|
||||||
388
cheats.c
Normal file
388
cheats.c
Normal file
@ -0,0 +1,388 @@
|
|||||||
|
/* gameplaySP
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
cheat_type cheats[MAX_CHEATS];
|
||||||
|
u32 num_cheats;
|
||||||
|
|
||||||
|
void decrypt_gsa_code(u32 *address_ptr, u32 *value_ptr, cheat_variant_enum
|
||||||
|
cheat_variant)
|
||||||
|
{
|
||||||
|
u32 i, i2, code_position;
|
||||||
|
u32 address = *address_ptr;
|
||||||
|
u32 value = *value_ptr;
|
||||||
|
u32 r = 0xc6ef3720;
|
||||||
|
|
||||||
|
u32 seeds_v1[4] =
|
||||||
|
{
|
||||||
|
0x09f4fbbd, 0x9681884a, 0x352027e9, 0xf3dee5a7
|
||||||
|
};
|
||||||
|
u32 seeds_v3[4] =
|
||||||
|
{
|
||||||
|
0x7aa9648f, 0x7fae6994, 0xc0efaad5, 0x42712c57
|
||||||
|
};
|
||||||
|
u32 *seeds;
|
||||||
|
|
||||||
|
if(cheat_variant == CHEAT_TYPE_GAMESHARK_V1)
|
||||||
|
seeds = seeds_v1;
|
||||||
|
else
|
||||||
|
seeds = seeds_v3;
|
||||||
|
|
||||||
|
for(i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
value -= ((address << 4) + seeds[2]) ^ (address + r) ^
|
||||||
|
((address >> 5) + seeds[3]);
|
||||||
|
address -= ((value << 4) + seeds[0]) ^ (value + r) ^
|
||||||
|
((value >> 5) + seeds[1]);
|
||||||
|
r -= 0x9e3779b9;
|
||||||
|
}
|
||||||
|
|
||||||
|
*address_ptr = address;
|
||||||
|
*value_ptr = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_cheats(u8 *cheats_filename)
|
||||||
|
{
|
||||||
|
FILE *cheats_file;
|
||||||
|
u8 current_line[256];
|
||||||
|
u8 *name_ptr;
|
||||||
|
u32 *cheat_code_ptr;
|
||||||
|
u32 address, value;
|
||||||
|
u32 num_cheat_lines;
|
||||||
|
u32 cheat_name_length;
|
||||||
|
cheat_variant_enum current_cheat_variant;
|
||||||
|
|
||||||
|
num_cheats = 0;
|
||||||
|
|
||||||
|
cheats_file = fopen(cheats_filename, "rb");
|
||||||
|
|
||||||
|
if(cheats_file)
|
||||||
|
{
|
||||||
|
while(fgets(current_line, 256, cheats_file))
|
||||||
|
{
|
||||||
|
// Get the header line first
|
||||||
|
name_ptr = strchr(current_line, ' ');
|
||||||
|
if(name_ptr)
|
||||||
|
{
|
||||||
|
*name_ptr = 0;
|
||||||
|
name_ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!strcasecmp(current_line, "gameshark_v1") ||
|
||||||
|
!strcasecmp(current_line, "gameshark_v2") ||
|
||||||
|
!strcasecmp(current_line, "PAR_v1") ||
|
||||||
|
!strcasecmp(current_line, "PAR_v2"))
|
||||||
|
{
|
||||||
|
current_cheat_variant = CHEAT_TYPE_GAMESHARK_V1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
|
||||||
|
if(!strcasecmp(current_line, "gameshark_v3") ||
|
||||||
|
!strcasecmp(current_line, "PAR_v3"))
|
||||||
|
{
|
||||||
|
current_cheat_variant = CHEAT_TYPE_GAMESHARK_V3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_cheat_variant = CHEAT_TYPE_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(current_cheat_variant != CHEAT_TYPE_INVALID)
|
||||||
|
{
|
||||||
|
strncpy(cheats[num_cheats].cheat_name, name_ptr, CHEAT_NAME_LENGTH - 1);
|
||||||
|
cheats[num_cheats].cheat_name[CHEAT_NAME_LENGTH - 1] = 0;
|
||||||
|
cheat_name_length = strlen(cheats[num_cheats].cheat_name);
|
||||||
|
if(cheat_name_length &&
|
||||||
|
(cheats[num_cheats].cheat_name[cheat_name_length - 1] == '\n') ||
|
||||||
|
(cheats[num_cheats].cheat_name[cheat_name_length - 1] == '\r'))
|
||||||
|
{
|
||||||
|
cheats[num_cheats].cheat_name[cheat_name_length - 1] = 0;
|
||||||
|
cheat_name_length--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cheat_name_length &&
|
||||||
|
cheats[num_cheats].cheat_name[cheat_name_length - 1] == '\r')
|
||||||
|
{
|
||||||
|
cheats[num_cheats].cheat_name[cheat_name_length - 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cheats[num_cheats].cheat_variant = current_cheat_variant;
|
||||||
|
cheat_code_ptr = cheats[num_cheats].cheat_codes;
|
||||||
|
num_cheat_lines = 0;
|
||||||
|
|
||||||
|
while(fgets(current_line, 256, cheats_file))
|
||||||
|
{
|
||||||
|
if(strlen(current_line) < 3)
|
||||||
|
break;
|
||||||
|
|
||||||
|
sscanf(current_line, "%08x %08x", &address, &value);
|
||||||
|
|
||||||
|
decrypt_gsa_code(&address, &value, current_cheat_variant);
|
||||||
|
|
||||||
|
cheat_code_ptr[0] = address;
|
||||||
|
cheat_code_ptr[1] = value;
|
||||||
|
|
||||||
|
cheat_code_ptr += 2;
|
||||||
|
num_cheat_lines++;
|
||||||
|
}
|
||||||
|
|
||||||
|
cheats[num_cheats].num_cheat_lines = num_cheat_lines;
|
||||||
|
|
||||||
|
num_cheats++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(cheats_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_cheat_gs1(cheat_type *cheat)
|
||||||
|
{
|
||||||
|
u32 cheat_opcode;
|
||||||
|
u32 *code_ptr = cheat->cheat_codes;
|
||||||
|
u32 address, value;
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
for(i = 0; i < cheat->num_cheat_lines; i++)
|
||||||
|
{
|
||||||
|
address = code_ptr[0];
|
||||||
|
value = code_ptr[1];
|
||||||
|
|
||||||
|
code_ptr += 2;
|
||||||
|
|
||||||
|
cheat_opcode = address >> 28;
|
||||||
|
address &= 0xFFFFFFF;
|
||||||
|
|
||||||
|
switch(cheat_opcode)
|
||||||
|
{
|
||||||
|
case 0x0:
|
||||||
|
write_memory8(address, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x1:
|
||||||
|
write_memory16(address, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x2:
|
||||||
|
write_memory32(address, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x3:
|
||||||
|
{
|
||||||
|
u32 num_addresses = address & 0xFFFF;
|
||||||
|
u32 address1, address2;
|
||||||
|
u32 i2;
|
||||||
|
|
||||||
|
for(i2 = 0; i2 < num_addresses; i2++)
|
||||||
|
{
|
||||||
|
address1 = code_ptr[0];
|
||||||
|
address2 = code_ptr[1];
|
||||||
|
code_ptr += 2;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
write_memory32(address1, value);
|
||||||
|
if(address2 != 0)
|
||||||
|
write_memory32(address2, value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ROM patch not supported yet
|
||||||
|
case 0x6:
|
||||||
|
break;
|
||||||
|
|
||||||
|
// GS button down not supported yet
|
||||||
|
case 0x8:
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Reencryption (DEADFACE) not supported yet
|
||||||
|
case 0xD:
|
||||||
|
if(read_memory16(address) != (value & 0xFFFF))
|
||||||
|
{
|
||||||
|
code_ptr += 2;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xE:
|
||||||
|
if(read_memory16(value & 0xFFFFFFF) != (address & 0xFFFF))
|
||||||
|
{
|
||||||
|
u32 skip = ((address >> 16) & 0x03);
|
||||||
|
code_ptr += skip * 2;
|
||||||
|
i += skip;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Hook routine not supported yet (not important??)
|
||||||
|
case 0x0F:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are especially incomplete.
|
||||||
|
|
||||||
|
void process_cheat_gs3(cheat_type *cheat)
|
||||||
|
{
|
||||||
|
u32 cheat_opcode;
|
||||||
|
u32 *code_ptr = cheat->cheat_codes;
|
||||||
|
u32 address, value;
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
for(i = 0; i < cheat->num_cheat_lines; i++)
|
||||||
|
{
|
||||||
|
address = code_ptr[0];
|
||||||
|
value = code_ptr[1];
|
||||||
|
|
||||||
|
code_ptr += 2;
|
||||||
|
|
||||||
|
cheat_opcode = address >> 28;
|
||||||
|
address &= 0xFFFFFFF;
|
||||||
|
|
||||||
|
switch(cheat_opcode)
|
||||||
|
{
|
||||||
|
case 0x0:
|
||||||
|
cheat_opcode = address >> 24;
|
||||||
|
address = (address & 0xFFFFF) + ((address << 4) & 0xF000000);
|
||||||
|
|
||||||
|
switch(cheat_opcode)
|
||||||
|
{
|
||||||
|
case 0x0:
|
||||||
|
{
|
||||||
|
u32 iterations = value >> 24;
|
||||||
|
u32 i2;
|
||||||
|
|
||||||
|
value &= 0xFF;
|
||||||
|
|
||||||
|
for(i2 = 0; i2 <= iterations; i2++, address++)
|
||||||
|
{
|
||||||
|
write_memory8(address, value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x2:
|
||||||
|
{
|
||||||
|
u32 iterations = value >> 16;
|
||||||
|
u32 i2;
|
||||||
|
|
||||||
|
value &= 0xFFFF;
|
||||||
|
|
||||||
|
for(i2 = 0; i2 <= iterations; i2++, address += 2)
|
||||||
|
{
|
||||||
|
write_memory16(address, value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x4:
|
||||||
|
write_memory32(address, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x4:
|
||||||
|
cheat_opcode = address >> 24;
|
||||||
|
address = (address & 0xFFFFF) + ((address << 4) & 0xF000000);
|
||||||
|
|
||||||
|
switch(cheat_opcode)
|
||||||
|
{
|
||||||
|
case 0x0:
|
||||||
|
address = read_memory32(address) + (value >> 24);
|
||||||
|
write_memory8(address, value & 0xFF);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x2:
|
||||||
|
address = read_memory32(address) + ((value >> 16) * 2);
|
||||||
|
write_memory16(address, value & 0xFFFF);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x4:
|
||||||
|
address = read_memory32(address);
|
||||||
|
write_memory32(address, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x8:
|
||||||
|
cheat_opcode = address >> 24;
|
||||||
|
address = (address & 0xFFFFF) + ((address << 4) & 0xF000000);
|
||||||
|
|
||||||
|
switch(cheat_opcode)
|
||||||
|
{
|
||||||
|
case 0x0:
|
||||||
|
value = (value & 0xFF) + read_memory8(address);
|
||||||
|
write_memory8(address, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x2:
|
||||||
|
value = (value & 0xFFFF) + read_memory16(address);
|
||||||
|
write_memory16(address, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x4:
|
||||||
|
value = value + read_memory32(address);
|
||||||
|
write_memory32(address, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xC:
|
||||||
|
cheat_opcode = address >> 24;
|
||||||
|
address = (address & 0xFFFFFF) + 0x4000000;
|
||||||
|
|
||||||
|
switch(cheat_opcode)
|
||||||
|
{
|
||||||
|
case 0x6:
|
||||||
|
write_memory16(address, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x7:
|
||||||
|
write_memory32(address, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void process_cheats()
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
for(i = 0; i < num_cheats; i++)
|
||||||
|
{
|
||||||
|
if(cheats[i].cheat_active)
|
||||||
|
{
|
||||||
|
switch(cheats[i].cheat_variant)
|
||||||
|
{
|
||||||
|
case CHEAT_TYPE_GAMESHARK_V1:
|
||||||
|
process_cheat_gs1(cheats + i);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CHEAT_TYPE_GAMESHARK_V3:
|
||||||
|
process_cheat_gs3(cheats + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
44
cheats.h
Normal file
44
cheats.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/* gameplaySP
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CHEAT_NAME_LENGTH 17
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CHEAT_TYPE_GAMESHARK_V1,
|
||||||
|
CHEAT_TYPE_GAMESHARK_V3,
|
||||||
|
CHEAT_TYPE_INVALID
|
||||||
|
} cheat_variant_enum;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u8 cheat_name[CHEAT_NAME_LENGTH];
|
||||||
|
u32 cheat_active;
|
||||||
|
u32 cheat_codes[256];
|
||||||
|
u32 num_cheat_lines;
|
||||||
|
cheat_variant_enum cheat_variant;
|
||||||
|
} cheat_type;
|
||||||
|
|
||||||
|
void process_cheats();
|
||||||
|
void add_cheats(u8 *cheats_filename);
|
||||||
|
|
||||||
|
#define MAX_CHEATS 16
|
||||||
|
|
||||||
|
extern cheat_type cheats[MAX_CHEATS];
|
||||||
|
extern u32 num_cheats;
|
||||||
276
common.h
Normal file
276
common.h
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
/* gameplaySP
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COMMON_H
|
||||||
|
#define COMMON_H
|
||||||
|
|
||||||
|
#define ror(dest, value, shift) \
|
||||||
|
dest = ((value) >> shift) | ((value) << (32 - shift)) \
|
||||||
|
|
||||||
|
// These includes must be used before SDL is included.
|
||||||
|
#ifdef ARM_ARCH
|
||||||
|
|
||||||
|
#ifdef _WIN32_WCE
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif /* _WIN32_WCE */
|
||||||
|
|
||||||
|
#ifdef GIZ_BUILD
|
||||||
|
#include "giz/giz.h"
|
||||||
|
#endif
|
||||||
|
#endif /* ARM_ARCH */
|
||||||
|
|
||||||
|
// Huge thanks to pollux for the heads up on using native file I/O
|
||||||
|
// functions on PSP for vastly improved memstick performance.
|
||||||
|
|
||||||
|
#define file_write_mem(filename_tag, buffer, size) \
|
||||||
|
{ \
|
||||||
|
memcpy(write_mem_ptr, buffer, size); \
|
||||||
|
write_mem_ptr += size; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define file_write_mem_array(filename_tag, array) \
|
||||||
|
file_write_mem(filename_tag, array, sizeof(array)) \
|
||||||
|
|
||||||
|
#define file_write_mem_variable(filename_tag, variable) \
|
||||||
|
file_write_mem(filename_tag, &variable, sizeof(variable)) \
|
||||||
|
|
||||||
|
#ifdef PSP_BUILD
|
||||||
|
#define fastcall
|
||||||
|
|
||||||
|
#include <pspkernel.h>
|
||||||
|
#include <pspdebug.h>
|
||||||
|
#include <pspctrl.h>
|
||||||
|
#include <pspgu.h>
|
||||||
|
#include <pspaudio.h>
|
||||||
|
#include <pspaudiolib.h>
|
||||||
|
#include <psprtc.h>
|
||||||
|
|
||||||
|
#define function_cc
|
||||||
|
|
||||||
|
#define convert_palette(value) \
|
||||||
|
value = ((value & 0x7FE0) << 1) | (value & 0x1F) \
|
||||||
|
|
||||||
|
#define psp_file_open_read PSP_O_RDONLY
|
||||||
|
#define psp_file_open_write (PSP_O_CREAT | PSP_O_WRONLY | PSP_O_TRUNC)
|
||||||
|
|
||||||
|
#define file_open(filename_tag, filename, mode) \
|
||||||
|
s32 filename_tag = sceIoOpen(filename, psp_file_open_##mode, 0777) \
|
||||||
|
|
||||||
|
#define file_check_valid(filename_tag) \
|
||||||
|
(filename_tag >= 0) \
|
||||||
|
|
||||||
|
#define file_close(filename_tag) \
|
||||||
|
sceIoClose(filename_tag) \
|
||||||
|
|
||||||
|
#define file_read(filename_tag, buffer, size) \
|
||||||
|
sceIoRead(filename_tag, buffer, size) \
|
||||||
|
|
||||||
|
#define file_write(filename_tag, buffer, size) \
|
||||||
|
sceIoWrite(filename_tag, buffer, size) \
|
||||||
|
|
||||||
|
#define file_seek(filename_tag, offset, type) \
|
||||||
|
sceIoLseek(filename_tag, offset, PSP_##type) \
|
||||||
|
|
||||||
|
#define file_tag_type s32
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#else
|
||||||
|
#include "SDL.h"
|
||||||
|
|
||||||
|
#ifdef ARM_ARCH
|
||||||
|
#define function_cc
|
||||||
|
#else
|
||||||
|
#define function_cc __attribute__((regparm(2)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef unsigned char u8;
|
||||||
|
typedef signed char s8;
|
||||||
|
typedef unsigned short int u16;
|
||||||
|
typedef signed short int s16;
|
||||||
|
typedef unsigned long u32;
|
||||||
|
typedef signed long s32;
|
||||||
|
typedef unsigned long long int u64;
|
||||||
|
typedef signed long long int s64;
|
||||||
|
|
||||||
|
#define convert_palette(value) \
|
||||||
|
value = ((value & 0x1F) << 11) | ((value & 0x03E0) << 1) | (value >> 10) \
|
||||||
|
|
||||||
|
#define stdio_file_open_read "rb"
|
||||||
|
#define stdio_file_open_write "wb"
|
||||||
|
|
||||||
|
#define file_open(filename_tag, filename, mode) \
|
||||||
|
FILE *filename_tag = fopen(filename, stdio_file_open_##mode) \
|
||||||
|
|
||||||
|
#define file_check_valid(filename_tag) \
|
||||||
|
(filename_tag) \
|
||||||
|
|
||||||
|
#ifdef GP2X_BUILD
|
||||||
|
|
||||||
|
#define file_close(filename_tag) \
|
||||||
|
{ \
|
||||||
|
sync(); \
|
||||||
|
fclose(filename_tag); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define file_close(filename_tag) \
|
||||||
|
fclose(filename_tag) \
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define file_read(filename_tag, buffer, size) \
|
||||||
|
fread(buffer, size, 1, filename_tag) \
|
||||||
|
|
||||||
|
#define file_write(filename_tag, buffer, size) \
|
||||||
|
fwrite(buffer, size, 1, filename_tag) \
|
||||||
|
|
||||||
|
#define file_seek(filename_tag, offset, type) \
|
||||||
|
fseek(filename_tag, offset, type) \
|
||||||
|
|
||||||
|
#define file_tag_type FILE *
|
||||||
|
|
||||||
|
// The ARM arch uses SDL, and SDL requires you to know what resolution
|
||||||
|
// you want. Define the resolution for ARM arch builds here.
|
||||||
|
// Placed in common.h for use with video.c and gui.c.
|
||||||
|
|
||||||
|
#ifndef PC_BUILD
|
||||||
|
|
||||||
|
#define GP2X_SCREEN_WIDTH 320
|
||||||
|
#define GP2X_SCREEN_HEIGHT 240
|
||||||
|
|
||||||
|
#define GIZ_SCREEN_WIDTH 320
|
||||||
|
#define GIZ_SCREEN_HEIGHT 240
|
||||||
|
|
||||||
|
#ifdef GP2X_BUILD
|
||||||
|
#define SDL_SCREEN_WIDTH GP2X_SCREEN_WIDTH
|
||||||
|
#define SDL_SCREEN_HEIGHT GP2X_SCREEN_HEIGHT
|
||||||
|
|
||||||
|
#elif defined(GIZ_BUILD)
|
||||||
|
|
||||||
|
#define SDL_SCREEN_WIDTH GIZ_SCREEN_WIDTH
|
||||||
|
#define SDL_SCREEN_HEIGHT GIZ_SCREEN_HEIGHT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// These must be variables, not constants.
|
||||||
|
|
||||||
|
#define file_read_variable(filename_tag, variable) \
|
||||||
|
file_read(filename_tag, &variable, sizeof(variable)) \
|
||||||
|
|
||||||
|
#define file_write_variable(filename_tag, variable) \
|
||||||
|
file_write(filename_tag, &variable, sizeof(variable)) \
|
||||||
|
|
||||||
|
// These must be statically declared arrays (ie, global or on the stack,
|
||||||
|
// not dynamically allocated on the heap)
|
||||||
|
|
||||||
|
#define file_read_array(filename_tag, array) \
|
||||||
|
file_read(filename_tag, array, sizeof(array)) \
|
||||||
|
|
||||||
|
#define file_write_array(filename_tag, array) \
|
||||||
|
file_write(filename_tag, array, sizeof(array)) \
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef u32 fixed16_16;
|
||||||
|
|
||||||
|
#define float_to_fp16_16(value) \
|
||||||
|
(fixed16_16)((value) * 65536.0) \
|
||||||
|
|
||||||
|
#define fp16_16_to_float(value) \
|
||||||
|
(float)((value) / 65536.0) \
|
||||||
|
|
||||||
|
#define u32_to_fp16_16(value) \
|
||||||
|
((value) << 16) \
|
||||||
|
|
||||||
|
#define fp16_16_to_u32(value) \
|
||||||
|
((value) >> 16) \
|
||||||
|
|
||||||
|
#define fp16_16_fractional_part(value) \
|
||||||
|
((value) & 0xFFFF) \
|
||||||
|
|
||||||
|
#define fixed_div(numerator, denominator, bits) \
|
||||||
|
(((numerator * (1 << bits)) + (denominator / 2)) / denominator) \
|
||||||
|
|
||||||
|
#define address8(base, offset) \
|
||||||
|
*((u8 *)((u8 *)base + (offset))) \
|
||||||
|
|
||||||
|
#define address16(base, offset) \
|
||||||
|
*((u16 *)((u8 *)base + (offset))) \
|
||||||
|
|
||||||
|
#define address32(base, offset) \
|
||||||
|
*((u32 *)((u8 *)base + (offset))) \
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "SDL.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "video.h"
|
||||||
|
#include "input.h"
|
||||||
|
#include "sound.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "gui.h"
|
||||||
|
#include "zip.h"
|
||||||
|
#include "cheats.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PSP_BUILD
|
||||||
|
#define printf pspDebugScreenPrintf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PC_BUILD
|
||||||
|
#define STDIO_DEBUG
|
||||||
|
//#define REGISTER_USAGE_ANALYZE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GP2X_BUILD
|
||||||
|
#include <strings.h>
|
||||||
|
#include "gp2x/gp2x.h"
|
||||||
|
|
||||||
|
#define printf(format, ...) \
|
||||||
|
fprintf(stderr, format, ##__VA_ARGS__) \
|
||||||
|
|
||||||
|
#define vprintf(format, ap) \
|
||||||
|
vfprintf(stderr, format, ap) \
|
||||||
|
|
||||||
|
void gp2x_overclock(void);
|
||||||
|
|
||||||
|
// #define STDIO_DEBUG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
210
cpu.h
Normal file
210
cpu.h
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
/* gameplaySP
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPU_H
|
||||||
|
#define CPU_H
|
||||||
|
|
||||||
|
// System mode and user mode are represented as the same here
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MODE_USER,
|
||||||
|
MODE_IRQ,
|
||||||
|
MODE_FIQ,
|
||||||
|
MODE_SUPERVISOR,
|
||||||
|
MODE_ABORT,
|
||||||
|
MODE_UNDEFINED,
|
||||||
|
MODE_INVALID
|
||||||
|
} cpu_mode_type;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CPU_ALERT_NONE,
|
||||||
|
CPU_ALERT_HALT,
|
||||||
|
CPU_ALERT_SMC,
|
||||||
|
CPU_ALERT_IRQ
|
||||||
|
} cpu_alert_type;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CPU_ACTIVE,
|
||||||
|
CPU_HALT,
|
||||||
|
CPU_STOP
|
||||||
|
} cpu_halt_type;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
IRQ_NONE = 0x0000,
|
||||||
|
IRQ_VBLANK = 0x0001,
|
||||||
|
IRQ_HBLANK = 0x0002,
|
||||||
|
IRQ_VCOUNT = 0x0004,
|
||||||
|
IRQ_TIMER0 = 0x0008,
|
||||||
|
IRQ_TIMER1 = 0x0010,
|
||||||
|
IRQ_TIMER2 = 0x0020,
|
||||||
|
IRQ_TIMER3 = 0x0040,
|
||||||
|
IRQ_SERIAL = 0x0080,
|
||||||
|
IRQ_DMA0 = 0x0100,
|
||||||
|
IRQ_DMA1 = 0x0200,
|
||||||
|
IRQ_DMA2 = 0x0400,
|
||||||
|
IRQ_DMA3 = 0x0800,
|
||||||
|
IRQ_KEYPAD = 0x1000,
|
||||||
|
IRQ_GAMEPAK = 0x2000,
|
||||||
|
} irq_type;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
REG_SP = 13,
|
||||||
|
REG_LR = 14,
|
||||||
|
REG_PC = 15,
|
||||||
|
REG_N_FLAG = 16,
|
||||||
|
REG_Z_FLAG = 17,
|
||||||
|
REG_C_FLAG = 18,
|
||||||
|
REG_V_FLAG = 19,
|
||||||
|
REG_CPSR = 20,
|
||||||
|
REG_SAVE = 21,
|
||||||
|
REG_SAVE2 = 22,
|
||||||
|
REG_SAVE3 = 23,
|
||||||
|
CPU_MODE = 29,
|
||||||
|
CPU_HALT_STATE = 30,
|
||||||
|
CHANGED_PC_STATUS = 31
|
||||||
|
} ext_reg_numbers;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
STEP,
|
||||||
|
PC_BREAKPOINT,
|
||||||
|
VCOUNT_BREAKPOINT,
|
||||||
|
Z_BREAKPOINT,
|
||||||
|
COUNTDOWN_BREAKPOINT,
|
||||||
|
COUNTDOWN_BREAKPOINT_B,
|
||||||
|
COUNTDOWN_BREAKPOINT_C,
|
||||||
|
STEP_RUN,
|
||||||
|
RUN
|
||||||
|
} debug_state;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
TRANSLATION_REGION_RAM,
|
||||||
|
TRANSLATION_REGION_ROM,
|
||||||
|
TRANSLATION_REGION_BIOS
|
||||||
|
} translation_region_type;
|
||||||
|
|
||||||
|
extern debug_state current_debug_state;
|
||||||
|
extern u32 instruction_count;
|
||||||
|
extern u32 last_instruction;
|
||||||
|
|
||||||
|
u32 function_cc step_debug(u32 pc, u32 cycles);
|
||||||
|
u32 execute_arm(u32 cycles);
|
||||||
|
void raise_interrupt(irq_type irq_raised);
|
||||||
|
|
||||||
|
u32 function_cc execute_load_u8(u32 address);
|
||||||
|
u32 function_cc execute_load_u16(u32 address);
|
||||||
|
u32 function_cc execute_load_u32(u32 address);
|
||||||
|
u32 function_cc execute_load_s8(u32 address);
|
||||||
|
u32 function_cc execute_load_s16(u32 address);
|
||||||
|
void function_cc execute_store_u8(u32 address, u32 source);
|
||||||
|
void function_cc execute_store_u16(u32 address, u32 source);
|
||||||
|
void function_cc execute_store_u32(u32 address, u32 source);
|
||||||
|
u32 function_cc execute_arm_translate(u32 cycles);
|
||||||
|
void init_translater();
|
||||||
|
void cpu_write_mem_savestate(file_tag_type savestate_file);
|
||||||
|
void cpu_read_savestate(file_tag_type savestate_file);
|
||||||
|
|
||||||
|
u8 function_cc *block_lookup_address_arm(u32 pc);
|
||||||
|
u8 function_cc *block_lookup_address_thumb(u32 pc);
|
||||||
|
s32 translate_block_arm(u32 pc, translation_region_type translation_region,
|
||||||
|
u32 smc_enable);
|
||||||
|
s32 translate_block_thumb(u32 pc, translation_region_type translation_region,
|
||||||
|
u32 smc_enable);
|
||||||
|
|
||||||
|
#ifdef GP2X_BUILD
|
||||||
|
#define ROM_TRANSLATION_CACHE_SIZE (1024 * 512 * 4 * 5)
|
||||||
|
#define RAM_TRANSLATION_CACHE_SIZE (1024 * 384 * 2)
|
||||||
|
#define BIOS_TRANSLATION_CACHE_SIZE (1024 * 128 * 2)
|
||||||
|
#define TRANSLATION_CACHE_LIMIT_THRESHOLD (1024 * 32)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define ROM_TRANSLATION_CACHE_SIZE (1024 * 512 * 4)
|
||||||
|
#define RAM_TRANSLATION_CACHE_SIZE (1024 * 384)
|
||||||
|
#define BIOS_TRANSLATION_CACHE_SIZE (1024 * 128)
|
||||||
|
#define TRANSLATION_CACHE_LIMIT_THRESHOLD (1024)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern u8 rom_translation_cache[ROM_TRANSLATION_CACHE_SIZE];
|
||||||
|
extern u8 ram_translation_cache[RAM_TRANSLATION_CACHE_SIZE];
|
||||||
|
extern u8 bios_translation_cache[BIOS_TRANSLATION_CACHE_SIZE];
|
||||||
|
extern u8 *rom_translation_ptr;
|
||||||
|
extern u8 *ram_translation_ptr;
|
||||||
|
extern u8 *bios_translation_ptr;
|
||||||
|
|
||||||
|
#define MAX_TRANSLATION_GATES 8
|
||||||
|
|
||||||
|
extern u32 idle_loop_target_pc;
|
||||||
|
extern u32 force_pc_update_target;
|
||||||
|
extern u32 iwram_stack_optimize;
|
||||||
|
extern u32 allow_smc_ram_u8;
|
||||||
|
extern u32 allow_smc_ram_u16;
|
||||||
|
extern u32 allow_smc_ram_u32;
|
||||||
|
extern u32 direct_map_vram;
|
||||||
|
extern u32 translation_gate_targets;
|
||||||
|
extern u32 translation_gate_target_pc[MAX_TRANSLATION_GATES];
|
||||||
|
|
||||||
|
extern u32 in_interrupt;
|
||||||
|
|
||||||
|
#define ROM_BRANCH_HASH_SIZE (1024 * 64)
|
||||||
|
|
||||||
|
/* EDIT: Shouldn't this be extern ?! */
|
||||||
|
extern u32 *rom_branch_hash[ROM_BRANCH_HASH_SIZE];
|
||||||
|
|
||||||
|
void flush_translation_cache_rom();
|
||||||
|
void flush_translation_cache_ram();
|
||||||
|
void flush_translation_cache_bios();
|
||||||
|
void dump_translation_cache();
|
||||||
|
|
||||||
|
extern u32 reg_mode[7][7];
|
||||||
|
extern u32 spsr[6];
|
||||||
|
|
||||||
|
extern u32 cpu_modes[32];
|
||||||
|
extern const u32 psr_masks[16];
|
||||||
|
|
||||||
|
extern u32 breakpoint_value;
|
||||||
|
|
||||||
|
extern u32 memory_region_access_read_u8[16];
|
||||||
|
extern u32 memory_region_access_read_s8[16];
|
||||||
|
extern u32 memory_region_access_read_u16[16];
|
||||||
|
extern u32 memory_region_access_read_s16[16];
|
||||||
|
extern u32 memory_region_access_read_u32[16];
|
||||||
|
extern u32 memory_region_access_write_u8[16];
|
||||||
|
extern u32 memory_region_access_write_u16[16];
|
||||||
|
extern u32 memory_region_access_write_u32[16];
|
||||||
|
extern u32 memory_reads_u8;
|
||||||
|
extern u32 memory_reads_s8;
|
||||||
|
extern u32 memory_reads_u16;
|
||||||
|
extern u32 memory_reads_s16;
|
||||||
|
extern u32 memory_reads_u32;
|
||||||
|
extern u32 memory_writes_u8;
|
||||||
|
extern u32 memory_writes_u16;
|
||||||
|
extern u32 memory_writes_u32;
|
||||||
|
|
||||||
|
void init_cpu();
|
||||||
|
void move_reg();
|
||||||
|
|
||||||
|
#endif
|
||||||
3508
cpu_threaded.c
Normal file
3508
cpu_threaded.c
Normal file
File diff suppressed because it is too large
Load Diff
184
disasm.c
Normal file
184
disasm.c
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
/* gameplaySP
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define arm_decode_data_proc_reg() \
|
||||||
|
u32 rn = (opcode >> 16) & 0x0F; \
|
||||||
|
u32 rd = (opcode >> 12) & 0x0F; \
|
||||||
|
u32 rm = opcode & 0x0F \
|
||||||
|
|
||||||
|
#define arm_decode_data_proc_imm() \
|
||||||
|
u32 rn = (opcode >> 16) & 0x0F; \
|
||||||
|
u32 rd = (opcode >> 12) & 0x0F; \
|
||||||
|
u32 imm; \
|
||||||
|
ror(imm, opcode & 0xFF, ((opcode >> 8) & 0x0F) * 2) \
|
||||||
|
|
||||||
|
#define arm_decode_psr_reg() \
|
||||||
|
u32 psr_field = (opcode >> 16) & 0x0F; \
|
||||||
|
u32 rd = (opcode >> 12) & 0x0F; \
|
||||||
|
u32 rm = opcode & 0x0F \
|
||||||
|
|
||||||
|
#define arm_decode_psr_imm() \
|
||||||
|
u32 psr_field = (opcode >> 16) & 0x0F; \
|
||||||
|
u32 rd = (opcode >> 12) & 0x0F; \
|
||||||
|
u32 imm; \
|
||||||
|
ror(imm, opcode & 0xFF, ((opcode >> 8) & 0x0F) * 2) \
|
||||||
|
|
||||||
|
#define arm_decode_branchx() \
|
||||||
|
u32 rn = opcode & 0x0F \
|
||||||
|
|
||||||
|
#define arm_decode_multiply() \
|
||||||
|
u32 rd = (opcode >> 16) & 0x0F; \
|
||||||
|
u32 rn = (opcode >> 12) & 0x0F; \
|
||||||
|
u32 rs = (opcode >> 8) & 0x0F; \
|
||||||
|
u32 rm = opcode & 0x0F \
|
||||||
|
|
||||||
|
#define arm_decode_multiply_long() \
|
||||||
|
u32 rdhi = (opcode >> 16) & 0x0F; \
|
||||||
|
u32 rdlo = (opcode >> 12) & 0x0F; \
|
||||||
|
u32 rn = (opcode >> 8) & 0x0F; \
|
||||||
|
u32 rm = opcode & 0x0F \
|
||||||
|
|
||||||
|
#define arm_decode_swap() \
|
||||||
|
u32 rn = (opcode >> 16) & 0x0F; \
|
||||||
|
u32 rd = (opcode >> 12) & 0x0F; \
|
||||||
|
u32 rm = opcode & 0x0F \
|
||||||
|
|
||||||
|
#define arm_decode_half_trans_r() \
|
||||||
|
u32 rn = (opcode >> 16) & 0x0F; \
|
||||||
|
u32 rd = (opcode >> 12) & 0x0F; \
|
||||||
|
u32 rm = opcode & 0x0F \
|
||||||
|
|
||||||
|
#define arm_decode_half_trans_of() \
|
||||||
|
u32 rn = (opcode >> 16) & 0x0F; \
|
||||||
|
u32 rd = (opcode >> 12) & 0x0F; \
|
||||||
|
u32 offset = ((opcode >> 4) & 0xF0) | (opcode & 0x0F) \
|
||||||
|
|
||||||
|
#define arm_decode_data_trans_imm() \
|
||||||
|
u32 rn = (opcode >> 16) & 0x0F; \
|
||||||
|
u32 rd = (opcode >> 12) & 0x0F; \
|
||||||
|
u32 offset = opcode & 0x0FFF \
|
||||||
|
|
||||||
|
#define arm_decode_data_trans_reg() \
|
||||||
|
u32 rn = (opcode >> 16) & 0x0F; \
|
||||||
|
u32 rd = (opcode >> 12) & 0x0F; \
|
||||||
|
u32 rm = opcode & 0x0F \
|
||||||
|
|
||||||
|
#define arm_decode_block_trans() \
|
||||||
|
u32 rn = (opcode >> 16) & 0x0F; \
|
||||||
|
u32 reg_list = opcode & 0xFFFF \
|
||||||
|
|
||||||
|
#define arm_decode_branch() \
|
||||||
|
s32 offset = ((s32)(opcode & 0xFFFFFF) << 8) >> 6 \
|
||||||
|
|
||||||
|
#define thumb_decode_shift() \
|
||||||
|
u32 imm = (opcode >> 6) & 0x1F; \
|
||||||
|
u32 rs = (opcode >> 3) & 0x07; \
|
||||||
|
u32 rd = opcode & 0x07 \
|
||||||
|
|
||||||
|
#define thumb_decode_add_sub() \
|
||||||
|
u32 rn = (opcode >> 6) & 0x07; \
|
||||||
|
u32 rs = (opcode >> 3) & 0x07; \
|
||||||
|
u32 rd = opcode & 0x07 \
|
||||||
|
|
||||||
|
#define thumb_decode_add_sub_imm() \
|
||||||
|
u32 imm = (opcode >> 6) & 0x07; \
|
||||||
|
u32 rs = (opcode >> 3) & 0x07; \
|
||||||
|
u32 rd = opcode & 0x07 \
|
||||||
|
|
||||||
|
#define thumb_decode_imm() \
|
||||||
|
u32 imm = opcode & 0xFF \
|
||||||
|
|
||||||
|
#define thumb_decode_alu_op() \
|
||||||
|
u32 rs = (opcode >> 3) & 0x07; \
|
||||||
|
u32 rd = opcode & 0x07 \
|
||||||
|
|
||||||
|
#define thumb_decode_hireg_op() \
|
||||||
|
u32 rs = (opcode >> 3) & 0x0F; \
|
||||||
|
u32 rd = ((opcode >> 4) & 0x08) | (opcode & 0x07) \
|
||||||
|
|
||||||
|
#define thumb_decode_mem_reg() \
|
||||||
|
u32 ro = (opcode >> 6) & 0x07; \
|
||||||
|
u32 rb = (opcode >> 3) & 0x07; \
|
||||||
|
u32 rd = opcode & 0x07 \
|
||||||
|
|
||||||
|
#define thumb_decode_mem_imm() \
|
||||||
|
u32 imm = (opcode >> 6) & 0x1F; \
|
||||||
|
u32 rb = (opcode >> 3) & 0x07; \
|
||||||
|
u32 rd = opcode & 0x07 \
|
||||||
|
|
||||||
|
#define thumb_decode_add_sp() \
|
||||||
|
u32 imm = opcode & 0x7F \
|
||||||
|
|
||||||
|
#define thumb_decode_rlist() \
|
||||||
|
u32 reg_list = opcode & 0xFF \
|
||||||
|
|
||||||
|
#define thumb_decode_branch_cond() \
|
||||||
|
s32 offset = (s8)(opcode & 0xFF) \
|
||||||
|
|
||||||
|
#define thumb_decode_swi() \
|
||||||
|
u32 comment = opcode & 0xFF \
|
||||||
|
|
||||||
|
#define thumb_decode_branch() \
|
||||||
|
u32 offset = opcode & 0x07FF \
|
||||||
|
|
||||||
|
const char *condition_table[] =
|
||||||
|
{
|
||||||
|
"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
|
||||||
|
"hi", "ls", "ge", "lt", "gt", "le", "al", "nv"
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *data_proc_opcode_table[] =
|
||||||
|
{
|
||||||
|
"and", "eor", "sub", "rsb", "add", "adc", "sbc", "rsc",
|
||||||
|
"tst", "teq", "cmp", "cmn", "orr", "mov", "bic", "mvn"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
u32 print_disasm_arm_instruction(u32 opcode)
|
||||||
|
{
|
||||||
|
u32 condition = opcode >> 28;
|
||||||
|
|
||||||
|
switch((opcode >> 25) & 0x07)
|
||||||
|
{
|
||||||
|
// Data processing reg, multiply, bx, memory transfer half/byte, swap,
|
||||||
|
// PSR reg
|
||||||
|
case 0x0:
|
||||||
|
|
||||||
|
// Data processing imm, PSR imm
|
||||||
|
case 0x1:
|
||||||
|
|
||||||
|
// Memory transfer imm
|
||||||
|
case 0x2:
|
||||||
|
|
||||||
|
// Memory transfer reg, undefined
|
||||||
|
case 0x3:
|
||||||
|
|
||||||
|
// Block memory transfer
|
||||||
|
case 0x4:
|
||||||
|
|
||||||
|
// Branch
|
||||||
|
case 0x5:
|
||||||
|
|
||||||
|
// Coprocessor
|
||||||
|
case 0x6:
|
||||||
|
|
||||||
|
// Coprocessor, SWI
|
||||||
|
case 0x7:
|
||||||
|
}
|
||||||
932
game_config.txt
Normal file
932
game_config.txt
Normal file
@ -0,0 +1,932 @@
|
|||||||
|
# gpSP game settings database
|
||||||
|
|
||||||
|
# What is this file??? game_config.txt is a database of settings on a
|
||||||
|
# per-game basis. A couple of the settings are required to make games
|
||||||
|
# work at all, but most of them are there to improve the performance of
|
||||||
|
# a game. If a game doesn't work then look through the settings here,
|
||||||
|
# but keep in mind that this file can not be used to fix a majority of
|
||||||
|
# games, the ones that don't work because of emulator bugs. For those
|
||||||
|
# you'll have to wait for a new release and hope it someday gets fixed.
|
||||||
|
|
||||||
|
# This file is meant to be edited in plain text, with a normal editor.
|
||||||
|
# game_name, game_code, and vender_code can be found in the game's header.
|
||||||
|
# All three must match for the game to be used, and those setting must be
|
||||||
|
# in that order. Be sure to use [!] ROMs (verified by GoodGBA) when
|
||||||
|
# building this list. Right now I don't know how much overlap there is
|
||||||
|
# between different region games, but usually idle loops don't apply to
|
||||||
|
# them. If you're using a different region than the one in here you can
|
||||||
|
# try copying the entry, it might improve it.
|
||||||
|
|
||||||
|
# You can also find the three identifying codes on the second line from
|
||||||
|
# the top in gpSP's main menu. So anyone should be able to add settings
|
||||||
|
# to this file if they know what to set, but for some options it'll take
|
||||||
|
# a lot of special knowledge for them to be of any use. Be sure to see if
|
||||||
|
# your game is already here, but only if the game_name/game_code/
|
||||||
|
# vender_code all match. Only the first full match's settings will be used.
|
||||||
|
|
||||||
|
# Everything here is case sensitive. Don't mess with this file unless
|
||||||
|
# you know what you're doing - if in doubt sooner ask someone who does.
|
||||||
|
|
||||||
|
# I mainly focus on USA versions, so try those first. And, just because
|
||||||
|
# a game is on here doesn't mean the game actually works in the current
|
||||||
|
# version. :/
|
||||||
|
|
||||||
|
# These are the following options:
|
||||||
|
|
||||||
|
# idle_loop_eliminate_target - tells the recompiler that this branch
|
||||||
|
# is an idle loop and thus a hardware update should follow it every
|
||||||
|
# time. This is purely a speed improvement and is not meant to improve
|
||||||
|
# compatibility - if it does it represents a strange timing problem in
|
||||||
|
# the game. You can only set one of these for now. Don't use this if
|
||||||
|
# you don't know what you're doing, it can break the game. Some games
|
||||||
|
# will run miserably slowly without this option.
|
||||||
|
|
||||||
|
# translation_gate_target - tells the recompiler to put an indirect
|
||||||
|
# branch (gate) at this point, so artificially stop the current block.
|
||||||
|
# This is useful if the game performs self modifying code from within
|
||||||
|
# the same block it is currently executing - this can prevent it from
|
||||||
|
# causing SMC hits far more times than it should. This is also only a
|
||||||
|
# speed hack; you can have up to 8 of these. Don't use this if you don't
|
||||||
|
# know what you're doing, they'll just make the game slower and are
|
||||||
|
# rarely helpful (good for Camelot games).
|
||||||
|
|
||||||
|
# iwram_stack_optimize - set this to "no" to turn it off. By default this
|
||||||
|
# is set on. It will turn off an optimization that assumes that the stack
|
||||||
|
# is always in IWRAM, and thus makes ldm/stm relative to the stack much
|
||||||
|
# faster. Turning it off will degrade game speed slightly, but is
|
||||||
|
# necessary for a few games that don't follow this convention.
|
||||||
|
|
||||||
|
# flash_rom_type - set this to 128KB if the game has a 128KB flash ROM,
|
||||||
|
# otherwise leave it alone or you might break game saving. If you get
|
||||||
|
# a white screen when the game starts try this option.
|
||||||
|
|
||||||
|
# bios_rom_hack_39 - a hack that allows "roll" to work with the correct BIOS
|
||||||
|
# in Zelda: Minish Cap.
|
||||||
|
|
||||||
|
# bios_rom_hack_2C - like the above but allows Rayman Advance to work.
|
||||||
|
|
||||||
|
# Castlevania: Circle of the Moon (U)
|
||||||
|
game_name = DRACULA AGB1
|
||||||
|
game_code = AAME
|
||||||
|
vender_code = A4
|
||||||
|
idle_loop_eliminate_target = 080003d2
|
||||||
|
|
||||||
|
# Megaman Battle Network (U)
|
||||||
|
game_name = MEGAMAN_BN
|
||||||
|
game_code = AREE
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 08000338
|
||||||
|
|
||||||
|
# Megaman Battle Network 2 (U)
|
||||||
|
game_name = MEGAMAN_EXE2
|
||||||
|
game_code = AE2E
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 08000358
|
||||||
|
|
||||||
|
# Megaman Battle Network 3 White (U)
|
||||||
|
game_name = MEGA_EXE3_WH
|
||||||
|
game_code = A6BE
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 0800036c
|
||||||
|
|
||||||
|
# Megaman Battle Network 3 Blue (U)
|
||||||
|
game_name = MEGA_EXE3_BL
|
||||||
|
game_code = A3XE
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 0800036c
|
||||||
|
|
||||||
|
# Megaman Battle Network 4 Red Sun (U)
|
||||||
|
game_name = MEGAMANBN4RS
|
||||||
|
game_code = B4WE
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 080003a6
|
||||||
|
|
||||||
|
# Megaman Battle Network 4 Blue Moon (U)
|
||||||
|
game_name = MEGAMANBN4BM
|
||||||
|
game_code = B4BE
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 080003a6
|
||||||
|
|
||||||
|
# Megaman Battle Network 5 Team Protoman (U)
|
||||||
|
game_name = MEGAMAN5_TP_
|
||||||
|
game_code = BRBE
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 080003ca
|
||||||
|
|
||||||
|
# Megaman Battle Network 5 Team Colonel (U)
|
||||||
|
game_name = MEGAMAN5_TC_
|
||||||
|
game_code = BRKE
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 080003ca
|
||||||
|
|
||||||
|
# Megaman Battle Network 6 Cybeast Gregar (U)
|
||||||
|
game_name = MEGAMAN6_GXX
|
||||||
|
game_code = BR5E
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 080003da
|
||||||
|
|
||||||
|
# Megaman Zero (U/E)
|
||||||
|
game_name = MEGAMAN ZERO
|
||||||
|
game_code = AZCE
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 080004ee
|
||||||
|
|
||||||
|
# Megaman Zero 2 (U)
|
||||||
|
game_name = MEGAMANZERO2
|
||||||
|
game_code = A62E
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 08000664
|
||||||
|
|
||||||
|
# Megaman Zero 3 (U)
|
||||||
|
game_name = MEGAMANZERO3
|
||||||
|
game_code = BZ3E
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 08001a08
|
||||||
|
|
||||||
|
# Megaman Zero 4 (U)
|
||||||
|
game_name = MEGAMANZERO4
|
||||||
|
game_code = B4ZP
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 0800090c
|
||||||
|
|
||||||
|
# Kirby: Nightmare in Dreamland (U)
|
||||||
|
game_name = AGB KIRBY DX
|
||||||
|
game_code = A7KE
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 08000fae
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# Hoshi no Kirby: Yume no Izumi Deluxe (J)
|
||||||
|
game_name = AGB KIRBY DX
|
||||||
|
game_code = A7KJ
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 08000f92
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# Kirby: Nightmare in Dreamland (E)
|
||||||
|
game_name = AGB KIRBY DX
|
||||||
|
game_code = A7KP
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 08000fae
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# Super Mario Advance (U)
|
||||||
|
game_name = SUPER MARIOA
|
||||||
|
game_code = AMZE
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 08001cf2
|
||||||
|
|
||||||
|
# Super Mario Advance 2 (U)
|
||||||
|
game_name = SUPER MARIOB
|
||||||
|
game_code = AA2E
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 08000534
|
||||||
|
|
||||||
|
# Super Mario Advance 3 (U)
|
||||||
|
game_name = SUPER MARIOC
|
||||||
|
game_code = A3AE
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 08002ba4
|
||||||
|
|
||||||
|
# Super Mario Advance 4 (U)
|
||||||
|
game_name = SUPER MARIOD
|
||||||
|
game_code = AX4E
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 08000732
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Super Mario Advance 4 (J)
|
||||||
|
game_name = SUPER MARIOD
|
||||||
|
game_code = AX4J
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 08000732
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Super Mario Advance 4 (E)
|
||||||
|
game_name = SUPER MARIOD
|
||||||
|
game_code = AX4P
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 08000732
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Advance Wars (U)
|
||||||
|
# This one was really annoying to find, I hope it's okay.. there
|
||||||
|
# might be a better one somewhere.
|
||||||
|
game_name = ADVANCEWARS
|
||||||
|
game_code = AWRE
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 0803880a
|
||||||
|
|
||||||
|
# Pokemon Emerald (E/U)
|
||||||
|
# I don't know why this has an idle loop when Ruby doesn't....
|
||||||
|
game_name = POKEMON EMER
|
||||||
|
game_code = BPEE
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080008ce
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon Emerald (J)
|
||||||
|
game_name = POKEMON EMER
|
||||||
|
game_code = BPEJ
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080008ce
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon Emerald (G)
|
||||||
|
game_name = POKEMON EMER
|
||||||
|
game_code = BPED
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080008ce
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon Emerald (F)
|
||||||
|
game_name = POKEMON EMER
|
||||||
|
game_code = BPEF
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080008ce
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon Emerald (S)
|
||||||
|
game_name = POKEMON EMER
|
||||||
|
game_code = BPES
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080008ce
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon Emerald (I)
|
||||||
|
game_name = POKEMON EMER
|
||||||
|
game_code = BPEI
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080008ce
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon Sapphire (U)
|
||||||
|
game_name = POKEMON SAPP
|
||||||
|
game_code = AXPE
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon Sapphire (J)
|
||||||
|
game_name = POKEMON SAPP
|
||||||
|
game_code = AXPJ
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon Sapphire (G)
|
||||||
|
game_name = POKEMON SAPP
|
||||||
|
game_code = AXPD
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon Sapphire (I)
|
||||||
|
game_name = POKEMON SAPP
|
||||||
|
game_code = AXPI
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon Sapphire (S)
|
||||||
|
game_name = POKEMON SAPP
|
||||||
|
game_code = AXPS
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon Sapphire (F)
|
||||||
|
game_name = POKEMON SAPP
|
||||||
|
game_code = AXPF
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon Ruby (U)
|
||||||
|
game_name = POKEMON RUBY
|
||||||
|
game_code = AXVE
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon Ruby (J)
|
||||||
|
game_name = POKEMON RUBY
|
||||||
|
game_code = AXVJ
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon Ruby (G)
|
||||||
|
game_name = POKEMON RUBY
|
||||||
|
game_code = AXVD
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon Ruby (I)
|
||||||
|
game_name = POKEMON RUBY
|
||||||
|
game_code = AXVI
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon Ruby (S)
|
||||||
|
game_name = POKEMON RUBY
|
||||||
|
game_code = AXVS
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon Ruby (F)
|
||||||
|
game_name = POKEMON RUBY
|
||||||
|
game_code = AXVF
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# V-Rally 3 (E)
|
||||||
|
game_name = V-RALLY 3
|
||||||
|
game_code = AVRP
|
||||||
|
vender_code = 70
|
||||||
|
idle_loop_eliminate_target = 080aa920
|
||||||
|
|
||||||
|
# Mario Vs Donkey Kong (U)
|
||||||
|
game_name = MARIOVSDK
|
||||||
|
game_code = BM5E
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 08033eec
|
||||||
|
|
||||||
|
# Pokemon: Sapphire (U)
|
||||||
|
game_name = POKEMON SAPP
|
||||||
|
game_code = AXPE
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon: Sapphire (G)
|
||||||
|
game_name = POKEMON SAPP
|
||||||
|
game_code = AXPD
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon: Fire Red (J)
|
||||||
|
game_name = POKEMON FIRE
|
||||||
|
game_code = BPRJ
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080008b2
|
||||||
|
# If you have the European version try this instead.
|
||||||
|
#idle_loop_eliminate_target = 080008c6
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon: Fire Red (E/U)
|
||||||
|
game_name = POKEMON FIRE
|
||||||
|
game_code = BPRE
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080008c6
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon: Fire Red (S)
|
||||||
|
game_name = POKEMON FIRE
|
||||||
|
game_code = BPRS
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080008c6
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon: Fire Red (G)
|
||||||
|
game_name = POKEMON FIRE
|
||||||
|
game_code = BPRD
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080008c6
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon: Fire Red (I)
|
||||||
|
game_name = POKEMON FIRE
|
||||||
|
game_code = BPRI
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080008c6
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon: Fire Red (F)
|
||||||
|
game_name = POKEMON FIRE
|
||||||
|
game_code = BPRE
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080008c6
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon: Leaf Green (E/U)
|
||||||
|
# Hey, this one is the same as Fire Red, who'd have thought? :B
|
||||||
|
game_name = POKEMON LEAF
|
||||||
|
game_code = BPGE
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080008b2
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon: Leaf Green (S)
|
||||||
|
game_name = POKEMON LEAF
|
||||||
|
game_code = BPGS
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080008b6
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon: Leaf Green (G)
|
||||||
|
game_name = POKEMON LEAF
|
||||||
|
game_code = BPGD
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080008b6
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon: Leaf Green (I)
|
||||||
|
game_name = POKEMON LEAF
|
||||||
|
game_code = BPGI
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080008b6
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon: Leaf Green (F)
|
||||||
|
game_name = POKEMON LEAF
|
||||||
|
game_code = BPGF
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080008b6
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon: Fushigi no Dungeon Aka no Kyuujotai (J)
|
||||||
|
game_name = POKE DUNGEON
|
||||||
|
game_code = B24J
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Pokemon: Red Rescue Team (E/U)
|
||||||
|
game_name = POKE DUNGEON
|
||||||
|
game_code = B24E
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# F-Zero: Climax (J)
|
||||||
|
game_name = F-ZEROCLIMAX
|
||||||
|
game_code = BFTJ
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Final Fantasy Tactics Advance (U)
|
||||||
|
game_name = FFTA_USVER.
|
||||||
|
game_code = AFXE
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 0800041e
|
||||||
|
|
||||||
|
# Gradius Galaxies (U)
|
||||||
|
# Badly coded game with several idle loops. This one works for level
|
||||||
|
# one at least.
|
||||||
|
game_name = GRADIUSGALAX
|
||||||
|
game_code = AGAE
|
||||||
|
vender_code = A4
|
||||||
|
idle_loop_eliminate_target = 08013844
|
||||||
|
|
||||||
|
# Rebelstar: Tactical Command (U)
|
||||||
|
# Badly coded game with several idle loops. I don't think any are
|
||||||
|
# even close to dominant, and it jumps around too much when things
|
||||||
|
# matter....
|
||||||
|
game_name = REBELSTAR
|
||||||
|
game_code = BRLE
|
||||||
|
vender_code = AF
|
||||||
|
idle_loop_eliminate_target = 0800041a
|
||||||
|
|
||||||
|
# Golden Sun
|
||||||
|
game_name = Golden_Sun_A
|
||||||
|
game_code = AGSE
|
||||||
|
vender_code = 01
|
||||||
|
translation_gate_target = 03000820
|
||||||
|
translation_gate_target = 030009ac
|
||||||
|
translation_gate_target = 03007dac
|
||||||
|
|
||||||
|
# Golden Sun: The Lost Age (U)
|
||||||
|
# Probably the most horrifically coded GBA game in existence.
|
||||||
|
game_name = GOLDEN_SUN_B
|
||||||
|
game_code = AGFE
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 08013542
|
||||||
|
translation_gate_target = 030009ac
|
||||||
|
#translation_gate_target = 03007d70
|
||||||
|
|
||||||
|
# Nothing to see here :/
|
||||||
|
# Mario & Luigi: Superstar Saga (U)
|
||||||
|
game_name = MARIO&LUIGIU
|
||||||
|
game_code = A88E
|
||||||
|
vender_code = 01
|
||||||
|
|
||||||
|
# Mario Party Advance (U)
|
||||||
|
game_name = MARIOPARTYUS
|
||||||
|
game_code = B8ME
|
||||||
|
vender_code = 01
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# Mario Party Advance (J)
|
||||||
|
game_name = MARIOPARTYJA
|
||||||
|
game_code = B8MJ
|
||||||
|
vender_code = 01
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# Mario Party Advance (E)
|
||||||
|
game_name = MARIOPARTYEU
|
||||||
|
game_code = B8MP
|
||||||
|
vender_code = 01
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# Mario Golf: Advance Tour (U)
|
||||||
|
game_name = MARIOGOLFGBA
|
||||||
|
game_code = BMGE
|
||||||
|
vender_code = 01
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
idle_loop_eliminate_target = 08014e0a
|
||||||
|
translation_gate_target = 03000d00
|
||||||
|
translation_gate_target = 03000a30
|
||||||
|
|
||||||
|
# Mario Golf: GBA Tour (J)
|
||||||
|
game_name = MARIOGOLFGBA
|
||||||
|
game_code = BMGJ
|
||||||
|
vender_code = 01
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
idle_loop_eliminate_target = 08014e0a
|
||||||
|
translation_gate_target = 03000d00
|
||||||
|
translation_gate_target = 03000a30
|
||||||
|
|
||||||
|
# Mario Golf: Advance Tour (E)
|
||||||
|
game_name = MARIOGOLFGBA
|
||||||
|
game_code = BMGP
|
||||||
|
vender_code = 01
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
idle_loop_eliminate_target = 08014e0a
|
||||||
|
translation_gate_target = 03000d00
|
||||||
|
translation_gate_target = 03000a30
|
||||||
|
|
||||||
|
# Mario Golf: Advance Tour (S)
|
||||||
|
game_name = MARIOGOLFGBA
|
||||||
|
game_code = BMGS
|
||||||
|
vender_code = 01
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
idle_loop_eliminate_target = 08014e0a
|
||||||
|
translation_gate_target = 03000d00
|
||||||
|
translation_gate_target = 03000a30
|
||||||
|
|
||||||
|
# Mario Golf: Advance Tour (F)
|
||||||
|
game_name = MARIOGOLFGBA
|
||||||
|
game_code = BMGF
|
||||||
|
vender_code = 01
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
idle_loop_eliminate_target = 08014e0a
|
||||||
|
translation_gate_target = 03000d00
|
||||||
|
translation_gate_target = 03000a30
|
||||||
|
|
||||||
|
# Mario Golf: Advance Tour (I)
|
||||||
|
game_name = MARIOGOLFGBA
|
||||||
|
game_code = BMGI
|
||||||
|
vender_code = 01
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
idle_loop_eliminate_target = 08014e0a
|
||||||
|
translation_gate_target = 03000d00
|
||||||
|
translation_gate_target = 03000a30
|
||||||
|
|
||||||
|
# Mario Golf: Advance Tour (G)
|
||||||
|
game_name = MARIOGOLFGBA
|
||||||
|
game_code = BMGD
|
||||||
|
vender_code = 01
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
idle_loop_eliminate_target = 08014e0a
|
||||||
|
translation_gate_target = 03000d00
|
||||||
|
translation_gate_target = 03000a30
|
||||||
|
|
||||||
|
# Mario Golf: Advance Tour (A)
|
||||||
|
game_name = MARIOGOLFGBA
|
||||||
|
game_code = BMGU
|
||||||
|
vender_code = 01
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
idle_loop_eliminate_target = 08014e0a
|
||||||
|
translation_gate_target = 03000d00
|
||||||
|
translation_gate_target = 03000a30
|
||||||
|
|
||||||
|
# Tales of Phantasia (U)
|
||||||
|
game_name = PHANTASIA
|
||||||
|
game_code = AN8E
|
||||||
|
vender_code = 01
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# Tales of Phantasia (J)
|
||||||
|
game_name = PHANTASIA
|
||||||
|
game_code = AN8J
|
||||||
|
vender_code = AF
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# Tales of Phantasia (E)
|
||||||
|
game_name = PHANTASIA
|
||||||
|
game_code = AN8P
|
||||||
|
vender_code = 01
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# Advance Wars 2: Black Hole Rising (U)
|
||||||
|
game_name = ADVANCEWARS2
|
||||||
|
game_code = AW2E
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 08036e2a
|
||||||
|
|
||||||
|
# Bomberman Tournament (U)
|
||||||
|
game_name = BOMSTORYUSA
|
||||||
|
game_code = ABSE
|
||||||
|
vender_code = 52
|
||||||
|
idle_loop_eliminate_target = 08000526
|
||||||
|
|
||||||
|
# Broken Sword - The Shadow of the Templars (U)
|
||||||
|
game_name = BROKENSWORD
|
||||||
|
game_code = ABJE
|
||||||
|
vender_code = 6L
|
||||||
|
idle_loop_eliminate_target = 08000a26
|
||||||
|
|
||||||
|
# Defender of The Crown (U)
|
||||||
|
game_name = DOTC
|
||||||
|
game_code = ADHE
|
||||||
|
vender_code = 5N
|
||||||
|
idle_loop_eliminate_target = 080007ec
|
||||||
|
|
||||||
|
# Drill Dozer (U)
|
||||||
|
game_name = DRILL DOZER
|
||||||
|
game_code = V49E
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080006c2
|
||||||
|
|
||||||
|
# F-Zero - Maximum Velocity (U)
|
||||||
|
game_name = F-ZERO ADVAN
|
||||||
|
game_code = AFZE
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 08000c2e
|
||||||
|
|
||||||
|
# Megaman Zero 2 (U)
|
||||||
|
game_name = MEGAMANZERO2
|
||||||
|
game_code = A62E
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 08000664
|
||||||
|
|
||||||
|
# Megaman Zero 3 (U)
|
||||||
|
game_name = MEGAMANZERO3
|
||||||
|
game_code = BZ3E
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 08001a08
|
||||||
|
|
||||||
|
# Megaman Zero 4 (U)
|
||||||
|
game_name = MEGAMANZERO4
|
||||||
|
game_code = B4ZE
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 0800090c
|
||||||
|
|
||||||
|
# Metal Slug Advance (U)
|
||||||
|
game_name = METAL SLUG
|
||||||
|
game_code = BSME
|
||||||
|
vender_code = B7
|
||||||
|
idle_loop_eliminate_target = 08000298
|
||||||
|
|
||||||
|
# Magical Quest 2 Starring Mickey & Minnie (U)
|
||||||
|
game_name = M&M MAGICAL2
|
||||||
|
game_code = AQME
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 0801d340
|
||||||
|
|
||||||
|
# Magical Quest 3 Starring Mickey & Donald (U)
|
||||||
|
game_name = M&D MAGICAL3
|
||||||
|
game_code = BMQE
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 08016064
|
||||||
|
|
||||||
|
# Pinball Challenge Deluxe (E)
|
||||||
|
game_name = PINBALL CHAL
|
||||||
|
game_code = APLP
|
||||||
|
vender_code = 41
|
||||||
|
idle_loop_eliminate_target = 080075a6
|
||||||
|
|
||||||
|
# Prince of Persia - The Sands of Time (U)
|
||||||
|
game_name = PRINCEPERSIA
|
||||||
|
game_code = BPYE
|
||||||
|
vender_code = 41
|
||||||
|
idle_loop_eliminate_target = 0808ff3a
|
||||||
|
|
||||||
|
# Rhythm Tengoku (J)
|
||||||
|
game_name = RHYTHMTENGOK
|
||||||
|
game_code = BRIJ
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080013d4
|
||||||
|
|
||||||
|
# River City Ransom EX (U)
|
||||||
|
game_name = RIVERCRANSOM
|
||||||
|
game_code = BDTE
|
||||||
|
vender_code = EB
|
||||||
|
idle_loop_eliminate_target = 0800065a
|
||||||
|
|
||||||
|
# Super Puzzle Fighter II Turbo (U)
|
||||||
|
game_name = PUZZLEFIGHT2
|
||||||
|
game_code = AZ8E
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 08002b5e
|
||||||
|
|
||||||
|
# Yu-Gi-Oh! - Dungeon Dice Monsters (U)
|
||||||
|
game_name = YU-GI-OH DDM
|
||||||
|
game_code = AYDE
|
||||||
|
vender_code = A4
|
||||||
|
idle_loop_eliminate_target = 0802cc6a
|
||||||
|
|
||||||
|
# Yu-Gi-Oh! - The Eternal Duelist Soul (U)
|
||||||
|
game_name = YU-GI-OH!EDS
|
||||||
|
game_code = AY5E
|
||||||
|
vender_code = A4
|
||||||
|
idle_loop_eliminate_target = 08075d96
|
||||||
|
|
||||||
|
# Yu-Gi-Oh! - The Sacred Cards (U)
|
||||||
|
game_name = YUGIOH DM7
|
||||||
|
game_code = AY7E
|
||||||
|
vender_code = A4
|
||||||
|
idle_loop_eliminate_target = 08003bd6
|
||||||
|
|
||||||
|
# Yu-Gi-Oh! - World Championship Tournament 2004 (U)
|
||||||
|
game_name = YWCT2004USA
|
||||||
|
game_code = BYWE
|
||||||
|
vender_code = A4
|
||||||
|
idle_loop_eliminate_target = 080831da
|
||||||
|
|
||||||
|
# Yu-Gi-Oh! - Worldwide Edition - Stairway to the Destined Duel (U)
|
||||||
|
game_name = YUGIOHWWE
|
||||||
|
game_code = AYWE
|
||||||
|
vender_code = A4
|
||||||
|
idle_loop_eliminate_target = 08089792
|
||||||
|
|
||||||
|
# Wario Ware, Inc. Mega Microgames (U)
|
||||||
|
game_name = WARIOWAREINC
|
||||||
|
game_code = AZWE
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 08000f66
|
||||||
|
|
||||||
|
# Tom Clancy's Splinter Cell (U)
|
||||||
|
game_name = SPLINTERCELL
|
||||||
|
game_code = AO4E
|
||||||
|
vender_code = 41
|
||||||
|
idle_loop_eliminate_target = 0807a0c4
|
||||||
|
|
||||||
|
# Tom Clancy's Splinter Cell - Pandora Tomorrow (U)
|
||||||
|
game_name = TOM CLANCY'S
|
||||||
|
game_code = BSLE
|
||||||
|
vender_code = 41
|
||||||
|
idle_loop_eliminate_target = 0807785e
|
||||||
|
|
||||||
|
# Final Fantasy IV Advance (U)
|
||||||
|
game_name = FF4ADVANCE
|
||||||
|
game_code = BZ4E
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 0800fabe
|
||||||
|
# or try 00000430
|
||||||
|
|
||||||
|
# Digimon Battle Spirit (U)
|
||||||
|
game_name = DIGIMON BTSP
|
||||||
|
game_code = A8SE
|
||||||
|
vender_code = B2
|
||||||
|
idle_loop_eliminate_target = 08011208
|
||||||
|
|
||||||
|
# Digimon Battle Spirit 2 (U)
|
||||||
|
game_name = DIGIMON BS2
|
||||||
|
game_code = BDSE
|
||||||
|
vender_code = B2
|
||||||
|
idle_loop_eliminate_target = 08010eb0
|
||||||
|
|
||||||
|
# Donald Duck Advance (U)
|
||||||
|
game_name = DISNEY'S DON
|
||||||
|
game_code = ADKE
|
||||||
|
vender_code = 41
|
||||||
|
idle_loop_eliminate_target = 08002f30
|
||||||
|
|
||||||
|
# Final Fight One (U)
|
||||||
|
game_name = FINAL FIGHT
|
||||||
|
game_code = AFFE
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 0800b428
|
||||||
|
|
||||||
|
# Megaman Battle Chip Challenge (U)
|
||||||
|
game_name = BATTLECHIPGP
|
||||||
|
game_code = A89E
|
||||||
|
vender_code = 08
|
||||||
|
idle_loop_eliminate_target = 08000544
|
||||||
|
|
||||||
|
# Monster Force (U)
|
||||||
|
game_name = MONSTERFORCE
|
||||||
|
game_code = AM8E
|
||||||
|
vender_code = 7D
|
||||||
|
idle_loop_eliminate_target = 08000b00
|
||||||
|
|
||||||
|
# Monster Rancher Advance (U)
|
||||||
|
game_name = MONSRANCHERA
|
||||||
|
game_code = AMFE
|
||||||
|
vender_code = 9B
|
||||||
|
idle_loop_eliminate_target = 0809f394
|
||||||
|
|
||||||
|
# Monster Rancher Advance 2 (U)
|
||||||
|
game_name = MONSTERRANC2
|
||||||
|
game_code = A2QE
|
||||||
|
vender_code = 9B
|
||||||
|
idle_loop_eliminate_target = 081c7290
|
||||||
|
|
||||||
|
# The Pinball of The Dead
|
||||||
|
game_name = PINBALL DEAD
|
||||||
|
game_code = APDE
|
||||||
|
vender_code = 78
|
||||||
|
idle_loop_eliminate_target = 08000300
|
||||||
|
|
||||||
|
# Tringo (U)
|
||||||
|
game_name = TRINGO
|
||||||
|
game_code = BTJE
|
||||||
|
vender_code = 4Z
|
||||||
|
idle_loop_eliminate_target = 080009a4
|
||||||
|
|
||||||
|
# Virtual Kasparov (U)
|
||||||
|
game_name = VIRTKASPAROV
|
||||||
|
game_code = AVKE
|
||||||
|
vender_code = 60
|
||||||
|
idle_loop_eliminate_target = 0800093a
|
||||||
|
|
||||||
|
# Advance Wars 2 - Black Hole Rising (E)
|
||||||
|
game_name = ADVANCEWARS2
|
||||||
|
game_code = AW2P
|
||||||
|
vender_code = 01
|
||||||
|
idle_loop_eliminate_target = 080371be
|
||||||
|
|
||||||
|
# Bookworm (U)
|
||||||
|
game_name = BOOKWORM
|
||||||
|
game_code = BKWE
|
||||||
|
vender_code = 5G
|
||||||
|
idle_loop_eliminate_target = 0800397c
|
||||||
|
|
||||||
|
# 007 - Nightfire (U)
|
||||||
|
game_name = NIGHTFIRE
|
||||||
|
game_code = A7OE
|
||||||
|
vender_code = 69
|
||||||
|
idle_loop_eliminate_target = 080031d6
|
||||||
|
|
||||||
|
# Asterix & Obelix XXL (E)
|
||||||
|
game_name = ASTERIX
|
||||||
|
game_code = BLXP
|
||||||
|
vender_code = 70
|
||||||
|
idle_loop_eliminate_target = 0846d060
|
||||||
|
|
||||||
|
# Was this game released in Japan? What as?
|
||||||
|
# Ninja Five-0 (U)
|
||||||
|
game_name = NINJA FIVE 0
|
||||||
|
game_code = ANXE
|
||||||
|
vender_code = A4
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# Ninja Cop (E)
|
||||||
|
game_name = NINJA COP
|
||||||
|
game_code = ANXP
|
||||||
|
vender_code = A4
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# Sennen Kazoku (J)
|
||||||
|
game_name = SENNENKAZOKU
|
||||||
|
game_code = BKAJ
|
||||||
|
vender_code = 01
|
||||||
|
flash_rom_type = 128KB
|
||||||
|
|
||||||
|
# Doom 2 (U)
|
||||||
|
game_name = DOOM II
|
||||||
|
game_code = A9DE
|
||||||
|
vender_code = 52
|
||||||
|
translation_gate_target = 030041c8
|
||||||
|
translation_gate_target = 03004fa0
|
||||||
|
|
||||||
|
# Bleach Advance (J)
|
||||||
|
game_name = BLEACH ADV1
|
||||||
|
game_code = BLEJ
|
||||||
|
vender_code = 8P
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# Shining Soul (J)
|
||||||
|
game_name = SHINING SOUL
|
||||||
|
game_code = AHUJ
|
||||||
|
vender_code = 8P
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# Shining Soul (U)
|
||||||
|
game_name = SHINING SOUL
|
||||||
|
game_code = AHUE
|
||||||
|
vender_code = EB
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# Shining Soul (E)
|
||||||
|
game_name = SHINING SOUL
|
||||||
|
game_code = AHUP
|
||||||
|
vender_code = 8P
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# Shining Soul 2 (J)
|
||||||
|
game_name = SHININGSOUL2
|
||||||
|
game_code = AU2J
|
||||||
|
vender_code = 8P
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# Shining Soul 2 (U)
|
||||||
|
game_name = SHININGSOUL2
|
||||||
|
game_code = AU2E
|
||||||
|
vender_code = EB
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# Shining Soul 2 (E)
|
||||||
|
game_name = SHININGSOUL2
|
||||||
|
game_code = AU2P
|
||||||
|
vender_code = 8P
|
||||||
|
iwram_stack_optimize = no
|
||||||
|
|
||||||
|
# This is needed to make the game work.
|
||||||
|
# Another World (Homebrew)
|
||||||
|
game_name = FoxAnWorld
|
||||||
|
game_code = Home
|
||||||
|
vender_code = 00
|
||||||
|
translation_gate_target = 03000f1c
|
||||||
|
|
||||||
51
gp2x/Makefile
Normal file
51
gp2x/Makefile
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# gpSP makefile
|
||||||
|
# Gilead Kutnick - Exophase
|
||||||
|
# GP2X port(ion) - Z
|
||||||
|
|
||||||
|
# Global definitions
|
||||||
|
|
||||||
|
PREFIX = /opt/open2x/gcc-4.1.1-glibc-2.3.6
|
||||||
|
CC = $(PREFIX)/bin/arm-open2x-linux-gcc
|
||||||
|
STRIP = $(PREFIX)/bin/arm-open2x-linux-strip
|
||||||
|
|
||||||
|
OBJS = main.o cpu.o memory.u video.o input.o sound.o gp2x.o gui.o \
|
||||||
|
cheats.o zip.o cpu_threaded.z cpu_speed.o cpuctrl.o \
|
||||||
|
gp2xminilib.o font.o display.o speedtest.o cmdline.o daemon.o \
|
||||||
|
arm_stub.o video_blend.o
|
||||||
|
BIN = gpsp.gpe
|
||||||
|
|
||||||
|
# Platform specific definitions
|
||||||
|
|
||||||
|
VPATH += ..
|
||||||
|
CFLAGS += -DARM_ARCH -DGP2X_BUILD
|
||||||
|
# NOTE: -funroll-loops will slow down compiling considerably
|
||||||
|
CFLAGS += -O3 -std=c99 -msoft-float -funsigned-char -fno-common \
|
||||||
|
-fno-builtin \
|
||||||
|
|
||||||
|
INCLUDES = `$(PREFIX)/bin/arm-open2x-linux-sdl-config --cflags`
|
||||||
|
LIBS = `$(PREFIX)/bin/arm-open2x-linux-sdl-config --libs` \
|
||||||
|
-lm -ldl -lpthread -lz -static
|
||||||
|
|
||||||
|
# Compilation:
|
||||||
|
|
||||||
|
.SUFFIXES: .c
|
||||||
|
|
||||||
|
%.z: %.c
|
||||||
|
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||||
|
|
||||||
|
%.u: %.c
|
||||||
|
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||||
|
|
||||||
|
%.o: %.S
|
||||||
|
$(CC) $(ASFLAGS) $(INCLUDES) -c -o $@ $<
|
||||||
|
|
||||||
|
all: $(OBJS)
|
||||||
|
$(CC) $(OBJS) $(LIBS) -o $(BIN)
|
||||||
|
$(STRIP) $(BIN)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o *.u *.z $(BIN)
|
||||||
|
|
||||||
48
gp2x/align_test.c
Normal file
48
gp2x/align_test.c
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Betting on GCC aligning this for efficiency.
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
unsigned short int read_16 = 0xF1F2;
|
||||||
|
unsigned int read_32 = 0xF1F2F3F4;
|
||||||
|
|
||||||
|
unsigned short int write_16 = 0xF00D;
|
||||||
|
unsigned int write_32 = 0xF00DFEED;
|
||||||
|
// 16bit unsigned reads, we expect 0xF1F2 and 0xF20000F1
|
||||||
|
fprintf(stderr, "%04x %04x\n",
|
||||||
|
*((unsigned short int *)((char *)&read_16)),
|
||||||
|
*((unsigned short int *)((char *)&read_16 + 1)));
|
||||||
|
|
||||||
|
// 16bit signed reads, we expect 0xFFFFF1F2 and 0xFFFFFFF1
|
||||||
|
fprintf(stderr, "%04x %04x\n",
|
||||||
|
*((short int *)((char *)&read_16)),
|
||||||
|
*((short int *)((char *)&read_16 + 1)));
|
||||||
|
|
||||||
|
// 32bit reads, we expect 0xF1F2F3F4, 0xF4F1F2F3, 0xF3F4F1F2,
|
||||||
|
// and 0xF2F3F4F1
|
||||||
|
|
||||||
|
fprintf(stderr, "%08x %08x %08x %08x\n",
|
||||||
|
*((int *)((char *)&read_32)),
|
||||||
|
*((int *)((char *)&read_32 + 1)),
|
||||||
|
*((int *)((char *)&read_32 + 2)),
|
||||||
|
*((int *)((char *)&read_32 + 3)));
|
||||||
|
|
||||||
|
// 16bit writes, we expect write_16 to remain 0xF00D
|
||||||
|
|
||||||
|
*((short int *)((char *)&write_16)) = 0xF00D;
|
||||||
|
*((short int *)((char *)&write_16) + 1) = 0xF00D;
|
||||||
|
|
||||||
|
fprintf(stderr, "%04x\n", write_16);
|
||||||
|
|
||||||
|
// 32bit writes, we expect write_32 to remain 0xF00DFEED
|
||||||
|
|
||||||
|
*((int *)((char *)&write_16)) = 0xF00DFEED;
|
||||||
|
*((int *)((char *)&write_16) + 1) = 0xF00DFEED;
|
||||||
|
*((int *)((char *)&write_16) + 2) = 0xF00DFEED;
|
||||||
|
*((int *)((char *)&write_16) + 3) = 0xF00DFEED;
|
||||||
|
|
||||||
|
fprintf(stderr, "%08x\n", write_32);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
1392
gp2x/arm_codegen.h
Normal file
1392
gp2x/arm_codegen.h
Normal file
File diff suppressed because it is too large
Load Diff
1661
gp2x/arm_dpimacros.h
Normal file
1661
gp2x/arm_dpimacros.h
Normal file
File diff suppressed because it is too large
Load Diff
1952
gp2x/arm_emit.h
Normal file
1952
gp2x/arm_emit.h
Normal file
File diff suppressed because it is too large
Load Diff
1016
gp2x/arm_stub.S
Normal file
1016
gp2x/arm_stub.S
Normal file
File diff suppressed because it is too large
Load Diff
478
gp2x/bios_cache.S
Normal file
478
gp2x/bios_cache.S
Normal file
@ -0,0 +1,478 @@
|
|||||||
|
|
||||||
|
//Gp2x/gp2x/mnt/nand/bios_cache.bin: file format binary
|
||||||
|
|
||||||
|
Disassembly of section .data:
|
||||||
|
|
||||||
|
00000000 <.data>:
|
||||||
|
0: e3a00f02 mov r0, #8 ; 0x8
|
||||||
|
4: ebcb1afd bl step_debug
|
||||||
|
8: e25cc001 subs ip, ip, #1 ; 0x1
|
||||||
|
c: 5a000001 bpl 0x18
|
||||||
|
10: e3a00d05 mov r0, #320 ; 0x140
|
||||||
|
14: ebcb18d0 bl 0xff2c635c
|
||||||
|
18: eaffffff b 0x1c
|
||||||
|
1c: e3a00d05 mov r0, #320 ; 0x140
|
||||||
|
20: ebcb1af6 bl step_debug
|
||||||
|
24: e59a9034 ldr r9, [sl, #52]
|
||||||
|
28: e249900c sub r9, r9, #12 ; 0xc
|
||||||
|
2c: e59a0034 ldr r0, [sl, #52]
|
||||||
|
30: e240000c sub r0, r0, #12 ; 0xc
|
||||||
|
34: e58a0034 str r0, [sl, #52]
|
||||||
|
38: e3c99003 bic r9, r9, #3 ; 0x3
|
||||||
|
3c: e2890000 add r0, r9, #0 ; 0x0
|
||||||
|
40: e59a102c ldr r1, [sl, #44]
|
||||||
|
44: ebcb1a8e bl 0xff2c6a84
|
||||||
|
48: e2890004 add r0, r9, #4 ; 0x4
|
||||||
|
4c: e1a01007 mov r1, r7
|
||||||
|
50: ebcb1a8b bl 0xff2c6a84
|
||||||
|
54: e2890008 add r0, r9, #8 ; 0x8
|
||||||
|
58: e1a01008 mov r1, r8
|
||||||
|
5c: e3a02f51 mov r2, #324 ; 0x144
|
||||||
|
60: ebcb1a6f bl 0xff2c6a24
|
||||||
|
64: e3a00f51 mov r0, #324 ; 0x144
|
||||||
|
68: ebcb1ae4 bl step_debug
|
||||||
|
6c: e2480002 sub r0, r8, #2 ; 0x2
|
||||||
|
70: ebcb1a95 bl 0xff2c6acc
|
||||||
|
74: e1a07000 mov r7, r0
|
||||||
|
78: e3a00f52 mov r0, #328 ; 0x148
|
||||||
|
7c: ebcb1adf bl step_debug
|
||||||
|
80: e3a01e15 mov r1, #336 ; 0x150
|
||||||
|
84: e2810078 add r0, r1, #120 ; 0x78
|
||||||
|
88: e58a002c str r0, [sl, #44]
|
||||||
|
8c: e3a00f53 mov r0, #332 ; 0x14c
|
||||||
|
90: ebcb1ada bl step_debug
|
||||||
|
94: e59a002c ldr r0, [sl, #44]
|
||||||
|
98: e0800107 add r0, r0, r7, lsl #2
|
||||||
|
9c: ebcb1ac9 bl 0xff2c6bc8
|
||||||
|
a0: e1a07000 mov r7, r0
|
||||||
|
a4: e3a00e15 mov r0, #336 ; 0x150
|
||||||
|
a8: ebcb1ad4 bl step_debug
|
||||||
|
ac: ebcb194d bl 0xff2c65e8
|
||||||
|
b0: e58a002c str r0, [sl, #44]
|
||||||
|
b4: e3a00f55 mov r0, #340 ; 0x154
|
||||||
|
b8: ebcb1ad0 bl step_debug
|
||||||
|
bc: e59a9034 ldr r9, [sl, #52]
|
||||||
|
c0: e2499004 sub r9, r9, #4 ; 0x4
|
||||||
|
c4: e59a0034 ldr r0, [sl, #52]
|
||||||
|
c8: e2400004 sub r0, r0, #4 ; 0x4
|
||||||
|
cc: e58a0034 str r0, [sl, #52]
|
||||||
|
d0: e3c99003 bic r9, r9, #3 ; 0x3
|
||||||
|
d4: e2890000 add r0, r9, #0 ; 0x0
|
||||||
|
d8: e59a102c ldr r1, [sl, #44]
|
||||||
|
dc: e3a02f56 mov r2, #344 ; 0x158
|
||||||
|
e0: ebcb1a4f bl 0xff2c6a24
|
||||||
|
e4: e3a00f56 mov r0, #344 ; 0x158
|
||||||
|
e8: ebcb1ac4 bl step_debug
|
||||||
|
ec: e59a102c ldr r1, [sl, #44]
|
||||||
|
f0: e2010080 and r0, r1, #128 ; 0x80
|
||||||
|
f4: e58a002c str r0, [sl, #44]
|
||||||
|
f8: e3a00f57 mov r0, #348 ; 0x15c
|
||||||
|
fc: ebcb1abf bl step_debug
|
||||||
|
100: e59a102c ldr r1, [sl, #44]
|
||||||
|
104: e381001f orr r0, r1, #31 ; 0x1f
|
||||||
|
108: e58a002c str r0, [sl, #44]
|
||||||
|
10c: e3a00e16 mov r0, #352 ; 0x160
|
||||||
|
110: ebcb1aba bl step_debug
|
||||||
|
114: e59a002c ldr r0, [sl, #44]
|
||||||
|
118: e3a02e16 mov r2, #352 ; 0x160
|
||||||
|
11c: e3a010ff mov r1, #255 ; 0xff
|
||||||
|
120: e38114ff orr r1, r1, #-16777216 ; 0xff000000
|
||||||
|
124: ebcb190a bl 0xff2c6554
|
||||||
|
128: e3a00f59 mov r0, #356 ; 0x164
|
||||||
|
12c: ebcb1ab3 bl step_debug
|
||||||
|
130: e59a9034 ldr r9, [sl, #52]
|
||||||
|
134: e2499008 sub r9, r9, #8 ; 0x8
|
||||||
|
138: e59a0034 ldr r0, [sl, #52]
|
||||||
|
13c: e2400008 sub r0, r0, #8 ; 0x8
|
||||||
|
140: e58a0034 str r0, [sl, #52]
|
||||||
|
144: e3c99003 bic r9, r9, #3 ; 0x3
|
||||||
|
148: e2890000 add r0, r9, #0 ; 0x0
|
||||||
|
14c: e59a1008 ldr r1, [sl, #8]
|
||||||
|
150: ebcb1a4b bl 0xff2c6a84
|
||||||
|
154: e2890004 add r0, r9, #4 ; 0x4
|
||||||
|
158: e1a01008 mov r1, r8
|
||||||
|
15c: e3a02f5a mov r2, #360 ; 0x168
|
||||||
|
160: ebcb1a2f bl 0xff2c6a24
|
||||||
|
164: e3a00f5a mov r0, #360 ; 0x168
|
||||||
|
168: ebcb1aa4 bl step_debug
|
||||||
|
16c: e3a01e17 mov r1, #368 ; 0x170
|
||||||
|
170: e2818000 add r8, r1, #0 ; 0x0
|
||||||
|
174: e3a00f5b mov r0, #364 ; 0x16c
|
||||||
|
178: ebcb1aa0 bl step_debug
|
||||||
|
17c: e1a00007 mov r0, r7
|
||||||
|
180: e24cc016 sub ip, ip, #22 ; 0x16
|
||||||
|
184: eacb18be b 0xff2c6484
|
||||||
|
188: e3a00ff1 mov r0, #964 ; 0x3c4
|
||||||
|
18c: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
190: ebcb1a9a bl step_debug
|
||||||
|
194: e59a9034 ldr r9, [sl, #52]
|
||||||
|
198: e2499020 sub r9, r9, #32 ; 0x20
|
||||||
|
19c: e59a0034 ldr r0, [sl, #52]
|
||||||
|
1a0: e2400020 sub r0, r0, #32 ; 0x20
|
||||||
|
1a4: e58a0034 str r0, [sl, #52]
|
||||||
|
1a8: e3c99003 bic r9, r9, #3 ; 0x3
|
||||||
|
1ac: e2890000 add r0, r9, #0 ; 0x0
|
||||||
|
1b0: e59a1010 ldr r1, [sl, #16]
|
||||||
|
1b4: ebcb1a32 bl 0xff2c6a84
|
||||||
|
1b8: e2890004 add r0, r9, #4 ; 0x4
|
||||||
|
1bc: e59a1014 ldr r1, [sl, #20]
|
||||||
|
1c0: ebcb1a2f bl 0xff2c6a84
|
||||||
|
1c4: e2890008 add r0, r9, #8 ; 0x8
|
||||||
|
1c8: e1a01005 mov r1, r5
|
||||||
|
1cc: ebcb1a2c bl 0xff2c6a84
|
||||||
|
1d0: e289000c add r0, r9, #12 ; 0xc
|
||||||
|
1d4: e59a101c ldr r1, [sl, #28]
|
||||||
|
1d8: ebcb1a29 bl 0xff2c6a84
|
||||||
|
1dc: e2890010 add r0, r9, #16 ; 0x10
|
||||||
|
1e0: e59a1020 ldr r1, [sl, #32]
|
||||||
|
1e4: ebcb1a26 bl 0xff2c6a84
|
||||||
|
1e8: e2890014 add r0, r9, #20 ; 0x14
|
||||||
|
1ec: e1a01006 mov r1, r6
|
||||||
|
1f0: ebcb1a23 bl 0xff2c6a84
|
||||||
|
1f4: e2890018 add r0, r9, #24 ; 0x18
|
||||||
|
1f8: e59a1028 ldr r1, [sl, #40]
|
||||||
|
1fc: ebcb1a20 bl 0xff2c6a84
|
||||||
|
200: e289001c add r0, r9, #28 ; 0x1c
|
||||||
|
204: e1a01008 mov r1, r8
|
||||||
|
208: e3a02ff2 mov r2, #968 ; 0x3c8
|
||||||
|
20c: e3822b02 orr r2, r2, #2048 ; 0x800
|
||||||
|
210: ebcb1a03 bl 0xff2c6a24
|
||||||
|
214: e3a00ff2 mov r0, #968 ; 0x3c8
|
||||||
|
218: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
21c: ebcb1a77 bl step_debug
|
||||||
|
220: e59a0008 ldr r0, [sl, #8]
|
||||||
|
224: e1a00580 mov r0, r0, lsl #11
|
||||||
|
228: e58a0028 str r0, [sl, #40]
|
||||||
|
22c: e3a00ff3 mov r0, #972 ; 0x3cc
|
||||||
|
230: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
234: ebcb1a71 bl step_debug
|
||||||
|
238: e59a0028 ldr r0, [sl, #40]
|
||||||
|
23c: e128f00b msr CPSR_f, fp
|
||||||
|
240: e1b074a0 movs r7, r0, lsr #9
|
||||||
|
244: e10fb000 mrs fp, CPSR
|
||||||
|
248: e3a00ebd mov r0, #3024 ; 0xbd0
|
||||||
|
24c: ebcb1a6b bl step_debug
|
||||||
|
250: e3a00ff5 mov r0, #980 ; 0x3d4
|
||||||
|
254: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
258: e1a08000 mov r8, r0
|
||||||
|
25c: e25cc00c subs ip, ip, #12 ; 0xc
|
||||||
|
260: 5a000002 bpl 0x270
|
||||||
|
264: e3a00fe9 mov r0, #932 ; 0x3a4
|
||||||
|
268: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
26c: ebcb183a bl 0xff2c635c
|
||||||
|
270: eaffffff b 0x274
|
||||||
|
274: e3a00fe9 mov r0, #932 ; 0x3a4
|
||||||
|
278: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
27c: ebcb1a5f bl step_debug
|
||||||
|
280: e3570000 cmp r7, #0 ; 0x0
|
||||||
|
284: e10fb000 mrs fp, CPSR
|
||||||
|
288: e3a00fea mov r0, #936 ; 0x3a8
|
||||||
|
28c: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
290: ebcb1a5a bl step_debug
|
||||||
|
294: e24cc002 sub ip, ip, #2 ; 0x2
|
||||||
|
298: e128f00b msr CPSR_f, fp
|
||||||
|
29c: 1a000007 bne 0x2c0
|
||||||
|
2a0: 5a000002 bpl 0x2b0
|
||||||
|
2a4: e3a00fef mov r0, #956 ; 0x3bc
|
||||||
|
2a8: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
2ac: ebcb182a bl 0xff2c635c
|
||||||
|
2b0: ea000013 b 0x304
|
||||||
|
2b4: e3a00feb mov r0, #940 ; 0x3ac
|
||||||
|
2b8: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
2bc: ebcb1a4f bl step_debug
|
||||||
|
2c0: e3c774fe bic r7, r7, #-33554432 ; 0xfe000000
|
||||||
|
2c4: e3a00ebb mov r0, #2992 ; 0xbb0
|
||||||
|
2c8: ebcb1a4c bl step_debug
|
||||||
|
2cc: e0837007 add r7, r3, r7
|
||||||
|
2d0: e3a00fed mov r0, #948 ; 0x3b4
|
||||||
|
2d4: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
2d8: ebcb1a48 bl step_debug
|
||||||
|
2dc: e313040e tst r3, #234881024 ; 0xe000000
|
||||||
|
2e0: e10fb000 mrs fp, CPSR
|
||||||
|
2e4: e3a00fee mov r0, #952 ; 0x3b8
|
||||||
|
2e8: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
2ec: ebcb1a43 bl step_debug
|
||||||
|
2f0: e24cc004 sub ip, ip, #4 ; 0x4
|
||||||
|
2f4: e128f00b msr CPSR_f, fp
|
||||||
|
2f8: 0a000004 beq 0x310
|
||||||
|
2fc: e317040e tst r7, #234881024 ; 0xe000000
|
||||||
|
300: e10fb000 mrs fp, CPSR
|
||||||
|
304: e3a00fef mov r0, #956 ; 0x3bc
|
||||||
|
308: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
30c: ebcb1a3b bl step_debug
|
||||||
|
310: e1a00008 mov r0, r8
|
||||||
|
314: e24cc001 sub ip, ip, #1 ; 0x1
|
||||||
|
318: eacb1859 b 0xff2c6484
|
||||||
|
31c: e3a00ff5 mov r0, #980 ; 0x3d4
|
||||||
|
320: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
324: ebcb1a35 bl step_debug
|
||||||
|
328: e24cc001 sub ip, ip, #1 ; 0x1
|
||||||
|
32c: e128f00b msr CPSR_f, fp
|
||||||
|
330: 1a000007 bne 0x354
|
||||||
|
334: 5a000002 bpl 0x344
|
||||||
|
338: e3a00f09 mov r0, #36 ; 0x24
|
||||||
|
33c: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||||
|
340: ebcb1805 bl 0xff2c635c
|
||||||
|
344: ea0000d6 b 0x6a4
|
||||||
|
348: e3a00ff6 mov r0, #984 ; 0x3d8
|
||||||
|
34c: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
350: ebcb1a2a bl step_debug
|
||||||
|
354: e59a0028 ldr r0, [sl, #40]
|
||||||
|
358: e08404a0 add r0, r4, r0, lsr #9
|
||||||
|
35c: e58a0028 str r0, [sl, #40]
|
||||||
|
360: e3a00ff7 mov r0, #988 ; 0x3dc
|
||||||
|
364: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
368: ebcb1a24 bl step_debug
|
||||||
|
36c: e59a0008 ldr r0, [sl, #8]
|
||||||
|
370: e128f00b msr CPSR_f, fp
|
||||||
|
374: e1b00ca0 movs r0, r0, lsr #25
|
||||||
|
378: e10fb000 mrs fp, CPSR
|
||||||
|
37c: e58a0008 str r0, [sl, #8]
|
||||||
|
380: e3a00ebe mov r0, #3040 ; 0xbe0
|
||||||
|
384: ebcb1a1d bl step_debug
|
||||||
|
388: e24cc003 sub ip, ip, #3 ; 0x3
|
||||||
|
38c: e128f00b msr CPSR_f, fp
|
||||||
|
390: 2a000007 bcs 0x3b4
|
||||||
|
394: 5a000002 bpl 0x3a4
|
||||||
|
398: e3a00f05 mov r0, #20 ; 0x14
|
||||||
|
39c: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||||
|
3a0: ebcb17ed bl 0xff2c635c
|
||||||
|
3a4: ea00006a b 0x554
|
||||||
|
3a8: e3a00ff9 mov r0, #996 ; 0x3e4
|
||||||
|
3ac: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
3b0: ebcb1a12 bl step_debug
|
||||||
|
3b4: e2830000 add r0, r3, #0 ; 0x0
|
||||||
|
3b8: ebcb1a02 bl 0xff2c6bc8
|
||||||
|
3bc: e58a0008 str r0, [sl, #8]
|
||||||
|
3c0: e3a00ffa mov r0, #1000 ; 0x3e8
|
||||||
|
3c4: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
3c8: ebcb1a0c bl step_debug
|
||||||
|
3cc: e59a0008 ldr r0, [sl, #8]
|
||||||
|
3d0: e1a00000 nop (mov r0,r0)
|
||||||
|
3d4: e58a000c str r0, [sl, #12]
|
||||||
|
3d8: e3a00ffb mov r0, #1004 ; 0x3ec
|
||||||
|
3dc: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
3e0: ebcb1a06 bl step_debug
|
||||||
|
3e4: e59a0008 ldr r0, [sl, #8]
|
||||||
|
3e8: e1a00000 nop (mov r0,r0)
|
||||||
|
3ec: e58a0010 str r0, [sl, #16]
|
||||||
|
3f0: e3a00ebf mov r0, #3056 ; 0xbf0
|
||||||
|
3f4: ebcb1a01 bl step_debug
|
||||||
|
3f8: e59a0008 ldr r0, [sl, #8]
|
||||||
|
3fc: e1a00000 nop (mov r0,r0)
|
||||||
|
400: e58a0014 str r0, [sl, #20]
|
||||||
|
404: e3a00ffd mov r0, #1012 ; 0x3f4
|
||||||
|
408: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
40c: ebcb19fb bl step_debug
|
||||||
|
410: e59a0008 ldr r0, [sl, #8]
|
||||||
|
414: e1a05000 mov r5, r0
|
||||||
|
418: e3a00ffe mov r0, #1016 ; 0x3f8
|
||||||
|
41c: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
420: ebcb19f6 bl step_debug
|
||||||
|
424: e59a0008 ldr r0, [sl, #8]
|
||||||
|
428: e1a00000 nop (mov r0,r0)
|
||||||
|
42c: e58a001c str r0, [sl, #28]
|
||||||
|
430: e3a00fff mov r0, #1020 ; 0x3fc
|
||||||
|
434: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||||
|
438: ebcb19f0 bl step_debug
|
||||||
|
43c: e59a0008 ldr r0, [sl, #8]
|
||||||
|
440: e1a00000 nop (mov r0,r0)
|
||||||
|
444: e58a0020 str r0, [sl, #32]
|
||||||
|
448: e3a00b03 mov r0, #3072 ; 0xc00
|
||||||
|
44c: ebcb19eb bl step_debug
|
||||||
|
450: e59a0008 ldr r0, [sl, #8]
|
||||||
|
454: e1a06000 mov r6, r0
|
||||||
|
458: e24cc00a sub ip, ip, #10 ; 0xa
|
||||||
|
|
||||||
|
45c: e3a00f01 mov r0, #4 ; 0x4
|
||||||
|
460: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||||
|
464: ebcb19e5 bl step_debug
|
||||||
|
|
||||||
|
468: e59a0028 ldr r0, [sl, #40]
|
||||||
|
46c: e1540000 cmp r4, r0
|
||||||
|
470: e10fb000 mrs fp, CPSR
|
||||||
|
|
||||||
|
474: e3a00f02 mov r0, #8 ; 0x8
|
||||||
|
478: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||||
|
|
||||||
|
47c: ebcb19df bl step_debug
|
||||||
|
480: e24cc002 sub ip, ip, #2 ; 0x2
|
||||||
|
484: e128f00b msr CPSR_f, fp
|
||||||
|
|
||||||
|
488: aa000021 bge 0x514
|
||||||
|
48c: e1a09004 mov r9, r4
|
||||||
|
|
||||||
|
490: e1a00004 mov r0, r4
|
||||||
|
494: e2800020 add r0, r0, #32 ; 0x20
|
||||||
|
498: e1a04000 mov r4, r0
|
||||||
|
49c: e3c99003 bic r9, r9, #3 ; 0x3
|
||||||
|
4a0: e2890000 add r0, r9, #0 ; 0x0
|
||||||
|
4a4: e59a1008 ldr r1, [sl, #8]
|
||||||
|
4a8: ebcb1975 bl 0xff2c6a84
|
||||||
|
4ac: e2890004 add r0, r9, #4 ; 0x4
|
||||||
|
4b0: e59a100c ldr r1, [sl, #12]
|
||||||
|
4b4: ebcb1972 bl 0xff2c6a84
|
||||||
|
4b8: e2890008 add r0, r9, #8 ; 0x8
|
||||||
|
4bc: e59a1010 ldr r1, [sl, #16]
|
||||||
|
4c0: ebcb196f bl 0xff2c6a84
|
||||||
|
4c4: e289000c add r0, r9, #12 ; 0xc
|
||||||
|
4c8: e59a1014 ldr r1, [sl, #20]
|
||||||
|
4cc: ebcb196c bl 0xff2c6a84
|
||||||
|
4d0: e2890010 add r0, r9, #16 ; 0x10
|
||||||
|
4d4: e1a01005 mov r1, r5
|
||||||
|
4d8: ebcb1969 bl 0xff2c6a84
|
||||||
|
4dc: e2890014 add r0, r9, #20 ; 0x14
|
||||||
|
4e0: e59a101c ldr r1, [sl, #28]
|
||||||
|
4e4: ebcb1966 bl 0xff2c6a84
|
||||||
|
4e8: e2890018 add r0, r9, #24 ; 0x18
|
||||||
|
4ec: e59a1020 ldr r1, [sl, #32]
|
||||||
|
4f0: ebcb1963 bl 0xff2c6a84
|
||||||
|
4f4: e289001c add r0, r9, #28 ; 0x1c
|
||||||
|
4f8: e1a01006 mov r1, r6
|
||||||
|
4fc: e3a02f03 mov r2, #12 ; 0xc
|
||||||
|
500: e3822b03 orr r2, r2, #3072 ; 0xc00
|
||||||
|
504: ebcb1946 bl 0xff2c6a24
|
||||||
|
508: e3a00f03 mov r0, #12 ; 0xc
|
||||||
|
50c: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||||
|
510: ebcb19ba bl step_debug
|
||||||
|
514: e24cc009 sub ip, ip, #9 ; 0x9
|
||||||
|
518: e128f00b msr CPSR_f, fp
|
||||||
|
51c: aa000006 bge 0x53c
|
||||||
|
520: 5a000002 bpl 0x530
|
||||||
|
524: e3a00f01 mov r0, #4 ; 0x4
|
||||||
|
528: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||||
|
52c: ebcb178a bl 0xff2c635c
|
||||||
|
530: eaffffc9 b 0x45c
|
||||||
|
534: e3a00ec1 mov r0, #3088 ; 0xc10
|
||||||
|
538: ebcb19b0 bl step_debug
|
||||||
|
53c: e25cc001 subs ip, ip, #1 ; 0x1
|
||||||
|
540: 5a000002 bpl 0x550
|
||||||
|
544: e3a00f09 mov r0, #36 ; 0x24
|
||||||
|
548: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||||
|
54c: ebcb1782 bl 0xff2c635c
|
||||||
|
550: ea000053 b 0x6a4
|
||||||
|
554: e3a00f05 mov r0, #20 ; 0x14
|
||||||
|
558: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||||
|
55c: ebcb19a7 bl step_debug
|
||||||
|
560: e59a0028 ldr r0, [sl, #40]
|
||||||
|
564: e1540000 cmp r4, r0
|
||||||
|
568: e10fb000 mrs fp, CPSR
|
||||||
|
56c: e3a00f06 mov r0, #24 ; 0x18
|
||||||
|
570: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||||
|
574: ebcb19a1 bl step_debug
|
||||||
|
578: e24cc002 sub ip, ip, #2 ; 0x2
|
||||||
|
57c: e128f00b msr CPSR_f, fp
|
||||||
|
580: aa00003f bge 0x684
|
||||||
|
584: e1a09003 mov r9, r3
|
||||||
|
588: e1a00003 mov r0, r3
|
||||||
|
58c: e2800020 add r0, r0, #32 ; 0x20
|
||||||
|
590: e1a03000 mov r3, r0
|
||||||
|
594: e3c99003 bic r9, r9, #3 ; 0x3
|
||||||
|
598: e2890000 add r0, r9, #0 ; 0x0
|
||||||
|
59c: ebcb1989 bl 0xff2c6bc8
|
||||||
|
5a0: e58a0008 str r0, [sl, #8]
|
||||||
|
5a4: e2890004 add r0, r9, #4 ; 0x4
|
||||||
|
5a8: ebcb1986 bl 0xff2c6bc8
|
||||||
|
5ac: e58a000c str r0, [sl, #12]
|
||||||
|
5b0: e2890008 add r0, r9, #8 ; 0x8
|
||||||
|
5b4: ebcb1983 bl 0xff2c6bc8
|
||||||
|
5b8: e58a0010 str r0, [sl, #16]
|
||||||
|
5bc: e289000c add r0, r9, #12 ; 0xc
|
||||||
|
5c0: ebcb1980 bl 0xff2c6bc8
|
||||||
|
5c4: e58a0014 str r0, [sl, #20]
|
||||||
|
5c8: e2890010 add r0, r9, #16 ; 0x10
|
||||||
|
5cc: ebcb197d bl 0xff2c6bc8
|
||||||
|
5d0: e1a05000 mov r5, r0
|
||||||
|
5d4: e2890014 add r0, r9, #20 ; 0x14
|
||||||
|
5d8: ebcb197a bl 0xff2c6bc8
|
||||||
|
5dc: e58a001c str r0, [sl, #28]
|
||||||
|
5e0: e2890018 add r0, r9, #24 ; 0x18
|
||||||
|
5e4: ebcb1977 bl 0xff2c6bc8
|
||||||
|
5e8: e58a0020 str r0, [sl, #32]
|
||||||
|
5ec: e289001c add r0, r9, #28 ; 0x1c
|
||||||
|
5f0: ebcb1974 bl 0xff2c6bc8
|
||||||
|
5f4: e1a06000 mov r6, r0
|
||||||
|
5f8: e3a00f07 mov r0, #28 ; 0x1c
|
||||||
|
5fc: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||||
|
600: ebcb197e bl step_debug
|
||||||
|
604: e1a09004 mov r9, r4
|
||||||
|
608: e1a00004 mov r0, r4
|
||||||
|
60c: e2800020 add r0, r0, #32 ; 0x20
|
||||||
|
610: e1a04000 mov r4, r0
|
||||||
|
614: e3c99003 bic r9, r9, #3 ; 0x3
|
||||||
|
618: e2890000 add r0, r9, #0 ; 0x0
|
||||||
|
61c: e59a1008 ldr r1, [sl, #8]
|
||||||
|
620: ebcb1917 bl 0xff2c6a84
|
||||||
|
624: e2890004 add r0, r9, #4 ; 0x4
|
||||||
|
628: e59a100c ldr r1, [sl, #12]
|
||||||
|
62c: ebcb1914 bl 0xff2c6a84
|
||||||
|
630: e2890008 add r0, r9, #8 ; 0x8
|
||||||
|
634: e59a1010 ldr r1, [sl, #16]
|
||||||
|
638: ebcb1911 bl 0xff2c6a84
|
||||||
|
63c: e289000c add r0, r9, #12 ; 0xc
|
||||||
|
640: e59a1014 ldr r1, [sl, #20]
|
||||||
|
644: ebcb190e bl 0xff2c6a84
|
||||||
|
648: e2890010 add r0, r9, #16 ; 0x10
|
||||||
|
64c: e1a01005 mov r1, r5
|
||||||
|
650: ebcb190b bl 0xff2c6a84
|
||||||
|
654: e2890014 add r0, r9, #20 ; 0x14
|
||||||
|
658: e59a101c ldr r1, [sl, #28]
|
||||||
|
65c: ebcb1908 bl 0xff2c6a84
|
||||||
|
660: e2890018 add r0, r9, #24 ; 0x18
|
||||||
|
664: e59a1020 ldr r1, [sl, #32]
|
||||||
|
668: ebcb1905 bl 0xff2c6a84
|
||||||
|
66c: e289001c add r0, r9, #28 ; 0x1c
|
||||||
|
670: e1a01006 mov r1, r6
|
||||||
|
674: e3a02ec2 mov r2, #3104 ; 0xc20
|
||||||
|
678: ebcb18e9 bl 0xff2c6a24
|
||||||
|
|
||||||
|
67c: e3a00ec2 mov r0, #3104 ; 0xc20
|
||||||
|
680: ebcb195e bl step_debug
|
||||||
|
684: e24cc012 sub ip, ip, #18 ; 0x12
|
||||||
|
688: e128f00b msr CPSR_f, fp
|
||||||
|
68c: aa000007 bge 0x6b0
|
||||||
|
690: 5a000002 bpl 0x6a0
|
||||||
|
694: e3a00f05 mov r0, #20 ; 0x14
|
||||||
|
698: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||||
|
69c: ebcb172e bl 0xff2c635c
|
||||||
|
6a0: eaffffab b 0x554
|
||||||
|
|
||||||
|
6a4: e3a00f09 mov r0, #36 ; 0x24
|
||||||
|
6a8: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||||
|
6ac: ebcb1953 bl step_debug
|
||||||
|
6b0: e59a9034 ldr r9, [sl, #52]
|
||||||
|
6b4: e59a0034 ldr r0, [sl, #52]
|
||||||
|
6b8: e2800020 add r0, r0, #32 ; 0x20
|
||||||
|
6bc: e58a0034 str r0, [sl, #52]
|
||||||
|
6c0: e3c99003 bic r9, r9, #3 ; 0x3
|
||||||
|
6c4: e2890000 add r0, r9, #0 ; 0x0
|
||||||
|
6c8: ebcb193e bl 0xff2c6bc8
|
||||||
|
6cc: e58a0010 str r0, [sl, #16]
|
||||||
|
6d0: e2890004 add r0, r9, #4 ; 0x4
|
||||||
|
6d4: ebcb193b bl 0xff2c6bc8
|
||||||
|
6d8: e58a0014 str r0, [sl, #20]
|
||||||
|
6dc: e2890008 add r0, r9, #8 ; 0x8
|
||||||
|
6e0: ebcb1938 bl 0xff2c6bc8
|
||||||
|
6e4: e1a05000 mov r5, r0
|
||||||
|
6e8: e289000c add r0, r9, #12 ; 0xc
|
||||||
|
6ec: ebcb1935 bl 0xff2c6bc8
|
||||||
|
6f0: e58a001c str r0, [sl, #28]
|
||||||
|
6f4: e2890010 add r0, r9, #16 ; 0x10
|
||||||
|
6f8: ebcb1932 bl 0xff2c6bc8
|
||||||
|
6fc: e58a0020 str r0, [sl, #32]
|
||||||
|
700: e2890014 add r0, r9, #20 ; 0x14
|
||||||
|
704: ebcb192f bl 0xff2c6bc8
|
||||||
|
708: e1a06000 mov r6, r0
|
||||||
|
70c: e2890018 add r0, r9, #24 ; 0x18
|
||||||
|
710: ebcb192c bl 0xff2c6bc8
|
||||||
|
714: e58a0028 str r0, [sl, #40]
|
||||||
|
718: e289001c add r0, r9, #28 ; 0x1c
|
||||||
|
71c: ebcb1929 bl 0xff2c6bc8
|
||||||
|
720: e1a08000 mov r8, r0
|
||||||
|
|
||||||
|
724: e3a00f0a mov r0, #40 ; 0x28
|
||||||
|
728: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||||
|
72c: ebcb1933 bl step_debug
|
||||||
|
730: e1a00008 mov r0, r8
|
||||||
|
734: e24cc00a sub ip, ip, #10 ; 0xa
|
||||||
|
738: eacb1751 b 0xff2c6484
|
||||||
256
gp2x/cmdline.c
Normal file
256
gp2x/cmdline.c
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
|
||||||
|
/* commandline.c for GP2X Version 2.0
|
||||||
|
Copyright (C) 2006 god_at_hell
|
||||||
|
|
||||||
|
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "cpuctrl.h"
|
||||||
|
#include "gp2xminilib.h"
|
||||||
|
#include "cpuctrl.h"
|
||||||
|
|
||||||
|
|
||||||
|
void fallback(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
//beginning commandline-utilizing
|
||||||
|
if (argc == 3)
|
||||||
|
{
|
||||||
|
if (atoi(argv[1]) == 0)
|
||||||
|
{
|
||||||
|
if(atoi(argv[2]) > 36){gp2x_deinit();exit(1);}
|
||||||
|
if(atoi(argv[2]) < -20){gp2x_deinit();exit(1);}
|
||||||
|
set_add_FLCDCLK(atoi(argv[2]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(atoi(argv[2]) > 10){gp2x_deinit();exit(1);}
|
||||||
|
if(atoi(argv[2]) < -5){gp2x_deinit();exit(1);}
|
||||||
|
set_add_ULCDCLK(atoi(argv[2]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc == 4)
|
||||||
|
{
|
||||||
|
if(atoi(argv[3]) > 320){gp2x_deinit();exit(1);}
|
||||||
|
if(atoi(argv[3]) < 33){gp2x_deinit();exit(1);}
|
||||||
|
if (atoi(argv[1]) == 0)
|
||||||
|
{
|
||||||
|
if(atoi(argv[2]) > 36){gp2x_deinit();exit(1);}
|
||||||
|
if(atoi(argv[2]) < -20){gp2x_deinit();exit(1);}
|
||||||
|
set_add_FLCDCLK(atoi(argv[2]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(atoi(argv[2]) > 10){gp2x_deinit();exit(1);}
|
||||||
|
if(atoi(argv[2]) < -5){gp2x_deinit();exit(1);}
|
||||||
|
set_add_ULCDCLK(atoi(argv[2]));
|
||||||
|
}
|
||||||
|
set_FCLK(atoi(argv[3]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc == 5)
|
||||||
|
{
|
||||||
|
if(atoi(argv[3]) > 320){gp2x_deinit();exit(1);}
|
||||||
|
if(atoi(argv[3]) < 33){gp2x_deinit();exit(1);}
|
||||||
|
if(atof(argv[4]) > 10){gp2x_deinit();exit(1);}
|
||||||
|
if(atof(argv[4]) < 0.02){gp2x_deinit();exit(1);}
|
||||||
|
if (atoi(argv[1]) == 0)
|
||||||
|
{
|
||||||
|
if(atoi(argv[2]) > 36){gp2x_deinit();exit(1);}
|
||||||
|
if(atoi(argv[2]) < -20){gp2x_deinit();exit(1);}
|
||||||
|
set_add_FLCDCLK(atoi(argv[2]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(atoi(argv[2]) > 10){gp2x_deinit();exit(1);}
|
||||||
|
if(atoi(argv[2]) < -5){gp2x_deinit();exit(1);}
|
||||||
|
set_add_ULCDCLK(atoi(argv[2]));
|
||||||
|
}
|
||||||
|
set_FCLK(atoi(argv[3]));
|
||||||
|
set_gamma(atof(argv[4]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmdhelp()
|
||||||
|
{
|
||||||
|
printf ("\ngpSP2X v0.9003 Beta by Exophase/ZodTTD\r\n");
|
||||||
|
printf ("cpu_speed by god_at_hell\r\n");
|
||||||
|
printf ("Usage: cpu_speed.gpe [option1] [value1] [option2]...\r\n");
|
||||||
|
printf ("Options:\r\n");
|
||||||
|
printf (" RAM-Options\r\n");
|
||||||
|
printf (" -----------\r\n");
|
||||||
|
printf (" --cas CAS Latency. Delay in clock cycles between the registration \n\t\tof a READ command and the first bit of output data. \n\t\tValid values are 2 and 3 cycles.\r\n");
|
||||||
|
printf (" --trc ACTIVE to ACTIVE /AUTOREFRESH command delay. Defines ACTIVE \n\t\tto ACTIVE/auto refresh command period delay. \n\t\tValid values are from 1 to 16 cycles.\r\n");
|
||||||
|
printf (" --tras ACTIVE to PRECHARGE delay. Defines the delay between the ACTIVE \n\t\tand PRECHARGE commands. \n\t\tValid values are from 1 to 16 cycles.\r\n");
|
||||||
|
printf (" --twr Write recovery time in cycles.\n\t\tValid values are from 1 to 16 cycles.\r\n");
|
||||||
|
printf (" --tmrd LOAD MODE REGISTER command cycle time.\n\t\tValid values are from 1 to 16 cycles.\r\n");
|
||||||
|
printf (" --trfc AUTO REFRESH command period in cycles.\n\t\tValid values are from 1 to 16 cycles.\r\n");
|
||||||
|
printf (" --trp PRECHARGE command period in cycles.\n\t\tValid values are from 1 to 16 cycles.\r\n");
|
||||||
|
printf (" --trcd RAS to CAS Delay in cycles.\n\t\tValid values are from 1 to 16 cycles.\r\n");
|
||||||
|
printf (" --refperd Refresh Period. Defines maximum time period between \n\t\tAUTOREFRESH commands.\n\t\tValid values are from 1 to 65535 (default ~ 250) cycles.\r\n");
|
||||||
|
printf (" --ramdiv Divider for the Memory-Clock which is 1/2 of the CPU-Clock. \n\t\tValid values are from 1 to 8.\r\n");
|
||||||
|
printf ("\n CPU-Options\r\n");
|
||||||
|
printf (" -----------\r\n");
|
||||||
|
printf (" --cpuclk Sets the CPU-Frequency in Mhz. \n\t\tValid values are from 33 to 340.\r\n");
|
||||||
|
printf (" --cpudiv Divider for the CPU-Clock. \n\t\tValid values are from 1 to 8.\r\n");
|
||||||
|
printf ("\n Display-Options\r\n");
|
||||||
|
printf ("----------------\r\n");
|
||||||
|
printf (" --fpll Sets clockgenerator to fpll (for firmware 1.0 - 1.0.1).\r\n");
|
||||||
|
printf (" --upll Sets clockgenerator to upll (for the rest).\r\n");
|
||||||
|
printf (" --timing Timing Prescaler to eliminate flickering. \n\t\tValid values are: -20 to 36 with fpll.\n\t\t\t\t -6 to 10 with upll.\r\n");
|
||||||
|
printf (" --gamma Regulates the gamma. \n\t\tValid values are from 0.0001 to 15.0000.\r\n");
|
||||||
|
printf ("\n Daemon-Mode \r\n");
|
||||||
|
printf ("----------------\r\n");
|
||||||
|
printf ("Usage: cpu_speed.gpe --daemon [option1] [value1] [option2]...\r\n");
|
||||||
|
printf ("Shutdown: cpu_speed.gpe --kill[-daemon]\r\n");
|
||||||
|
printf ("Options:\r\n");
|
||||||
|
printf (" --min Sets the minimum CPU-Frequency in Mhz. \n\t\tValid values are from 33 to 340.\r\n");
|
||||||
|
printf (" --max Sets the maximum CPU-Frequency in Mhz. \n\t\tValid values are from 33 to 340.\r\n");
|
||||||
|
printf (" --start Sets the CPU-Frequency in Mhz. \n\t\tValid values are from 33 to 340.\r\n");
|
||||||
|
printf (" --step Sets the CPU-Frequency step in Mhz. \n\t\tValid values are from 1 to 340.\r\n");
|
||||||
|
printf (" --hotkey Sets the hotkey. (Default: LR) \n\t\tValid values are a combination of LRXYZAB+-S/@ or ``None''\n\t\t (+- are volume, S is Start, / is Select, @ is Stick).\r\n");
|
||||||
|
printf (" --incr Sets the increment key. (Default: +) \n\t\tValid values are a combination of LRXYZAB+-S/@ or ``None''\n\t\t (+- are volume, S is Start, / is Select, @ is Stick).\r\n");
|
||||||
|
printf (" --decr Sets the decrement key. (Default: -) \n\t\tValid values are a combination of LRXYZAB+-S/@ or ``None''\n\t\t (+- are volume, S is Start, / is Select, @ is Stick).\r\n");
|
||||||
|
printf (" --no-hotkey Alias for --hotkey None.\r\n");
|
||||||
|
printf (" --no-incr Alias for --incr None.\r\n");
|
||||||
|
printf (" --no-decr Alias for --decr None.\r\n");
|
||||||
|
printf (" --foreground Do not switch to daemon mode. (Useful for debugging)\r\n");
|
||||||
|
printf (" --background Switch to daemon mode. (Default)\r\n");
|
||||||
|
printf (" --display Enable on screen display. COMING SOON!\r\n");
|
||||||
|
printf (" --no-display Disable on screen display.\r\n");
|
||||||
|
printf ("\nNOTE:\nThe old commandline-settings are working ... read more about this in the readme\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmdline(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
short i,n;
|
||||||
|
short varis = 11;
|
||||||
|
char clockgen = get_Clkgen();
|
||||||
|
char var[11][9]={"--cas","--trc","--tras","--twr","--tmrd","--trfc","--trp","--trcd","--ramdiv","--cpuclk","--cpudiv"};
|
||||||
|
|
||||||
|
short val[varis];
|
||||||
|
for(n=0;n<varis;n++) //initialize the variable-array
|
||||||
|
{
|
||||||
|
val[n] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
short timing = -100;
|
||||||
|
int refperd = -1;
|
||||||
|
float gamma = -1.;
|
||||||
|
|
||||||
|
|
||||||
|
for(i=1; i<argc; i++)
|
||||||
|
{
|
||||||
|
if(strcmp(argv[i], "--fpll") == 0) clockgen = 0;
|
||||||
|
if(strcmp(argv[i], "--upll") == 0) clockgen = 1;
|
||||||
|
|
||||||
|
for(n=0; n<varis; n++)
|
||||||
|
{
|
||||||
|
if(strcmp(argv[i], var[n]) == 0)
|
||||||
|
{
|
||||||
|
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",var[n]);gp2x_deinit();exit(1);}
|
||||||
|
val[n] = atoi(argv[i+1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(strcmp(argv[i], "--refperd") == 0)
|
||||||
|
{
|
||||||
|
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||||
|
refperd = atoi(argv[i+1]);
|
||||||
|
}
|
||||||
|
if(strcmp(argv[i], "--gamma") == 0)
|
||||||
|
{
|
||||||
|
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||||
|
gamma = atof(argv[i+1]);
|
||||||
|
}
|
||||||
|
if(strcmp(argv[i], "--timing") == 0)
|
||||||
|
{
|
||||||
|
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||||
|
timing = atoi(argv[i+1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(clockgen == 0)
|
||||||
|
{
|
||||||
|
if(timing > -21)
|
||||||
|
{
|
||||||
|
if(timing < 37) set_add_FLCDCLK(timing);
|
||||||
|
}
|
||||||
|
else set_add_FLCDCLK(get_LCDClk(clockgen));
|
||||||
|
}
|
||||||
|
if(clockgen == 1)
|
||||||
|
{
|
||||||
|
if(timing > -7)
|
||||||
|
{
|
||||||
|
if(timing < 11) set_add_ULCDCLK(timing);
|
||||||
|
}
|
||||||
|
else set_add_ULCDCLK(get_LCDClk(clockgen));
|
||||||
|
}
|
||||||
|
if(refperd-1 > -1)
|
||||||
|
{
|
||||||
|
if(refperd-1 < 0xffff) set_REFPERD(refperd-1);
|
||||||
|
}
|
||||||
|
if(gamma > 0.)
|
||||||
|
{
|
||||||
|
if(gamma < 15.) set_gamma(gamma);
|
||||||
|
}
|
||||||
|
if(val[0]-2 > -1)
|
||||||
|
{
|
||||||
|
if(val[0]-2 < 2) set_CAS(val[0]-2);
|
||||||
|
}
|
||||||
|
if(val[1]-1 > -1)
|
||||||
|
{
|
||||||
|
if(val[1]-1 < 16) set_tRC(val[1]-1);
|
||||||
|
}
|
||||||
|
if(val[2]-1 > -1)
|
||||||
|
{
|
||||||
|
if(val[2]-1 < 16) set_tRAS(val[2]-1);
|
||||||
|
}
|
||||||
|
if(val[3]-1 > -1)
|
||||||
|
{
|
||||||
|
if(val[3]-1 < 16) set_tWR(val[3]-1);
|
||||||
|
}
|
||||||
|
if(val[4]-1 > -1)
|
||||||
|
{
|
||||||
|
if(val[4]-1 < 16) set_tMRD(val[4]-1);
|
||||||
|
}
|
||||||
|
if(val[5]-1 > -1)
|
||||||
|
{
|
||||||
|
if(val[5]-1 < 16) set_tRFC(val[5]-1);
|
||||||
|
}
|
||||||
|
if(val[6]-1 > -1)
|
||||||
|
{
|
||||||
|
if(val[6] < 16) set_tRP(val[6]-1);
|
||||||
|
}
|
||||||
|
if(val[7]-1 > -1)
|
||||||
|
{
|
||||||
|
if(val[7]-1 < 16) set_tRCD(val[7]-1);
|
||||||
|
}
|
||||||
|
if(val[8]-1 > -1)
|
||||||
|
{
|
||||||
|
if(val[8]-1 < 8) set_DCLK_Div(val[8]-1);
|
||||||
|
}
|
||||||
|
if(val[9] > 32)
|
||||||
|
{
|
||||||
|
if(val[9] < 341) set_FCLK(val[9]);
|
||||||
|
}
|
||||||
|
if(val[10]-1 > -1)
|
||||||
|
{
|
||||||
|
if(val[10]-1 < 8) set_920_Div(val[10]-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
3
gp2x/cmdline.h
Normal file
3
gp2x/cmdline.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
void fallback(int argc, char *argv[]);
|
||||||
|
void cmdhelp();
|
||||||
|
void cmdline(int argc, char *argv[]);
|
||||||
1276
gp2x/cpu_speed.c
Normal file
1276
gp2x/cpu_speed.c
Normal file
File diff suppressed because it is too large
Load Diff
484
gp2x/cpuctrl.c
Normal file
484
gp2x/cpuctrl.c
Normal file
@ -0,0 +1,484 @@
|
|||||||
|
/* cpuctrl.c for GP2X (CPU/LCD/RAM-Tuner Version 2.0)
|
||||||
|
Copyright (C) 2006 god_at_hell
|
||||||
|
original CPU-Overclocker (c) by Hermes/PS2Reality
|
||||||
|
the gamma-routine was provided by theoddbot
|
||||||
|
parts (c) Rlyehs Work
|
||||||
|
|
||||||
|
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************************************************************************/
|
||||||
|
// CPU CONTROL
|
||||||
|
/****************************************************************************************************************************************/
|
||||||
|
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "gp2xminilib.h"
|
||||||
|
|
||||||
|
#define SYS_CLK_FREQ 7372800
|
||||||
|
|
||||||
|
//from minimal library rlyeh
|
||||||
|
|
||||||
|
extern unsigned long gp2x_dev[4];
|
||||||
|
extern unsigned short *gp2x_memregs;
|
||||||
|
|
||||||
|
// system registers
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
unsigned short SYSCLKENREG,SYSCSETREG,FPLLVSETREG,DUALINT920,DUALINT940,DUALCTRL940,DISPCSETREG,MEMTIMEX0;
|
||||||
|
unsigned short MEMTIMEX1,MEMREFX,MLC_GAMM_BYPATH,MLC_GAMMA_A,MLC_GAMMA_D,YBNKLVL;
|
||||||
|
}
|
||||||
|
system_reg;
|
||||||
|
|
||||||
|
volatile unsigned short *MEM_REG;
|
||||||
|
unsigned MDIV,PDIV,SCALE;
|
||||||
|
volatile unsigned *arm940code;
|
||||||
|
|
||||||
|
void cpuctrl_init()
|
||||||
|
{
|
||||||
|
MEM_REG=&gp2x_memregs[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void save_system_regs()
|
||||||
|
{
|
||||||
|
system_reg.SYSCSETREG=MEM_REG[0x91c>>1];
|
||||||
|
system_reg.FPLLVSETREG=MEM_REG[0x912>>1];
|
||||||
|
system_reg.SYSCLKENREG=MEM_REG[0x904>>1];
|
||||||
|
system_reg.DUALINT920=MEM_REG[0x3B40>>1];
|
||||||
|
system_reg.DUALINT940=MEM_REG[0x3B42>>1];
|
||||||
|
system_reg.DUALCTRL940=MEM_REG[0x3B48>>1];
|
||||||
|
system_reg.DISPCSETREG=MEM_REG[0x924>>1];
|
||||||
|
system_reg.MEMTIMEX0=MEM_REG[0x3802>>1];
|
||||||
|
system_reg.MEMTIMEX1=MEM_REG[0x3804>>1];
|
||||||
|
system_reg.MEMREFX=MEM_REG[0x3808>>1];
|
||||||
|
system_reg.MLC_GAMM_BYPATH=MEM_REG[0x2880>>1];
|
||||||
|
system_reg.MLC_GAMMA_A=MEM_REG[0x295C>>1];
|
||||||
|
system_reg.MLC_GAMMA_D=MEM_REG[0x295E>>1];
|
||||||
|
system_reg.YBNKLVL=MEM_REG[0x283A>>1];
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_system_regs()
|
||||||
|
{
|
||||||
|
MEM_REG[0x91c>>1]=system_reg.SYSCSETREG;
|
||||||
|
MEM_REG[0x910>>1]=system_reg.FPLLVSETREG;
|
||||||
|
MEM_REG[0x3B40>>1]=system_reg.DUALINT920;
|
||||||
|
MEM_REG[0x3B42>>1]=system_reg.DUALINT940;
|
||||||
|
MEM_REG[0x3B48>>1]=system_reg.DUALCTRL940;
|
||||||
|
MEM_REG[0x904>>1]=system_reg.SYSCLKENREG;
|
||||||
|
/* Set UPLLSETVREG to 0x4F02, which gives 80MHz */
|
||||||
|
MEM_REG[0x0914>>1] = 0x4F02;
|
||||||
|
/* Wait for clock change to start */
|
||||||
|
while (MEM_REG[0x0902>>1] & 2);
|
||||||
|
/* Wait for clock change to be verified */
|
||||||
|
while (MEM_REG[0x0916>>1] != 0x4F02);
|
||||||
|
MEM_REG[0x3802>>1]=system_reg.MEMTIMEX0;
|
||||||
|
MEM_REG[0x3804>>1]=system_reg.MEMTIMEX1;
|
||||||
|
MEM_REG[0x3808>>1]=system_reg.MEMREFX;
|
||||||
|
MEM_REG[0x2880>>1]=system_reg.MLC_GAMM_BYPATH;
|
||||||
|
MEM_REG[0x295C>>1]=system_reg.MLC_GAMMA_A;
|
||||||
|
MEM_REG[0x295E>>1]=system_reg.MLC_GAMMA_D;
|
||||||
|
MEM_REG[0x283A>>1]=system_reg.YBNKLVL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void set_FCLK(unsigned MHZ)
|
||||||
|
{
|
||||||
|
printf ("set CPU-Frequency = %uMHz\r\n",MHZ);
|
||||||
|
unsigned v;
|
||||||
|
unsigned mdiv,pdiv=3,scale=0;
|
||||||
|
MHZ*=1000000;
|
||||||
|
mdiv=(MHZ*pdiv)/SYS_CLK_FREQ;
|
||||||
|
//printf ("Old value = %04X\r",MEM_REG[0x924>>1]," ");
|
||||||
|
//printf ("APLL = %04X\r",MEM_REG[0x91A>>1]," ");
|
||||||
|
mdiv=((mdiv-8)<<8) & 0xff00;
|
||||||
|
pdiv=((pdiv-2)<<2) & 0xfc;
|
||||||
|
scale&=3;
|
||||||
|
v=mdiv | pdiv | scale;
|
||||||
|
MEM_REG[0x910>>1]=v;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_FCLK()
|
||||||
|
{
|
||||||
|
return MEM_REG[0x910>>1];
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_add_FLCDCLK(int addclock)
|
||||||
|
{
|
||||||
|
//Set LCD controller to use FPLL
|
||||||
|
printf ("...set to FPLL-Clockgen...\r\n");
|
||||||
|
printf ("set Timing-Prescaler = %i\r\n",addclock);
|
||||||
|
MEM_REG[0x924>>1]= 0x5A00 + ((addclock)<<8);
|
||||||
|
//If you change the initial timing, don't forget to shift your intervall-borders in "cpu_speed.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_add_ULCDCLK(int addclock)
|
||||||
|
{
|
||||||
|
//Set LCD controller to use UPLL
|
||||||
|
printf ("...set to UPLL-Clockgen...\r\n");
|
||||||
|
printf ("set Timing-Prescaler = %i\r\n",addclock);
|
||||||
|
MEM_REG[0x0924>>1] = 0x8900 + ((addclock)<<8);
|
||||||
|
//If you change the initial timing, don't forget to shift your intervall-borders in "cpu_speed.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_LCDClk()
|
||||||
|
{
|
||||||
|
if (MEM_REG[0x0924>>1] < 0x7A01) return((MEM_REG[0x0924>>1] - 0x5A00)>>8);
|
||||||
|
else return((MEM_REG[0x0924>>1] - 0x8900)>>8);
|
||||||
|
}
|
||||||
|
|
||||||
|
char get_Clkgen()
|
||||||
|
{
|
||||||
|
if (MEM_REG[0x0924>>1] < 0x7A01) return(0);
|
||||||
|
else return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_freq_UCLK()
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
unsigned reg,mdiv,pdiv,scale;
|
||||||
|
i = MEM_REG[0x900>>1];
|
||||||
|
i = ((i >> 7) & 1) ;
|
||||||
|
if(i) return 0;
|
||||||
|
reg=MEM_REG[0x916>>1];
|
||||||
|
mdiv = ((reg & 0xff00) >> 8) + 8;
|
||||||
|
pdiv = ((reg & 0xfc) >> 2) + 2;
|
||||||
|
scale = reg & 3;
|
||||||
|
return ((SYS_CLK_FREQ * mdiv) / (pdiv << scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_freq_ACLK()
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
unsigned reg,mdiv,pdiv,scale;
|
||||||
|
i = MEM_REG[0x900>>1];
|
||||||
|
i = ((i >> 8) & 1) ;
|
||||||
|
if(i) return 0;
|
||||||
|
reg=MEM_REG[0x918>>1];
|
||||||
|
mdiv = ((reg & 0xff00) >> 8) + 8;
|
||||||
|
pdiv = ((reg & 0xfc) >> 2) + 2;
|
||||||
|
scale = reg & 3;
|
||||||
|
return ((SYS_CLK_FREQ * mdiv)/(pdiv << scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_freq_920_CLK()
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
unsigned reg,mdiv,pdiv,scale;
|
||||||
|
reg=MEM_REG[0x912>>1];
|
||||||
|
mdiv = ((reg & 0xff00) >> 8) + 8;
|
||||||
|
pdiv = ((reg & 0xfc) >> 2) + 2;
|
||||||
|
scale = reg & 3;
|
||||||
|
MDIV=mdiv;
|
||||||
|
PDIV=pdiv;
|
||||||
|
SCALE=scale;
|
||||||
|
i = (MEM_REG[0x91c>>1] & 7)+1;
|
||||||
|
return ((SYS_CLK_FREQ * mdiv)/(pdiv << scale))/i;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_freq_940_CLK()
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
unsigned reg,mdiv,pdiv,scale;
|
||||||
|
reg=MEM_REG[0x912>>1];
|
||||||
|
mdiv = ((reg & 0xff00) >> 8) + 8;
|
||||||
|
pdiv = ((reg & 0xfc) >> 2) + 2;
|
||||||
|
scale = reg & 3;
|
||||||
|
i = ((MEM_REG[0x91c>>1]>>3) & 7)+1;
|
||||||
|
return ((SYS_CLK_FREQ * mdiv) / (pdiv << scale))/i;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_freq_DCLK()
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
unsigned reg,mdiv,pdiv,scale;
|
||||||
|
reg=MEM_REG[0x912>>1];
|
||||||
|
mdiv = ((reg & 0xff00) >> 8) + 8;
|
||||||
|
pdiv = ((reg & 0xfc) >> 2) + 2;
|
||||||
|
scale = reg & 3;
|
||||||
|
i = ((MEM_REG[0x91c>>1]>>6) & 7)+1;
|
||||||
|
return ((SYS_CLK_FREQ * mdiv) / (pdiv << scale))/i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_920_Div(unsigned short div)
|
||||||
|
{
|
||||||
|
printf ("set divider for CPU-Clock = %u\r\n",div+1);
|
||||||
|
unsigned short v;
|
||||||
|
v = MEM_REG[0x91c>>1] & (~0x3);
|
||||||
|
MEM_REG[0x91c>>1] = (div & 0x7) | v;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short get_920_Div()
|
||||||
|
{
|
||||||
|
return (MEM_REG[0x91c>>1] & 0x7);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_940_Div(unsigned short div)
|
||||||
|
{
|
||||||
|
unsigned short v;
|
||||||
|
v = (unsigned short)( MEM_REG[0x91c>>1] & (~(0x7 << 3)));
|
||||||
|
MEM_REG[0x91c>>1] = ((div & 0x7) << 3) | v;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short get_940_Div()
|
||||||
|
{
|
||||||
|
return ((MEM_REG[0x91c>>1] >> 3) & 0x7);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_DCLK_Div( unsigned short div )
|
||||||
|
{
|
||||||
|
printf ("set divider for RAM-Clock = %u\r\n",div+1);
|
||||||
|
unsigned short v;
|
||||||
|
v = (unsigned short)( MEM_REG[0x91c>>1] & (~(0x7 << 6)));
|
||||||
|
MEM_REG[0x91c>>1] = ((div & 0x7) << 6) | v;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short get_DCLK_Div()
|
||||||
|
{
|
||||||
|
return ((MEM_REG[0x91c>>1] >> 6) & 0x7);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short Disable_Int_920()
|
||||||
|
{
|
||||||
|
unsigned short ret;
|
||||||
|
ret=MEM_REG[0x3B40>>1];
|
||||||
|
MEM_REG[0x3B40>>1]=0;
|
||||||
|
MEM_REG[0x3B44>>1]=0xffff;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short Disable_Int_940()
|
||||||
|
{
|
||||||
|
unsigned short ret;
|
||||||
|
ret=MEM_REG[0x3B42>>1];
|
||||||
|
MEM_REG[0x3B42>>1]=0;
|
||||||
|
MEM_REG[0x3B46>>1]=0xffff;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_state940()
|
||||||
|
{
|
||||||
|
return MEM_REG[0x904>>1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Enable_Int_920(unsigned short flag)
|
||||||
|
{
|
||||||
|
MEM_REG[0x3B40>>1]=flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Enable_Int_940(unsigned short flag)
|
||||||
|
{
|
||||||
|
MEM_REG[0x3B42>>1]=flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Disable_940()
|
||||||
|
{
|
||||||
|
Disable_Int_940();
|
||||||
|
MEM_REG[0x3B48>>1]|= (1 << 7);
|
||||||
|
MEM_REG[0x904>>1]&=0xfffe;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Load_940_code(unsigned *code,int size)
|
||||||
|
{
|
||||||
|
unsigned *cp;
|
||||||
|
int i;
|
||||||
|
arm940code=(unsigned short *)mmap(0, 0x100000, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_dev[2], 0x03000000);
|
||||||
|
Disable_940();
|
||||||
|
cp=(unsigned *) code;
|
||||||
|
for (i = 0; i < size/4; i ++)
|
||||||
|
{
|
||||||
|
arm940code[i] = cp[i];
|
||||||
|
}
|
||||||
|
for (i = 0; i < 64; i ++)
|
||||||
|
{
|
||||||
|
arm940code[0x3FC0+i] = 0;
|
||||||
|
}
|
||||||
|
MEM_REG[0x3B48>>1]=(MEM_REG[0x3B48>>1] & 0xFF00) | 0x03; // allow 940
|
||||||
|
}
|
||||||
|
|
||||||
|
void clock_940_off()
|
||||||
|
{
|
||||||
|
MEM_REG[0x904>>1]&=0xfffe;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clock_940_on()
|
||||||
|
{
|
||||||
|
MEM_REG[0x904>>1]|=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------
|
||||||
|
//Memory Timings
|
||||||
|
//--------------
|
||||||
|
|
||||||
|
//get
|
||||||
|
|
||||||
|
unsigned get_CAS()
|
||||||
|
{
|
||||||
|
return ((MEM_REG[0x3804>>1] >> 12) & 0x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_tRC()
|
||||||
|
{
|
||||||
|
return ((MEM_REG[0x3804>>1] >> 8) & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_tRAS()
|
||||||
|
{
|
||||||
|
return ((MEM_REG[0x3804>>1] >> 4) & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_tWR()
|
||||||
|
{
|
||||||
|
return (MEM_REG[0x3804>>1] & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_tMRD()
|
||||||
|
{
|
||||||
|
return ((MEM_REG[0x3802>>1] >> 12) & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_tRFC()
|
||||||
|
{
|
||||||
|
return ((MEM_REG[0x3802>>1] >> 8) & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_tRP()
|
||||||
|
{
|
||||||
|
return ((MEM_REG[0x3802>>1] >> 4) & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_tRCD()
|
||||||
|
{
|
||||||
|
return (MEM_REG[0x3802>>1] & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_REFPERD()
|
||||||
|
{
|
||||||
|
return MEM_REG[0x3808>>1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//set
|
||||||
|
|
||||||
|
void set_CAS(unsigned short timing)
|
||||||
|
{
|
||||||
|
printf ("set CAS = %u\r\n",timing+2);
|
||||||
|
unsigned short v;
|
||||||
|
v = (unsigned short)(MEM_REG[0x3804>>1] & (~(0x1 << 12)));
|
||||||
|
MEM_REG[0x3804>>1] = ((timing & 0x1) << 12) | v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_tRC(unsigned short timing)
|
||||||
|
{
|
||||||
|
printf ("set tRC = %u\r\n",timing+1);
|
||||||
|
unsigned short v;
|
||||||
|
v = (unsigned short)(MEM_REG[0x3804>>1] & (~(0xF << 8)));
|
||||||
|
MEM_REG[0x3804>>1] = ((timing & 0xF) << 8) | v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_tRAS(unsigned short timing)
|
||||||
|
{
|
||||||
|
printf ("set tRAS = %u\r\n",timing+1);
|
||||||
|
unsigned short v;
|
||||||
|
v = (unsigned short)(MEM_REG[0x3804>>1] & (~(0xF << 4)));
|
||||||
|
MEM_REG[0x3804>>1] = ((timing & 0xF) << 4) | v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_tWR(unsigned short timing)
|
||||||
|
{
|
||||||
|
printf ("set tWR = %u\r\n",timing+1);
|
||||||
|
unsigned short v;
|
||||||
|
v = (unsigned short)(MEM_REG[0x3804>>1] & (~(0xF)));
|
||||||
|
MEM_REG[0x3804>>1] = (timing & 0xF) | v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_tMRD(unsigned short timing)
|
||||||
|
{
|
||||||
|
printf ("set tMRD = %u\r\n",timing+1);
|
||||||
|
unsigned short v;
|
||||||
|
v = (unsigned short)(MEM_REG[0x3802>>1] & (~(0xF << 12)));
|
||||||
|
MEM_REG[0x3802>>1] = ((timing & 0xF) << 12) | v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_tRFC(unsigned short timing)
|
||||||
|
{
|
||||||
|
printf ("set tRFC = %u\r\n",timing+1);
|
||||||
|
unsigned short v;
|
||||||
|
v = (unsigned short)(MEM_REG[0x3802>>1] & (~(0xF << 8)));
|
||||||
|
MEM_REG[0x3802>>1] = ((timing & 0xF) << 8) | v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_tRP(unsigned short timing)
|
||||||
|
{
|
||||||
|
printf ("set tRP = %u\r\n",timing+1);
|
||||||
|
unsigned short v;
|
||||||
|
v = (unsigned short)(MEM_REG[0x3802>>1] & (~(0xF << 4)));
|
||||||
|
MEM_REG[0x3802>>1] = ((timing & 0xF) << 4) | v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_tRCD(unsigned short timing)
|
||||||
|
{
|
||||||
|
printf ("set tRCD = %u\r\n",timing+1);
|
||||||
|
unsigned short v;
|
||||||
|
v = (unsigned short)(MEM_REG[0x3802>>1] & (~(0xF)));
|
||||||
|
MEM_REG[0x3802>>1] = (timing & 0xF) | v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_REFPERD(unsigned short timing)
|
||||||
|
{
|
||||||
|
printf ("set Refresh Period = %u\r\n",timing+1);
|
||||||
|
MEM_REG[0x3808>>1] = timing;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----
|
||||||
|
//Gamma
|
||||||
|
//-----
|
||||||
|
|
||||||
|
void set_gamma(float gamma)
|
||||||
|
{
|
||||||
|
printf ("set gamma = %f\r\n",gamma);
|
||||||
|
int i;
|
||||||
|
gamma = 1/gamma;
|
||||||
|
|
||||||
|
//enable gamma
|
||||||
|
MEM_REG[0x2880>>1]&=~(1<<12);
|
||||||
|
|
||||||
|
MEM_REG[0x295C>>1]=0;
|
||||||
|
for(i=0; i<256; i++)
|
||||||
|
{
|
||||||
|
unsigned char g;
|
||||||
|
unsigned short s;
|
||||||
|
g =(unsigned char)(255.0*pow(i/255.0,gamma));
|
||||||
|
s = (g<<8) | g;
|
||||||
|
MEM_REG[0x295E>>1]= s;
|
||||||
|
MEM_REG[0x295E>>1]= g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_YBNKLVL()
|
||||||
|
{
|
||||||
|
return (MEM_REG[0x283A>>1] & 0x3FF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_YBNKLVL(unsigned short val)
|
||||||
|
{
|
||||||
|
unsigned short temp = (unsigned short)(MEM_REG[0x3808>>1] & (~(0x3FF)));
|
||||||
|
MEM_REG[0x3808>>1] = (val & 0x3FF) | temp;
|
||||||
|
}
|
||||||
72
gp2x/cpuctrl.h
Normal file
72
gp2x/cpuctrl.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#if !defined(_CPUCTRL_)
|
||||||
|
#define _CPUCTRL_
|
||||||
|
|
||||||
|
void cpuctrl_init(); // call this at first
|
||||||
|
|
||||||
|
void save_system_regs(); // save some registers
|
||||||
|
void load_system_regs();
|
||||||
|
|
||||||
|
void set_FCLK(unsigned MHZ); // adjust the clock frequency (in Mhz units)
|
||||||
|
void set_add_ULCDCLK(int addclock);
|
||||||
|
void set_add_FLCDCLK(int addclock);
|
||||||
|
|
||||||
|
unsigned get_FCLK();
|
||||||
|
unsigned get_freq_UCLK();
|
||||||
|
unsigned get_freq_ACLK();
|
||||||
|
unsigned get_freq_920_CLK();
|
||||||
|
unsigned get_freq_940_CLK();
|
||||||
|
unsigned get_freq_DCLK();
|
||||||
|
unsigned get_LCDClk();
|
||||||
|
char get_Clkgen();
|
||||||
|
unsigned get_state940();
|
||||||
|
|
||||||
|
void set_920_Div(unsigned short div); /* 0 to 7 divider (freq=FCLK/(1+div)) */
|
||||||
|
unsigned short get_920_Div();
|
||||||
|
|
||||||
|
void set_940_Div(unsigned short div); /* 0 to 7 divider (freq=FCLK/(1+div)) */
|
||||||
|
unsigned short get_940_Div();
|
||||||
|
|
||||||
|
void set_DCLK_Div(unsigned short div); /* 0 to 7 divider (freq=FCLK/(1+div)) */
|
||||||
|
unsigned short get_DCLK_Div();
|
||||||
|
|
||||||
|
unsigned short Disable_Int_920();
|
||||||
|
unsigned short Disable_Int_940();
|
||||||
|
|
||||||
|
void Enable_Int_920(unsigned short flag);
|
||||||
|
void Enable_Int_940(unsigned short flag);
|
||||||
|
|
||||||
|
void Disable_940(); // 940t down
|
||||||
|
|
||||||
|
extern volatile unsigned *arm940code; // memory address of 940t code
|
||||||
|
|
||||||
|
void Load_940_code(unsigned *code,int size); // enable 940t, load 940t code and clock 940t off
|
||||||
|
|
||||||
|
void clock_940_off(); // 940t stops
|
||||||
|
void clock_940_on(); // 940t running
|
||||||
|
|
||||||
|
//Memory Timings
|
||||||
|
unsigned get_CAS(); //CAS Latency
|
||||||
|
unsigned get_tRC(); //ACTIVE to ACTIVE /AUTOREFRESH command delay
|
||||||
|
unsigned get_tRAS(); //ACTIVE to PRECHARGE delay
|
||||||
|
unsigned get_tWR(); //Write recovery time
|
||||||
|
unsigned get_tMRD(); //LOAD MODE REGISTER command cycle time
|
||||||
|
unsigned get_tRFC(); //AUTO REFRESH command period
|
||||||
|
unsigned get_tRP(); //PRECHARGE command period
|
||||||
|
unsigned get_tRCD(); //RAS to CAS Delay
|
||||||
|
unsigned get_REFPERD();//Refresh Period
|
||||||
|
|
||||||
|
void set_CAS();
|
||||||
|
void set_tRC();
|
||||||
|
void set_tRAS();
|
||||||
|
void set_tWR();
|
||||||
|
void set_tMRD();
|
||||||
|
void set_tRFC();
|
||||||
|
void set_tRP();
|
||||||
|
void set_tRCD();
|
||||||
|
void set_REFPERD();
|
||||||
|
|
||||||
|
void set_gamma(float gamma);
|
||||||
|
|
||||||
|
unsigned get_YBNKLVL();
|
||||||
|
void set_YBNKLVL(unsigned short val);
|
||||||
|
#endif
|
||||||
671
gp2x/daemon.c
Normal file
671
gp2x/daemon.c
Normal file
@ -0,0 +1,671 @@
|
|||||||
|
/* daemon.c for GP2X Version 2.0
|
||||||
|
Copyright (C) 2006 jannis harder
|
||||||
|
|
||||||
|
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "gp2xminilib.h"
|
||||||
|
#include "cpuctrl.h"
|
||||||
|
#include "display.h"
|
||||||
|
|
||||||
|
#include "daemon.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern unsigned COLORFONDO; // background-color
|
||||||
|
extern unsigned WHITE;
|
||||||
|
extern unsigned TEXTBACK;
|
||||||
|
|
||||||
|
extern unsigned char cad[256];
|
||||||
|
|
||||||
|
extern unsigned short *gp2x_memregs;
|
||||||
|
extern pthread_t gp2x_sound_thread;
|
||||||
|
|
||||||
|
int start_daemon(
|
||||||
|
unsigned int minimal_cpu_speed, unsigned int maximal_cpu_speed, unsigned int start_cpu_speed, int cpu_speed_step,
|
||||||
|
unsigned long hotkey, unsigned long incrementkey, unsigned long decrementkey,
|
||||||
|
int speed_display, int foreground,
|
||||||
|
unsigned long delay)
|
||||||
|
{
|
||||||
|
pid_t pid, sid;
|
||||||
|
|
||||||
|
if(!foreground) {
|
||||||
|
kill_running_daemon();
|
||||||
|
|
||||||
|
|
||||||
|
FILE * pidfile = fopen("/tmp/cpu_daemon.pid","w");
|
||||||
|
|
||||||
|
if(!pidfile) {
|
||||||
|
printf("couldn't write pidfile\r\n");
|
||||||
|
exit(-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
|
||||||
|
if(pid > 0) {
|
||||||
|
fprintf(pidfile,"%i\n",pid);
|
||||||
|
fclose(pidfile);
|
||||||
|
}
|
||||||
|
if(pid != 0)
|
||||||
|
return pid;
|
||||||
|
|
||||||
|
|
||||||
|
fclose(pidfile);
|
||||||
|
|
||||||
|
umask(0);
|
||||||
|
sid = setsid();
|
||||||
|
|
||||||
|
|
||||||
|
close(STDIN_FILENO);
|
||||||
|
close(STDOUT_FILENO);
|
||||||
|
close(STDERR_FILENO);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(foreground)
|
||||||
|
printf("daemon ready\r\n");
|
||||||
|
|
||||||
|
nano_setup(); // loading the full minilib would be overkill and i guess some games/emus wouldn't like it
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int current_cpu_speed = start_cpu_speed;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
usleep(delay);
|
||||||
|
unsigned long keystate = gp2x_joystick_read();
|
||||||
|
|
||||||
|
unsigned int last_cpu_speed = 0;
|
||||||
|
|
||||||
|
while(
|
||||||
|
(hotkey && (keystate & hotkey) == hotkey) ||
|
||||||
|
((!hotkey) && (
|
||||||
|
(incrementkey && (keystate & incrementkey) == incrementkey) ||
|
||||||
|
(decrementkey && (keystate & decrementkey) == decrementkey)
|
||||||
|
))
|
||||||
|
) {
|
||||||
|
if(foreground && !last_cpu_speed)
|
||||||
|
printf("cpu daemon activated!\r\n");
|
||||||
|
|
||||||
|
if(incrementkey && (keystate & incrementkey) == incrementkey) {
|
||||||
|
current_cpu_speed += cpu_speed_step;
|
||||||
|
while((keystate & incrementkey) == incrementkey) usleep(100000),keystate = gp2x_joystick_read();
|
||||||
|
}
|
||||||
|
else if(decrementkey && (keystate & decrementkey) == decrementkey) {
|
||||||
|
current_cpu_speed -= cpu_speed_step;
|
||||||
|
while((keystate & decrementkey) == decrementkey) usleep(100000),keystate = gp2x_joystick_read();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(current_cpu_speed < minimal_cpu_speed)
|
||||||
|
current_cpu_speed = minimal_cpu_speed;
|
||||||
|
if(current_cpu_speed > maximal_cpu_speed)
|
||||||
|
current_cpu_speed = maximal_cpu_speed;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(last_cpu_speed != current_cpu_speed) {
|
||||||
|
set_FCLK(current_cpu_speed);
|
||||||
|
}
|
||||||
|
last_cpu_speed = current_cpu_speed;
|
||||||
|
keystate = gp2x_joystick_read();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int kill_running_daemon() {
|
||||||
|
|
||||||
|
FILE * pidfile = fopen("/tmp/cpu_daemon.pid","r");
|
||||||
|
char pid_buffer[14];
|
||||||
|
pid_buffer[0] = 'k';
|
||||||
|
pid_buffer[1] = 'i';
|
||||||
|
pid_buffer[2] = 'l';
|
||||||
|
pid_buffer[3] = 'l';
|
||||||
|
pid_buffer[4] = ' ';
|
||||||
|
pid_buffer[5] = 0;
|
||||||
|
if(pidfile) {
|
||||||
|
printf("found pidfile\r\n");
|
||||||
|
fgets(&(pid_buffer[5]),10,pidfile);
|
||||||
|
fclose(pidfile);
|
||||||
|
int return_code = system(pid_buffer);
|
||||||
|
if(return_code)
|
||||||
|
printf("daemon wasn't running\r\n");
|
||||||
|
else
|
||||||
|
printf("killed old daemon\r\n");
|
||||||
|
unlink("/tmp/cpu_daemon.pid");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void nano_setup() {
|
||||||
|
if(!gp2x_sound_thread) {
|
||||||
|
gp2x_memregs=(unsigned short *)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, open("/dev/mem", O_RDWR), 0xc0000000);
|
||||||
|
cpuctrl_init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmd_daemon(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
int cpu_div = get_920_Div();
|
||||||
|
int sysfreq=get_freq_920_CLK();
|
||||||
|
sysfreq*=cpu_div+1;
|
||||||
|
int cpufreq=sysfreq/1000000;
|
||||||
|
|
||||||
|
unsigned int minimal_value = 33;
|
||||||
|
unsigned int maximal_value = 260;
|
||||||
|
unsigned int start_value = cpufreq;
|
||||||
|
unsigned int step = 10;
|
||||||
|
unsigned long hotkey = GP2X_L | GP2X_R;
|
||||||
|
unsigned long downkey = GP2X_VOL_UP;
|
||||||
|
unsigned long upkey = GP2X_VOL_DOWN;
|
||||||
|
int foreground = 0;
|
||||||
|
int display = 1;
|
||||||
|
float delay = 1;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for( i = 2; i < argc; i++) {
|
||||||
|
if(!strcmp(argv[i],"--min")) {
|
||||||
|
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||||
|
minimal_value = atoi(argv[i+1]);
|
||||||
|
if(minimal_value < 33)
|
||||||
|
minimal_value = 33;
|
||||||
|
}
|
||||||
|
else if(!strcmp(argv[i],"--max")) {
|
||||||
|
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||||
|
maximal_value = atoi(argv[i+1]);
|
||||||
|
if(maximal_value > 340)
|
||||||
|
maximal_value = 340;
|
||||||
|
}
|
||||||
|
else if(!strcmp(argv[i],"--start")) {
|
||||||
|
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||||
|
start_value = atoi(argv[i+1]);
|
||||||
|
}
|
||||||
|
else if(!strcmp(argv[i],"--step")) {
|
||||||
|
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||||
|
step = atoi(argv[i+1]);
|
||||||
|
}
|
||||||
|
else if(!strcmp(argv[i],"--hotkey")) {
|
||||||
|
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||||
|
hotkey = parse_key_sequence(argv[i+1]);
|
||||||
|
}
|
||||||
|
else if(!strcmp(argv[i],"--incr")) {
|
||||||
|
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||||
|
upkey = parse_key_sequence(argv[i+1]);
|
||||||
|
}
|
||||||
|
else if(!strcmp(argv[i],"--decr")) {
|
||||||
|
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||||
|
downkey = parse_key_sequence(argv[i+1]);
|
||||||
|
}
|
||||||
|
else if(!strcmp(argv[i],"--delay")) {
|
||||||
|
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||||
|
delay = atof(argv[i+1]);
|
||||||
|
}
|
||||||
|
else if(!strcmp(argv[i],"--no-incr")) {
|
||||||
|
upkey = 0;
|
||||||
|
}
|
||||||
|
else if(!strcmp(argv[i],"--no-decr")) {
|
||||||
|
downkey = 0;
|
||||||
|
}
|
||||||
|
else if(!strcmp(argv[i],"--no-hotkey")) {
|
||||||
|
hotkey = 0;
|
||||||
|
}
|
||||||
|
else if(!strcmp(argv[i],"--foreground")) {
|
||||||
|
foreground = 1;
|
||||||
|
}
|
||||||
|
else if(!strcmp(argv[i],"--background")) {
|
||||||
|
foreground = 0;
|
||||||
|
}
|
||||||
|
else if(!strcmp(argv[i],"--display")) {
|
||||||
|
display = 1;
|
||||||
|
}
|
||||||
|
else if(!strcmp(argv[i],"--no-display")) {
|
||||||
|
display = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((hotkey & downkey) == downkey)
|
||||||
|
printf("warning: hotkey includes decrement keypress!\r\n");
|
||||||
|
if((hotkey & upkey) == upkey)
|
||||||
|
printf("warning: hotkey includes increment keypress!\r\n");
|
||||||
|
|
||||||
|
int pid = start_daemon(minimal_value, maximal_value, start_value, step, hotkey, upkey, downkey, display, foreground, delay* 1000000);
|
||||||
|
|
||||||
|
if(pid < 0) {
|
||||||
|
printf("couldn't start daemon\r\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
else if(pid > 0) {
|
||||||
|
printf("daemon started\r\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long parse_key_sequence(char *key_sequence) {
|
||||||
|
unsigned long hotkey = 0;
|
||||||
|
if(!strcmp(key_sequence,"None"))
|
||||||
|
return 0;
|
||||||
|
char *mask = key_sequence;
|
||||||
|
while(*mask) {
|
||||||
|
switch(*mask) {
|
||||||
|
case 'l':
|
||||||
|
case 'L':
|
||||||
|
hotkey |= GP2X_L;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
case 'R':
|
||||||
|
hotkey |= GP2X_R;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
hotkey |= GP2X_A;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
case 'B':
|
||||||
|
hotkey |= GP2X_B;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
case 'X':
|
||||||
|
hotkey |= GP2X_X;
|
||||||
|
break;
|
||||||
|
case 'y':
|
||||||
|
case 'Y':
|
||||||
|
hotkey |= GP2X_Y;
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
hotkey |= GP2X_VOL_DOWN;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
hotkey |= GP2X_VOL_UP;
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
case 's':
|
||||||
|
hotkey |= GP2X_START;
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
hotkey |= GP2X_SELECT;
|
||||||
|
break;
|
||||||
|
case '@':
|
||||||
|
hotkey |= GP2X_PUSH;
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("unknown key %c\r\n",*mask);
|
||||||
|
}
|
||||||
|
mask++;
|
||||||
|
}
|
||||||
|
return hotkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
int daemonsettings[8];
|
||||||
|
|
||||||
|
|
||||||
|
void cleardisp();
|
||||||
|
|
||||||
|
|
||||||
|
void formatkey(char * base, unsigned long keyseq) {
|
||||||
|
|
||||||
|
if(!keyseq)
|
||||||
|
strcat(base,"None");
|
||||||
|
|
||||||
|
if(keyseq & GP2X_L)
|
||||||
|
strcat(base,"L");
|
||||||
|
if(keyseq & GP2X_R)
|
||||||
|
strcat(base,"R");
|
||||||
|
if(keyseq & GP2X_A)
|
||||||
|
strcat(base,"A");
|
||||||
|
if(keyseq & GP2X_B)
|
||||||
|
strcat(base,"B");
|
||||||
|
if(keyseq & GP2X_X)
|
||||||
|
strcat(base,"X");
|
||||||
|
if(keyseq & GP2X_Y)
|
||||||
|
strcat(base,"Y");
|
||||||
|
if(keyseq & GP2X_VOL_DOWN)
|
||||||
|
strcat(base,"+");
|
||||||
|
if(keyseq & GP2X_VOL_UP)
|
||||||
|
strcat(base,"-");
|
||||||
|
if(keyseq & GP2X_START)
|
||||||
|
strcat(base,"S");
|
||||||
|
if(keyseq & GP2X_SELECT)
|
||||||
|
strcat(base,"/");
|
||||||
|
if(keyseq & GP2X_PUSH)
|
||||||
|
strcat(base,"@");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define VALID_KEYS ((GP2X_L) | (GP2X_R) | (GP2X_X) | (GP2X_Y) | (GP2X_A) | (GP2X_B) | (GP2X_START) | (GP2X_SELECT) | (GP2X_VOL_UP) | (GP2X_VOL_DOWN) | (GP2X_PUSH) )
|
||||||
|
|
||||||
|
int running;
|
||||||
|
|
||||||
|
void daemon_itemhelp(int menuitem)
|
||||||
|
{
|
||||||
|
switch(menuitem) {
|
||||||
|
case 0:
|
||||||
|
v_putcad(26,8,0xffffff,COLORFONDO,"Choose a");
|
||||||
|
v_putcad(26,9,0xffffff,COLORFONDO,"minimal");
|
||||||
|
v_putcad(26,10,0xffffff,COLORFONDO,"clockspeed");
|
||||||
|
v_putcad(26,11,0xffffff,COLORFONDO,"with R/L or");
|
||||||
|
v_putcad(26,12,0xffffff,COLORFONDO,"Vol UP/Down.");
|
||||||
|
v_putcad(26,14,0xffffff,COLORFONDO,"Valid speeds");
|
||||||
|
v_putcad(26,15,0xffffff,COLORFONDO,"are:");
|
||||||
|
v_putcad(26,16,0xffffff,COLORFONDO,"33 to 340Mhz");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
v_putcad(26,8,0xffffff,COLORFONDO,"Choose a");
|
||||||
|
v_putcad(26,9,0xffffff,COLORFONDO,"maximal");
|
||||||
|
v_putcad(26,10,0xffffff,COLORFONDO,"clockspeed");
|
||||||
|
v_putcad(26,11,0xffffff,COLORFONDO,"with R/L or");
|
||||||
|
v_putcad(26,12,0xffffff,COLORFONDO,"Vol UP/Down.");
|
||||||
|
v_putcad(26,14,0xffffff,COLORFONDO,"Valid speeds");
|
||||||
|
v_putcad(26,15,0xffffff,COLORFONDO,"are:");
|
||||||
|
v_putcad(26,16,0xffffff,COLORFONDO,"33 to 340Mhz");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
v_putcad(26,8,0xffffff,COLORFONDO,"Choose a step");
|
||||||
|
v_putcad(26,9,0xffffff,COLORFONDO,"width for");
|
||||||
|
v_putcad(26,10,0xffffff,COLORFONDO,"changing the");
|
||||||
|
v_putcad(26,11,0xffffff,COLORFONDO,"clockspeed.");
|
||||||
|
v_putcad(26,13,0xffffff,COLORFONDO,"Use R/L or");
|
||||||
|
v_putcad(26,14,0xffffff,COLORFONDO,"Vol UP/Down.");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
v_putcad(26,8,0xffffff,COLORFONDO,"Choose a");
|
||||||
|
v_putcad(26,9,0xffffff,COLORFONDO,"delay between");
|
||||||
|
v_putcad(26,10,0xffffff,COLORFONDO,"each hotkey");
|
||||||
|
v_putcad(26,11,0xffffff,COLORFONDO,"check");
|
||||||
|
v_putcad(26,13,0xffffff,COLORFONDO,"Use R/L or");
|
||||||
|
v_putcad(26,14,0xffffff,COLORFONDO,"Vol UP/Down.");
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
v_putcad(26,8,0xffffff,COLORFONDO,"Choose a");
|
||||||
|
v_putcad(26,9,0xffffff,COLORFONDO,"hotkey.");
|
||||||
|
v_putcad(26,10,0xffffff,COLORFONDO,"Add or delete");
|
||||||
|
v_putcad(26,11,0xffffff,COLORFONDO,"a button by");
|
||||||
|
v_putcad(26,12,0xffffff,COLORFONDO,"pressing it.");
|
||||||
|
v_putcad(26,14,0x0000DD,COLORFONDO,"Joystick is");
|
||||||
|
v_putcad(26,15,0x0000DD,COLORFONDO,"not allowed.");
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
v_putcad(26,8,0xffffff,COLORFONDO,"Choose a");
|
||||||
|
v_putcad(26,9,0xffffff,COLORFONDO,"key for");
|
||||||
|
v_putcad(26,10,0xffffff,COLORFONDO,"incrementing");
|
||||||
|
v_putcad(26,11,0xffffff,COLORFONDO,"the clkspeed.");
|
||||||
|
v_putcad(26,12,0xffffff,COLORFONDO,"Add or delete");
|
||||||
|
v_putcad(26,13,0xffffff,COLORFONDO,"a button by");
|
||||||
|
v_putcad(26,14,0xffffff,COLORFONDO,"pressing it.");
|
||||||
|
v_putcad(26,16,0x0000DD,COLORFONDO,"Joystick is");
|
||||||
|
v_putcad(26,17,0x0000DD,COLORFONDO,"not allowed.");
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
v_putcad(26,8,0xffffff,COLORFONDO,"Choose a");
|
||||||
|
v_putcad(26,9,0xffffff,COLORFONDO,"key for");
|
||||||
|
v_putcad(26,10,0xffffff,COLORFONDO,"decrementing");
|
||||||
|
v_putcad(26,11,0xffffff,COLORFONDO,"the clkspeed.");
|
||||||
|
v_putcad(26,12,0xffffff,COLORFONDO,"Add or delete");
|
||||||
|
v_putcad(26,13,0xffffff,COLORFONDO,"a button by");
|
||||||
|
v_putcad(26,14,0xffffff,COLORFONDO,"pressing it.");
|
||||||
|
v_putcad(26,16,0x0000DD,COLORFONDO,"Joystick is");
|
||||||
|
v_putcad(26,17,0x0000DD,COLORFONDO,"not allowed.");
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
/* v_putcad(26,8,0xffffff,COLORFONDO,"Enable or");
|
||||||
|
v_putcad(26,9,0xffffff,COLORFONDO,"disable");
|
||||||
|
v_putcad(26,10,0xffffff,COLORFONDO,"on screen");
|
||||||
|
v_putcad(26,11,0xffffff,COLORFONDO,"display.");
|
||||||
|
v_putcad(26,13,0x0000DD,COLORFONDO,"May cause");
|
||||||
|
v_putcad(26,14,0x0000DD,COLORFONDO,"conflicts");
|
||||||
|
v_putcad(26,15,0x0000DD,COLORFONDO,"with");
|
||||||
|
v_putcad(26,16,0x0000DD,COLORFONDO,"some apps!");*/
|
||||||
|
v_putcad(26,8,0x0000DD,COLORFONDO,"COMING SOON");
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
if(running) {
|
||||||
|
v_putcad(26,8,0xffffff,COLORFONDO,"Press B to");
|
||||||
|
v_putcad(26,9,0xffffff,COLORFONDO,"kill the");
|
||||||
|
v_putcad(26,10,0xffffff,COLORFONDO,"running");
|
||||||
|
v_putcad(26,11,0xffffff,COLORFONDO,"daemon");
|
||||||
|
v_putcad(26,12,0xffffff,COLORFONDO,"process.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v_putcad(26,8,0xffffff,COLORFONDO,"Press B to");
|
||||||
|
v_putcad(26,9,0xffffff,COLORFONDO,"start the ");
|
||||||
|
v_putcad(26,10,0xffffff,COLORFONDO,"daemon in the");
|
||||||
|
v_putcad(26,11,0xffffff,COLORFONDO, "background.");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void daemonmenu() {
|
||||||
|
|
||||||
|
int menupoint = 0;
|
||||||
|
running = !access("/tmp/cpu_daemon.pid",R_OK);
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long gp2x_nKeys;
|
||||||
|
while(1) {
|
||||||
|
|
||||||
|
if(daemonsettings[0] < 33)
|
||||||
|
daemonsettings[0] = 33;
|
||||||
|
if(daemonsettings[1] > 340)
|
||||||
|
daemonsettings[1] = 340;
|
||||||
|
if(daemonsettings[1] < daemonsettings[0])
|
||||||
|
daemonsettings[1] = daemonsettings[0];
|
||||||
|
if(daemonsettings[0] > daemonsettings[1])
|
||||||
|
daemonsettings[0] = daemonsettings[1];
|
||||||
|
if(daemonsettings[2] < 1)
|
||||||
|
daemonsettings[2] = 1;
|
||||||
|
if(daemonsettings[3] < 1)
|
||||||
|
daemonsettings[3] = 1;
|
||||||
|
//if(daemonsettings[7] == 10 || daemonsettings[7] == -10)
|
||||||
|
// daemonsettings[7] = 1;
|
||||||
|
//if(daemonsettings[7] == 11 || daemonsettings[7] == -9)
|
||||||
|
daemonsettings[7] = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cleardisp();
|
||||||
|
v_putcad(13,2,WHITE,COLORFONDO,"Daemon Setup");
|
||||||
|
|
||||||
|
v_putcad(2,5,0xffff00,COLORFONDO,"CPU Clockspeed:");
|
||||||
|
|
||||||
|
sprintf(cad,"From: %huMhz",daemonsettings[0]);
|
||||||
|
|
||||||
|
v_putcad(2,7,0xffff,COLORFONDO,cad);
|
||||||
|
if(menupoint == 0)
|
||||||
|
v_putcad(2,7,0xffff,TEXTBACK,cad);
|
||||||
|
|
||||||
|
sprintf(cad,"To: %huMhz",daemonsettings[1]);
|
||||||
|
|
||||||
|
v_putcad(2,8,0xffff,COLORFONDO,cad);
|
||||||
|
if(menupoint == 1)
|
||||||
|
v_putcad(2,8,0xffff,TEXTBACK,cad);
|
||||||
|
|
||||||
|
sprintf(cad,"Step: %huMhz",daemonsettings[2]);
|
||||||
|
|
||||||
|
v_putcad(2,9,0xffff,COLORFONDO,cad);
|
||||||
|
if(menupoint == 2)
|
||||||
|
v_putcad(2,9,0xffff,TEXTBACK,cad);
|
||||||
|
|
||||||
|
|
||||||
|
v_putcad(2,11,0xffff00,COLORFONDO,"Buttons:");
|
||||||
|
|
||||||
|
sprintf(cad,"Delay: %0.1fsec",daemonsettings[3]/10.0f);
|
||||||
|
|
||||||
|
v_putcad(2,13,0xffff,COLORFONDO,cad);
|
||||||
|
if(menupoint == 3)
|
||||||
|
v_putcad(2,13,0xffff,TEXTBACK,cad);
|
||||||
|
|
||||||
|
sprintf(cad,"Hotkey: ");
|
||||||
|
|
||||||
|
formatkey(cad,daemonsettings[4]);
|
||||||
|
|
||||||
|
v_putcad(2,15,0xffff,COLORFONDO,cad);
|
||||||
|
if(menupoint == 4)
|
||||||
|
v_putcad(2,15,0xffff,TEXTBACK,cad);
|
||||||
|
|
||||||
|
|
||||||
|
sprintf(cad,"IncrKey: ");
|
||||||
|
|
||||||
|
formatkey(cad,daemonsettings[5]);
|
||||||
|
|
||||||
|
v_putcad(2,16,0xffff,COLORFONDO,cad);
|
||||||
|
if(menupoint == 5)
|
||||||
|
v_putcad(2,16,0xffff,TEXTBACK,cad);
|
||||||
|
|
||||||
|
sprintf(cad,"DecrKey: ");
|
||||||
|
|
||||||
|
formatkey(cad,daemonsettings[6]);
|
||||||
|
|
||||||
|
v_putcad(2,17,0xffff,COLORFONDO,cad);
|
||||||
|
if(menupoint == 6)
|
||||||
|
v_putcad(2,17,0xffff,TEXTBACK,cad);
|
||||||
|
|
||||||
|
if(menupoint >= 4 && menupoint <=6)
|
||||||
|
v_putcad(2,26,WHITE,COLORFONDO,"---------- Stick:UP/DOWN");
|
||||||
|
|
||||||
|
v_putcad(2,19,0xffff00,COLORFONDO,"Misc:");
|
||||||
|
|
||||||
|
|
||||||
|
v_putcad(2,21,0xffff,COLORFONDO,(daemonsettings[7] ? "On Screen Display: On" : "On Screen Display: Off"));
|
||||||
|
if(menupoint == 7)
|
||||||
|
v_putcad(2,21,0xffff,TEXTBACK,(daemonsettings[7] ? "On Screen Display: On" : "On Screen Display: Off"));
|
||||||
|
|
||||||
|
|
||||||
|
v_putcad(2,23,0xffff,COLORFONDO,(running ? "Kill Running Daemon" : "Start Daemon"));
|
||||||
|
if(menupoint == 8)
|
||||||
|
v_putcad(2,23,0xffff,TEXTBACK,(running ? "Kill Running Daemon" : "Start Daemon"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
daemon_itemhelp(menupoint);
|
||||||
|
|
||||||
|
gp2x_video_flip();
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
gp2x_nKeys=gp2x_joystick_read();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if((gp2x_nKeys & GP2X_DOWN))
|
||||||
|
{
|
||||||
|
menupoint++;
|
||||||
|
if(menupoint>8) menupoint=0;
|
||||||
|
usleep(200000);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((gp2x_nKeys & GP2X_UP))
|
||||||
|
{
|
||||||
|
menupoint--;
|
||||||
|
if(menupoint<0) menupoint=8;
|
||||||
|
usleep(200000);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((menupoint >= 4) && (menupoint <= 6) && (gp2x_nKeys & VALID_KEYS))
|
||||||
|
{
|
||||||
|
daemonsettings[menupoint] ^= (gp2x_nKeys & VALID_KEYS);
|
||||||
|
usleep(200000);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(menupoint < 8 &&(gp2x_nKeys & GP2X_R))
|
||||||
|
{
|
||||||
|
daemonsettings[menupoint] += 10;
|
||||||
|
usleep(200000);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(menupoint < 4 && (gp2x_nKeys & GP2X_VOL_UP))
|
||||||
|
{
|
||||||
|
daemonsettings[menupoint] -= 1;
|
||||||
|
usleep(200000);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(menupoint < 4 && (gp2x_nKeys & GP2X_VOL_DOWN))
|
||||||
|
{
|
||||||
|
daemonsettings[menupoint] += 1;
|
||||||
|
usleep(200000);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(menupoint < 8 && (gp2x_nKeys & GP2X_L))
|
||||||
|
{
|
||||||
|
daemonsettings[menupoint] -= 10;
|
||||||
|
usleep(200000);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(menupoint == 8 && (gp2x_nKeys & GP2X_B))
|
||||||
|
{
|
||||||
|
if(running)
|
||||||
|
kill_running_daemon();
|
||||||
|
else {
|
||||||
|
int cpu_div = get_920_Div();
|
||||||
|
int sysfreq=get_freq_920_CLK();
|
||||||
|
sysfreq*=cpu_div+1;
|
||||||
|
int cpufreq=sysfreq/1000000;
|
||||||
|
|
||||||
|
start_daemon_by_settings();
|
||||||
|
}
|
||||||
|
usleep(200000);
|
||||||
|
running = !access("/tmp/cpu_daemon.pid",R_OK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if((gp2x_nKeys & GP2X_START))
|
||||||
|
{
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
gp2x_nKeys=gp2x_joystick_read();
|
||||||
|
if(!(gp2x_nKeys & GP2X_START)) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(running) { // update values!
|
||||||
|
start_daemon_by_settings();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void start_daemon_by_settings() {
|
||||||
|
int cpu_div = get_920_Div();
|
||||||
|
int sysfreq=get_freq_920_CLK();
|
||||||
|
sysfreq*=cpu_div+1;
|
||||||
|
int cpufreq=sysfreq/1000000;
|
||||||
|
|
||||||
|
start_daemon(daemonsettings[0], daemonsettings[1], cpufreq, daemonsettings[2], daemonsettings[4], daemonsettings[5],
|
||||||
|
daemonsettings[6], daemonsettings[7], 0, daemonsettings[3] * 100000);
|
||||||
|
}
|
||||||
18
gp2x/daemon.h
Normal file
18
gp2x/daemon.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
int start_daemon(
|
||||||
|
unsigned int minimal_cpu_speed, unsigned int maximal_cpu_speed, unsigned int start_cpu_speed, int cpu_speed_step,
|
||||||
|
unsigned long hotkey, unsigned long incrementkey, unsigned long decrmentkey,
|
||||||
|
int speed_display, int foreground,
|
||||||
|
unsigned long delay);
|
||||||
|
|
||||||
|
int kill_running_daemon();
|
||||||
|
|
||||||
|
void nano_setup();
|
||||||
|
void cmd_daemon(int argc, char *argv[]);
|
||||||
|
|
||||||
|
unsigned long parse_key_sequence(char *key_sequence);
|
||||||
|
|
||||||
|
void daemonmenu();
|
||||||
|
|
||||||
|
void formatkey(char * base, unsigned long keyseq);
|
||||||
|
|
||||||
|
void start_daemon_by_settings();
|
||||||
139
gp2x/display.c
Normal file
139
gp2x/display.c
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/* display.c for GP2X (CPU/LCD/RAM-Tuner Version 2.0)
|
||||||
|
Copyright (C) 2006 god_at_hell
|
||||||
|
original CPU-Overclocker (c) by Hermes/PS2Reality
|
||||||
|
parts (c) Rlyehs Work
|
||||||
|
|
||||||
|
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "gp2xminilib.h"
|
||||||
|
#include "cpuctrl.h"
|
||||||
|
#define WIDTH 320
|
||||||
|
#define HEIGHT 240
|
||||||
|
|
||||||
|
//unsigned TEXTBACK=0x900000; // text-background-color
|
||||||
|
|
||||||
|
extern unsigned char msx[]; // define la fuente externa usada para dibujar letras y numeros
|
||||||
|
|
||||||
|
void ClearScreen(unsigned val) // se usa para 'borrar' la pantalla virtual con un color
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
unsigned char *c;
|
||||||
|
unsigned short col;
|
||||||
|
c=&val;
|
||||||
|
col=gp2x_video_color15(c[0],c[1],c[2],0);
|
||||||
|
for(n=0;n<320*240;n++)
|
||||||
|
{
|
||||||
|
gp2x_screen15[n]=col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawBox(unsigned val)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
unsigned char *c;
|
||||||
|
unsigned short col;
|
||||||
|
c=&val;
|
||||||
|
col=gp2x_video_color15(c[0],c[1],c[2],0);
|
||||||
|
|
||||||
|
for(n=320*27+2;n<320*28-1;n++)
|
||||||
|
{
|
||||||
|
gp2x_screen15[n]=col;
|
||||||
|
gp2x_screen15[n+320*209]=col;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(n=320*29+4;n<320*30-3;n++)
|
||||||
|
{
|
||||||
|
gp2x_screen15[n]=col;
|
||||||
|
gp2x_screen15[n+320*169]=col;
|
||||||
|
gp2x_screen15[n+320*205]=col;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(n=320*28;n<320*237;n=n+320)
|
||||||
|
{
|
||||||
|
gp2x_screen15[n+2]=col;
|
||||||
|
gp2x_screen15[n-2]=col;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(n=320*30;n<320*235;n=n+320)
|
||||||
|
{
|
||||||
|
gp2x_screen15[n+4]=col;
|
||||||
|
gp2x_screen15[n-4]=col;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(n=320*30;n<320*199;n=n+320)
|
||||||
|
{
|
||||||
|
gp2x_screen15[n-120]=col;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(n=320*55-120;n<320*55-4;n++)
|
||||||
|
{
|
||||||
|
gp2x_screen15[n]=col;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void v_putchar( unsigned x, unsigned y, unsigned color, unsigned textback, unsigned char ch) // rutina usada para dibujar caracteres (coordenadas de 8x8)
|
||||||
|
{
|
||||||
|
int i,j,v;
|
||||||
|
unsigned char *font;
|
||||||
|
unsigned char *c;
|
||||||
|
unsigned short col,col2;
|
||||||
|
if(x>=WIDTH || y>=HEIGHT) return;
|
||||||
|
c=&color;
|
||||||
|
col=gp2x_video_color15(c[0],c[1],c[2],0);
|
||||||
|
c=&textback;
|
||||||
|
col2=gp2x_video_color15(c[0],c[1],c[2],0);
|
||||||
|
v=(y*320*8);
|
||||||
|
font = &msx[ (int)ch * 8];
|
||||||
|
for (i=0; i < 8; i++, font++)
|
||||||
|
{
|
||||||
|
for (j=0; j < 8; j++)
|
||||||
|
{
|
||||||
|
if ((*font & (128 >> j)))
|
||||||
|
{
|
||||||
|
gp2x_screen15[v+(((x<<3)+j))]=col;
|
||||||
|
}
|
||||||
|
else gp2x_screen15[v+(((x<<3)+j))]=col2;
|
||||||
|
}
|
||||||
|
v+=WIDTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// display array of chars
|
||||||
|
|
||||||
|
void v_putcad(int x,int y,unsigned color,unsigned textback,char *cad) // dibuja una cadena de texto
|
||||||
|
{
|
||||||
|
while(cad[0]!=0) {v_putchar(x,y,color,textback,cad[0]);cad++;x++;}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void gp2x_sound_frame(void *unused, unsigned char *stream, int samples)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
short *pu;
|
||||||
|
pu=stream;
|
||||||
|
for(n=0;n<(samples);n++)
|
||||||
|
{
|
||||||
|
*pu++=0;*pu++=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
5
gp2x/display.h
Normal file
5
gp2x/display.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
void ClearScreen(unsigned val);
|
||||||
|
void DrawBox(unsigned val);
|
||||||
|
void v_putchar( unsigned x, unsigned y, unsigned color, unsigned textback, unsigned char ch);
|
||||||
|
void v_putcad(int x,int y,unsigned color,unsigned textback,char *cad);
|
||||||
|
void gp2x_sound_frame(void *unused, unsigned char *stream, int samples);
|
||||||
143
gp2x/font.c
Normal file
143
gp2x/font.c
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
_____ ___ ____
|
||||||
|
____| | ____| PSX2 OpenSource Project
|
||||||
|
| ___| |____ (C)2001, Gustavo Scotti (gustavo@scotti.com)
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
font.c
|
||||||
|
EE UGLY DEBUG ON SCREEN - FONT BASE
|
||||||
|
This is mostly based on Duke's work
|
||||||
|
*/
|
||||||
|
//#include <tamtypes.h>
|
||||||
|
|
||||||
|
unsigned char msx[]=
|
||||||
|
"\x00\x00\x00\x00\x00\x00\x00\x00\x3c\x42\xa5\x81\xa5\x99\x42\x3c"
|
||||||
|
"\x3c\x7e\xdb\xff\xff\xdb\x66\x3c\x6c\xfe\xfe\xfe\x7c\x38\x10\x00"
|
||||||
|
"\x10\x38\x7c\xfe\x7c\x38\x10\x00\x10\x38\x54\xfe\x54\x10\x38\x00"
|
||||||
|
"\x10\x38\x7c\xfe\xfe\x10\x38\x00\x00\x00\x00\x30\x30\x00\x00\x00"
|
||||||
|
"\xff\xff\xff\xe7\xe7\xff\xff\xff\x38\x44\x82\x82\x82\x44\x38\x00"
|
||||||
|
"\xc7\xbb\x7d\x7d\x7d\xbb\xc7\xff\x0f\x03\x05\x79\x88\x88\x88\x70"
|
||||||
|
"\x38\x44\x44\x44\x38\x10\x7c\x10\x30\x28\x24\x24\x28\x20\xe0\xc0"
|
||||||
|
"\x3c\x24\x3c\x24\x24\xe4\xdc\x18\x10\x54\x38\xee\x38\x54\x10\x00"
|
||||||
|
"\x10\x10\x10\x7c\x10\x10\x10\x10\x10\x10\x10\xff\x00\x00\x00\x00"
|
||||||
|
"\x00\x00\x00\xff\x10\x10\x10\x10\x10\x10\x10\xf0\x10\x10\x10\x10"
|
||||||
|
"\x10\x10\x10\x1f\x10\x10\x10\x10\x10\x10\x10\xff\x10\x10\x10\x10"
|
||||||
|
"\x10\x10\x10\x10\x10\x10\x10\x10\x00\x00\x00\xff\x00\x00\x00\x00"
|
||||||
|
"\x00\x00\x00\x1f\x10\x10\x10\x10\x00\x00\x00\xf0\x10\x10\x10\x10"
|
||||||
|
"\x10\x10\x10\x1f\x00\x00\x00\x00\x10\x10\x10\xf0\x00\x00\x00\x00"
|
||||||
|
"\x81\x42\x24\x18\x18\x24\x42\x81\x01\x02\x04\x08\x10\x20\x40\x80"
|
||||||
|
"\x80\x40\x20\x10\x08\x04\x02\x01\x00\x10\x10\xff\x10\x10\x00\x00"
|
||||||
|
"\x00\x00\x00\x00\x00\x00\x00\x00\x20\x20\x20\x20\x00\x00\x20\x00"
|
||||||
|
"\x50\x50\x50\x00\x00\x00\x00\x00\x50\x50\xf8\x50\xf8\x50\x50\x00"
|
||||||
|
"\x20\x78\xa0\x70\x28\xf0\x20\x00\xc0\xc8\x10\x20\x40\x98\x18\x00"
|
||||||
|
"\x40\xa0\x40\xa8\x90\x98\x60\x00\x10\x20\x40\x00\x00\x00\x00\x00"
|
||||||
|
"\x10\x20\x40\x40\x40\x20\x10\x00\x40\x20\x10\x10\x10\x20\x40\x00"
|
||||||
|
"\x20\xa8\x70\x20\x70\xa8\x20\x00\x00\x20\x20\xf8\x20\x20\x00\x00"
|
||||||
|
"\x00\x00\x00\x00\x00\x20\x20\x40\x00\x00\x00\x78\x00\x00\x00\x00"
|
||||||
|
"\x00\x00\x00\x00\x00\x60\x60\x00\x00\x00\x08\x10\x20\x40\x80\x00"
|
||||||
|
"\x70\x88\x98\xa8\xc8\x88\x70\x00\x20\x60\xa0\x20\x20\x20\xf8\x00"
|
||||||
|
"\x70\x88\x08\x10\x60\x80\xf8\x00\x70\x88\x08\x30\x08\x88\x70\x00"
|
||||||
|
"\x10\x30\x50\x90\xf8\x10\x10\x00\xf8\x80\xe0\x10\x08\x10\xe0\x00"
|
||||||
|
"\x30\x40\x80\xf0\x88\x88\x70\x00\xf8\x88\x10\x20\x20\x20\x20\x00"
|
||||||
|
"\x70\x88\x88\x70\x88\x88\x70\x00\x70\x88\x88\x78\x08\x10\x60\x00"
|
||||||
|
"\x00\x00\x20\x00\x00\x20\x00\x00\x00\x00\x20\x00\x00\x20\x20\x40"
|
||||||
|
"\x18\x30\x60\xc0\x60\x30\x18\x00\x00\x00\xf8\x00\xf8\x00\x00\x00"
|
||||||
|
"\xc0\x60\x30\x18\x30\x60\xc0\x00\x70\x88\x08\x10\x20\x00\x20\x00"
|
||||||
|
"\x70\x88\x08\x68\xa8\xa8\x70\x00\x20\x50\x88\x88\xf8\x88\x88\x00"
|
||||||
|
"\xf0\x48\x48\x70\x48\x48\xf0\x00\x30\x48\x80\x80\x80\x48\x30\x00"
|
||||||
|
"\xe0\x50\x48\x48\x48\x50\xe0\x00\xf8\x80\x80\xf0\x80\x80\xf8\x00"
|
||||||
|
"\xf8\x80\x80\xf0\x80\x80\x80\x00\x70\x88\x80\xb8\x88\x88\x70\x00"
|
||||||
|
"\x88\x88\x88\xf8\x88\x88\x88\x00\x70\x20\x20\x20\x20\x20\x70\x00"
|
||||||
|
"\x38\x10\x10\x10\x90\x90\x60\x00\x88\x90\xa0\xc0\xa0\x90\x88\x00"
|
||||||
|
"\x80\x80\x80\x80\x80\x80\xf8\x00\x88\xd8\xa8\xa8\x88\x88\x88\x00"
|
||||||
|
"\x88\xc8\xc8\xa8\x98\x98\x88\x00\x70\x88\x88\x88\x88\x88\x70\x00"
|
||||||
|
"\xf0\x88\x88\xf0\x80\x80\x80\x00\x70\x88\x88\x88\xa8\x90\x68\x00"
|
||||||
|
"\xf0\x88\x88\xf0\xa0\x90\x88\x00\x70\x88\x80\x70\x08\x88\x70\x00"
|
||||||
|
"\xf8\x20\x20\x20\x20\x20\x20\x00\x88\x88\x88\x88\x88\x88\x70\x00"
|
||||||
|
"\x88\x88\x88\x88\x50\x50\x20\x00\x88\x88\x88\xa8\xa8\xd8\x88\x00"
|
||||||
|
"\x88\x88\x50\x20\x50\x88\x88\x00\x88\x88\x88\x70\x20\x20\x20\x00"
|
||||||
|
"\xf8\x08\x10\x20\x40\x80\xf8\x00\x70\x40\x40\x40\x40\x40\x70\x00"
|
||||||
|
"\x00\x00\x80\x40\x20\x10\x08\x00\x70\x10\x10\x10\x10\x10\x70\x00"
|
||||||
|
"\x20\x50\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x00"
|
||||||
|
"\x40\x20\x10\x00\x00\x00\x00\x00\x00\x00\x70\x08\x78\x88\x78\x00"
|
||||||
|
"\x80\x80\xb0\xc8\x88\xc8\xb0\x00\x00\x00\x70\x88\x80\x88\x70\x00"
|
||||||
|
"\x08\x08\x68\x98\x88\x98\x68\x00\x00\x00\x70\x88\xf8\x80\x70\x00"
|
||||||
|
"\x10\x28\x20\xf8\x20\x20\x20\x00\x00\x00\x68\x98\x98\x68\x08\x70"
|
||||||
|
"\x80\x80\xf0\x88\x88\x88\x88\x00\x20\x00\x60\x20\x20\x20\x70\x00"
|
||||||
|
"\x10\x00\x30\x10\x10\x10\x90\x60\x40\x40\x48\x50\x60\x50\x48\x00"
|
||||||
|
"\x60\x20\x20\x20\x20\x20\x70\x00\x00\x00\xd0\xa8\xa8\xa8\xa8\x00"
|
||||||
|
"\x00\x00\xb0\xc8\x88\x88\x88\x00\x00\x00\x70\x88\x88\x88\x70\x00"
|
||||||
|
"\x00\x00\xb0\xc8\xc8\xb0\x80\x80\x00\x00\x68\x98\x98\x68\x08\x08"
|
||||||
|
"\x00\x00\xb0\xc8\x80\x80\x80\x00\x00\x00\x78\x80\xf0\x08\xf0\x00"
|
||||||
|
"\x40\x40\xf0\x40\x40\x48\x30\x00\x00\x00\x90\x90\x90\x90\x68\x00"
|
||||||
|
"\x00\x00\x88\x88\x88\x50\x20\x00\x00\x00\x88\xa8\xa8\xa8\x50\x00"
|
||||||
|
"\x00\x00\x88\x50\x20\x50\x88\x00\x00\x00\x88\x88\x98\x68\x08\x70"
|
||||||
|
"\x00\x00\xf8\x10\x20\x40\xf8\x00\x18\x20\x20\x40\x20\x20\x18\x00"
|
||||||
|
"\x20\x20\x20\x00\x20\x20\x20\x00\xc0\x20\x20\x10\x20\x20\xc0\x00"
|
||||||
|
"\x40\xa8\x10\x00\x00\x00\x00\x00\x00\x00\x20\x50\xf8\x00\x00\x00"
|
||||||
|
"\x70\x88\x80\x80\x88\x70\x20\x60\x90\x00\x00\x90\x90\x90\x68\x00"
|
||||||
|
"\x10\x20\x70\x88\xf8\x80\x70\x00\x20\x50\x70\x08\x78\x88\x78\x00"
|
||||||
|
"\x48\x00\x70\x08\x78\x88\x78\x00\x20\x10\x70\x08\x78\x88\x78\x00"
|
||||||
|
"\x20\x00\x70\x08\x78\x88\x78\x00\x00\x70\x80\x80\x80\x70\x10\x60"
|
||||||
|
"\x20\x50\x70\x88\xf8\x80\x70\x00\x50\x00\x70\x88\xf8\x80\x70\x00"
|
||||||
|
"\x20\x10\x70\x88\xf8\x80\x70\x00\x50\x00\x00\x60\x20\x20\x70\x00"
|
||||||
|
"\x20\x50\x00\x60\x20\x20\x70\x00\x40\x20\x00\x60\x20\x20\x70\x00"
|
||||||
|
"\x50\x00\x20\x50\x88\xf8\x88\x00\x20\x00\x20\x50\x88\xf8\x88\x00"
|
||||||
|
"\x10\x20\xf8\x80\xf0\x80\xf8\x00\x00\x00\x6c\x12\x7e\x90\x6e\x00"
|
||||||
|
"\x3e\x50\x90\x9c\xf0\x90\x9e\x00\x60\x90\x00\x60\x90\x90\x60\x00"
|
||||||
|
"\x90\x00\x00\x60\x90\x90\x60\x00\x40\x20\x00\x60\x90\x90\x60\x00"
|
||||||
|
"\x40\xa0\x00\xa0\xa0\xa0\x50\x00\x40\x20\x00\xa0\xa0\xa0\x50\x00"
|
||||||
|
"\x90\x00\x90\x90\xb0\x50\x10\xe0\x50\x00\x70\x88\x88\x88\x70\x00"
|
||||||
|
"\x50\x00\x88\x88\x88\x88\x70\x00\x20\x20\x78\x80\x80\x78\x20\x20"
|
||||||
|
"\x18\x24\x20\xf8\x20\xe2\x5c\x00\x88\x50\x20\xf8\x20\xf8\x20\x00"
|
||||||
|
"\xc0\xa0\xa0\xc8\x9c\x88\x88\x8c\x18\x20\x20\xf8\x20\x20\x20\x40"
|
||||||
|
"\x10\x20\x70\x08\x78\x88\x78\x00\x10\x20\x00\x60\x20\x20\x70\x00"
|
||||||
|
"\x20\x40\x00\x60\x90\x90\x60\x00\x20\x40\x00\x90\x90\x90\x68\x00"
|
||||||
|
"\x50\xa0\x00\xa0\xd0\x90\x90\x00\x28\x50\x00\xc8\xa8\x98\x88\x00"
|
||||||
|
"\x00\x70\x08\x78\x88\x78\x00\xf8\x00\x60\x90\x90\x90\x60\x00\xf0"
|
||||||
|
"\x20\x00\x20\x40\x80\x88\x70\x00\x00\x00\x00\xf8\x80\x80\x00\x00"
|
||||||
|
"\x00\x00\x00\xf8\x08\x08\x00\x00\x84\x88\x90\xa8\x54\x84\x08\x1c"
|
||||||
|
"\x84\x88\x90\xa8\x58\xa8\x3c\x08\x20\x00\x00\x20\x20\x20\x20\x00"
|
||||||
|
"\x00\x00\x24\x48\x90\x48\x24\x00\x00\x00\x90\x48\x24\x48\x90\x00"
|
||||||
|
"\x28\x50\x20\x50\x88\xf8\x88\x00\x28\x50\x70\x08\x78\x88\x78\x00"
|
||||||
|
"\x28\x50\x00\x70\x20\x20\x70\x00\x28\x50\x00\x20\x20\x20\x70\x00"
|
||||||
|
"\x28\x50\x00\x70\x88\x88\x70\x00\x50\xa0\x00\x60\x90\x90\x60\x00"
|
||||||
|
"\x28\x50\x00\x88\x88\x88\x70\x00\x50\xa0\x00\xa0\xa0\xa0\x50\x00"
|
||||||
|
"\xfc\x48\x48\x48\xe8\x08\x50\x20\x00\x50\x00\x50\x50\x50\x10\x20"
|
||||||
|
"\xc0\x44\xc8\x54\xec\x54\x9e\x04\x10\xa8\x40\x00\x00\x00\x00\x00"
|
||||||
|
"\x00\x20\x50\x88\x50\x20\x00\x00\x88\x10\x20\x40\x80\x28\x00\x00"
|
||||||
|
"\x7c\xa8\xa8\x68\x28\x28\x28\x00\x38\x40\x30\x48\x48\x30\x08\x70"
|
||||||
|
"\x00\x00\x00\x00\x00\x00\xff\xff\xf0\xf0\xf0\xf0\x0f\x0f\x0f\x0f"
|
||||||
|
"\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00"
|
||||||
|
"\x00\x00\x00\x3c\x3c\x00\x00\x00\xff\xff\xff\xff\xff\xff\x00\x00"
|
||||||
|
"\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x0f\x0f\x0f\x0f\xf0\xf0\xf0\xf0"
|
||||||
|
"\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\x03\x03\x03\x03\x03\x03\x03\x03"
|
||||||
|
"\x3f\x3f\x3f\x3f\x3f\x3f\x3f\x3f\x11\x22\x44\x88\x11\x22\x44\x88"
|
||||||
|
"\x88\x44\x22\x11\x88\x44\x22\x11\xfe\x7c\x38\x10\x00\x00\x00\x00"
|
||||||
|
"\x00\x00\x00\x00\x10\x38\x7c\xfe\x80\xc0\xe0\xf0\xe0\xc0\x80\x00"
|
||||||
|
"\x01\x03\x07\x0f\x07\x03\x01\x00\xff\x7e\x3c\x18\x18\x3c\x7e\xff"
|
||||||
|
"\x81\xc3\xe7\xff\xff\xe7\xc3\x81\xf0\xf0\xf0\xf0\x00\x00\x00\x00"
|
||||||
|
"\x00\x00\x00\x00\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x00\x00\x00\x00"
|
||||||
|
"\x00\x00\x00\x00\xf0\xf0\xf0\xf0\x33\x33\xcc\xcc\x33\x33\xcc\xcc"
|
||||||
|
"\x00\x20\x20\x50\x50\x88\xf8\x00\x20\x20\x70\x20\x70\x20\x20\x00"
|
||||||
|
"\x00\x00\x00\x50\x88\xa8\x50\x00\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||||
|
"\x00\x00\x00\x00\xff\xff\xff\xff\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0"
|
||||||
|
"\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\xff\xff\xff\xff\x00\x00\x00\x00"
|
||||||
|
"\x00\x00\x68\x90\x90\x90\x68\x00\x30\x48\x48\x70\x48\x48\x70\xc0"
|
||||||
|
"\xf8\x88\x80\x80\x80\x80\x80\x00\xf8\x50\x50\x50\x50\x50\x98\x00"
|
||||||
|
"\xf8\x88\x40\x20\x40\x88\xf8\x00\x00\x00\x78\x90\x90\x90\x60\x00"
|
||||||
|
"\x00\x50\x50\x50\x50\x68\x80\x80\x00\x50\xa0\x20\x20\x20\x20\x00"
|
||||||
|
"\xf8\x20\x70\xa8\xa8\x70\x20\xf8\x20\x50\x88\xf8\x88\x50\x20\x00"
|
||||||
|
"\x70\x88\x88\x88\x50\x50\xd8\x00\x30\x40\x40\x20\x50\x50\x50\x20"
|
||||||
|
"\x00\x00\x00\x50\xa8\xa8\x50\x00\x08\x70\xa8\xa8\xa8\x70\x80\x00"
|
||||||
|
"\x38\x40\x80\xf8\x80\x40\x38\x00\x70\x88\x88\x88\x88\x88\x88\x00"
|
||||||
|
"\x00\xf8\x00\xf8\x00\xf8\x00\x00\x20\x20\xf8\x20\x20\x00\xf8\x00"
|
||||||
|
"\xc0\x30\x08\x30\xc0\x00\xf8\x00\x18\x60\x80\x60\x18\x00\xf8\x00"
|
||||||
|
"\x10\x28\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\xa0\x40"
|
||||||
|
"\x00\x20\x00\xf8\x00\x20\x00\x00\x00\x50\xa0\x00\x50\xa0\x00\x00"
|
||||||
|
"\x00\x18\x24\x24\x18\x00\x00\x00\x00\x30\x78\x78\x30\x00\x00\x00"
|
||||||
|
"\x00\x00\x00\x00\x30\x00\x00\x00\x3e\x20\x20\x20\xa0\x60\x20\x00"
|
||||||
|
"\xa0\x50\x50\x50\x00\x00\x00\x00\x40\xa0\x20\x40\xe0\x00\x00\x00"
|
||||||
|
"\x00\x38\x38\x38\x38\x38\x38\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
93
gp2x/gp2x.c
Normal file
93
gp2x/gp2x.c
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/* Parts used from cpuctrl */
|
||||||
|
/* cpuctrl for GP2X
|
||||||
|
Copyright (C) 2005 Hermes/PS2Reality
|
||||||
|
|
||||||
|
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/soundcard.h>
|
||||||
|
#include "../common.h"
|
||||||
|
#include "gp2x.h"
|
||||||
|
|
||||||
|
extern int main_cpuspeed(int argc, char *argv[]);
|
||||||
|
extern SDL_Surface* screen;
|
||||||
|
|
||||||
|
u32 gp2x_audio_volume = 74;
|
||||||
|
u32 gpsp_gp2x_dev_audio = 0;
|
||||||
|
u32 gpsp_gp2x_dev = 0;
|
||||||
|
|
||||||
|
volatile u16 *gpsp_gp2x_memregs;
|
||||||
|
volatile u32 *gpsp_gp2x_memregl;
|
||||||
|
|
||||||
|
static volatile u16 *MEM_REG;
|
||||||
|
|
||||||
|
s32 gp2x_load_mmuhack()
|
||||||
|
{
|
||||||
|
s32 mmufd = open("/dev/mmuhack", O_RDWR);
|
||||||
|
|
||||||
|
if(mmufd < 0)
|
||||||
|
{
|
||||||
|
system("/sbin/insmod mmuhack.o");
|
||||||
|
mmufd = open("/dev/mmuhack", O_RDWR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mmufd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
close(mmufd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gp2x_overclock()
|
||||||
|
{
|
||||||
|
gpsp_gp2x_dev = open("/dev/mem", O_RDWR);
|
||||||
|
gpsp_gp2x_dev_audio = open("/dev/mixer", O_RDWR);
|
||||||
|
gpsp_gp2x_memregl =
|
||||||
|
(unsigned long *)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED,
|
||||||
|
gpsp_gp2x_dev, 0xc0000000);
|
||||||
|
gpsp_gp2x_memregs = (unsigned short *)gpsp_gp2x_memregl;
|
||||||
|
|
||||||
|
clear_screen(0);
|
||||||
|
main_cpuspeed(0, NULL);
|
||||||
|
gp2x_sound_volume(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gp2x_quit()
|
||||||
|
{
|
||||||
|
munmap((void *)gpsp_gp2x_memregl, 0x10000);
|
||||||
|
close(gpsp_gp2x_dev_audio);
|
||||||
|
close(gpsp_gp2x_dev);
|
||||||
|
chdir("/usr/gp2x");
|
||||||
|
execl("gp2xmenu", "gp2xmenu", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gp2x_sound_volume(u32 volume_up)
|
||||||
|
{
|
||||||
|
u32 volume;
|
||||||
|
if((volume_up == 0) && (gp2x_audio_volume > 0))
|
||||||
|
gp2x_audio_volume--;
|
||||||
|
|
||||||
|
if((volume_up != 0) && (gp2x_audio_volume < 100))
|
||||||
|
gp2x_audio_volume++;
|
||||||
|
|
||||||
|
volume = (gp2x_audio_volume * 0x50) / 100;
|
||||||
|
volume = (gp2x_audio_volume << 8) | gp2x_audio_volume;
|
||||||
|
ioctl(gpsp_gp2x_dev_audio, SOUND_MIXER_WRITE_PCM, &volume);
|
||||||
|
}
|
||||||
|
|
||||||
50
gp2x/gp2x.h
Normal file
50
gp2x/gp2x.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef GP2X_H
|
||||||
|
#define GP2X_H
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
GP2X_UP = 1 << 0,
|
||||||
|
GP2X_LEFT = 1 << 2,
|
||||||
|
GP2X_DOWN = 1 << 4,
|
||||||
|
GP2X_RIGHT = 1 << 6,
|
||||||
|
GP2X_START = 1 << 8,
|
||||||
|
GP2X_SELECT = 1 << 9,
|
||||||
|
GP2X_L = 1 << 10,
|
||||||
|
GP2X_R = 1 << 11,
|
||||||
|
GP2X_A = 1 << 12,
|
||||||
|
GP2X_B = 1 << 13,
|
||||||
|
GP2X_X = 1 << 14,
|
||||||
|
GP2X_Y = 1 << 15,
|
||||||
|
GP2X_VOL_DOWN = 1 << 22,
|
||||||
|
GP2X_VOL_UP = 1 << 23,
|
||||||
|
GP2X_PUSH = 1 << 27
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern u32 gpsp_gp2x_dev_audio;
|
||||||
|
extern u32 gpsp_gp2x_dev;
|
||||||
|
extern volatile u16 *gpsp_gp2x_memregs;
|
||||||
|
extern volatile u32 *gpsp_gp2x_memregl;
|
||||||
|
|
||||||
|
void gp2x_sound_volume(u32 volume_up);
|
||||||
|
void gp2x_quit();
|
||||||
|
|
||||||
|
// call this at first
|
||||||
|
void cpuctrl_init(void);
|
||||||
|
void save_system_regs(void);
|
||||||
|
void cpuctrl_deinit(void);
|
||||||
|
void set_display_clock_div(unsigned div);
|
||||||
|
|
||||||
|
void set_FCLK(u32 MHZ);
|
||||||
|
// 0 to 7 divider (freq = FCLK / (1 + div))
|
||||||
|
void set_920_Div(u16 div);
|
||||||
|
void set_DCLK_Div(u16 div);
|
||||||
|
|
||||||
|
void Disable_940(void);
|
||||||
|
void gp2x_video_wait_vsync(void);
|
||||||
|
unsigned short get_920_Div();
|
||||||
|
void set_940_Div(u16 div);
|
||||||
|
|
||||||
|
s32 gp2x_load_mmuhack();
|
||||||
|
|
||||||
|
#endif
|
||||||
242
gp2x/gp2xminilib.c
Normal file
242
gp2x/gp2xminilib.c
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
GP2X minimal library v0.5 by rlyeh, 2005.
|
||||||
|
|
||||||
|
+ GP2X video library with double buffering.
|
||||||
|
+ GP2X soundring buffer library with double buffering.
|
||||||
|
+ GP2X joystick library.
|
||||||
|
|
||||||
|
Thanks to Squidge, Robster, snaff and NK, for the help & previous work! :-)
|
||||||
|
|
||||||
|
|
||||||
|
What's new
|
||||||
|
==========
|
||||||
|
|
||||||
|
0.5: patched sound for real stereo (using NK's solution); better init code.
|
||||||
|
|
||||||
|
0.4: lots of cleanups; sound is threaded now, double buffered too; 8 bpp video support; better exiting code.
|
||||||
|
|
||||||
|
0.3: shorter library; improved joystick diagonal detection.
|
||||||
|
|
||||||
|
0.2: better code layout; public release.
|
||||||
|
|
||||||
|
0.1: beta release
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/soundcard.h>
|
||||||
|
#include <linux/fb.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include "gp2xminilib.h"
|
||||||
|
|
||||||
|
extern void gp2x_sound_frame(void *blah, void *bufferg, int samples);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long gp2x_dev[4]={0,0,0,0}, gp2x_physvram[4];
|
||||||
|
unsigned short *gp2x_memregs, *gp2x_screen15, *gp2x_logvram15[2], gp2x_sound_buffer[4+(44100*2)*4]; //*2=stereo, *4=max buffers
|
||||||
|
volatile unsigned short gp2x_palette[512][2];
|
||||||
|
unsigned char *gp2x_screen8, *gp2x_logvram8[2];
|
||||||
|
pthread_t gp2x_sound_thread=0, gp2x_sound_thread_exit=0;
|
||||||
|
|
||||||
|
void gp2x_video_flip(void)
|
||||||
|
{
|
||||||
|
unsigned long address=gp2x_physvram[gp2x_physvram[3]];
|
||||||
|
|
||||||
|
gp2x_screen15=gp2x_logvram15[gp2x_physvram[3]^=1];
|
||||||
|
gp2x_screen8 =gp2x_logvram8 [gp2x_physvram[3] ];
|
||||||
|
|
||||||
|
gp2x_memregs[0x290E>>1]=(unsigned short)(address & 0xffff);
|
||||||
|
gp2x_memregs[0x2910>>1]=(unsigned short)(address >> 16);
|
||||||
|
gp2x_memregs[0x2912>>1]=(unsigned short)(address & 0xffff);
|
||||||
|
gp2x_memregs[0x2914>>1]=(unsigned short)(address >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gp2x_video_setpalette(void)
|
||||||
|
{int i;
|
||||||
|
gp2x_memregs[0x2958>>1]=0;
|
||||||
|
for(i=0; i<512; i++) gp2x_memregs[0x295A>>1]=gp2x_palette[i][0], gp2x_memregs[0x295A>>1]=gp2x_palette[i][1];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long gp2x_joystick_read(void)
|
||||||
|
{
|
||||||
|
unsigned long value=(gp2x_memregs[0x1198>>1] & 0x00FF);
|
||||||
|
|
||||||
|
if(value==0xFD) value=0xFA;
|
||||||
|
if(value==0xF7) value=0xEB;
|
||||||
|
if(value==0xDF) value=0xAF;
|
||||||
|
if(value==0x7F) value=0xBE;
|
||||||
|
|
||||||
|
return ~((gp2x_memregs[0x1184>>1] & 0xFF00) | value | (gp2x_memregs[0x1186>>1] << 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void *gp2x_sound_play(void *blah)
|
||||||
|
{
|
||||||
|
struct timespec ts;
|
||||||
|
int flip=0;
|
||||||
|
|
||||||
|
ts.tv_sec=0, ts.tv_nsec=gp2x_sound_buffer[2];
|
||||||
|
|
||||||
|
while(! gp2x_sound_thread_exit)
|
||||||
|
{
|
||||||
|
gp2x_sound_frame(blah, (void *)(&gp2x_sound_buffer[4+flip]), gp2x_sound_buffer[0]);
|
||||||
|
write(gp2x_dev[3], (void *)(&gp2x_sound_buffer[4+flip]), gp2x_sound_buffer[1]);
|
||||||
|
|
||||||
|
flip^=gp2x_sound_buffer[1];
|
||||||
|
|
||||||
|
//nanosleep(&ts, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void gp2x_deinit(void)
|
||||||
|
{int i;
|
||||||
|
if(gp2x_sound_thread) { gp2x_sound_thread_exit=1; for(i=0;i<1000000;i++); }
|
||||||
|
|
||||||
|
gp2x_memregs[0x28DA>>1]=0x4AB;
|
||||||
|
gp2x_memregs[0x290C>>1]=640;
|
||||||
|
|
||||||
|
close(gp2x_dev[0]);
|
||||||
|
close(gp2x_dev[1]);
|
||||||
|
close(gp2x_dev[2]);
|
||||||
|
//close(gp2x_dev[3]);
|
||||||
|
//fcloseall();
|
||||||
|
}
|
||||||
|
|
||||||
|
void gp2x_init(int bpp, int rate, int bits, int stereo, int Hz)
|
||||||
|
{
|
||||||
|
struct fb_fix_screeninfo fixed_info;
|
||||||
|
|
||||||
|
if(!gp2x_dev[0]) gp2x_dev[0] = open("/dev/fb0", O_RDWR);
|
||||||
|
if(!gp2x_dev[1]) gp2x_dev[1] = open("/dev/fb1", O_RDWR);
|
||||||
|
if(!gp2x_dev[2]) gp2x_dev[2] = open("/dev/mem", O_RDWR);
|
||||||
|
//if(!gp2x_dev[3]) gp2x_dev[3] = open("/dev/dsp", O_WRONLY);
|
||||||
|
|
||||||
|
gp2x_memregs=(unsigned short *)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_dev[2], 0xc0000000);
|
||||||
|
|
||||||
|
if(!gp2x_sound_thread) { gp2x_memregs[0x0F16>>1] = 0x830a; sleep(1);
|
||||||
|
gp2x_memregs[0x0F58>>1] = 0x100c; sleep(1); }
|
||||||
|
|
||||||
|
ioctl (gp2x_dev[0], FBIOGET_FSCREENINFO, &fixed_info);
|
||||||
|
gp2x_screen15=gp2x_logvram15[0]=(unsigned short *)mmap(0, 320*240*2, PROT_WRITE, MAP_SHARED, gp2x_dev[0], 0);
|
||||||
|
gp2x_screen8=gp2x_logvram8[0]=(unsigned char *)gp2x_logvram15[0];
|
||||||
|
gp2x_physvram[0]=fixed_info.smem_start;
|
||||||
|
|
||||||
|
ioctl (gp2x_dev[1], FBIOGET_FSCREENINFO, &fixed_info);
|
||||||
|
gp2x_logvram15[1]=(unsigned short *)mmap(0, 320*240*2, PROT_WRITE, MAP_SHARED, gp2x_dev[1], 0);
|
||||||
|
gp2x_logvram8[1]=(unsigned char *)gp2x_logvram15[1];
|
||||||
|
gp2x_physvram[1]=fixed_info.smem_start;
|
||||||
|
|
||||||
|
gp2x_memregs[0x28DA>>1]=(((bpp+1)/8)<<9)|0xAB; /*8/15/16/24bpp...*/
|
||||||
|
gp2x_memregs[0x290C>>1]=320*((bpp+1)/8); /*line width in bytes*/
|
||||||
|
|
||||||
|
ioctl(gp2x_dev[3], SNDCTL_DSP_SPEED, &rate);
|
||||||
|
ioctl(gp2x_dev[3], SNDCTL_DSP_SETFMT, &bits);
|
||||||
|
ioctl(gp2x_dev[3], SNDCTL_DSP_STEREO, &stereo);
|
||||||
|
|
||||||
|
gp2x_sound_buffer[1]=(gp2x_sound_buffer[0]=(rate/Hz)) << (stereo + (bits==16));
|
||||||
|
gp2x_sound_buffer[2]=(1000000/Hz);
|
||||||
|
|
||||||
|
if(!gp2x_sound_thread) { gp2x_sound_thread = 1; //pthread_create( &gp2x_sound_thread, NULL, gp2x_sound_play, NULL);
|
||||||
|
atexit(gp2x_deinit); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
EXAMPLE
|
||||||
|
=======
|
||||||
|
|
||||||
|
now supply your own function for 16 bits, stereo:
|
||||||
|
|
||||||
|
void gp2x_sound_frame(void *blah, void *bufferg, int samples)
|
||||||
|
{
|
||||||
|
signed short *buffer=(signed short *)bufferg;
|
||||||
|
while(samples--)
|
||||||
|
{
|
||||||
|
*buffer++=0; //Left channel
|
||||||
|
*buffer++=0; //Right channel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
or 16 bits mono:
|
||||||
|
|
||||||
|
void gp2x_sound_frame(void *blah, void *bufferg, int samples)
|
||||||
|
{
|
||||||
|
signed short *buffer=(signed short *)bufferg;
|
||||||
|
while(samples--)
|
||||||
|
{
|
||||||
|
*buffer++=0; //Central channel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
now the main program...
|
||||||
|
|
||||||
|
hicolor example:
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
//this sets video to hicolor (16 bpp)
|
||||||
|
//it also sets sound to 44100,16bits,stereo and syncs audio to 50 Hz (PAL timing)
|
||||||
|
|
||||||
|
//Warning: GP2X does not support 8bit sound sampling! (at least within Linux)
|
||||||
|
|
||||||
|
gp2x_init(16,44100,16,1,50);
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
unsigned long pad=gp2x_joystick_read();
|
||||||
|
unsigned short color=gp2x_video_color15(255,255,255,0);
|
||||||
|
|
||||||
|
if(pad & GP2X_L) if(pad & GP2X_R) exit();
|
||||||
|
|
||||||
|
if(pad & GP2X_A) color=gp2x_color15(255,255,255,0); //white
|
||||||
|
else color=gp2x_color15(255,0,0,0); //red
|
||||||
|
|
||||||
|
gp2x_screen15[160+120*320]=color; //x=160, y=120
|
||||||
|
gp2x_video_flip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
palettized example:
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
//this sets video to palette mode (8 bpp)
|
||||||
|
//it also sets sound to 11025,16bits,stereo and syncs audio to 60 Hz (NSTC timing)
|
||||||
|
|
||||||
|
//Warning: GP2X does not support 8bit sound sampling! (at least within Linux)
|
||||||
|
|
||||||
|
gp2x_init(8,11025,16,1,60);
|
||||||
|
|
||||||
|
gp2x_video_color8(0,0,0,0); //color #0 is black for us
|
||||||
|
gp2x_video_color8(1,255,255,255); //color #1 is white for us
|
||||||
|
gp2x_video_color8(2,255,0,0); //color #2 is red for us
|
||||||
|
gp2x_video_setpalette();
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
unsigned long pad=gp2x_joystick_read();
|
||||||
|
unsigned char color;
|
||||||
|
|
||||||
|
if(pad & GP2X_L) if(pad & GP2X_R) exit();
|
||||||
|
|
||||||
|
if(pad & GP2X_A) color=1; //white
|
||||||
|
else color=2; //red
|
||||||
|
|
||||||
|
gp2x_screen8[160+120*320]=color; //x=160, y=120
|
||||||
|
gp2x_video_flip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
58
gp2x/gp2xminilib.h
Normal file
58
gp2x/gp2xminilib.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
GP2X minimal library v0.5 by rlyeh, 2005.
|
||||||
|
|
||||||
|
+ GP2X video library with double buffering.
|
||||||
|
+ GP2X soundring buffer library with double buffering.
|
||||||
|
+ GP2X joystick library.
|
||||||
|
|
||||||
|
Thanks to Squidge, Robster, snaff and NK, for the help & previous work! :-)
|
||||||
|
|
||||||
|
|
||||||
|
What's new
|
||||||
|
==========
|
||||||
|
|
||||||
|
0.5: patched sound for real stereo (using NK's solution); better init code.
|
||||||
|
|
||||||
|
0.4: lots of cleanups; sound is threaded now, double buffered too; 8 bpp video support; better exiting code.
|
||||||
|
|
||||||
|
0.3: shorter library; improved joystick diagonal detection.
|
||||||
|
|
||||||
|
0.2: better code layout; public release.
|
||||||
|
|
||||||
|
0.1: beta release
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* .h by Hermes/PS2Reality*/
|
||||||
|
|
||||||
|
#if !defined(GP2XMINILIB)
|
||||||
|
#define GP2XMINILIB
|
||||||
|
|
||||||
|
enum { GP2X_UP=0x1, GP2X_LEFT=0x4, GP2X_DOWN=0x10, GP2X_RIGHT=0x40,
|
||||||
|
GP2X_START=1<<8, GP2X_SELECT=1<<9, GP2X_L=1<<10, GP2X_R=1<<11,
|
||||||
|
GP2X_A=1<<12, GP2X_B=1<<13, GP2X_X=1<<14, GP2X_Y=1<<15,
|
||||||
|
GP2X_VOL_UP=1<<22, GP2X_VOL_DOWN=1<<23, GP2X_PUSH=1<<27, };
|
||||||
|
|
||||||
|
#define gp2x_video_color15(R,G,B,A) (((R&0xF8)<<8)|((G&0xF8)<<3)|((B&0xF8)>>3)|(A<<5))
|
||||||
|
#define gp2x_video_color8 (C,R,G,B) gp2x_palette[C][0]=(G<<8)|B,gp2x_palette[C][1]=R;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern unsigned short *gp2x_memregs, *gp2x_screen15, *gp2x_logvram15[2], gp2x_sound_buffer[4+(44100*2)*4]; //*2=stereo, *4=max buffers
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern unsigned long gp2x_dev[4];
|
||||||
|
|
||||||
|
|
||||||
|
void gp2x_video_flip(void);
|
||||||
|
void gp2x_video_setpalette(void);
|
||||||
|
unsigned long gp2x_joystick_read(void);
|
||||||
|
void *gp2x_sound_play(void *blah);
|
||||||
|
void gp2x_deinit(void);
|
||||||
|
void gp2x_init(int bpp, int rate, int bits, int stereo, int Hz);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
135
gp2x/load_imm_test.c
Normal file
135
gp2x/load_imm_test.c
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
typedef unsigned int u32;
|
||||||
|
|
||||||
|
u32 arm_imm_find_nonzero(u32 imm, u32 start_bit)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
for(i = start_bit; i < 32; i += 2)
|
||||||
|
{
|
||||||
|
if((imm >> i) & 0x03)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 arm_disect_imm_32bit(u32 imm, u32 *stores, u32 *rotations)
|
||||||
|
{
|
||||||
|
u32 store_count = 0;
|
||||||
|
u32 left_shift = 0;
|
||||||
|
|
||||||
|
// Otherwise it'll return 0 things to store because it'll never
|
||||||
|
// find anything.
|
||||||
|
if(imm == 0)
|
||||||
|
{
|
||||||
|
rotations[0] = 0;
|
||||||
|
stores[0] = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find chunks of non-zero data at 2 bit alignments.
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
left_shift = arm_imm_find_nonzero(imm, left_shift);
|
||||||
|
|
||||||
|
if(left_shift == 32)
|
||||||
|
{
|
||||||
|
// We've hit the end of the useful data.
|
||||||
|
return store_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hit the end, it might wrap back around to the beginning.
|
||||||
|
if(left_shift >= 24)
|
||||||
|
{
|
||||||
|
// Make a mask for the residual bits. IE, if we have
|
||||||
|
// 5 bits of data at the end we can wrap around to 3
|
||||||
|
// bits of data in the beginning. Thus the first
|
||||||
|
// thing, after being shifted left, has to be less
|
||||||
|
// than 111b, 0x7, or (1 << 3) - 1.
|
||||||
|
u32 top_bits = 32 - left_shift;
|
||||||
|
u32 residual_bits = 8 - top_bits;
|
||||||
|
u32 residual_mask = (1 << residual_bits) - 1;
|
||||||
|
|
||||||
|
if((store_count > 1) && (left_shift > 24) &&
|
||||||
|
((stores[0] << (32 - rotations[0])) < residual_mask))
|
||||||
|
{
|
||||||
|
// Then we can throw out the last bit and tack it on
|
||||||
|
// to the first bit.
|
||||||
|
u32 initial_bits = rotations[0];
|
||||||
|
stores[0] = (stores[0] << (top_bits + (32 - rotations[0]))) |
|
||||||
|
((imm >> left_shift) & 0xFF);
|
||||||
|
rotations[0] = top_bits;
|
||||||
|
|
||||||
|
return store_count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// There's nothing to wrap over to in the beginning
|
||||||
|
stores[store_count] = (imm >> left_shift) & 0xFF;
|
||||||
|
rotations[store_count] = (32 - left_shift) & 0x1F;
|
||||||
|
return store_count + 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
stores[store_count] = (imm >> left_shift) & 0xFF;
|
||||||
|
rotations[store_count] = (32 - left_shift) & 0x1F;
|
||||||
|
|
||||||
|
store_count++;
|
||||||
|
left_shift += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ror(value, shift) \
|
||||||
|
((value) >> shift) | ((value) << (32 - shift)) \
|
||||||
|
|
||||||
|
u32 arm_assemble_imm_32bit(u32 *stores, u32 *rotations, u32 store_count)
|
||||||
|
{
|
||||||
|
u32 n = ror(stores[0], rotations[0]);
|
||||||
|
u32 i;
|
||||||
|
printf("%x : %x\n", stores[0], rotations[0]);
|
||||||
|
|
||||||
|
for(i = 1; i < store_count; i++)
|
||||||
|
{
|
||||||
|
printf("%x : %x\n", stores[i], rotations[i]);
|
||||||
|
n |= ror(stores[i], rotations[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
u32 n = 0;
|
||||||
|
u32 stores[4];
|
||||||
|
u32 rotations[4];
|
||||||
|
u32 store_count;
|
||||||
|
u32 n2;
|
||||||
|
|
||||||
|
if(argc != 1)
|
||||||
|
{
|
||||||
|
n = strtoul(argv[1], NULL, 16);
|
||||||
|
store_count = arm_disect_imm_32bit(n, stores, rotations);
|
||||||
|
n2 = arm_assemble_imm_32bit(stores, rotations, store_count);
|
||||||
|
printf("%08x -> %08x (%d stores)\n", n, n2, store_count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
store_count = arm_disect_imm_32bit(n, stores, rotations);
|
||||||
|
n2 = arm_assemble_imm_32bit(stores, rotations, store_count);
|
||||||
|
if(n != n2)
|
||||||
|
{
|
||||||
|
printf("Failure: %08x -/-> %08x\n", n, n2);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
n++;
|
||||||
|
} while(n != 0);
|
||||||
|
|
||||||
|
printf("Done!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
262
gp2x/readme_gp2x.txt
Normal file
262
gp2x/readme_gp2x.txt
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
-- gameplaySP2X Gameboy Advance emulator for GP2X --
|
||||||
|
|
||||||
|
gpSP2X is a version of my (Exophase)'s emulator originally for Sony PSP.
|
||||||
|
A large amount of effort has been done to make it more optimized for the
|
||||||
|
ARM CPU present in the GP2X, however it is still very much a work in
|
||||||
|
progress.
|
||||||
|
|
||||||
|
See readme.txt for the PSP version readme, which contains a lot of
|
||||||
|
information relevant to the GP2X version (note that some of it does
|
||||||
|
not apply however).
|
||||||
|
|
||||||
|
|
||||||
|
Changelog:
|
||||||
|
|
||||||
|
0.9-2xb:
|
||||||
|
-- IMPORTANT-- If you're overwriting an old version, be sure to delete the
|
||||||
|
gpsp.cfg file first, or be prepared to have a bunch of weird button
|
||||||
|
settings that would require fixing.
|
||||||
|
|
||||||
|
- Fixed some bugs stunting compatability.
|
||||||
|
- Optimized alpha blends in renderer.
|
||||||
|
- Some more optimizations to dynarec output.
|
||||||
|
- Savestates should work better now.
|
||||||
|
- Cheat/misc menu won't crash the emulator.
|
||||||
|
- Main button config window works (not all buttons are in yet)
|
||||||
|
|
||||||
|
0.9-2Xa: (Exophase release)
|
||||||
|
- Redid autoframeskip. Should work more reliably.
|
||||||
|
- Rewrote dynamic recompiler from x86 source (arm_emit.h, arm_stub.S).
|
||||||
|
Has some more sophisticated behavior than the last version, more is
|
||||||
|
still to come... Should notice a slight speed improvement over the
|
||||||
|
last version.
|
||||||
|
- Tweaked GUI to be a little more useable. Buttons are now mirroring the
|
||||||
|
PSP version's.
|
||||||
|
- Code unification + cleanup amongst versions.
|
||||||
|
|
||||||
|
|
||||||
|
v9008: (zodttd release)
|
||||||
|
- Updated the way autoframeskip works. Should be better now. Still has a max
|
||||||
|
frameskip value.
|
||||||
|
- Added a slight performance increase to the dynarec.
|
||||||
|
- Added sync() to make sure files such as savestates and in-game saves are
|
||||||
|
saved properly to the GP2X.
|
||||||
|
|
||||||
|
v9006: (zodttd release)
|
||||||
|
- Initial public release
|
||||||
|
|
||||||
|
|
||||||
|
Installation:
|
||||||
|
|
||||||
|
1. Place the "gpsp.gpe" and "game_config.txt" file in a directory on your SD
|
||||||
|
card used with the GP2X.
|
||||||
|
|
||||||
|
2. Place your GBA BIOS in the directory from step 1. This file must be named
|
||||||
|
"gba_bios.bin" in all lowercase as shown, so rename it if needed.
|
||||||
|
|
||||||
|
-- NOTE --
|
||||||
|
|
||||||
|
There are two commonly available BIOSes - one is the correct one used in
|
||||||
|
production GBA's worldwide and the other is a prototype BIOS. The latter
|
||||||
|
will not cause some games to not work correctly or crash. If you attempt
|
||||||
|
to use this BIOS you will be presented with a warning before being
|
||||||
|
allowed to continue. This screen will give you a checksum of the real
|
||||||
|
BIOS image (see readme.txt for further information).
|
||||||
|
|
||||||
|
3. Place your GBA games in the directory from step 1. These files should have
|
||||||
|
a ".gba" or ".bin" file extension. Zip compressed games should be supported
|
||||||
|
and are recognized with the ".zip" file extension. Note that 32MB ROMs will
|
||||||
|
probably not run if zipped. 16MB and smaller should be OK.
|
||||||
|
|
||||||
|
4. Done. Run gpsp.gpe.
|
||||||
|
|
||||||
|
|
||||||
|
Controls:
|
||||||
|
|
||||||
|
How to use gpSP on the GP2X:
|
||||||
|
Buttons are mapped as follows (GBA/ingame buttons can be changed in the menu):
|
||||||
|
|
||||||
|
GP2X--------------------GBA
|
||||||
|
X -> A
|
||||||
|
B -> B
|
||||||
|
L TRIG -> L TRIG
|
||||||
|
R TRIG -> R TRIG
|
||||||
|
START -> START
|
||||||
|
SELECT -> SELECT
|
||||||
|
|
||||||
|
GP2X--------------------------------gpSP
|
||||||
|
|
||||||
|
-- IN-GAME --
|
||||||
|
|
||||||
|
VOL MIDDLE (UP + DOWN) -> menu
|
||||||
|
PUSH STICK -> fps display toggle (second number is
|
||||||
|
frames actually drawn)
|
||||||
|
|
||||||
|
-- IN-MENU --
|
||||||
|
B -> select option
|
||||||
|
X -> cancel/exit menu
|
||||||
|
A -> escape (up one director level in the
|
||||||
|
file selector)
|
||||||
|
|
||||||
|
When gpSP is started, you are presented with the option to overclock your
|
||||||
|
GP2X. Use the L/R TRIG to change the CPU clockspeed and press START to
|
||||||
|
continue. You may also change RAM timings here - experiment with what
|
||||||
|
works well. Note that going too high on overclocking or low on RAM
|
||||||
|
timings can cause the game to crash or the GP2X to outright freeze up.
|
||||||
|
|
||||||
|
If you do not want to overclock, press START without using L/R.
|
||||||
|
You will now be presented with a menu to choose a game. Press the IN-MENU
|
||||||
|
"SELECT" button shown above to pick a game to load.
|
||||||
|
|
||||||
|
If you would like to test gpSP for the GP2X with a homebrew (free public
|
||||||
|
domain) game, a game by Russ Prince works very well with gpSP. It is called
|
||||||
|
Bust-A-Move and is a remake of the classic game it's named after.
|
||||||
|
|
||||||
|
|
||||||
|
How to build from source:
|
||||||
|
|
||||||
|
The makefile included in the source is geared towards the Open2x toolchain.
|
||||||
|
If you use Open2x and installed it in the way recommended then it should
|
||||||
|
work okay, assuming you also have up to date HW-SDL (and have
|
||||||
|
arm-linux-sdl-config installed in the right place). The makefile is in the
|
||||||
|
gp2x directory, so go there first then just type make to build gpsp.gpe.
|
||||||
|
Might need a little tweaking if your setup is different. If you need help
|
||||||
|
you can ask me, but I'll probably nag you about why you want to build it in
|
||||||
|
the first place.
|
||||||
|
|
||||||
|
|
||||||
|
GP2X version FAQ:
|
||||||
|
|
||||||
|
Q) Help! This game doesn't work. Am I using a bad version of the ROM?
|
||||||
|
|
||||||
|
A) First, make sure you're using the correct BIOS version. If you aren't
|
||||||
|
gpSP should tell you. Other than that, there are some games that are
|
||||||
|
known to not work now (and will probably work later), and perhaps
|
||||||
|
many more games that I don't know about that don't work. I haven't
|
||||||
|
launched a full scale compatability test at this version, so it might
|
||||||
|
take a while before the compatability levels are high.
|
||||||
|
|
||||||
|
|
||||||
|
Q) Why is this version slower than the PSP version?
|
||||||
|
|
||||||
|
A) gpSP is still a work in progress. It might be possible to obtain more
|
||||||
|
speed from both this version and the PSP one too (and others in the
|
||||||
|
future). With that in mind, know that even a very agressively overclocked
|
||||||
|
GP2X is still less powerful than a PSP, generally speaking. Still, I
|
||||||
|
have a lot of ideas. It's unlikely that the GP2X version will ever be as
|
||||||
|
fast/faster than the PSP version for anyone but anything's possible.
|
||||||
|
|
||||||
|
|
||||||
|
Q) How high does my GP2X have to overclock to enjoy gpSP?
|
||||||
|
|
||||||
|
A) That depends on you. Higher overclocking will mean less frames skipped
|
||||||
|
on autoframeskip, or less frameskip needed if on manual. Or it can
|
||||||
|
make the difference between whether or not virtual 60fps can be reached.
|
||||||
|
For some games no GP2X in the world will be able to run them fullspeed,
|
||||||
|
with any amount of frameskip. A few might run well with no overclocking
|
||||||
|
and a generous level of frameskip (probably manual). If you don't care
|
||||||
|
about battery life (or you're plugged into an outlet) you should push
|
||||||
|
it as high as you can while still maintaining stability, because
|
||||||
|
chances are high that whatever you play will benefit from it. Right now
|
||||||
|
you'll probably want 260MHz if you can achieve it, but with a lot of
|
||||||
|
luck this number will lower slightly in the future (and is just a vague
|
||||||
|
ballpark figure anyway). I don't want to scare anyone off from using the
|
||||||
|
emulator, you should give it a try and see how it plays for you
|
||||||
|
regardless of how high you can overclock. Just note that this is far
|
||||||
|
from a locked smooth experience for everyone on every game.
|
||||||
|
|
||||||
|
|
||||||
|
Q) GBA has an ARM processor, GP2X has an ARM processor. GP2X is more
|
||||||
|
powerful than GBA. This emulator should run great without overclocking,
|
||||||
|
so therefore you're doing it wrong.
|
||||||
|
|
||||||
|
A) That's not a question, but I'll field it anyway. Two things: first,
|
||||||
|
"virtualization", or running the GBA code "natively" on the GP2X is
|
||||||
|
probably not possible, at least not with the way I want to do things.
|
||||||
|
For reasons why go read my blog (see below). So yes, you actually
|
||||||
|
do need more than 16.7MHz of ARM9 power to emulate the GBA's CPU.
|
||||||
|
Second: there is a whole lot of work behind emulating the pretty 2D
|
||||||
|
graphics on the GBA, something it can do in hardware a lot better than
|
||||||
|
this platform can.
|
||||||
|
End result: GBA emulation on GP2X isn't as easy as you think it is.
|
||||||
|
|
||||||
|
|
||||||
|
Q) What are you working on now? When will you release the next version?
|
||||||
|
|
||||||
|
A) See the gpSP development blog:
|
||||||
|
|
||||||
|
http://gpsp-dev.blogspot.com/
|
||||||
|
|
||||||
|
Note that I don't give release dates, ever, unless I'm right on the verge
|
||||||
|
of releasing. Be grateful that I've decided to be much more open about
|
||||||
|
the development of the emulator now.
|
||||||
|
|
||||||
|
|
||||||
|
Q) Thanks to your blog I heard that you made some improvement. Can I have
|
||||||
|
a copy of the new code?
|
||||||
|
|
||||||
|
A) No. Builds in transition often have a lot of problems, and I like for
|
||||||
|
releases to be relatively substantial. I can probably be bribed out of
|
||||||
|
them with donations though. :P
|
||||||
|
|
||||||
|
|
||||||
|
Q) Why do the menu suck so much? Why do half the options not work or not
|
||||||
|
make any sense?
|
||||||
|
|
||||||
|
A) Sorry, the menu still hasn't been modified very much to fit the GP2X
|
||||||
|
version instead of the PSP version.. hopefully this will improve in the
|
||||||
|
future.
|
||||||
|
|
||||||
|
|
||||||
|
Q) Who's in charge of the GP2X version anyway?
|
||||||
|
|
||||||
|
A) Originally, zodttd was. I, Exophase, have basically usurped control of it
|
||||||
|
now to encourage zodttd to work more on his PS1 emulator (that and I'm
|
||||||
|
possessive of gpSP and get nervous when people work on it too heavily).
|
||||||
|
zodttd will most likely still be around to work on things though.
|
||||||
|
|
||||||
|
|
||||||
|
Q) I'm a super nice person and would like to donate some of my hard earned
|
||||||
|
money to this one-off GBA emulator. Where do I send my money to?
|
||||||
|
|
||||||
|
A) Exophase: exophase@gmail.com on PayPal
|
||||||
|
zodttd: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=heirloomer
|
||||||
|
%40pobox%2ecom&item_number=1&no_shipping=1&no_note=1&tax=0&cy_code=USD&bn=
|
||||||
|
PP%2dDonationsBF&charset=UTF%2d8
|
||||||
|
^ Click there for donating on PayPal (remove whitespace/linebreaks).
|
||||||
|
|
||||||
|
GP2X people have already donated a lot more to me than PSP people have,
|
||||||
|
even though there's an order of magnitude or two less users. And they've
|
||||||
|
donated far more to zodttd than they have to me. So I'm not going to ask
|
||||||
|
people to donate..
|
||||||
|
|
||||||
|
However I won't lie: donating ups the chances of me actually working on the
|
||||||
|
next version (for which I have a lot of ideas, but not necessarily time to
|
||||||
|
dedicate to.. that time might need more incentive to be allotted from other
|
||||||
|
things). This could change depending on my employment situation, but right
|
||||||
|
now I feel guilty doing anything that doesn't help guarantee that I'll be
|
||||||
|
able to buy food a year from now.
|
||||||
|
|
||||||
|
|
||||||
|
Q) Tell me all of your personal information.
|
||||||
|
|
||||||
|
A) Again not a question, but why not. I'm Exophase, real name: Gilead Kutnick,
|
||||||
|
male, 23 years old, current residence Bloomington, IN; straight/single/not
|
||||||
|
actively looking, almost have an MS in Computer Science (do have a BS
|
||||||
|
underneath it), likes PSP more than GP2X, will not write a Nintendo DS
|
||||||
|
emulator for either, am currently looking for a job for after I graduate.
|
||||||
|
|
||||||
|
|
||||||
|
Q) You said you're looking for a job.
|
||||||
|
|
||||||
|
A) Yes. If you have one or know someone who needs a low level oriented
|
||||||
|
programmer then I'm up for grabs. And this is my resume:
|
||||||
|
http://exophase.devzero.co.uk/resume.pdf
|
||||||
|
|
||||||
|
|
||||||
|
Credits:
|
||||||
|
|
||||||
|
Original codebase: Exophase (exophase@gmail.com)
|
||||||
|
Foundation gp2x code: zodttd
|
||||||
|
GP2X dynarec/stubs + current code maintainance: Exophase
|
||||||
|
|
||||||
37007
gp2x/rom_cache.S
Normal file
37007
gp2x/rom_cache.S
Normal file
File diff suppressed because it is too large
Load Diff
205
gp2x/speedtest.c
Normal file
205
gp2x/speedtest.c
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
/* speedtest.c for GP2X (CPU/LCD/RAM-Tuner Version 2.0)
|
||||||
|
Copyright (C) 2006 god_at_hell
|
||||||
|
|
||||||
|
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "display.h"
|
||||||
|
#include "cpuctrl.h"
|
||||||
|
#include "gp2xminilib.h"
|
||||||
|
|
||||||
|
void prim()
|
||||||
|
{
|
||||||
|
//FILE *primout;
|
||||||
|
unsigned char cad[256];
|
||||||
|
char p = 0;
|
||||||
|
int primnumber;
|
||||||
|
int l = 1;
|
||||||
|
float g = 0;
|
||||||
|
int i = 3;
|
||||||
|
|
||||||
|
while(i != 500000)
|
||||||
|
{
|
||||||
|
int m = 2;
|
||||||
|
float temp = sqrt(i);
|
||||||
|
float ifloat = (float)i;
|
||||||
|
|
||||||
|
if(temp == (int)temp)
|
||||||
|
{
|
||||||
|
m = i;
|
||||||
|
p = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(m < temp)
|
||||||
|
{
|
||||||
|
g = ifloat/m;
|
||||||
|
if (g == (int)g)
|
||||||
|
{
|
||||||
|
m = i;
|
||||||
|
p = 1;
|
||||||
|
}
|
||||||
|
m++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == 0)
|
||||||
|
{
|
||||||
|
l += 1;
|
||||||
|
primnumber = i;
|
||||||
|
sprintf(cad,"%u is primnumber",i);
|
||||||
|
v_putcad(1,13,0xffffff,0xB00000,cad);
|
||||||
|
//primout = fopen("/mnt/sd/primnumber.txt", "a");
|
||||||
|
//fprintf(primout,"%u: %u\n", l, i);
|
||||||
|
//fclose(primout);
|
||||||
|
//execl("sync",NULL);
|
||||||
|
gp2x_video_flip();
|
||||||
|
}
|
||||||
|
p = 0;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ant()
|
||||||
|
{
|
||||||
|
int i,n;
|
||||||
|
unsigned char cad[256];
|
||||||
|
short direction = 0; //clockwise ... 0 = Up, 1 = Right
|
||||||
|
unsigned short col1, col2;
|
||||||
|
col1=gp2x_video_color15(0,0,0,0);
|
||||||
|
col2=gp2x_video_color15(0xFF,0xFF,0xFF,0);
|
||||||
|
short antx = 200;
|
||||||
|
short anty = 140;
|
||||||
|
for(i = 0; i < 9000; i++)
|
||||||
|
{
|
||||||
|
for(n = 0; n < 500000; n++);
|
||||||
|
if(gp2x_screen15[(320*anty) + antx]==col1)
|
||||||
|
{
|
||||||
|
for(n = 0; n < 3; n++)
|
||||||
|
{
|
||||||
|
int m = 0;
|
||||||
|
for(m = 0; m < 3; m++)
|
||||||
|
{
|
||||||
|
gp2x_screen15[320*(anty+n)+antx+m] = col2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sprintf(cad,"%u steps left ",8999-i);
|
||||||
|
v_putcad(1,3,0x000000,0xffffff,cad);
|
||||||
|
gp2x_video_flip();
|
||||||
|
for(n = 0; n < 3; n++)
|
||||||
|
{
|
||||||
|
int m = 0;
|
||||||
|
for(m = 0; m < 3; m++)
|
||||||
|
{
|
||||||
|
gp2x_screen15[320*(anty+n)+antx+m] = col2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sprintf(cad,"%u steps left ",8999-i);
|
||||||
|
v_putcad(1,3,0x000000,0xffffff,cad);
|
||||||
|
gp2x_video_flip();
|
||||||
|
if(direction == 0) antx-=3;
|
||||||
|
if(direction == 1) anty-=3;
|
||||||
|
if(direction == 2) antx+=3;
|
||||||
|
if(direction == 3) anty+=3;
|
||||||
|
direction--;
|
||||||
|
if(direction < 0) direction=3;
|
||||||
|
}
|
||||||
|
if(gp2x_screen15[(320*anty) + antx]==col2)
|
||||||
|
{
|
||||||
|
for(n = 0; n < 3; n++)
|
||||||
|
{
|
||||||
|
int m = 0;
|
||||||
|
for(m = 0; m < 3; m++)
|
||||||
|
{
|
||||||
|
gp2x_screen15[320*(anty+n)+antx+m] = col1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sprintf(cad,"%u steps left ",8999-i);
|
||||||
|
v_putcad(1,3,0x000000,0xffffff,cad);
|
||||||
|
gp2x_video_flip();
|
||||||
|
for(n = 0; n < 3; n++)
|
||||||
|
{
|
||||||
|
int m = 0;
|
||||||
|
for(m = 0; m < 3; m++)
|
||||||
|
{
|
||||||
|
gp2x_screen15[320*(anty+n)+antx+m] = col1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sprintf(cad,"%u steps left ",8999-i);
|
||||||
|
v_putcad(1,3,0x000000,0xffffff,cad);
|
||||||
|
gp2x_video_flip();
|
||||||
|
if(direction == 0) antx+=3;
|
||||||
|
if(direction == 1) anty+=3;
|
||||||
|
if(direction == 2) antx-=3;
|
||||||
|
if(direction == 3) anty-=3;
|
||||||
|
direction++;
|
||||||
|
if(direction > 3) direction=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void speedtest(short test)
|
||||||
|
{
|
||||||
|
unsigned BACKGROUND;
|
||||||
|
if(test == 0) BACKGROUND=0xB00000;
|
||||||
|
if(test == 1) BACKGROUND=0xFFFFFF;
|
||||||
|
short start = 240;
|
||||||
|
short cpuspeed = start;
|
||||||
|
unsigned char cad[256];
|
||||||
|
FILE *speed;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
speed = fopen("/mnt/sd/speed.txt", "w");
|
||||||
|
ClearScreen(BACKGROUND);
|
||||||
|
if(test == 0) v_putcad(1,1,0x00ff00,BACKGROUND,"Prim-Speedtest");
|
||||||
|
if(test == 1) v_putcad(1,1,0x006600,BACKGROUND,"Ant-Speedtest");
|
||||||
|
v_putcad(1,6,0xffffff,BACKGROUND,"Testing Speed");
|
||||||
|
if(cpuspeed > start)
|
||||||
|
{
|
||||||
|
sprintf(cad,"%uMhz checked",cpuspeed-5);
|
||||||
|
v_putcad(1,9,0xffffff,BACKGROUND,cad);
|
||||||
|
}
|
||||||
|
gp2x_video_flip();
|
||||||
|
ClearScreen(BACKGROUND);
|
||||||
|
if(test == 0) v_putcad(1,1,0x00ff00,BACKGROUND,"Prim-Speedtest");
|
||||||
|
if(test == 1) v_putcad(1,1,0x006600,BACKGROUND,"Ant-Speedtest");
|
||||||
|
v_putcad(1,6,0xffffff,BACKGROUND,"Testing Speed");
|
||||||
|
if(cpuspeed > start)
|
||||||
|
{
|
||||||
|
sprintf(cad,"%uMhz checked",cpuspeed-5);
|
||||||
|
if(test == 0) v_putcad(1,9,0xffffff,BACKGROUND,cad);
|
||||||
|
if(test == 1) v_putcad(1,9,0x000000,BACKGROUND,cad);
|
||||||
|
}
|
||||||
|
gp2x_video_flip();
|
||||||
|
fprintf (speed,"set CPU-Frequency = %uMHz\r\n",cpuspeed);
|
||||||
|
set_FCLK(cpuspeed);
|
||||||
|
|
||||||
|
if(test == 0) prim();
|
||||||
|
if(test == 1) ant();
|
||||||
|
|
||||||
|
fprintf(speed,"%uMhz checked\n\n", cpuspeed);
|
||||||
|
cpuspeed = cpuspeed + 5;
|
||||||
|
fclose(speed);
|
||||||
|
execl("sync",NULL);
|
||||||
|
}
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
3
gp2x/speedtest.h
Normal file
3
gp2x/speedtest.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
void prim();
|
||||||
|
void ant();
|
||||||
|
void speedtest(short test);
|
||||||
78790
gp2x/video.S
Normal file
78790
gp2x/video.S
Normal file
File diff suppressed because it is too large
Load Diff
181
gp2x/video_blend.S
Normal file
181
gp2x/video_blend.S
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
.align 2
|
||||||
|
|
||||||
|
.global expand_blend
|
||||||
|
.global expand_normal
|
||||||
|
|
||||||
|
@ Input:
|
||||||
|
@ r0 = screen_src_ptr
|
||||||
|
@ r1 = screen_dest_ptr
|
||||||
|
@ r2 = start
|
||||||
|
@ r3 = end
|
||||||
|
|
||||||
|
6:
|
||||||
|
.word io_registers
|
||||||
|
.word palette_ram_converted
|
||||||
|
.word 0x04000200 @ combine test mask
|
||||||
|
.word 0x07E0F81F @ clamp mask
|
||||||
|
.word 0x000003FE @ palette index mask
|
||||||
|
.word 0x08010020 @ saturation mask
|
||||||
|
|
||||||
|
expand_blend:
|
||||||
|
stmdb sp!, { r4, r5, r6, r9, r10, r11, r14 }
|
||||||
|
|
||||||
|
add r0, r0, r2, lsl #2 @ screen_src_ptr += start
|
||||||
|
add r1, r1, r2, lsl #1 @ screen_dest_ptr += start
|
||||||
|
sub r2, r3, r2 @ r2 = end - start
|
||||||
|
ldr r3, 6b @ r3 = io_registers
|
||||||
|
ldr r3, [r3, #0x52] @ r3 = bldalpha
|
||||||
|
mov r4, r3, lsr #8 @ r4 = bldalpha >> 8
|
||||||
|
and r3, r3, #0x1F @ r3 = blend_a
|
||||||
|
and r4, r4, #0x1F @ r4 = blend_b
|
||||||
|
cmp r3, #16 @ if(blend_a > 16)
|
||||||
|
movgt r3, #16 @ blend_a = 16
|
||||||
|
cmp r4, #16 @ if(blend_b > 16)
|
||||||
|
movgt r3, #16 @ blend_b = 16
|
||||||
|
|
||||||
|
ldr r14, 6b + 4 @ r14 = palette_ram_converted
|
||||||
|
ldr r12, 6b + 8 @ r12 = 0x04000200
|
||||||
|
ldr r11, 6b + 12 @ r11 = 0x07E0F81F
|
||||||
|
ldr r10, 6b + 16 @ r10 = 0x000003FE
|
||||||
|
|
||||||
|
add r5, r3, r4 @ r5 = blend_a + blend_b
|
||||||
|
cmp r5, #16 @ if((blend_a + blend_b) > 16)
|
||||||
|
bgt 3f @ goto loop w/saturation
|
||||||
|
|
||||||
|
|
||||||
|
@ loop w/o saturation
|
||||||
|
1:
|
||||||
|
ldr r5, [r0], #4 @ r5 = pixel_pair, screen_src_ptr++
|
||||||
|
and r6, r5, r12 @ r6 = r5 & 0x04000200
|
||||||
|
cmp r6, r12 @ if(r6 != 0x4000200)
|
||||||
|
bne 2f @ goto no_blend
|
||||||
|
|
||||||
|
and r6, r10, r5, lsl #1 @ r6 = (pixel_pair & 0x1FF) << 1
|
||||||
|
ldrh r6, [r14, r6] @ r6 = pixel_top
|
||||||
|
orr r6, r6, r6, lsl #16 @ r6 = pixel_top | (pixel_top << 16)
|
||||||
|
and r6, r6, r11 @ r6 = pixel_top_dilated
|
||||||
|
|
||||||
|
and r5, r10, r5, lsr #15 @ r5 = ((pixel_pair >> 16) & 0x1FF) << 1
|
||||||
|
ldrh r5, [r14, r5] @ r5 = pixel_bottom
|
||||||
|
orr r5, r5, r5, lsl #16 @ r5 = pixel_bottom | (pixel_bottom << 16)
|
||||||
|
and r5, r5, r11 @ r5 = pixel_bottom_dilated
|
||||||
|
|
||||||
|
mul r5, r4, r5 @ r5 = pixel_bottom * blend_b = bottom_mul
|
||||||
|
mla r5, r3, r6, r5 @ r5 = (pixel_top * blend_a) + bottom_mul
|
||||||
|
|
||||||
|
and r5, r11, r5, lsr #4 @ r5 = (color_dilated >> 4) & 0x07E0F81F
|
||||||
|
orr r5, r5, r5, lsr #16 @ r5 = color_dilated | (color_dilated >> 16)
|
||||||
|
|
||||||
|
strh r5, [r1], #2 @ *screen_dest_ptr = r5, screen_dest_ptr++
|
||||||
|
subs r2, r2, #1 @ counter--
|
||||||
|
bne 1b @ go again
|
||||||
|
|
||||||
|
ldmia sp!, { r4, r5, r6, r9, r10, r11, pc }
|
||||||
|
|
||||||
|
2:
|
||||||
|
and r5, r10, r5, lsl #1 @ r5 = (pixel_pair & 0x1FF) << 1
|
||||||
|
ldrh r5, [r14, r5] @ r5 = pixel_top
|
||||||
|
strh r5, [r1], #2 @ *screen_dest_ptr = r5, screen_dest_ptr++
|
||||||
|
|
||||||
|
subs r2, r2, #1 @ counter--
|
||||||
|
bne 1b @ go again
|
||||||
|
|
||||||
|
ldmia sp!, { r4, r5, r6, r9, r10, r11, pc }
|
||||||
|
|
||||||
|
@ loop w/saturation
|
||||||
|
|
||||||
|
3:
|
||||||
|
ldr r9, 6b + 20 @ r9 = 0x08010020
|
||||||
|
|
||||||
|
4:
|
||||||
|
ldr r5, [r0], #4 @ r5 = pixel_pair, screen_src_ptr++
|
||||||
|
and r6, r5, r12 @ r6 = r5 & 0x04000200
|
||||||
|
cmp r6, r12 @ if(r6 != 0x4000200)
|
||||||
|
bne 5f @ goto no_blend
|
||||||
|
|
||||||
|
and r6, r10, r5, lsl #1 @ r6 = (pixel_pair & 0x1FF) << 1
|
||||||
|
ldrh r6, [r14, r6] @ r6 = pixel_top
|
||||||
|
orr r6, r6, r6, lsl #16 @ r6 = pixel_top | (pixel_top << 16)
|
||||||
|
and r6, r6, r11 @ r6 = pixel_top_dilated
|
||||||
|
|
||||||
|
and r5, r10, r5, lsr #15 @ r5 = ((pixel_pair >> 16) & 0x1FF) << 1
|
||||||
|
ldrh r5, [r14, r5] @ r5 = pixel_bottom
|
||||||
|
orr r5, r5, r5, lsl #16 @ r5 = pixel_bottom | (pixel_bottom << 16)
|
||||||
|
and r5, r5, r11 @ r5 = pixel_bottom_dilated
|
||||||
|
|
||||||
|
mul r5, r4, r5 @ r5 = pixel_bottom * blend_b = bottom_mul
|
||||||
|
mla r5, r3, r6, r5 @ r5 = (pixel_top * blend_a) + bottom_mul
|
||||||
|
|
||||||
|
and r6, r9, r5, lsr #4 @ r6 = saturation bits
|
||||||
|
orr r6, r6, r6, lsr #1 @ propogate saturation down msb
|
||||||
|
orr r6, r6, r6, lsr #2 @ propogate down next two bits
|
||||||
|
orr r6, r6, r6, lsr #3 @ propogate down next three bits
|
||||||
|
orr r5, r6, r5, lsr #4 @ mask over result w/saturation
|
||||||
|
|
||||||
|
and r5, r11, r5 @ r5 = (color_dilated >> 4) & 0x07E0F81F
|
||||||
|
orr r5, r5, r5, lsr #16 @ r5 = color_dilated | (color_dilated >> 16)
|
||||||
|
strh r5, [r1], #2 @ *screen_dest_ptr = r5, screen_dest_ptr++
|
||||||
|
|
||||||
|
subs r2, r2, #1 @ counter--
|
||||||
|
bne 4b @ go again
|
||||||
|
|
||||||
|
ldmia sp!, { r4, r5, r6, r9, r10, r11, pc }
|
||||||
|
|
||||||
|
5:
|
||||||
|
and r5, r10, r5, lsl #1 @ r5 = (pixel_pair & 0x1FF) << 1
|
||||||
|
ldrh r5, [r14, r5] @ r5 = pixel_top
|
||||||
|
strh r5, [r1], #2 @ *screen_dest_ptr = r5, screen_dest_ptr++
|
||||||
|
|
||||||
|
subs r2, r2, #1 @ counter--
|
||||||
|
bne 4b @ go again
|
||||||
|
|
||||||
|
ldmia sp!, { r4, r5, r6, r9, r10, r11, pc }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ The following function isn't complete (only works on run multiples of 8),
|
||||||
|
@ but unfortunately I don't see much potential for actually being able to
|
||||||
|
@ use it..
|
||||||
|
|
||||||
|
#define expand_pixel_pair(reg, temp) ;\
|
||||||
|
and temp, r3, reg, lsr #15 ;\
|
||||||
|
ldrh temp, [r2, temp] ;\
|
||||||
|
;\
|
||||||
|
and reg, r3, reg, lsl #1 ;\
|
||||||
|
ldrh reg, [r2, reg] ;\
|
||||||
|
;\
|
||||||
|
orr reg, reg, temp, lsl #16 ;\
|
||||||
|
|
||||||
|
|
||||||
|
@ Input:
|
||||||
|
@ r0 = screen_ptr
|
||||||
|
@ r1 = start
|
||||||
|
@ r2 = end
|
||||||
|
|
||||||
|
1:
|
||||||
|
.word palette_ram_converted
|
||||||
|
.word 0x3FE
|
||||||
|
|
||||||
|
expand_normal:
|
||||||
|
stmdb sp!, { r4, r5, r6, r7, r14 }
|
||||||
|
|
||||||
|
add r0, r0, r1, lsl #1 @ screen_ptr += start
|
||||||
|
sub r1, r2, r1 @ r1 = end - start
|
||||||
|
ldr r2, 1b @ r2 = palette_ram_converted
|
||||||
|
ldr r3, 1b + 4 @ r3 = 0x3FE
|
||||||
|
|
||||||
|
2:
|
||||||
|
ldmia r0, { r4, r5, r6, r7 }
|
||||||
|
|
||||||
|
expand_pixel_pair(r4, r14)
|
||||||
|
expand_pixel_pair(r5, r14)
|
||||||
|
expand_pixel_pair(r6, r14)
|
||||||
|
expand_pixel_pair(r7, r14)
|
||||||
|
|
||||||
|
stmia r0!, { r4, r5, r6, r7 }
|
||||||
|
|
||||||
|
subs r1, r1, #8
|
||||||
|
bne 2b
|
||||||
|
|
||||||
|
ldmia sp!, { r4, r5, r6, r7, pc }
|
||||||
|
|
||||||
40
gui.h
Normal file
40
gui.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* gameplaySP
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GUI_H
|
||||||
|
#define GUI_H
|
||||||
|
|
||||||
|
#define GPSP_CONFIG_FILENAME "gpsp.cfg"
|
||||||
|
|
||||||
|
s32 load_file(u8 **wildcards, u8 *result);
|
||||||
|
u32 adjust_frameskip(u32 button_id);
|
||||||
|
s32 load_game_config_file();
|
||||||
|
s32 load_config_file();
|
||||||
|
s32 save_game_config_file();
|
||||||
|
s32 save_config_file();
|
||||||
|
u32 menu(u16 *original_screen);
|
||||||
|
|
||||||
|
extern u32 savestate_slot;
|
||||||
|
|
||||||
|
void get_savestate_filename_noshot(u32 slot, u8 *name_buffer);
|
||||||
|
void get_savestate_filename(u32 slot, u8 *name_buffer);
|
||||||
|
void get_savestate_snapshot(u8 *savestate_filename);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
899
input.c
Normal file
899
input.c
Normal file
@ -0,0 +1,899 @@
|
|||||||
|
/* gameplaySP
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
// Special thanks to psp298 for the analog->dpad code!
|
||||||
|
|
||||||
|
void trigger_key(u32 key)
|
||||||
|
{
|
||||||
|
u32 p1_cnt = io_registers[REG_P1CNT];
|
||||||
|
u32 p1;
|
||||||
|
|
||||||
|
if((p1_cnt >> 14) & 0x01)
|
||||||
|
{
|
||||||
|
u32 key_intersection = (p1_cnt & key) & 0x3FF;
|
||||||
|
|
||||||
|
if(p1_cnt >> 15)
|
||||||
|
{
|
||||||
|
if(key_intersection == (p1_cnt & 0x3FF))
|
||||||
|
raise_interrupt(IRQ_KEYPAD);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(key_intersection)
|
||||||
|
raise_interrupt(IRQ_KEYPAD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 key = 0;
|
||||||
|
|
||||||
|
u32 global_enable_analog = 1;
|
||||||
|
u32 analog_sensitivity_level = 4;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
BUTTON_NOT_HELD,
|
||||||
|
BUTTON_HELD_INITIAL,
|
||||||
|
BUTTON_HELD_REPEAT
|
||||||
|
} button_repeat_state_type;
|
||||||
|
|
||||||
|
|
||||||
|
// These define autorepeat values (in microseconds), tweak as necessary.
|
||||||
|
|
||||||
|
#define BUTTON_REPEAT_START 200000
|
||||||
|
#define BUTTON_REPEAT_CONTINUE 50000
|
||||||
|
|
||||||
|
button_repeat_state_type button_repeat_state = BUTTON_NOT_HELD;
|
||||||
|
u32 button_repeat = 0;
|
||||||
|
gui_action_type cursor_repeat = CURSOR_NONE;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PSP_BUILD
|
||||||
|
|
||||||
|
u32 gamepad_config_map[16] =
|
||||||
|
{
|
||||||
|
BUTTON_ID_MENU, // Triangle
|
||||||
|
BUTTON_ID_A, // Circle
|
||||||
|
BUTTON_ID_B, // Cross
|
||||||
|
BUTTON_ID_START, // Square
|
||||||
|
BUTTON_ID_L, // Ltrigger
|
||||||
|
BUTTON_ID_R, // Rtrigger
|
||||||
|
BUTTON_ID_DOWN, // Down
|
||||||
|
BUTTON_ID_LEFT, // Left
|
||||||
|
BUTTON_ID_UP, // Up
|
||||||
|
BUTTON_ID_RIGHT, // Right
|
||||||
|
BUTTON_ID_SELECT, // Select
|
||||||
|
BUTTON_ID_START, // Start
|
||||||
|
BUTTON_ID_UP, // Analog up
|
||||||
|
BUTTON_ID_DOWN, // Analog down
|
||||||
|
BUTTON_ID_LEFT, // Analog left
|
||||||
|
BUTTON_ID_RIGHT // Analog right
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PSP_ALL_BUTTON_MASK 0xFFFF
|
||||||
|
|
||||||
|
gui_action_type get_gui_input()
|
||||||
|
{
|
||||||
|
SceCtrlData ctrl_data;
|
||||||
|
gui_action_type new_button = CURSOR_NONE;
|
||||||
|
u32 new_buttons;
|
||||||
|
|
||||||
|
static u32 last_buttons = 0;
|
||||||
|
static u64 button_repeat_timestamp;
|
||||||
|
|
||||||
|
delay_us(25000);
|
||||||
|
|
||||||
|
sceCtrlPeekBufferPositive(&ctrl_data, 1);
|
||||||
|
ctrl_data.Buttons &= PSP_ALL_BUTTON_MASK;
|
||||||
|
new_buttons = (last_buttons ^ ctrl_data.Buttons) & ctrl_data.Buttons;
|
||||||
|
last_buttons = ctrl_data.Buttons;
|
||||||
|
|
||||||
|
if(new_buttons & PSP_CTRL_LEFT)
|
||||||
|
new_button = CURSOR_LEFT;
|
||||||
|
|
||||||
|
if(new_buttons & PSP_CTRL_RIGHT)
|
||||||
|
new_button = CURSOR_RIGHT;
|
||||||
|
|
||||||
|
if(new_buttons & PSP_CTRL_UP)
|
||||||
|
new_button = CURSOR_UP;
|
||||||
|
|
||||||
|
if(new_buttons & PSP_CTRL_DOWN)
|
||||||
|
new_button = CURSOR_DOWN;
|
||||||
|
|
||||||
|
if(new_buttons & PSP_CTRL_START)
|
||||||
|
new_button = CURSOR_SELECT;
|
||||||
|
|
||||||
|
if(new_buttons & PSP_CTRL_CIRCLE)
|
||||||
|
new_button = CURSOR_SELECT;
|
||||||
|
|
||||||
|
if(new_buttons & PSP_CTRL_CROSS)
|
||||||
|
new_button = CURSOR_EXIT;
|
||||||
|
|
||||||
|
if(new_buttons & PSP_CTRL_SQUARE)
|
||||||
|
new_button = CURSOR_BACK;
|
||||||
|
|
||||||
|
if(new_button != CURSOR_NONE)
|
||||||
|
{
|
||||||
|
get_ticks_us(&button_repeat_timestamp);
|
||||||
|
button_repeat_state = BUTTON_HELD_INITIAL;
|
||||||
|
button_repeat = new_buttons;
|
||||||
|
cursor_repeat = new_button;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(ctrl_data.Buttons & button_repeat)
|
||||||
|
{
|
||||||
|
u64 new_ticks;
|
||||||
|
get_ticks_us(&new_ticks);
|
||||||
|
|
||||||
|
if(button_repeat_state == BUTTON_HELD_INITIAL)
|
||||||
|
{
|
||||||
|
if((new_ticks - button_repeat_timestamp) >
|
||||||
|
BUTTON_REPEAT_START)
|
||||||
|
{
|
||||||
|
new_button = cursor_repeat;
|
||||||
|
button_repeat_timestamp = new_ticks;
|
||||||
|
button_repeat_state = BUTTON_HELD_REPEAT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(button_repeat_state == BUTTON_HELD_REPEAT)
|
||||||
|
{
|
||||||
|
if((new_ticks - button_repeat_timestamp) >
|
||||||
|
BUTTON_REPEAT_CONTINUE)
|
||||||
|
{
|
||||||
|
new_button = cursor_repeat;
|
||||||
|
button_repeat_timestamp = new_ticks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_button;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PSP_CTRL_ANALOG_UP (1 << 28)
|
||||||
|
#define PSP_CTRL_ANALOG_DOWN (1 << 29)
|
||||||
|
#define PSP_CTRL_ANALOG_LEFT (1 << 30)
|
||||||
|
#define PSP_CTRL_ANALOG_RIGHT (1 << 31)
|
||||||
|
|
||||||
|
u32 button_psp_mask_to_config[] =
|
||||||
|
{
|
||||||
|
PSP_CTRL_TRIANGLE,
|
||||||
|
PSP_CTRL_CIRCLE,
|
||||||
|
PSP_CTRL_CROSS,
|
||||||
|
PSP_CTRL_SQUARE,
|
||||||
|
PSP_CTRL_LTRIGGER,
|
||||||
|
PSP_CTRL_RTRIGGER,
|
||||||
|
PSP_CTRL_DOWN,
|
||||||
|
PSP_CTRL_LEFT,
|
||||||
|
PSP_CTRL_UP,
|
||||||
|
PSP_CTRL_RIGHT,
|
||||||
|
PSP_CTRL_SELECT,
|
||||||
|
PSP_CTRL_START,
|
||||||
|
PSP_CTRL_ANALOG_UP,
|
||||||
|
PSP_CTRL_ANALOG_DOWN,
|
||||||
|
PSP_CTRL_ANALOG_LEFT,
|
||||||
|
PSP_CTRL_ANALOG_RIGHT
|
||||||
|
};
|
||||||
|
|
||||||
|
u32 button_id_to_gba_mask[] =
|
||||||
|
{
|
||||||
|
BUTTON_UP,
|
||||||
|
BUTTON_DOWN,
|
||||||
|
BUTTON_LEFT,
|
||||||
|
BUTTON_RIGHT,
|
||||||
|
BUTTON_A,
|
||||||
|
BUTTON_B,
|
||||||
|
BUTTON_L,
|
||||||
|
BUTTON_R,
|
||||||
|
BUTTON_START,
|
||||||
|
BUTTON_SELECT,
|
||||||
|
BUTTON_NONE,
|
||||||
|
BUTTON_NONE,
|
||||||
|
BUTTON_NONE,
|
||||||
|
BUTTON_NONE
|
||||||
|
};
|
||||||
|
|
||||||
|
gui_action_type get_gui_input_fs_hold(u32 button_id)
|
||||||
|
{
|
||||||
|
gui_action_type new_button = get_gui_input();
|
||||||
|
if((last_buttons & button_psp_mask_to_config[button_id]) == 0)
|
||||||
|
return CURSOR_BACK;
|
||||||
|
|
||||||
|
return new_button;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 rapidfire_flag = 1;
|
||||||
|
|
||||||
|
u32 update_input()
|
||||||
|
{
|
||||||
|
SceCtrlData ctrl_data;
|
||||||
|
u32 buttons;
|
||||||
|
u32 non_repeat_buttons;
|
||||||
|
u32 button_id;
|
||||||
|
u32 i;
|
||||||
|
u32 new_key = 0;
|
||||||
|
u32 analog_sensitivity = 92 - (analog_sensitivity_level * 4);
|
||||||
|
u32 inv_analog_sensitivity = 256 - analog_sensitivity;
|
||||||
|
|
||||||
|
sceCtrlPeekBufferPositive(&ctrl_data, 1);
|
||||||
|
|
||||||
|
buttons = ctrl_data.Buttons;
|
||||||
|
|
||||||
|
if(global_enable_analog)
|
||||||
|
{
|
||||||
|
if(ctrl_data.Lx < analog_sensitivity)
|
||||||
|
buttons |= PSP_CTRL_ANALOG_LEFT;
|
||||||
|
|
||||||
|
if(ctrl_data.Lx > inv_analog_sensitivity)
|
||||||
|
buttons |= PSP_CTRL_ANALOG_RIGHT;
|
||||||
|
|
||||||
|
if(ctrl_data.Ly < analog_sensitivity)
|
||||||
|
buttons |= PSP_CTRL_ANALOG_UP;
|
||||||
|
|
||||||
|
if(ctrl_data.Ly > inv_analog_sensitivity)
|
||||||
|
buttons |= PSP_CTRL_ANALOG_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
non_repeat_buttons = (last_buttons ^ buttons) & buttons;
|
||||||
|
last_buttons = buttons;
|
||||||
|
|
||||||
|
for(i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
if(non_repeat_buttons & button_psp_mask_to_config[i])
|
||||||
|
button_id = gamepad_config_map[i];
|
||||||
|
else
|
||||||
|
button_id = BUTTON_ID_NONE;
|
||||||
|
|
||||||
|
switch(button_id)
|
||||||
|
{
|
||||||
|
case BUTTON_ID_MENU:
|
||||||
|
{
|
||||||
|
u16 *screen_copy = copy_screen();
|
||||||
|
u32 ret_val = menu(screen_copy);
|
||||||
|
free(screen_copy);
|
||||||
|
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BUTTON_ID_LOADSTATE:
|
||||||
|
{
|
||||||
|
u8 current_savestate_filename[512];
|
||||||
|
get_savestate_filename_noshot(savestate_slot,
|
||||||
|
current_savestate_filename);
|
||||||
|
load_state(current_savestate_filename);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BUTTON_ID_SAVESTATE:
|
||||||
|
{
|
||||||
|
u8 current_savestate_filename[512];
|
||||||
|
u16 *current_screen = copy_screen();
|
||||||
|
get_savestate_filename_noshot(savestate_slot,
|
||||||
|
current_savestate_filename);
|
||||||
|
save_state(current_savestate_filename, current_screen);
|
||||||
|
free(current_screen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BUTTON_ID_FASTFORWARD:
|
||||||
|
print_string("FASTFORWARD", 0xFFFF, 0x0000, 0, 50);
|
||||||
|
synchronize_flag ^= 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(buttons & button_psp_mask_to_config[i])
|
||||||
|
{
|
||||||
|
button_id = gamepad_config_map[i];
|
||||||
|
if(button_id < BUTTON_ID_MENU)
|
||||||
|
{
|
||||||
|
new_key |= button_id_to_gba_mask[button_id];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
|
||||||
|
if((button_id >= BUTTON_ID_RAPIDFIRE_A) &&
|
||||||
|
(button_id <= BUTTON_ID_RAPIDFIRE_L))
|
||||||
|
{
|
||||||
|
rapidfire_flag ^= 1;
|
||||||
|
if(rapidfire_flag)
|
||||||
|
{
|
||||||
|
new_key |= button_id_to_gba_mask[button_id -
|
||||||
|
BUTTON_ID_RAPIDFIRE_A + BUTTON_ID_A];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_key &= ~button_id_to_gba_mask[button_id -
|
||||||
|
BUTTON_ID_RAPIDFIRE_A + BUTTON_ID_A];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((new_key | key) != key)
|
||||||
|
trigger_key(new_key);
|
||||||
|
|
||||||
|
key = new_key;
|
||||||
|
|
||||||
|
io_registers[REG_P1] = (~key) & 0x3FF;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_input()
|
||||||
|
{
|
||||||
|
sceCtrlSetSamplingCycle(0);
|
||||||
|
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef GP2X_BUILD
|
||||||
|
|
||||||
|
// GP2X SDL requires a user made input method
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include "gp2x/gp2x.h"
|
||||||
|
|
||||||
|
u32 gamepad_config_map[16] =
|
||||||
|
{
|
||||||
|
BUTTON_ID_UP, // Up
|
||||||
|
BUTTON_ID_LEFT, // Left
|
||||||
|
BUTTON_ID_DOWN, // Down
|
||||||
|
BUTTON_ID_RIGHT, // Right
|
||||||
|
BUTTON_ID_START, // Start
|
||||||
|
BUTTON_ID_SELECT, // Select
|
||||||
|
BUTTON_ID_L, // Ltrigger
|
||||||
|
BUTTON_ID_R, // Rtrigger
|
||||||
|
BUTTON_ID_NONE, // A
|
||||||
|
BUTTON_ID_A, // B
|
||||||
|
BUTTON_ID_B, // X
|
||||||
|
BUTTON_ID_NONE, // Y
|
||||||
|
BUTTON_ID_VOLDOWN, // Vol down
|
||||||
|
BUTTON_ID_VOLUP, // Vol up
|
||||||
|
BUTTON_ID_FPS, // Push
|
||||||
|
BUTTON_ID_MENU // Vol middle
|
||||||
|
};
|
||||||
|
|
||||||
|
extern u32 gp2x_fps_debug;
|
||||||
|
|
||||||
|
u32 gpsp_gp2x_joystick_read(void)
|
||||||
|
{
|
||||||
|
u32 value = (gpsp_gp2x_memregs[0x1198 >> 1] & 0x00FF);
|
||||||
|
|
||||||
|
if(value == 0xFD)
|
||||||
|
value = 0xFA;
|
||||||
|
if(value == 0xF7)
|
||||||
|
value = 0xEB;
|
||||||
|
if(value == 0xDF)
|
||||||
|
value = 0xAF;
|
||||||
|
if(value == 0x7F)
|
||||||
|
value = 0xBE;
|
||||||
|
|
||||||
|
return ~((gpsp_gp2x_memregs[0x1184 >> 1] & 0xFF00) | value |
|
||||||
|
(gpsp_gp2x_memregs[0x1186 >> 1] << 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_action_type get_gui_input()
|
||||||
|
{
|
||||||
|
gui_action_type new_button = CURSOR_NONE;
|
||||||
|
u32 buttons = gpsp_gp2x_joystick_read();
|
||||||
|
u32 new_buttons;
|
||||||
|
|
||||||
|
static u32 last_buttons = 0;
|
||||||
|
static u64 button_repeat_timestamp;
|
||||||
|
|
||||||
|
delay_us(25000);
|
||||||
|
|
||||||
|
new_buttons = (last_buttons ^ buttons) & buttons;
|
||||||
|
last_buttons = buttons;
|
||||||
|
|
||||||
|
if(new_buttons & GP2X_A)
|
||||||
|
new_button = CURSOR_BACK;
|
||||||
|
|
||||||
|
if(new_buttons & GP2X_X)
|
||||||
|
new_button = CURSOR_EXIT;
|
||||||
|
|
||||||
|
if(new_buttons & GP2X_B)
|
||||||
|
new_button = CURSOR_SELECT;
|
||||||
|
|
||||||
|
if(new_buttons & GP2X_UP)
|
||||||
|
new_button = CURSOR_UP;
|
||||||
|
|
||||||
|
if(new_buttons & GP2X_DOWN)
|
||||||
|
new_button = CURSOR_DOWN;
|
||||||
|
|
||||||
|
if(new_buttons & GP2X_LEFT)
|
||||||
|
new_button = CURSOR_LEFT;
|
||||||
|
|
||||||
|
if(new_buttons & GP2X_RIGHT)
|
||||||
|
new_button = CURSOR_RIGHT;
|
||||||
|
|
||||||
|
|
||||||
|
if(new_button != CURSOR_NONE)
|
||||||
|
{
|
||||||
|
get_ticks_us(&button_repeat_timestamp);
|
||||||
|
button_repeat_state = BUTTON_HELD_INITIAL;
|
||||||
|
button_repeat = new_buttons;
|
||||||
|
cursor_repeat = new_button;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(buttons & button_repeat)
|
||||||
|
{
|
||||||
|
u64 new_ticks;
|
||||||
|
get_ticks_us(&new_ticks);
|
||||||
|
|
||||||
|
if(button_repeat_state == BUTTON_HELD_INITIAL)
|
||||||
|
{
|
||||||
|
if((new_ticks - button_repeat_timestamp) >
|
||||||
|
BUTTON_REPEAT_START)
|
||||||
|
{
|
||||||
|
new_button = cursor_repeat;
|
||||||
|
button_repeat_timestamp = new_ticks;
|
||||||
|
button_repeat_state = BUTTON_HELD_REPEAT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(button_repeat_state == BUTTON_HELD_REPEAT)
|
||||||
|
{
|
||||||
|
if((new_ticks - button_repeat_timestamp) >
|
||||||
|
BUTTON_REPEAT_CONTINUE)
|
||||||
|
{
|
||||||
|
new_button = cursor_repeat;
|
||||||
|
button_repeat_timestamp = new_ticks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_button;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GP2X_VOL_MIDDLE (1 << 24)
|
||||||
|
|
||||||
|
u32 button_gp2x_mask_to_config[] =
|
||||||
|
{
|
||||||
|
GP2X_UP,
|
||||||
|
GP2X_LEFT,
|
||||||
|
GP2X_DOWN,
|
||||||
|
GP2X_RIGHT,
|
||||||
|
GP2X_START,
|
||||||
|
GP2X_SELECT,
|
||||||
|
GP2X_L,
|
||||||
|
GP2X_R,
|
||||||
|
GP2X_A,
|
||||||
|
GP2X_B,
|
||||||
|
GP2X_X,
|
||||||
|
GP2X_Y,
|
||||||
|
GP2X_VOL_DOWN,
|
||||||
|
GP2X_VOL_UP,
|
||||||
|
GP2X_PUSH,
|
||||||
|
GP2X_VOL_MIDDLE
|
||||||
|
};
|
||||||
|
|
||||||
|
u32 button_id_to_gba_mask[] =
|
||||||
|
{
|
||||||
|
BUTTON_UP,
|
||||||
|
BUTTON_DOWN,
|
||||||
|
BUTTON_LEFT,
|
||||||
|
BUTTON_RIGHT,
|
||||||
|
BUTTON_A,
|
||||||
|
BUTTON_B,
|
||||||
|
BUTTON_L,
|
||||||
|
BUTTON_R,
|
||||||
|
BUTTON_START,
|
||||||
|
BUTTON_SELECT,
|
||||||
|
BUTTON_NONE,
|
||||||
|
BUTTON_NONE,
|
||||||
|
BUTTON_NONE,
|
||||||
|
BUTTON_NONE
|
||||||
|
};
|
||||||
|
|
||||||
|
u32 update_input()
|
||||||
|
{
|
||||||
|
static u32 rapidfire_flag = 1;
|
||||||
|
static u32 last_buttons;
|
||||||
|
u32 non_repeat_buttons;
|
||||||
|
u32 button_id;
|
||||||
|
u32 new_key = 0;
|
||||||
|
u32 buttons = gpsp_gp2x_joystick_read();
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
if((buttons & GP2X_VOL_DOWN) && (buttons & GP2X_VOL_UP))
|
||||||
|
{
|
||||||
|
buttons &= ~(GP2X_VOL_DOWN | GP2X_VOL_UP);
|
||||||
|
buttons |= GP2X_VOL_MIDDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
non_repeat_buttons = (last_buttons ^ buttons) & buttons;
|
||||||
|
last_buttons = buttons;
|
||||||
|
|
||||||
|
for(i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
if(non_repeat_buttons & button_gp2x_mask_to_config[i])
|
||||||
|
button_id = gamepad_config_map[i];
|
||||||
|
else
|
||||||
|
button_id = BUTTON_ID_NONE;
|
||||||
|
|
||||||
|
switch(button_id)
|
||||||
|
{
|
||||||
|
case BUTTON_ID_MENU:
|
||||||
|
{
|
||||||
|
u16 *screen_copy = copy_screen();
|
||||||
|
u32 ret_val = menu(screen_copy);
|
||||||
|
free(screen_copy);
|
||||||
|
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BUTTON_ID_LOADSTATE:
|
||||||
|
{
|
||||||
|
u8 current_savestate_filename[512];
|
||||||
|
get_savestate_filename_noshot(savestate_slot,
|
||||||
|
current_savestate_filename);
|
||||||
|
load_state(current_savestate_filename);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BUTTON_ID_SAVESTATE:
|
||||||
|
{
|
||||||
|
u8 current_savestate_filename[512];
|
||||||
|
u16 *current_screen = copy_screen();
|
||||||
|
get_savestate_filename_noshot(savestate_slot,
|
||||||
|
current_savestate_filename);
|
||||||
|
save_state(current_savestate_filename, current_screen);
|
||||||
|
free(current_screen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BUTTON_ID_FASTFORWARD:
|
||||||
|
print_string("FASTFORWARD", 0xFFFF, 0x0000, 0, 50);
|
||||||
|
synchronize_flag ^= 1;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case BUTTON_ID_VOLUP:
|
||||||
|
gp2x_sound_volume(1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BUTTON_ID_VOLDOWN:
|
||||||
|
gp2x_sound_volume(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BUTTON_ID_FPS:
|
||||||
|
gp2x_fps_debug ^= 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(buttons & button_gp2x_mask_to_config[i])
|
||||||
|
{
|
||||||
|
button_id = gamepad_config_map[i];
|
||||||
|
if(button_id < BUTTON_ID_MENU)
|
||||||
|
{
|
||||||
|
new_key |= button_id_to_gba_mask[button_id];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
|
||||||
|
if((button_id >= BUTTON_ID_RAPIDFIRE_A) &&
|
||||||
|
(button_id <= BUTTON_ID_RAPIDFIRE_L))
|
||||||
|
{
|
||||||
|
rapidfire_flag ^= 1;
|
||||||
|
if(rapidfire_flag)
|
||||||
|
{
|
||||||
|
new_key |= button_id_to_gba_mask[button_id -
|
||||||
|
BUTTON_ID_RAPIDFIRE_A + BUTTON_ID_A];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_key &= ~button_id_to_gba_mask[button_id -
|
||||||
|
BUTTON_ID_RAPIDFIRE_A + BUTTON_ID_A];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((new_key | key) != key)
|
||||||
|
trigger_key(new_key);
|
||||||
|
|
||||||
|
key = new_key;
|
||||||
|
|
||||||
|
io_registers[REG_P1] = (~key) & 0x3FF;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_input()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PC_BUILD
|
||||||
|
|
||||||
|
u32 key_map(SDLKey key_sym)
|
||||||
|
{
|
||||||
|
switch(key_sym)
|
||||||
|
{
|
||||||
|
case SDLK_LSHIFT:
|
||||||
|
return BUTTON_L;
|
||||||
|
|
||||||
|
case SDLK_x:
|
||||||
|
return BUTTON_R;
|
||||||
|
|
||||||
|
case SDLK_DOWN:
|
||||||
|
return BUTTON_DOWN;
|
||||||
|
|
||||||
|
case SDLK_UP:
|
||||||
|
return BUTTON_UP;
|
||||||
|
|
||||||
|
case SDLK_LEFT:
|
||||||
|
return BUTTON_LEFT;
|
||||||
|
|
||||||
|
case SDLK_RIGHT:
|
||||||
|
return BUTTON_RIGHT;
|
||||||
|
|
||||||
|
case SDLK_RETURN:
|
||||||
|
return BUTTON_START;
|
||||||
|
|
||||||
|
case SDLK_RSHIFT:
|
||||||
|
return BUTTON_SELECT;
|
||||||
|
|
||||||
|
case SDLK_LCTRL:
|
||||||
|
return BUTTON_B;
|
||||||
|
|
||||||
|
case SDLK_LALT:
|
||||||
|
return BUTTON_A;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return BUTTON_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 joy_map(u32 button)
|
||||||
|
{
|
||||||
|
switch(button)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
return BUTTON_L;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
return BUTTON_R;
|
||||||
|
|
||||||
|
case 9:
|
||||||
|
return BUTTON_START;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
return BUTTON_SELECT;
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
return BUTTON_B;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
return BUTTON_A;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return BUTTON_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_action_type get_gui_input()
|
||||||
|
{
|
||||||
|
SDL_Event event;
|
||||||
|
gui_action_type gui_action = CURSOR_NONE;
|
||||||
|
|
||||||
|
delay_us(30000);
|
||||||
|
|
||||||
|
while(SDL_PollEvent(&event))
|
||||||
|
{
|
||||||
|
switch(event.type)
|
||||||
|
{
|
||||||
|
case SDL_QUIT:
|
||||||
|
quit();
|
||||||
|
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
{
|
||||||
|
switch(event.key.keysym.sym)
|
||||||
|
{
|
||||||
|
case SDLK_ESCAPE:
|
||||||
|
gui_action = CURSOR_EXIT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_DOWN:
|
||||||
|
gui_action = CURSOR_DOWN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_UP:
|
||||||
|
gui_action = CURSOR_UP;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_LEFT:
|
||||||
|
gui_action = CURSOR_LEFT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_RIGHT:
|
||||||
|
gui_action = CURSOR_RIGHT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_RETURN:
|
||||||
|
gui_action = CURSOR_SELECT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_BACKSPACE:
|
||||||
|
gui_action = CURSOR_BACK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return gui_action;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 update_input()
|
||||||
|
{
|
||||||
|
SDL_Event event;
|
||||||
|
|
||||||
|
while(SDL_PollEvent(&event))
|
||||||
|
{
|
||||||
|
switch(event.type)
|
||||||
|
{
|
||||||
|
case SDL_QUIT:
|
||||||
|
quit();
|
||||||
|
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
{
|
||||||
|
if(event.key.keysym.sym == SDLK_ESCAPE)
|
||||||
|
{
|
||||||
|
quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(event.key.keysym.sym == SDLK_BACKSPACE)
|
||||||
|
{
|
||||||
|
u16 *screen_copy = copy_screen();
|
||||||
|
u32 ret_val = menu(screen_copy);
|
||||||
|
free(screen_copy);
|
||||||
|
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
|
||||||
|
if(event.key.keysym.sym == SDLK_F1)
|
||||||
|
{
|
||||||
|
debug_on();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
|
||||||
|
if(event.key.keysym.sym == SDLK_F2)
|
||||||
|
{
|
||||||
|
FILE *fp = fopen("palette_ram.bin", "wb");
|
||||||
|
printf("writing palette RAM\n");
|
||||||
|
fwrite(palette_ram, 1024, 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
printf("writing palette VRAM\n");
|
||||||
|
fp = fopen("vram.bin", "wb");
|
||||||
|
fwrite(vram, 1024 * 96, 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
printf("writing palette OAM RAM\n");
|
||||||
|
fp = fopen("oam_ram.bin", "wb");
|
||||||
|
fwrite(oam_ram, 1024, 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
printf("writing palette I/O registers\n");
|
||||||
|
fp = fopen("io_registers.bin", "wb");
|
||||||
|
fwrite(io_registers, 1024, 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
|
||||||
|
if(event.key.keysym.sym == SDLK_F3)
|
||||||
|
{
|
||||||
|
dump_translation_cache();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
|
||||||
|
if(event.key.keysym.sym == SDLK_F5)
|
||||||
|
{
|
||||||
|
u8 current_savestate_filename[512];
|
||||||
|
u16 *current_screen = copy_screen();
|
||||||
|
get_savestate_filename_noshot(savestate_slot,
|
||||||
|
current_savestate_filename);
|
||||||
|
save_state(current_savestate_filename, current_screen);
|
||||||
|
free(current_screen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
|
||||||
|
if(event.key.keysym.sym == SDLK_F7)
|
||||||
|
{
|
||||||
|
u8 current_savestate_filename[512];
|
||||||
|
get_savestate_filename_noshot(savestate_slot,
|
||||||
|
current_savestate_filename);
|
||||||
|
load_state(current_savestate_filename);
|
||||||
|
debug_on();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
|
||||||
|
if(event.key.keysym.sym == SDLK_BACKQUOTE)
|
||||||
|
{
|
||||||
|
synchronize_flag ^= 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
key |= key_map(event.key.keysym.sym);
|
||||||
|
trigger_key(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_KEYUP:
|
||||||
|
{
|
||||||
|
key &= ~(key_map(event.key.keysym.sym));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_JOYBUTTONDOWN:
|
||||||
|
{
|
||||||
|
key |= joy_map(event.jbutton.button);
|
||||||
|
trigger_key(key);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_JOYBUTTONUP:
|
||||||
|
{
|
||||||
|
key &= ~(joy_map(event.jbutton.button));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
io_registers[REG_P1] = (~key) & 0x3FF;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_input()
|
||||||
|
{
|
||||||
|
u32 joystick_count = SDL_NumJoysticks();
|
||||||
|
|
||||||
|
if(joystick_count > 0)
|
||||||
|
{
|
||||||
|
SDL_JoystickOpen(0);
|
||||||
|
SDL_JoystickEventState(SDL_ENABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define input_savestate_builder(type) \
|
||||||
|
void input_##type##_savestate(file_tag_type savestate_file) \
|
||||||
|
{ \
|
||||||
|
file_##type##_variable(savestate_file, key); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
input_savestate_builder(read);
|
||||||
|
input_savestate_builder(write_mem);
|
||||||
|
|
||||||
92
input.h
Normal file
92
input.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/* gameplaySP
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INPUT_H
|
||||||
|
#define INPUT_H
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
BUTTON_L = 0x200,
|
||||||
|
BUTTON_R = 0x100,
|
||||||
|
BUTTON_DOWN = 0x80,
|
||||||
|
BUTTON_UP = 0x40,
|
||||||
|
BUTTON_LEFT = 0x20,
|
||||||
|
BUTTON_RIGHT = 0x10,
|
||||||
|
BUTTON_START = 0x08,
|
||||||
|
BUTTON_SELECT = 0x04,
|
||||||
|
BUTTON_B = 0x02,
|
||||||
|
BUTTON_A = 0x01,
|
||||||
|
BUTTON_NONE = 0x00
|
||||||
|
} input_buttons_type;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
BUTTON_ID_UP,
|
||||||
|
BUTTON_ID_DOWN,
|
||||||
|
BUTTON_ID_LEFT,
|
||||||
|
BUTTON_ID_RIGHT,
|
||||||
|
BUTTON_ID_A,
|
||||||
|
BUTTON_ID_B,
|
||||||
|
BUTTON_ID_L,
|
||||||
|
BUTTON_ID_R,
|
||||||
|
BUTTON_ID_START,
|
||||||
|
BUTTON_ID_SELECT,
|
||||||
|
BUTTON_ID_MENU,
|
||||||
|
BUTTON_ID_FASTFORWARD,
|
||||||
|
BUTTON_ID_LOADSTATE,
|
||||||
|
BUTTON_ID_SAVESTATE,
|
||||||
|
BUTTON_ID_RAPIDFIRE_A,
|
||||||
|
BUTTON_ID_RAPIDFIRE_B,
|
||||||
|
BUTTON_ID_RAPIDFIRE_L,
|
||||||
|
BUTTON_ID_RAPIDFIRE_R,
|
||||||
|
BUTTON_ID_VOLUP,
|
||||||
|
BUTTON_ID_VOLDOWN,
|
||||||
|
BUTTON_ID_FPS,
|
||||||
|
BUTTON_ID_NONE
|
||||||
|
} input_buttons_id_type;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CURSOR_UP,
|
||||||
|
CURSOR_DOWN,
|
||||||
|
CURSOR_LEFT,
|
||||||
|
CURSOR_RIGHT,
|
||||||
|
CURSOR_SELECT,
|
||||||
|
CURSOR_BACK,
|
||||||
|
CURSOR_EXIT,
|
||||||
|
CURSOR_NONE
|
||||||
|
} gui_action_type;
|
||||||
|
|
||||||
|
void init_input();
|
||||||
|
u32 update_input();
|
||||||
|
gui_action_type get_gui_input();
|
||||||
|
gui_action_type get_gui_input_fs_hold(u32 button_id);
|
||||||
|
void input_write_mem_savestate(file_tag_type savestate_file);
|
||||||
|
void input_read_savestate(file_tag_type savestate_file);
|
||||||
|
|
||||||
|
extern u32 gamepad_config_map[16];
|
||||||
|
extern u32 global_enable_analog;
|
||||||
|
extern u32 analog_sensitivity_level;
|
||||||
|
|
||||||
|
#if defined(GP2X_BUILD)
|
||||||
|
u32 gpsp_gp2x_joystick_read(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
202
main.h
Normal file
202
main.h
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
/* gameplaySP
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MAIN_H
|
||||||
|
#define MAIN_H
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
TIMER_INACTIVE,
|
||||||
|
TIMER_PRESCALE,
|
||||||
|
TIMER_CASCADE
|
||||||
|
} timer_status_type;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
TIMER_NO_IRQ,
|
||||||
|
TIMER_TRIGGER_IRQ
|
||||||
|
} timer_irq_type;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
TIMER_DS_CHANNEL_NONE,
|
||||||
|
TIMER_DS_CHANNEL_A,
|
||||||
|
TIMER_DS_CHANNEL_B,
|
||||||
|
TIMER_DS_CHANNEL_BOTH
|
||||||
|
} timer_ds_channel_type;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
s32 count;
|
||||||
|
u32 reload;
|
||||||
|
u32 prescale;
|
||||||
|
u32 stop_cpu_ticks;
|
||||||
|
fixed16_16 frequency_step;
|
||||||
|
timer_ds_channel_type direct_sound_channels;
|
||||||
|
timer_irq_type irq;
|
||||||
|
timer_status_type status;
|
||||||
|
} timer_type;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
auto_frameskip,
|
||||||
|
manual_frameskip,
|
||||||
|
no_frameskip
|
||||||
|
} frameskip_type;
|
||||||
|
|
||||||
|
extern u32 cpu_ticks;
|
||||||
|
extern u32 frame_ticks;
|
||||||
|
extern u32 execute_cycles;
|
||||||
|
extern frameskip_type current_frameskip_type;
|
||||||
|
extern u32 frameskip_value;
|
||||||
|
extern u32 random_skip;
|
||||||
|
extern u32 global_cycles_per_instruction;
|
||||||
|
extern u32 synchronize_flag;
|
||||||
|
extern u32 skip_next_frame;
|
||||||
|
|
||||||
|
extern timer_type timer[4];
|
||||||
|
static u32 prescale_table[] = { 0, 6, 8, 10 };
|
||||||
|
|
||||||
|
extern u32 cycle_memory_access;
|
||||||
|
extern u32 cycle_pc_relative_access;
|
||||||
|
extern u32 cycle_sp_relative_access;
|
||||||
|
extern u32 cycle_block_memory_access;
|
||||||
|
extern u32 cycle_block_memory_sp_access;
|
||||||
|
extern u32 cycle_block_memory_words;
|
||||||
|
extern u32 cycle_dma16_words;
|
||||||
|
extern u32 cycle_dma32_words;
|
||||||
|
extern u32 flush_ram_count;
|
||||||
|
|
||||||
|
extern u64 base_timestamp;
|
||||||
|
|
||||||
|
extern u8 main_path[512];
|
||||||
|
|
||||||
|
extern u32 update_backup_flag;
|
||||||
|
extern u32 clock_speed;
|
||||||
|
|
||||||
|
u32 update_gba();
|
||||||
|
void reset_gba();
|
||||||
|
void synchronize();
|
||||||
|
void quit();
|
||||||
|
void delay_us(u32 us_count);
|
||||||
|
void get_ticks_us(u64 *tick_return);
|
||||||
|
void game_name_ext(u8 *src, u8 *buffer, u8 *extension);
|
||||||
|
void main_write_mem_savestate(file_tag_type savestate_file);
|
||||||
|
void main_read_savestate(file_tag_type savestate_file);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PSP_BUILD
|
||||||
|
|
||||||
|
u32 file_length(u8 *filename, s32 dummy);
|
||||||
|
|
||||||
|
extern u32 real_frame_count;
|
||||||
|
extern u32 virtual_frame_count;
|
||||||
|
extern u32 max_frameskip;
|
||||||
|
extern u32 num_skipped_frames;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef GP2X_BUILD
|
||||||
|
|
||||||
|
extern u64 frame_count_initial_timestamp;
|
||||||
|
extern u32 real_frame_count;
|
||||||
|
extern u32 virtual_frame_count;
|
||||||
|
extern u32 max_frameskip;
|
||||||
|
extern u32 num_skipped_frames;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PC_BUILD
|
||||||
|
|
||||||
|
u32 file_length(u8 *dummy, FILE *fp);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define count_timer(timer_number) \
|
||||||
|
timer[timer_number].reload = 0x10000 - value; \
|
||||||
|
if(timer_number < 2) \
|
||||||
|
{ \
|
||||||
|
u32 timer_reload = \
|
||||||
|
timer[timer_number].reload << timer[timer_number].prescale; \
|
||||||
|
sound_update_frequency_step(timer_number); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define adjust_sound_buffer(timer_number, channel) \
|
||||||
|
if(timer[timer_number].direct_sound_channels & (0x01 << channel)) \
|
||||||
|
{ \
|
||||||
|
direct_sound_channel[channel].buffer_index = \
|
||||||
|
(direct_sound_channel[channel].buffer_index + buffer_adjust) % \
|
||||||
|
BUFFER_SIZE; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define trigger_timer(timer_number) \
|
||||||
|
if(value & 0x80) \
|
||||||
|
{ \
|
||||||
|
if(timer[timer_number].status == TIMER_INACTIVE) \
|
||||||
|
{ \
|
||||||
|
u32 prescale = prescale_table[value & 0x03]; \
|
||||||
|
u32 timer_reload = timer[timer_number].reload; \
|
||||||
|
\
|
||||||
|
if((value >> 2) & 0x01) \
|
||||||
|
timer[timer_number].status = TIMER_CASCADE; \
|
||||||
|
else \
|
||||||
|
timer[timer_number].status = TIMER_PRESCALE; \
|
||||||
|
\
|
||||||
|
timer[timer_number].prescale = prescale; \
|
||||||
|
timer[timer_number].irq = (value >> 6) & 0x01; \
|
||||||
|
\
|
||||||
|
address16(io_registers, 0x100 + (timer_number * 4)) = \
|
||||||
|
-timer_reload; \
|
||||||
|
\
|
||||||
|
timer_reload <<= prescale; \
|
||||||
|
timer[timer_number].count = timer_reload; \
|
||||||
|
\
|
||||||
|
if(timer_reload < execute_cycles) \
|
||||||
|
execute_cycles = timer_reload; \
|
||||||
|
\
|
||||||
|
if(timer_number < 2) \
|
||||||
|
{ \
|
||||||
|
u32 buffer_adjust = \
|
||||||
|
(u32)(((float)(cpu_ticks - timer[timer_number].stop_cpu_ticks) * \
|
||||||
|
sound_frequency) / 16777216.0) * 2; \
|
||||||
|
\
|
||||||
|
sound_update_frequency_step(timer_number); \
|
||||||
|
adjust_sound_buffer(timer_number, 0); \
|
||||||
|
adjust_sound_buffer(timer_number, 1); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
if(timer[timer_number].status != TIMER_INACTIVE) \
|
||||||
|
{ \
|
||||||
|
timer[timer_number].status = TIMER_INACTIVE; \
|
||||||
|
timer[timer_number].stop_cpu_ticks = cpu_ticks; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
address16(io_registers, 0x102 + (timer_number * 4)) = value; \
|
||||||
|
|
||||||
|
void change_ext(u8 *src, u8 *buffer, u8 *extension);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
219
memory.h
Normal file
219
memory.h
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
/* gameplaySP
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MEMORY_H
|
||||||
|
#define MEMORY_H
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DMA_START_IMMEDIATELY,
|
||||||
|
DMA_START_VBLANK,
|
||||||
|
DMA_START_HBLANK,
|
||||||
|
DMA_START_SPECIAL,
|
||||||
|
DMA_INACTIVE
|
||||||
|
} dma_start_type;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DMA_16BIT,
|
||||||
|
DMA_32BIT
|
||||||
|
} dma_length_type;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DMA_NO_REPEAT,
|
||||||
|
DMA_REPEAT
|
||||||
|
} dma_repeat_type;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DMA_INCREMENT,
|
||||||
|
DMA_DECREMENT,
|
||||||
|
DMA_FIXED,
|
||||||
|
DMA_RELOAD
|
||||||
|
} dma_increment_type;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DMA_NO_IRQ,
|
||||||
|
DMA_TRIGGER_IRQ
|
||||||
|
} dma_irq_type;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DMA_DIRECT_SOUND_A,
|
||||||
|
DMA_DIRECT_SOUND_B,
|
||||||
|
DMA_NO_DIRECT_SOUND
|
||||||
|
} dma_ds_type;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 dma_channel;
|
||||||
|
u32 source_address;
|
||||||
|
u32 dest_address;
|
||||||
|
u32 length;
|
||||||
|
dma_repeat_type repeat_type;
|
||||||
|
dma_ds_type direct_sound_channel;
|
||||||
|
dma_increment_type source_direction;
|
||||||
|
dma_increment_type dest_direction;
|
||||||
|
dma_length_type length_type;
|
||||||
|
dma_start_type start_type;
|
||||||
|
dma_irq_type irq;
|
||||||
|
} dma_transfer_type;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
REG_DISPCNT = 0x000,
|
||||||
|
REG_DISPSTAT = 0x002,
|
||||||
|
REG_VCOUNT = 0x003,
|
||||||
|
REG_BG0CNT = 0x004,
|
||||||
|
REG_BG1CNT = 0x005,
|
||||||
|
REG_BG2CNT = 0x006,
|
||||||
|
REG_BG3CNT = 0x007,
|
||||||
|
REG_BG0HOFS = 0x08,
|
||||||
|
REG_BG0VOFS = 0x09,
|
||||||
|
REG_BG1HOFS = 0x0A,
|
||||||
|
REG_BG1VOFS = 0x0B,
|
||||||
|
REG_BG2HOFS = 0x0C,
|
||||||
|
REG_BG2VOFS = 0x0D,
|
||||||
|
REG_BG3HOFS = 0x0E,
|
||||||
|
REG_BG3VOFS = 0x0F,
|
||||||
|
REG_BG2PA = 0x10,
|
||||||
|
REG_BG2PB = 0x11,
|
||||||
|
REG_BG2PC = 0x12,
|
||||||
|
REG_BG2PD = 0x13,
|
||||||
|
REG_BG2X_L = 0x14,
|
||||||
|
REG_BG2X_H = 0x15,
|
||||||
|
REG_BG2Y_L = 0x16,
|
||||||
|
REG_BG2Y_H = 0x17,
|
||||||
|
REG_BG3PA = 0x18,
|
||||||
|
REG_BG3PB = 0x19,
|
||||||
|
REG_BG3PC = 0x1A,
|
||||||
|
REG_BG3PD = 0x1B,
|
||||||
|
REG_BG3X_L = 0x1C,
|
||||||
|
REG_BG3X_H = 0x1D,
|
||||||
|
REG_BG3Y_L = 0x1E,
|
||||||
|
REG_BG3Y_H = 0x1F,
|
||||||
|
REG_WIN0H = 0x20,
|
||||||
|
REG_WIN1H = 0x21,
|
||||||
|
REG_WIN0V = 0x22,
|
||||||
|
REG_WIN1V = 0x23,
|
||||||
|
REG_WININ = 0x24,
|
||||||
|
REG_WINOUT = 0x25,
|
||||||
|
REG_BLDCNT = 0x28,
|
||||||
|
REG_BLDALPHA = 0x29,
|
||||||
|
REG_BLDY = 0x2A,
|
||||||
|
REG_TM0D = 0x80,
|
||||||
|
REG_TM0CNT = 0x81,
|
||||||
|
REG_TM1D = 0x82,
|
||||||
|
REG_TM1CNT = 0x83,
|
||||||
|
REG_TM2D = 0x84,
|
||||||
|
REG_TM2CNT = 0x85,
|
||||||
|
REG_TM3D = 0x86,
|
||||||
|
REG_TM3CNT = 0x87,
|
||||||
|
REG_P1 = 0x098,
|
||||||
|
REG_P1CNT = 0x099,
|
||||||
|
REG_RCNT = 0x9A,
|
||||||
|
REG_IE = 0x100,
|
||||||
|
REG_IF = 0x101,
|
||||||
|
REG_IME = 0x104,
|
||||||
|
REG_HALTCNT = 0x180
|
||||||
|
} hardware_register;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
FLASH_DEVICE_MACRONIX_64KB = 0x1C,
|
||||||
|
FLASH_DEVICE_AMTEL_64KB = 0x3D,
|
||||||
|
FLASH_DEVICE_SST_64K = 0xD4,
|
||||||
|
FLASH_DEVICE_PANASONIC_64KB = 0x1B,
|
||||||
|
FLASH_DEVICE_MACRONIX_128KB = 0x09
|
||||||
|
} flash_device_id_type;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
FLASH_MANUFACTURER_MACRONIX = 0xC2,
|
||||||
|
FLASH_MANUFACTURER_AMTEL = 0x1F,
|
||||||
|
FLASH_MANUFACTURER_PANASONIC = 0x32,
|
||||||
|
FLASH_MANUFACTURER_SST = 0xBF
|
||||||
|
} flash_manufacturer_id_type;
|
||||||
|
|
||||||
|
u8 function_cc read_memory8(u32 address);
|
||||||
|
u32 function_cc read_memory16(u32 address);
|
||||||
|
u16 function_cc read_memory16_signed(u32 address);
|
||||||
|
u32 function_cc read_memory32(u32 address);
|
||||||
|
cpu_alert_type function_cc write_memory8(u32 address, u8 value);
|
||||||
|
cpu_alert_type function_cc write_memory16(u32 address, u16 value);
|
||||||
|
cpu_alert_type function_cc write_memory32(u32 address, u32 value);
|
||||||
|
|
||||||
|
extern u8 *memory_regions[16];
|
||||||
|
extern u32 memory_limits[16];
|
||||||
|
|
||||||
|
/* EDIT: Shouldn't this be extern ?! */
|
||||||
|
extern u32 waitstate_cycles_sequential[16][3];
|
||||||
|
|
||||||
|
extern u32 gamepak_size;
|
||||||
|
extern u8 gamepak_title[13];
|
||||||
|
extern u8 gamepak_code[5];
|
||||||
|
extern u8 gamepak_maker[3];
|
||||||
|
extern u8 gamepak_filename[512];
|
||||||
|
|
||||||
|
cpu_alert_type dma_transfer(dma_transfer_type *dma);
|
||||||
|
u8 *memory_region(u32 address, u32 *memory_limit);
|
||||||
|
u32 load_gamepak(char *name);
|
||||||
|
u32 load_backup(char *name);
|
||||||
|
s32 load_bios(char *name);
|
||||||
|
void update_backup();
|
||||||
|
void update_backup_force();
|
||||||
|
void init_memory();
|
||||||
|
void init_gamepak_buffer();
|
||||||
|
void bios_region_read_allow();
|
||||||
|
void bios_region_read_protect();
|
||||||
|
u8 *load_gamepak_page(u32 physical_index);
|
||||||
|
void memory_write_mem_savestate(file_tag_type savestate_file);
|
||||||
|
void memory_read_savestate(file_tag_type savestate_file);
|
||||||
|
void load_state(char *savestate_filename);
|
||||||
|
void save_state(char *savestate_filename, u16 *screen_capture);
|
||||||
|
|
||||||
|
extern u8 *gamepak_rom;
|
||||||
|
extern u32 gamepak_ram_buffer_size;
|
||||||
|
extern u32 oam_update;
|
||||||
|
extern u32 gbc_sound_update;
|
||||||
|
extern u32 gbc_sound_wave_update;
|
||||||
|
extern dma_transfer_type dma[4];
|
||||||
|
|
||||||
|
extern u8 *write_mem_ptr;
|
||||||
|
|
||||||
|
extern u16 palette_ram[512];
|
||||||
|
extern u16 oam_ram[512];
|
||||||
|
extern u16 palette_ram_converted[512];
|
||||||
|
extern u16 io_registers[1024 * 16];
|
||||||
|
extern u8 ewram[1024 * 256 * 2];
|
||||||
|
extern u8 iwram[1024 * 32 * 2];
|
||||||
|
extern u8 vram[1024 * 96 * 2];
|
||||||
|
|
||||||
|
extern u8 bios_rom[1024 * 32];
|
||||||
|
extern u32 bios_read_protect;
|
||||||
|
|
||||||
|
extern u8 *memory_map_read[8 * 1024];
|
||||||
|
extern u32 *reg;
|
||||||
|
extern u8 *memory_map_write[8 * 1024];
|
||||||
|
|
||||||
|
extern flash_device_id_type flash_device_id;
|
||||||
|
|
||||||
|
#endif
|
||||||
26
psp/Makefile
Normal file
26
psp/Makefile
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# -x assembler-with-cpp
|
||||||
|
# gpSP makefile
|
||||||
|
# Gilead Kutnick - Exophase
|
||||||
|
|
||||||
|
# Global definitions
|
||||||
|
|
||||||
|
PSPSDK = ${shell psp-config --pspsdk-path}
|
||||||
|
PREFIX = ${shell psp-config --psp-prefix}
|
||||||
|
|
||||||
|
OBJS = main.o cpu.o video.o memory.o sound.o input.o \
|
||||||
|
cpu_threaded.o gui.o zip.o cheats.o mips_stub.o
|
||||||
|
|
||||||
|
TARGET = gpSP
|
||||||
|
|
||||||
|
VPATH += ..
|
||||||
|
CFLAGS += -O3 -DPSP_BUILD -G0 -funsigned-char
|
||||||
|
CFLAGS += ${shell ${PREFIX}/bin/sdl-config --cflags}
|
||||||
|
ASFLAGS = ${CFLAGS}
|
||||||
|
PSP_EBOOT_TITLE = gpSP
|
||||||
|
EXTRA_TARGETS = EBOOT.PBP
|
||||||
|
|
||||||
|
LIBS += ${shell ${PREFIX}/bin/sdl-config --libs} -lpsppower \
|
||||||
|
-lz
|
||||||
|
|
||||||
|
include ${PSPSDK}/lib/build.mak
|
||||||
|
|
||||||
2531
psp/mips_emit.h
Normal file
2531
psp/mips_emit.h
Normal file
File diff suppressed because it is too large
Load Diff
3427
psp/mips_stub.S
Normal file
3427
psp/mips_stub.S
Normal file
File diff suppressed because it is too large
Load Diff
880
readme.txt
Normal file
880
readme.txt
Normal file
@ -0,0 +1,880 @@
|
|||||||
|
-- gameplaySP Gameboy Advance emulator for Playstation Portable --
|
||||||
|
|
||||||
|
|
||||||
|
-- Release log --
|
||||||
|
|
||||||
|
v0.91 (minor cleanup release)
|
||||||
|
|
||||||
|
NOTE: I don't usually do minor releases but I rewrote a ton of
|
||||||
|
things in gpSP 0.9, much of it during the last few days, and although
|
||||||
|
I spent a lot of time debugging a few bugs inevitably crept in.
|
||||||
|
|
||||||
|
# Fixed some issues in the new memory handlers that crept up, hopefully
|
||||||
|
should fix the problems between 0.8 and 0.9.
|
||||||
|
# Fixed a bug introduced in 0.9 that could cause crashes when selecting
|
||||||
|
things in the menu (I hope, at least).
|
||||||
|
# Fixed a bug with a certain invalid opcode causing a jump to be scanned
|
||||||
|
when there isn't one (fixes Sabre Wulf).
|
||||||
|
# Removed 2048 option for audio buffer.
|
||||||
|
|
||||||
|
v0.9 (yes, it's still beta)
|
||||||
|
|
||||||
|
NOTE: As some of you may be aware I'm pretty much tired of these
|
||||||
|
unofficial releases by people (okay, mostly single person) who
|
||||||
|
don't wish to follow my wishes. I'm in the process of asking this
|
||||||
|
person to stop, in his own language. However, I want to make
|
||||||
|
something clear. Look at the last six new features in this
|
||||||
|
changelog. I added these TODAY. I could have done them at any
|
||||||
|
time. But I didn't, because I spent many (dozens, quite possibly
|
||||||
|
hundreds) hours debugging games that people want to play. I have
|
||||||
|
always believed that this is far more important than spending time
|
||||||
|
on new features. Frankly, I'm tired of my emulator being hacked on
|
||||||
|
by other people, and if it doesn't stop I'm going to make this
|
||||||
|
project closed source.
|
||||||
|
|
||||||
|
Since I know this information is most visible when updated on the
|
||||||
|
major sites, note that it is the news posters I am especially
|
||||||
|
talking to. Next time you upload unofficial releases of my
|
||||||
|
emulator (without even knowing what's changed) bear in mind that
|
||||||
|
you're only encouraging me to stop working on this. If you want
|
||||||
|
to pick sides between me and unofficial devs, be my guest. I'll
|
||||||
|
let you decide by the contents of this release who's doing more
|
||||||
|
for my emulator.
|
||||||
|
|
||||||
|
Oh, and if you downloaded a version of gpSP that has more than
|
||||||
|
"gpSP" in its name then you're using one of their versions. Shame
|
||||||
|
on them for not even removing this threatening message, and shame
|
||||||
|
on you. Unless you're using a port I endorse (GP2X, Dreamcast, etc),
|
||||||
|
in which case everything's good.
|
||||||
|
|
||||||
|
|
||||||
|
# Fixed stereo output being reversed.
|
||||||
|
# Fixed a bug causing misaligned errors on 8bit writes to the gbc
|
||||||
|
audio channel 3 wave data (fixes various Super Robot Wars games)
|
||||||
|
# Fixed DMA with garbage in their upper 4 bits (fixes a crash in
|
||||||
|
Zelda: Minish Cap)
|
||||||
|
# Added double buffering to the rendering, removes line artifacts.
|
||||||
|
Big thanks to Brunni for the idea.
|
||||||
|
# Fixed a bug preventing some SRAM based games from saving (fixes
|
||||||
|
MMBN4-6)
|
||||||
|
# Fixed a bug causing part of EWRAM to potentially get corrupted if
|
||||||
|
code segments loaded in EWRAM cross 32KB boundaries (fixes
|
||||||
|
Phantasy Star 2)
|
||||||
|
# Fixed a bug causing games using movs pc in user mode (very bad
|
||||||
|
behavior) to crash. Fixes Colin McRae Rally 2.0.
|
||||||
|
# Improved timing a bit more. Fixes GTA Advance.
|
||||||
|
# Fixed a sprite clipping bug (fixes crash in third boss of Zelda:
|
||||||
|
Minish cap)
|
||||||
|
# Increased translation buffer size significantly (fixes Donkey Kong:
|
||||||
|
King of Swing)
|
||||||
|
# Fixed a dynarec bug causing add pc, reg to not work in Thumb code
|
||||||
|
(fixes crash in DBZ:LoZ, seems to fix crashes in battle in Golden
|
||||||
|
Sun, probably fixes other games)
|
||||||
|
# Made sprites using tiles < 512 not display in modes 3-5 (fixes
|
||||||
|
a couple minor graphical bugs)
|
||||||
|
# Removed abort on instruction 0x00000000 hack, was breaking a
|
||||||
|
certain bugged up game (Scurge)
|
||||||
|
# Fixed bug in flags generating variable logical shifts (fixes
|
||||||
|
SD Gundam Force)
|
||||||
|
# Fixed unaligned 16bit reads (fixes DBZ:LoZ in game)
|
||||||
|
# Redid contiguous block flag modification checking AGAIN and
|
||||||
|
hopefully got it right this time (fixes Mario vs. Donkey Kong)
|
||||||
|
# Redid ldm/stm instructions, fixing some cases (along with the
|
||||||
|
timing improvements fixes Mario & Luigi)
|
||||||
|
# Fixed 14bit EEPROM addressing (hopefully fixes saving in a lot
|
||||||
|
of games)
|
||||||
|
# Completely redid memory handlers, accurately emulates open and
|
||||||
|
BIOS reads now. Fixes Zelda: Minish Cap (roll bug, last dungeon),
|
||||||
|
Rayman, MMBN 1 (last dungeon), probably others.
|
||||||
|
# Fixed a minor graphical glitch on the edges of the screen
|
||||||
|
(thanks Brunni and hlide for the help!)
|
||||||
|
# Fixed crash on loading savestates from files of games not currently
|
||||||
|
loaded, but be sure you have the exact file you loaded it from or
|
||||||
|
gpSP will exit.
|
||||||
|
@ New memory handlers should provide performance boost for games
|
||||||
|
that access VRAM significantly (ie 3D games)
|
||||||
|
@ Added dead flag elimination checking for logical shifts, probably
|
||||||
|
doesn't make a noticeable difference but should have been there
|
||||||
|
anyway.
|
||||||
|
+ Added rapidfire to the button mappings.
|
||||||
|
+ Added auto frameskip. Removed fractional frameskip (don't think
|
||||||
|
it's very useful with auto anyway). Select auto in the graphics/
|
||||||
|
sound menu to activate it; frameskip value will act as the
|
||||||
|
maximum (auto is by default on). Thanks again to Brunni for some
|
||||||
|
help with this. Frameskip options are game specific.
|
||||||
|
+ Added vsync to the rendering. Only occurs when frames aren't
|
||||||
|
skipped. Seems to reduce tearing at least some of the time.
|
||||||
|
+ Added non-filtered video option.
|
||||||
|
+ Cheat support (Gameshark/Pro Action Replay v1-v3 only), still
|
||||||
|
in early stages, doesn't support everything; codes may cause
|
||||||
|
the game to crash, haven't determined yet if the codes are bad
|
||||||
|
or the implementation is. See cheat section for more information.
|
||||||
|
+ Added ability to change audio buffer size. Does not take affect
|
||||||
|
until you restart the game.
|
||||||
|
+ Added analog config options.
|
||||||
|
+ Added ability to set analog sensitivity and turn off analog.
|
||||||
|
+ Added ability to change the clock speed. This is a game specific
|
||||||
|
option. Try lower speeds w/auto frameskip to save battery life.
|
||||||
|
+ Fixed savestate speed on crappy Sony sticks.
|
||||||
|
|
||||||
|
(legend: # bug fix, + feature addition, @ optimization)
|
||||||
|
|
||||||
|
v0.8 - ("unlocked" beta)
|
||||||
|
|
||||||
|
NOTE 1: It has come to my attention that there are actually BIOSes
|
||||||
|
out there that are being used that cause some games to not work.
|
||||||
|
The BIOS md5sum listed here is for the BIOS actually in GBAs and
|
||||||
|
is as accurate as you'll get, (if you have a GBA and a flashcart
|
||||||
|
you can dump it yourself, see http://wiki.pocketheaven.com/GBA_BIOS)
|
||||||
|
|
||||||
|
NOTE 2: Since I know this is as far as a lot of people here I have a
|
||||||
|
little request. Please, please, (I'd italicize this if I could)
|
||||||
|
please stop constantly asking me when the next release will be,
|
||||||
|
what it'll have, etc. And while you're at it, please stop asking me
|
||||||
|
to implement wi-fi multiplayer, cheat support, or fix all of your
|
||||||
|
games. Some things will happen in due time, other things might not
|
||||||
|
ever happen. I devote about as much time as I can to this emulator
|
||||||
|
and I carefully include as much as I can in releases to try to
|
||||||
|
minimize the number of people who will nag me next time (erm, I
|
||||||
|
mean, to make the most people happy), so I don't release every other
|
||||||
|
day or anything like that. Sorry that I can't release once a week,
|
||||||
|
but I'm a lot busier now than I was when I was first developing this
|
||||||
|
emulator. Good thing I got the first version out before that, wasn't
|
||||||
|
it?
|
||||||
|
|
||||||
|
Congratulations, you made it this far! Now read the rest of the this
|
||||||
|
thing. *_*
|
||||||
|
|
||||||
|
|
||||||
|
# Fixed bug in dead flag elimination, "alt" version no longer needed.
|
||||||
|
# Fixed EEPROM saves being saved as 32kb instead of 512bytes/8kb
|
||||||
|
+ 32MB ROM support has been added. ROMS are "demand loaded" as
|
||||||
|
necessary and page swapped out; there might be a small loading lag,
|
||||||
|
but I have yet to ever really notice anything.
|
||||||
|
NOTE: 32MB ROM support only works for unzipped ROMs.
|
||||||
|
+ Save states have been added. See the save state menu for save/load
|
||||||
|
options.
|
||||||
|
+ Support for the real-time clock (RTC) chip in Pokemon cartridegs
|
||||||
|
and other games. The implementation is based off of VBA's, whatever
|
||||||
|
notes on gbadev I could find, and some of my own reverse engineering
|
||||||
|
of what the games do... it might not be totally correct. Also,
|
||||||
|
setting the time does not work.
|
||||||
|
+ Per-game configuration. Currently this only saves frameskip and
|
||||||
|
frameskip variation options.
|
||||||
|
+ Removed the flash type option from the menu and instead added it
|
||||||
|
to game_config.txt. Hopefully got everything - let me know if you
|
||||||
|
find something that isn't there. It's pretty easy to add them if you
|
||||||
|
have to.
|
||||||
|
+ Added a display in the upper left-hand corner to indicate when
|
||||||
|
fast-forward is on.
|
||||||
|
+ Added button bindings for save/load state.
|
||||||
|
@ Found a fix of StrmnNrmn proportion: far too much unnecessary mutex
|
||||||
|
synchronization was going on. Removing the two offending lines of
|
||||||
|
code gave a massive speed boost for free. Enjoy.
|
||||||
|
|
||||||
|
v0.7 - (beta than ever)
|
||||||
|
|
||||||
|
# Fixed a dynarec bug involving flags generating functions in
|
||||||
|
contiguous conditional blocks. Fixes music in Super Mario
|
||||||
|
Advance 2-4.
|
||||||
|
# Fixed a dynarec bug where Thumb mov imm instructions wouldn't
|
||||||
|
set flags. Fixes Zelda: Minish Cap, Megaman Battle Network,
|
||||||
|
probably others. Comes at a slight speed cost.
|
||||||
|
# Fixed a MIPS dynarec bug where some delay slots might not
|
||||||
|
get filled rarely, causing chaos. Don't know if it improves
|
||||||
|
any games.
|
||||||
|
# Improved self-modifying code detection. Makes Golden Sun,
|
||||||
|
Golden Sun 2, and Madden 2007 sorta work but excrutiatingly
|
||||||
|
slowly. Looking for a game-specific workaround for this - if you
|
||||||
|
want to play these games you'll have to wait for now :(
|
||||||
|
# Fixed a bug causing the interrupt disable flag to go down
|
||||||
|
when SWIs are entered, causing crashes/resets. Fixes
|
||||||
|
Super Mario Advance 2-4.
|
||||||
|
# Fixed menu crashing when strings with certain characters are
|
||||||
|
printed (for instance going to the menu after loading the
|
||||||
|
BIOS)
|
||||||
|
# Accidentally forgot to render win0 + win1 + objwin when all
|
||||||
|
active at the same time, many weeks ago. Added that, should fix
|
||||||
|
some parts in games that had frozen screens.
|
||||||
|
# Fixed some issues with gpsp.cfg needing to be present and
|
||||||
|
corrupting, hopefully. At the very least sanity checks are
|
||||||
|
performed on the config file.
|
||||||
|
# Made it so assigning the frameskip button to something besides
|
||||||
|
triangle actually worked as expected.
|
||||||
|
# Fixed ability to restart current game if nothing is loaded
|
||||||
|
(ie, crash)
|
||||||
|
# Added interrupt on cpsr modification support to the dynarec
|
||||||
|
(fixes backgrounds in Castlevania: Harmony of Dissonance)
|
||||||
|
# Added open addressing for ldm/stm instructions (fixes
|
||||||
|
Super Mario Advance 3)
|
||||||
|
# Improved cycle accuracy a little. Don't know of anything this
|
||||||
|
fixes, but games with idle loops will run a little better w/o
|
||||||
|
idle loop elimination (but should still be added when possible)
|
||||||
|
# Fixed some bugs causing sound to play sometimes when it shouldn't.
|
||||||
|
@ Added dead flag elimination for Thumb code. May possibly have
|
||||||
|
noticeable performance increases (Thumb emited coded size can
|
||||||
|
have a reduction of 20% or more)
|
||||||
|
@ Added code generation for divide SWI. May have a small speed
|
||||||
|
increase in some games.
|
||||||
|
+ Added analog nub support (special thanks to psp298 for the
|
||||||
|
code)
|
||||||
|
+ Added fractional frameskip. Go below 0 to get them. A frameskip
|
||||||
|
of 1/2 for instance means render 2 out of every 3 frames, 2/3
|
||||||
|
means render 3 out of every 4 frames, etc. Possibly useful for
|
||||||
|
games that are not quite fast enough at fs0 but fullspeed at
|
||||||
|
fs1...
|
||||||
|
|
||||||
|
v0.6 - (still beta quality, look out for new bugs)
|
||||||
|
|
||||||
|
NOTE: Please include gpsp.cfg with EBOOT.PBP, this shouldn't be
|
||||||
|
necessary but I think it is right now.
|
||||||
|
|
||||||
|
# Fixed a nasty bug that shouldn't have made it into the initial
|
||||||
|
release; a lot of games that TECM.. erm.. crash won't anymore.
|
||||||
|
NOTE: This doesn't mean that no game will ever crash, freeze,
|
||||||
|
otherwise not work.
|
||||||
|
# Fixed some crashes in the GUI and the ability to "go up" past
|
||||||
|
ms0:/PSP. Made the "go up" button square like it was supposed to
|
||||||
|
be (instead of cross).
|
||||||
|
+ There's now a menu that you can access, by default press right
|
||||||
|
while holding down triangle for the frameskip bar.
|
||||||
|
+ Menu option: resize screen aspect ratio, the default is now
|
||||||
|
"scaled 3:2" which makes it look more like a normal GBA. You
|
||||||
|
can use "fullscreen" (what it was like before) or "unscaled 3:2"
|
||||||
|
(tiny but pixel for pixel like a GBA)
|
||||||
|
+ Menu option: You can now load new games while the current one
|
||||||
|
is running.
|
||||||
|
+ Menu option: You can now restart the currently running game.
|
||||||
|
+ Menu option: Frameskip variation - this defaults to "uniform"
|
||||||
|
whereas it defaulted to "random" last release. Basically, turn
|
||||||
|
it on random if you find that frameskip causes flickering
|
||||||
|
animations to make things disappear. Other than that it will
|
||||||
|
generally look better on uniform.
|
||||||
|
+ GUI and file loading now have "auto repeat" on the buttons so
|
||||||
|
they're not such a pain to navigate.
|
||||||
|
+ Menu option: Added support for 128KB flash ROM, some games
|
||||||
|
require it (Pokemon Firered/Leaf Green, Super Mario Advance 4),
|
||||||
|
turn it on before running the game to make sure it works.
|
||||||
|
NOTE: There are some versions of these ROMs that have been
|
||||||
|
hacked to get around their 128KB flash, and may not even work
|
||||||
|
properly at all. Look out for them, these games should save
|
||||||
|
128KB save files after you set the setting to it, IF they use
|
||||||
|
128KB flash.
|
||||||
|
+ Menu option: Added ability to make the .sav files only update
|
||||||
|
when you exit the emulator, use with extreme caution (in other
|
||||||
|
words, it's not a good idea to use something like this in beta
|
||||||
|
quality software if you care about your saves). Does NOT update
|
||||||
|
if you exit through the home button, don't use the home button
|
||||||
|
if you can help it.
|
||||||
|
+ Zip support thanks to SiberianSTAR. It will load the first file
|
||||||
|
with the extension .gba or .bin that it finds.
|
||||||
|
+ Menu options are saved to gpsp.cfg. Note that it does not save
|
||||||
|
frameskip options or flash ROM options because these are very
|
||||||
|
per game particular.
|
||||||
|
+ The emulator will now try to save backup files to something
|
||||||
|
more matching the backup size than a fixed 64KB.
|
||||||
|
@ Loading ROMs and the auto save of the .sav files is MUCH faster
|
||||||
|
now. Thanks for the heads up on how to improve this from pollux!
|
||||||
|
@ While coding for the screen resize code I found that SDL just
|
||||||
|
wasn't cutting it and had to code for the GU myself. Turns out
|
||||||
|
the new code is faster (but because it is render code any
|
||||||
|
improvement will be diminished to nothing as frameskip is
|
||||||
|
increased). Special thanks to Zx-81 for the tips on this one
|
||||||
|
and for his GU code in the PSPVBA source as an example.
|
||||||
|
@ Added some games to game_config.txt. Note that not all versions
|
||||||
|
of these ROMs will work with these options, try to use the USA
|
||||||
|
version if possible.
|
||||||
|
|
||||||
|
8-19-2006 v0.5 - Initial release (public beta quality)
|
||||||
|
|
||||||
|
|
||||||
|
-- About --
|
||||||
|
|
||||||
|
gameplaySP (gpSP for short) is a GBA emulator written completely from
|
||||||
|
scratch. It is still pretty young (only having started a 3 months prior
|
||||||
|
to the first release) and thus rather immature, but it does a decent
|
||||||
|
job of playing a number of games, and is being improved upon somewhat
|
||||||
|
regularly. It is currently somewhat minimalistic, in the sourcecode,
|
||||||
|
presentation, and features. Its number one focus is to deliver a GBA
|
||||||
|
gaming experience in the most playable way that PSP can manage, with
|
||||||
|
frills being secondary (although still a consideration, at least for
|
||||||
|
some of them).
|
||||||
|
|
||||||
|
Having said that, optimization was the important way in achieving this
|
||||||
|
goal, with overall compatability being a near second. Because of this
|
||||||
|
some games may not run at the favor of running more games significantly
|
||||||
|
better. Of course, the compatability will improve with time. The
|
||||||
|
compatability in the current version (0.8) is perhaps around 80%
|
||||||
|
(assuming the correct BIOS image is used).
|
||||||
|
|
||||||
|
Many games will run at their best out of the box, but some games will
|
||||||
|
run very slowly unless idle loops are taken care of. There is a supplied
|
||||||
|
ROM database, game_config.txt, that gives idle loop targets and other
|
||||||
|
settings that may help a game to run better (or at all) on a per-game
|
||||||
|
basis. Currently (as of version 0.8) a few dozen games are on this list,
|
||||||
|
mostly only USA versions. This list will continue to be updated; there's
|
||||||
|
no real telling exactly how many of the ~2500 GBA games will need to
|
||||||
|
appear here.
|
||||||
|
|
||||||
|
gpSP currently requires an authentic GBA BIOS image file to run. It will
|
||||||
|
make no effort to run without one present; this file is 16kb and should
|
||||||
|
be called gba_bios.bin and present in the same location as the EBOOT.PBP
|
||||||
|
file. Please do not ask me where to obtain this, you'll have to look
|
||||||
|
online or grab it from a GBA. Note that it is not legal to have this file
|
||||||
|
unless you own a GBA, and even then it's rather gray area.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Features --
|
||||||
|
|
||||||
|
gpSP mostly emulates the core Gameboy Advance system. As of right now it
|
||||||
|
does not emulate any special hardware present on various GBA cartridges.
|
||||||
|
|
||||||
|
|
||||||
|
What it emulates:
|
||||||
|
|
||||||
|
GBA CPU: All ARM7TDMI ARM and Thumb mode opcodes except block memory w/
|
||||||
|
s-bit (probably aren't used in GBA games)
|
||||||
|
Video: Modes 0, 1, 2 almost completely, basic 3-5 support, sprites,
|
||||||
|
windows/OBJ windows
|
||||||
|
Interrupts: HBlank, VBlank, all timers, all DMA channels, keypad
|
||||||
|
DMA: Immediate, HBlank, VBlank, sound timer triggered
|
||||||
|
Sound: Both DirectSound channels and all 4 GBC audio channels
|
||||||
|
Input: Basic GBA input delivered through PSP controls
|
||||||
|
Cartridges: Currently supports ROMs up to 32MB in size (the maximum for
|
||||||
|
GBA) with the technique of ROM page swapping to fit within PSP's RAM.
|
||||||
|
Backup: 32/64kb SRAM, 64/128kb flash, 512bit/8kb EEPROM
|
||||||
|
RTC: The real-time clock present in cartridges such as most of the
|
||||||
|
Pokemon games and some others.
|
||||||
|
|
||||||
|
|
||||||
|
What it lacks:
|
||||||
|
|
||||||
|
Video: No mosaic, bitmap modes lack color effects (alpha, fades),
|
||||||
|
there might be some minor inaccuracies in blending...
|
||||||
|
Cycle accuracy: Very cycle innacurate; CPU is effectively somewhat
|
||||||
|
overclocked, meaning games with rampant idle loops will probably run
|
||||||
|
rather poorly. DMA transfers effectively happen for free (0 cycle).
|
||||||
|
Please do NOT use gpSP as a first source for developing GBA homebrew,
|
||||||
|
try No$GBA instead.
|
||||||
|
|
||||||
|
|
||||||
|
Additional features it has:
|
||||||
|
- The ability to attempt to run games at faster than GBA speed (sometimes
|
||||||
|
they can end up a lot faster, other times not so much)
|
||||||
|
- Savestates: the ability to save a game's state to a file and resume
|
||||||
|
playing where you left off later.
|
||||||
|
- Mild cheat support
|
||||||
|
|
||||||
|
|
||||||
|
Features that it doesn't have (please don't ask me to implement these!)
|
||||||
|
- Wi-fi multiplayer
|
||||||
|
|
||||||
|
|
||||||
|
-- Controls --
|
||||||
|
|
||||||
|
The default control scheme is very simple. If you don't like it you can
|
||||||
|
change it in the configuration menu.
|
||||||
|
|
||||||
|
At the ROM selection screen:
|
||||||
|
|
||||||
|
Up/down: navigate current selection window.
|
||||||
|
Left/right: switch between file window and directory window.
|
||||||
|
Circle/start: select current entry.
|
||||||
|
Square: go one directory up.
|
||||||
|
|
||||||
|
In game:
|
||||||
|
|
||||||
|
Up/down/left/right: GBA d-pad
|
||||||
|
Circle: GBA A button
|
||||||
|
Cross: GBA B button
|
||||||
|
Square/start: GBA start button
|
||||||
|
Select: GBA select button
|
||||||
|
Left trigger: GBA left trigger
|
||||||
|
Right trigger: GBA right trigger
|
||||||
|
Triangle: Adjust frameksip
|
||||||
|
|
||||||
|
In frameskip adjustment:
|
||||||
|
|
||||||
|
Hold down triangle to keep up, press up/down to increase/decrease
|
||||||
|
frameskip, respectively. Press down at 0 to change to auto, and up
|
||||||
|
at auto to change to 0.
|
||||||
|
|
||||||
|
In the menu:
|
||||||
|
|
||||||
|
Up/down: navigate current menu.
|
||||||
|
Left/right: change value in current menu selection (if a value is present)
|
||||||
|
Circle/start: select current entry (see help for entry to see what this means)
|
||||||
|
Square: exit the current menu.
|
||||||
|
|
||||||
|
|
||||||
|
-- Frameskip --
|
||||||
|
|
||||||
|
The purpose behind frameskip is to cause the emulator to not render every
|
||||||
|
frame of graphics to make the emulation closer to fullspeed. Many games will
|
||||||
|
run fullspeed without skipping any frames, however, some (particularly more
|
||||||
|
graphically demanding ones) will require this.
|
||||||
|
|
||||||
|
Frameskip can be set to two forms, either auto or manual. Auto will attempt
|
||||||
|
to skip only as many frames as necessary to make the game full speed, and
|
||||||
|
will not skip more than 4 in a row no matter what speed the game runs at
|
||||||
|
(at this point the benefits of frameskip yield diminishing returns).
|
||||||
|
|
||||||
|
It is recommended that you keep frameskip on auto, but manual is maintained
|
||||||
|
as an option if you want it and works as follows:
|
||||||
|
|
||||||
|
Manual frameskip will only render one out of every (n + 1) frames, where n
|
||||||
|
is the current frameskip value (so 0 will render everything). Increasing
|
||||||
|
the frameskip can improve speed, especially with very graphically
|
||||||
|
intensive games.
|
||||||
|
|
||||||
|
|
||||||
|
-- Cheats --
|
||||||
|
|
||||||
|
Currently, gpSP supports some functionality of Gameshark/Pro Action Replay
|
||||||
|
cheat codes. To use these, you must first make a file with the same name
|
||||||
|
as the ROM you want the cheat code to apply to, but with the extension .cht.
|
||||||
|
Put this file in the same directory as the ROM. To make it use a normal
|
||||||
|
text editor like notepad or wordpad if you're on Windows.
|
||||||
|
|
||||||
|
To write a code, write the type of model it is, gameshark_v1, gameshark_v3,
|
||||||
|
PAR_v1, or PAR_v3. gameshark_v1/PAR_v1 and gameshark_v3/PAR_v3 respectively
|
||||||
|
are interchangeable, but v1 and v3 are not! So if you don't know which
|
||||||
|
version it is, try both to see if it'll work.
|
||||||
|
|
||||||
|
Then, after that, put a space and put the name you'd like to give the cheat.
|
||||||
|
|
||||||
|
On the next several lines, put each cheat code pair, which should look like
|
||||||
|
this:
|
||||||
|
|
||||||
|
AAAAAAAA BBBBBBBB
|
||||||
|
|
||||||
|
Then put a blank line when you're done with that code, and start a new code
|
||||||
|
immediately after it. Here's an example of what a cheat file should look
|
||||||
|
like:
|
||||||
|
|
||||||
|
|
||||||
|
gameshark_v3 MarioInfHP
|
||||||
|
995fa0d9 0c6720d2
|
||||||
|
|
||||||
|
gameshark_v3 MarioMaxHP
|
||||||
|
21d58888 c5d0e432
|
||||||
|
|
||||||
|
gameshark_v3 InfHlthBat
|
||||||
|
6f4feadb 0581b00e
|
||||||
|
79af5dc6 5ce0d2b1
|
||||||
|
dbbd5995 44b801c9
|
||||||
|
65f8924d 2fbcd3c4
|
||||||
|
|
||||||
|
gameshark_v3 StopTimer
|
||||||
|
2b399ca4 ec81f071
|
||||||
|
|
||||||
|
|
||||||
|
After you have written the .cht file, you have to enable the cheats
|
||||||
|
individually in the game menu. Go to the Cheats/Misc menu, and you will
|
||||||
|
see the cheats; turn them on here. You may turn them on and off as you
|
||||||
|
please, but note that some cheats may still hold after you turn them off,
|
||||||
|
due to the nature of the system. Restart to completely get rid of them.
|
||||||
|
|
||||||
|
IMPORTANT NOTES:
|
||||||
|
|
||||||
|
This is still very work in progress! I basically added this in only 1.5
|
||||||
|
or so hours, and I don't have a lot of time right now to work on it
|
||||||
|
before releasing. So I'll probably improve it later.
|
||||||
|
|
||||||
|
Not all of gameshark's features are supported, especially for v3. Only
|
||||||
|
basic cheats will work, more or less.
|
||||||
|
|
||||||
|
Cheats may be unstable and may crash your game. If you're having problems
|
||||||
|
turn the cheats off.
|
||||||
|
|
||||||
|
Really, there's no guarantee that ANY cheats will work; I tried a few and
|
||||||
|
some seem to work, others are questionable. Try for yourself, but don't
|
||||||
|
expect anything to actually work right now. Do expect this feature to
|
||||||
|
improve in future versions.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Frequently Asked Questions --
|
||||||
|
|
||||||
|
Q) How do I run this on my PSP?
|
||||||
|
|
||||||
|
A) Provided is an EBOOT.PBP which will run as is on a 1.0 firmware
|
||||||
|
PSP or custom firmware that can run unsigned EBOOTs. On 1.5 firmwares
|
||||||
|
you must use a kxploit tool to run it (try SeiPSPtool). On 2.0
|
||||||
|
firmwares and higher further exploits must be used - see
|
||||||
|
http://pspupdates.qj.net/ for more information. Note that I have NOT
|
||||||
|
tested this emulator on any firmware version besides 1.5, and it's
|
||||||
|
very possible that it doesn't run well, or at all on higher versions.
|
||||||
|
Therefore I strongly recommend you downgrade if possible, and use
|
||||||
|
Devhook to run games that require > 1.5 version firmwares.
|
||||||
|
|
||||||
|
Be sure to include in the same directory as the EBOOT.PBP file the
|
||||||
|
game_config.txt file included and the gba_bios.bin file which you
|
||||||
|
must provide yourself.
|
||||||
|
|
||||||
|
gpSP does not run on PSPs with version 2.71 or higher firmware yet,
|
||||||
|
nor does any other homebrew executable.
|
||||||
|
|
||||||
|
|
||||||
|
Q) What is a BIOS image file? Why do I need it to run gpSP? Other GBA
|
||||||
|
emulators don't require this...
|
||||||
|
|
||||||
|
A) The GBA BIOS image file is a copy of a ROM on the GBA system that
|
||||||
|
has code for starting up the GBA (it shows the logo), verifying the
|
||||||
|
game, and most importantly, providing utility functions for the games
|
||||||
|
to use. It is the latter that gpSP needs the BIOS present for. It's
|
||||||
|
possible to replace all of these functions with equivilent code, but
|
||||||
|
this will take time - in the future gpSP may not require a BIOS image.
|
||||||
|
|
||||||
|
|
||||||
|
Q) I can't find this BIOS image.. please send it to me.
|
||||||
|
|
||||||
|
A) Sorry, but you're on your own. I won't send you a BIOS or tell you
|
||||||
|
where to get one (unless you want to rip it from a GBA yourself, in
|
||||||
|
which case I'll just give you the same link at the top). I can't do
|
||||||
|
this because it's not legal to send it around and I don't want to
|
||||||
|
get a reputation for illegally distributing BIOS images.
|
||||||
|
|
||||||
|
|
||||||
|
Q) How do I know I have the right BIOS?
|
||||||
|
|
||||||
|
A) If you have md5sum you can check if it has this hash:
|
||||||
|
a860e8c0b6d573d191e4ec7db1b1e4f6
|
||||||
|
That BIOS should work fine. I think that some others work fine too,
|
||||||
|
although I haven't confirmed this with absolute certainty. It's also
|
||||||
|
theoretically possible to use custom (and free) BIOS replacements,
|
||||||
|
but I don't know of any publically availablone ones.
|
||||||
|
|
||||||
|
As far as I'm aware there are two BIOSes floating around, I doubt
|
||||||
|
you'll get one that isn't one of those two. There's a very easy way
|
||||||
|
to determine which one you have - just look at the very first byte in
|
||||||
|
a hex editor. The correct BIOS begins with 0x18, the buggy BIOS begins
|
||||||
|
with 0x14.
|
||||||
|
|
||||||
|
|
||||||
|
Q) My favorite game won't run.
|
||||||
|
|
||||||
|
A) There probably isn't anything you can do about this, although a
|
||||||
|
change to game_config.txt might help. gpSP is still an emulator in
|
||||||
|
its infancy so the compatability is not superb. I don't have time
|
||||||
|
to test too many games so I'm releasing it as a public beta to get
|
||||||
|
a feel for some things that don't work. The next version could
|
||||||
|
perhaps fix it, or it might never run. There are always other
|
||||||
|
emulators of course, please try one.
|
||||||
|
|
||||||
|
However, before nagging me there is one thing I recommend you try,
|
||||||
|
and that is to add the option "iwram_stack_optimize = no" for the
|
||||||
|
game in game_config.txt. See the file itself for more information
|
||||||
|
on how to do this. If this fixes your game (and it's not already
|
||||||
|
in the game_config.txt) please tell me about it.
|
||||||
|
|
||||||
|
|
||||||
|
Q) My favorite game is very slow.
|
||||||
|
|
||||||
|
A) Emulating GBA takes a number of resources and getting it done well
|
||||||
|
on PSP is no simple task by any means. Some games are just going to
|
||||||
|
overwhelm the emulator completely. Of course, there is one special
|
||||||
|
case of game (a lot of early generation games fall under this
|
||||||
|
category) that can be made much faster by a simple addition to the
|
||||||
|
game_config.txt file. Wait for a new version of this file or the
|
||||||
|
next version of the emulator and the game may be improved.
|
||||||
|
|
||||||
|
That aside, there are still numerous optimizations that can be done,
|
||||||
|
and I sure you future versions will be faster (I just can't tell you
|
||||||
|
how much)
|
||||||
|
|
||||||
|
Also, a lot of games will be sped up considerably by adding an
|
||||||
|
idle_loop_eliminate_target line for it in game_config.txt. There
|
||||||
|
are some more obscurer options there that can improve speed too. If
|
||||||
|
the game is VERY slow there might be something wrong with its
|
||||||
|
emulation that can be improved. For instance, if you can't get a game
|
||||||
|
to run fullspeed on any frameskip you should e-mail me about it.
|
||||||
|
|
||||||
|
|
||||||
|
Q) Some games run fullspeed but the sound is messed up. Why?
|
||||||
|
|
||||||
|
A) At least 9 out of 10 times it means the game isn't really running
|
||||||
|
full speed, but just that you can't notice the difference. Increasing
|
||||||
|
frameskip will almost always improve sound quality in these
|
||||||
|
situations, to a certain point (after around frameskip 3 you
|
||||||
|
probably won't be seeing many more returns if it isn't already
|
||||||
|
fullspeed). The rest of the time it means there's a bug somewhere else
|
||||||
|
in the emulator, probably in the CPU core. Chances are that all you
|
||||||
|
can do is wait for it to be fixed in a later release.
|
||||||
|
|
||||||
|
|
||||||
|
Q) The emulator crashed!
|
||||||
|
|
||||||
|
A) Most games that don't run will probably take the emulator down with
|
||||||
|
it, or it could be an emulator bug completely unrelated to the game
|
||||||
|
(but unlikely). Press home and wait for the next version.
|
||||||
|
|
||||||
|
There is some information that comes up when the game crashes. This
|
||||||
|
information may be slightly useful to me, but chances are it
|
||||||
|
usually won't be all that interesting.
|
||||||
|
|
||||||
|
These days games are more likely to exit with a "bad crash" error.
|
||||||
|
This number is possibly useful to me, but to debug a game I'll have
|
||||||
|
to reproduce the crash anyway. When this happens it's probably due to
|
||||||
|
a bug in the CPU core that hasn't been fixed yet.
|
||||||
|
|
||||||
|
|
||||||
|
Q) Why won't my game save?
|
||||||
|
|
||||||
|
A) The game might need 128KB flash turned on and might not be listed in
|
||||||
|
game_config.txt. See game_config.txt for more information regarding
|
||||||
|
this. Be sure to include game_config.txt with the EBOOT.PBP file.
|
||||||
|
|
||||||
|
Other games might simply have bugs in the save support. For now, use
|
||||||
|
savestates as an alternative if you can't save.
|
||||||
|
|
||||||
|
|
||||||
|
Q) How do I change sound quality?
|
||||||
|
|
||||||
|
A) Right now, you can't. For those wondering, sound is locked at 44.1KHz
|
||||||
|
(sounds a bit high? It is, but it's currently necessary to play
|
||||||
|
everything correctly). I don't have any plans to allow changing this
|
||||||
|
right now, because I don't think there's really much reason to be
|
||||||
|
able to (it'd be a tiny speed boost at best and I don't think SDL even
|
||||||
|
allows for anything besides this sampling rate on PSP)
|
||||||
|
|
||||||
|
|
||||||
|
Q) What is this emulator's name?
|
||||||
|
|
||||||
|
A) Um.. what? It's gameplaySP, isn't it? You call it gpSP for short.
|
||||||
|
Somehow the name can't have the acronyms gbSP, gbapSP, or really
|
||||||
|
just about anything else you feel like giving it. Oh, and if you
|
||||||
|
really want to make me happy get the capitalization right too.
|
||||||
|
That's gpSP, not gPSP, GPsp.. you get the idea.
|
||||||
|
|
||||||
|
|
||||||
|
Q) Does gpSP run Gameboy/Gameboy Color games? Will it later?
|
||||||
|
|
||||||
|
A) No. Even though GBA can run these games it uses separate hardware
|
||||||
|
that proper GBA games have no access to (save for the audio chip),
|
||||||
|
and thus there's no point including it in a GBA emulator (it
|
||||||
|
doesn't help run GBA games). I recommend using a GB/GBC emulator
|
||||||
|
like Rin for playing these games. It'll probably give you a lot
|
||||||
|
more options anyway. gpSP will never actually emulate GB/GBC
|
||||||
|
games. You'd may as well be waiting for it to emulate PS2 games...
|
||||||
|
(that was an analogy. gpSP won't ever emulate PS2 games. >_>)
|
||||||
|
|
||||||
|
|
||||||
|
Q) Other emulators use the PSP's graphical hardware to accelerate the
|
||||||
|
video emulation. Is this possible for gpSP?
|
||||||
|
|
||||||
|
A) I'm honestly not too sure at this point. It's definitely a rather
|
||||||
|
complicated procedure, and I don't think it'll be possible to
|
||||||
|
accurately accelerate alpha blending. On the other hand, affine
|
||||||
|
transformations could perhaps receive a speed boost this way. Any
|
||||||
|
solution would have to be hybrid hardware/software, which might be
|
||||||
|
possible due to the nature of the PSP's VRAM. Maybe someone will
|
||||||
|
be willing to help me think of possibilities here?
|
||||||
|
|
||||||
|
But don't bother of you're just going to tell me to render a list
|
||||||
|
of quads...
|
||||||
|
|
||||||
|
|
||||||
|
Q) Other emulators use the PSP's second CPU to offload the sound
|
||||||
|
emulation. Is this possible for gpSP?
|
||||||
|
|
||||||
|
A) Yes, but it wouldn't improve it nearly as much as say, SNES9x TYL.
|
||||||
|
This is because most of the processing that goes into sound on a GBA
|
||||||
|
game is done in the CPU, not in dedicated audio hardware. It could
|
||||||
|
help a little, but probably not a lot. Maybe enough to be worthwhile.
|
||||||
|
It might also be possible to split the video rendering to the main
|
||||||
|
CPU and the main emulation to the secondary one, but there are a lot
|
||||||
|
of coherency issues involved.
|
||||||
|
|
||||||
|
|
||||||
|
Q) I heard gpSP can only load games 16MB or smaller in size. Is this
|
||||||
|
true? What about zipped games?
|
||||||
|
|
||||||
|
A) As of version 0.8 gpSP can play 32MB ROMs. However, they must be
|
||||||
|
unzipped. The reason for this is that parts of the ROM are constantly
|
||||||
|
loaded to memory as needed, and for this to be as fast as possible the
|
||||||
|
ROM has to be present on the memory stick in raw format.
|
||||||
|
|
||||||
|
You might be wondering, why not just have gpSP unzip the ROM to a file
|
||||||
|
then delete the file when it is done? The reason why is because this
|
||||||
|
would impose a "hidden" requirement of 32MB on the user that very
|
||||||
|
likely may not be there. Furthermore, there are only a few 32MB games
|
||||||
|
that anyone actually wants to play. If you only have one 32MB game on
|
||||||
|
your memstick then it'd actually require signifnicantly more free space
|
||||||
|
to hold both the ROM and the 32MB raw file. With 2 32MB ROMs you only
|
||||||
|
gain a around 10-25MB of free space, depending on how effective the
|
||||||
|
compression is.
|
||||||
|
|
||||||
|
|
||||||
|
Q) Savestates? From other emulators??
|
||||||
|
|
||||||
|
A) See the savestates option in main menu. gpSP will probably never
|
||||||
|
support savestates from other emulators, there's just too much in the
|
||||||
|
way of emulator specific data in them.
|
||||||
|
|
||||||
|
Savestates are currently 506,943 bytes. They would be a little smaller
|
||||||
|
without the snapshot, but I find that very useful and it wouldn't help
|
||||||
|
size immensely. Compression would help, but I wanted the size to be
|
||||||
|
constant so you knew exactly how much you could hold and to improve
|
||||||
|
save/load speed.
|
||||||
|
|
||||||
|
|
||||||
|
Q) What's with the zip support?
|
||||||
|
|
||||||
|
A) I hear stories that some games work unzipped and not zipped, so you
|
||||||
|
might want to try unzipping them if it gives you problems. You also
|
||||||
|
might want to try making fresh zips with WinRAR - users have
|
||||||
|
reported some higher success rates doing this.
|
||||||
|
|
||||||
|
|
||||||
|
Q) What's with the config file? Should I make it read only?
|
||||||
|
|
||||||
|
A) There was a bug in version 0.6 that caused the config file to not
|
||||||
|
get updated or get corrupted sometimes. Hopefully this is fixed now,
|
||||||
|
but if it DOES get corrupted making it read only can prevent this
|
||||||
|
from happening in the future.
|
||||||
|
|
||||||
|
|
||||||
|
Q) So when WILL the next version be released?
|
||||||
|
|
||||||
|
A) Sorry, but I almost never announce release dates. Furthermore, I'll
|
||||||
|
probably be pretty hush hush on internal development, just to keep
|
||||||
|
people from nagging me about it and building too much suspense.
|
||||||
|
|
||||||
|
|
||||||
|
Q) I don't like this emulator. Are there other alternatives?
|
||||||
|
|
||||||
|
A) Yes. Try PSPVBA by Zx-81 (http://zx81.dcemu.co.uk/). Overall I doubt
|
||||||
|
the compatability is significantly higher than gpSP's anymore, but
|
||||||
|
I'm sure there are some games it runs that gpSP doesn't.
|
||||||
|
|
||||||
|
|
||||||
|
Q) I heard there was a version of gpSP for PCs. Is that true?
|
||||||
|
|
||||||
|
A) I developed this emulator internally on PC. It might have a speed
|
||||||
|
advantage over other PC GBA emulators, although the PSP version has
|
||||||
|
more sophisticated optimizations. Most people have fast enough
|
||||||
|
computers to run better GBA emulators for PC and gpSP lacks some
|
||||||
|
important features (screen resizing) that the PSP version kinda
|
||||||
|
hides. Even though gpSP spent a majority of its development
|
||||||
|
gestation as a PC app it was always developed with the PSP in mind,
|
||||||
|
so the PC version will probably not see the light of the day unless
|
||||||
|
I get overwhelming demand for it. It is, however, possible to
|
||||||
|
build it from the source. But I request that you don't distribute
|
||||||
|
such builds. If you happen to find one, bear in mind that I don't
|
||||||
|
offer any support for it, and as far as I'm concerned it won't
|
||||||
|
exist.
|
||||||
|
|
||||||
|
|
||||||
|
Q) I hear there's a version of gpSP for other platforms too, like
|
||||||
|
Dreamcast. And I hear they're slow! What gives?
|
||||||
|
|
||||||
|
These are ports, done by other people (or maybe myself?). This is
|
||||||
|
possible because gpSP is open source and its base version is fairly
|
||||||
|
portable, but to run fast enough on anything but platforms quite a
|
||||||
|
bit faster than PSP it at least needs a CPU specific dynarec backend.
|
||||||
|
|
||||||
|
I don't (necessarily) maintain all builds of gpSP, so you'll have to
|
||||||
|
contact the authors of these ports for more information. That
|
||||||
|
notwithstanding, I try to get as involved in other ports of gpSP as
|
||||||
|
I can.
|
||||||
|
|
||||||
|
|
||||||
|
Q) I want to modify gpSP. How can I do this, and am I at liberty to do
|
||||||
|
so?
|
||||||
|
|
||||||
|
A) Yes, you are, under the terms of the GPL (see the included
|
||||||
|
COPYING.DOC). You can download the sourcecode from whereever you
|
||||||
|
downloaded this; if you can't find it please e-mail me and I'll give
|
||||||
|
you a link to it. I would vastly appreciate it if you contacted me first
|
||||||
|
before forking my project, especially if you're just looking to gain
|
||||||
|
recognition without adding much to it. It's better to keep all changes
|
||||||
|
tidy in one branch of development.
|
||||||
|
|
||||||
|
I would like to stress this a little more seriously (hopefully those
|
||||||
|
interested are reading this). Although you are legally entitled to
|
||||||
|
release your own forks of gpSP it would be much more benficial to me,
|
||||||
|
to you, and to the users of this program if you instead tried working
|
||||||
|
with me to get your changes incorporated into the next version. I
|
||||||
|
really don't feel like competing with other builds of my source
|
||||||
|
anymore, so please do me a big favor and send me an e-mail if you want
|
||||||
|
to work with gpSP.
|
||||||
|
|
||||||
|
|
||||||
|
Q) How do I build gpSP?
|
||||||
|
|
||||||
|
A) make will build it. You need to have SDL for PSP installed, as well
|
||||||
|
as the standard PSP toolchain/PSPSDK and zlib. gpSP isn't much of a
|
||||||
|
"build it yourself" program so please don't bother me much about how to
|
||||||
|
build it unless you have a good reason for wanting to do so.
|
||||||
|
|
||||||
|
|
||||||
|
Q) What is with the version numbers?
|
||||||
|
|
||||||
|
A) Anything less than 1.0 means beta. Beta means that I still have major
|
||||||
|
plans for working on it, and that I don't fully back it as being
|
||||||
|
stable or reliable software. Of course, if it does hit 1.0, that doesn't
|
||||||
|
mean it'll be perfect. It just means I'll have spent a lot of cumulative
|
||||||
|
time working things out. The closer it gets to 0.9, the happier I am with
|
||||||
|
it overall.
|
||||||
|
|
||||||
|
|
||||||
|
Q) Donations?
|
||||||
|
|
||||||
|
A) Very appreciated. exophase@gmail.com on PayPal. <3
|
||||||
|
|
||||||
|
|
||||||
|
Q) How can I contact you?
|
||||||
|
|
||||||
|
A) exophase@gmail.com, Exophase on AIM, exophase@adelphia.net on MSN. I
|
||||||
|
welcome IMs, but if you nag me a lot you'll make me sad inside. And
|
||||||
|
don't ask me for ROMs or the GBA BIOS. I figured this was common sense
|
||||||
|
but apparently not.
|
||||||
|
|
||||||
|
|
||||||
|
-- Credits --
|
||||||
|
|
||||||
|
Exophase: main developer
|
||||||
|
siberianSTAR: zip support
|
||||||
|
psp298: analog nub code
|
||||||
|
|
||||||
|
Beta testers for 0.7:
|
||||||
|
theohsoawesome1
|
||||||
|
thisnamesucks837
|
||||||
|
blackdragonwave9
|
||||||
|
dagreatpeewee
|
||||||
|
xsgenji
|
||||||
|
|
||||||
|
Beta testers for 0.8:
|
||||||
|
Runaway_prisoner
|
||||||
|
theohsoawesome1
|
||||||
|
tanyareimyoko
|
||||||
|
spynghotoh2020
|
||||||
|
|
||||||
|
Beta testers for 0.9:
|
||||||
|
RunawayPrisoner (my right hand man)
|
||||||
|
Veskgar (my left hand man)
|
||||||
|
qasim
|
||||||
|
|
||||||
|
-- Special thanks --
|
||||||
|
|
||||||
|
Quasar84: He's helped me in so many ways with this. We both kinda learned
|
||||||
|
GBA together, he did little demos for me and I got them emulated. It was
|
||||||
|
great trying out your more advanced code for your own projects once you
|
||||||
|
got to them, it was equally rewarding to see your work and to be able to
|
||||||
|
run it at the same time. Least of all I wouldn't have been able to do any
|
||||||
|
of this without your constant support and presence. I really owe this
|
||||||
|
release to you.
|
||||||
|
|
||||||
|
gladius: You are an amazing GBA coder. I wouldn't have been able to get
|
||||||
|
through some tough parts without your help. Its been good talking about
|
||||||
|
ideas with you.. I'm sure you're glad to see that there's finally a GBA
|
||||||
|
emulator with dynarec ;)
|
||||||
|
|
||||||
|
|
||||||
|
Many, many others of course, probably too many to name, and I don't want
|
||||||
|
to make anyone feel bad by putting others above them (well, except those
|
||||||
|
two, heh) so if you think you should be on here, you probably should be!
|
||||||
|
Just pretend you are for now, and maybe I'll put you here next time.
|
||||||
|
|
||||||
812
sound.c
Normal file
812
sound.c
Normal file
@ -0,0 +1,812 @@
|
|||||||
|
/* gameplaySP
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include <SDL.h>
|
||||||
|
u32 global_enable_audio = 1;
|
||||||
|
|
||||||
|
direct_sound_struct direct_sound_channel[2];
|
||||||
|
gbc_sound_struct gbc_sound_channel[4];
|
||||||
|
|
||||||
|
#if defined(GP2X_BUILD) || defined(TAVI_BUILD)
|
||||||
|
u32 sound_frequency = 44100;
|
||||||
|
#else
|
||||||
|
u32 sound_frequency = 44100;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_AudioSpec sound_settings;
|
||||||
|
SDL_mutex *sound_mutex;
|
||||||
|
SDL_cond *sound_cv;
|
||||||
|
|
||||||
|
#ifndef PSP_BUILD
|
||||||
|
u32 audio_buffer_size_number = 7;
|
||||||
|
#else
|
||||||
|
u32 audio_buffer_size_number = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
u32 audio_buffer_size;
|
||||||
|
u32 sound_on = 0;
|
||||||
|
s16 sound_buffer[BUFFER_SIZE];
|
||||||
|
u32 sound_buffer_base = 0;
|
||||||
|
|
||||||
|
u32 sound_last_cpu_ticks = 0;
|
||||||
|
fixed16_16 gbc_sound_tick_step;
|
||||||
|
|
||||||
|
// Queue 1, 2, or 4 samples to the top of the DS FIFO, wrap around circularly
|
||||||
|
|
||||||
|
#define sound_timer_queue(size, value) \
|
||||||
|
*((s##size *)(ds->fifo + ds->fifo_top)) = value; \
|
||||||
|
ds->fifo_top = (ds->fifo_top + 1) % 32; \
|
||||||
|
|
||||||
|
void sound_timer_queue8(u32 channel, u8 value)
|
||||||
|
{
|
||||||
|
direct_sound_struct *ds = direct_sound_channel + channel;
|
||||||
|
sound_timer_queue(8, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sound_timer_queue16(u32 channel, u16 value)
|
||||||
|
{
|
||||||
|
direct_sound_struct *ds = direct_sound_channel + channel;
|
||||||
|
sound_timer_queue(8, value & 0xFF);
|
||||||
|
sound_timer_queue(8, value >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sound_timer_queue32(u32 channel, u32 value)
|
||||||
|
{
|
||||||
|
direct_sound_struct *ds = direct_sound_channel + channel;
|
||||||
|
|
||||||
|
sound_timer_queue(8, value & 0xFF);
|
||||||
|
sound_timer_queue(8, (value >> 8) & 0xFF);
|
||||||
|
sound_timer_queue(8, (value >> 16) & 0xFF);
|
||||||
|
sound_timer_queue(8, value >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unqueue 1 sample from the base of the DS FIFO and place it on the audio
|
||||||
|
// buffer for as many samples as necessary. If the DS FIFO is 16 bytes or
|
||||||
|
// smaller and if DMA is enabled for the sound channel initiate a DMA transfer
|
||||||
|
// to the DS FIFO.
|
||||||
|
|
||||||
|
#define render_sample_null() \
|
||||||
|
|
||||||
|
#define render_sample_left() \
|
||||||
|
sound_buffer[buffer_index] += current_sample + \
|
||||||
|
fp16_16_to_u32((next_sample - current_sample) * fifo_fractional) \
|
||||||
|
|
||||||
|
#define render_sample_right() \
|
||||||
|
sound_buffer[buffer_index + 1] += current_sample + \
|
||||||
|
fp16_16_to_u32((next_sample - current_sample) * fifo_fractional) \
|
||||||
|
|
||||||
|
#define render_sample_both() \
|
||||||
|
dest_sample = current_sample + \
|
||||||
|
fp16_16_to_u32((next_sample - current_sample) * fifo_fractional); \
|
||||||
|
sound_buffer[buffer_index] += dest_sample; \
|
||||||
|
sound_buffer[buffer_index + 1] += dest_sample \
|
||||||
|
|
||||||
|
#define render_samples(type) \
|
||||||
|
while(fifo_fractional <= 0xFFFF) \
|
||||||
|
{ \
|
||||||
|
render_sample_##type(); \
|
||||||
|
fifo_fractional += frequency_step; \
|
||||||
|
buffer_index = (buffer_index + 2) % BUFFER_SIZE; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
void sound_timer(fixed16_16 frequency_step, u32 channel)
|
||||||
|
{
|
||||||
|
direct_sound_struct *ds = direct_sound_channel + channel;
|
||||||
|
|
||||||
|
fixed16_16 fifo_fractional = ds->fifo_fractional;
|
||||||
|
u32 buffer_index = ds->buffer_index;
|
||||||
|
s16 current_sample, next_sample, dest_sample;
|
||||||
|
|
||||||
|
current_sample = ds->fifo[ds->fifo_base] << 4;
|
||||||
|
ds->fifo_base = (ds->fifo_base + 1) % 32;
|
||||||
|
next_sample = ds->fifo[ds->fifo_base] << 4;
|
||||||
|
|
||||||
|
if(sound_on == 1)
|
||||||
|
{
|
||||||
|
if(ds->volume == DIRECT_SOUND_VOLUME_50)
|
||||||
|
{
|
||||||
|
current_sample >>= 1;
|
||||||
|
next_sample >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(ds->status)
|
||||||
|
{
|
||||||
|
case DIRECT_SOUND_INACTIVE:
|
||||||
|
render_samples(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DIRECT_SOUND_RIGHT:
|
||||||
|
render_samples(right);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DIRECT_SOUND_LEFT:
|
||||||
|
render_samples(left);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DIRECT_SOUND_LEFTRIGHT:
|
||||||
|
render_samples(both);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
render_samples(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
ds->buffer_index = buffer_index;
|
||||||
|
ds->fifo_fractional = fp16_16_fractional_part(fifo_fractional);
|
||||||
|
|
||||||
|
if(((ds->fifo_top - ds->fifo_base) % 32) <= 16)
|
||||||
|
{
|
||||||
|
if(dma[1].direct_sound_channel == channel)
|
||||||
|
dma_transfer(dma + 1);
|
||||||
|
|
||||||
|
if(dma[2].direct_sound_channel == channel)
|
||||||
|
dma_transfer(dma + 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sound_reset_fifo(u32 channel)
|
||||||
|
{
|
||||||
|
direct_sound_struct *ds = direct_sound_channel;
|
||||||
|
|
||||||
|
memset(ds->fifo, 0, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial pattern data = 4bits (signed)
|
||||||
|
// Channel volume = 12bits
|
||||||
|
// Envelope volume = 14bits
|
||||||
|
// Master volume = 2bits
|
||||||
|
|
||||||
|
// Recalculate left and right volume as volume changes.
|
||||||
|
// To calculate the current sample, use (sample * volume) >> 16
|
||||||
|
|
||||||
|
// Square waves range from -8 (low) to 7 (high)
|
||||||
|
|
||||||
|
s8 square_pattern_duty[4][8] =
|
||||||
|
{
|
||||||
|
{ 0xF8, 0xF8, 0xF8, 0xF8, 0x07, 0xF8, 0xF8, 0xF8 },
|
||||||
|
{ 0xF8, 0xF8, 0xF8, 0xF8, 0x07, 0x07, 0xF8, 0xF8 },
|
||||||
|
{ 0xF8, 0xF8, 0x07, 0x07, 0x07, 0x07, 0xF8, 0xF8 },
|
||||||
|
{ 0x07, 0x07, 0x07, 0x07, 0xF8, 0xF8, 0x07, 0x07 },
|
||||||
|
};
|
||||||
|
|
||||||
|
s8 wave_samples[64];
|
||||||
|
|
||||||
|
u32 noise_table15[1024];
|
||||||
|
u32 noise_table7[4];
|
||||||
|
|
||||||
|
u32 gbc_sound_master_volume_table[4] = { 1, 2, 4, 0 };
|
||||||
|
|
||||||
|
u32 gbc_sound_channel_volume_table[8] =
|
||||||
|
{
|
||||||
|
fixed_div(0, 7, 12),
|
||||||
|
fixed_div(1, 7, 12),
|
||||||
|
fixed_div(2, 7, 12),
|
||||||
|
fixed_div(3, 7, 12),
|
||||||
|
fixed_div(4, 7, 12),
|
||||||
|
fixed_div(5, 7, 12),
|
||||||
|
fixed_div(6, 7, 12),
|
||||||
|
fixed_div(7, 7, 12)
|
||||||
|
};
|
||||||
|
|
||||||
|
u32 gbc_sound_envelope_volume_table[16] =
|
||||||
|
{
|
||||||
|
fixed_div(0, 15, 14),
|
||||||
|
fixed_div(1, 15, 14),
|
||||||
|
fixed_div(2, 15, 14),
|
||||||
|
fixed_div(3, 15, 14),
|
||||||
|
fixed_div(4, 15, 14),
|
||||||
|
fixed_div(5, 15, 14),
|
||||||
|
fixed_div(6, 15, 14),
|
||||||
|
fixed_div(7, 15, 14),
|
||||||
|
fixed_div(8, 15, 14),
|
||||||
|
fixed_div(9, 15, 14),
|
||||||
|
fixed_div(10, 15, 14),
|
||||||
|
fixed_div(11, 15, 14),
|
||||||
|
fixed_div(12, 15, 14),
|
||||||
|
fixed_div(13, 15, 14),
|
||||||
|
fixed_div(14, 15, 14),
|
||||||
|
fixed_div(15, 15, 14)
|
||||||
|
};
|
||||||
|
|
||||||
|
u32 gbc_sound_buffer_index = 0;
|
||||||
|
u32 gbc_sound_last_cpu_ticks = 0;
|
||||||
|
u32 gbc_sound_partial_ticks = 0;
|
||||||
|
|
||||||
|
u32 gbc_sound_master_volume_left;
|
||||||
|
u32 gbc_sound_master_volume_right;
|
||||||
|
u32 gbc_sound_master_volume;
|
||||||
|
|
||||||
|
#define update_volume_channel_envelope(channel) \
|
||||||
|
volume_##channel = gbc_sound_envelope_volume_table[envelope_volume] * \
|
||||||
|
gbc_sound_channel_volume_table[gbc_sound_master_volume_##channel] * \
|
||||||
|
gbc_sound_master_volume_table[gbc_sound_master_volume] \
|
||||||
|
|
||||||
|
#define update_volume_channel_noenvelope(channel) \
|
||||||
|
volume_##channel = gs->wave_volume * \
|
||||||
|
gbc_sound_channel_volume_table[gbc_sound_master_volume_##channel] * \
|
||||||
|
gbc_sound_master_volume_table[gbc_sound_master_volume] \
|
||||||
|
|
||||||
|
#define update_volume(type) \
|
||||||
|
update_volume_channel_##type(left); \
|
||||||
|
update_volume_channel_##type(right) \
|
||||||
|
|
||||||
|
#define update_tone_sweep() \
|
||||||
|
if(gs->sweep_status) \
|
||||||
|
{ \
|
||||||
|
u32 sweep_ticks = gs->sweep_ticks - 1; \
|
||||||
|
\
|
||||||
|
if(sweep_ticks == 0) \
|
||||||
|
{ \
|
||||||
|
u32 rate = gs->rate; \
|
||||||
|
\
|
||||||
|
if(gs->sweep_direction) \
|
||||||
|
rate = rate - (rate >> gs->sweep_shift); \
|
||||||
|
else \
|
||||||
|
rate = rate + (rate >> gs->sweep_shift); \
|
||||||
|
\
|
||||||
|
if(rate > 2048) \
|
||||||
|
rate = 2048; \
|
||||||
|
\
|
||||||
|
frequency_step = float_to_fp16_16(((131072.0 / (2048 - rate)) * 8.0) / \
|
||||||
|
sound_frequency); \
|
||||||
|
\
|
||||||
|
gs->frequency_step = frequency_step; \
|
||||||
|
gs->rate = rate; \
|
||||||
|
\
|
||||||
|
sweep_ticks = gs->sweep_initial_ticks; \
|
||||||
|
} \
|
||||||
|
gs->sweep_ticks = sweep_ticks; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define update_tone_nosweep() \
|
||||||
|
|
||||||
|
#define update_tone_envelope() \
|
||||||
|
if(gs->envelope_status) \
|
||||||
|
{ \
|
||||||
|
u32 envelope_ticks = gs->envelope_ticks - 1; \
|
||||||
|
envelope_volume = gs->envelope_volume; \
|
||||||
|
\
|
||||||
|
if(envelope_ticks == 0) \
|
||||||
|
{ \
|
||||||
|
if(gs->envelope_direction) \
|
||||||
|
{ \
|
||||||
|
if(envelope_volume != 15) \
|
||||||
|
envelope_volume = gs->envelope_volume + 1; \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
if(envelope_volume != 0) \
|
||||||
|
envelope_volume = gs->envelope_volume - 1; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
update_volume(envelope); \
|
||||||
|
\
|
||||||
|
gs->envelope_volume = envelope_volume; \
|
||||||
|
gs->envelope_ticks = gs->envelope_initial_ticks; \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
gs->envelope_ticks = envelope_ticks; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define update_tone_noenvelope() \
|
||||||
|
|
||||||
|
#define gbc_sound_synchronize() \
|
||||||
|
while(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) > \
|
||||||
|
(audio_buffer_size * 2)) \
|
||||||
|
{ \
|
||||||
|
SDL_CondWait(sound_cv, sound_mutex); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define update_tone_counters(envelope_op, sweep_op) \
|
||||||
|
tick_counter += gbc_sound_tick_step; \
|
||||||
|
if(tick_counter > 0xFFFF) \
|
||||||
|
{ \
|
||||||
|
if(gs->length_status) \
|
||||||
|
{ \
|
||||||
|
u32 length_ticks = gs->length_ticks - 1; \
|
||||||
|
gs->length_ticks = length_ticks; \
|
||||||
|
\
|
||||||
|
if(length_ticks == 0) \
|
||||||
|
{ \
|
||||||
|
gs->active_flag = 0; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
update_tone_##envelope_op(); \
|
||||||
|
update_tone_##sweep_op(); \
|
||||||
|
\
|
||||||
|
tick_counter &= 0xFFFF; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define gbc_sound_render_sample_right() \
|
||||||
|
sound_buffer[buffer_index + 1] += (current_sample * volume_right) >> 22 \
|
||||||
|
|
||||||
|
#define gbc_sound_render_sample_left() \
|
||||||
|
sound_buffer[buffer_index] += (current_sample * volume_left) >> 22 \
|
||||||
|
|
||||||
|
#define gbc_sound_render_sample_both() \
|
||||||
|
gbc_sound_render_sample_right(); \
|
||||||
|
gbc_sound_render_sample_left() \
|
||||||
|
|
||||||
|
#define gbc_sound_render_samples(type, sample_length, envelope_op, sweep_op) \
|
||||||
|
for(i = 0; i < buffer_ticks; i++) \
|
||||||
|
{ \
|
||||||
|
current_sample = \
|
||||||
|
sample_data[fp16_16_to_u32(sample_index) % sample_length]; \
|
||||||
|
gbc_sound_render_sample_##type(); \
|
||||||
|
\
|
||||||
|
sample_index += frequency_step; \
|
||||||
|
buffer_index = (buffer_index + 2) % BUFFER_SIZE; \
|
||||||
|
\
|
||||||
|
update_tone_counters(envelope_op, sweep_op); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define gbc_noise_wrap_full 32767
|
||||||
|
|
||||||
|
#define gbc_noise_wrap_half 126
|
||||||
|
|
||||||
|
#define get_noise_sample_full() \
|
||||||
|
current_sample = \
|
||||||
|
((s32)(noise_table15[fp16_16_to_u32(sample_index) >> 5] << \
|
||||||
|
(fp16_16_to_u32(sample_index) & 0x1F)) >> 31) & 0x0F \
|
||||||
|
|
||||||
|
#define get_noise_sample_half() \
|
||||||
|
current_sample = \
|
||||||
|
((s32)(noise_table7[fp16_16_to_u32(sample_index) >> 5] << \
|
||||||
|
(fp16_16_to_u32(sample_index) & 0x1F)) >> 31) & 0x0F \
|
||||||
|
|
||||||
|
#define gbc_sound_render_noise(type, noise_type, envelope_op, sweep_op) \
|
||||||
|
for(i = 0; i < buffer_ticks; i++) \
|
||||||
|
{ \
|
||||||
|
get_noise_sample_##noise_type(); \
|
||||||
|
gbc_sound_render_sample_##type(); \
|
||||||
|
\
|
||||||
|
sample_index += frequency_step; \
|
||||||
|
\
|
||||||
|
if(sample_index >= u32_to_fp16_16(gbc_noise_wrap_##noise_type)) \
|
||||||
|
sample_index -= u32_to_fp16_16(gbc_noise_wrap_##noise_type); \
|
||||||
|
\
|
||||||
|
buffer_index = (buffer_index + 2) % BUFFER_SIZE; \
|
||||||
|
update_tone_counters(envelope_op, sweep_op); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define gbc_sound_render_channel(type, sample_length, envelope_op, sweep_op) \
|
||||||
|
buffer_index = gbc_sound_buffer_index; \
|
||||||
|
sample_index = gs->sample_index; \
|
||||||
|
frequency_step = gs->frequency_step; \
|
||||||
|
tick_counter = gs->tick_counter; \
|
||||||
|
\
|
||||||
|
update_volume(envelope_op); \
|
||||||
|
\
|
||||||
|
switch(gs->status) \
|
||||||
|
{ \
|
||||||
|
case GBC_SOUND_INACTIVE: \
|
||||||
|
break; \
|
||||||
|
\
|
||||||
|
case GBC_SOUND_LEFT: \
|
||||||
|
gbc_sound_render_##type(left, sample_length, envelope_op, sweep_op); \
|
||||||
|
break; \
|
||||||
|
\
|
||||||
|
case GBC_SOUND_RIGHT: \
|
||||||
|
gbc_sound_render_##type(right, sample_length, envelope_op, sweep_op); \
|
||||||
|
break; \
|
||||||
|
\
|
||||||
|
case GBC_SOUND_LEFTRIGHT: \
|
||||||
|
gbc_sound_render_##type(both, sample_length, envelope_op, sweep_op); \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
gs->sample_index = sample_index; \
|
||||||
|
gs->tick_counter = tick_counter; \
|
||||||
|
|
||||||
|
#define gbc_sound_load_wave_ram(bank) \
|
||||||
|
wave_bank = wave_samples + (bank * 32); \
|
||||||
|
for(i = 0, i2 = 0; i < 16; i++, i2 += 2) \
|
||||||
|
{ \
|
||||||
|
current_sample = wave_ram[i]; \
|
||||||
|
wave_bank[i2] = (((current_sample >> 4) & 0x0F) - 8); \
|
||||||
|
wave_bank[i2 + 1] = ((current_sample & 0x0F) - 8); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
void synchronize_sound()
|
||||||
|
{
|
||||||
|
SDL_LockMutex(sound_mutex);
|
||||||
|
|
||||||
|
gbc_sound_synchronize();
|
||||||
|
|
||||||
|
SDL_UnlockMutex(sound_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_gbc_sound(u32 cpu_ticks)
|
||||||
|
{
|
||||||
|
fixed16_16 buffer_ticks = float_to_fp16_16(((float)(cpu_ticks -
|
||||||
|
gbc_sound_last_cpu_ticks) * sound_frequency) / 16777216.0);
|
||||||
|
u32 i, i2;
|
||||||
|
gbc_sound_struct *gs = gbc_sound_channel;
|
||||||
|
fixed16_16 sample_index, frequency_step;
|
||||||
|
fixed16_16 tick_counter;
|
||||||
|
u32 buffer_index;
|
||||||
|
s32 volume_left, volume_right;
|
||||||
|
u32 envelope_volume;
|
||||||
|
s32 current_sample;
|
||||||
|
u32 sound_status = address16(io_registers, 0x84) & 0xFFF0;
|
||||||
|
s8 *sample_data;
|
||||||
|
s8 *wave_bank;
|
||||||
|
u8 *wave_ram = ((u8 *)io_registers) + 0x90;
|
||||||
|
|
||||||
|
gbc_sound_partial_ticks += fp16_16_fractional_part(buffer_ticks);
|
||||||
|
buffer_ticks = fp16_16_to_u32(buffer_ticks);
|
||||||
|
|
||||||
|
if(gbc_sound_partial_ticks > 0xFFFF)
|
||||||
|
{
|
||||||
|
buffer_ticks += 1;
|
||||||
|
gbc_sound_partial_ticks &= 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_LockMutex(sound_mutex);
|
||||||
|
if(synchronize_flag)
|
||||||
|
{
|
||||||
|
if(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) >
|
||||||
|
(audio_buffer_size * 3 / 2))
|
||||||
|
{
|
||||||
|
while(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) >
|
||||||
|
(audio_buffer_size * 3 / 2))
|
||||||
|
{
|
||||||
|
SDL_CondWait(sound_cv, sound_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PSP_BUILD
|
||||||
|
if(current_frameskip_type == auto_frameskip)
|
||||||
|
{
|
||||||
|
sceDisplayWaitVblankStart();
|
||||||
|
real_frame_count = 0;
|
||||||
|
virtual_frame_count = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
#ifdef GP2X_BUILD
|
||||||
|
if(current_frameskip_type == auto_frameskip)
|
||||||
|
{
|
||||||
|
u64 current_ticks;
|
||||||
|
u64 next_ticks;
|
||||||
|
get_ticks_us(¤t_ticks);
|
||||||
|
|
||||||
|
next_ticks = ((current_ticks + 16666) / 16667) * 16667;
|
||||||
|
delay_us(next_ticks - current_ticks);
|
||||||
|
|
||||||
|
get_ticks_us(&frame_count_initial_timestamp);
|
||||||
|
real_frame_count = 0;
|
||||||
|
virtual_frame_count = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(sound_on == 1)
|
||||||
|
{
|
||||||
|
gs = gbc_sound_channel + 0;
|
||||||
|
if(gs->active_flag)
|
||||||
|
{
|
||||||
|
sound_status |= 0x01;
|
||||||
|
sample_data = gs->sample_data;
|
||||||
|
envelope_volume = gs->envelope_volume;
|
||||||
|
gbc_sound_render_channel(samples, 8, envelope, sweep);
|
||||||
|
}
|
||||||
|
|
||||||
|
gs = gbc_sound_channel + 1;
|
||||||
|
if(gs->active_flag)
|
||||||
|
{
|
||||||
|
sound_status |= 0x02;
|
||||||
|
sample_data = gs->sample_data;
|
||||||
|
envelope_volume = gs->envelope_volume;
|
||||||
|
gbc_sound_render_channel(samples, 8, envelope, nosweep);
|
||||||
|
}
|
||||||
|
|
||||||
|
gs = gbc_sound_channel + 2;
|
||||||
|
if(gbc_sound_wave_update)
|
||||||
|
{
|
||||||
|
if(gs->wave_bank == 1)
|
||||||
|
{
|
||||||
|
gbc_sound_load_wave_ram(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gbc_sound_load_wave_ram(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
gbc_sound_wave_update = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((gs->active_flag) && (gs->master_enable))
|
||||||
|
{
|
||||||
|
sound_status |= 0x04;
|
||||||
|
sample_data = wave_samples;
|
||||||
|
if(gs->wave_type == 0)
|
||||||
|
{
|
||||||
|
if(gs->wave_bank == 1)
|
||||||
|
sample_data += 32;
|
||||||
|
|
||||||
|
gbc_sound_render_channel(samples, 32, noenvelope, nosweep);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gbc_sound_render_channel(samples, 64, noenvelope, nosweep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gs = gbc_sound_channel + 3;
|
||||||
|
if(gs->active_flag)
|
||||||
|
{
|
||||||
|
sound_status |= 0x08;
|
||||||
|
envelope_volume = gs->envelope_volume;
|
||||||
|
|
||||||
|
if(gs->noise_type == 1)
|
||||||
|
{
|
||||||
|
gbc_sound_render_channel(noise, half, envelope, nosweep);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gbc_sound_render_channel(noise, full, envelope, nosweep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
address16(io_registers, 0x84) = sound_status;
|
||||||
|
|
||||||
|
SDL_CondSignal(sound_cv);
|
||||||
|
|
||||||
|
SDL_UnlockMutex(sound_mutex);
|
||||||
|
|
||||||
|
gbc_sound_last_cpu_ticks = cpu_ticks;
|
||||||
|
gbc_sound_buffer_index =
|
||||||
|
(gbc_sound_buffer_index + (buffer_ticks * 2)) % BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define sound_copy_normal() \
|
||||||
|
current_sample = source[i] \
|
||||||
|
|
||||||
|
#define sound_copy(source_offset, length, render_type) \
|
||||||
|
_length = (length) / 2; \
|
||||||
|
source = (s16 *)(sound_buffer + source_offset); \
|
||||||
|
for(i = 0; i < _length; i++) \
|
||||||
|
{ \
|
||||||
|
sound_copy_##render_type(); \
|
||||||
|
if(current_sample > 2047) \
|
||||||
|
current_sample = 2047; \
|
||||||
|
if(current_sample < -2048) \
|
||||||
|
current_sample = -2048; \
|
||||||
|
\
|
||||||
|
stream_base[i] = current_sample << 4; \
|
||||||
|
source[i] = 0; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define sound_copy_null(source_offset, length) \
|
||||||
|
_length = (length) / 2; \
|
||||||
|
source = (s16 *)(sound_buffer + source_offset); \
|
||||||
|
for(i = 0; i < _length; i++) \
|
||||||
|
{ \
|
||||||
|
stream_base[i] = 0; \
|
||||||
|
source[i] = 0; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
|
||||||
|
void sound_callback(void *userdata, Uint8 *stream, int length)
|
||||||
|
{
|
||||||
|
u32 sample_length = length / 2;
|
||||||
|
u32 _length;
|
||||||
|
u32 i;
|
||||||
|
s16 *stream_base = (s16 *)stream;
|
||||||
|
s16 *source;
|
||||||
|
s32 current_sample;
|
||||||
|
|
||||||
|
SDL_LockMutex(sound_mutex);
|
||||||
|
|
||||||
|
while(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) <
|
||||||
|
length)
|
||||||
|
{
|
||||||
|
SDL_CondWait(sound_cv, sound_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(global_enable_audio)
|
||||||
|
{
|
||||||
|
if((sound_buffer_base + sample_length) >= BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
u32 partial_length = (BUFFER_SIZE - sound_buffer_base) * 2;
|
||||||
|
sound_copy(sound_buffer_base, partial_length, normal);
|
||||||
|
source = (s16 *)sound_buffer;
|
||||||
|
sound_copy(0, length - partial_length, normal);
|
||||||
|
sound_buffer_base = (length - partial_length) / 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sound_copy(sound_buffer_base, length, normal);
|
||||||
|
sound_buffer_base += sample_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if((sound_buffer_base + sample_length) >= BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
u32 partial_length = (BUFFER_SIZE - sound_buffer_base) * 2;
|
||||||
|
sound_copy_null(sound_buffer_base, partial_length);
|
||||||
|
source = (s16 *)sound_buffer;
|
||||||
|
sound_copy(0, length - partial_length, normal);
|
||||||
|
sound_buffer_base = (length - partial_length) / 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sound_copy_null(sound_buffer_base, length);
|
||||||
|
sound_buffer_base += sample_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_CondSignal(sound_cv);
|
||||||
|
|
||||||
|
SDL_UnlockMutex(sound_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special thanks to blarrg for the LSFR frequency used in Meridian, as posted
|
||||||
|
// on the forum at http://meridian.overclocked.org:
|
||||||
|
// http://meridian.overclocked.org/cgi-bin/wwwthreads/showpost.pl?Board=merid
|
||||||
|
// angeneraldiscussion&Number=2069&page=0&view=expanded&mode=threaded&sb=4
|
||||||
|
// Hope you don't mind me borrowing it ^_-
|
||||||
|
|
||||||
|
void init_noise_table(u32 *table, u32 period, u32 bit_length)
|
||||||
|
{
|
||||||
|
u32 shift_register = 0xFF;
|
||||||
|
u32 mask = ~(1 << bit_length);
|
||||||
|
s32 table_pos, bit_pos;
|
||||||
|
u32 current_entry;
|
||||||
|
u32 table_period = (period + 31) / 32;
|
||||||
|
|
||||||
|
// Bits are stored in reverse order so they can be more easily moved to
|
||||||
|
// bit 31, for sign extended shift down.
|
||||||
|
|
||||||
|
for(table_pos = 0; table_pos < table_period; table_pos++)
|
||||||
|
{
|
||||||
|
current_entry = 0;
|
||||||
|
for(bit_pos = 31; bit_pos >= 0; bit_pos--)
|
||||||
|
{
|
||||||
|
current_entry |= (shift_register & 0x01) << bit_pos;
|
||||||
|
|
||||||
|
shift_register =
|
||||||
|
((1 & (shift_register ^ (shift_register >> 1))) << bit_length) |
|
||||||
|
((shift_register >> 1) & mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
table[table_pos] = current_entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_sound()
|
||||||
|
{
|
||||||
|
direct_sound_struct *ds = direct_sound_channel;
|
||||||
|
gbc_sound_struct *gs = gbc_sound_channel;
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
sound_on = 0;
|
||||||
|
sound_buffer_base = 0;
|
||||||
|
sound_last_cpu_ticks = 0;
|
||||||
|
memset(sound_buffer, 0, audio_buffer_size);
|
||||||
|
|
||||||
|
for(i = 0; i < 2; i++, ds++)
|
||||||
|
{
|
||||||
|
ds->buffer_index = 0;
|
||||||
|
ds->status = DIRECT_SOUND_INACTIVE;
|
||||||
|
ds->fifo_top = 0;
|
||||||
|
ds->fifo_base = 0;
|
||||||
|
ds->fifo_fractional = 0;
|
||||||
|
ds->last_cpu_ticks = 0;
|
||||||
|
memset(ds->fifo, 0, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
gbc_sound_buffer_index = 0;
|
||||||
|
gbc_sound_last_cpu_ticks = 0;
|
||||||
|
gbc_sound_partial_ticks = 0;
|
||||||
|
|
||||||
|
gbc_sound_master_volume_left = 0;
|
||||||
|
gbc_sound_master_volume_right = 0;
|
||||||
|
gbc_sound_master_volume = 0;
|
||||||
|
memset(wave_samples, 0, 64);
|
||||||
|
|
||||||
|
for(i = 0; i < 4; i++, gs++)
|
||||||
|
{
|
||||||
|
gs->status = GBC_SOUND_INACTIVE;
|
||||||
|
gs->sample_data = square_pattern_duty[2];
|
||||||
|
gs->active_flag = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sound_exit()
|
||||||
|
{
|
||||||
|
gbc_sound_buffer_index =
|
||||||
|
(sound_buffer_base + audio_buffer_size) % BUFFER_SIZE;
|
||||||
|
SDL_PauseAudio(1);
|
||||||
|
SDL_CondSignal(sound_cv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_sound()
|
||||||
|
{
|
||||||
|
#ifdef PSP_BUILD
|
||||||
|
audio_buffer_size = (audio_buffer_size_number * 1024) + 3072;
|
||||||
|
#elif defined(TAVI_BUILD) || defined(ARM_ARCH)
|
||||||
|
audio_buffer_size = 16 << audio_buffer_size_number;
|
||||||
|
// audio_buffer_size = 16384;
|
||||||
|
#else
|
||||||
|
audio_buffer_size = 16384;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_AudioSpec desired_spec =
|
||||||
|
{
|
||||||
|
sound_frequency,
|
||||||
|
AUDIO_S16,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
audio_buffer_size / 4,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
sound_callback,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
gbc_sound_tick_step =
|
||||||
|
float_to_fp16_16(256.0 / sound_frequency);
|
||||||
|
|
||||||
|
init_noise_table(noise_table15, 32767, 14);
|
||||||
|
init_noise_table(noise_table7, 127, 6);
|
||||||
|
|
||||||
|
reset_sound();
|
||||||
|
|
||||||
|
SDL_OpenAudio(&desired_spec, &sound_settings);
|
||||||
|
sound_frequency = sound_settings.freq;
|
||||||
|
sound_mutex = SDL_CreateMutex();
|
||||||
|
sound_cv = SDL_CreateCond();
|
||||||
|
SDL_PauseAudio(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define sound_savestate_builder(type) \
|
||||||
|
void sound_##type##_savestate(file_tag_type savestate_file) \
|
||||||
|
{ \
|
||||||
|
file_##type##_variable(savestate_file, sound_on); \
|
||||||
|
file_##type##_variable(savestate_file, sound_buffer_base); \
|
||||||
|
file_##type##_variable(savestate_file, sound_last_cpu_ticks); \
|
||||||
|
file_##type##_variable(savestate_file, gbc_sound_buffer_index); \
|
||||||
|
file_##type##_variable(savestate_file, gbc_sound_last_cpu_ticks); \
|
||||||
|
file_##type##_variable(savestate_file, gbc_sound_partial_ticks); \
|
||||||
|
file_##type##_variable(savestate_file, gbc_sound_master_volume_left); \
|
||||||
|
file_##type##_variable(savestate_file, gbc_sound_master_volume_right); \
|
||||||
|
file_##type##_variable(savestate_file, gbc_sound_master_volume); \
|
||||||
|
file_##type##_array(savestate_file, wave_samples); \
|
||||||
|
file_##type##_array(savestate_file, direct_sound_channel); \
|
||||||
|
file_##type##_array(savestate_file, gbc_sound_channel); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
sound_savestate_builder(read);
|
||||||
|
sound_savestate_builder(write_mem);
|
||||||
|
|
||||||
328
sound.h
Normal file
328
sound.h
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
/* gameplaySP
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SOUND_H
|
||||||
|
#define SOUND_H
|
||||||
|
|
||||||
|
#define BUFFER_SIZE 65536
|
||||||
|
|
||||||
|
// A lot of sound cards on PC can't handle such small buffers but this
|
||||||
|
// seems to work well on PSP.
|
||||||
|
|
||||||
|
#ifdef PSP_BUILD
|
||||||
|
|
||||||
|
#define SOUND_BUFFER_SIZE 4096
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define SOUND_BUFFER_SIZE 16384
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DIRECT_SOUND_INACTIVE,
|
||||||
|
DIRECT_SOUND_RIGHT,
|
||||||
|
DIRECT_SOUND_LEFT,
|
||||||
|
DIRECT_SOUND_LEFTRIGHT
|
||||||
|
} direct_sound_status_type;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DIRECT_SOUND_VOLUME_50,
|
||||||
|
DIRECT_SOUND_VOLUME_100
|
||||||
|
} direct_sound_volume_type;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
s8 fifo[32];
|
||||||
|
u32 fifo_base;
|
||||||
|
u32 fifo_top;
|
||||||
|
fixed16_16 fifo_fractional;
|
||||||
|
// The + 1 is to give some extra room for linear interpolation
|
||||||
|
// when wrapping around.
|
||||||
|
u32 buffer_index;
|
||||||
|
direct_sound_status_type status;
|
||||||
|
direct_sound_volume_type volume;
|
||||||
|
u32 last_cpu_ticks;
|
||||||
|
} direct_sound_struct;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GBC_SOUND_INACTIVE,
|
||||||
|
GBC_SOUND_RIGHT,
|
||||||
|
GBC_SOUND_LEFT,
|
||||||
|
GBC_SOUND_LEFTRIGHT
|
||||||
|
} gbc_sound_status_type;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 rate;
|
||||||
|
fixed16_16 frequency_step;
|
||||||
|
fixed16_16 sample_index;
|
||||||
|
fixed16_16 tick_counter;
|
||||||
|
u32 total_volume;
|
||||||
|
u32 envelope_initial_volume;
|
||||||
|
u32 envelope_volume;
|
||||||
|
u32 envelope_direction;
|
||||||
|
u32 envelope_status;
|
||||||
|
u32 envelope_step;
|
||||||
|
u32 envelope_ticks;
|
||||||
|
u32 envelope_initial_ticks;
|
||||||
|
u32 sweep_status;
|
||||||
|
u32 sweep_direction;
|
||||||
|
u32 sweep_ticks;
|
||||||
|
u32 sweep_initial_ticks;
|
||||||
|
u32 sweep_shift;
|
||||||
|
u32 length_status;
|
||||||
|
u32 length_ticks;
|
||||||
|
u32 noise_type;
|
||||||
|
u32 wave_type;
|
||||||
|
u32 wave_bank;
|
||||||
|
u32 wave_volume;
|
||||||
|
gbc_sound_status_type status;
|
||||||
|
u32 active_flag;
|
||||||
|
u32 master_enable;
|
||||||
|
s8 *sample_data;
|
||||||
|
} gbc_sound_struct;
|
||||||
|
|
||||||
|
extern direct_sound_struct direct_sound_channel[2];
|
||||||
|
extern gbc_sound_struct gbc_sound_channel[4];
|
||||||
|
extern s8 square_pattern_duty[4][8];
|
||||||
|
extern u32 gbc_sound_master_volume_left;
|
||||||
|
extern u32 gbc_sound_master_volume_right;
|
||||||
|
extern u32 gbc_sound_master_volume;
|
||||||
|
|
||||||
|
extern u32 sound_frequency;
|
||||||
|
extern u32 sound_on;
|
||||||
|
|
||||||
|
extern u32 global_enable_audio;
|
||||||
|
extern u32 enable_low_pass_filter;
|
||||||
|
extern u32 audio_buffer_size_number;
|
||||||
|
|
||||||
|
extern SDL_mutex *sound_mutex;
|
||||||
|
extern SDL_cond *sound_cv;
|
||||||
|
|
||||||
|
void sound_timer_queue8(u32 channel, u8 value);
|
||||||
|
void sound_timer_queue16(u32 channel, u16 value);
|
||||||
|
void sound_timer_queue32(u32 channel, u32 value);
|
||||||
|
void sound_timer(fixed16_16 frequency_step, u32 channel);
|
||||||
|
void sound_reset_fifo(u32 channel);
|
||||||
|
void update_gbc_sound(u32 cpu_ticks);
|
||||||
|
void init_sound();
|
||||||
|
void sound_write_mem_savestate(file_tag_type savestate_file);
|
||||||
|
void sound_read_savestate(file_tag_type savestate_file);
|
||||||
|
|
||||||
|
#define gbc_sound_tone_control_low(channel, address) \
|
||||||
|
{ \
|
||||||
|
u32 initial_volume = (value >> 12) & 0x0F; \
|
||||||
|
u32 envelope_ticks = ((value >> 8) & 0x07) * 4; \
|
||||||
|
gbc_sound_channel[channel].length_ticks = 64 - (value & 0x3F); \
|
||||||
|
gbc_sound_channel[channel].sample_data = \
|
||||||
|
square_pattern_duty[(value >> 6) & 0x03]; \
|
||||||
|
gbc_sound_channel[channel].envelope_direction = (value >> 11) & 0x01; \
|
||||||
|
gbc_sound_channel[channel].envelope_initial_volume = initial_volume; \
|
||||||
|
gbc_sound_channel[channel].envelope_volume = initial_volume; \
|
||||||
|
gbc_sound_channel[channel].envelope_initial_ticks = envelope_ticks; \
|
||||||
|
gbc_sound_channel[channel].envelope_ticks = envelope_ticks; \
|
||||||
|
gbc_sound_channel[channel].envelope_status = (envelope_ticks != 0); \
|
||||||
|
gbc_sound_channel[channel].envelope_volume = initial_volume; \
|
||||||
|
gbc_sound_update = 1; \
|
||||||
|
address16(io_registers, address) = value; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define gbc_sound_tone_control_high(channel, address) \
|
||||||
|
{ \
|
||||||
|
u32 rate = value & 0x7FF; \
|
||||||
|
gbc_sound_channel[channel].rate = rate; \
|
||||||
|
gbc_sound_channel[channel].frequency_step = \
|
||||||
|
float_to_fp16_16(((131072.0 / (2048 - rate)) * 8.0) / sound_frequency); \
|
||||||
|
gbc_sound_channel[channel].length_status = (value >> 14) & 0x01; \
|
||||||
|
if(value & 0x8000) \
|
||||||
|
{ \
|
||||||
|
gbc_sound_channel[channel].active_flag = 1; \
|
||||||
|
gbc_sound_channel[channel].sample_index -= float_to_fp16_16(1.0 / 12.0); \
|
||||||
|
gbc_sound_channel[channel].envelope_ticks = \
|
||||||
|
gbc_sound_channel[channel].envelope_initial_ticks; \
|
||||||
|
gbc_sound_channel[channel].envelope_volume = \
|
||||||
|
gbc_sound_channel[channel].envelope_initial_volume; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
gbc_sound_update = 1; \
|
||||||
|
address16(io_registers, address) = value; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define gbc_sound_tone_control_sweep() \
|
||||||
|
{ \
|
||||||
|
u32 sweep_ticks = ((value >> 4) & 0x07) * 2; \
|
||||||
|
gbc_sound_channel[0].sweep_shift = value & 0x07; \
|
||||||
|
gbc_sound_channel[0].sweep_direction = (value >> 3) & 0x01; \
|
||||||
|
gbc_sound_channel[0].sweep_status = (value != 8); \
|
||||||
|
gbc_sound_channel[0].sweep_ticks = sweep_ticks; \
|
||||||
|
gbc_sound_channel[0].sweep_initial_ticks = sweep_ticks; \
|
||||||
|
gbc_sound_update = 1; \
|
||||||
|
address16(io_registers, 0x60) = value; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define gbc_sound_wave_control() \
|
||||||
|
{ \
|
||||||
|
gbc_sound_channel[2].wave_type = (value >> 5) & 0x01; \
|
||||||
|
gbc_sound_channel[2].wave_bank = (value >> 6) & 0x01; \
|
||||||
|
if(value & 0x80) \
|
||||||
|
{ \
|
||||||
|
gbc_sound_channel[2].master_enable = 1; \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
gbc_sound_channel[2].master_enable = 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
gbc_sound_update = 1; \
|
||||||
|
address16(io_registers, 0x70) = value; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
static u32 gbc_sound_wave_volume[4] = { 0, 16384, 8192, 4096 };
|
||||||
|
|
||||||
|
#define gbc_sound_tone_control_low_wave() \
|
||||||
|
{ \
|
||||||
|
gbc_sound_channel[2].length_ticks = 256 - (value & 0xFF); \
|
||||||
|
if((value >> 15) & 0x01) \
|
||||||
|
{ \
|
||||||
|
gbc_sound_channel[2].wave_volume = 12288; \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
gbc_sound_channel[2].wave_volume = \
|
||||||
|
gbc_sound_wave_volume[(value >> 13) & 0x03]; \
|
||||||
|
} \
|
||||||
|
gbc_sound_update = 1; \
|
||||||
|
address16(io_registers, 0x72) = value; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define gbc_sound_tone_control_high_wave() \
|
||||||
|
{ \
|
||||||
|
u32 rate = value & 0x7FF; \
|
||||||
|
gbc_sound_channel[2].rate = rate; \
|
||||||
|
gbc_sound_channel[2].frequency_step = \
|
||||||
|
float_to_fp16_16((2097152.0 / (2048 - rate)) / sound_frequency); \
|
||||||
|
gbc_sound_channel[2].length_status = (value >> 14) & 0x01; \
|
||||||
|
if(value & 0x8000) \
|
||||||
|
{ \
|
||||||
|
gbc_sound_channel[2].sample_index = 0; \
|
||||||
|
gbc_sound_channel[2].active_flag = 1; \
|
||||||
|
} \
|
||||||
|
gbc_sound_update = 1; \
|
||||||
|
address16(io_registers, 0x74) = value; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define gbc_sound_noise_control() \
|
||||||
|
{ \
|
||||||
|
u32 dividing_ratio = value & 0x07; \
|
||||||
|
u32 frequency_shift = (value >> 4) & 0x0F; \
|
||||||
|
if(dividing_ratio == 0) \
|
||||||
|
{ \
|
||||||
|
gbc_sound_channel[3].frequency_step = \
|
||||||
|
float_to_fp16_16(1048576.0 / (1 << (frequency_shift + 1)) / \
|
||||||
|
sound_frequency); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
gbc_sound_channel[3].frequency_step = \
|
||||||
|
float_to_fp16_16(524288.0 / (dividing_ratio * \
|
||||||
|
(1 << (frequency_shift + 1))) / sound_frequency); \
|
||||||
|
} \
|
||||||
|
gbc_sound_channel[3].noise_type = (value >> 3) & 0x01; \
|
||||||
|
gbc_sound_channel[3].length_status = (value >> 14) & 0x01; \
|
||||||
|
if(value & 0x8000) \
|
||||||
|
{ \
|
||||||
|
gbc_sound_channel[3].sample_index = 0; \
|
||||||
|
gbc_sound_channel[3].active_flag = 1; \
|
||||||
|
gbc_sound_channel[3].envelope_ticks = \
|
||||||
|
gbc_sound_channel[3].envelope_initial_ticks; \
|
||||||
|
gbc_sound_channel[3].envelope_volume = \
|
||||||
|
gbc_sound_channel[3].envelope_initial_volume; \
|
||||||
|
} \
|
||||||
|
gbc_sound_update = 1; \
|
||||||
|
address16(io_registers, 0x7C) = value; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define gbc_trigger_sound_channel(channel) \
|
||||||
|
gbc_sound_master_volume_right = value & 0x07; \
|
||||||
|
gbc_sound_master_volume_left = (value >> 4) & 0x07; \
|
||||||
|
gbc_sound_channel[channel].status = ((value >> (channel + 8)) & 0x01) | \
|
||||||
|
((value >> (channel + 11)) & 0x03) \
|
||||||
|
|
||||||
|
#define gbc_trigger_sound() \
|
||||||
|
{ \
|
||||||
|
gbc_trigger_sound_channel(0); \
|
||||||
|
gbc_trigger_sound_channel(1); \
|
||||||
|
gbc_trigger_sound_channel(2); \
|
||||||
|
gbc_trigger_sound_channel(3); \
|
||||||
|
address16(io_registers, 0x80) = value; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define trigger_sound() \
|
||||||
|
{ \
|
||||||
|
timer[0].direct_sound_channels = (((value >> 10) & 0x01) == 0) | \
|
||||||
|
((((value >> 14) & 0x01) == 0) << 1); \
|
||||||
|
timer[1].direct_sound_channels = (((value >> 10) & 0x01) == 1) | \
|
||||||
|
((((value >> 14) & 0x01) == 1) << 1); \
|
||||||
|
direct_sound_channel[0].volume = (value >> 2) & 0x01; \
|
||||||
|
direct_sound_channel[0].status = (value >> 8) & 0x03; \
|
||||||
|
direct_sound_channel[1].volume = (value >> 3) & 0x01; \
|
||||||
|
direct_sound_channel[1].status = (value >> 12) & 0x03; \
|
||||||
|
gbc_sound_master_volume = value & 0x03; \
|
||||||
|
\
|
||||||
|
if((value >> 11) & 0x01) \
|
||||||
|
sound_reset_fifo(0); \
|
||||||
|
if((value >> 15) & 0x01) \
|
||||||
|
sound_reset_fifo(1); \
|
||||||
|
address16(io_registers, 0x82) = value; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define sound_on() \
|
||||||
|
if(value & 0x80) \
|
||||||
|
{ \
|
||||||
|
if(sound_on != 1) \
|
||||||
|
{ \
|
||||||
|
sound_on = 1; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
u32 i; \
|
||||||
|
for(i = 0; i < 4; i++) \
|
||||||
|
{ \
|
||||||
|
gbc_sound_channel[i].active_flag = 0; \
|
||||||
|
} \
|
||||||
|
sound_on = 0; \
|
||||||
|
} \
|
||||||
|
address16(io_registers, 0x84) = \
|
||||||
|
(address16(io_registers, 0x84) & 0x000F) | (value & 0xFFF0); \
|
||||||
|
|
||||||
|
#define sound_update_frequency_step(timer_number) \
|
||||||
|
timer[timer_number].frequency_step = \
|
||||||
|
float_to_fp16_16(16777216.0 / (timer_reload * sound_frequency)) \
|
||||||
|
|
||||||
|
|
||||||
|
void reset_sound();
|
||||||
|
void sound_exit();
|
||||||
|
|
||||||
|
#endif
|
||||||
94
video.h
Normal file
94
video.h
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/* gameplaySP
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VIDEO_H
|
||||||
|
#define VIDEO_H
|
||||||
|
|
||||||
|
void update_scanline();
|
||||||
|
void update_screen();
|
||||||
|
void init_video();
|
||||||
|
void video_resolution_large();
|
||||||
|
void video_resolution_small();
|
||||||
|
void print_string(const char *str, u16 fg_color, u16 bg_color,
|
||||||
|
u32 x, u32 y);
|
||||||
|
void print_string_pad(const char *str, u16 fg_color, u16 bg_color,
|
||||||
|
u32 x, u32 y, u32 pad);
|
||||||
|
void print_string_ext(const char *str, u16 fg_color, u16 bg_color,
|
||||||
|
u32 x, u32 y, void *_dest_ptr, u32 pitch, u32 pad);
|
||||||
|
void clear_screen(u16 color);
|
||||||
|
void blit_to_screen(u16 *src, u32 w, u32 h, u32 x, u32 y);
|
||||||
|
u16 *copy_screen();
|
||||||
|
void flip_screen();
|
||||||
|
void video_write_mem_savestate(file_tag_type savestate_file);
|
||||||
|
void video_read_savestate(file_tag_type savestate_file);
|
||||||
|
|
||||||
|
void debug_screen_clear();
|
||||||
|
void debug_screen_start();
|
||||||
|
void debug_screen_end();
|
||||||
|
void debug_screen_printf(const char *format, ...);
|
||||||
|
void debug_screen_printl(const char *format, ...);
|
||||||
|
void debug_screen_newline(u32 count);
|
||||||
|
void debug_screen_update();
|
||||||
|
|
||||||
|
extern u32 frame_speed;
|
||||||
|
|
||||||
|
extern s32 affine_reference_x[2];
|
||||||
|
extern s32 affine_reference_y[2];
|
||||||
|
|
||||||
|
typedef void (* tile_render_function)(u32 layer_number, u32 start, u32 end,
|
||||||
|
void *dest_ptr);
|
||||||
|
typedef void (* bitmap_render_function)(u32 start, u32 end, void *dest_ptr);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
tile_render_function normal_render_base;
|
||||||
|
tile_render_function normal_render_transparent;
|
||||||
|
tile_render_function alpha_render_base;
|
||||||
|
tile_render_function alpha_render_transparent;
|
||||||
|
tile_render_function color16_render_base;
|
||||||
|
tile_render_function color16_render_transparent;
|
||||||
|
tile_render_function color32_render_base;
|
||||||
|
tile_render_function color32_render_transparent;
|
||||||
|
} tile_layer_render_struct;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
bitmap_render_function normal_render;
|
||||||
|
} bitmap_layer_render_struct;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
unscaled,
|
||||||
|
scaled_aspect,
|
||||||
|
fullscreen,
|
||||||
|
} video_scale_type;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
filter_nearest,
|
||||||
|
filter_bilinear
|
||||||
|
} video_filter_type;
|
||||||
|
|
||||||
|
extern video_scale_type screen_scale;
|
||||||
|
extern video_scale_type current_scale;
|
||||||
|
extern video_filter_type screen_filter;
|
||||||
|
|
||||||
|
void set_gba_resolution(video_scale_type scale);
|
||||||
|
|
||||||
|
#endif
|
||||||
38
x86/Makefile
Normal file
38
x86/Makefile
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# gpSP makefile
|
||||||
|
# Gilead Kutnick - Exophase
|
||||||
|
|
||||||
|
# Global definitions
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
STRIP = strip
|
||||||
|
AS = as
|
||||||
|
|
||||||
|
PREFIX = /usr
|
||||||
|
OBJS = main.o cpu.o memory.o video.o input.o sound.o \
|
||||||
|
cpu_threaded.o gui.o x86_stub.o cheats.o zip.o
|
||||||
|
BIN ?= gpsp.exe
|
||||||
|
|
||||||
|
# Platform specific definitions
|
||||||
|
|
||||||
|
VPATH += ..
|
||||||
|
CFLAGS += -DPC_BUILD
|
||||||
|
INCLUDES = -I${PREFIX}/include `sdl-config --cflags`
|
||||||
|
LIBS = -L${PREFIX}/lib `sdl-config --libs` -mconsole -lz
|
||||||
|
|
||||||
|
# Compilation:
|
||||||
|
|
||||||
|
.SUFFIXES: .c .S
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
${CC} ${CFLAGS} ${INCLUDES} -c -o $@ $<
|
||||||
|
|
||||||
|
%.o: %.S
|
||||||
|
${AS} -o $@ $<
|
||||||
|
|
||||||
|
all: ${OBJS}
|
||||||
|
${CC} ${OBJS} ${LIBS} -o ${BIN}
|
||||||
|
${STRIP} ${BIN}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o ${BIN}
|
||||||
|
|
||||||
2327
x86/x86_emit.h
Normal file
2327
x86/x86_emit.h
Normal file
File diff suppressed because it is too large
Load Diff
501
x86/x86_stub.S
Normal file
501
x86/x86_stub.S
Normal file
@ -0,0 +1,501 @@
|
|||||||
|
# gameplaySP
|
||||||
|
#
|
||||||
|
# Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 2 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
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
.global _x86_update_gba
|
||||||
|
.global _x86_indirect_branch_arm
|
||||||
|
.global _x86_indirect_branch_thumb
|
||||||
|
.global _x86_indirect_branch_dual
|
||||||
|
.global _execute_store_u8
|
||||||
|
.global _execute_store_u16
|
||||||
|
.global _execute_store_u32
|
||||||
|
.global _execute_store_cpsr
|
||||||
|
.global _execute_arm_translate
|
||||||
|
.global _step_debug_x86
|
||||||
|
|
||||||
|
.global _memory_map_read
|
||||||
|
.global _memory_map_write
|
||||||
|
.global _reg
|
||||||
|
|
||||||
|
.global _oam_update
|
||||||
|
|
||||||
|
.global _iwram
|
||||||
|
.global _ewram
|
||||||
|
.global _vram
|
||||||
|
.global _oam_ram
|
||||||
|
.global _bios_rom
|
||||||
|
.global _io_registers
|
||||||
|
|
||||||
|
.extern _spsr
|
||||||
|
|
||||||
|
.equ REG_SP, (13 * 4)
|
||||||
|
.equ REG_LR, (14 * 4)
|
||||||
|
.equ REG_PC, (15 * 4)
|
||||||
|
.equ REG_N_FLAG, (16 * 4)
|
||||||
|
.equ REG_Z_FLAG, (17 * 4)
|
||||||
|
.equ REG_C_FLAG, (18 * 4)
|
||||||
|
.equ REG_V_FLAG, (19 * 4)
|
||||||
|
.equ REG_CPSR, (20 * 4)
|
||||||
|
.equ REG_SAVE, (21 * 4)
|
||||||
|
.equ REG_SAVE2, (22 * 4)
|
||||||
|
.equ REG_SAVE3, (23 * 4)
|
||||||
|
.equ CPU_MODE, (29 * 4)
|
||||||
|
.equ CPU_HALT_STATE, (30 * 4)
|
||||||
|
.equ CHANGED_PC_STATUS, (31 * 4)
|
||||||
|
|
||||||
|
# destroys ecx and edx
|
||||||
|
|
||||||
|
.macro collapse_flag offset, shift
|
||||||
|
mov \offset(%ebx), %ecx
|
||||||
|
shl $\shift, %ecx
|
||||||
|
or %ecx, %edx
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro collapse_flags_no_update
|
||||||
|
xor %edx, %edx
|
||||||
|
collapse_flag REG_N_FLAG, 31
|
||||||
|
collapse_flag REG_Z_FLAG, 30
|
||||||
|
collapse_flag REG_C_FLAG, 29
|
||||||
|
collapse_flag REG_V_FLAG, 28
|
||||||
|
mov REG_CPSR(%ebx), %ecx
|
||||||
|
and $0xFF, %ecx
|
||||||
|
or %ecx, %edx
|
||||||
|
.endm
|
||||||
|
|
||||||
|
|
||||||
|
.macro collapse_flags
|
||||||
|
collapse_flags_no_update
|
||||||
|
mov %edx, REG_CPSR(%ebx)
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro extract_flag shift, offset
|
||||||
|
mov REG_CPSR(%ebx), %edx
|
||||||
|
shr $\shift, %edx
|
||||||
|
and $0x01, %edx
|
||||||
|
mov %edx, _reg + \offset
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro extract_flags
|
||||||
|
extract_flag 31, REG_N_FLAG
|
||||||
|
extract_flag 30, REG_Z_FLAG
|
||||||
|
extract_flag 29, REG_C_FLAG
|
||||||
|
extract_flag 28, REG_V_FLAG
|
||||||
|
.endm
|
||||||
|
|
||||||
|
# Process a hardware event. Since an interrupt might be
|
||||||
|
# raised we have to check if the PC has changed.
|
||||||
|
|
||||||
|
# eax: current address
|
||||||
|
|
||||||
|
st:
|
||||||
|
.asciz "u\n"
|
||||||
|
|
||||||
|
_x86_update_gba:
|
||||||
|
mov %eax, REG_PC(%ebx) # current PC = eax
|
||||||
|
collapse_flags # update cpsr, trashes ecx and edx
|
||||||
|
|
||||||
|
call _update_gba # process the next event
|
||||||
|
|
||||||
|
mov %eax, %edi # edi = new cycle count
|
||||||
|
# did the PC change?
|
||||||
|
cmpl $1, CHANGED_PC_STATUS(%ebx)
|
||||||
|
je lookup_pc
|
||||||
|
ret # if not, go back to caller
|
||||||
|
|
||||||
|
# Perform this on an indirect branch that will definitely go to
|
||||||
|
# ARM code, IE anything that changes the PC in ARM mode except
|
||||||
|
# for BX and data processing to PC with the S bit set.
|
||||||
|
|
||||||
|
# eax: GBA address to branch to
|
||||||
|
# edi: Cycle counter
|
||||||
|
|
||||||
|
_x86_indirect_branch_arm:
|
||||||
|
call _block_lookup_address_arm
|
||||||
|
jmp *%eax
|
||||||
|
|
||||||
|
# For indirect branches that'll definitely go to Thumb. In
|
||||||
|
# Thumb mode any indirect branches except for BX.
|
||||||
|
|
||||||
|
_x86_indirect_branch_thumb:
|
||||||
|
call _block_lookup_address_thumb
|
||||||
|
jmp *%eax
|
||||||
|
|
||||||
|
# For indirect branches that can go to either Thumb or ARM,
|
||||||
|
# mainly BX (also data processing to PC with S bit set, be
|
||||||
|
# sure to adjust the target with a 1 in the lowest bit for this)
|
||||||
|
|
||||||
|
_x86_indirect_branch_dual:
|
||||||
|
call _block_lookup_address_dual
|
||||||
|
jmp *%eax
|
||||||
|
|
||||||
|
|
||||||
|
# General ext memory routines
|
||||||
|
|
||||||
|
ext_store_ignore:
|
||||||
|
ret # ignore these writes
|
||||||
|
|
||||||
|
write_epilogue:
|
||||||
|
cmp $0, %eax # 0 return means nothing happened
|
||||||
|
jz no_alert # if so we can leave
|
||||||
|
|
||||||
|
collapse_flags # make sure flags are good for function call
|
||||||
|
cmp $2, %eax # see if it was an SMC trigger
|
||||||
|
je smc_write
|
||||||
|
|
||||||
|
alert_loop:
|
||||||
|
call _update_gba # process the next event
|
||||||
|
|
||||||
|
# see if the halt status has changed
|
||||||
|
mov CPU_HALT_STATE(%ebx), %edx
|
||||||
|
|
||||||
|
cmp $0, %edx # 0 means it has
|
||||||
|
jnz alert_loop # if not go again
|
||||||
|
|
||||||
|
mov %eax, %edi # edi = new cycle count
|
||||||
|
jmp lookup_pc # pc has definitely changed
|
||||||
|
|
||||||
|
no_alert:
|
||||||
|
ret
|
||||||
|
|
||||||
|
ext_store_eeprom:
|
||||||
|
jmp _write_eeprom # perform eeprom write
|
||||||
|
|
||||||
|
|
||||||
|
# 8bit ext memory routines
|
||||||
|
|
||||||
|
ext_store_io8:
|
||||||
|
and $0x3FF, %eax # wrap around address
|
||||||
|
and $0xFF, %edx
|
||||||
|
call _write_io_register8 # perform 8bit I/O register write
|
||||||
|
jmp write_epilogue # see if it requires any system update
|
||||||
|
|
||||||
|
ext_store_palette8:
|
||||||
|
and $0x3FE, %eax # wrap around address and align to 16bits
|
||||||
|
jmp ext_store_palette16b # perform 16bit palette write
|
||||||
|
|
||||||
|
ext_store_vram8:
|
||||||
|
and $0x1FFFE, %eax # wrap around address and align to 16bits
|
||||||
|
mov %dl, %dh # copy lower 8bits of value into full 16bits
|
||||||
|
cmp $0x18000, %eax # see if address is in upper region
|
||||||
|
jb ext_store_vram8b
|
||||||
|
sub $0x8000, %eax # if so wrap down
|
||||||
|
|
||||||
|
ext_store_vram8b:
|
||||||
|
mov %dx, _vram(%eax) # perform 16bit store
|
||||||
|
ret
|
||||||
|
|
||||||
|
ext_store_oam8:
|
||||||
|
movl $1, _oam_update # flag OAM update
|
||||||
|
and $0x3FE, %eax # wrap around address and align to 16bits
|
||||||
|
mov %dl, %dh # copy lower 8bits of value into full 16bits
|
||||||
|
mov %dx, _oam_ram(%eax) # perform 16bit store
|
||||||
|
ret
|
||||||
|
|
||||||
|
ext_store_backup:
|
||||||
|
and $0xFF, %edx # make value 8bit
|
||||||
|
and $0xFFFF, %eax # mask address
|
||||||
|
jmp _write_backup # perform backup write
|
||||||
|
|
||||||
|
ext_store_u8_jtable:
|
||||||
|
.long ext_store_ignore # 0x00 BIOS, ignore
|
||||||
|
.long ext_store_ignore # 0x01 invalid, ignore
|
||||||
|
.long ext_store_ignore # 0x02 EWRAM, should have been hit already
|
||||||
|
.long ext_store_ignore # 0x03 IWRAM, should have been hit already
|
||||||
|
.long ext_store_io8 # 0x04 I/O registers
|
||||||
|
.long ext_store_palette8 # 0x05 Palette RAM
|
||||||
|
.long ext_store_vram8 # 0x06 VRAM
|
||||||
|
.long ext_store_oam8 # 0x07 OAM RAM
|
||||||
|
.long ext_store_ignore # 0x08 gamepak (no RTC accepted in 8bit)
|
||||||
|
.long ext_store_ignore # 0x09 gamepak, ignore
|
||||||
|
.long ext_store_ignore # 0x0A gamepak, ignore
|
||||||
|
.long ext_store_ignore # 0x0B gamepak, ignore
|
||||||
|
.long ext_store_ignore # 0x0C gamepak, ignore
|
||||||
|
.long ext_store_eeprom # 0x0D EEPROM (possibly)
|
||||||
|
.long ext_store_backup # 0x0E Flash ROM/SRAM
|
||||||
|
|
||||||
|
ext_store_u8:
|
||||||
|
mov %eax, %ecx # ecx = address
|
||||||
|
shr $24, %ecx # ecx = address >> 24
|
||||||
|
cmp $15, %ecx
|
||||||
|
ja ext_store_ignore
|
||||||
|
# ecx = ext_store_u8_jtable[address >> 24]
|
||||||
|
mov ext_store_u8_jtable(, %ecx, 4), %ecx
|
||||||
|
jmp *%ecx # jump to table index
|
||||||
|
|
||||||
|
# eax: address to write to
|
||||||
|
# edx: value to write
|
||||||
|
# ecx: current pc
|
||||||
|
|
||||||
|
_execute_store_u8:
|
||||||
|
mov %ecx, REG_PC(%ebx) # write out the PC
|
||||||
|
mov %eax, %ecx # ecx = address
|
||||||
|
test $0xF0000000, %ecx # check address range
|
||||||
|
jnz ext_store_u8 # if above perform an extended write
|
||||||
|
shr $15, %ecx # ecx = page number of address
|
||||||
|
# load the corresponding memory map offset
|
||||||
|
mov _memory_map_write(, %ecx, 4), %ecx
|
||||||
|
test %ecx, %ecx # see if it's NULL
|
||||||
|
jz ext_store_u8 # if so perform an extended write
|
||||||
|
and $0x7FFF, %eax # isolate the lower 15bits of the address
|
||||||
|
mov %dl, (%eax, %ecx) # store the value
|
||||||
|
# check for self-modifying code
|
||||||
|
testb $0xFF, -32768(%eax, %ecx)
|
||||||
|
jne smc_write
|
||||||
|
ret # return
|
||||||
|
|
||||||
|
_execute_store_u16:
|
||||||
|
mov %ecx, REG_PC(%ebx) # write out the PC
|
||||||
|
and $~0x01, %eax # fix alignment
|
||||||
|
mov %eax, %ecx # ecx = address
|
||||||
|
test $0xF0000000, %ecx # check address range
|
||||||
|
jnz ext_store_u16 # if above perform an extended write
|
||||||
|
shr $15, %ecx # ecx = page number of address
|
||||||
|
# load the corresponding memory map offset
|
||||||
|
mov _memory_map_write(, %ecx, 4), %ecx
|
||||||
|
test %ecx, %ecx # see if it's NULL
|
||||||
|
jz ext_store_u16 # if so perform an extended write
|
||||||
|
and $0x7FFF, %eax # isolate the lower 15bits of the address
|
||||||
|
mov %dx, (%eax, %ecx) # store the value
|
||||||
|
# check for self-modifying code
|
||||||
|
testw $0xFFFF, -32768(%eax, %ecx)
|
||||||
|
jne smc_write
|
||||||
|
ret # return
|
||||||
|
|
||||||
|
# 16bit ext memory routines
|
||||||
|
|
||||||
|
ext_store_io16:
|
||||||
|
and $0x3FF, %eax # wrap around address
|
||||||
|
and $0xFFFF, %edx
|
||||||
|
call _write_io_register16 # perform 16bit I/O register write
|
||||||
|
jmp write_epilogue # see if it requires any system update
|
||||||
|
|
||||||
|
ext_store_palette16:
|
||||||
|
and $0x3FF, %eax # wrap around address
|
||||||
|
|
||||||
|
ext_store_palette16b: # entry point for 8bit write
|
||||||
|
mov %dx, _palette_ram(%eax) # write out palette value
|
||||||
|
mov %edx, %ecx # cx = dx
|
||||||
|
shl $11, %ecx # cx <<= 11 (red component is in high bits)
|
||||||
|
mov %dh, %cl # bottom bits of cx = top bits of dx
|
||||||
|
shr $2, %cl # move the blue component to the bottom of cl
|
||||||
|
and $0x03E0, %dx # isolate green component of dx
|
||||||
|
shl $1, %dx # make green component 6bits
|
||||||
|
or %edx, %ecx # combine green component into ecx
|
||||||
|
# write out the freshly converted palette value
|
||||||
|
mov %cx, _palette_ram_converted(%eax)
|
||||||
|
ret # done
|
||||||
|
|
||||||
|
ext_store_vram16:
|
||||||
|
and $0x1FFFF, %eax # wrap around address
|
||||||
|
cmp $0x18000, %eax # see if address is in upper region
|
||||||
|
jb ext_store_vram16b
|
||||||
|
sub $0x8000, %eax # if so wrap down
|
||||||
|
|
||||||
|
ext_store_vram16b:
|
||||||
|
mov %dx, _vram(%eax) # perform 16bit store
|
||||||
|
ret
|
||||||
|
|
||||||
|
ext_store_oam16:
|
||||||
|
movl $1, _oam_update # flag OAM update
|
||||||
|
and $0x3FF, %eax # wrap around address
|
||||||
|
mov %dx, _oam_ram(%eax) # perform 16bit store
|
||||||
|
ret
|
||||||
|
|
||||||
|
ext_store_rtc:
|
||||||
|
and $0xFFFF, %edx # make value 16bit
|
||||||
|
and $0xFF, %eax # mask address
|
||||||
|
jmp _write_rtc # write out RTC register
|
||||||
|
|
||||||
|
ext_store_u16_jtable:
|
||||||
|
.long ext_store_ignore # 0x00 BIOS, ignore
|
||||||
|
.long ext_store_ignore # 0x01 invalid, ignore
|
||||||
|
.long ext_store_ignore # 0x02 EWRAM, should have been hit already
|
||||||
|
.long ext_store_ignore # 0x03 IWRAM, should have been hit already
|
||||||
|
.long ext_store_io16 # 0x04 I/O registers
|
||||||
|
.long ext_store_palette16 # 0x05 Palette RAM
|
||||||
|
.long ext_store_vram16 # 0x06 VRAM
|
||||||
|
.long ext_store_oam16 # 0x07 OAM RAM
|
||||||
|
.long ext_store_rtc # 0x08 gamepak or RTC
|
||||||
|
.long ext_store_ignore # 0x09 gamepak, ignore
|
||||||
|
.long ext_store_ignore # 0x0A gamepak, ignore
|
||||||
|
.long ext_store_ignore # 0x0B gamepak, ignore
|
||||||
|
.long ext_store_ignore # 0x0C gamepak, ignore
|
||||||
|
.long ext_store_eeprom # 0x0D EEPROM (possibly)
|
||||||
|
.long ext_store_ignore # 0x0E Flash ROM/SRAM must be 8bit
|
||||||
|
|
||||||
|
ext_store_u16:
|
||||||
|
mov %eax, %ecx # ecx = address
|
||||||
|
shr $24, %ecx # ecx = address >> 24
|
||||||
|
cmp $15, %ecx
|
||||||
|
ja ext_store_ignore
|
||||||
|
# ecx = ext_store_u16_jtable[address >> 24]
|
||||||
|
mov ext_store_u16_jtable(, %ecx, 4), %ecx
|
||||||
|
jmp *%ecx # jump to table index
|
||||||
|
|
||||||
|
_execute_store_u32:
|
||||||
|
mov %ecx, REG_PC(%ebx) # write out the PC
|
||||||
|
and $~0x03, %eax # fix alignment
|
||||||
|
mov %eax, %ecx # ecx = address
|
||||||
|
test $0xF0000000, %ecx # check address range
|
||||||
|
jnz ext_store_u32 # if above perform an extended write
|
||||||
|
shr $15, %ecx # ecx = page number of address
|
||||||
|
# load the corresponding memory map offset
|
||||||
|
mov _memory_map_write(, %ecx, 4), %ecx
|
||||||
|
test %ecx, %ecx # see if it's NULL
|
||||||
|
jz ext_store_u32 # if so perform an extended write
|
||||||
|
and $0x7FFF, %eax # isolate the lower 15bits of the address
|
||||||
|
mov %edx, (%eax, %ecx) # store the value
|
||||||
|
# check for self-modifying code
|
||||||
|
testl $0xFFFFFFFF, -32768(%eax, %ecx)
|
||||||
|
jne smc_write
|
||||||
|
ret # return it
|
||||||
|
|
||||||
|
# 32bit ext memory routines
|
||||||
|
|
||||||
|
ext_store_io32:
|
||||||
|
and $0x3FF, %eax # wrap around address
|
||||||
|
call _write_io_register32 # perform 32bit I/O register write
|
||||||
|
jmp write_epilogue # see if it requires any system update
|
||||||
|
|
||||||
|
ext_store_palette32:
|
||||||
|
and $0x3FF, %eax # wrap around address
|
||||||
|
call ext_store_palette16b # write first 16bits
|
||||||
|
add $2, %eax # go to next address
|
||||||
|
shr $16, %edx # go to next 16bits
|
||||||
|
jmp ext_store_palette16b # write next 16bits
|
||||||
|
|
||||||
|
ext_store_vram32:
|
||||||
|
and $0x1FFFF, %eax # wrap around address
|
||||||
|
cmp $0x18000, %eax # see if address is in upper region
|
||||||
|
jb ext_store_vram32b
|
||||||
|
sub $0x8000, %eax # if so wrap down
|
||||||
|
|
||||||
|
ext_store_vram32b:
|
||||||
|
mov %edx, _vram(%eax) # perform 32bit store
|
||||||
|
ret
|
||||||
|
|
||||||
|
ext_store_oam32:
|
||||||
|
movl $1, _oam_update # flag OAM update
|
||||||
|
and $0x3FF, %eax # wrap around address
|
||||||
|
mov %edx, _oam_ram(%eax) # perform 32bit store
|
||||||
|
ret
|
||||||
|
|
||||||
|
ext_store_u32_jtable:
|
||||||
|
.long ext_store_ignore # 0x00 BIOS, ignore
|
||||||
|
.long ext_store_ignore # 0x01 invalid, ignore
|
||||||
|
.long ext_store_ignore # 0x02 EWRAM, should have been hit already
|
||||||
|
.long ext_store_ignore # 0x03 IWRAM, should have been hit already
|
||||||
|
.long ext_store_io32 # 0x04 I/O registers
|
||||||
|
.long ext_store_palette32 # 0x05 Palette RAM
|
||||||
|
.long ext_store_vram32 # 0x06 VRAM
|
||||||
|
.long ext_store_oam32 # 0x07 OAM RAM
|
||||||
|
.long ext_store_ignore # 0x08 gamepak, ignore (no RTC in 32bit)
|
||||||
|
.long ext_store_ignore # 0x09 gamepak, ignore
|
||||||
|
.long ext_store_ignore # 0x0A gamepak, ignore
|
||||||
|
.long ext_store_ignore # 0x0B gamepak, ignore
|
||||||
|
.long ext_store_ignore # 0x0C gamepak, ignore
|
||||||
|
.long ext_store_eeprom # 0x0D EEPROM (possibly)
|
||||||
|
.long ext_store_ignore # 0x0E Flash ROM/SRAM must be 8bit
|
||||||
|
|
||||||
|
|
||||||
|
ext_store_u32:
|
||||||
|
mov %eax, %ecx # ecx = address
|
||||||
|
shr $24, %ecx # ecx = address >> 24
|
||||||
|
cmp $15, %ecx
|
||||||
|
ja ext_store_ignore
|
||||||
|
# ecx = ext_store_u32_jtable[address >> 24]
|
||||||
|
mov ext_store_u32_jtable(, %ecx, 4), %ecx
|
||||||
|
jmp *%ecx
|
||||||
|
|
||||||
|
# %eax = new_cpsr
|
||||||
|
# %edx = store_mask
|
||||||
|
|
||||||
|
_execute_store_cpsr:
|
||||||
|
mov %edx, REG_SAVE(%ebx) # save store_mask
|
||||||
|
mov %ecx, REG_SAVE2(%ebx) # save PC too
|
||||||
|
|
||||||
|
mov %eax, %ecx # ecx = new_cpsr
|
||||||
|
and %edx, %ecx # ecx = new_cpsr & store_mask
|
||||||
|
mov REG_CPSR(%ebx), %eax # eax = cpsr
|
||||||
|
not %edx # edx = ~store_mask
|
||||||
|
and %edx, %eax # eax = cpsr & ~store_mask
|
||||||
|
or %ecx, %eax # eax = new cpsr combined with old
|
||||||
|
|
||||||
|
call _execute_store_cpsr_body # do the dirty work in this C function
|
||||||
|
|
||||||
|
extract_flags # pull out flag vars from new CPSR
|
||||||
|
|
||||||
|
cmp $0, %eax # see if return value is 0
|
||||||
|
jnz changed_pc_cpsr # might have changed the PC
|
||||||
|
|
||||||
|
ret # return
|
||||||
|
|
||||||
|
changed_pc_cpsr:
|
||||||
|
add $4, %esp # get rid of current return address
|
||||||
|
call _block_lookup_address_arm # lookup new PC
|
||||||
|
jmp *%eax
|
||||||
|
|
||||||
|
smc_write:
|
||||||
|
call _flush_translation_cache_ram
|
||||||
|
|
||||||
|
lookup_pc:
|
||||||
|
add $4, %esp
|
||||||
|
movl $0, CHANGED_PC_STATUS(%ebx)
|
||||||
|
mov REG_PC(%ebx), %eax
|
||||||
|
testl $0x20, REG_CPSR(%ebx)
|
||||||
|
jz lookup_pc_arm
|
||||||
|
|
||||||
|
lookup_pc_thumb:
|
||||||
|
call _block_lookup_address_thumb
|
||||||
|
jmp *%eax
|
||||||
|
|
||||||
|
lookup_pc_arm:
|
||||||
|
call _block_lookup_address_arm
|
||||||
|
jmp *%eax
|
||||||
|
|
||||||
|
# eax: cycle counter
|
||||||
|
|
||||||
|
_execute_arm_translate:
|
||||||
|
movl $_reg, %ebx # load base register
|
||||||
|
extract_flags # load flag variables
|
||||||
|
movl %eax, %edi # load edi cycle counter
|
||||||
|
|
||||||
|
movl REG_PC(%ebx), %eax # load PC
|
||||||
|
|
||||||
|
testl $0x20, REG_CPSR(%ebx)
|
||||||
|
jnz 1f
|
||||||
|
|
||||||
|
call _block_lookup_address_arm
|
||||||
|
jmp *%eax # jump to it
|
||||||
|
|
||||||
|
1:
|
||||||
|
call _block_lookup_address_thumb
|
||||||
|
jmp *%eax
|
||||||
|
|
||||||
|
_step_debug_x86:
|
||||||
|
collapse_flags
|
||||||
|
# mov $100, %edi
|
||||||
|
mov %edi, %edx
|
||||||
|
jmp _step_debug
|
||||||
|
|
||||||
|
.comm _memory_map_read 0x8000
|
||||||
|
.comm _memory_map_write 0x8000
|
||||||
|
.comm _reg 0x100
|
||||||
|
|
||||||
|
|
||||||
155
zip.c
Normal file
155
zip.c
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/* gameplaySP
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||||
|
* Copyright (C) 2006 SiberianSTAR
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zlib.h>
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define ZIP_BUFFER_SIZE (128 * 1024)
|
||||||
|
|
||||||
|
struct SZIPFileDataDescriptor
|
||||||
|
{
|
||||||
|
s32 CRC32;
|
||||||
|
s32 CompressedSize;
|
||||||
|
s32 UncompressedSize;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct SZIPFileHeader
|
||||||
|
{
|
||||||
|
char Sig[4]; // EDIT: Used to be s32 Sig;
|
||||||
|
s16 VersionToExtract;
|
||||||
|
s16 GeneralBitFlag;
|
||||||
|
s16 CompressionMethod;
|
||||||
|
s16 LastModFileTime;
|
||||||
|
s16 LastModFileDate;
|
||||||
|
struct SZIPFileDataDescriptor DataDescriptor;
|
||||||
|
s16 FilenameLength;
|
||||||
|
s16 ExtraFieldLength;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
u32 load_file_zip(char *filename)
|
||||||
|
{
|
||||||
|
struct SZIPFileHeader data;
|
||||||
|
u8 tmp[1024];
|
||||||
|
s32 retval = -1;
|
||||||
|
u8 *buffer = NULL;
|
||||||
|
u8 *cbuffer;
|
||||||
|
u8 *ext;
|
||||||
|
|
||||||
|
file_open(fd, filename, read);
|
||||||
|
|
||||||
|
if(!file_check_valid(fd))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
#if 0 // EDIT: Why this while(1) is used is unknown and can cause a crash.
|
||||||
|
while(1)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
file_read(fd, &data, sizeof(struct SZIPFileHeader));
|
||||||
|
|
||||||
|
// EDIT: Check if this is a zip file without worrying about endian
|
||||||
|
// It checks for the following: 0x50 0x4B 0x03 0x04 (PK..)
|
||||||
|
// Used to be: if(data.Sig != 0x04034b50) break;
|
||||||
|
if( data.Sig[0] != 0x50 || data.Sig[1] != 0x4B ||
|
||||||
|
data.Sig[2] != 0x03 || data.Sig[3] != 0x04 )
|
||||||
|
{
|
||||||
|
goto outcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_read(fd, tmp, data.FilenameLength);
|
||||||
|
tmp[data.FilenameLength] = 0; // end string
|
||||||
|
|
||||||
|
if(data.ExtraFieldLength)
|
||||||
|
file_seek(fd, data.ExtraFieldLength, SEEK_CUR);
|
||||||
|
|
||||||
|
if(data.GeneralBitFlag & 0x0008)
|
||||||
|
{
|
||||||
|
file_read(fd, &data.DataDescriptor,
|
||||||
|
sizeof(struct SZIPFileDataDescriptor));
|
||||||
|
}
|
||||||
|
|
||||||
|
ext = strrchr(tmp, '.') + 1;
|
||||||
|
|
||||||
|
// file is too big
|
||||||
|
if(data.DataDescriptor.UncompressedSize > gamepak_ram_buffer_size)
|
||||||
|
goto outcode;
|
||||||
|
|
||||||
|
if(!strcasecmp(ext, "bin") || !strcasecmp(ext, "gba"))
|
||||||
|
{
|
||||||
|
buffer = gamepak_rom;
|
||||||
|
|
||||||
|
// ok, found
|
||||||
|
switch(data.CompressionMethod)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
retval = data.DataDescriptor.UncompressedSize;
|
||||||
|
file_read(fd, buffer, retval);
|
||||||
|
|
||||||
|
goto outcode;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
z_stream stream;
|
||||||
|
s32 err;
|
||||||
|
|
||||||
|
cbuffer = malloc(ZIP_BUFFER_SIZE);
|
||||||
|
|
||||||
|
stream.next_in = (Bytef*)cbuffer;
|
||||||
|
stream.avail_in = (u32)ZIP_BUFFER_SIZE;
|
||||||
|
|
||||||
|
stream.next_out = (Bytef*)buffer;
|
||||||
|
|
||||||
|
// EDIT: Now uses proper conversion of data types for retval.
|
||||||
|
retval = (u32)data.DataDescriptor.UncompressedSize;
|
||||||
|
stream.avail_out = data.DataDescriptor.UncompressedSize;
|
||||||
|
|
||||||
|
stream.zalloc = (alloc_func)0;
|
||||||
|
stream.zfree = (free_func)0;
|
||||||
|
|
||||||
|
err = inflateInit2(&stream, -MAX_WBITS);
|
||||||
|
|
||||||
|
file_read(fd, cbuffer, ZIP_BUFFER_SIZE);
|
||||||
|
|
||||||
|
if(err == Z_OK)
|
||||||
|
{
|
||||||
|
while(err != Z_STREAM_END)
|
||||||
|
{
|
||||||
|
err = inflate(&stream, Z_SYNC_FLUSH);
|
||||||
|
if(err == Z_BUF_ERROR)
|
||||||
|
{
|
||||||
|
stream.avail_in = ZIP_BUFFER_SIZE;
|
||||||
|
stream.next_in = (Bytef*)cbuffer;
|
||||||
|
file_read(fd, cbuffer, ZIP_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = Z_OK;
|
||||||
|
inflateEnd(&stream);
|
||||||
|
}
|
||||||
|
free(cbuffer);
|
||||||
|
goto outcode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outcode:
|
||||||
|
file_close(fd);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
26
zip.h
Normal file
26
zip.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/* gameplaySP
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COMMON_H
|
||||||
|
#define COMMON_H
|
||||||
|
|
||||||
|
u32 load_file_zip(char *filename);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user