original source from gpsp09-2xb_src.tar.bz2
This commit is contained in:
commit
2823a4c819
|
@ -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.
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -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
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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:
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
void fallback(int argc, char *argv[]);
|
||||
void cmdhelp();
|
||||
void cmdline(int argc, char *argv[]);
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -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";
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
void prim();
|
||||
void ant();
|
||||
void speedtest(short test);
|
File diff suppressed because it is too large
Load Diff
|
@ -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 }
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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.
|
||||
|
|
@ -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);
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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…
Reference in New Issue