mirror of
https://github.com/libretro/gpsp.git
synced 2024-10-06 22:23:21 +00:00
original source from gpsp09-2xb_src.tar.bz2
This commit is contained in:
commit
2823a4c819
340
COPYING.DOC
Normal file
340
COPYING.DOC
Normal file
@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
11
build.txt
Normal file
11
build.txt
Normal file
@ -0,0 +1,11 @@
|
||||
How to build gpSP for PSP:
|
||||
|
||||
The makefile is in the psp directory, simply go there and type make.
|
||||
make kxploit will build for 1.5 firmware. Be sure to include
|
||||
game_config.txt and gpsp.cfg in the same directory as EBOOT.PBP, as
|
||||
well as gba_bios.bin (not included).
|
||||
|
||||
Dependencies as of v0.6:
|
||||
|
||||
SDL
|
||||
zlib
|
388
cheats.c
Normal file
388
cheats.c
Normal file
@ -0,0 +1,388 @@
|
||||
/* gameplaySP
|
||||
*
|
||||
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
cheat_type cheats[MAX_CHEATS];
|
||||
u32 num_cheats;
|
||||
|
||||
void decrypt_gsa_code(u32 *address_ptr, u32 *value_ptr, cheat_variant_enum
|
||||
cheat_variant)
|
||||
{
|
||||
u32 i, i2, code_position;
|
||||
u32 address = *address_ptr;
|
||||
u32 value = *value_ptr;
|
||||
u32 r = 0xc6ef3720;
|
||||
|
||||
u32 seeds_v1[4] =
|
||||
{
|
||||
0x09f4fbbd, 0x9681884a, 0x352027e9, 0xf3dee5a7
|
||||
};
|
||||
u32 seeds_v3[4] =
|
||||
{
|
||||
0x7aa9648f, 0x7fae6994, 0xc0efaad5, 0x42712c57
|
||||
};
|
||||
u32 *seeds;
|
||||
|
||||
if(cheat_variant == CHEAT_TYPE_GAMESHARK_V1)
|
||||
seeds = seeds_v1;
|
||||
else
|
||||
seeds = seeds_v3;
|
||||
|
||||
for(i = 0; i < 32; i++)
|
||||
{
|
||||
value -= ((address << 4) + seeds[2]) ^ (address + r) ^
|
||||
((address >> 5) + seeds[3]);
|
||||
address -= ((value << 4) + seeds[0]) ^ (value + r) ^
|
||||
((value >> 5) + seeds[1]);
|
||||
r -= 0x9e3779b9;
|
||||
}
|
||||
|
||||
*address_ptr = address;
|
||||
*value_ptr = value;
|
||||
}
|
||||
|
||||
void add_cheats(u8 *cheats_filename)
|
||||
{
|
||||
FILE *cheats_file;
|
||||
u8 current_line[256];
|
||||
u8 *name_ptr;
|
||||
u32 *cheat_code_ptr;
|
||||
u32 address, value;
|
||||
u32 num_cheat_lines;
|
||||
u32 cheat_name_length;
|
||||
cheat_variant_enum current_cheat_variant;
|
||||
|
||||
num_cheats = 0;
|
||||
|
||||
cheats_file = fopen(cheats_filename, "rb");
|
||||
|
||||
if(cheats_file)
|
||||
{
|
||||
while(fgets(current_line, 256, cheats_file))
|
||||
{
|
||||
// Get the header line first
|
||||
name_ptr = strchr(current_line, ' ');
|
||||
if(name_ptr)
|
||||
{
|
||||
*name_ptr = 0;
|
||||
name_ptr++;
|
||||
}
|
||||
|
||||
if(!strcasecmp(current_line, "gameshark_v1") ||
|
||||
!strcasecmp(current_line, "gameshark_v2") ||
|
||||
!strcasecmp(current_line, "PAR_v1") ||
|
||||
!strcasecmp(current_line, "PAR_v2"))
|
||||
{
|
||||
current_cheat_variant = CHEAT_TYPE_GAMESHARK_V1;
|
||||
}
|
||||
else
|
||||
|
||||
if(!strcasecmp(current_line, "gameshark_v3") ||
|
||||
!strcasecmp(current_line, "PAR_v3"))
|
||||
{
|
||||
current_cheat_variant = CHEAT_TYPE_GAMESHARK_V3;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_cheat_variant = CHEAT_TYPE_INVALID;
|
||||
}
|
||||
|
||||
if(current_cheat_variant != CHEAT_TYPE_INVALID)
|
||||
{
|
||||
strncpy(cheats[num_cheats].cheat_name, name_ptr, CHEAT_NAME_LENGTH - 1);
|
||||
cheats[num_cheats].cheat_name[CHEAT_NAME_LENGTH - 1] = 0;
|
||||
cheat_name_length = strlen(cheats[num_cheats].cheat_name);
|
||||
if(cheat_name_length &&
|
||||
(cheats[num_cheats].cheat_name[cheat_name_length - 1] == '\n') ||
|
||||
(cheats[num_cheats].cheat_name[cheat_name_length - 1] == '\r'))
|
||||
{
|
||||
cheats[num_cheats].cheat_name[cheat_name_length - 1] = 0;
|
||||
cheat_name_length--;
|
||||
}
|
||||
|
||||
if(cheat_name_length &&
|
||||
cheats[num_cheats].cheat_name[cheat_name_length - 1] == '\r')
|
||||
{
|
||||
cheats[num_cheats].cheat_name[cheat_name_length - 1] = 0;
|
||||
}
|
||||
|
||||
cheats[num_cheats].cheat_variant = current_cheat_variant;
|
||||
cheat_code_ptr = cheats[num_cheats].cheat_codes;
|
||||
num_cheat_lines = 0;
|
||||
|
||||
while(fgets(current_line, 256, cheats_file))
|
||||
{
|
||||
if(strlen(current_line) < 3)
|
||||
break;
|
||||
|
||||
sscanf(current_line, "%08x %08x", &address, &value);
|
||||
|
||||
decrypt_gsa_code(&address, &value, current_cheat_variant);
|
||||
|
||||
cheat_code_ptr[0] = address;
|
||||
cheat_code_ptr[1] = value;
|
||||
|
||||
cheat_code_ptr += 2;
|
||||
num_cheat_lines++;
|
||||
}
|
||||
|
||||
cheats[num_cheats].num_cheat_lines = num_cheat_lines;
|
||||
|
||||
num_cheats++;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(cheats_file);
|
||||
}
|
||||
}
|
||||
|
||||
void process_cheat_gs1(cheat_type *cheat)
|
||||
{
|
||||
u32 cheat_opcode;
|
||||
u32 *code_ptr = cheat->cheat_codes;
|
||||
u32 address, value;
|
||||
u32 i;
|
||||
|
||||
for(i = 0; i < cheat->num_cheat_lines; i++)
|
||||
{
|
||||
address = code_ptr[0];
|
||||
value = code_ptr[1];
|
||||
|
||||
code_ptr += 2;
|
||||
|
||||
cheat_opcode = address >> 28;
|
||||
address &= 0xFFFFFFF;
|
||||
|
||||
switch(cheat_opcode)
|
||||
{
|
||||
case 0x0:
|
||||
write_memory8(address, value);
|
||||
break;
|
||||
|
||||
case 0x1:
|
||||
write_memory16(address, value);
|
||||
break;
|
||||
|
||||
case 0x2:
|
||||
write_memory32(address, value);
|
||||
break;
|
||||
|
||||
case 0x3:
|
||||
{
|
||||
u32 num_addresses = address & 0xFFFF;
|
||||
u32 address1, address2;
|
||||
u32 i2;
|
||||
|
||||
for(i2 = 0; i2 < num_addresses; i2++)
|
||||
{
|
||||
address1 = code_ptr[0];
|
||||
address2 = code_ptr[1];
|
||||
code_ptr += 2;
|
||||
i++;
|
||||
|
||||
write_memory32(address1, value);
|
||||
if(address2 != 0)
|
||||
write_memory32(address2, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// ROM patch not supported yet
|
||||
case 0x6:
|
||||
break;
|
||||
|
||||
// GS button down not supported yet
|
||||
case 0x8:
|
||||
break;
|
||||
|
||||
// Reencryption (DEADFACE) not supported yet
|
||||
case 0xD:
|
||||
if(read_memory16(address) != (value & 0xFFFF))
|
||||
{
|
||||
code_ptr += 2;
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE:
|
||||
if(read_memory16(value & 0xFFFFFFF) != (address & 0xFFFF))
|
||||
{
|
||||
u32 skip = ((address >> 16) & 0x03);
|
||||
code_ptr += skip * 2;
|
||||
i += skip;
|
||||
}
|
||||
break;
|
||||
|
||||
// Hook routine not supported yet (not important??)
|
||||
case 0x0F:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// These are especially incomplete.
|
||||
|
||||
void process_cheat_gs3(cheat_type *cheat)
|
||||
{
|
||||
u32 cheat_opcode;
|
||||
u32 *code_ptr = cheat->cheat_codes;
|
||||
u32 address, value;
|
||||
u32 i;
|
||||
|
||||
for(i = 0; i < cheat->num_cheat_lines; i++)
|
||||
{
|
||||
address = code_ptr[0];
|
||||
value = code_ptr[1];
|
||||
|
||||
code_ptr += 2;
|
||||
|
||||
cheat_opcode = address >> 28;
|
||||
address &= 0xFFFFFFF;
|
||||
|
||||
switch(cheat_opcode)
|
||||
{
|
||||
case 0x0:
|
||||
cheat_opcode = address >> 24;
|
||||
address = (address & 0xFFFFF) + ((address << 4) & 0xF000000);
|
||||
|
||||
switch(cheat_opcode)
|
||||
{
|
||||
case 0x0:
|
||||
{
|
||||
u32 iterations = value >> 24;
|
||||
u32 i2;
|
||||
|
||||
value &= 0xFF;
|
||||
|
||||
for(i2 = 0; i2 <= iterations; i2++, address++)
|
||||
{
|
||||
write_memory8(address, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x2:
|
||||
{
|
||||
u32 iterations = value >> 16;
|
||||
u32 i2;
|
||||
|
||||
value &= 0xFFFF;
|
||||
|
||||
for(i2 = 0; i2 <= iterations; i2++, address += 2)
|
||||
{
|
||||
write_memory16(address, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x4:
|
||||
write_memory32(address, value);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x4:
|
||||
cheat_opcode = address >> 24;
|
||||
address = (address & 0xFFFFF) + ((address << 4) & 0xF000000);
|
||||
|
||||
switch(cheat_opcode)
|
||||
{
|
||||
case 0x0:
|
||||
address = read_memory32(address) + (value >> 24);
|
||||
write_memory8(address, value & 0xFF);
|
||||
break;
|
||||
|
||||
case 0x2:
|
||||
address = read_memory32(address) + ((value >> 16) * 2);
|
||||
write_memory16(address, value & 0xFFFF);
|
||||
break;
|
||||
|
||||
case 0x4:
|
||||
address = read_memory32(address);
|
||||
write_memory32(address, value);
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x8:
|
||||
cheat_opcode = address >> 24;
|
||||
address = (address & 0xFFFFF) + ((address << 4) & 0xF000000);
|
||||
|
||||
switch(cheat_opcode)
|
||||
{
|
||||
case 0x0:
|
||||
value = (value & 0xFF) + read_memory8(address);
|
||||
write_memory8(address, value);
|
||||
break;
|
||||
|
||||
case 0x2:
|
||||
value = (value & 0xFFFF) + read_memory16(address);
|
||||
write_memory16(address, value);
|
||||
break;
|
||||
|
||||
case 0x4:
|
||||
value = value + read_memory32(address);
|
||||
write_memory32(address, value);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC:
|
||||
cheat_opcode = address >> 24;
|
||||
address = (address & 0xFFFFFF) + 0x4000000;
|
||||
|
||||
switch(cheat_opcode)
|
||||
{
|
||||
case 0x6:
|
||||
write_memory16(address, value);
|
||||
break;
|
||||
|
||||
case 0x7:
|
||||
write_memory32(address, value);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void process_cheats()
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for(i = 0; i < num_cheats; i++)
|
||||
{
|
||||
if(cheats[i].cheat_active)
|
||||
{
|
||||
switch(cheats[i].cheat_variant)
|
||||
{
|
||||
case CHEAT_TYPE_GAMESHARK_V1:
|
||||
process_cheat_gs1(cheats + i);
|
||||
break;
|
||||
|
||||
case CHEAT_TYPE_GAMESHARK_V3:
|
||||
process_cheat_gs3(cheats + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
44
cheats.h
Normal file
44
cheats.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* gameplaySP
|
||||
*
|
||||
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define CHEAT_NAME_LENGTH 17
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CHEAT_TYPE_GAMESHARK_V1,
|
||||
CHEAT_TYPE_GAMESHARK_V3,
|
||||
CHEAT_TYPE_INVALID
|
||||
} cheat_variant_enum;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 cheat_name[CHEAT_NAME_LENGTH];
|
||||
u32 cheat_active;
|
||||
u32 cheat_codes[256];
|
||||
u32 num_cheat_lines;
|
||||
cheat_variant_enum cheat_variant;
|
||||
} cheat_type;
|
||||
|
||||
void process_cheats();
|
||||
void add_cheats(u8 *cheats_filename);
|
||||
|
||||
#define MAX_CHEATS 16
|
||||
|
||||
extern cheat_type cheats[MAX_CHEATS];
|
||||
extern u32 num_cheats;
|
276
common.h
Normal file
276
common.h
Normal file
@ -0,0 +1,276 @@
|
||||
/* gameplaySP
|
||||
*
|
||||
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#define ror(dest, value, shift) \
|
||||
dest = ((value) >> shift) | ((value) << (32 - shift)) \
|
||||
|
||||
// These includes must be used before SDL is included.
|
||||
#ifdef ARM_ARCH
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#endif /* _WIN32_WCE */
|
||||
|
||||
#ifdef GIZ_BUILD
|
||||
#include "giz/giz.h"
|
||||
#endif
|
||||
#endif /* ARM_ARCH */
|
||||
|
||||
// Huge thanks to pollux for the heads up on using native file I/O
|
||||
// functions on PSP for vastly improved memstick performance.
|
||||
|
||||
#define file_write_mem(filename_tag, buffer, size) \
|
||||
{ \
|
||||
memcpy(write_mem_ptr, buffer, size); \
|
||||
write_mem_ptr += size; \
|
||||
} \
|
||||
|
||||
#define file_write_mem_array(filename_tag, array) \
|
||||
file_write_mem(filename_tag, array, sizeof(array)) \
|
||||
|
||||
#define file_write_mem_variable(filename_tag, variable) \
|
||||
file_write_mem(filename_tag, &variable, sizeof(variable)) \
|
||||
|
||||
#ifdef PSP_BUILD
|
||||
#define fastcall
|
||||
|
||||
#include <pspkernel.h>
|
||||
#include <pspdebug.h>
|
||||
#include <pspctrl.h>
|
||||
#include <pspgu.h>
|
||||
#include <pspaudio.h>
|
||||
#include <pspaudiolib.h>
|
||||
#include <psprtc.h>
|
||||
|
||||
#define function_cc
|
||||
|
||||
#define convert_palette(value) \
|
||||
value = ((value & 0x7FE0) << 1) | (value & 0x1F) \
|
||||
|
||||
#define psp_file_open_read PSP_O_RDONLY
|
||||
#define psp_file_open_write (PSP_O_CREAT | PSP_O_WRONLY | PSP_O_TRUNC)
|
||||
|
||||
#define file_open(filename_tag, filename, mode) \
|
||||
s32 filename_tag = sceIoOpen(filename, psp_file_open_##mode, 0777) \
|
||||
|
||||
#define file_check_valid(filename_tag) \
|
||||
(filename_tag >= 0) \
|
||||
|
||||
#define file_close(filename_tag) \
|
||||
sceIoClose(filename_tag) \
|
||||
|
||||
#define file_read(filename_tag, buffer, size) \
|
||||
sceIoRead(filename_tag, buffer, size) \
|
||||
|
||||
#define file_write(filename_tag, buffer, size) \
|
||||
sceIoWrite(filename_tag, buffer, size) \
|
||||
|
||||
#define file_seek(filename_tag, offset, type) \
|
||||
sceIoLseek(filename_tag, offset, PSP_##type) \
|
||||
|
||||
#define file_tag_type s32
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#else
|
||||
#include "SDL.h"
|
||||
|
||||
#ifdef ARM_ARCH
|
||||
#define function_cc
|
||||
#else
|
||||
#define function_cc __attribute__((regparm(2)))
|
||||
#endif
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef signed char s8;
|
||||
typedef unsigned short int u16;
|
||||
typedef signed short int s16;
|
||||
typedef unsigned long u32;
|
||||
typedef signed long s32;
|
||||
typedef unsigned long long int u64;
|
||||
typedef signed long long int s64;
|
||||
|
||||
#define convert_palette(value) \
|
||||
value = ((value & 0x1F) << 11) | ((value & 0x03E0) << 1) | (value >> 10) \
|
||||
|
||||
#define stdio_file_open_read "rb"
|
||||
#define stdio_file_open_write "wb"
|
||||
|
||||
#define file_open(filename_tag, filename, mode) \
|
||||
FILE *filename_tag = fopen(filename, stdio_file_open_##mode) \
|
||||
|
||||
#define file_check_valid(filename_tag) \
|
||||
(filename_tag) \
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
|
||||
#define file_close(filename_tag) \
|
||||
{ \
|
||||
sync(); \
|
||||
fclose(filename_tag); \
|
||||
} \
|
||||
|
||||
#else
|
||||
|
||||
#define file_close(filename_tag) \
|
||||
fclose(filename_tag) \
|
||||
|
||||
#endif
|
||||
|
||||
#define file_read(filename_tag, buffer, size) \
|
||||
fread(buffer, size, 1, filename_tag) \
|
||||
|
||||
#define file_write(filename_tag, buffer, size) \
|
||||
fwrite(buffer, size, 1, filename_tag) \
|
||||
|
||||
#define file_seek(filename_tag, offset, type) \
|
||||
fseek(filename_tag, offset, type) \
|
||||
|
||||
#define file_tag_type FILE *
|
||||
|
||||
// The ARM arch uses SDL, and SDL requires you to know what resolution
|
||||
// you want. Define the resolution for ARM arch builds here.
|
||||
// Placed in common.h for use with video.c and gui.c.
|
||||
|
||||
#ifndef PC_BUILD
|
||||
|
||||
#define GP2X_SCREEN_WIDTH 320
|
||||
#define GP2X_SCREEN_HEIGHT 240
|
||||
|
||||
#define GIZ_SCREEN_WIDTH 320
|
||||
#define GIZ_SCREEN_HEIGHT 240
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
#define SDL_SCREEN_WIDTH GP2X_SCREEN_WIDTH
|
||||
#define SDL_SCREEN_HEIGHT GP2X_SCREEN_HEIGHT
|
||||
|
||||
#elif defined(GIZ_BUILD)
|
||||
|
||||
#define SDL_SCREEN_WIDTH GIZ_SCREEN_WIDTH
|
||||
#define SDL_SCREEN_HEIGHT GIZ_SCREEN_HEIGHT
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// These must be variables, not constants.
|
||||
|
||||
#define file_read_variable(filename_tag, variable) \
|
||||
file_read(filename_tag, &variable, sizeof(variable)) \
|
||||
|
||||
#define file_write_variable(filename_tag, variable) \
|
||||
file_write(filename_tag, &variable, sizeof(variable)) \
|
||||
|
||||
// These must be statically declared arrays (ie, global or on the stack,
|
||||
// not dynamically allocated on the heap)
|
||||
|
||||
#define file_read_array(filename_tag, array) \
|
||||
file_read(filename_tag, array, sizeof(array)) \
|
||||
|
||||
#define file_write_array(filename_tag, array) \
|
||||
file_write(filename_tag, array, sizeof(array)) \
|
||||
|
||||
|
||||
|
||||
typedef u32 fixed16_16;
|
||||
|
||||
#define float_to_fp16_16(value) \
|
||||
(fixed16_16)((value) * 65536.0) \
|
||||
|
||||
#define fp16_16_to_float(value) \
|
||||
(float)((value) / 65536.0) \
|
||||
|
||||
#define u32_to_fp16_16(value) \
|
||||
((value) << 16) \
|
||||
|
||||
#define fp16_16_to_u32(value) \
|
||||
((value) >> 16) \
|
||||
|
||||
#define fp16_16_fractional_part(value) \
|
||||
((value) & 0xFFFF) \
|
||||
|
||||
#define fixed_div(numerator, denominator, bits) \
|
||||
(((numerator * (1 << bits)) + (denominator / 2)) / denominator) \
|
||||
|
||||
#define address8(base, offset) \
|
||||
*((u8 *)((u8 *)base + (offset))) \
|
||||
|
||||
#define address16(base, offset) \
|
||||
*((u16 *)((u8 *)base + (offset))) \
|
||||
|
||||
#define address32(base, offset) \
|
||||
*((u32 *)((u8 *)base + (offset))) \
|
||||
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include "SDL.h"
|
||||
#include "cpu.h"
|
||||
#include "memory.h"
|
||||
#include "video.h"
|
||||
#include "input.h"
|
||||
#include "sound.h"
|
||||
#include "main.h"
|
||||
#include "gui.h"
|
||||
#include "zip.h"
|
||||
#include "cheats.h"
|
||||
|
||||
|
||||
#ifdef PSP_BUILD
|
||||
#define printf pspDebugScreenPrintf
|
||||
#endif
|
||||
|
||||
#ifdef PC_BUILD
|
||||
#define STDIO_DEBUG
|
||||
//#define REGISTER_USAGE_ANALYZE
|
||||
#endif
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
#include <strings.h>
|
||||
#include "gp2x/gp2x.h"
|
||||
|
||||
#define printf(format, ...) \
|
||||
fprintf(stderr, format, ##__VA_ARGS__) \
|
||||
|
||||
#define vprintf(format, ap) \
|
||||
vfprintf(stderr, format, ap) \
|
||||
|
||||
void gp2x_overclock(void);
|
||||
|
||||
// #define STDIO_DEBUG
|
||||
#endif
|
||||
|
||||
#endif
|
210
cpu.h
Normal file
210
cpu.h
Normal file
@ -0,0 +1,210 @@
|
||||
/* gameplaySP
|
||||
*
|
||||
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef CPU_H
|
||||
#define CPU_H
|
||||
|
||||
// System mode and user mode are represented as the same here
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MODE_USER,
|
||||
MODE_IRQ,
|
||||
MODE_FIQ,
|
||||
MODE_SUPERVISOR,
|
||||
MODE_ABORT,
|
||||
MODE_UNDEFINED,
|
||||
MODE_INVALID
|
||||
} cpu_mode_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CPU_ALERT_NONE,
|
||||
CPU_ALERT_HALT,
|
||||
CPU_ALERT_SMC,
|
||||
CPU_ALERT_IRQ
|
||||
} cpu_alert_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CPU_ACTIVE,
|
||||
CPU_HALT,
|
||||
CPU_STOP
|
||||
} cpu_halt_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IRQ_NONE = 0x0000,
|
||||
IRQ_VBLANK = 0x0001,
|
||||
IRQ_HBLANK = 0x0002,
|
||||
IRQ_VCOUNT = 0x0004,
|
||||
IRQ_TIMER0 = 0x0008,
|
||||
IRQ_TIMER1 = 0x0010,
|
||||
IRQ_TIMER2 = 0x0020,
|
||||
IRQ_TIMER3 = 0x0040,
|
||||
IRQ_SERIAL = 0x0080,
|
||||
IRQ_DMA0 = 0x0100,
|
||||
IRQ_DMA1 = 0x0200,
|
||||
IRQ_DMA2 = 0x0400,
|
||||
IRQ_DMA3 = 0x0800,
|
||||
IRQ_KEYPAD = 0x1000,
|
||||
IRQ_GAMEPAK = 0x2000,
|
||||
} irq_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
REG_SP = 13,
|
||||
REG_LR = 14,
|
||||
REG_PC = 15,
|
||||
REG_N_FLAG = 16,
|
||||
REG_Z_FLAG = 17,
|
||||
REG_C_FLAG = 18,
|
||||
REG_V_FLAG = 19,
|
||||
REG_CPSR = 20,
|
||||
REG_SAVE = 21,
|
||||
REG_SAVE2 = 22,
|
||||
REG_SAVE3 = 23,
|
||||
CPU_MODE = 29,
|
||||
CPU_HALT_STATE = 30,
|
||||
CHANGED_PC_STATUS = 31
|
||||
} ext_reg_numbers;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STEP,
|
||||
PC_BREAKPOINT,
|
||||
VCOUNT_BREAKPOINT,
|
||||
Z_BREAKPOINT,
|
||||
COUNTDOWN_BREAKPOINT,
|
||||
COUNTDOWN_BREAKPOINT_B,
|
||||
COUNTDOWN_BREAKPOINT_C,
|
||||
STEP_RUN,
|
||||
RUN
|
||||
} debug_state;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TRANSLATION_REGION_RAM,
|
||||
TRANSLATION_REGION_ROM,
|
||||
TRANSLATION_REGION_BIOS
|
||||
} translation_region_type;
|
||||
|
||||
extern debug_state current_debug_state;
|
||||
extern u32 instruction_count;
|
||||
extern u32 last_instruction;
|
||||
|
||||
u32 function_cc step_debug(u32 pc, u32 cycles);
|
||||
u32 execute_arm(u32 cycles);
|
||||
void raise_interrupt(irq_type irq_raised);
|
||||
|
||||
u32 function_cc execute_load_u8(u32 address);
|
||||
u32 function_cc execute_load_u16(u32 address);
|
||||
u32 function_cc execute_load_u32(u32 address);
|
||||
u32 function_cc execute_load_s8(u32 address);
|
||||
u32 function_cc execute_load_s16(u32 address);
|
||||
void function_cc execute_store_u8(u32 address, u32 source);
|
||||
void function_cc execute_store_u16(u32 address, u32 source);
|
||||
void function_cc execute_store_u32(u32 address, u32 source);
|
||||
u32 function_cc execute_arm_translate(u32 cycles);
|
||||
void init_translater();
|
||||
void cpu_write_mem_savestate(file_tag_type savestate_file);
|
||||
void cpu_read_savestate(file_tag_type savestate_file);
|
||||
|
||||
u8 function_cc *block_lookup_address_arm(u32 pc);
|
||||
u8 function_cc *block_lookup_address_thumb(u32 pc);
|
||||
s32 translate_block_arm(u32 pc, translation_region_type translation_region,
|
||||
u32 smc_enable);
|
||||
s32 translate_block_thumb(u32 pc, translation_region_type translation_region,
|
||||
u32 smc_enable);
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
#define ROM_TRANSLATION_CACHE_SIZE (1024 * 512 * 4 * 5)
|
||||
#define RAM_TRANSLATION_CACHE_SIZE (1024 * 384 * 2)
|
||||
#define BIOS_TRANSLATION_CACHE_SIZE (1024 * 128 * 2)
|
||||
#define TRANSLATION_CACHE_LIMIT_THRESHOLD (1024 * 32)
|
||||
|
||||
#else
|
||||
|
||||
#define ROM_TRANSLATION_CACHE_SIZE (1024 * 512 * 4)
|
||||
#define RAM_TRANSLATION_CACHE_SIZE (1024 * 384)
|
||||
#define BIOS_TRANSLATION_CACHE_SIZE (1024 * 128)
|
||||
#define TRANSLATION_CACHE_LIMIT_THRESHOLD (1024)
|
||||
|
||||
#endif
|
||||
|
||||
extern u8 rom_translation_cache[ROM_TRANSLATION_CACHE_SIZE];
|
||||
extern u8 ram_translation_cache[RAM_TRANSLATION_CACHE_SIZE];
|
||||
extern u8 bios_translation_cache[BIOS_TRANSLATION_CACHE_SIZE];
|
||||
extern u8 *rom_translation_ptr;
|
||||
extern u8 *ram_translation_ptr;
|
||||
extern u8 *bios_translation_ptr;
|
||||
|
||||
#define MAX_TRANSLATION_GATES 8
|
||||
|
||||
extern u32 idle_loop_target_pc;
|
||||
extern u32 force_pc_update_target;
|
||||
extern u32 iwram_stack_optimize;
|
||||
extern u32 allow_smc_ram_u8;
|
||||
extern u32 allow_smc_ram_u16;
|
||||
extern u32 allow_smc_ram_u32;
|
||||
extern u32 direct_map_vram;
|
||||
extern u32 translation_gate_targets;
|
||||
extern u32 translation_gate_target_pc[MAX_TRANSLATION_GATES];
|
||||
|
||||
extern u32 in_interrupt;
|
||||
|
||||
#define ROM_BRANCH_HASH_SIZE (1024 * 64)
|
||||
|
||||
/* EDIT: Shouldn't this be extern ?! */
|
||||
extern u32 *rom_branch_hash[ROM_BRANCH_HASH_SIZE];
|
||||
|
||||
void flush_translation_cache_rom();
|
||||
void flush_translation_cache_ram();
|
||||
void flush_translation_cache_bios();
|
||||
void dump_translation_cache();
|
||||
|
||||
extern u32 reg_mode[7][7];
|
||||
extern u32 spsr[6];
|
||||
|
||||
extern u32 cpu_modes[32];
|
||||
extern const u32 psr_masks[16];
|
||||
|
||||
extern u32 breakpoint_value;
|
||||
|
||||
extern u32 memory_region_access_read_u8[16];
|
||||
extern u32 memory_region_access_read_s8[16];
|
||||
extern u32 memory_region_access_read_u16[16];
|
||||
extern u32 memory_region_access_read_s16[16];
|
||||
extern u32 memory_region_access_read_u32[16];
|
||||
extern u32 memory_region_access_write_u8[16];
|
||||
extern u32 memory_region_access_write_u16[16];
|
||||
extern u32 memory_region_access_write_u32[16];
|
||||
extern u32 memory_reads_u8;
|
||||
extern u32 memory_reads_s8;
|
||||
extern u32 memory_reads_u16;
|
||||
extern u32 memory_reads_s16;
|
||||
extern u32 memory_reads_u32;
|
||||
extern u32 memory_writes_u8;
|
||||
extern u32 memory_writes_u16;
|
||||
extern u32 memory_writes_u32;
|
||||
|
||||
void init_cpu();
|
||||
void move_reg();
|
||||
|
||||
#endif
|
3508
cpu_threaded.c
Normal file
3508
cpu_threaded.c
Normal file
File diff suppressed because it is too large
Load Diff
184
disasm.c
Normal file
184
disasm.c
Normal file
@ -0,0 +1,184 @@
|
||||
/* gameplaySP
|
||||
*
|
||||
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#define arm_decode_data_proc_reg() \
|
||||
u32 rn = (opcode >> 16) & 0x0F; \
|
||||
u32 rd = (opcode >> 12) & 0x0F; \
|
||||
u32 rm = opcode & 0x0F \
|
||||
|
||||
#define arm_decode_data_proc_imm() \
|
||||
u32 rn = (opcode >> 16) & 0x0F; \
|
||||
u32 rd = (opcode >> 12) & 0x0F; \
|
||||
u32 imm; \
|
||||
ror(imm, opcode & 0xFF, ((opcode >> 8) & 0x0F) * 2) \
|
||||
|
||||
#define arm_decode_psr_reg() \
|
||||
u32 psr_field = (opcode >> 16) & 0x0F; \
|
||||
u32 rd = (opcode >> 12) & 0x0F; \
|
||||
u32 rm = opcode & 0x0F \
|
||||
|
||||
#define arm_decode_psr_imm() \
|
||||
u32 psr_field = (opcode >> 16) & 0x0F; \
|
||||
u32 rd = (opcode >> 12) & 0x0F; \
|
||||
u32 imm; \
|
||||
ror(imm, opcode & 0xFF, ((opcode >> 8) & 0x0F) * 2) \
|
||||
|
||||
#define arm_decode_branchx() \
|
||||
u32 rn = opcode & 0x0F \
|
||||
|
||||
#define arm_decode_multiply() \
|
||||
u32 rd = (opcode >> 16) & 0x0F; \
|
||||
u32 rn = (opcode >> 12) & 0x0F; \
|
||||
u32 rs = (opcode >> 8) & 0x0F; \
|
||||
u32 rm = opcode & 0x0F \
|
||||
|
||||
#define arm_decode_multiply_long() \
|
||||
u32 rdhi = (opcode >> 16) & 0x0F; \
|
||||
u32 rdlo = (opcode >> 12) & 0x0F; \
|
||||
u32 rn = (opcode >> 8) & 0x0F; \
|
||||
u32 rm = opcode & 0x0F \
|
||||
|
||||
#define arm_decode_swap() \
|
||||
u32 rn = (opcode >> 16) & 0x0F; \
|
||||
u32 rd = (opcode >> 12) & 0x0F; \
|
||||
u32 rm = opcode & 0x0F \
|
||||
|
||||
#define arm_decode_half_trans_r() \
|
||||
u32 rn = (opcode >> 16) & 0x0F; \
|
||||
u32 rd = (opcode >> 12) & 0x0F; \
|
||||
u32 rm = opcode & 0x0F \
|
||||
|
||||
#define arm_decode_half_trans_of() \
|
||||
u32 rn = (opcode >> 16) & 0x0F; \
|
||||
u32 rd = (opcode >> 12) & 0x0F; \
|
||||
u32 offset = ((opcode >> 4) & 0xF0) | (opcode & 0x0F) \
|
||||
|
||||
#define arm_decode_data_trans_imm() \
|
||||
u32 rn = (opcode >> 16) & 0x0F; \
|
||||
u32 rd = (opcode >> 12) & 0x0F; \
|
||||
u32 offset = opcode & 0x0FFF \
|
||||
|
||||
#define arm_decode_data_trans_reg() \
|
||||
u32 rn = (opcode >> 16) & 0x0F; \
|
||||
u32 rd = (opcode >> 12) & 0x0F; \
|
||||
u32 rm = opcode & 0x0F \
|
||||
|
||||
#define arm_decode_block_trans() \
|
||||
u32 rn = (opcode >> 16) & 0x0F; \
|
||||
u32 reg_list = opcode & 0xFFFF \
|
||||
|
||||
#define arm_decode_branch() \
|
||||
s32 offset = ((s32)(opcode & 0xFFFFFF) << 8) >> 6 \
|
||||
|
||||
#define thumb_decode_shift() \
|
||||
u32 imm = (opcode >> 6) & 0x1F; \
|
||||
u32 rs = (opcode >> 3) & 0x07; \
|
||||
u32 rd = opcode & 0x07 \
|
||||
|
||||
#define thumb_decode_add_sub() \
|
||||
u32 rn = (opcode >> 6) & 0x07; \
|
||||
u32 rs = (opcode >> 3) & 0x07; \
|
||||
u32 rd = opcode & 0x07 \
|
||||
|
||||
#define thumb_decode_add_sub_imm() \
|
||||
u32 imm = (opcode >> 6) & 0x07; \
|
||||
u32 rs = (opcode >> 3) & 0x07; \
|
||||
u32 rd = opcode & 0x07 \
|
||||
|
||||
#define thumb_decode_imm() \
|
||||
u32 imm = opcode & 0xFF \
|
||||
|
||||
#define thumb_decode_alu_op() \
|
||||
u32 rs = (opcode >> 3) & 0x07; \
|
||||
u32 rd = opcode & 0x07 \
|
||||
|
||||
#define thumb_decode_hireg_op() \
|
||||
u32 rs = (opcode >> 3) & 0x0F; \
|
||||
u32 rd = ((opcode >> 4) & 0x08) | (opcode & 0x07) \
|
||||
|
||||
#define thumb_decode_mem_reg() \
|
||||
u32 ro = (opcode >> 6) & 0x07; \
|
||||
u32 rb = (opcode >> 3) & 0x07; \
|
||||
u32 rd = opcode & 0x07 \
|
||||
|
||||
#define thumb_decode_mem_imm() \
|
||||
u32 imm = (opcode >> 6) & 0x1F; \
|
||||
u32 rb = (opcode >> 3) & 0x07; \
|
||||
u32 rd = opcode & 0x07 \
|
||||
|
||||
#define thumb_decode_add_sp() \
|
||||
u32 imm = opcode & 0x7F \
|
||||
|
||||
#define thumb_decode_rlist() \
|
||||
u32 reg_list = opcode & 0xFF \
|
||||
|
||||
#define thumb_decode_branch_cond() \
|
||||
s32 offset = (s8)(opcode & 0xFF) \
|
||||
|
||||
#define thumb_decode_swi() \
|
||||
u32 comment = opcode & 0xFF \
|
||||
|
||||
#define thumb_decode_branch() \
|
||||
u32 offset = opcode & 0x07FF \
|
||||
|
||||
const char *condition_table[] =
|
||||
{
|
||||
"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
|
||||
"hi", "ls", "ge", "lt", "gt", "le", "al", "nv"
|
||||
};
|
||||
|
||||
const char *data_proc_opcode_table[] =
|
||||
{
|
||||
"and", "eor", "sub", "rsb", "add", "adc", "sbc", "rsc",
|
||||
"tst", "teq", "cmp", "cmn", "orr", "mov", "bic", "mvn"
|
||||
};
|
||||
|
||||
|
||||
u32 print_disasm_arm_instruction(u32 opcode)
|
||||
{
|
||||
u32 condition = opcode >> 28;
|
||||
|
||||
switch((opcode >> 25) & 0x07)
|
||||
{
|
||||
// Data processing reg, multiply, bx, memory transfer half/byte, swap,
|
||||
// PSR reg
|
||||
case 0x0:
|
||||
|
||||
// Data processing imm, PSR imm
|
||||
case 0x1:
|
||||
|
||||
// Memory transfer imm
|
||||
case 0x2:
|
||||
|
||||
// Memory transfer reg, undefined
|
||||
case 0x3:
|
||||
|
||||
// Block memory transfer
|
||||
case 0x4:
|
||||
|
||||
// Branch
|
||||
case 0x5:
|
||||
|
||||
// Coprocessor
|
||||
case 0x6:
|
||||
|
||||
// Coprocessor, SWI
|
||||
case 0x7:
|
||||
}
|
932
game_config.txt
Normal file
932
game_config.txt
Normal file
@ -0,0 +1,932 @@
|
||||
# gpSP game settings database
|
||||
|
||||
# What is this file??? game_config.txt is a database of settings on a
|
||||
# per-game basis. A couple of the settings are required to make games
|
||||
# work at all, but most of them are there to improve the performance of
|
||||
# a game. If a game doesn't work then look through the settings here,
|
||||
# but keep in mind that this file can not be used to fix a majority of
|
||||
# games, the ones that don't work because of emulator bugs. For those
|
||||
# you'll have to wait for a new release and hope it someday gets fixed.
|
||||
|
||||
# This file is meant to be edited in plain text, with a normal editor.
|
||||
# game_name, game_code, and vender_code can be found in the game's header.
|
||||
# All three must match for the game to be used, and those setting must be
|
||||
# in that order. Be sure to use [!] ROMs (verified by GoodGBA) when
|
||||
# building this list. Right now I don't know how much overlap there is
|
||||
# between different region games, but usually idle loops don't apply to
|
||||
# them. If you're using a different region than the one in here you can
|
||||
# try copying the entry, it might improve it.
|
||||
|
||||
# You can also find the three identifying codes on the second line from
|
||||
# the top in gpSP's main menu. So anyone should be able to add settings
|
||||
# to this file if they know what to set, but for some options it'll take
|
||||
# a lot of special knowledge for them to be of any use. Be sure to see if
|
||||
# your game is already here, but only if the game_name/game_code/
|
||||
# vender_code all match. Only the first full match's settings will be used.
|
||||
|
||||
# Everything here is case sensitive. Don't mess with this file unless
|
||||
# you know what you're doing - if in doubt sooner ask someone who does.
|
||||
|
||||
# I mainly focus on USA versions, so try those first. And, just because
|
||||
# a game is on here doesn't mean the game actually works in the current
|
||||
# version. :/
|
||||
|
||||
# These are the following options:
|
||||
|
||||
# idle_loop_eliminate_target - tells the recompiler that this branch
|
||||
# is an idle loop and thus a hardware update should follow it every
|
||||
# time. This is purely a speed improvement and is not meant to improve
|
||||
# compatibility - if it does it represents a strange timing problem in
|
||||
# the game. You can only set one of these for now. Don't use this if
|
||||
# you don't know what you're doing, it can break the game. Some games
|
||||
# will run miserably slowly without this option.
|
||||
|
||||
# translation_gate_target - tells the recompiler to put an indirect
|
||||
# branch (gate) at this point, so artificially stop the current block.
|
||||
# This is useful if the game performs self modifying code from within
|
||||
# the same block it is currently executing - this can prevent it from
|
||||
# causing SMC hits far more times than it should. This is also only a
|
||||
# speed hack; you can have up to 8 of these. Don't use this if you don't
|
||||
# know what you're doing, they'll just make the game slower and are
|
||||
# rarely helpful (good for Camelot games).
|
||||
|
||||
# iwram_stack_optimize - set this to "no" to turn it off. By default this
|
||||
# is set on. It will turn off an optimization that assumes that the stack
|
||||
# is always in IWRAM, and thus makes ldm/stm relative to the stack much
|
||||
# faster. Turning it off will degrade game speed slightly, but is
|
||||
# necessary for a few games that don't follow this convention.
|
||||
|
||||
# flash_rom_type - set this to 128KB if the game has a 128KB flash ROM,
|
||||
# otherwise leave it alone or you might break game saving. If you get
|
||||
# a white screen when the game starts try this option.
|
||||
|
||||
# bios_rom_hack_39 - a hack that allows "roll" to work with the correct BIOS
|
||||
# in Zelda: Minish Cap.
|
||||
|
||||
# bios_rom_hack_2C - like the above but allows Rayman Advance to work.
|
||||
|
||||
# Castlevania: Circle of the Moon (U)
|
||||
game_name = DRACULA AGB1
|
||||
game_code = AAME
|
||||
vender_code = A4
|
||||
idle_loop_eliminate_target = 080003d2
|
||||
|
||||
# Megaman Battle Network (U)
|
||||
game_name = MEGAMAN_BN
|
||||
game_code = AREE
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 08000338
|
||||
|
||||
# Megaman Battle Network 2 (U)
|
||||
game_name = MEGAMAN_EXE2
|
||||
game_code = AE2E
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 08000358
|
||||
|
||||
# Megaman Battle Network 3 White (U)
|
||||
game_name = MEGA_EXE3_WH
|
||||
game_code = A6BE
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 0800036c
|
||||
|
||||
# Megaman Battle Network 3 Blue (U)
|
||||
game_name = MEGA_EXE3_BL
|
||||
game_code = A3XE
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 0800036c
|
||||
|
||||
# Megaman Battle Network 4 Red Sun (U)
|
||||
game_name = MEGAMANBN4RS
|
||||
game_code = B4WE
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 080003a6
|
||||
|
||||
# Megaman Battle Network 4 Blue Moon (U)
|
||||
game_name = MEGAMANBN4BM
|
||||
game_code = B4BE
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 080003a6
|
||||
|
||||
# Megaman Battle Network 5 Team Protoman (U)
|
||||
game_name = MEGAMAN5_TP_
|
||||
game_code = BRBE
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 080003ca
|
||||
|
||||
# Megaman Battle Network 5 Team Colonel (U)
|
||||
game_name = MEGAMAN5_TC_
|
||||
game_code = BRKE
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 080003ca
|
||||
|
||||
# Megaman Battle Network 6 Cybeast Gregar (U)
|
||||
game_name = MEGAMAN6_GXX
|
||||
game_code = BR5E
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 080003da
|
||||
|
||||
# Megaman Zero (U/E)
|
||||
game_name = MEGAMAN ZERO
|
||||
game_code = AZCE
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 080004ee
|
||||
|
||||
# Megaman Zero 2 (U)
|
||||
game_name = MEGAMANZERO2
|
||||
game_code = A62E
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 08000664
|
||||
|
||||
# Megaman Zero 3 (U)
|
||||
game_name = MEGAMANZERO3
|
||||
game_code = BZ3E
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 08001a08
|
||||
|
||||
# Megaman Zero 4 (U)
|
||||
game_name = MEGAMANZERO4
|
||||
game_code = B4ZP
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 0800090c
|
||||
|
||||
# Kirby: Nightmare in Dreamland (U)
|
||||
game_name = AGB KIRBY DX
|
||||
game_code = A7KE
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 08000fae
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# Hoshi no Kirby: Yume no Izumi Deluxe (J)
|
||||
game_name = AGB KIRBY DX
|
||||
game_code = A7KJ
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 08000f92
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# Kirby: Nightmare in Dreamland (E)
|
||||
game_name = AGB KIRBY DX
|
||||
game_code = A7KP
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 08000fae
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# Super Mario Advance (U)
|
||||
game_name = SUPER MARIOA
|
||||
game_code = AMZE
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 08001cf2
|
||||
|
||||
# Super Mario Advance 2 (U)
|
||||
game_name = SUPER MARIOB
|
||||
game_code = AA2E
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 08000534
|
||||
|
||||
# Super Mario Advance 3 (U)
|
||||
game_name = SUPER MARIOC
|
||||
game_code = A3AE
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 08002ba4
|
||||
|
||||
# Super Mario Advance 4 (U)
|
||||
game_name = SUPER MARIOD
|
||||
game_code = AX4E
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 08000732
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Super Mario Advance 4 (J)
|
||||
game_name = SUPER MARIOD
|
||||
game_code = AX4J
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 08000732
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Super Mario Advance 4 (E)
|
||||
game_name = SUPER MARIOD
|
||||
game_code = AX4P
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 08000732
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Advance Wars (U)
|
||||
# This one was really annoying to find, I hope it's okay.. there
|
||||
# might be a better one somewhere.
|
||||
game_name = ADVANCEWARS
|
||||
game_code = AWRE
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 0803880a
|
||||
|
||||
# Pokemon Emerald (E/U)
|
||||
# I don't know why this has an idle loop when Ruby doesn't....
|
||||
game_name = POKEMON EMER
|
||||
game_code = BPEE
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080008ce
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon Emerald (J)
|
||||
game_name = POKEMON EMER
|
||||
game_code = BPEJ
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080008ce
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon Emerald (G)
|
||||
game_name = POKEMON EMER
|
||||
game_code = BPED
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080008ce
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon Emerald (F)
|
||||
game_name = POKEMON EMER
|
||||
game_code = BPEF
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080008ce
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon Emerald (S)
|
||||
game_name = POKEMON EMER
|
||||
game_code = BPES
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080008ce
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon Emerald (I)
|
||||
game_name = POKEMON EMER
|
||||
game_code = BPEI
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080008ce
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon Sapphire (U)
|
||||
game_name = POKEMON SAPP
|
||||
game_code = AXPE
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon Sapphire (J)
|
||||
game_name = POKEMON SAPP
|
||||
game_code = AXPJ
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon Sapphire (G)
|
||||
game_name = POKEMON SAPP
|
||||
game_code = AXPD
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon Sapphire (I)
|
||||
game_name = POKEMON SAPP
|
||||
game_code = AXPI
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon Sapphire (S)
|
||||
game_name = POKEMON SAPP
|
||||
game_code = AXPS
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon Sapphire (F)
|
||||
game_name = POKEMON SAPP
|
||||
game_code = AXPF
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon Ruby (U)
|
||||
game_name = POKEMON RUBY
|
||||
game_code = AXVE
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon Ruby (J)
|
||||
game_name = POKEMON RUBY
|
||||
game_code = AXVJ
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon Ruby (G)
|
||||
game_name = POKEMON RUBY
|
||||
game_code = AXVD
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon Ruby (I)
|
||||
game_name = POKEMON RUBY
|
||||
game_code = AXVI
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon Ruby (S)
|
||||
game_name = POKEMON RUBY
|
||||
game_code = AXVS
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon Ruby (F)
|
||||
game_name = POKEMON RUBY
|
||||
game_code = AXVF
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# V-Rally 3 (E)
|
||||
game_name = V-RALLY 3
|
||||
game_code = AVRP
|
||||
vender_code = 70
|
||||
idle_loop_eliminate_target = 080aa920
|
||||
|
||||
# Mario Vs Donkey Kong (U)
|
||||
game_name = MARIOVSDK
|
||||
game_code = BM5E
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 08033eec
|
||||
|
||||
# Pokemon: Sapphire (U)
|
||||
game_name = POKEMON SAPP
|
||||
game_code = AXPE
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon: Sapphire (G)
|
||||
game_name = POKEMON SAPP
|
||||
game_code = AXPD
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon: Fire Red (J)
|
||||
game_name = POKEMON FIRE
|
||||
game_code = BPRJ
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080008b2
|
||||
# If you have the European version try this instead.
|
||||
#idle_loop_eliminate_target = 080008c6
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon: Fire Red (E/U)
|
||||
game_name = POKEMON FIRE
|
||||
game_code = BPRE
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080008c6
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon: Fire Red (S)
|
||||
game_name = POKEMON FIRE
|
||||
game_code = BPRS
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080008c6
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon: Fire Red (G)
|
||||
game_name = POKEMON FIRE
|
||||
game_code = BPRD
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080008c6
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon: Fire Red (I)
|
||||
game_name = POKEMON FIRE
|
||||
game_code = BPRI
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080008c6
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon: Fire Red (F)
|
||||
game_name = POKEMON FIRE
|
||||
game_code = BPRE
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080008c6
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon: Leaf Green (E/U)
|
||||
# Hey, this one is the same as Fire Red, who'd have thought? :B
|
||||
game_name = POKEMON LEAF
|
||||
game_code = BPGE
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080008b2
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon: Leaf Green (S)
|
||||
game_name = POKEMON LEAF
|
||||
game_code = BPGS
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080008b6
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon: Leaf Green (G)
|
||||
game_name = POKEMON LEAF
|
||||
game_code = BPGD
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080008b6
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon: Leaf Green (I)
|
||||
game_name = POKEMON LEAF
|
||||
game_code = BPGI
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080008b6
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon: Leaf Green (F)
|
||||
game_name = POKEMON LEAF
|
||||
game_code = BPGF
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080008b6
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon: Fushigi no Dungeon Aka no Kyuujotai (J)
|
||||
game_name = POKE DUNGEON
|
||||
game_code = B24J
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Pokemon: Red Rescue Team (E/U)
|
||||
game_name = POKE DUNGEON
|
||||
game_code = B24E
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# F-Zero: Climax (J)
|
||||
game_name = F-ZEROCLIMAX
|
||||
game_code = BFTJ
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Final Fantasy Tactics Advance (U)
|
||||
game_name = FFTA_USVER.
|
||||
game_code = AFXE
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 0800041e
|
||||
|
||||
# Gradius Galaxies (U)
|
||||
# Badly coded game with several idle loops. This one works for level
|
||||
# one at least.
|
||||
game_name = GRADIUSGALAX
|
||||
game_code = AGAE
|
||||
vender_code = A4
|
||||
idle_loop_eliminate_target = 08013844
|
||||
|
||||
# Rebelstar: Tactical Command (U)
|
||||
# Badly coded game with several idle loops. I don't think any are
|
||||
# even close to dominant, and it jumps around too much when things
|
||||
# matter....
|
||||
game_name = REBELSTAR
|
||||
game_code = BRLE
|
||||
vender_code = AF
|
||||
idle_loop_eliminate_target = 0800041a
|
||||
|
||||
# Golden Sun
|
||||
game_name = Golden_Sun_A
|
||||
game_code = AGSE
|
||||
vender_code = 01
|
||||
translation_gate_target = 03000820
|
||||
translation_gate_target = 030009ac
|
||||
translation_gate_target = 03007dac
|
||||
|
||||
# Golden Sun: The Lost Age (U)
|
||||
# Probably the most horrifically coded GBA game in existence.
|
||||
game_name = GOLDEN_SUN_B
|
||||
game_code = AGFE
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 08013542
|
||||
translation_gate_target = 030009ac
|
||||
#translation_gate_target = 03007d70
|
||||
|
||||
# Nothing to see here :/
|
||||
# Mario & Luigi: Superstar Saga (U)
|
||||
game_name = MARIO&LUIGIU
|
||||
game_code = A88E
|
||||
vender_code = 01
|
||||
|
||||
# Mario Party Advance (U)
|
||||
game_name = MARIOPARTYUS
|
||||
game_code = B8ME
|
||||
vender_code = 01
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# Mario Party Advance (J)
|
||||
game_name = MARIOPARTYJA
|
||||
game_code = B8MJ
|
||||
vender_code = 01
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# Mario Party Advance (E)
|
||||
game_name = MARIOPARTYEU
|
||||
game_code = B8MP
|
||||
vender_code = 01
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# Mario Golf: Advance Tour (U)
|
||||
game_name = MARIOGOLFGBA
|
||||
game_code = BMGE
|
||||
vender_code = 01
|
||||
iwram_stack_optimize = no
|
||||
idle_loop_eliminate_target = 08014e0a
|
||||
translation_gate_target = 03000d00
|
||||
translation_gate_target = 03000a30
|
||||
|
||||
# Mario Golf: GBA Tour (J)
|
||||
game_name = MARIOGOLFGBA
|
||||
game_code = BMGJ
|
||||
vender_code = 01
|
||||
iwram_stack_optimize = no
|
||||
idle_loop_eliminate_target = 08014e0a
|
||||
translation_gate_target = 03000d00
|
||||
translation_gate_target = 03000a30
|
||||
|
||||
# Mario Golf: Advance Tour (E)
|
||||
game_name = MARIOGOLFGBA
|
||||
game_code = BMGP
|
||||
vender_code = 01
|
||||
iwram_stack_optimize = no
|
||||
idle_loop_eliminate_target = 08014e0a
|
||||
translation_gate_target = 03000d00
|
||||
translation_gate_target = 03000a30
|
||||
|
||||
# Mario Golf: Advance Tour (S)
|
||||
game_name = MARIOGOLFGBA
|
||||
game_code = BMGS
|
||||
vender_code = 01
|
||||
iwram_stack_optimize = no
|
||||
idle_loop_eliminate_target = 08014e0a
|
||||
translation_gate_target = 03000d00
|
||||
translation_gate_target = 03000a30
|
||||
|
||||
# Mario Golf: Advance Tour (F)
|
||||
game_name = MARIOGOLFGBA
|
||||
game_code = BMGF
|
||||
vender_code = 01
|
||||
iwram_stack_optimize = no
|
||||
idle_loop_eliminate_target = 08014e0a
|
||||
translation_gate_target = 03000d00
|
||||
translation_gate_target = 03000a30
|
||||
|
||||
# Mario Golf: Advance Tour (I)
|
||||
game_name = MARIOGOLFGBA
|
||||
game_code = BMGI
|
||||
vender_code = 01
|
||||
iwram_stack_optimize = no
|
||||
idle_loop_eliminate_target = 08014e0a
|
||||
translation_gate_target = 03000d00
|
||||
translation_gate_target = 03000a30
|
||||
|
||||
# Mario Golf: Advance Tour (G)
|
||||
game_name = MARIOGOLFGBA
|
||||
game_code = BMGD
|
||||
vender_code = 01
|
||||
iwram_stack_optimize = no
|
||||
idle_loop_eliminate_target = 08014e0a
|
||||
translation_gate_target = 03000d00
|
||||
translation_gate_target = 03000a30
|
||||
|
||||
# Mario Golf: Advance Tour (A)
|
||||
game_name = MARIOGOLFGBA
|
||||
game_code = BMGU
|
||||
vender_code = 01
|
||||
iwram_stack_optimize = no
|
||||
idle_loop_eliminate_target = 08014e0a
|
||||
translation_gate_target = 03000d00
|
||||
translation_gate_target = 03000a30
|
||||
|
||||
# Tales of Phantasia (U)
|
||||
game_name = PHANTASIA
|
||||
game_code = AN8E
|
||||
vender_code = 01
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# Tales of Phantasia (J)
|
||||
game_name = PHANTASIA
|
||||
game_code = AN8J
|
||||
vender_code = AF
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# Tales of Phantasia (E)
|
||||
game_name = PHANTASIA
|
||||
game_code = AN8P
|
||||
vender_code = 01
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# Advance Wars 2: Black Hole Rising (U)
|
||||
game_name = ADVANCEWARS2
|
||||
game_code = AW2E
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 08036e2a
|
||||
|
||||
# Bomberman Tournament (U)
|
||||
game_name = BOMSTORYUSA
|
||||
game_code = ABSE
|
||||
vender_code = 52
|
||||
idle_loop_eliminate_target = 08000526
|
||||
|
||||
# Broken Sword - The Shadow of the Templars (U)
|
||||
game_name = BROKENSWORD
|
||||
game_code = ABJE
|
||||
vender_code = 6L
|
||||
idle_loop_eliminate_target = 08000a26
|
||||
|
||||
# Defender of The Crown (U)
|
||||
game_name = DOTC
|
||||
game_code = ADHE
|
||||
vender_code = 5N
|
||||
idle_loop_eliminate_target = 080007ec
|
||||
|
||||
# Drill Dozer (U)
|
||||
game_name = DRILL DOZER
|
||||
game_code = V49E
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080006c2
|
||||
|
||||
# F-Zero - Maximum Velocity (U)
|
||||
game_name = F-ZERO ADVAN
|
||||
game_code = AFZE
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 08000c2e
|
||||
|
||||
# Megaman Zero 2 (U)
|
||||
game_name = MEGAMANZERO2
|
||||
game_code = A62E
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 08000664
|
||||
|
||||
# Megaman Zero 3 (U)
|
||||
game_name = MEGAMANZERO3
|
||||
game_code = BZ3E
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 08001a08
|
||||
|
||||
# Megaman Zero 4 (U)
|
||||
game_name = MEGAMANZERO4
|
||||
game_code = B4ZE
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 0800090c
|
||||
|
||||
# Metal Slug Advance (U)
|
||||
game_name = METAL SLUG
|
||||
game_code = BSME
|
||||
vender_code = B7
|
||||
idle_loop_eliminate_target = 08000298
|
||||
|
||||
# Magical Quest 2 Starring Mickey & Minnie (U)
|
||||
game_name = M&M MAGICAL2
|
||||
game_code = AQME
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 0801d340
|
||||
|
||||
# Magical Quest 3 Starring Mickey & Donald (U)
|
||||
game_name = M&D MAGICAL3
|
||||
game_code = BMQE
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 08016064
|
||||
|
||||
# Pinball Challenge Deluxe (E)
|
||||
game_name = PINBALL CHAL
|
||||
game_code = APLP
|
||||
vender_code = 41
|
||||
idle_loop_eliminate_target = 080075a6
|
||||
|
||||
# Prince of Persia - The Sands of Time (U)
|
||||
game_name = PRINCEPERSIA
|
||||
game_code = BPYE
|
||||
vender_code = 41
|
||||
idle_loop_eliminate_target = 0808ff3a
|
||||
|
||||
# Rhythm Tengoku (J)
|
||||
game_name = RHYTHMTENGOK
|
||||
game_code = BRIJ
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080013d4
|
||||
|
||||
# River City Ransom EX (U)
|
||||
game_name = RIVERCRANSOM
|
||||
game_code = BDTE
|
||||
vender_code = EB
|
||||
idle_loop_eliminate_target = 0800065a
|
||||
|
||||
# Super Puzzle Fighter II Turbo (U)
|
||||
game_name = PUZZLEFIGHT2
|
||||
game_code = AZ8E
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 08002b5e
|
||||
|
||||
# Yu-Gi-Oh! - Dungeon Dice Monsters (U)
|
||||
game_name = YU-GI-OH DDM
|
||||
game_code = AYDE
|
||||
vender_code = A4
|
||||
idle_loop_eliminate_target = 0802cc6a
|
||||
|
||||
# Yu-Gi-Oh! - The Eternal Duelist Soul (U)
|
||||
game_name = YU-GI-OH!EDS
|
||||
game_code = AY5E
|
||||
vender_code = A4
|
||||
idle_loop_eliminate_target = 08075d96
|
||||
|
||||
# Yu-Gi-Oh! - The Sacred Cards (U)
|
||||
game_name = YUGIOH DM7
|
||||
game_code = AY7E
|
||||
vender_code = A4
|
||||
idle_loop_eliminate_target = 08003bd6
|
||||
|
||||
# Yu-Gi-Oh! - World Championship Tournament 2004 (U)
|
||||
game_name = YWCT2004USA
|
||||
game_code = BYWE
|
||||
vender_code = A4
|
||||
idle_loop_eliminate_target = 080831da
|
||||
|
||||
# Yu-Gi-Oh! - Worldwide Edition - Stairway to the Destined Duel (U)
|
||||
game_name = YUGIOHWWE
|
||||
game_code = AYWE
|
||||
vender_code = A4
|
||||
idle_loop_eliminate_target = 08089792
|
||||
|
||||
# Wario Ware, Inc. Mega Microgames (U)
|
||||
game_name = WARIOWAREINC
|
||||
game_code = AZWE
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 08000f66
|
||||
|
||||
# Tom Clancy's Splinter Cell (U)
|
||||
game_name = SPLINTERCELL
|
||||
game_code = AO4E
|
||||
vender_code = 41
|
||||
idle_loop_eliminate_target = 0807a0c4
|
||||
|
||||
# Tom Clancy's Splinter Cell - Pandora Tomorrow (U)
|
||||
game_name = TOM CLANCY'S
|
||||
game_code = BSLE
|
||||
vender_code = 41
|
||||
idle_loop_eliminate_target = 0807785e
|
||||
|
||||
# Final Fantasy IV Advance (U)
|
||||
game_name = FF4ADVANCE
|
||||
game_code = BZ4E
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 0800fabe
|
||||
# or try 00000430
|
||||
|
||||
# Digimon Battle Spirit (U)
|
||||
game_name = DIGIMON BTSP
|
||||
game_code = A8SE
|
||||
vender_code = B2
|
||||
idle_loop_eliminate_target = 08011208
|
||||
|
||||
# Digimon Battle Spirit 2 (U)
|
||||
game_name = DIGIMON BS2
|
||||
game_code = BDSE
|
||||
vender_code = B2
|
||||
idle_loop_eliminate_target = 08010eb0
|
||||
|
||||
# Donald Duck Advance (U)
|
||||
game_name = DISNEY'S DON
|
||||
game_code = ADKE
|
||||
vender_code = 41
|
||||
idle_loop_eliminate_target = 08002f30
|
||||
|
||||
# Final Fight One (U)
|
||||
game_name = FINAL FIGHT
|
||||
game_code = AFFE
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 0800b428
|
||||
|
||||
# Megaman Battle Chip Challenge (U)
|
||||
game_name = BATTLECHIPGP
|
||||
game_code = A89E
|
||||
vender_code = 08
|
||||
idle_loop_eliminate_target = 08000544
|
||||
|
||||
# Monster Force (U)
|
||||
game_name = MONSTERFORCE
|
||||
game_code = AM8E
|
||||
vender_code = 7D
|
||||
idle_loop_eliminate_target = 08000b00
|
||||
|
||||
# Monster Rancher Advance (U)
|
||||
game_name = MONSRANCHERA
|
||||
game_code = AMFE
|
||||
vender_code = 9B
|
||||
idle_loop_eliminate_target = 0809f394
|
||||
|
||||
# Monster Rancher Advance 2 (U)
|
||||
game_name = MONSTERRANC2
|
||||
game_code = A2QE
|
||||
vender_code = 9B
|
||||
idle_loop_eliminate_target = 081c7290
|
||||
|
||||
# The Pinball of The Dead
|
||||
game_name = PINBALL DEAD
|
||||
game_code = APDE
|
||||
vender_code = 78
|
||||
idle_loop_eliminate_target = 08000300
|
||||
|
||||
# Tringo (U)
|
||||
game_name = TRINGO
|
||||
game_code = BTJE
|
||||
vender_code = 4Z
|
||||
idle_loop_eliminate_target = 080009a4
|
||||
|
||||
# Virtual Kasparov (U)
|
||||
game_name = VIRTKASPAROV
|
||||
game_code = AVKE
|
||||
vender_code = 60
|
||||
idle_loop_eliminate_target = 0800093a
|
||||
|
||||
# Advance Wars 2 - Black Hole Rising (E)
|
||||
game_name = ADVANCEWARS2
|
||||
game_code = AW2P
|
||||
vender_code = 01
|
||||
idle_loop_eliminate_target = 080371be
|
||||
|
||||
# Bookworm (U)
|
||||
game_name = BOOKWORM
|
||||
game_code = BKWE
|
||||
vender_code = 5G
|
||||
idle_loop_eliminate_target = 0800397c
|
||||
|
||||
# 007 - Nightfire (U)
|
||||
game_name = NIGHTFIRE
|
||||
game_code = A7OE
|
||||
vender_code = 69
|
||||
idle_loop_eliminate_target = 080031d6
|
||||
|
||||
# Asterix & Obelix XXL (E)
|
||||
game_name = ASTERIX
|
||||
game_code = BLXP
|
||||
vender_code = 70
|
||||
idle_loop_eliminate_target = 0846d060
|
||||
|
||||
# Was this game released in Japan? What as?
|
||||
# Ninja Five-0 (U)
|
||||
game_name = NINJA FIVE 0
|
||||
game_code = ANXE
|
||||
vender_code = A4
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# Ninja Cop (E)
|
||||
game_name = NINJA COP
|
||||
game_code = ANXP
|
||||
vender_code = A4
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# Sennen Kazoku (J)
|
||||
game_name = SENNENKAZOKU
|
||||
game_code = BKAJ
|
||||
vender_code = 01
|
||||
flash_rom_type = 128KB
|
||||
|
||||
# Doom 2 (U)
|
||||
game_name = DOOM II
|
||||
game_code = A9DE
|
||||
vender_code = 52
|
||||
translation_gate_target = 030041c8
|
||||
translation_gate_target = 03004fa0
|
||||
|
||||
# Bleach Advance (J)
|
||||
game_name = BLEACH ADV1
|
||||
game_code = BLEJ
|
||||
vender_code = 8P
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# Shining Soul (J)
|
||||
game_name = SHINING SOUL
|
||||
game_code = AHUJ
|
||||
vender_code = 8P
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# Shining Soul (U)
|
||||
game_name = SHINING SOUL
|
||||
game_code = AHUE
|
||||
vender_code = EB
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# Shining Soul (E)
|
||||
game_name = SHINING SOUL
|
||||
game_code = AHUP
|
||||
vender_code = 8P
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# Shining Soul 2 (J)
|
||||
game_name = SHININGSOUL2
|
||||
game_code = AU2J
|
||||
vender_code = 8P
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# Shining Soul 2 (U)
|
||||
game_name = SHININGSOUL2
|
||||
game_code = AU2E
|
||||
vender_code = EB
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# Shining Soul 2 (E)
|
||||
game_name = SHININGSOUL2
|
||||
game_code = AU2P
|
||||
vender_code = 8P
|
||||
iwram_stack_optimize = no
|
||||
|
||||
# This is needed to make the game work.
|
||||
# Another World (Homebrew)
|
||||
game_name = FoxAnWorld
|
||||
game_code = Home
|
||||
vender_code = 00
|
||||
translation_gate_target = 03000f1c
|
||||
|
51
gp2x/Makefile
Normal file
51
gp2x/Makefile
Normal file
@ -0,0 +1,51 @@
|
||||
# gpSP makefile
|
||||
# Gilead Kutnick - Exophase
|
||||
# GP2X port(ion) - Z
|
||||
|
||||
# Global definitions
|
||||
|
||||
PREFIX = /opt/open2x/gcc-4.1.1-glibc-2.3.6
|
||||
CC = $(PREFIX)/bin/arm-open2x-linux-gcc
|
||||
STRIP = $(PREFIX)/bin/arm-open2x-linux-strip
|
||||
|
||||
OBJS = main.o cpu.o memory.u video.o input.o sound.o gp2x.o gui.o \
|
||||
cheats.o zip.o cpu_threaded.z cpu_speed.o cpuctrl.o \
|
||||
gp2xminilib.o font.o display.o speedtest.o cmdline.o daemon.o \
|
||||
arm_stub.o video_blend.o
|
||||
BIN = gpsp.gpe
|
||||
|
||||
# Platform specific definitions
|
||||
|
||||
VPATH += ..
|
||||
CFLAGS += -DARM_ARCH -DGP2X_BUILD
|
||||
# NOTE: -funroll-loops will slow down compiling considerably
|
||||
CFLAGS += -O3 -std=c99 -msoft-float -funsigned-char -fno-common \
|
||||
-fno-builtin \
|
||||
|
||||
INCLUDES = `$(PREFIX)/bin/arm-open2x-linux-sdl-config --cflags`
|
||||
LIBS = `$(PREFIX)/bin/arm-open2x-linux-sdl-config --libs` \
|
||||
-lm -ldl -lpthread -lz -static
|
||||
|
||||
# Compilation:
|
||||
|
||||
.SUFFIXES: .c
|
||||
|
||||
%.z: %.c
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
||||
%.u: %.c
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
||||
%.o: %.S
|
||||
$(CC) $(ASFLAGS) $(INCLUDES) -c -o $@ $<
|
||||
|
||||
all: $(OBJS)
|
||||
$(CC) $(OBJS) $(LIBS) -o $(BIN)
|
||||
$(STRIP) $(BIN)
|
||||
|
||||
clean:
|
||||
rm -f *.o *.u *.z $(BIN)
|
||||
|
48
gp2x/align_test.c
Normal file
48
gp2x/align_test.c
Normal file
@ -0,0 +1,48 @@
|
||||
// Betting on GCC aligning this for efficiency.
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
unsigned short int read_16 = 0xF1F2;
|
||||
unsigned int read_32 = 0xF1F2F3F4;
|
||||
|
||||
unsigned short int write_16 = 0xF00D;
|
||||
unsigned int write_32 = 0xF00DFEED;
|
||||
// 16bit unsigned reads, we expect 0xF1F2 and 0xF20000F1
|
||||
fprintf(stderr, "%04x %04x\n",
|
||||
*((unsigned short int *)((char *)&read_16)),
|
||||
*((unsigned short int *)((char *)&read_16 + 1)));
|
||||
|
||||
// 16bit signed reads, we expect 0xFFFFF1F2 and 0xFFFFFFF1
|
||||
fprintf(stderr, "%04x %04x\n",
|
||||
*((short int *)((char *)&read_16)),
|
||||
*((short int *)((char *)&read_16 + 1)));
|
||||
|
||||
// 32bit reads, we expect 0xF1F2F3F4, 0xF4F1F2F3, 0xF3F4F1F2,
|
||||
// and 0xF2F3F4F1
|
||||
|
||||
fprintf(stderr, "%08x %08x %08x %08x\n",
|
||||
*((int *)((char *)&read_32)),
|
||||
*((int *)((char *)&read_32 + 1)),
|
||||
*((int *)((char *)&read_32 + 2)),
|
||||
*((int *)((char *)&read_32 + 3)));
|
||||
|
||||
// 16bit writes, we expect write_16 to remain 0xF00D
|
||||
|
||||
*((short int *)((char *)&write_16)) = 0xF00D;
|
||||
*((short int *)((char *)&write_16) + 1) = 0xF00D;
|
||||
|
||||
fprintf(stderr, "%04x\n", write_16);
|
||||
|
||||
// 32bit writes, we expect write_32 to remain 0xF00DFEED
|
||||
|
||||
*((int *)((char *)&write_16)) = 0xF00DFEED;
|
||||
*((int *)((char *)&write_16) + 1) = 0xF00DFEED;
|
||||
*((int *)((char *)&write_16) + 2) = 0xF00DFEED;
|
||||
*((int *)((char *)&write_16) + 3) = 0xF00DFEED;
|
||||
|
||||
fprintf(stderr, "%08x\n", write_32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
1392
gp2x/arm_codegen.h
Normal file
1392
gp2x/arm_codegen.h
Normal file
File diff suppressed because it is too large
Load Diff
1661
gp2x/arm_dpimacros.h
Normal file
1661
gp2x/arm_dpimacros.h
Normal file
File diff suppressed because it is too large
Load Diff
1952
gp2x/arm_emit.h
Normal file
1952
gp2x/arm_emit.h
Normal file
File diff suppressed because it is too large
Load Diff
1016
gp2x/arm_stub.S
Normal file
1016
gp2x/arm_stub.S
Normal file
File diff suppressed because it is too large
Load Diff
478
gp2x/bios_cache.S
Normal file
478
gp2x/bios_cache.S
Normal file
@ -0,0 +1,478 @@
|
||||
|
||||
//Gp2x/gp2x/mnt/nand/bios_cache.bin: file format binary
|
||||
|
||||
Disassembly of section .data:
|
||||
|
||||
00000000 <.data>:
|
||||
0: e3a00f02 mov r0, #8 ; 0x8
|
||||
4: ebcb1afd bl step_debug
|
||||
8: e25cc001 subs ip, ip, #1 ; 0x1
|
||||
c: 5a000001 bpl 0x18
|
||||
10: e3a00d05 mov r0, #320 ; 0x140
|
||||
14: ebcb18d0 bl 0xff2c635c
|
||||
18: eaffffff b 0x1c
|
||||
1c: e3a00d05 mov r0, #320 ; 0x140
|
||||
20: ebcb1af6 bl step_debug
|
||||
24: e59a9034 ldr r9, [sl, #52]
|
||||
28: e249900c sub r9, r9, #12 ; 0xc
|
||||
2c: e59a0034 ldr r0, [sl, #52]
|
||||
30: e240000c sub r0, r0, #12 ; 0xc
|
||||
34: e58a0034 str r0, [sl, #52]
|
||||
38: e3c99003 bic r9, r9, #3 ; 0x3
|
||||
3c: e2890000 add r0, r9, #0 ; 0x0
|
||||
40: e59a102c ldr r1, [sl, #44]
|
||||
44: ebcb1a8e bl 0xff2c6a84
|
||||
48: e2890004 add r0, r9, #4 ; 0x4
|
||||
4c: e1a01007 mov r1, r7
|
||||
50: ebcb1a8b bl 0xff2c6a84
|
||||
54: e2890008 add r0, r9, #8 ; 0x8
|
||||
58: e1a01008 mov r1, r8
|
||||
5c: e3a02f51 mov r2, #324 ; 0x144
|
||||
60: ebcb1a6f bl 0xff2c6a24
|
||||
64: e3a00f51 mov r0, #324 ; 0x144
|
||||
68: ebcb1ae4 bl step_debug
|
||||
6c: e2480002 sub r0, r8, #2 ; 0x2
|
||||
70: ebcb1a95 bl 0xff2c6acc
|
||||
74: e1a07000 mov r7, r0
|
||||
78: e3a00f52 mov r0, #328 ; 0x148
|
||||
7c: ebcb1adf bl step_debug
|
||||
80: e3a01e15 mov r1, #336 ; 0x150
|
||||
84: e2810078 add r0, r1, #120 ; 0x78
|
||||
88: e58a002c str r0, [sl, #44]
|
||||
8c: e3a00f53 mov r0, #332 ; 0x14c
|
||||
90: ebcb1ada bl step_debug
|
||||
94: e59a002c ldr r0, [sl, #44]
|
||||
98: e0800107 add r0, r0, r7, lsl #2
|
||||
9c: ebcb1ac9 bl 0xff2c6bc8
|
||||
a0: e1a07000 mov r7, r0
|
||||
a4: e3a00e15 mov r0, #336 ; 0x150
|
||||
a8: ebcb1ad4 bl step_debug
|
||||
ac: ebcb194d bl 0xff2c65e8
|
||||
b0: e58a002c str r0, [sl, #44]
|
||||
b4: e3a00f55 mov r0, #340 ; 0x154
|
||||
b8: ebcb1ad0 bl step_debug
|
||||
bc: e59a9034 ldr r9, [sl, #52]
|
||||
c0: e2499004 sub r9, r9, #4 ; 0x4
|
||||
c4: e59a0034 ldr r0, [sl, #52]
|
||||
c8: e2400004 sub r0, r0, #4 ; 0x4
|
||||
cc: e58a0034 str r0, [sl, #52]
|
||||
d0: e3c99003 bic r9, r9, #3 ; 0x3
|
||||
d4: e2890000 add r0, r9, #0 ; 0x0
|
||||
d8: e59a102c ldr r1, [sl, #44]
|
||||
dc: e3a02f56 mov r2, #344 ; 0x158
|
||||
e0: ebcb1a4f bl 0xff2c6a24
|
||||
e4: e3a00f56 mov r0, #344 ; 0x158
|
||||
e8: ebcb1ac4 bl step_debug
|
||||
ec: e59a102c ldr r1, [sl, #44]
|
||||
f0: e2010080 and r0, r1, #128 ; 0x80
|
||||
f4: e58a002c str r0, [sl, #44]
|
||||
f8: e3a00f57 mov r0, #348 ; 0x15c
|
||||
fc: ebcb1abf bl step_debug
|
||||
100: e59a102c ldr r1, [sl, #44]
|
||||
104: e381001f orr r0, r1, #31 ; 0x1f
|
||||
108: e58a002c str r0, [sl, #44]
|
||||
10c: e3a00e16 mov r0, #352 ; 0x160
|
||||
110: ebcb1aba bl step_debug
|
||||
114: e59a002c ldr r0, [sl, #44]
|
||||
118: e3a02e16 mov r2, #352 ; 0x160
|
||||
11c: e3a010ff mov r1, #255 ; 0xff
|
||||
120: e38114ff orr r1, r1, #-16777216 ; 0xff000000
|
||||
124: ebcb190a bl 0xff2c6554
|
||||
128: e3a00f59 mov r0, #356 ; 0x164
|
||||
12c: ebcb1ab3 bl step_debug
|
||||
130: e59a9034 ldr r9, [sl, #52]
|
||||
134: e2499008 sub r9, r9, #8 ; 0x8
|
||||
138: e59a0034 ldr r0, [sl, #52]
|
||||
13c: e2400008 sub r0, r0, #8 ; 0x8
|
||||
140: e58a0034 str r0, [sl, #52]
|
||||
144: e3c99003 bic r9, r9, #3 ; 0x3
|
||||
148: e2890000 add r0, r9, #0 ; 0x0
|
||||
14c: e59a1008 ldr r1, [sl, #8]
|
||||
150: ebcb1a4b bl 0xff2c6a84
|
||||
154: e2890004 add r0, r9, #4 ; 0x4
|
||||
158: e1a01008 mov r1, r8
|
||||
15c: e3a02f5a mov r2, #360 ; 0x168
|
||||
160: ebcb1a2f bl 0xff2c6a24
|
||||
164: e3a00f5a mov r0, #360 ; 0x168
|
||||
168: ebcb1aa4 bl step_debug
|
||||
16c: e3a01e17 mov r1, #368 ; 0x170
|
||||
170: e2818000 add r8, r1, #0 ; 0x0
|
||||
174: e3a00f5b mov r0, #364 ; 0x16c
|
||||
178: ebcb1aa0 bl step_debug
|
||||
17c: e1a00007 mov r0, r7
|
||||
180: e24cc016 sub ip, ip, #22 ; 0x16
|
||||
184: eacb18be b 0xff2c6484
|
||||
188: e3a00ff1 mov r0, #964 ; 0x3c4
|
||||
18c: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
190: ebcb1a9a bl step_debug
|
||||
194: e59a9034 ldr r9, [sl, #52]
|
||||
198: e2499020 sub r9, r9, #32 ; 0x20
|
||||
19c: e59a0034 ldr r0, [sl, #52]
|
||||
1a0: e2400020 sub r0, r0, #32 ; 0x20
|
||||
1a4: e58a0034 str r0, [sl, #52]
|
||||
1a8: e3c99003 bic r9, r9, #3 ; 0x3
|
||||
1ac: e2890000 add r0, r9, #0 ; 0x0
|
||||
1b0: e59a1010 ldr r1, [sl, #16]
|
||||
1b4: ebcb1a32 bl 0xff2c6a84
|
||||
1b8: e2890004 add r0, r9, #4 ; 0x4
|
||||
1bc: e59a1014 ldr r1, [sl, #20]
|
||||
1c0: ebcb1a2f bl 0xff2c6a84
|
||||
1c4: e2890008 add r0, r9, #8 ; 0x8
|
||||
1c8: e1a01005 mov r1, r5
|
||||
1cc: ebcb1a2c bl 0xff2c6a84
|
||||
1d0: e289000c add r0, r9, #12 ; 0xc
|
||||
1d4: e59a101c ldr r1, [sl, #28]
|
||||
1d8: ebcb1a29 bl 0xff2c6a84
|
||||
1dc: e2890010 add r0, r9, #16 ; 0x10
|
||||
1e0: e59a1020 ldr r1, [sl, #32]
|
||||
1e4: ebcb1a26 bl 0xff2c6a84
|
||||
1e8: e2890014 add r0, r9, #20 ; 0x14
|
||||
1ec: e1a01006 mov r1, r6
|
||||
1f0: ebcb1a23 bl 0xff2c6a84
|
||||
1f4: e2890018 add r0, r9, #24 ; 0x18
|
||||
1f8: e59a1028 ldr r1, [sl, #40]
|
||||
1fc: ebcb1a20 bl 0xff2c6a84
|
||||
200: e289001c add r0, r9, #28 ; 0x1c
|
||||
204: e1a01008 mov r1, r8
|
||||
208: e3a02ff2 mov r2, #968 ; 0x3c8
|
||||
20c: e3822b02 orr r2, r2, #2048 ; 0x800
|
||||
210: ebcb1a03 bl 0xff2c6a24
|
||||
214: e3a00ff2 mov r0, #968 ; 0x3c8
|
||||
218: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
21c: ebcb1a77 bl step_debug
|
||||
220: e59a0008 ldr r0, [sl, #8]
|
||||
224: e1a00580 mov r0, r0, lsl #11
|
||||
228: e58a0028 str r0, [sl, #40]
|
||||
22c: e3a00ff3 mov r0, #972 ; 0x3cc
|
||||
230: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
234: ebcb1a71 bl step_debug
|
||||
238: e59a0028 ldr r0, [sl, #40]
|
||||
23c: e128f00b msr CPSR_f, fp
|
||||
240: e1b074a0 movs r7, r0, lsr #9
|
||||
244: e10fb000 mrs fp, CPSR
|
||||
248: e3a00ebd mov r0, #3024 ; 0xbd0
|
||||
24c: ebcb1a6b bl step_debug
|
||||
250: e3a00ff5 mov r0, #980 ; 0x3d4
|
||||
254: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
258: e1a08000 mov r8, r0
|
||||
25c: e25cc00c subs ip, ip, #12 ; 0xc
|
||||
260: 5a000002 bpl 0x270
|
||||
264: e3a00fe9 mov r0, #932 ; 0x3a4
|
||||
268: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
26c: ebcb183a bl 0xff2c635c
|
||||
270: eaffffff b 0x274
|
||||
274: e3a00fe9 mov r0, #932 ; 0x3a4
|
||||
278: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
27c: ebcb1a5f bl step_debug
|
||||
280: e3570000 cmp r7, #0 ; 0x0
|
||||
284: e10fb000 mrs fp, CPSR
|
||||
288: e3a00fea mov r0, #936 ; 0x3a8
|
||||
28c: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
290: ebcb1a5a bl step_debug
|
||||
294: e24cc002 sub ip, ip, #2 ; 0x2
|
||||
298: e128f00b msr CPSR_f, fp
|
||||
29c: 1a000007 bne 0x2c0
|
||||
2a0: 5a000002 bpl 0x2b0
|
||||
2a4: e3a00fef mov r0, #956 ; 0x3bc
|
||||
2a8: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
2ac: ebcb182a bl 0xff2c635c
|
||||
2b0: ea000013 b 0x304
|
||||
2b4: e3a00feb mov r0, #940 ; 0x3ac
|
||||
2b8: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
2bc: ebcb1a4f bl step_debug
|
||||
2c0: e3c774fe bic r7, r7, #-33554432 ; 0xfe000000
|
||||
2c4: e3a00ebb mov r0, #2992 ; 0xbb0
|
||||
2c8: ebcb1a4c bl step_debug
|
||||
2cc: e0837007 add r7, r3, r7
|
||||
2d0: e3a00fed mov r0, #948 ; 0x3b4
|
||||
2d4: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
2d8: ebcb1a48 bl step_debug
|
||||
2dc: e313040e tst r3, #234881024 ; 0xe000000
|
||||
2e0: e10fb000 mrs fp, CPSR
|
||||
2e4: e3a00fee mov r0, #952 ; 0x3b8
|
||||
2e8: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
2ec: ebcb1a43 bl step_debug
|
||||
2f0: e24cc004 sub ip, ip, #4 ; 0x4
|
||||
2f4: e128f00b msr CPSR_f, fp
|
||||
2f8: 0a000004 beq 0x310
|
||||
2fc: e317040e tst r7, #234881024 ; 0xe000000
|
||||
300: e10fb000 mrs fp, CPSR
|
||||
304: e3a00fef mov r0, #956 ; 0x3bc
|
||||
308: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
30c: ebcb1a3b bl step_debug
|
||||
310: e1a00008 mov r0, r8
|
||||
314: e24cc001 sub ip, ip, #1 ; 0x1
|
||||
318: eacb1859 b 0xff2c6484
|
||||
31c: e3a00ff5 mov r0, #980 ; 0x3d4
|
||||
320: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
324: ebcb1a35 bl step_debug
|
||||
328: e24cc001 sub ip, ip, #1 ; 0x1
|
||||
32c: e128f00b msr CPSR_f, fp
|
||||
330: 1a000007 bne 0x354
|
||||
334: 5a000002 bpl 0x344
|
||||
338: e3a00f09 mov r0, #36 ; 0x24
|
||||
33c: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||
340: ebcb1805 bl 0xff2c635c
|
||||
344: ea0000d6 b 0x6a4
|
||||
348: e3a00ff6 mov r0, #984 ; 0x3d8
|
||||
34c: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
350: ebcb1a2a bl step_debug
|
||||
354: e59a0028 ldr r0, [sl, #40]
|
||||
358: e08404a0 add r0, r4, r0, lsr #9
|
||||
35c: e58a0028 str r0, [sl, #40]
|
||||
360: e3a00ff7 mov r0, #988 ; 0x3dc
|
||||
364: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
368: ebcb1a24 bl step_debug
|
||||
36c: e59a0008 ldr r0, [sl, #8]
|
||||
370: e128f00b msr CPSR_f, fp
|
||||
374: e1b00ca0 movs r0, r0, lsr #25
|
||||
378: e10fb000 mrs fp, CPSR
|
||||
37c: e58a0008 str r0, [sl, #8]
|
||||
380: e3a00ebe mov r0, #3040 ; 0xbe0
|
||||
384: ebcb1a1d bl step_debug
|
||||
388: e24cc003 sub ip, ip, #3 ; 0x3
|
||||
38c: e128f00b msr CPSR_f, fp
|
||||
390: 2a000007 bcs 0x3b4
|
||||
394: 5a000002 bpl 0x3a4
|
||||
398: e3a00f05 mov r0, #20 ; 0x14
|
||||
39c: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||
3a0: ebcb17ed bl 0xff2c635c
|
||||
3a4: ea00006a b 0x554
|
||||
3a8: e3a00ff9 mov r0, #996 ; 0x3e4
|
||||
3ac: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
3b0: ebcb1a12 bl step_debug
|
||||
3b4: e2830000 add r0, r3, #0 ; 0x0
|
||||
3b8: ebcb1a02 bl 0xff2c6bc8
|
||||
3bc: e58a0008 str r0, [sl, #8]
|
||||
3c0: e3a00ffa mov r0, #1000 ; 0x3e8
|
||||
3c4: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
3c8: ebcb1a0c bl step_debug
|
||||
3cc: e59a0008 ldr r0, [sl, #8]
|
||||
3d0: e1a00000 nop (mov r0,r0)
|
||||
3d4: e58a000c str r0, [sl, #12]
|
||||
3d8: e3a00ffb mov r0, #1004 ; 0x3ec
|
||||
3dc: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
3e0: ebcb1a06 bl step_debug
|
||||
3e4: e59a0008 ldr r0, [sl, #8]
|
||||
3e8: e1a00000 nop (mov r0,r0)
|
||||
3ec: e58a0010 str r0, [sl, #16]
|
||||
3f0: e3a00ebf mov r0, #3056 ; 0xbf0
|
||||
3f4: ebcb1a01 bl step_debug
|
||||
3f8: e59a0008 ldr r0, [sl, #8]
|
||||
3fc: e1a00000 nop (mov r0,r0)
|
||||
400: e58a0014 str r0, [sl, #20]
|
||||
404: e3a00ffd mov r0, #1012 ; 0x3f4
|
||||
408: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
40c: ebcb19fb bl step_debug
|
||||
410: e59a0008 ldr r0, [sl, #8]
|
||||
414: e1a05000 mov r5, r0
|
||||
418: e3a00ffe mov r0, #1016 ; 0x3f8
|
||||
41c: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
420: ebcb19f6 bl step_debug
|
||||
424: e59a0008 ldr r0, [sl, #8]
|
||||
428: e1a00000 nop (mov r0,r0)
|
||||
42c: e58a001c str r0, [sl, #28]
|
||||
430: e3a00fff mov r0, #1020 ; 0x3fc
|
||||
434: e3800b02 orr r0, r0, #2048 ; 0x800
|
||||
438: ebcb19f0 bl step_debug
|
||||
43c: e59a0008 ldr r0, [sl, #8]
|
||||
440: e1a00000 nop (mov r0,r0)
|
||||
444: e58a0020 str r0, [sl, #32]
|
||||
448: e3a00b03 mov r0, #3072 ; 0xc00
|
||||
44c: ebcb19eb bl step_debug
|
||||
450: e59a0008 ldr r0, [sl, #8]
|
||||
454: e1a06000 mov r6, r0
|
||||
458: e24cc00a sub ip, ip, #10 ; 0xa
|
||||
|
||||
45c: e3a00f01 mov r0, #4 ; 0x4
|
||||
460: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||
464: ebcb19e5 bl step_debug
|
||||
|
||||
468: e59a0028 ldr r0, [sl, #40]
|
||||
46c: e1540000 cmp r4, r0
|
||||
470: e10fb000 mrs fp, CPSR
|
||||
|
||||
474: e3a00f02 mov r0, #8 ; 0x8
|
||||
478: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||
|
||||
47c: ebcb19df bl step_debug
|
||||
480: e24cc002 sub ip, ip, #2 ; 0x2
|
||||
484: e128f00b msr CPSR_f, fp
|
||||
|
||||
488: aa000021 bge 0x514
|
||||
48c: e1a09004 mov r9, r4
|
||||
|
||||
490: e1a00004 mov r0, r4
|
||||
494: e2800020 add r0, r0, #32 ; 0x20
|
||||
498: e1a04000 mov r4, r0
|
||||
49c: e3c99003 bic r9, r9, #3 ; 0x3
|
||||
4a0: e2890000 add r0, r9, #0 ; 0x0
|
||||
4a4: e59a1008 ldr r1, [sl, #8]
|
||||
4a8: ebcb1975 bl 0xff2c6a84
|
||||
4ac: e2890004 add r0, r9, #4 ; 0x4
|
||||
4b0: e59a100c ldr r1, [sl, #12]
|
||||
4b4: ebcb1972 bl 0xff2c6a84
|
||||
4b8: e2890008 add r0, r9, #8 ; 0x8
|
||||
4bc: e59a1010 ldr r1, [sl, #16]
|
||||
4c0: ebcb196f bl 0xff2c6a84
|
||||
4c4: e289000c add r0, r9, #12 ; 0xc
|
||||
4c8: e59a1014 ldr r1, [sl, #20]
|
||||
4cc: ebcb196c bl 0xff2c6a84
|
||||
4d0: e2890010 add r0, r9, #16 ; 0x10
|
||||
4d4: e1a01005 mov r1, r5
|
||||
4d8: ebcb1969 bl 0xff2c6a84
|
||||
4dc: e2890014 add r0, r9, #20 ; 0x14
|
||||
4e0: e59a101c ldr r1, [sl, #28]
|
||||
4e4: ebcb1966 bl 0xff2c6a84
|
||||
4e8: e2890018 add r0, r9, #24 ; 0x18
|
||||
4ec: e59a1020 ldr r1, [sl, #32]
|
||||
4f0: ebcb1963 bl 0xff2c6a84
|
||||
4f4: e289001c add r0, r9, #28 ; 0x1c
|
||||
4f8: e1a01006 mov r1, r6
|
||||
4fc: e3a02f03 mov r2, #12 ; 0xc
|
||||
500: e3822b03 orr r2, r2, #3072 ; 0xc00
|
||||
504: ebcb1946 bl 0xff2c6a24
|
||||
508: e3a00f03 mov r0, #12 ; 0xc
|
||||
50c: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||
510: ebcb19ba bl step_debug
|
||||
514: e24cc009 sub ip, ip, #9 ; 0x9
|
||||
518: e128f00b msr CPSR_f, fp
|
||||
51c: aa000006 bge 0x53c
|
||||
520: 5a000002 bpl 0x530
|
||||
524: e3a00f01 mov r0, #4 ; 0x4
|
||||
528: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||
52c: ebcb178a bl 0xff2c635c
|
||||
530: eaffffc9 b 0x45c
|
||||
534: e3a00ec1 mov r0, #3088 ; 0xc10
|
||||
538: ebcb19b0 bl step_debug
|
||||
53c: e25cc001 subs ip, ip, #1 ; 0x1
|
||||
540: 5a000002 bpl 0x550
|
||||
544: e3a00f09 mov r0, #36 ; 0x24
|
||||
548: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||
54c: ebcb1782 bl 0xff2c635c
|
||||
550: ea000053 b 0x6a4
|
||||
554: e3a00f05 mov r0, #20 ; 0x14
|
||||
558: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||
55c: ebcb19a7 bl step_debug
|
||||
560: e59a0028 ldr r0, [sl, #40]
|
||||
564: e1540000 cmp r4, r0
|
||||
568: e10fb000 mrs fp, CPSR
|
||||
56c: e3a00f06 mov r0, #24 ; 0x18
|
||||
570: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||
574: ebcb19a1 bl step_debug
|
||||
578: e24cc002 sub ip, ip, #2 ; 0x2
|
||||
57c: e128f00b msr CPSR_f, fp
|
||||
580: aa00003f bge 0x684
|
||||
584: e1a09003 mov r9, r3
|
||||
588: e1a00003 mov r0, r3
|
||||
58c: e2800020 add r0, r0, #32 ; 0x20
|
||||
590: e1a03000 mov r3, r0
|
||||
594: e3c99003 bic r9, r9, #3 ; 0x3
|
||||
598: e2890000 add r0, r9, #0 ; 0x0
|
||||
59c: ebcb1989 bl 0xff2c6bc8
|
||||
5a0: e58a0008 str r0, [sl, #8]
|
||||
5a4: e2890004 add r0, r9, #4 ; 0x4
|
||||
5a8: ebcb1986 bl 0xff2c6bc8
|
||||
5ac: e58a000c str r0, [sl, #12]
|
||||
5b0: e2890008 add r0, r9, #8 ; 0x8
|
||||
5b4: ebcb1983 bl 0xff2c6bc8
|
||||
5b8: e58a0010 str r0, [sl, #16]
|
||||
5bc: e289000c add r0, r9, #12 ; 0xc
|
||||
5c0: ebcb1980 bl 0xff2c6bc8
|
||||
5c4: e58a0014 str r0, [sl, #20]
|
||||
5c8: e2890010 add r0, r9, #16 ; 0x10
|
||||
5cc: ebcb197d bl 0xff2c6bc8
|
||||
5d0: e1a05000 mov r5, r0
|
||||
5d4: e2890014 add r0, r9, #20 ; 0x14
|
||||
5d8: ebcb197a bl 0xff2c6bc8
|
||||
5dc: e58a001c str r0, [sl, #28]
|
||||
5e0: e2890018 add r0, r9, #24 ; 0x18
|
||||
5e4: ebcb1977 bl 0xff2c6bc8
|
||||
5e8: e58a0020 str r0, [sl, #32]
|
||||
5ec: e289001c add r0, r9, #28 ; 0x1c
|
||||
5f0: ebcb1974 bl 0xff2c6bc8
|
||||
5f4: e1a06000 mov r6, r0
|
||||
5f8: e3a00f07 mov r0, #28 ; 0x1c
|
||||
5fc: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||
600: ebcb197e bl step_debug
|
||||
604: e1a09004 mov r9, r4
|
||||
608: e1a00004 mov r0, r4
|
||||
60c: e2800020 add r0, r0, #32 ; 0x20
|
||||
610: e1a04000 mov r4, r0
|
||||
614: e3c99003 bic r9, r9, #3 ; 0x3
|
||||
618: e2890000 add r0, r9, #0 ; 0x0
|
||||
61c: e59a1008 ldr r1, [sl, #8]
|
||||
620: ebcb1917 bl 0xff2c6a84
|
||||
624: e2890004 add r0, r9, #4 ; 0x4
|
||||
628: e59a100c ldr r1, [sl, #12]
|
||||
62c: ebcb1914 bl 0xff2c6a84
|
||||
630: e2890008 add r0, r9, #8 ; 0x8
|
||||
634: e59a1010 ldr r1, [sl, #16]
|
||||
638: ebcb1911 bl 0xff2c6a84
|
||||
63c: e289000c add r0, r9, #12 ; 0xc
|
||||
640: e59a1014 ldr r1, [sl, #20]
|
||||
644: ebcb190e bl 0xff2c6a84
|
||||
648: e2890010 add r0, r9, #16 ; 0x10
|
||||
64c: e1a01005 mov r1, r5
|
||||
650: ebcb190b bl 0xff2c6a84
|
||||
654: e2890014 add r0, r9, #20 ; 0x14
|
||||
658: e59a101c ldr r1, [sl, #28]
|
||||
65c: ebcb1908 bl 0xff2c6a84
|
||||
660: e2890018 add r0, r9, #24 ; 0x18
|
||||
664: e59a1020 ldr r1, [sl, #32]
|
||||
668: ebcb1905 bl 0xff2c6a84
|
||||
66c: e289001c add r0, r9, #28 ; 0x1c
|
||||
670: e1a01006 mov r1, r6
|
||||
674: e3a02ec2 mov r2, #3104 ; 0xc20
|
||||
678: ebcb18e9 bl 0xff2c6a24
|
||||
|
||||
67c: e3a00ec2 mov r0, #3104 ; 0xc20
|
||||
680: ebcb195e bl step_debug
|
||||
684: e24cc012 sub ip, ip, #18 ; 0x12
|
||||
688: e128f00b msr CPSR_f, fp
|
||||
68c: aa000007 bge 0x6b0
|
||||
690: 5a000002 bpl 0x6a0
|
||||
694: e3a00f05 mov r0, #20 ; 0x14
|
||||
698: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||
69c: ebcb172e bl 0xff2c635c
|
||||
6a0: eaffffab b 0x554
|
||||
|
||||
6a4: e3a00f09 mov r0, #36 ; 0x24
|
||||
6a8: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||
6ac: ebcb1953 bl step_debug
|
||||
6b0: e59a9034 ldr r9, [sl, #52]
|
||||
6b4: e59a0034 ldr r0, [sl, #52]
|
||||
6b8: e2800020 add r0, r0, #32 ; 0x20
|
||||
6bc: e58a0034 str r0, [sl, #52]
|
||||
6c0: e3c99003 bic r9, r9, #3 ; 0x3
|
||||
6c4: e2890000 add r0, r9, #0 ; 0x0
|
||||
6c8: ebcb193e bl 0xff2c6bc8
|
||||
6cc: e58a0010 str r0, [sl, #16]
|
||||
6d0: e2890004 add r0, r9, #4 ; 0x4
|
||||
6d4: ebcb193b bl 0xff2c6bc8
|
||||
6d8: e58a0014 str r0, [sl, #20]
|
||||
6dc: e2890008 add r0, r9, #8 ; 0x8
|
||||
6e0: ebcb1938 bl 0xff2c6bc8
|
||||
6e4: e1a05000 mov r5, r0
|
||||
6e8: e289000c add r0, r9, #12 ; 0xc
|
||||
6ec: ebcb1935 bl 0xff2c6bc8
|
||||
6f0: e58a001c str r0, [sl, #28]
|
||||
6f4: e2890010 add r0, r9, #16 ; 0x10
|
||||
6f8: ebcb1932 bl 0xff2c6bc8
|
||||
6fc: e58a0020 str r0, [sl, #32]
|
||||
700: e2890014 add r0, r9, #20 ; 0x14
|
||||
704: ebcb192f bl 0xff2c6bc8
|
||||
708: e1a06000 mov r6, r0
|
||||
70c: e2890018 add r0, r9, #24 ; 0x18
|
||||
710: ebcb192c bl 0xff2c6bc8
|
||||
714: e58a0028 str r0, [sl, #40]
|
||||
718: e289001c add r0, r9, #28 ; 0x1c
|
||||
71c: ebcb1929 bl 0xff2c6bc8
|
||||
720: e1a08000 mov r8, r0
|
||||
|
||||
724: e3a00f0a mov r0, #40 ; 0x28
|
||||
728: e3800b03 orr r0, r0, #3072 ; 0xc00
|
||||
72c: ebcb1933 bl step_debug
|
||||
730: e1a00008 mov r0, r8
|
||||
734: e24cc00a sub ip, ip, #10 ; 0xa
|
||||
738: eacb1751 b 0xff2c6484
|
256
gp2x/cmdline.c
Normal file
256
gp2x/cmdline.c
Normal file
@ -0,0 +1,256 @@
|
||||
|
||||
/* commandline.c for GP2X Version 2.0
|
||||
Copyright (C) 2006 god_at_hell
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "cpuctrl.h"
|
||||
#include "gp2xminilib.h"
|
||||
#include "cpuctrl.h"
|
||||
|
||||
|
||||
void fallback(int argc, char *argv[])
|
||||
{
|
||||
//beginning commandline-utilizing
|
||||
if (argc == 3)
|
||||
{
|
||||
if (atoi(argv[1]) == 0)
|
||||
{
|
||||
if(atoi(argv[2]) > 36){gp2x_deinit();exit(1);}
|
||||
if(atoi(argv[2]) < -20){gp2x_deinit();exit(1);}
|
||||
set_add_FLCDCLK(atoi(argv[2]));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(atoi(argv[2]) > 10){gp2x_deinit();exit(1);}
|
||||
if(atoi(argv[2]) < -5){gp2x_deinit();exit(1);}
|
||||
set_add_ULCDCLK(atoi(argv[2]));
|
||||
}
|
||||
}
|
||||
|
||||
if (argc == 4)
|
||||
{
|
||||
if(atoi(argv[3]) > 320){gp2x_deinit();exit(1);}
|
||||
if(atoi(argv[3]) < 33){gp2x_deinit();exit(1);}
|
||||
if (atoi(argv[1]) == 0)
|
||||
{
|
||||
if(atoi(argv[2]) > 36){gp2x_deinit();exit(1);}
|
||||
if(atoi(argv[2]) < -20){gp2x_deinit();exit(1);}
|
||||
set_add_FLCDCLK(atoi(argv[2]));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(atoi(argv[2]) > 10){gp2x_deinit();exit(1);}
|
||||
if(atoi(argv[2]) < -5){gp2x_deinit();exit(1);}
|
||||
set_add_ULCDCLK(atoi(argv[2]));
|
||||
}
|
||||
set_FCLK(atoi(argv[3]));
|
||||
}
|
||||
|
||||
if (argc == 5)
|
||||
{
|
||||
if(atoi(argv[3]) > 320){gp2x_deinit();exit(1);}
|
||||
if(atoi(argv[3]) < 33){gp2x_deinit();exit(1);}
|
||||
if(atof(argv[4]) > 10){gp2x_deinit();exit(1);}
|
||||
if(atof(argv[4]) < 0.02){gp2x_deinit();exit(1);}
|
||||
if (atoi(argv[1]) == 0)
|
||||
{
|
||||
if(atoi(argv[2]) > 36){gp2x_deinit();exit(1);}
|
||||
if(atoi(argv[2]) < -20){gp2x_deinit();exit(1);}
|
||||
set_add_FLCDCLK(atoi(argv[2]));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(atoi(argv[2]) > 10){gp2x_deinit();exit(1);}
|
||||
if(atoi(argv[2]) < -5){gp2x_deinit();exit(1);}
|
||||
set_add_ULCDCLK(atoi(argv[2]));
|
||||
}
|
||||
set_FCLK(atoi(argv[3]));
|
||||
set_gamma(atof(argv[4]));
|
||||
}
|
||||
}
|
||||
|
||||
void cmdhelp()
|
||||
{
|
||||
printf ("\ngpSP2X v0.9003 Beta by Exophase/ZodTTD\r\n");
|
||||
printf ("cpu_speed by god_at_hell\r\n");
|
||||
printf ("Usage: cpu_speed.gpe [option1] [value1] [option2]...\r\n");
|
||||
printf ("Options:\r\n");
|
||||
printf (" RAM-Options\r\n");
|
||||
printf (" -----------\r\n");
|
||||
printf (" --cas CAS Latency. Delay in clock cycles between the registration \n\t\tof a READ command and the first bit of output data. \n\t\tValid values are 2 and 3 cycles.\r\n");
|
||||
printf (" --trc ACTIVE to ACTIVE /AUTOREFRESH command delay. Defines ACTIVE \n\t\tto ACTIVE/auto refresh command period delay. \n\t\tValid values are from 1 to 16 cycles.\r\n");
|
||||
printf (" --tras ACTIVE to PRECHARGE delay. Defines the delay between the ACTIVE \n\t\tand PRECHARGE commands. \n\t\tValid values are from 1 to 16 cycles.\r\n");
|
||||
printf (" --twr Write recovery time in cycles.\n\t\tValid values are from 1 to 16 cycles.\r\n");
|
||||
printf (" --tmrd LOAD MODE REGISTER command cycle time.\n\t\tValid values are from 1 to 16 cycles.\r\n");
|
||||
printf (" --trfc AUTO REFRESH command period in cycles.\n\t\tValid values are from 1 to 16 cycles.\r\n");
|
||||
printf (" --trp PRECHARGE command period in cycles.\n\t\tValid values are from 1 to 16 cycles.\r\n");
|
||||
printf (" --trcd RAS to CAS Delay in cycles.\n\t\tValid values are from 1 to 16 cycles.\r\n");
|
||||
printf (" --refperd Refresh Period. Defines maximum time period between \n\t\tAUTOREFRESH commands.\n\t\tValid values are from 1 to 65535 (default ~ 250) cycles.\r\n");
|
||||
printf (" --ramdiv Divider for the Memory-Clock which is 1/2 of the CPU-Clock. \n\t\tValid values are from 1 to 8.\r\n");
|
||||
printf ("\n CPU-Options\r\n");
|
||||
printf (" -----------\r\n");
|
||||
printf (" --cpuclk Sets the CPU-Frequency in Mhz. \n\t\tValid values are from 33 to 340.\r\n");
|
||||
printf (" --cpudiv Divider for the CPU-Clock. \n\t\tValid values are from 1 to 8.\r\n");
|
||||
printf ("\n Display-Options\r\n");
|
||||
printf ("----------------\r\n");
|
||||
printf (" --fpll Sets clockgenerator to fpll (for firmware 1.0 - 1.0.1).\r\n");
|
||||
printf (" --upll Sets clockgenerator to upll (for the rest).\r\n");
|
||||
printf (" --timing Timing Prescaler to eliminate flickering. \n\t\tValid values are: -20 to 36 with fpll.\n\t\t\t\t -6 to 10 with upll.\r\n");
|
||||
printf (" --gamma Regulates the gamma. \n\t\tValid values are from 0.0001 to 15.0000.\r\n");
|
||||
printf ("\n Daemon-Mode \r\n");
|
||||
printf ("----------------\r\n");
|
||||
printf ("Usage: cpu_speed.gpe --daemon [option1] [value1] [option2]...\r\n");
|
||||
printf ("Shutdown: cpu_speed.gpe --kill[-daemon]\r\n");
|
||||
printf ("Options:\r\n");
|
||||
printf (" --min Sets the minimum CPU-Frequency in Mhz. \n\t\tValid values are from 33 to 340.\r\n");
|
||||
printf (" --max Sets the maximum CPU-Frequency in Mhz. \n\t\tValid values are from 33 to 340.\r\n");
|
||||
printf (" --start Sets the CPU-Frequency in Mhz. \n\t\tValid values are from 33 to 340.\r\n");
|
||||
printf (" --step Sets the CPU-Frequency step in Mhz. \n\t\tValid values are from 1 to 340.\r\n");
|
||||
printf (" --hotkey Sets the hotkey. (Default: LR) \n\t\tValid values are a combination of LRXYZAB+-S/@ or ``None''\n\t\t (+- are volume, S is Start, / is Select, @ is Stick).\r\n");
|
||||
printf (" --incr Sets the increment key. (Default: +) \n\t\tValid values are a combination of LRXYZAB+-S/@ or ``None''\n\t\t (+- are volume, S is Start, / is Select, @ is Stick).\r\n");
|
||||
printf (" --decr Sets the decrement key. (Default: -) \n\t\tValid values are a combination of LRXYZAB+-S/@ or ``None''\n\t\t (+- are volume, S is Start, / is Select, @ is Stick).\r\n");
|
||||
printf (" --no-hotkey Alias for --hotkey None.\r\n");
|
||||
printf (" --no-incr Alias for --incr None.\r\n");
|
||||
printf (" --no-decr Alias for --decr None.\r\n");
|
||||
printf (" --foreground Do not switch to daemon mode. (Useful for debugging)\r\n");
|
||||
printf (" --background Switch to daemon mode. (Default)\r\n");
|
||||
printf (" --display Enable on screen display. COMING SOON!\r\n");
|
||||
printf (" --no-display Disable on screen display.\r\n");
|
||||
printf ("\nNOTE:\nThe old commandline-settings are working ... read more about this in the readme\n\n");
|
||||
}
|
||||
|
||||
void cmdline(int argc, char *argv[])
|
||||
{
|
||||
short i,n;
|
||||
short varis = 11;
|
||||
char clockgen = get_Clkgen();
|
||||
char var[11][9]={"--cas","--trc","--tras","--twr","--tmrd","--trfc","--trp","--trcd","--ramdiv","--cpuclk","--cpudiv"};
|
||||
|
||||
short val[varis];
|
||||
for(n=0;n<varis;n++) //initialize the variable-array
|
||||
{
|
||||
val[n] = -1;
|
||||
}
|
||||
|
||||
short timing = -100;
|
||||
int refperd = -1;
|
||||
float gamma = -1.;
|
||||
|
||||
|
||||
for(i=1; i<argc; i++)
|
||||
{
|
||||
if(strcmp(argv[i], "--fpll") == 0) clockgen = 0;
|
||||
if(strcmp(argv[i], "--upll") == 0) clockgen = 1;
|
||||
|
||||
for(n=0; n<varis; n++)
|
||||
{
|
||||
if(strcmp(argv[i], var[n]) == 0)
|
||||
{
|
||||
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",var[n]);gp2x_deinit();exit(1);}
|
||||
val[n] = atoi(argv[i+1]);
|
||||
}
|
||||
}
|
||||
if(strcmp(argv[i], "--refperd") == 0)
|
||||
{
|
||||
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||
refperd = atoi(argv[i+1]);
|
||||
}
|
||||
if(strcmp(argv[i], "--gamma") == 0)
|
||||
{
|
||||
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||
gamma = atof(argv[i+1]);
|
||||
}
|
||||
if(strcmp(argv[i], "--timing") == 0)
|
||||
{
|
||||
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||
timing = atoi(argv[i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
if(clockgen == 0)
|
||||
{
|
||||
if(timing > -21)
|
||||
{
|
||||
if(timing < 37) set_add_FLCDCLK(timing);
|
||||
}
|
||||
else set_add_FLCDCLK(get_LCDClk(clockgen));
|
||||
}
|
||||
if(clockgen == 1)
|
||||
{
|
||||
if(timing > -7)
|
||||
{
|
||||
if(timing < 11) set_add_ULCDCLK(timing);
|
||||
}
|
||||
else set_add_ULCDCLK(get_LCDClk(clockgen));
|
||||
}
|
||||
if(refperd-1 > -1)
|
||||
{
|
||||
if(refperd-1 < 0xffff) set_REFPERD(refperd-1);
|
||||
}
|
||||
if(gamma > 0.)
|
||||
{
|
||||
if(gamma < 15.) set_gamma(gamma);
|
||||
}
|
||||
if(val[0]-2 > -1)
|
||||
{
|
||||
if(val[0]-2 < 2) set_CAS(val[0]-2);
|
||||
}
|
||||
if(val[1]-1 > -1)
|
||||
{
|
||||
if(val[1]-1 < 16) set_tRC(val[1]-1);
|
||||
}
|
||||
if(val[2]-1 > -1)
|
||||
{
|
||||
if(val[2]-1 < 16) set_tRAS(val[2]-1);
|
||||
}
|
||||
if(val[3]-1 > -1)
|
||||
{
|
||||
if(val[3]-1 < 16) set_tWR(val[3]-1);
|
||||
}
|
||||
if(val[4]-1 > -1)
|
||||
{
|
||||
if(val[4]-1 < 16) set_tMRD(val[4]-1);
|
||||
}
|
||||
if(val[5]-1 > -1)
|
||||
{
|
||||
if(val[5]-1 < 16) set_tRFC(val[5]-1);
|
||||
}
|
||||
if(val[6]-1 > -1)
|
||||
{
|
||||
if(val[6] < 16) set_tRP(val[6]-1);
|
||||
}
|
||||
if(val[7]-1 > -1)
|
||||
{
|
||||
if(val[7]-1 < 16) set_tRCD(val[7]-1);
|
||||
}
|
||||
if(val[8]-1 > -1)
|
||||
{
|
||||
if(val[8]-1 < 8) set_DCLK_Div(val[8]-1);
|
||||
}
|
||||
if(val[9] > 32)
|
||||
{
|
||||
if(val[9] < 341) set_FCLK(val[9]);
|
||||
}
|
||||
if(val[10]-1 > -1)
|
||||
{
|
||||
if(val[10]-1 < 8) set_920_Div(val[10]-1);
|
||||
}
|
||||
}
|
3
gp2x/cmdline.h
Normal file
3
gp2x/cmdline.h
Normal file
@ -0,0 +1,3 @@
|
||||
void fallback(int argc, char *argv[]);
|
||||
void cmdhelp();
|
||||
void cmdline(int argc, char *argv[]);
|
1276
gp2x/cpu_speed.c
Normal file
1276
gp2x/cpu_speed.c
Normal file
File diff suppressed because it is too large
Load Diff
484
gp2x/cpuctrl.c
Normal file
484
gp2x/cpuctrl.c
Normal file
@ -0,0 +1,484 @@
|
||||
/* cpuctrl.c for GP2X (CPU/LCD/RAM-Tuner Version 2.0)
|
||||
Copyright (C) 2006 god_at_hell
|
||||
original CPU-Overclocker (c) by Hermes/PS2Reality
|
||||
the gamma-routine was provided by theoddbot
|
||||
parts (c) Rlyehs Work
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/****************************************************************************************************************************************/
|
||||
// CPU CONTROL
|
||||
/****************************************************************************************************************************************/
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "gp2xminilib.h"
|
||||
|
||||
#define SYS_CLK_FREQ 7372800
|
||||
|
||||
//from minimal library rlyeh
|
||||
|
||||
extern unsigned long gp2x_dev[4];
|
||||
extern unsigned short *gp2x_memregs;
|
||||
|
||||
// system registers
|
||||
static struct
|
||||
{
|
||||
unsigned short SYSCLKENREG,SYSCSETREG,FPLLVSETREG,DUALINT920,DUALINT940,DUALCTRL940,DISPCSETREG,MEMTIMEX0;
|
||||
unsigned short MEMTIMEX1,MEMREFX,MLC_GAMM_BYPATH,MLC_GAMMA_A,MLC_GAMMA_D,YBNKLVL;
|
||||
}
|
||||
system_reg;
|
||||
|
||||
volatile unsigned short *MEM_REG;
|
||||
unsigned MDIV,PDIV,SCALE;
|
||||
volatile unsigned *arm940code;
|
||||
|
||||
void cpuctrl_init()
|
||||
{
|
||||
MEM_REG=&gp2x_memregs[0];
|
||||
}
|
||||
|
||||
void save_system_regs()
|
||||
{
|
||||
system_reg.SYSCSETREG=MEM_REG[0x91c>>1];
|
||||
system_reg.FPLLVSETREG=MEM_REG[0x912>>1];
|
||||
system_reg.SYSCLKENREG=MEM_REG[0x904>>1];
|
||||
system_reg.DUALINT920=MEM_REG[0x3B40>>1];
|
||||
system_reg.DUALINT940=MEM_REG[0x3B42>>1];
|
||||
system_reg.DUALCTRL940=MEM_REG[0x3B48>>1];
|
||||
system_reg.DISPCSETREG=MEM_REG[0x924>>1];
|
||||
system_reg.MEMTIMEX0=MEM_REG[0x3802>>1];
|
||||
system_reg.MEMTIMEX1=MEM_REG[0x3804>>1];
|
||||
system_reg.MEMREFX=MEM_REG[0x3808>>1];
|
||||
system_reg.MLC_GAMM_BYPATH=MEM_REG[0x2880>>1];
|
||||
system_reg.MLC_GAMMA_A=MEM_REG[0x295C>>1];
|
||||
system_reg.MLC_GAMMA_D=MEM_REG[0x295E>>1];
|
||||
system_reg.YBNKLVL=MEM_REG[0x283A>>1];
|
||||
}
|
||||
|
||||
void load_system_regs()
|
||||
{
|
||||
MEM_REG[0x91c>>1]=system_reg.SYSCSETREG;
|
||||
MEM_REG[0x910>>1]=system_reg.FPLLVSETREG;
|
||||
MEM_REG[0x3B40>>1]=system_reg.DUALINT920;
|
||||
MEM_REG[0x3B42>>1]=system_reg.DUALINT940;
|
||||
MEM_REG[0x3B48>>1]=system_reg.DUALCTRL940;
|
||||
MEM_REG[0x904>>1]=system_reg.SYSCLKENREG;
|
||||
/* Set UPLLSETVREG to 0x4F02, which gives 80MHz */
|
||||
MEM_REG[0x0914>>1] = 0x4F02;
|
||||
/* Wait for clock change to start */
|
||||
while (MEM_REG[0x0902>>1] & 2);
|
||||
/* Wait for clock change to be verified */
|
||||
while (MEM_REG[0x0916>>1] != 0x4F02);
|
||||
MEM_REG[0x3802>>1]=system_reg.MEMTIMEX0;
|
||||
MEM_REG[0x3804>>1]=system_reg.MEMTIMEX1;
|
||||
MEM_REG[0x3808>>1]=system_reg.MEMREFX;
|
||||
MEM_REG[0x2880>>1]=system_reg.MLC_GAMM_BYPATH;
|
||||
MEM_REG[0x295C>>1]=system_reg.MLC_GAMMA_A;
|
||||
MEM_REG[0x295E>>1]=system_reg.MLC_GAMMA_D;
|
||||
MEM_REG[0x283A>>1]=system_reg.YBNKLVL;
|
||||
}
|
||||
|
||||
|
||||
void set_FCLK(unsigned MHZ)
|
||||
{
|
||||
printf ("set CPU-Frequency = %uMHz\r\n",MHZ);
|
||||
unsigned v;
|
||||
unsigned mdiv,pdiv=3,scale=0;
|
||||
MHZ*=1000000;
|
||||
mdiv=(MHZ*pdiv)/SYS_CLK_FREQ;
|
||||
//printf ("Old value = %04X\r",MEM_REG[0x924>>1]," ");
|
||||
//printf ("APLL = %04X\r",MEM_REG[0x91A>>1]," ");
|
||||
mdiv=((mdiv-8)<<8) & 0xff00;
|
||||
pdiv=((pdiv-2)<<2) & 0xfc;
|
||||
scale&=3;
|
||||
v=mdiv | pdiv | scale;
|
||||
MEM_REG[0x910>>1]=v;
|
||||
}
|
||||
|
||||
unsigned get_FCLK()
|
||||
{
|
||||
return MEM_REG[0x910>>1];
|
||||
}
|
||||
|
||||
void set_add_FLCDCLK(int addclock)
|
||||
{
|
||||
//Set LCD controller to use FPLL
|
||||
printf ("...set to FPLL-Clockgen...\r\n");
|
||||
printf ("set Timing-Prescaler = %i\r\n",addclock);
|
||||
MEM_REG[0x924>>1]= 0x5A00 + ((addclock)<<8);
|
||||
//If you change the initial timing, don't forget to shift your intervall-borders in "cpu_speed.c"
|
||||
}
|
||||
|
||||
void set_add_ULCDCLK(int addclock)
|
||||
{
|
||||
//Set LCD controller to use UPLL
|
||||
printf ("...set to UPLL-Clockgen...\r\n");
|
||||
printf ("set Timing-Prescaler = %i\r\n",addclock);
|
||||
MEM_REG[0x0924>>1] = 0x8900 + ((addclock)<<8);
|
||||
//If you change the initial timing, don't forget to shift your intervall-borders in "cpu_speed.c"
|
||||
}
|
||||
|
||||
unsigned get_LCDClk()
|
||||
{
|
||||
if (MEM_REG[0x0924>>1] < 0x7A01) return((MEM_REG[0x0924>>1] - 0x5A00)>>8);
|
||||
else return((MEM_REG[0x0924>>1] - 0x8900)>>8);
|
||||
}
|
||||
|
||||
char get_Clkgen()
|
||||
{
|
||||
if (MEM_REG[0x0924>>1] < 0x7A01) return(0);
|
||||
else return(1);
|
||||
}
|
||||
|
||||
unsigned get_freq_UCLK()
|
||||
{
|
||||
unsigned i;
|
||||
unsigned reg,mdiv,pdiv,scale;
|
||||
i = MEM_REG[0x900>>1];
|
||||
i = ((i >> 7) & 1) ;
|
||||
if(i) return 0;
|
||||
reg=MEM_REG[0x916>>1];
|
||||
mdiv = ((reg & 0xff00) >> 8) + 8;
|
||||
pdiv = ((reg & 0xfc) >> 2) + 2;
|
||||
scale = reg & 3;
|
||||
return ((SYS_CLK_FREQ * mdiv) / (pdiv << scale));
|
||||
}
|
||||
|
||||
unsigned get_freq_ACLK()
|
||||
{
|
||||
unsigned i;
|
||||
unsigned reg,mdiv,pdiv,scale;
|
||||
i = MEM_REG[0x900>>1];
|
||||
i = ((i >> 8) & 1) ;
|
||||
if(i) return 0;
|
||||
reg=MEM_REG[0x918>>1];
|
||||
mdiv = ((reg & 0xff00) >> 8) + 8;
|
||||
pdiv = ((reg & 0xfc) >> 2) + 2;
|
||||
scale = reg & 3;
|
||||
return ((SYS_CLK_FREQ * mdiv)/(pdiv << scale));
|
||||
}
|
||||
|
||||
unsigned get_freq_920_CLK()
|
||||
{
|
||||
unsigned i;
|
||||
unsigned reg,mdiv,pdiv,scale;
|
||||
reg=MEM_REG[0x912>>1];
|
||||
mdiv = ((reg & 0xff00) >> 8) + 8;
|
||||
pdiv = ((reg & 0xfc) >> 2) + 2;
|
||||
scale = reg & 3;
|
||||
MDIV=mdiv;
|
||||
PDIV=pdiv;
|
||||
SCALE=scale;
|
||||
i = (MEM_REG[0x91c>>1] & 7)+1;
|
||||
return ((SYS_CLK_FREQ * mdiv)/(pdiv << scale))/i;
|
||||
}
|
||||
|
||||
unsigned get_freq_940_CLK()
|
||||
{
|
||||
unsigned i;
|
||||
unsigned reg,mdiv,pdiv,scale;
|
||||
reg=MEM_REG[0x912>>1];
|
||||
mdiv = ((reg & 0xff00) >> 8) + 8;
|
||||
pdiv = ((reg & 0xfc) >> 2) + 2;
|
||||
scale = reg & 3;
|
||||
i = ((MEM_REG[0x91c>>1]>>3) & 7)+1;
|
||||
return ((SYS_CLK_FREQ * mdiv) / (pdiv << scale))/i;
|
||||
}
|
||||
|
||||
unsigned get_freq_DCLK()
|
||||
{
|
||||
unsigned i;
|
||||
unsigned reg,mdiv,pdiv,scale;
|
||||
reg=MEM_REG[0x912>>1];
|
||||
mdiv = ((reg & 0xff00) >> 8) + 8;
|
||||
pdiv = ((reg & 0xfc) >> 2) + 2;
|
||||
scale = reg & 3;
|
||||
i = ((MEM_REG[0x91c>>1]>>6) & 7)+1;
|
||||
return ((SYS_CLK_FREQ * mdiv) / (pdiv << scale))/i;
|
||||
}
|
||||
|
||||
void set_920_Div(unsigned short div)
|
||||
{
|
||||
printf ("set divider for CPU-Clock = %u\r\n",div+1);
|
||||
unsigned short v;
|
||||
v = MEM_REG[0x91c>>1] & (~0x3);
|
||||
MEM_REG[0x91c>>1] = (div & 0x7) | v;
|
||||
}
|
||||
|
||||
unsigned short get_920_Div()
|
||||
{
|
||||
return (MEM_REG[0x91c>>1] & 0x7);
|
||||
}
|
||||
|
||||
void set_940_Div(unsigned short div)
|
||||
{
|
||||
unsigned short v;
|
||||
v = (unsigned short)( MEM_REG[0x91c>>1] & (~(0x7 << 3)));
|
||||
MEM_REG[0x91c>>1] = ((div & 0x7) << 3) | v;
|
||||
}
|
||||
|
||||
unsigned short get_940_Div()
|
||||
{
|
||||
return ((MEM_REG[0x91c>>1] >> 3) & 0x7);
|
||||
}
|
||||
|
||||
void set_DCLK_Div( unsigned short div )
|
||||
{
|
||||
printf ("set divider for RAM-Clock = %u\r\n",div+1);
|
||||
unsigned short v;
|
||||
v = (unsigned short)( MEM_REG[0x91c>>1] & (~(0x7 << 6)));
|
||||
MEM_REG[0x91c>>1] = ((div & 0x7) << 6) | v;
|
||||
}
|
||||
|
||||
unsigned short get_DCLK_Div()
|
||||
{
|
||||
return ((MEM_REG[0x91c>>1] >> 6) & 0x7);
|
||||
}
|
||||
|
||||
unsigned short Disable_Int_920()
|
||||
{
|
||||
unsigned short ret;
|
||||
ret=MEM_REG[0x3B40>>1];
|
||||
MEM_REG[0x3B40>>1]=0;
|
||||
MEM_REG[0x3B44>>1]=0xffff;
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned short Disable_Int_940()
|
||||
{
|
||||
unsigned short ret;
|
||||
ret=MEM_REG[0x3B42>>1];
|
||||
MEM_REG[0x3B42>>1]=0;
|
||||
MEM_REG[0x3B46>>1]=0xffff;
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned get_state940()
|
||||
{
|
||||
return MEM_REG[0x904>>1];
|
||||
}
|
||||
|
||||
|
||||
void Enable_Int_920(unsigned short flag)
|
||||
{
|
||||
MEM_REG[0x3B40>>1]=flag;
|
||||
}
|
||||
|
||||
void Enable_Int_940(unsigned short flag)
|
||||
{
|
||||
MEM_REG[0x3B42>>1]=flag;
|
||||
}
|
||||
|
||||
void Disable_940()
|
||||
{
|
||||
Disable_Int_940();
|
||||
MEM_REG[0x3B48>>1]|= (1 << 7);
|
||||
MEM_REG[0x904>>1]&=0xfffe;
|
||||
}
|
||||
|
||||
void Load_940_code(unsigned *code,int size)
|
||||
{
|
||||
unsigned *cp;
|
||||
int i;
|
||||
arm940code=(unsigned short *)mmap(0, 0x100000, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_dev[2], 0x03000000);
|
||||
Disable_940();
|
||||
cp=(unsigned *) code;
|
||||
for (i = 0; i < size/4; i ++)
|
||||
{
|
||||
arm940code[i] = cp[i];
|
||||
}
|
||||
for (i = 0; i < 64; i ++)
|
||||
{
|
||||
arm940code[0x3FC0+i] = 0;
|
||||
}
|
||||
MEM_REG[0x3B48>>1]=(MEM_REG[0x3B48>>1] & 0xFF00) | 0x03; // allow 940
|
||||
}
|
||||
|
||||
void clock_940_off()
|
||||
{
|
||||
MEM_REG[0x904>>1]&=0xfffe;
|
||||
}
|
||||
|
||||
void clock_940_on()
|
||||
{
|
||||
MEM_REG[0x904>>1]|=1;
|
||||
}
|
||||
|
||||
|
||||
//--------------
|
||||
//Memory Timings
|
||||
//--------------
|
||||
|
||||
//get
|
||||
|
||||
unsigned get_CAS()
|
||||
{
|
||||
return ((MEM_REG[0x3804>>1] >> 12) & 0x1);
|
||||
}
|
||||
|
||||
unsigned get_tRC()
|
||||
{
|
||||
return ((MEM_REG[0x3804>>1] >> 8) & 0xF);
|
||||
}
|
||||
|
||||
unsigned get_tRAS()
|
||||
{
|
||||
return ((MEM_REG[0x3804>>1] >> 4) & 0xF);
|
||||
}
|
||||
|
||||
unsigned get_tWR()
|
||||
{
|
||||
return (MEM_REG[0x3804>>1] & 0xF);
|
||||
}
|
||||
|
||||
unsigned get_tMRD()
|
||||
{
|
||||
return ((MEM_REG[0x3802>>1] >> 12) & 0xF);
|
||||
}
|
||||
|
||||
unsigned get_tRFC()
|
||||
{
|
||||
return ((MEM_REG[0x3802>>1] >> 8) & 0xF);
|
||||
}
|
||||
|
||||
unsigned get_tRP()
|
||||
{
|
||||
return ((MEM_REG[0x3802>>1] >> 4) & 0xF);
|
||||
}
|
||||
|
||||
unsigned get_tRCD()
|
||||
{
|
||||
return (MEM_REG[0x3802>>1] & 0xF);
|
||||
}
|
||||
|
||||
unsigned get_REFPERD()
|
||||
{
|
||||
return MEM_REG[0x3808>>1];
|
||||
}
|
||||
|
||||
|
||||
//set
|
||||
|
||||
void set_CAS(unsigned short timing)
|
||||
{
|
||||
printf ("set CAS = %u\r\n",timing+2);
|
||||
unsigned short v;
|
||||
v = (unsigned short)(MEM_REG[0x3804>>1] & (~(0x1 << 12)));
|
||||
MEM_REG[0x3804>>1] = ((timing & 0x1) << 12) | v;
|
||||
}
|
||||
|
||||
void set_tRC(unsigned short timing)
|
||||
{
|
||||
printf ("set tRC = %u\r\n",timing+1);
|
||||
unsigned short v;
|
||||
v = (unsigned short)(MEM_REG[0x3804>>1] & (~(0xF << 8)));
|
||||
MEM_REG[0x3804>>1] = ((timing & 0xF) << 8) | v;
|
||||
}
|
||||
|
||||
void set_tRAS(unsigned short timing)
|
||||
{
|
||||
printf ("set tRAS = %u\r\n",timing+1);
|
||||
unsigned short v;
|
||||
v = (unsigned short)(MEM_REG[0x3804>>1] & (~(0xF << 4)));
|
||||
MEM_REG[0x3804>>1] = ((timing & 0xF) << 4) | v;
|
||||
}
|
||||
|
||||
void set_tWR(unsigned short timing)
|
||||
{
|
||||
printf ("set tWR = %u\r\n",timing+1);
|
||||
unsigned short v;
|
||||
v = (unsigned short)(MEM_REG[0x3804>>1] & (~(0xF)));
|
||||
MEM_REG[0x3804>>1] = (timing & 0xF) | v;
|
||||
}
|
||||
|
||||
void set_tMRD(unsigned short timing)
|
||||
{
|
||||
printf ("set tMRD = %u\r\n",timing+1);
|
||||
unsigned short v;
|
||||
v = (unsigned short)(MEM_REG[0x3802>>1] & (~(0xF << 12)));
|
||||
MEM_REG[0x3802>>1] = ((timing & 0xF) << 12) | v;
|
||||
}
|
||||
|
||||
void set_tRFC(unsigned short timing)
|
||||
{
|
||||
printf ("set tRFC = %u\r\n",timing+1);
|
||||
unsigned short v;
|
||||
v = (unsigned short)(MEM_REG[0x3802>>1] & (~(0xF << 8)));
|
||||
MEM_REG[0x3802>>1] = ((timing & 0xF) << 8) | v;
|
||||
}
|
||||
|
||||
void set_tRP(unsigned short timing)
|
||||
{
|
||||
printf ("set tRP = %u\r\n",timing+1);
|
||||
unsigned short v;
|
||||
v = (unsigned short)(MEM_REG[0x3802>>1] & (~(0xF << 4)));
|
||||
MEM_REG[0x3802>>1] = ((timing & 0xF) << 4) | v;
|
||||
}
|
||||
|
||||
void set_tRCD(unsigned short timing)
|
||||
{
|
||||
printf ("set tRCD = %u\r\n",timing+1);
|
||||
unsigned short v;
|
||||
v = (unsigned short)(MEM_REG[0x3802>>1] & (~(0xF)));
|
||||
MEM_REG[0x3802>>1] = (timing & 0xF) | v;
|
||||
}
|
||||
|
||||
void set_REFPERD(unsigned short timing)
|
||||
{
|
||||
printf ("set Refresh Period = %u\r\n",timing+1);
|
||||
MEM_REG[0x3808>>1] = timing;
|
||||
}
|
||||
|
||||
|
||||
//-----
|
||||
//Gamma
|
||||
//-----
|
||||
|
||||
void set_gamma(float gamma)
|
||||
{
|
||||
printf ("set gamma = %f\r\n",gamma);
|
||||
int i;
|
||||
gamma = 1/gamma;
|
||||
|
||||
//enable gamma
|
||||
MEM_REG[0x2880>>1]&=~(1<<12);
|
||||
|
||||
MEM_REG[0x295C>>1]=0;
|
||||
for(i=0; i<256; i++)
|
||||
{
|
||||
unsigned char g;
|
||||
unsigned short s;
|
||||
g =(unsigned char)(255.0*pow(i/255.0,gamma));
|
||||
s = (g<<8) | g;
|
||||
MEM_REG[0x295E>>1]= s;
|
||||
MEM_REG[0x295E>>1]= g;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned get_YBNKLVL()
|
||||
{
|
||||
return (MEM_REG[0x283A>>1] & 0x3FF);
|
||||
}
|
||||
|
||||
void set_YBNKLVL(unsigned short val)
|
||||
{
|
||||
unsigned short temp = (unsigned short)(MEM_REG[0x3808>>1] & (~(0x3FF)));
|
||||
MEM_REG[0x3808>>1] = (val & 0x3FF) | temp;
|
||||
}
|
72
gp2x/cpuctrl.h
Normal file
72
gp2x/cpuctrl.h
Normal file
@ -0,0 +1,72 @@
|
||||
#if !defined(_CPUCTRL_)
|
||||
#define _CPUCTRL_
|
||||
|
||||
void cpuctrl_init(); // call this at first
|
||||
|
||||
void save_system_regs(); // save some registers
|
||||
void load_system_regs();
|
||||
|
||||
void set_FCLK(unsigned MHZ); // adjust the clock frequency (in Mhz units)
|
||||
void set_add_ULCDCLK(int addclock);
|
||||
void set_add_FLCDCLK(int addclock);
|
||||
|
||||
unsigned get_FCLK();
|
||||
unsigned get_freq_UCLK();
|
||||
unsigned get_freq_ACLK();
|
||||
unsigned get_freq_920_CLK();
|
||||
unsigned get_freq_940_CLK();
|
||||
unsigned get_freq_DCLK();
|
||||
unsigned get_LCDClk();
|
||||
char get_Clkgen();
|
||||
unsigned get_state940();
|
||||
|
||||
void set_920_Div(unsigned short div); /* 0 to 7 divider (freq=FCLK/(1+div)) */
|
||||
unsigned short get_920_Div();
|
||||
|
||||
void set_940_Div(unsigned short div); /* 0 to 7 divider (freq=FCLK/(1+div)) */
|
||||
unsigned short get_940_Div();
|
||||
|
||||
void set_DCLK_Div(unsigned short div); /* 0 to 7 divider (freq=FCLK/(1+div)) */
|
||||
unsigned short get_DCLK_Div();
|
||||
|
||||
unsigned short Disable_Int_920();
|
||||
unsigned short Disable_Int_940();
|
||||
|
||||
void Enable_Int_920(unsigned short flag);
|
||||
void Enable_Int_940(unsigned short flag);
|
||||
|
||||
void Disable_940(); // 940t down
|
||||
|
||||
extern volatile unsigned *arm940code; // memory address of 940t code
|
||||
|
||||
void Load_940_code(unsigned *code,int size); // enable 940t, load 940t code and clock 940t off
|
||||
|
||||
void clock_940_off(); // 940t stops
|
||||
void clock_940_on(); // 940t running
|
||||
|
||||
//Memory Timings
|
||||
unsigned get_CAS(); //CAS Latency
|
||||
unsigned get_tRC(); //ACTIVE to ACTIVE /AUTOREFRESH command delay
|
||||
unsigned get_tRAS(); //ACTIVE to PRECHARGE delay
|
||||
unsigned get_tWR(); //Write recovery time
|
||||
unsigned get_tMRD(); //LOAD MODE REGISTER command cycle time
|
||||
unsigned get_tRFC(); //AUTO REFRESH command period
|
||||
unsigned get_tRP(); //PRECHARGE command period
|
||||
unsigned get_tRCD(); //RAS to CAS Delay
|
||||
unsigned get_REFPERD();//Refresh Period
|
||||
|
||||
void set_CAS();
|
||||
void set_tRC();
|
||||
void set_tRAS();
|
||||
void set_tWR();
|
||||
void set_tMRD();
|
||||
void set_tRFC();
|
||||
void set_tRP();
|
||||
void set_tRCD();
|
||||
void set_REFPERD();
|
||||
|
||||
void set_gamma(float gamma);
|
||||
|
||||
unsigned get_YBNKLVL();
|
||||
void set_YBNKLVL(unsigned short val);
|
||||
#endif
|
671
gp2x/daemon.c
Normal file
671
gp2x/daemon.c
Normal file
@ -0,0 +1,671 @@
|
||||
/* daemon.c for GP2X Version 2.0
|
||||
Copyright (C) 2006 jannis harder
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "gp2xminilib.h"
|
||||
#include "cpuctrl.h"
|
||||
#include "display.h"
|
||||
|
||||
#include "daemon.h"
|
||||
|
||||
|
||||
extern unsigned COLORFONDO; // background-color
|
||||
extern unsigned WHITE;
|
||||
extern unsigned TEXTBACK;
|
||||
|
||||
extern unsigned char cad[256];
|
||||
|
||||
extern unsigned short *gp2x_memregs;
|
||||
extern pthread_t gp2x_sound_thread;
|
||||
|
||||
int start_daemon(
|
||||
unsigned int minimal_cpu_speed, unsigned int maximal_cpu_speed, unsigned int start_cpu_speed, int cpu_speed_step,
|
||||
unsigned long hotkey, unsigned long incrementkey, unsigned long decrementkey,
|
||||
int speed_display, int foreground,
|
||||
unsigned long delay)
|
||||
{
|
||||
pid_t pid, sid;
|
||||
|
||||
if(!foreground) {
|
||||
kill_running_daemon();
|
||||
|
||||
|
||||
FILE * pidfile = fopen("/tmp/cpu_daemon.pid","w");
|
||||
|
||||
if(!pidfile) {
|
||||
printf("couldn't write pidfile\r\n");
|
||||
exit(-2);
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
|
||||
if(pid > 0) {
|
||||
fprintf(pidfile,"%i\n",pid);
|
||||
fclose(pidfile);
|
||||
}
|
||||
if(pid != 0)
|
||||
return pid;
|
||||
|
||||
|
||||
fclose(pidfile);
|
||||
|
||||
umask(0);
|
||||
sid = setsid();
|
||||
|
||||
|
||||
close(STDIN_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
}
|
||||
|
||||
if(foreground)
|
||||
printf("daemon ready\r\n");
|
||||
|
||||
nano_setup(); // loading the full minilib would be overkill and i guess some games/emus wouldn't like it
|
||||
|
||||
|
||||
unsigned int current_cpu_speed = start_cpu_speed;
|
||||
|
||||
while(1) {
|
||||
usleep(delay);
|
||||
unsigned long keystate = gp2x_joystick_read();
|
||||
|
||||
unsigned int last_cpu_speed = 0;
|
||||
|
||||
while(
|
||||
(hotkey && (keystate & hotkey) == hotkey) ||
|
||||
((!hotkey) && (
|
||||
(incrementkey && (keystate & incrementkey) == incrementkey) ||
|
||||
(decrementkey && (keystate & decrementkey) == decrementkey)
|
||||
))
|
||||
) {
|
||||
if(foreground && !last_cpu_speed)
|
||||
printf("cpu daemon activated!\r\n");
|
||||
|
||||
if(incrementkey && (keystate & incrementkey) == incrementkey) {
|
||||
current_cpu_speed += cpu_speed_step;
|
||||
while((keystate & incrementkey) == incrementkey) usleep(100000),keystate = gp2x_joystick_read();
|
||||
}
|
||||
else if(decrementkey && (keystate & decrementkey) == decrementkey) {
|
||||
current_cpu_speed -= cpu_speed_step;
|
||||
while((keystate & decrementkey) == decrementkey) usleep(100000),keystate = gp2x_joystick_read();
|
||||
}
|
||||
|
||||
if(current_cpu_speed < minimal_cpu_speed)
|
||||
current_cpu_speed = minimal_cpu_speed;
|
||||
if(current_cpu_speed > maximal_cpu_speed)
|
||||
current_cpu_speed = maximal_cpu_speed;
|
||||
|
||||
|
||||
|
||||
if(last_cpu_speed != current_cpu_speed) {
|
||||
set_FCLK(current_cpu_speed);
|
||||
}
|
||||
last_cpu_speed = current_cpu_speed;
|
||||
keystate = gp2x_joystick_read();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int kill_running_daemon() {
|
||||
|
||||
FILE * pidfile = fopen("/tmp/cpu_daemon.pid","r");
|
||||
char pid_buffer[14];
|
||||
pid_buffer[0] = 'k';
|
||||
pid_buffer[1] = 'i';
|
||||
pid_buffer[2] = 'l';
|
||||
pid_buffer[3] = 'l';
|
||||
pid_buffer[4] = ' ';
|
||||
pid_buffer[5] = 0;
|
||||
if(pidfile) {
|
||||
printf("found pidfile\r\n");
|
||||
fgets(&(pid_buffer[5]),10,pidfile);
|
||||
fclose(pidfile);
|
||||
int return_code = system(pid_buffer);
|
||||
if(return_code)
|
||||
printf("daemon wasn't running\r\n");
|
||||
else
|
||||
printf("killed old daemon\r\n");
|
||||
unlink("/tmp/cpu_daemon.pid");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void nano_setup() {
|
||||
if(!gp2x_sound_thread) {
|
||||
gp2x_memregs=(unsigned short *)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, open("/dev/mem", O_RDWR), 0xc0000000);
|
||||
cpuctrl_init();
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_daemon(int argc, char *argv[]) {
|
||||
|
||||
int cpu_div = get_920_Div();
|
||||
int sysfreq=get_freq_920_CLK();
|
||||
sysfreq*=cpu_div+1;
|
||||
int cpufreq=sysfreq/1000000;
|
||||
|
||||
unsigned int minimal_value = 33;
|
||||
unsigned int maximal_value = 260;
|
||||
unsigned int start_value = cpufreq;
|
||||
unsigned int step = 10;
|
||||
unsigned long hotkey = GP2X_L | GP2X_R;
|
||||
unsigned long downkey = GP2X_VOL_UP;
|
||||
unsigned long upkey = GP2X_VOL_DOWN;
|
||||
int foreground = 0;
|
||||
int display = 1;
|
||||
float delay = 1;
|
||||
|
||||
int i;
|
||||
for( i = 2; i < argc; i++) {
|
||||
if(!strcmp(argv[i],"--min")) {
|
||||
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||
minimal_value = atoi(argv[i+1]);
|
||||
if(minimal_value < 33)
|
||||
minimal_value = 33;
|
||||
}
|
||||
else if(!strcmp(argv[i],"--max")) {
|
||||
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||
maximal_value = atoi(argv[i+1]);
|
||||
if(maximal_value > 340)
|
||||
maximal_value = 340;
|
||||
}
|
||||
else if(!strcmp(argv[i],"--start")) {
|
||||
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||
start_value = atoi(argv[i+1]);
|
||||
}
|
||||
else if(!strcmp(argv[i],"--step")) {
|
||||
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||
step = atoi(argv[i+1]);
|
||||
}
|
||||
else if(!strcmp(argv[i],"--hotkey")) {
|
||||
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||
hotkey = parse_key_sequence(argv[i+1]);
|
||||
}
|
||||
else if(!strcmp(argv[i],"--incr")) {
|
||||
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||
upkey = parse_key_sequence(argv[i+1]);
|
||||
}
|
||||
else if(!strcmp(argv[i],"--decr")) {
|
||||
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||
downkey = parse_key_sequence(argv[i+1]);
|
||||
}
|
||||
else if(!strcmp(argv[i],"--delay")) {
|
||||
if(i+1 == argc){printf ("%s is missing it's parameter\r\n",argv[i]);gp2x_deinit();exit(1);}
|
||||
delay = atof(argv[i+1]);
|
||||
}
|
||||
else if(!strcmp(argv[i],"--no-incr")) {
|
||||
upkey = 0;
|
||||
}
|
||||
else if(!strcmp(argv[i],"--no-decr")) {
|
||||
downkey = 0;
|
||||
}
|
||||
else if(!strcmp(argv[i],"--no-hotkey")) {
|
||||
hotkey = 0;
|
||||
}
|
||||
else if(!strcmp(argv[i],"--foreground")) {
|
||||
foreground = 1;
|
||||
}
|
||||
else if(!strcmp(argv[i],"--background")) {
|
||||
foreground = 0;
|
||||
}
|
||||
else if(!strcmp(argv[i],"--display")) {
|
||||
display = 1;
|
||||
}
|
||||
else if(!strcmp(argv[i],"--no-display")) {
|
||||
display = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if((hotkey & downkey) == downkey)
|
||||
printf("warning: hotkey includes decrement keypress!\r\n");
|
||||
if((hotkey & upkey) == upkey)
|
||||
printf("warning: hotkey includes increment keypress!\r\n");
|
||||
|
||||
int pid = start_daemon(minimal_value, maximal_value, start_value, step, hotkey, upkey, downkey, display, foreground, delay* 1000000);
|
||||
|
||||
if(pid < 0) {
|
||||
printf("couldn't start daemon\r\n");
|
||||
exit(1);
|
||||
}
|
||||
else if(pid > 0) {
|
||||
printf("daemon started\r\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long parse_key_sequence(char *key_sequence) {
|
||||
unsigned long hotkey = 0;
|
||||
if(!strcmp(key_sequence,"None"))
|
||||
return 0;
|
||||
char *mask = key_sequence;
|
||||
while(*mask) {
|
||||
switch(*mask) {
|
||||
case 'l':
|
||||
case 'L':
|
||||
hotkey |= GP2X_L;
|
||||
break;
|
||||
case 'r':
|
||||
case 'R':
|
||||
hotkey |= GP2X_R;
|
||||
break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
hotkey |= GP2X_A;
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
hotkey |= GP2X_B;
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
hotkey |= GP2X_X;
|
||||
break;
|
||||
case 'y':
|
||||
case 'Y':
|
||||
hotkey |= GP2X_Y;
|
||||
break;
|
||||
case '+':
|
||||
hotkey |= GP2X_VOL_DOWN;
|
||||
break;
|
||||
case '-':
|
||||
hotkey |= GP2X_VOL_UP;
|
||||
break;
|
||||
case 'S':
|
||||
case 's':
|
||||
hotkey |= GP2X_START;
|
||||
break;
|
||||
case '/':
|
||||
hotkey |= GP2X_SELECT;
|
||||
break;
|
||||
case '@':
|
||||
hotkey |= GP2X_PUSH;
|
||||
break;
|
||||
case '\n':
|
||||
break;
|
||||
default:
|
||||
printf("unknown key %c\r\n",*mask);
|
||||
}
|
||||
mask++;
|
||||
}
|
||||
return hotkey;
|
||||
}
|
||||
|
||||
int daemonsettings[8];
|
||||
|
||||
|
||||
void cleardisp();
|
||||
|
||||
|
||||
void formatkey(char * base, unsigned long keyseq) {
|
||||
|
||||
if(!keyseq)
|
||||
strcat(base,"None");
|
||||
|
||||
if(keyseq & GP2X_L)
|
||||
strcat(base,"L");
|
||||
if(keyseq & GP2X_R)
|
||||
strcat(base,"R");
|
||||
if(keyseq & GP2X_A)
|
||||
strcat(base,"A");
|
||||
if(keyseq & GP2X_B)
|
||||
strcat(base,"B");
|
||||
if(keyseq & GP2X_X)
|
||||
strcat(base,"X");
|
||||
if(keyseq & GP2X_Y)
|
||||
strcat(base,"Y");
|
||||
if(keyseq & GP2X_VOL_DOWN)
|
||||
strcat(base,"+");
|
||||
if(keyseq & GP2X_VOL_UP)
|
||||
strcat(base,"-");
|
||||
if(keyseq & GP2X_START)
|
||||
strcat(base,"S");
|
||||
if(keyseq & GP2X_SELECT)
|
||||
strcat(base,"/");
|
||||
if(keyseq & GP2X_PUSH)
|
||||
strcat(base,"@");
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define VALID_KEYS ((GP2X_L) | (GP2X_R) | (GP2X_X) | (GP2X_Y) | (GP2X_A) | (GP2X_B) | (GP2X_START) | (GP2X_SELECT) | (GP2X_VOL_UP) | (GP2X_VOL_DOWN) | (GP2X_PUSH) )
|
||||
|
||||
int running;
|
||||
|
||||
void daemon_itemhelp(int menuitem)
|
||||
{
|
||||
switch(menuitem) {
|
||||
case 0:
|
||||
v_putcad(26,8,0xffffff,COLORFONDO,"Choose a");
|
||||
v_putcad(26,9,0xffffff,COLORFONDO,"minimal");
|
||||
v_putcad(26,10,0xffffff,COLORFONDO,"clockspeed");
|
||||
v_putcad(26,11,0xffffff,COLORFONDO,"with R/L or");
|
||||
v_putcad(26,12,0xffffff,COLORFONDO,"Vol UP/Down.");
|
||||
v_putcad(26,14,0xffffff,COLORFONDO,"Valid speeds");
|
||||
v_putcad(26,15,0xffffff,COLORFONDO,"are:");
|
||||
v_putcad(26,16,0xffffff,COLORFONDO,"33 to 340Mhz");
|
||||
break;
|
||||
case 1:
|
||||
v_putcad(26,8,0xffffff,COLORFONDO,"Choose a");
|
||||
v_putcad(26,9,0xffffff,COLORFONDO,"maximal");
|
||||
v_putcad(26,10,0xffffff,COLORFONDO,"clockspeed");
|
||||
v_putcad(26,11,0xffffff,COLORFONDO,"with R/L or");
|
||||
v_putcad(26,12,0xffffff,COLORFONDO,"Vol UP/Down.");
|
||||
v_putcad(26,14,0xffffff,COLORFONDO,"Valid speeds");
|
||||
v_putcad(26,15,0xffffff,COLORFONDO,"are:");
|
||||
v_putcad(26,16,0xffffff,COLORFONDO,"33 to 340Mhz");
|
||||
break;
|
||||
case 2:
|
||||
v_putcad(26,8,0xffffff,COLORFONDO,"Choose a step");
|
||||
v_putcad(26,9,0xffffff,COLORFONDO,"width for");
|
||||
v_putcad(26,10,0xffffff,COLORFONDO,"changing the");
|
||||
v_putcad(26,11,0xffffff,COLORFONDO,"clockspeed.");
|
||||
v_putcad(26,13,0xffffff,COLORFONDO,"Use R/L or");
|
||||
v_putcad(26,14,0xffffff,COLORFONDO,"Vol UP/Down.");
|
||||
break;
|
||||
case 3:
|
||||
v_putcad(26,8,0xffffff,COLORFONDO,"Choose a");
|
||||
v_putcad(26,9,0xffffff,COLORFONDO,"delay between");
|
||||
v_putcad(26,10,0xffffff,COLORFONDO,"each hotkey");
|
||||
v_putcad(26,11,0xffffff,COLORFONDO,"check");
|
||||
v_putcad(26,13,0xffffff,COLORFONDO,"Use R/L or");
|
||||
v_putcad(26,14,0xffffff,COLORFONDO,"Vol UP/Down.");
|
||||
break;
|
||||
case 4:
|
||||
v_putcad(26,8,0xffffff,COLORFONDO,"Choose a");
|
||||
v_putcad(26,9,0xffffff,COLORFONDO,"hotkey.");
|
||||
v_putcad(26,10,0xffffff,COLORFONDO,"Add or delete");
|
||||
v_putcad(26,11,0xffffff,COLORFONDO,"a button by");
|
||||
v_putcad(26,12,0xffffff,COLORFONDO,"pressing it.");
|
||||
v_putcad(26,14,0x0000DD,COLORFONDO,"Joystick is");
|
||||
v_putcad(26,15,0x0000DD,COLORFONDO,"not allowed.");
|
||||
break;
|
||||
case 5:
|
||||
v_putcad(26,8,0xffffff,COLORFONDO,"Choose a");
|
||||
v_putcad(26,9,0xffffff,COLORFONDO,"key for");
|
||||
v_putcad(26,10,0xffffff,COLORFONDO,"incrementing");
|
||||
v_putcad(26,11,0xffffff,COLORFONDO,"the clkspeed.");
|
||||
v_putcad(26,12,0xffffff,COLORFONDO,"Add or delete");
|
||||
v_putcad(26,13,0xffffff,COLORFONDO,"a button by");
|
||||
v_putcad(26,14,0xffffff,COLORFONDO,"pressing it.");
|
||||
v_putcad(26,16,0x0000DD,COLORFONDO,"Joystick is");
|
||||
v_putcad(26,17,0x0000DD,COLORFONDO,"not allowed.");
|
||||
break;
|
||||
case 6:
|
||||
v_putcad(26,8,0xffffff,COLORFONDO,"Choose a");
|
||||
v_putcad(26,9,0xffffff,COLORFONDO,"key for");
|
||||
v_putcad(26,10,0xffffff,COLORFONDO,"decrementing");
|
||||
v_putcad(26,11,0xffffff,COLORFONDO,"the clkspeed.");
|
||||
v_putcad(26,12,0xffffff,COLORFONDO,"Add or delete");
|
||||
v_putcad(26,13,0xffffff,COLORFONDO,"a button by");
|
||||
v_putcad(26,14,0xffffff,COLORFONDO,"pressing it.");
|
||||
v_putcad(26,16,0x0000DD,COLORFONDO,"Joystick is");
|
||||
v_putcad(26,17,0x0000DD,COLORFONDO,"not allowed.");
|
||||
break;
|
||||
case 7:
|
||||
/* v_putcad(26,8,0xffffff,COLORFONDO,"Enable or");
|
||||
v_putcad(26,9,0xffffff,COLORFONDO,"disable");
|
||||
v_putcad(26,10,0xffffff,COLORFONDO,"on screen");
|
||||
v_putcad(26,11,0xffffff,COLORFONDO,"display.");
|
||||
v_putcad(26,13,0x0000DD,COLORFONDO,"May cause");
|
||||
v_putcad(26,14,0x0000DD,COLORFONDO,"conflicts");
|
||||
v_putcad(26,15,0x0000DD,COLORFONDO,"with");
|
||||
v_putcad(26,16,0x0000DD,COLORFONDO,"some apps!");*/
|
||||
v_putcad(26,8,0x0000DD,COLORFONDO,"COMING SOON");
|
||||
break;
|
||||
case 8:
|
||||
if(running) {
|
||||
v_putcad(26,8,0xffffff,COLORFONDO,"Press B to");
|
||||
v_putcad(26,9,0xffffff,COLORFONDO,"kill the");
|
||||
v_putcad(26,10,0xffffff,COLORFONDO,"running");
|
||||
v_putcad(26,11,0xffffff,COLORFONDO,"daemon");
|
||||
v_putcad(26,12,0xffffff,COLORFONDO,"process.");
|
||||
}
|
||||
else {
|
||||
v_putcad(26,8,0xffffff,COLORFONDO,"Press B to");
|
||||
v_putcad(26,9,0xffffff,COLORFONDO,"start the ");
|
||||
v_putcad(26,10,0xffffff,COLORFONDO,"daemon in the");
|
||||
v_putcad(26,11,0xffffff,COLORFONDO, "background.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void daemonmenu() {
|
||||
|
||||
int menupoint = 0;
|
||||
running = !access("/tmp/cpu_daemon.pid",R_OK);
|
||||
|
||||
|
||||
unsigned long gp2x_nKeys;
|
||||
while(1) {
|
||||
|
||||
if(daemonsettings[0] < 33)
|
||||
daemonsettings[0] = 33;
|
||||
if(daemonsettings[1] > 340)
|
||||
daemonsettings[1] = 340;
|
||||
if(daemonsettings[1] < daemonsettings[0])
|
||||
daemonsettings[1] = daemonsettings[0];
|
||||
if(daemonsettings[0] > daemonsettings[1])
|
||||
daemonsettings[0] = daemonsettings[1];
|
||||
if(daemonsettings[2] < 1)
|
||||
daemonsettings[2] = 1;
|
||||
if(daemonsettings[3] < 1)
|
||||
daemonsettings[3] = 1;
|
||||
//if(daemonsettings[7] == 10 || daemonsettings[7] == -10)
|
||||
// daemonsettings[7] = 1;
|
||||
//if(daemonsettings[7] == 11 || daemonsettings[7] == -9)
|
||||
daemonsettings[7] = 0;
|
||||
|
||||
|
||||
|
||||
cleardisp();
|
||||
v_putcad(13,2,WHITE,COLORFONDO,"Daemon Setup");
|
||||
|
||||
v_putcad(2,5,0xffff00,COLORFONDO,"CPU Clockspeed:");
|
||||
|
||||
sprintf(cad,"From: %huMhz",daemonsettings[0]);
|
||||
|
||||
v_putcad(2,7,0xffff,COLORFONDO,cad);
|
||||
if(menupoint == 0)
|
||||
v_putcad(2,7,0xffff,TEXTBACK,cad);
|
||||
|
||||
sprintf(cad,"To: %huMhz",daemonsettings[1]);
|
||||
|
||||
v_putcad(2,8,0xffff,COLORFONDO,cad);
|
||||
if(menupoint == 1)
|
||||
v_putcad(2,8,0xffff,TEXTBACK,cad);
|
||||
|
||||
sprintf(cad,"Step: %huMhz",daemonsettings[2]);
|
||||
|
||||
v_putcad(2,9,0xffff,COLORFONDO,cad);
|
||||
if(menupoint == 2)
|
||||
v_putcad(2,9,0xffff,TEXTBACK,cad);
|
||||
|
||||
|
||||
v_putcad(2,11,0xffff00,COLORFONDO,"Buttons:");
|
||||
|
||||
sprintf(cad,"Delay: %0.1fsec",daemonsettings[3]/10.0f);
|
||||
|
||||
v_putcad(2,13,0xffff,COLORFONDO,cad);
|
||||
if(menupoint == 3)
|
||||
v_putcad(2,13,0xffff,TEXTBACK,cad);
|
||||
|
||||
sprintf(cad,"Hotkey: ");
|
||||
|
||||
formatkey(cad,daemonsettings[4]);
|
||||
|
||||
v_putcad(2,15,0xffff,COLORFONDO,cad);
|
||||
if(menupoint == 4)
|
||||
v_putcad(2,15,0xffff,TEXTBACK,cad);
|
||||
|
||||
|
||||
sprintf(cad,"IncrKey: ");
|
||||
|
||||
formatkey(cad,daemonsettings[5]);
|
||||
|
||||
v_putcad(2,16,0xffff,COLORFONDO,cad);
|
||||
if(menupoint == 5)
|
||||
v_putcad(2,16,0xffff,TEXTBACK,cad);
|
||||
|
||||
sprintf(cad,"DecrKey: ");
|
||||
|
||||
formatkey(cad,daemonsettings[6]);
|
||||
|
||||
v_putcad(2,17,0xffff,COLORFONDO,cad);
|
||||
if(menupoint == 6)
|
||||
v_putcad(2,17,0xffff,TEXTBACK,cad);
|
||||
|
||||
if(menupoint >= 4 && menupoint <=6)
|
||||
v_putcad(2,26,WHITE,COLORFONDO,"---------- Stick:UP/DOWN");
|
||||
|
||||
v_putcad(2,19,0xffff00,COLORFONDO,"Misc:");
|
||||
|
||||
|
||||
v_putcad(2,21,0xffff,COLORFONDO,(daemonsettings[7] ? "On Screen Display: On" : "On Screen Display: Off"));
|
||||
if(menupoint == 7)
|
||||
v_putcad(2,21,0xffff,TEXTBACK,(daemonsettings[7] ? "On Screen Display: On" : "On Screen Display: Off"));
|
||||
|
||||
|
||||
v_putcad(2,23,0xffff,COLORFONDO,(running ? "Kill Running Daemon" : "Start Daemon"));
|
||||
if(menupoint == 8)
|
||||
v_putcad(2,23,0xffff,TEXTBACK,(running ? "Kill Running Daemon" : "Start Daemon"));
|
||||
|
||||
|
||||
|
||||
daemon_itemhelp(menupoint);
|
||||
|
||||
gp2x_video_flip();
|
||||
while(1)
|
||||
{
|
||||
gp2x_nKeys=gp2x_joystick_read();
|
||||
|
||||
|
||||
|
||||
if((gp2x_nKeys & GP2X_DOWN))
|
||||
{
|
||||
menupoint++;
|
||||
if(menupoint>8) menupoint=0;
|
||||
usleep(200000);
|
||||
break;
|
||||
}
|
||||
|
||||
if((gp2x_nKeys & GP2X_UP))
|
||||
{
|
||||
menupoint--;
|
||||
if(menupoint<0) menupoint=8;
|
||||
usleep(200000);
|
||||
break;
|
||||
}
|
||||
|
||||
if((menupoint >= 4) && (menupoint <= 6) && (gp2x_nKeys & VALID_KEYS))
|
||||
{
|
||||
daemonsettings[menupoint] ^= (gp2x_nKeys & VALID_KEYS);
|
||||
usleep(200000);
|
||||
break;
|
||||
}
|
||||
|
||||
if(menupoint < 8 &&(gp2x_nKeys & GP2X_R))
|
||||
{
|
||||
daemonsettings[menupoint] += 10;
|
||||
usleep(200000);
|
||||
break;
|
||||
}
|
||||
|
||||
if(menupoint < 4 && (gp2x_nKeys & GP2X_VOL_UP))
|
||||
{
|
||||
daemonsettings[menupoint] -= 1;
|
||||
usleep(200000);
|
||||
break;
|
||||
}
|
||||
|
||||
if(menupoint < 4 && (gp2x_nKeys & GP2X_VOL_DOWN))
|
||||
{
|
||||
daemonsettings[menupoint] += 1;
|
||||
usleep(200000);
|
||||
break;
|
||||
}
|
||||
|
||||
if(menupoint < 8 && (gp2x_nKeys & GP2X_L))
|
||||
{
|
||||
daemonsettings[menupoint] -= 10;
|
||||
usleep(200000);
|
||||
break;
|
||||
}
|
||||
if(menupoint == 8 && (gp2x_nKeys & GP2X_B))
|
||||
{
|
||||
if(running)
|
||||
kill_running_daemon();
|
||||
else {
|
||||
int cpu_div = get_920_Div();
|
||||
int sysfreq=get_freq_920_CLK();
|
||||
sysfreq*=cpu_div+1;
|
||||
int cpufreq=sysfreq/1000000;
|
||||
|
||||
start_daemon_by_settings();
|
||||
}
|
||||
usleep(200000);
|
||||
running = !access("/tmp/cpu_daemon.pid",R_OK);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if((gp2x_nKeys & GP2X_START))
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
gp2x_nKeys=gp2x_joystick_read();
|
||||
if(!(gp2x_nKeys & GP2X_START)) break;
|
||||
}
|
||||
|
||||
if(running) { // update values!
|
||||
start_daemon_by_settings();
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void start_daemon_by_settings() {
|
||||
int cpu_div = get_920_Div();
|
||||
int sysfreq=get_freq_920_CLK();
|
||||
sysfreq*=cpu_div+1;
|
||||
int cpufreq=sysfreq/1000000;
|
||||
|
||||
start_daemon(daemonsettings[0], daemonsettings[1], cpufreq, daemonsettings[2], daemonsettings[4], daemonsettings[5],
|
||||
daemonsettings[6], daemonsettings[7], 0, daemonsettings[3] * 100000);
|
||||
}
|
18
gp2x/daemon.h
Normal file
18
gp2x/daemon.h
Normal file
@ -0,0 +1,18 @@
|
||||
int start_daemon(
|
||||
unsigned int minimal_cpu_speed, unsigned int maximal_cpu_speed, unsigned int start_cpu_speed, int cpu_speed_step,
|
||||
unsigned long hotkey, unsigned long incrementkey, unsigned long decrmentkey,
|
||||
int speed_display, int foreground,
|
||||
unsigned long delay);
|
||||
|
||||
int kill_running_daemon();
|
||||
|
||||
void nano_setup();
|
||||
void cmd_daemon(int argc, char *argv[]);
|
||||
|
||||
unsigned long parse_key_sequence(char *key_sequence);
|
||||
|
||||
void daemonmenu();
|
||||
|
||||
void formatkey(char * base, unsigned long keyseq);
|
||||
|
||||
void start_daemon_by_settings();
|
139
gp2x/display.c
Normal file
139
gp2x/display.c
Normal file
@ -0,0 +1,139 @@
|
||||
/* display.c for GP2X (CPU/LCD/RAM-Tuner Version 2.0)
|
||||
Copyright (C) 2006 god_at_hell
|
||||
original CPU-Overclocker (c) by Hermes/PS2Reality
|
||||
parts (c) Rlyehs Work
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "gp2xminilib.h"
|
||||
#include "cpuctrl.h"
|
||||
#define WIDTH 320
|
||||
#define HEIGHT 240
|
||||
|
||||
//unsigned TEXTBACK=0x900000; // text-background-color
|
||||
|
||||
extern unsigned char msx[]; // define la fuente externa usada para dibujar letras y numeros
|
||||
|
||||
void ClearScreen(unsigned val) // se usa para 'borrar' la pantalla virtual con un color
|
||||
{
|
||||
int n;
|
||||
unsigned char *c;
|
||||
unsigned short col;
|
||||
c=&val;
|
||||
col=gp2x_video_color15(c[0],c[1],c[2],0);
|
||||
for(n=0;n<320*240;n++)
|
||||
{
|
||||
gp2x_screen15[n]=col;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawBox(unsigned val)
|
||||
{
|
||||
int n;
|
||||
unsigned char *c;
|
||||
unsigned short col;
|
||||
c=&val;
|
||||
col=gp2x_video_color15(c[0],c[1],c[2],0);
|
||||
|
||||
for(n=320*27+2;n<320*28-1;n++)
|
||||
{
|
||||
gp2x_screen15[n]=col;
|
||||
gp2x_screen15[n+320*209]=col;
|
||||
}
|
||||
|
||||
for(n=320*29+4;n<320*30-3;n++)
|
||||
{
|
||||
gp2x_screen15[n]=col;
|
||||
gp2x_screen15[n+320*169]=col;
|
||||
gp2x_screen15[n+320*205]=col;
|
||||
}
|
||||
|
||||
for(n=320*28;n<320*237;n=n+320)
|
||||
{
|
||||
gp2x_screen15[n+2]=col;
|
||||
gp2x_screen15[n-2]=col;
|
||||
}
|
||||
|
||||
for(n=320*30;n<320*235;n=n+320)
|
||||
{
|
||||
gp2x_screen15[n+4]=col;
|
||||
gp2x_screen15[n-4]=col;
|
||||
}
|
||||
|
||||
for(n=320*30;n<320*199;n=n+320)
|
||||
{
|
||||
gp2x_screen15[n-120]=col;
|
||||
}
|
||||
|
||||
for(n=320*55-120;n<320*55-4;n++)
|
||||
{
|
||||
gp2x_screen15[n]=col;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void v_putchar( unsigned x, unsigned y, unsigned color, unsigned textback, unsigned char ch) // rutina usada para dibujar caracteres (coordenadas de 8x8)
|
||||
{
|
||||
int i,j,v;
|
||||
unsigned char *font;
|
||||
unsigned char *c;
|
||||
unsigned short col,col2;
|
||||
if(x>=WIDTH || y>=HEIGHT) return;
|
||||
c=&color;
|
||||
col=gp2x_video_color15(c[0],c[1],c[2],0);
|
||||
c=&textback;
|
||||
col2=gp2x_video_color15(c[0],c[1],c[2],0);
|
||||
v=(y*320*8);
|
||||
font = &msx[ (int)ch * 8];
|
||||
for (i=0; i < 8; i++, font++)
|
||||
{
|
||||
for (j=0; j < 8; j++)
|
||||
{
|
||||
if ((*font & (128 >> j)))
|
||||
{
|
||||
gp2x_screen15[v+(((x<<3)+j))]=col;
|
||||
}
|
||||
else gp2x_screen15[v+(((x<<3)+j))]=col2;
|
||||
}
|
||||
v+=WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
// display array of chars
|
||||
|
||||
void v_putcad(int x,int y,unsigned color,unsigned textback,char *cad) // dibuja una cadena de texto
|
||||
{
|
||||
while(cad[0]!=0) {v_putchar(x,y,color,textback,cad[0]);cad++;x++;}
|
||||
}
|
||||
|
||||
|
||||
void gp2x_sound_frame(void *unused, unsigned char *stream, int samples)
|
||||
{
|
||||
int n;
|
||||
short *pu;
|
||||
pu=stream;
|
||||
for(n=0;n<(samples);n++)
|
||||
{
|
||||
*pu++=0;*pu++=0;
|
||||
}
|
||||
}
|
5
gp2x/display.h
Normal file
5
gp2x/display.h
Normal file
@ -0,0 +1,5 @@
|
||||
void ClearScreen(unsigned val);
|
||||
void DrawBox(unsigned val);
|
||||
void v_putchar( unsigned x, unsigned y, unsigned color, unsigned textback, unsigned char ch);
|
||||
void v_putcad(int x,int y,unsigned color,unsigned textback,char *cad);
|
||||
void gp2x_sound_frame(void *unused, unsigned char *stream, int samples);
|
143
gp2x/font.c
Normal file
143
gp2x/font.c
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
_____ ___ ____
|
||||
____| | ____| PSX2 OpenSource Project
|
||||
| ___| |____ (C)2001, Gustavo Scotti (gustavo@scotti.com)
|
||||
------------------------------------------------------------------------
|
||||
font.c
|
||||
EE UGLY DEBUG ON SCREEN - FONT BASE
|
||||
This is mostly based on Duke's work
|
||||
*/
|
||||
//#include <tamtypes.h>
|
||||
|
||||
unsigned char msx[]=
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x3c\x42\xa5\x81\xa5\x99\x42\x3c"
|
||||
"\x3c\x7e\xdb\xff\xff\xdb\x66\x3c\x6c\xfe\xfe\xfe\x7c\x38\x10\x00"
|
||||
"\x10\x38\x7c\xfe\x7c\x38\x10\x00\x10\x38\x54\xfe\x54\x10\x38\x00"
|
||||
"\x10\x38\x7c\xfe\xfe\x10\x38\x00\x00\x00\x00\x30\x30\x00\x00\x00"
|
||||
"\xff\xff\xff\xe7\xe7\xff\xff\xff\x38\x44\x82\x82\x82\x44\x38\x00"
|
||||
"\xc7\xbb\x7d\x7d\x7d\xbb\xc7\xff\x0f\x03\x05\x79\x88\x88\x88\x70"
|
||||
"\x38\x44\x44\x44\x38\x10\x7c\x10\x30\x28\x24\x24\x28\x20\xe0\xc0"
|
||||
"\x3c\x24\x3c\x24\x24\xe4\xdc\x18\x10\x54\x38\xee\x38\x54\x10\x00"
|
||||
"\x10\x10\x10\x7c\x10\x10\x10\x10\x10\x10\x10\xff\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\xff\x10\x10\x10\x10\x10\x10\x10\xf0\x10\x10\x10\x10"
|
||||
"\x10\x10\x10\x1f\x10\x10\x10\x10\x10\x10\x10\xff\x10\x10\x10\x10"
|
||||
"\x10\x10\x10\x10\x10\x10\x10\x10\x00\x00\x00\xff\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x1f\x10\x10\x10\x10\x00\x00\x00\xf0\x10\x10\x10\x10"
|
||||
"\x10\x10\x10\x1f\x00\x00\x00\x00\x10\x10\x10\xf0\x00\x00\x00\x00"
|
||||
"\x81\x42\x24\x18\x18\x24\x42\x81\x01\x02\x04\x08\x10\x20\x40\x80"
|
||||
"\x80\x40\x20\x10\x08\x04\x02\x01\x00\x10\x10\xff\x10\x10\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x20\x20\x20\x20\x00\x00\x20\x00"
|
||||
"\x50\x50\x50\x00\x00\x00\x00\x00\x50\x50\xf8\x50\xf8\x50\x50\x00"
|
||||
"\x20\x78\xa0\x70\x28\xf0\x20\x00\xc0\xc8\x10\x20\x40\x98\x18\x00"
|
||||
"\x40\xa0\x40\xa8\x90\x98\x60\x00\x10\x20\x40\x00\x00\x00\x00\x00"
|
||||
"\x10\x20\x40\x40\x40\x20\x10\x00\x40\x20\x10\x10\x10\x20\x40\x00"
|
||||
"\x20\xa8\x70\x20\x70\xa8\x20\x00\x00\x20\x20\xf8\x20\x20\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x20\x20\x40\x00\x00\x00\x78\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x60\x60\x00\x00\x00\x08\x10\x20\x40\x80\x00"
|
||||
"\x70\x88\x98\xa8\xc8\x88\x70\x00\x20\x60\xa0\x20\x20\x20\xf8\x00"
|
||||
"\x70\x88\x08\x10\x60\x80\xf8\x00\x70\x88\x08\x30\x08\x88\x70\x00"
|
||||
"\x10\x30\x50\x90\xf8\x10\x10\x00\xf8\x80\xe0\x10\x08\x10\xe0\x00"
|
||||
"\x30\x40\x80\xf0\x88\x88\x70\x00\xf8\x88\x10\x20\x20\x20\x20\x00"
|
||||
"\x70\x88\x88\x70\x88\x88\x70\x00\x70\x88\x88\x78\x08\x10\x60\x00"
|
||||
"\x00\x00\x20\x00\x00\x20\x00\x00\x00\x00\x20\x00\x00\x20\x20\x40"
|
||||
"\x18\x30\x60\xc0\x60\x30\x18\x00\x00\x00\xf8\x00\xf8\x00\x00\x00"
|
||||
"\xc0\x60\x30\x18\x30\x60\xc0\x00\x70\x88\x08\x10\x20\x00\x20\x00"
|
||||
"\x70\x88\x08\x68\xa8\xa8\x70\x00\x20\x50\x88\x88\xf8\x88\x88\x00"
|
||||
"\xf0\x48\x48\x70\x48\x48\xf0\x00\x30\x48\x80\x80\x80\x48\x30\x00"
|
||||
"\xe0\x50\x48\x48\x48\x50\xe0\x00\xf8\x80\x80\xf0\x80\x80\xf8\x00"
|
||||
"\xf8\x80\x80\xf0\x80\x80\x80\x00\x70\x88\x80\xb8\x88\x88\x70\x00"
|
||||
"\x88\x88\x88\xf8\x88\x88\x88\x00\x70\x20\x20\x20\x20\x20\x70\x00"
|
||||
"\x38\x10\x10\x10\x90\x90\x60\x00\x88\x90\xa0\xc0\xa0\x90\x88\x00"
|
||||
"\x80\x80\x80\x80\x80\x80\xf8\x00\x88\xd8\xa8\xa8\x88\x88\x88\x00"
|
||||
"\x88\xc8\xc8\xa8\x98\x98\x88\x00\x70\x88\x88\x88\x88\x88\x70\x00"
|
||||
"\xf0\x88\x88\xf0\x80\x80\x80\x00\x70\x88\x88\x88\xa8\x90\x68\x00"
|
||||
"\xf0\x88\x88\xf0\xa0\x90\x88\x00\x70\x88\x80\x70\x08\x88\x70\x00"
|
||||
"\xf8\x20\x20\x20\x20\x20\x20\x00\x88\x88\x88\x88\x88\x88\x70\x00"
|
||||
"\x88\x88\x88\x88\x50\x50\x20\x00\x88\x88\x88\xa8\xa8\xd8\x88\x00"
|
||||
"\x88\x88\x50\x20\x50\x88\x88\x00\x88\x88\x88\x70\x20\x20\x20\x00"
|
||||
"\xf8\x08\x10\x20\x40\x80\xf8\x00\x70\x40\x40\x40\x40\x40\x70\x00"
|
||||
"\x00\x00\x80\x40\x20\x10\x08\x00\x70\x10\x10\x10\x10\x10\x70\x00"
|
||||
"\x20\x50\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x00"
|
||||
"\x40\x20\x10\x00\x00\x00\x00\x00\x00\x00\x70\x08\x78\x88\x78\x00"
|
||||
"\x80\x80\xb0\xc8\x88\xc8\xb0\x00\x00\x00\x70\x88\x80\x88\x70\x00"
|
||||
"\x08\x08\x68\x98\x88\x98\x68\x00\x00\x00\x70\x88\xf8\x80\x70\x00"
|
||||
"\x10\x28\x20\xf8\x20\x20\x20\x00\x00\x00\x68\x98\x98\x68\x08\x70"
|
||||
"\x80\x80\xf0\x88\x88\x88\x88\x00\x20\x00\x60\x20\x20\x20\x70\x00"
|
||||
"\x10\x00\x30\x10\x10\x10\x90\x60\x40\x40\x48\x50\x60\x50\x48\x00"
|
||||
"\x60\x20\x20\x20\x20\x20\x70\x00\x00\x00\xd0\xa8\xa8\xa8\xa8\x00"
|
||||
"\x00\x00\xb0\xc8\x88\x88\x88\x00\x00\x00\x70\x88\x88\x88\x70\x00"
|
||||
"\x00\x00\xb0\xc8\xc8\xb0\x80\x80\x00\x00\x68\x98\x98\x68\x08\x08"
|
||||
"\x00\x00\xb0\xc8\x80\x80\x80\x00\x00\x00\x78\x80\xf0\x08\xf0\x00"
|
||||
"\x40\x40\xf0\x40\x40\x48\x30\x00\x00\x00\x90\x90\x90\x90\x68\x00"
|
||||
"\x00\x00\x88\x88\x88\x50\x20\x00\x00\x00\x88\xa8\xa8\xa8\x50\x00"
|
||||
"\x00\x00\x88\x50\x20\x50\x88\x00\x00\x00\x88\x88\x98\x68\x08\x70"
|
||||
"\x00\x00\xf8\x10\x20\x40\xf8\x00\x18\x20\x20\x40\x20\x20\x18\x00"
|
||||
"\x20\x20\x20\x00\x20\x20\x20\x00\xc0\x20\x20\x10\x20\x20\xc0\x00"
|
||||
"\x40\xa8\x10\x00\x00\x00\x00\x00\x00\x00\x20\x50\xf8\x00\x00\x00"
|
||||
"\x70\x88\x80\x80\x88\x70\x20\x60\x90\x00\x00\x90\x90\x90\x68\x00"
|
||||
"\x10\x20\x70\x88\xf8\x80\x70\x00\x20\x50\x70\x08\x78\x88\x78\x00"
|
||||
"\x48\x00\x70\x08\x78\x88\x78\x00\x20\x10\x70\x08\x78\x88\x78\x00"
|
||||
"\x20\x00\x70\x08\x78\x88\x78\x00\x00\x70\x80\x80\x80\x70\x10\x60"
|
||||
"\x20\x50\x70\x88\xf8\x80\x70\x00\x50\x00\x70\x88\xf8\x80\x70\x00"
|
||||
"\x20\x10\x70\x88\xf8\x80\x70\x00\x50\x00\x00\x60\x20\x20\x70\x00"
|
||||
"\x20\x50\x00\x60\x20\x20\x70\x00\x40\x20\x00\x60\x20\x20\x70\x00"
|
||||
"\x50\x00\x20\x50\x88\xf8\x88\x00\x20\x00\x20\x50\x88\xf8\x88\x00"
|
||||
"\x10\x20\xf8\x80\xf0\x80\xf8\x00\x00\x00\x6c\x12\x7e\x90\x6e\x00"
|
||||
"\x3e\x50\x90\x9c\xf0\x90\x9e\x00\x60\x90\x00\x60\x90\x90\x60\x00"
|
||||
"\x90\x00\x00\x60\x90\x90\x60\x00\x40\x20\x00\x60\x90\x90\x60\x00"
|
||||
"\x40\xa0\x00\xa0\xa0\xa0\x50\x00\x40\x20\x00\xa0\xa0\xa0\x50\x00"
|
||||
"\x90\x00\x90\x90\xb0\x50\x10\xe0\x50\x00\x70\x88\x88\x88\x70\x00"
|
||||
"\x50\x00\x88\x88\x88\x88\x70\x00\x20\x20\x78\x80\x80\x78\x20\x20"
|
||||
"\x18\x24\x20\xf8\x20\xe2\x5c\x00\x88\x50\x20\xf8\x20\xf8\x20\x00"
|
||||
"\xc0\xa0\xa0\xc8\x9c\x88\x88\x8c\x18\x20\x20\xf8\x20\x20\x20\x40"
|
||||
"\x10\x20\x70\x08\x78\x88\x78\x00\x10\x20\x00\x60\x20\x20\x70\x00"
|
||||
"\x20\x40\x00\x60\x90\x90\x60\x00\x20\x40\x00\x90\x90\x90\x68\x00"
|
||||
"\x50\xa0\x00\xa0\xd0\x90\x90\x00\x28\x50\x00\xc8\xa8\x98\x88\x00"
|
||||
"\x00\x70\x08\x78\x88\x78\x00\xf8\x00\x60\x90\x90\x90\x60\x00\xf0"
|
||||
"\x20\x00\x20\x40\x80\x88\x70\x00\x00\x00\x00\xf8\x80\x80\x00\x00"
|
||||
"\x00\x00\x00\xf8\x08\x08\x00\x00\x84\x88\x90\xa8\x54\x84\x08\x1c"
|
||||
"\x84\x88\x90\xa8\x58\xa8\x3c\x08\x20\x00\x00\x20\x20\x20\x20\x00"
|
||||
"\x00\x00\x24\x48\x90\x48\x24\x00\x00\x00\x90\x48\x24\x48\x90\x00"
|
||||
"\x28\x50\x20\x50\x88\xf8\x88\x00\x28\x50\x70\x08\x78\x88\x78\x00"
|
||||
"\x28\x50\x00\x70\x20\x20\x70\x00\x28\x50\x00\x20\x20\x20\x70\x00"
|
||||
"\x28\x50\x00\x70\x88\x88\x70\x00\x50\xa0\x00\x60\x90\x90\x60\x00"
|
||||
"\x28\x50\x00\x88\x88\x88\x70\x00\x50\xa0\x00\xa0\xa0\xa0\x50\x00"
|
||||
"\xfc\x48\x48\x48\xe8\x08\x50\x20\x00\x50\x00\x50\x50\x50\x10\x20"
|
||||
"\xc0\x44\xc8\x54\xec\x54\x9e\x04\x10\xa8\x40\x00\x00\x00\x00\x00"
|
||||
"\x00\x20\x50\x88\x50\x20\x00\x00\x88\x10\x20\x40\x80\x28\x00\x00"
|
||||
"\x7c\xa8\xa8\x68\x28\x28\x28\x00\x38\x40\x30\x48\x48\x30\x08\x70"
|
||||
"\x00\x00\x00\x00\x00\x00\xff\xff\xf0\xf0\xf0\xf0\x0f\x0f\x0f\x0f"
|
||||
"\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x3c\x3c\x00\x00\x00\xff\xff\xff\xff\xff\xff\x00\x00"
|
||||
"\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\x0f\x0f\x0f\x0f\xf0\xf0\xf0\xf0"
|
||||
"\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\x03\x03\x03\x03\x03\x03\x03\x03"
|
||||
"\x3f\x3f\x3f\x3f\x3f\x3f\x3f\x3f\x11\x22\x44\x88\x11\x22\x44\x88"
|
||||
"\x88\x44\x22\x11\x88\x44\x22\x11\xfe\x7c\x38\x10\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x10\x38\x7c\xfe\x80\xc0\xe0\xf0\xe0\xc0\x80\x00"
|
||||
"\x01\x03\x07\x0f\x07\x03\x01\x00\xff\x7e\x3c\x18\x18\x3c\x7e\xff"
|
||||
"\x81\xc3\xe7\xff\xff\xe7\xc3\x81\xf0\xf0\xf0\xf0\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\xf0\xf0\xf0\xf0\x33\x33\xcc\xcc\x33\x33\xcc\xcc"
|
||||
"\x00\x20\x20\x50\x50\x88\xf8\x00\x20\x20\x70\x20\x70\x20\x20\x00"
|
||||
"\x00\x00\x00\x50\x88\xa8\x50\x00\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
"\x00\x00\x00\x00\xff\xff\xff\xff\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0"
|
||||
"\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\xff\xff\xff\xff\x00\x00\x00\x00"
|
||||
"\x00\x00\x68\x90\x90\x90\x68\x00\x30\x48\x48\x70\x48\x48\x70\xc0"
|
||||
"\xf8\x88\x80\x80\x80\x80\x80\x00\xf8\x50\x50\x50\x50\x50\x98\x00"
|
||||
"\xf8\x88\x40\x20\x40\x88\xf8\x00\x00\x00\x78\x90\x90\x90\x60\x00"
|
||||
"\x00\x50\x50\x50\x50\x68\x80\x80\x00\x50\xa0\x20\x20\x20\x20\x00"
|
||||
"\xf8\x20\x70\xa8\xa8\x70\x20\xf8\x20\x50\x88\xf8\x88\x50\x20\x00"
|
||||
"\x70\x88\x88\x88\x50\x50\xd8\x00\x30\x40\x40\x20\x50\x50\x50\x20"
|
||||
"\x00\x00\x00\x50\xa8\xa8\x50\x00\x08\x70\xa8\xa8\xa8\x70\x80\x00"
|
||||
"\x38\x40\x80\xf8\x80\x40\x38\x00\x70\x88\x88\x88\x88\x88\x88\x00"
|
||||
"\x00\xf8\x00\xf8\x00\xf8\x00\x00\x20\x20\xf8\x20\x20\x00\xf8\x00"
|
||||
"\xc0\x30\x08\x30\xc0\x00\xf8\x00\x18\x60\x80\x60\x18\x00\xf8\x00"
|
||||
"\x10\x28\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\xa0\x40"
|
||||
"\x00\x20\x00\xf8\x00\x20\x00\x00\x00\x50\xa0\x00\x50\xa0\x00\x00"
|
||||
"\x00\x18\x24\x24\x18\x00\x00\x00\x00\x30\x78\x78\x30\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x30\x00\x00\x00\x3e\x20\x20\x20\xa0\x60\x20\x00"
|
||||
"\xa0\x50\x50\x50\x00\x00\x00\x00\x40\xa0\x20\x40\xe0\x00\x00\x00"
|
||||
"\x00\x38\x38\x38\x38\x38\x38\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
|
||||
|
||||
|
93
gp2x/gp2x.c
Normal file
93
gp2x/gp2x.c
Normal file
@ -0,0 +1,93 @@
|
||||
/* Parts used from cpuctrl */
|
||||
/* cpuctrl for GP2X
|
||||
Copyright (C) 2005 Hermes/PS2Reality
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/soundcard.h>
|
||||
#include "../common.h"
|
||||
#include "gp2x.h"
|
||||
|
||||
extern int main_cpuspeed(int argc, char *argv[]);
|
||||
extern SDL_Surface* screen;
|
||||
|
||||
u32 gp2x_audio_volume = 74;
|
||||
u32 gpsp_gp2x_dev_audio = 0;
|
||||
u32 gpsp_gp2x_dev = 0;
|
||||
|
||||
volatile u16 *gpsp_gp2x_memregs;
|
||||
volatile u32 *gpsp_gp2x_memregl;
|
||||
|
||||
static volatile u16 *MEM_REG;
|
||||
|
||||
s32 gp2x_load_mmuhack()
|
||||
{
|
||||
s32 mmufd = open("/dev/mmuhack", O_RDWR);
|
||||
|
||||
if(mmufd < 0)
|
||||
{
|
||||
system("/sbin/insmod mmuhack.o");
|
||||
mmufd = open("/dev/mmuhack", O_RDWR);
|
||||
}
|
||||
|
||||
if(mmufd < 0)
|
||||
return -1;
|
||||
|
||||
close(mmufd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gp2x_overclock()
|
||||
{
|
||||
gpsp_gp2x_dev = open("/dev/mem", O_RDWR);
|
||||
gpsp_gp2x_dev_audio = open("/dev/mixer", O_RDWR);
|
||||
gpsp_gp2x_memregl =
|
||||
(unsigned long *)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED,
|
||||
gpsp_gp2x_dev, 0xc0000000);
|
||||
gpsp_gp2x_memregs = (unsigned short *)gpsp_gp2x_memregl;
|
||||
|
||||
clear_screen(0);
|
||||
main_cpuspeed(0, NULL);
|
||||
gp2x_sound_volume(1);
|
||||
}
|
||||
|
||||
void gp2x_quit()
|
||||
{
|
||||
munmap((void *)gpsp_gp2x_memregl, 0x10000);
|
||||
close(gpsp_gp2x_dev_audio);
|
||||
close(gpsp_gp2x_dev);
|
||||
chdir("/usr/gp2x");
|
||||
execl("gp2xmenu", "gp2xmenu", NULL);
|
||||
}
|
||||
|
||||
void gp2x_sound_volume(u32 volume_up)
|
||||
{
|
||||
u32 volume;
|
||||
if((volume_up == 0) && (gp2x_audio_volume > 0))
|
||||
gp2x_audio_volume--;
|
||||
|
||||
if((volume_up != 0) && (gp2x_audio_volume < 100))
|
||||
gp2x_audio_volume++;
|
||||
|
||||
volume = (gp2x_audio_volume * 0x50) / 100;
|
||||
volume = (gp2x_audio_volume << 8) | gp2x_audio_volume;
|
||||
ioctl(gpsp_gp2x_dev_audio, SOUND_MIXER_WRITE_PCM, &volume);
|
||||
}
|
||||
|
50
gp2x/gp2x.h
Normal file
50
gp2x/gp2x.h
Normal file
@ -0,0 +1,50 @@
|
||||
#ifndef GP2X_H
|
||||
#define GP2X_H
|
||||
|
||||
enum
|
||||
{
|
||||
GP2X_UP = 1 << 0,
|
||||
GP2X_LEFT = 1 << 2,
|
||||
GP2X_DOWN = 1 << 4,
|
||||
GP2X_RIGHT = 1 << 6,
|
||||
GP2X_START = 1 << 8,
|
||||
GP2X_SELECT = 1 << 9,
|
||||
GP2X_L = 1 << 10,
|
||||
GP2X_R = 1 << 11,
|
||||
GP2X_A = 1 << 12,
|
||||
GP2X_B = 1 << 13,
|
||||
GP2X_X = 1 << 14,
|
||||
GP2X_Y = 1 << 15,
|
||||
GP2X_VOL_DOWN = 1 << 22,
|
||||
GP2X_VOL_UP = 1 << 23,
|
||||
GP2X_PUSH = 1 << 27
|
||||
};
|
||||
|
||||
|
||||
extern u32 gpsp_gp2x_dev_audio;
|
||||
extern u32 gpsp_gp2x_dev;
|
||||
extern volatile u16 *gpsp_gp2x_memregs;
|
||||
extern volatile u32 *gpsp_gp2x_memregl;
|
||||
|
||||
void gp2x_sound_volume(u32 volume_up);
|
||||
void gp2x_quit();
|
||||
|
||||
// call this at first
|
||||
void cpuctrl_init(void);
|
||||
void save_system_regs(void);
|
||||
void cpuctrl_deinit(void);
|
||||
void set_display_clock_div(unsigned div);
|
||||
|
||||
void set_FCLK(u32 MHZ);
|
||||
// 0 to 7 divider (freq = FCLK / (1 + div))
|
||||
void set_920_Div(u16 div);
|
||||
void set_DCLK_Div(u16 div);
|
||||
|
||||
void Disable_940(void);
|
||||
void gp2x_video_wait_vsync(void);
|
||||
unsigned short get_920_Div();
|
||||
void set_940_Div(u16 div);
|
||||
|
||||
s32 gp2x_load_mmuhack();
|
||||
|
||||
#endif
|
242
gp2x/gp2xminilib.c
Normal file
242
gp2x/gp2xminilib.c
Normal file
@ -0,0 +1,242 @@
|
||||
|
||||
/*
|
||||
GP2X minimal library v0.5 by rlyeh, 2005.
|
||||
|
||||
+ GP2X video library with double buffering.
|
||||
+ GP2X soundring buffer library with double buffering.
|
||||
+ GP2X joystick library.
|
||||
|
||||
Thanks to Squidge, Robster, snaff and NK, for the help & previous work! :-)
|
||||
|
||||
|
||||
What's new
|
||||
==========
|
||||
|
||||
0.5: patched sound for real stereo (using NK's solution); better init code.
|
||||
|
||||
0.4: lots of cleanups; sound is threaded now, double buffered too; 8 bpp video support; better exiting code.
|
||||
|
||||
0.3: shorter library; improved joystick diagonal detection.
|
||||
|
||||
0.2: better code layout; public release.
|
||||
|
||||
0.1: beta release
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/soundcard.h>
|
||||
#include <linux/fb.h>
|
||||
#include <pthread.h>
|
||||
#include "gp2xminilib.h"
|
||||
|
||||
extern void gp2x_sound_frame(void *blah, void *bufferg, int samples);
|
||||
|
||||
|
||||
|
||||
unsigned long gp2x_dev[4]={0,0,0,0}, gp2x_physvram[4];
|
||||
unsigned short *gp2x_memregs, *gp2x_screen15, *gp2x_logvram15[2], gp2x_sound_buffer[4+(44100*2)*4]; //*2=stereo, *4=max buffers
|
||||
volatile unsigned short gp2x_palette[512][2];
|
||||
unsigned char *gp2x_screen8, *gp2x_logvram8[2];
|
||||
pthread_t gp2x_sound_thread=0, gp2x_sound_thread_exit=0;
|
||||
|
||||
void gp2x_video_flip(void)
|
||||
{
|
||||
unsigned long address=gp2x_physvram[gp2x_physvram[3]];
|
||||
|
||||
gp2x_screen15=gp2x_logvram15[gp2x_physvram[3]^=1];
|
||||
gp2x_screen8 =gp2x_logvram8 [gp2x_physvram[3] ];
|
||||
|
||||
gp2x_memregs[0x290E>>1]=(unsigned short)(address & 0xffff);
|
||||
gp2x_memregs[0x2910>>1]=(unsigned short)(address >> 16);
|
||||
gp2x_memregs[0x2912>>1]=(unsigned short)(address & 0xffff);
|
||||
gp2x_memregs[0x2914>>1]=(unsigned short)(address >> 16);
|
||||
}
|
||||
|
||||
void gp2x_video_setpalette(void)
|
||||
{int i;
|
||||
gp2x_memregs[0x2958>>1]=0;
|
||||
for(i=0; i<512; i++) gp2x_memregs[0x295A>>1]=gp2x_palette[i][0], gp2x_memregs[0x295A>>1]=gp2x_palette[i][1];
|
||||
}
|
||||
|
||||
unsigned long gp2x_joystick_read(void)
|
||||
{
|
||||
unsigned long value=(gp2x_memregs[0x1198>>1] & 0x00FF);
|
||||
|
||||
if(value==0xFD) value=0xFA;
|
||||
if(value==0xF7) value=0xEB;
|
||||
if(value==0xDF) value=0xAF;
|
||||
if(value==0x7F) value=0xBE;
|
||||
|
||||
return ~((gp2x_memregs[0x1184>>1] & 0xFF00) | value | (gp2x_memregs[0x1186>>1] << 16));
|
||||
}
|
||||
|
||||
#if 0
|
||||
void *gp2x_sound_play(void *blah)
|
||||
{
|
||||
struct timespec ts;
|
||||
int flip=0;
|
||||
|
||||
ts.tv_sec=0, ts.tv_nsec=gp2x_sound_buffer[2];
|
||||
|
||||
while(! gp2x_sound_thread_exit)
|
||||
{
|
||||
gp2x_sound_frame(blah, (void *)(&gp2x_sound_buffer[4+flip]), gp2x_sound_buffer[0]);
|
||||
write(gp2x_dev[3], (void *)(&gp2x_sound_buffer[4+flip]), gp2x_sound_buffer[1]);
|
||||
|
||||
flip^=gp2x_sound_buffer[1];
|
||||
|
||||
//nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
void gp2x_deinit(void)
|
||||
{int i;
|
||||
if(gp2x_sound_thread) { gp2x_sound_thread_exit=1; for(i=0;i<1000000;i++); }
|
||||
|
||||
gp2x_memregs[0x28DA>>1]=0x4AB;
|
||||
gp2x_memregs[0x290C>>1]=640;
|
||||
|
||||
close(gp2x_dev[0]);
|
||||
close(gp2x_dev[1]);
|
||||
close(gp2x_dev[2]);
|
||||
//close(gp2x_dev[3]);
|
||||
//fcloseall();
|
||||
}
|
||||
|
||||
void gp2x_init(int bpp, int rate, int bits, int stereo, int Hz)
|
||||
{
|
||||
struct fb_fix_screeninfo fixed_info;
|
||||
|
||||
if(!gp2x_dev[0]) gp2x_dev[0] = open("/dev/fb0", O_RDWR);
|
||||
if(!gp2x_dev[1]) gp2x_dev[1] = open("/dev/fb1", O_RDWR);
|
||||
if(!gp2x_dev[2]) gp2x_dev[2] = open("/dev/mem", O_RDWR);
|
||||
//if(!gp2x_dev[3]) gp2x_dev[3] = open("/dev/dsp", O_WRONLY);
|
||||
|
||||
gp2x_memregs=(unsigned short *)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_dev[2], 0xc0000000);
|
||||
|
||||
if(!gp2x_sound_thread) { gp2x_memregs[0x0F16>>1] = 0x830a; sleep(1);
|
||||
gp2x_memregs[0x0F58>>1] = 0x100c; sleep(1); }
|
||||
|
||||
ioctl (gp2x_dev[0], FBIOGET_FSCREENINFO, &fixed_info);
|
||||
gp2x_screen15=gp2x_logvram15[0]=(unsigned short *)mmap(0, 320*240*2, PROT_WRITE, MAP_SHARED, gp2x_dev[0], 0);
|
||||
gp2x_screen8=gp2x_logvram8[0]=(unsigned char *)gp2x_logvram15[0];
|
||||
gp2x_physvram[0]=fixed_info.smem_start;
|
||||
|
||||
ioctl (gp2x_dev[1], FBIOGET_FSCREENINFO, &fixed_info);
|
||||
gp2x_logvram15[1]=(unsigned short *)mmap(0, 320*240*2, PROT_WRITE, MAP_SHARED, gp2x_dev[1], 0);
|
||||
gp2x_logvram8[1]=(unsigned char *)gp2x_logvram15[1];
|
||||
gp2x_physvram[1]=fixed_info.smem_start;
|
||||
|
||||
gp2x_memregs[0x28DA>>1]=(((bpp+1)/8)<<9)|0xAB; /*8/15/16/24bpp...*/
|
||||
gp2x_memregs[0x290C>>1]=320*((bpp+1)/8); /*line width in bytes*/
|
||||
|
||||
ioctl(gp2x_dev[3], SNDCTL_DSP_SPEED, &rate);
|
||||
ioctl(gp2x_dev[3], SNDCTL_DSP_SETFMT, &bits);
|
||||
ioctl(gp2x_dev[3], SNDCTL_DSP_STEREO, &stereo);
|
||||
|
||||
gp2x_sound_buffer[1]=(gp2x_sound_buffer[0]=(rate/Hz)) << (stereo + (bits==16));
|
||||
gp2x_sound_buffer[2]=(1000000/Hz);
|
||||
|
||||
if(!gp2x_sound_thread) { gp2x_sound_thread = 1; //pthread_create( &gp2x_sound_thread, NULL, gp2x_sound_play, NULL);
|
||||
atexit(gp2x_deinit); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
EXAMPLE
|
||||
=======
|
||||
|
||||
now supply your own function for 16 bits, stereo:
|
||||
|
||||
void gp2x_sound_frame(void *blah, void *bufferg, int samples)
|
||||
{
|
||||
signed short *buffer=(signed short *)bufferg;
|
||||
while(samples--)
|
||||
{
|
||||
*buffer++=0; //Left channel
|
||||
*buffer++=0; //Right channel
|
||||
}
|
||||
}
|
||||
|
||||
or 16 bits mono:
|
||||
|
||||
void gp2x_sound_frame(void *blah, void *bufferg, int samples)
|
||||
{
|
||||
signed short *buffer=(signed short *)bufferg;
|
||||
while(samples--)
|
||||
{
|
||||
*buffer++=0; //Central channel
|
||||
}
|
||||
}
|
||||
|
||||
now the main program...
|
||||
|
||||
hicolor example:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
//this sets video to hicolor (16 bpp)
|
||||
//it also sets sound to 44100,16bits,stereo and syncs audio to 50 Hz (PAL timing)
|
||||
|
||||
//Warning: GP2X does not support 8bit sound sampling! (at least within Linux)
|
||||
|
||||
gp2x_init(16,44100,16,1,50);
|
||||
|
||||
while(1)
|
||||
{
|
||||
unsigned long pad=gp2x_joystick_read();
|
||||
unsigned short color=gp2x_video_color15(255,255,255,0);
|
||||
|
||||
if(pad & GP2X_L) if(pad & GP2X_R) exit();
|
||||
|
||||
if(pad & GP2X_A) color=gp2x_color15(255,255,255,0); //white
|
||||
else color=gp2x_color15(255,0,0,0); //red
|
||||
|
||||
gp2x_screen15[160+120*320]=color; //x=160, y=120
|
||||
gp2x_video_flip();
|
||||
}
|
||||
}
|
||||
|
||||
palettized example:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
//this sets video to palette mode (8 bpp)
|
||||
//it also sets sound to 11025,16bits,stereo and syncs audio to 60 Hz (NSTC timing)
|
||||
|
||||
//Warning: GP2X does not support 8bit sound sampling! (at least within Linux)
|
||||
|
||||
gp2x_init(8,11025,16,1,60);
|
||||
|
||||
gp2x_video_color8(0,0,0,0); //color #0 is black for us
|
||||
gp2x_video_color8(1,255,255,255); //color #1 is white for us
|
||||
gp2x_video_color8(2,255,0,0); //color #2 is red for us
|
||||
gp2x_video_setpalette();
|
||||
|
||||
while(1)
|
||||
{
|
||||
unsigned long pad=gp2x_joystick_read();
|
||||
unsigned char color;
|
||||
|
||||
if(pad & GP2X_L) if(pad & GP2X_R) exit();
|
||||
|
||||
if(pad & GP2X_A) color=1; //white
|
||||
else color=2; //red
|
||||
|
||||
gp2x_screen8[160+120*320]=color; //x=160, y=120
|
||||
gp2x_video_flip();
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
58
gp2x/gp2xminilib.h
Normal file
58
gp2x/gp2xminilib.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
GP2X minimal library v0.5 by rlyeh, 2005.
|
||||
|
||||
+ GP2X video library with double buffering.
|
||||
+ GP2X soundring buffer library with double buffering.
|
||||
+ GP2X joystick library.
|
||||
|
||||
Thanks to Squidge, Robster, snaff and NK, for the help & previous work! :-)
|
||||
|
||||
|
||||
What's new
|
||||
==========
|
||||
|
||||
0.5: patched sound for real stereo (using NK's solution); better init code.
|
||||
|
||||
0.4: lots of cleanups; sound is threaded now, double buffered too; 8 bpp video support; better exiting code.
|
||||
|
||||
0.3: shorter library; improved joystick diagonal detection.
|
||||
|
||||
0.2: better code layout; public release.
|
||||
|
||||
0.1: beta release
|
||||
*/
|
||||
|
||||
/* .h by Hermes/PS2Reality*/
|
||||
|
||||
#if !defined(GP2XMINILIB)
|
||||
#define GP2XMINILIB
|
||||
|
||||
enum { GP2X_UP=0x1, GP2X_LEFT=0x4, GP2X_DOWN=0x10, GP2X_RIGHT=0x40,
|
||||
GP2X_START=1<<8, GP2X_SELECT=1<<9, GP2X_L=1<<10, GP2X_R=1<<11,
|
||||
GP2X_A=1<<12, GP2X_B=1<<13, GP2X_X=1<<14, GP2X_Y=1<<15,
|
||||
GP2X_VOL_UP=1<<22, GP2X_VOL_DOWN=1<<23, GP2X_PUSH=1<<27, };
|
||||
|
||||
#define gp2x_video_color15(R,G,B,A) (((R&0xF8)<<8)|((G&0xF8)<<3)|((B&0xF8)>>3)|(A<<5))
|
||||
#define gp2x_video_color8 (C,R,G,B) gp2x_palette[C][0]=(G<<8)|B,gp2x_palette[C][1]=R;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
extern unsigned short *gp2x_memregs, *gp2x_screen15, *gp2x_logvram15[2], gp2x_sound_buffer[4+(44100*2)*4]; //*2=stereo, *4=max buffers
|
||||
|
||||
|
||||
|
||||
extern unsigned long gp2x_dev[4];
|
||||
|
||||
|
||||
void gp2x_video_flip(void);
|
||||
void gp2x_video_setpalette(void);
|
||||
unsigned long gp2x_joystick_read(void);
|
||||
void *gp2x_sound_play(void *blah);
|
||||
void gp2x_deinit(void);
|
||||
void gp2x_init(int bpp, int rate, int bits, int stereo, int Hz);
|
||||
|
||||
|
||||
|
||||
#endif
|
135
gp2x/load_imm_test.c
Normal file
135
gp2x/load_imm_test.c
Normal file
@ -0,0 +1,135 @@
|
||||
#include <stdio.h>
|
||||
|
||||
typedef unsigned int u32;
|
||||
|
||||
u32 arm_imm_find_nonzero(u32 imm, u32 start_bit)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for(i = start_bit; i < 32; i += 2)
|
||||
{
|
||||
if((imm >> i) & 0x03)
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
u32 arm_disect_imm_32bit(u32 imm, u32 *stores, u32 *rotations)
|
||||
{
|
||||
u32 store_count = 0;
|
||||
u32 left_shift = 0;
|
||||
|
||||
// Otherwise it'll return 0 things to store because it'll never
|
||||
// find anything.
|
||||
if(imm == 0)
|
||||
{
|
||||
rotations[0] = 0;
|
||||
stores[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Find chunks of non-zero data at 2 bit alignments.
|
||||
while(1)
|
||||
{
|
||||
left_shift = arm_imm_find_nonzero(imm, left_shift);
|
||||
|
||||
if(left_shift == 32)
|
||||
{
|
||||
// We've hit the end of the useful data.
|
||||
return store_count;
|
||||
}
|
||||
|
||||
// Hit the end, it might wrap back around to the beginning.
|
||||
if(left_shift >= 24)
|
||||
{
|
||||
// Make a mask for the residual bits. IE, if we have
|
||||
// 5 bits of data at the end we can wrap around to 3
|
||||
// bits of data in the beginning. Thus the first
|
||||
// thing, after being shifted left, has to be less
|
||||
// than 111b, 0x7, or (1 << 3) - 1.
|
||||
u32 top_bits = 32 - left_shift;
|
||||
u32 residual_bits = 8 - top_bits;
|
||||
u32 residual_mask = (1 << residual_bits) - 1;
|
||||
|
||||
if((store_count > 1) && (left_shift > 24) &&
|
||||
((stores[0] << (32 - rotations[0])) < residual_mask))
|
||||
{
|
||||
// Then we can throw out the last bit and tack it on
|
||||
// to the first bit.
|
||||
u32 initial_bits = rotations[0];
|
||||
stores[0] = (stores[0] << (top_bits + (32 - rotations[0]))) |
|
||||
((imm >> left_shift) & 0xFF);
|
||||
rotations[0] = top_bits;
|
||||
|
||||
return store_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
// There's nothing to wrap over to in the beginning
|
||||
stores[store_count] = (imm >> left_shift) & 0xFF;
|
||||
rotations[store_count] = (32 - left_shift) & 0x1F;
|
||||
return store_count + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
stores[store_count] = (imm >> left_shift) & 0xFF;
|
||||
rotations[store_count] = (32 - left_shift) & 0x1F;
|
||||
|
||||
store_count++;
|
||||
left_shift += 8;
|
||||
}
|
||||
}
|
||||
|
||||
#define ror(value, shift) \
|
||||
((value) >> shift) | ((value) << (32 - shift)) \
|
||||
|
||||
u32 arm_assemble_imm_32bit(u32 *stores, u32 *rotations, u32 store_count)
|
||||
{
|
||||
u32 n = ror(stores[0], rotations[0]);
|
||||
u32 i;
|
||||
printf("%x : %x\n", stores[0], rotations[0]);
|
||||
|
||||
for(i = 1; i < store_count; i++)
|
||||
{
|
||||
printf("%x : %x\n", stores[i], rotations[i]);
|
||||
n |= ror(stores[i], rotations[i]);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
u32 n = 0;
|
||||
u32 stores[4];
|
||||
u32 rotations[4];
|
||||
u32 store_count;
|
||||
u32 n2;
|
||||
|
||||
if(argc != 1)
|
||||
{
|
||||
n = strtoul(argv[1], NULL, 16);
|
||||
store_count = arm_disect_imm_32bit(n, stores, rotations);
|
||||
n2 = arm_assemble_imm_32bit(stores, rotations, store_count);
|
||||
printf("%08x -> %08x (%d stores)\n", n, n2, store_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
store_count = arm_disect_imm_32bit(n, stores, rotations);
|
||||
n2 = arm_assemble_imm_32bit(stores, rotations, store_count);
|
||||
if(n != n2)
|
||||
{
|
||||
printf("Failure: %08x -/-> %08x\n", n, n2);
|
||||
return -1;
|
||||
}
|
||||
n++;
|
||||
} while(n != 0);
|
||||
|
||||
printf("Done!\n");
|
||||
return 0;
|
||||
}
|
262
gp2x/readme_gp2x.txt
Normal file
262
gp2x/readme_gp2x.txt
Normal file
@ -0,0 +1,262 @@
|
||||
-- gameplaySP2X Gameboy Advance emulator for GP2X --
|
||||
|
||||
gpSP2X is a version of my (Exophase)'s emulator originally for Sony PSP.
|
||||
A large amount of effort has been done to make it more optimized for the
|
||||
ARM CPU present in the GP2X, however it is still very much a work in
|
||||
progress.
|
||||
|
||||
See readme.txt for the PSP version readme, which contains a lot of
|
||||
information relevant to the GP2X version (note that some of it does
|
||||
not apply however).
|
||||
|
||||
|
||||
Changelog:
|
||||
|
||||
0.9-2xb:
|
||||
-- IMPORTANT-- If you're overwriting an old version, be sure to delete the
|
||||
gpsp.cfg file first, or be prepared to have a bunch of weird button
|
||||
settings that would require fixing.
|
||||
|
||||
- Fixed some bugs stunting compatability.
|
||||
- Optimized alpha blends in renderer.
|
||||
- Some more optimizations to dynarec output.
|
||||
- Savestates should work better now.
|
||||
- Cheat/misc menu won't crash the emulator.
|
||||
- Main button config window works (not all buttons are in yet)
|
||||
|
||||
0.9-2Xa: (Exophase release)
|
||||
- Redid autoframeskip. Should work more reliably.
|
||||
- Rewrote dynamic recompiler from x86 source (arm_emit.h, arm_stub.S).
|
||||
Has some more sophisticated behavior than the last version, more is
|
||||
still to come... Should notice a slight speed improvement over the
|
||||
last version.
|
||||
- Tweaked GUI to be a little more useable. Buttons are now mirroring the
|
||||
PSP version's.
|
||||
- Code unification + cleanup amongst versions.
|
||||
|
||||
|
||||
v9008: (zodttd release)
|
||||
- Updated the way autoframeskip works. Should be better now. Still has a max
|
||||
frameskip value.
|
||||
- Added a slight performance increase to the dynarec.
|
||||
- Added sync() to make sure files such as savestates and in-game saves are
|
||||
saved properly to the GP2X.
|
||||
|
||||
v9006: (zodttd release)
|
||||
- Initial public release
|
||||
|
||||
|
||||
Installation:
|
||||
|
||||
1. Place the "gpsp.gpe" and "game_config.txt" file in a directory on your SD
|
||||
card used with the GP2X.
|
||||
|
||||
2. Place your GBA BIOS in the directory from step 1. This file must be named
|
||||
"gba_bios.bin" in all lowercase as shown, so rename it if needed.
|
||||
|
||||
-- NOTE --
|
||||
|
||||
There are two commonly available BIOSes - one is the correct one used in
|
||||
production GBA's worldwide and the other is a prototype BIOS. The latter
|
||||
will not cause some games to not work correctly or crash. If you attempt
|
||||
to use this BIOS you will be presented with a warning before being
|
||||
allowed to continue. This screen will give you a checksum of the real
|
||||
BIOS image (see readme.txt for further information).
|
||||
|
||||
3. Place your GBA games in the directory from step 1. These files should have
|
||||
a ".gba" or ".bin" file extension. Zip compressed games should be supported
|
||||
and are recognized with the ".zip" file extension. Note that 32MB ROMs will
|
||||
probably not run if zipped. 16MB and smaller should be OK.
|
||||
|
||||
4. Done. Run gpsp.gpe.
|
||||
|
||||
|
||||
Controls:
|
||||
|
||||
How to use gpSP on the GP2X:
|
||||
Buttons are mapped as follows (GBA/ingame buttons can be changed in the menu):
|
||||
|
||||
GP2X--------------------GBA
|
||||
X -> A
|
||||
B -> B
|
||||
L TRIG -> L TRIG
|
||||
R TRIG -> R TRIG
|
||||
START -> START
|
||||
SELECT -> SELECT
|
||||
|
||||
GP2X--------------------------------gpSP
|
||||
|
||||
-- IN-GAME --
|
||||
|
||||
VOL MIDDLE (UP + DOWN) -> menu
|
||||
PUSH STICK -> fps display toggle (second number is
|
||||
frames actually drawn)
|
||||
|
||||
-- IN-MENU --
|
||||
B -> select option
|
||||
X -> cancel/exit menu
|
||||
A -> escape (up one director level in the
|
||||
file selector)
|
||||
|
||||
When gpSP is started, you are presented with the option to overclock your
|
||||
GP2X. Use the L/R TRIG to change the CPU clockspeed and press START to
|
||||
continue. You may also change RAM timings here - experiment with what
|
||||
works well. Note that going too high on overclocking or low on RAM
|
||||
timings can cause the game to crash or the GP2X to outright freeze up.
|
||||
|
||||
If you do not want to overclock, press START without using L/R.
|
||||
You will now be presented with a menu to choose a game. Press the IN-MENU
|
||||
"SELECT" button shown above to pick a game to load.
|
||||
|
||||
If you would like to test gpSP for the GP2X with a homebrew (free public
|
||||
domain) game, a game by Russ Prince works very well with gpSP. It is called
|
||||
Bust-A-Move and is a remake of the classic game it's named after.
|
||||
|
||||
|
||||
How to build from source:
|
||||
|
||||
The makefile included in the source is geared towards the Open2x toolchain.
|
||||
If you use Open2x and installed it in the way recommended then it should
|
||||
work okay, assuming you also have up to date HW-SDL (and have
|
||||
arm-linux-sdl-config installed in the right place). The makefile is in the
|
||||
gp2x directory, so go there first then just type make to build gpsp.gpe.
|
||||
Might need a little tweaking if your setup is different. If you need help
|
||||
you can ask me, but I'll probably nag you about why you want to build it in
|
||||
the first place.
|
||||
|
||||
|
||||
GP2X version FAQ:
|
||||
|
||||
Q) Help! This game doesn't work. Am I using a bad version of the ROM?
|
||||
|
||||
A) First, make sure you're using the correct BIOS version. If you aren't
|
||||
gpSP should tell you. Other than that, there are some games that are
|
||||
known to not work now (and will probably work later), and perhaps
|
||||
many more games that I don't know about that don't work. I haven't
|
||||
launched a full scale compatability test at this version, so it might
|
||||
take a while before the compatability levels are high.
|
||||
|
||||
|
||||
Q) Why is this version slower than the PSP version?
|
||||
|
||||
A) gpSP is still a work in progress. It might be possible to obtain more
|
||||
speed from both this version and the PSP one too (and others in the
|
||||
future). With that in mind, know that even a very agressively overclocked
|
||||
GP2X is still less powerful than a PSP, generally speaking. Still, I
|
||||
have a lot of ideas. It's unlikely that the GP2X version will ever be as
|
||||
fast/faster than the PSP version for anyone but anything's possible.
|
||||
|
||||
|
||||
Q) How high does my GP2X have to overclock to enjoy gpSP?
|
||||
|
||||
A) That depends on you. Higher overclocking will mean less frames skipped
|
||||
on autoframeskip, or less frameskip needed if on manual. Or it can
|
||||
make the difference between whether or not virtual 60fps can be reached.
|
||||
For some games no GP2X in the world will be able to run them fullspeed,
|
||||
with any amount of frameskip. A few might run well with no overclocking
|
||||
and a generous level of frameskip (probably manual). If you don't care
|
||||
about battery life (or you're plugged into an outlet) you should push
|
||||
it as high as you can while still maintaining stability, because
|
||||
chances are high that whatever you play will benefit from it. Right now
|
||||
you'll probably want 260MHz if you can achieve it, but with a lot of
|
||||
luck this number will lower slightly in the future (and is just a vague
|
||||
ballpark figure anyway). I don't want to scare anyone off from using the
|
||||
emulator, you should give it a try and see how it plays for you
|
||||
regardless of how high you can overclock. Just note that this is far
|
||||
from a locked smooth experience for everyone on every game.
|
||||
|
||||
|
||||
Q) GBA has an ARM processor, GP2X has an ARM processor. GP2X is more
|
||||
powerful than GBA. This emulator should run great without overclocking,
|
||||
so therefore you're doing it wrong.
|
||||
|
||||
A) That's not a question, but I'll field it anyway. Two things: first,
|
||||
"virtualization", or running the GBA code "natively" on the GP2X is
|
||||
probably not possible, at least not with the way I want to do things.
|
||||
For reasons why go read my blog (see below). So yes, you actually
|
||||
do need more than 16.7MHz of ARM9 power to emulate the GBA's CPU.
|
||||
Second: there is a whole lot of work behind emulating the pretty 2D
|
||||
graphics on the GBA, something it can do in hardware a lot better than
|
||||
this platform can.
|
||||
End result: GBA emulation on GP2X isn't as easy as you think it is.
|
||||
|
||||
|
||||
Q) What are you working on now? When will you release the next version?
|
||||
|
||||
A) See the gpSP development blog:
|
||||
|
||||
http://gpsp-dev.blogspot.com/
|
||||
|
||||
Note that I don't give release dates, ever, unless I'm right on the verge
|
||||
of releasing. Be grateful that I've decided to be much more open about
|
||||
the development of the emulator now.
|
||||
|
||||
|
||||
Q) Thanks to your blog I heard that you made some improvement. Can I have
|
||||
a copy of the new code?
|
||||
|
||||
A) No. Builds in transition often have a lot of problems, and I like for
|
||||
releases to be relatively substantial. I can probably be bribed out of
|
||||
them with donations though. :P
|
||||
|
||||
|
||||
Q) Why do the menu suck so much? Why do half the options not work or not
|
||||
make any sense?
|
||||
|
||||
A) Sorry, the menu still hasn't been modified very much to fit the GP2X
|
||||
version instead of the PSP version.. hopefully this will improve in the
|
||||
future.
|
||||
|
||||
|
||||
Q) Who's in charge of the GP2X version anyway?
|
||||
|
||||
A) Originally, zodttd was. I, Exophase, have basically usurped control of it
|
||||
now to encourage zodttd to work more on his PS1 emulator (that and I'm
|
||||
possessive of gpSP and get nervous when people work on it too heavily).
|
||||
zodttd will most likely still be around to work on things though.
|
||||
|
||||
|
||||
Q) I'm a super nice person and would like to donate some of my hard earned
|
||||
money to this one-off GBA emulator. Where do I send my money to?
|
||||
|
||||
A) Exophase: exophase@gmail.com on PayPal
|
||||
zodttd: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=heirloomer
|
||||
%40pobox%2ecom&item_number=1&no_shipping=1&no_note=1&tax=0&cy_code=USD&bn=
|
||||
PP%2dDonationsBF&charset=UTF%2d8
|
||||
^ Click there for donating on PayPal (remove whitespace/linebreaks).
|
||||
|
||||
GP2X people have already donated a lot more to me than PSP people have,
|
||||
even though there's an order of magnitude or two less users. And they've
|
||||
donated far more to zodttd than they have to me. So I'm not going to ask
|
||||
people to donate..
|
||||
|
||||
However I won't lie: donating ups the chances of me actually working on the
|
||||
next version (for which I have a lot of ideas, but not necessarily time to
|
||||
dedicate to.. that time might need more incentive to be allotted from other
|
||||
things). This could change depending on my employment situation, but right
|
||||
now I feel guilty doing anything that doesn't help guarantee that I'll be
|
||||
able to buy food a year from now.
|
||||
|
||||
|
||||
Q) Tell me all of your personal information.
|
||||
|
||||
A) Again not a question, but why not. I'm Exophase, real name: Gilead Kutnick,
|
||||
male, 23 years old, current residence Bloomington, IN; straight/single/not
|
||||
actively looking, almost have an MS in Computer Science (do have a BS
|
||||
underneath it), likes PSP more than GP2X, will not write a Nintendo DS
|
||||
emulator for either, am currently looking for a job for after I graduate.
|
||||
|
||||
|
||||
Q) You said you're looking for a job.
|
||||
|
||||
A) Yes. If you have one or know someone who needs a low level oriented
|
||||
programmer then I'm up for grabs. And this is my resume:
|
||||
http://exophase.devzero.co.uk/resume.pdf
|
||||
|
||||
|
||||
Credits:
|
||||
|
||||
Original codebase: Exophase (exophase@gmail.com)
|
||||
Foundation gp2x code: zodttd
|
||||
GP2X dynarec/stubs + current code maintainance: Exophase
|
||||
|
37007
gp2x/rom_cache.S
Normal file
37007
gp2x/rom_cache.S
Normal file
File diff suppressed because it is too large
Load Diff
205
gp2x/speedtest.c
Normal file
205
gp2x/speedtest.c
Normal file
@ -0,0 +1,205 @@
|
||||
/* speedtest.c for GP2X (CPU/LCD/RAM-Tuner Version 2.0)
|
||||
Copyright (C) 2006 god_at_hell
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "display.h"
|
||||
#include "cpuctrl.h"
|
||||
#include "gp2xminilib.h"
|
||||
|
||||
void prim()
|
||||
{
|
||||
//FILE *primout;
|
||||
unsigned char cad[256];
|
||||
char p = 0;
|
||||
int primnumber;
|
||||
int l = 1;
|
||||
float g = 0;
|
||||
int i = 3;
|
||||
|
||||
while(i != 500000)
|
||||
{
|
||||
int m = 2;
|
||||
float temp = sqrt(i);
|
||||
float ifloat = (float)i;
|
||||
|
||||
if(temp == (int)temp)
|
||||
{
|
||||
m = i;
|
||||
p = 1;
|
||||
}
|
||||
|
||||
while(m < temp)
|
||||
{
|
||||
g = ifloat/m;
|
||||
if (g == (int)g)
|
||||
{
|
||||
m = i;
|
||||
p = 1;
|
||||
}
|
||||
m++;
|
||||
}
|
||||
|
||||
if (p == 0)
|
||||
{
|
||||
l += 1;
|
||||
primnumber = i;
|
||||
sprintf(cad,"%u is primnumber",i);
|
||||
v_putcad(1,13,0xffffff,0xB00000,cad);
|
||||
//primout = fopen("/mnt/sd/primnumber.txt", "a");
|
||||
//fprintf(primout,"%u: %u\n", l, i);
|
||||
//fclose(primout);
|
||||
//execl("sync",NULL);
|
||||
gp2x_video_flip();
|
||||
}
|
||||
p = 0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void ant()
|
||||
{
|
||||
int i,n;
|
||||
unsigned char cad[256];
|
||||
short direction = 0; //clockwise ... 0 = Up, 1 = Right
|
||||
unsigned short col1, col2;
|
||||
col1=gp2x_video_color15(0,0,0,0);
|
||||
col2=gp2x_video_color15(0xFF,0xFF,0xFF,0);
|
||||
short antx = 200;
|
||||
short anty = 140;
|
||||
for(i = 0; i < 9000; i++)
|
||||
{
|
||||
for(n = 0; n < 500000; n++);
|
||||
if(gp2x_screen15[(320*anty) + antx]==col1)
|
||||
{
|
||||
for(n = 0; n < 3; n++)
|
||||
{
|
||||
int m = 0;
|
||||
for(m = 0; m < 3; m++)
|
||||
{
|
||||
gp2x_screen15[320*(anty+n)+antx+m] = col2;
|
||||
}
|
||||
}
|
||||
sprintf(cad,"%u steps left ",8999-i);
|
||||
v_putcad(1,3,0x000000,0xffffff,cad);
|
||||
gp2x_video_flip();
|
||||
for(n = 0; n < 3; n++)
|
||||
{
|
||||
int m = 0;
|
||||
for(m = 0; m < 3; m++)
|
||||
{
|
||||
gp2x_screen15[320*(anty+n)+antx+m] = col2;
|
||||
}
|
||||
}
|
||||
sprintf(cad,"%u steps left ",8999-i);
|
||||
v_putcad(1,3,0x000000,0xffffff,cad);
|
||||
gp2x_video_flip();
|
||||
if(direction == 0) antx-=3;
|
||||
if(direction == 1) anty-=3;
|
||||
if(direction == 2) antx+=3;
|
||||
if(direction == 3) anty+=3;
|
||||
direction--;
|
||||
if(direction < 0) direction=3;
|
||||
}
|
||||
if(gp2x_screen15[(320*anty) + antx]==col2)
|
||||
{
|
||||
for(n = 0; n < 3; n++)
|
||||
{
|
||||
int m = 0;
|
||||
for(m = 0; m < 3; m++)
|
||||
{
|
||||
gp2x_screen15[320*(anty+n)+antx+m] = col1;
|
||||
}
|
||||
}
|
||||
sprintf(cad,"%u steps left ",8999-i);
|
||||
v_putcad(1,3,0x000000,0xffffff,cad);
|
||||
gp2x_video_flip();
|
||||
for(n = 0; n < 3; n++)
|
||||
{
|
||||
int m = 0;
|
||||
for(m = 0; m < 3; m++)
|
||||
{
|
||||
gp2x_screen15[320*(anty+n)+antx+m] = col1;
|
||||
}
|
||||
}
|
||||
sprintf(cad,"%u steps left ",8999-i);
|
||||
v_putcad(1,3,0x000000,0xffffff,cad);
|
||||
gp2x_video_flip();
|
||||
if(direction == 0) antx+=3;
|
||||
if(direction == 1) anty+=3;
|
||||
if(direction == 2) antx-=3;
|
||||
if(direction == 3) anty-=3;
|
||||
direction++;
|
||||
if(direction > 3) direction=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void speedtest(short test)
|
||||
{
|
||||
unsigned BACKGROUND;
|
||||
if(test == 0) BACKGROUND=0xB00000;
|
||||
if(test == 1) BACKGROUND=0xFFFFFF;
|
||||
short start = 240;
|
||||
short cpuspeed = start;
|
||||
unsigned char cad[256];
|
||||
FILE *speed;
|
||||
|
||||
do
|
||||
{
|
||||
speed = fopen("/mnt/sd/speed.txt", "w");
|
||||
ClearScreen(BACKGROUND);
|
||||
if(test == 0) v_putcad(1,1,0x00ff00,BACKGROUND,"Prim-Speedtest");
|
||||
if(test == 1) v_putcad(1,1,0x006600,BACKGROUND,"Ant-Speedtest");
|
||||
v_putcad(1,6,0xffffff,BACKGROUND,"Testing Speed");
|
||||
if(cpuspeed > start)
|
||||
{
|
||||
sprintf(cad,"%uMhz checked",cpuspeed-5);
|
||||
v_putcad(1,9,0xffffff,BACKGROUND,cad);
|
||||
}
|
||||
gp2x_video_flip();
|
||||
ClearScreen(BACKGROUND);
|
||||
if(test == 0) v_putcad(1,1,0x00ff00,BACKGROUND,"Prim-Speedtest");
|
||||
if(test == 1) v_putcad(1,1,0x006600,BACKGROUND,"Ant-Speedtest");
|
||||
v_putcad(1,6,0xffffff,BACKGROUND,"Testing Speed");
|
||||
if(cpuspeed > start)
|
||||
{
|
||||
sprintf(cad,"%uMhz checked",cpuspeed-5);
|
||||
if(test == 0) v_putcad(1,9,0xffffff,BACKGROUND,cad);
|
||||
if(test == 1) v_putcad(1,9,0x000000,BACKGROUND,cad);
|
||||
}
|
||||
gp2x_video_flip();
|
||||
fprintf (speed,"set CPU-Frequency = %uMHz\r\n",cpuspeed);
|
||||
set_FCLK(cpuspeed);
|
||||
|
||||
if(test == 0) prim();
|
||||
if(test == 1) ant();
|
||||
|
||||
fprintf(speed,"%uMhz checked\n\n", cpuspeed);
|
||||
cpuspeed = cpuspeed + 5;
|
||||
fclose(speed);
|
||||
execl("sync",NULL);
|
||||
}
|
||||
while(1);
|
||||
}
|
3
gp2x/speedtest.h
Normal file
3
gp2x/speedtest.h
Normal file
@ -0,0 +1,3 @@
|
||||
void prim();
|
||||
void ant();
|
||||
void speedtest(short test);
|
78790
gp2x/video.S
Normal file
78790
gp2x/video.S
Normal file
File diff suppressed because it is too large
Load Diff
181
gp2x/video_blend.S
Normal file
181
gp2x/video_blend.S
Normal file
@ -0,0 +1,181 @@
|
||||
.align 2
|
||||
|
||||
.global expand_blend
|
||||
.global expand_normal
|
||||
|
||||
@ Input:
|
||||
@ r0 = screen_src_ptr
|
||||
@ r1 = screen_dest_ptr
|
||||
@ r2 = start
|
||||
@ r3 = end
|
||||
|
||||
6:
|
||||
.word io_registers
|
||||
.word palette_ram_converted
|
||||
.word 0x04000200 @ combine test mask
|
||||
.word 0x07E0F81F @ clamp mask
|
||||
.word 0x000003FE @ palette index mask
|
||||
.word 0x08010020 @ saturation mask
|
||||
|
||||
expand_blend:
|
||||
stmdb sp!, { r4, r5, r6, r9, r10, r11, r14 }
|
||||
|
||||
add r0, r0, r2, lsl #2 @ screen_src_ptr += start
|
||||
add r1, r1, r2, lsl #1 @ screen_dest_ptr += start
|
||||
sub r2, r3, r2 @ r2 = end - start
|
||||
ldr r3, 6b @ r3 = io_registers
|
||||
ldr r3, [r3, #0x52] @ r3 = bldalpha
|
||||
mov r4, r3, lsr #8 @ r4 = bldalpha >> 8
|
||||
and r3, r3, #0x1F @ r3 = blend_a
|
||||
and r4, r4, #0x1F @ r4 = blend_b
|
||||
cmp r3, #16 @ if(blend_a > 16)
|
||||
movgt r3, #16 @ blend_a = 16
|
||||
cmp r4, #16 @ if(blend_b > 16)
|
||||
movgt r3, #16 @ blend_b = 16
|
||||
|
||||
ldr r14, 6b + 4 @ r14 = palette_ram_converted
|
||||
ldr r12, 6b + 8 @ r12 = 0x04000200
|
||||
ldr r11, 6b + 12 @ r11 = 0x07E0F81F
|
||||
ldr r10, 6b + 16 @ r10 = 0x000003FE
|
||||
|
||||
add r5, r3, r4 @ r5 = blend_a + blend_b
|
||||
cmp r5, #16 @ if((blend_a + blend_b) > 16)
|
||||
bgt 3f @ goto loop w/saturation
|
||||
|
||||
|
||||
@ loop w/o saturation
|
||||
1:
|
||||
ldr r5, [r0], #4 @ r5 = pixel_pair, screen_src_ptr++
|
||||
and r6, r5, r12 @ r6 = r5 & 0x04000200
|
||||
cmp r6, r12 @ if(r6 != 0x4000200)
|
||||
bne 2f @ goto no_blend
|
||||
|
||||
and r6, r10, r5, lsl #1 @ r6 = (pixel_pair & 0x1FF) << 1
|
||||
ldrh r6, [r14, r6] @ r6 = pixel_top
|
||||
orr r6, r6, r6, lsl #16 @ r6 = pixel_top | (pixel_top << 16)
|
||||
and r6, r6, r11 @ r6 = pixel_top_dilated
|
||||
|
||||
and r5, r10, r5, lsr #15 @ r5 = ((pixel_pair >> 16) & 0x1FF) << 1
|
||||
ldrh r5, [r14, r5] @ r5 = pixel_bottom
|
||||
orr r5, r5, r5, lsl #16 @ r5 = pixel_bottom | (pixel_bottom << 16)
|
||||
and r5, r5, r11 @ r5 = pixel_bottom_dilated
|
||||
|
||||
mul r5, r4, r5 @ r5 = pixel_bottom * blend_b = bottom_mul
|
||||
mla r5, r3, r6, r5 @ r5 = (pixel_top * blend_a) + bottom_mul
|
||||
|
||||
and r5, r11, r5, lsr #4 @ r5 = (color_dilated >> 4) & 0x07E0F81F
|
||||
orr r5, r5, r5, lsr #16 @ r5 = color_dilated | (color_dilated >> 16)
|
||||
|
||||
strh r5, [r1], #2 @ *screen_dest_ptr = r5, screen_dest_ptr++
|
||||
subs r2, r2, #1 @ counter--
|
||||
bne 1b @ go again
|
||||
|
||||
ldmia sp!, { r4, r5, r6, r9, r10, r11, pc }
|
||||
|
||||
2:
|
||||
and r5, r10, r5, lsl #1 @ r5 = (pixel_pair & 0x1FF) << 1
|
||||
ldrh r5, [r14, r5] @ r5 = pixel_top
|
||||
strh r5, [r1], #2 @ *screen_dest_ptr = r5, screen_dest_ptr++
|
||||
|
||||
subs r2, r2, #1 @ counter--
|
||||
bne 1b @ go again
|
||||
|
||||
ldmia sp!, { r4, r5, r6, r9, r10, r11, pc }
|
||||
|
||||
@ loop w/saturation
|
||||
|
||||
3:
|
||||
ldr r9, 6b + 20 @ r9 = 0x08010020
|
||||
|
||||
4:
|
||||
ldr r5, [r0], #4 @ r5 = pixel_pair, screen_src_ptr++
|
||||
and r6, r5, r12 @ r6 = r5 & 0x04000200
|
||||
cmp r6, r12 @ if(r6 != 0x4000200)
|
||||
bne 5f @ goto no_blend
|
||||
|
||||
and r6, r10, r5, lsl #1 @ r6 = (pixel_pair & 0x1FF) << 1
|
||||
ldrh r6, [r14, r6] @ r6 = pixel_top
|
||||
orr r6, r6, r6, lsl #16 @ r6 = pixel_top | (pixel_top << 16)
|
||||
and r6, r6, r11 @ r6 = pixel_top_dilated
|
||||
|
||||
and r5, r10, r5, lsr #15 @ r5 = ((pixel_pair >> 16) & 0x1FF) << 1
|
||||
ldrh r5, [r14, r5] @ r5 = pixel_bottom
|
||||
orr r5, r5, r5, lsl #16 @ r5 = pixel_bottom | (pixel_bottom << 16)
|
||||
and r5, r5, r11 @ r5 = pixel_bottom_dilated
|
||||
|
||||
mul r5, r4, r5 @ r5 = pixel_bottom * blend_b = bottom_mul
|
||||
mla r5, r3, r6, r5 @ r5 = (pixel_top * blend_a) + bottom_mul
|
||||
|
||||
and r6, r9, r5, lsr #4 @ r6 = saturation bits
|
||||
orr r6, r6, r6, lsr #1 @ propogate saturation down msb
|
||||
orr r6, r6, r6, lsr #2 @ propogate down next two bits
|
||||
orr r6, r6, r6, lsr #3 @ propogate down next three bits
|
||||
orr r5, r6, r5, lsr #4 @ mask over result w/saturation
|
||||
|
||||
and r5, r11, r5 @ r5 = (color_dilated >> 4) & 0x07E0F81F
|
||||
orr r5, r5, r5, lsr #16 @ r5 = color_dilated | (color_dilated >> 16)
|
||||
strh r5, [r1], #2 @ *screen_dest_ptr = r5, screen_dest_ptr++
|
||||
|
||||
subs r2, r2, #1 @ counter--
|
||||
bne 4b @ go again
|
||||
|
||||
ldmia sp!, { r4, r5, r6, r9, r10, r11, pc }
|
||||
|
||||
5:
|
||||
and r5, r10, r5, lsl #1 @ r5 = (pixel_pair & 0x1FF) << 1
|
||||
ldrh r5, [r14, r5] @ r5 = pixel_top
|
||||
strh r5, [r1], #2 @ *screen_dest_ptr = r5, screen_dest_ptr++
|
||||
|
||||
subs r2, r2, #1 @ counter--
|
||||
bne 4b @ go again
|
||||
|
||||
ldmia sp!, { r4, r5, r6, r9, r10, r11, pc }
|
||||
|
||||
|
||||
|
||||
@ The following function isn't complete (only works on run multiples of 8),
|
||||
@ but unfortunately I don't see much potential for actually being able to
|
||||
@ use it..
|
||||
|
||||
#define expand_pixel_pair(reg, temp) ;\
|
||||
and temp, r3, reg, lsr #15 ;\
|
||||
ldrh temp, [r2, temp] ;\
|
||||
;\
|
||||
and reg, r3, reg, lsl #1 ;\
|
||||
ldrh reg, [r2, reg] ;\
|
||||
;\
|
||||
orr reg, reg, temp, lsl #16 ;\
|
||||
|
||||
|
||||
@ Input:
|
||||
@ r0 = screen_ptr
|
||||
@ r1 = start
|
||||
@ r2 = end
|
||||
|
||||
1:
|
||||
.word palette_ram_converted
|
||||
.word 0x3FE
|
||||
|
||||
expand_normal:
|
||||
stmdb sp!, { r4, r5, r6, r7, r14 }
|
||||
|
||||
add r0, r0, r1, lsl #1 @ screen_ptr += start
|
||||
sub r1, r2, r1 @ r1 = end - start
|
||||
ldr r2, 1b @ r2 = palette_ram_converted
|
||||
ldr r3, 1b + 4 @ r3 = 0x3FE
|
||||
|
||||
2:
|
||||
ldmia r0, { r4, r5, r6, r7 }
|
||||
|
||||
expand_pixel_pair(r4, r14)
|
||||
expand_pixel_pair(r5, r14)
|
||||
expand_pixel_pair(r6, r14)
|
||||
expand_pixel_pair(r7, r14)
|
||||
|
||||
stmia r0!, { r4, r5, r6, r7 }
|
||||
|
||||
subs r1, r1, #8
|
||||
bne 2b
|
||||
|
||||
ldmia sp!, { r4, r5, r6, r7, pc }
|
||||
|
40
gui.h
Normal file
40
gui.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* gameplaySP
|
||||
*
|
||||
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef GUI_H
|
||||
#define GUI_H
|
||||
|
||||
#define GPSP_CONFIG_FILENAME "gpsp.cfg"
|
||||
|
||||
s32 load_file(u8 **wildcards, u8 *result);
|
||||
u32 adjust_frameskip(u32 button_id);
|
||||
s32 load_game_config_file();
|
||||
s32 load_config_file();
|
||||
s32 save_game_config_file();
|
||||
s32 save_config_file();
|
||||
u32 menu(u16 *original_screen);
|
||||
|
||||
extern u32 savestate_slot;
|
||||
|
||||
void get_savestate_filename_noshot(u32 slot, u8 *name_buffer);
|
||||
void get_savestate_filename(u32 slot, u8 *name_buffer);
|
||||
void get_savestate_snapshot(u8 *savestate_filename);
|
||||
|
||||
#endif
|
||||
|
899
input.c
Normal file
899
input.c
Normal file
@ -0,0 +1,899 @@
|
||||
/* gameplaySP
|
||||
*
|
||||
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
// Special thanks to psp298 for the analog->dpad code!
|
||||
|
||||
void trigger_key(u32 key)
|
||||
{
|
||||
u32 p1_cnt = io_registers[REG_P1CNT];
|
||||
u32 p1;
|
||||
|
||||
if((p1_cnt >> 14) & 0x01)
|
||||
{
|
||||
u32 key_intersection = (p1_cnt & key) & 0x3FF;
|
||||
|
||||
if(p1_cnt >> 15)
|
||||
{
|
||||
if(key_intersection == (p1_cnt & 0x3FF))
|
||||
raise_interrupt(IRQ_KEYPAD);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(key_intersection)
|
||||
raise_interrupt(IRQ_KEYPAD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 key = 0;
|
||||
|
||||
u32 global_enable_analog = 1;
|
||||
u32 analog_sensitivity_level = 4;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BUTTON_NOT_HELD,
|
||||
BUTTON_HELD_INITIAL,
|
||||
BUTTON_HELD_REPEAT
|
||||
} button_repeat_state_type;
|
||||
|
||||
|
||||
// These define autorepeat values (in microseconds), tweak as necessary.
|
||||
|
||||
#define BUTTON_REPEAT_START 200000
|
||||
#define BUTTON_REPEAT_CONTINUE 50000
|
||||
|
||||
button_repeat_state_type button_repeat_state = BUTTON_NOT_HELD;
|
||||
u32 button_repeat = 0;
|
||||
gui_action_type cursor_repeat = CURSOR_NONE;
|
||||
|
||||
|
||||
#ifdef PSP_BUILD
|
||||
|
||||
u32 gamepad_config_map[16] =
|
||||
{
|
||||
BUTTON_ID_MENU, // Triangle
|
||||
BUTTON_ID_A, // Circle
|
||||
BUTTON_ID_B, // Cross
|
||||
BUTTON_ID_START, // Square
|
||||
BUTTON_ID_L, // Ltrigger
|
||||
BUTTON_ID_R, // Rtrigger
|
||||
BUTTON_ID_DOWN, // Down
|
||||
BUTTON_ID_LEFT, // Left
|
||||
BUTTON_ID_UP, // Up
|
||||
BUTTON_ID_RIGHT, // Right
|
||||
BUTTON_ID_SELECT, // Select
|
||||
BUTTON_ID_START, // Start
|
||||
BUTTON_ID_UP, // Analog up
|
||||
BUTTON_ID_DOWN, // Analog down
|
||||
BUTTON_ID_LEFT, // Analog left
|
||||
BUTTON_ID_RIGHT // Analog right
|
||||
};
|
||||
|
||||
#define PSP_ALL_BUTTON_MASK 0xFFFF
|
||||
|
||||
gui_action_type get_gui_input()
|
||||
{
|
||||
SceCtrlData ctrl_data;
|
||||
gui_action_type new_button = CURSOR_NONE;
|
||||
u32 new_buttons;
|
||||
|
||||
static u32 last_buttons = 0;
|
||||
static u64 button_repeat_timestamp;
|
||||
|
||||
delay_us(25000);
|
||||
|
||||
sceCtrlPeekBufferPositive(&ctrl_data, 1);
|
||||
ctrl_data.Buttons &= PSP_ALL_BUTTON_MASK;
|
||||
new_buttons = (last_buttons ^ ctrl_data.Buttons) & ctrl_data.Buttons;
|
||||
last_buttons = ctrl_data.Buttons;
|
||||
|
||||
if(new_buttons & PSP_CTRL_LEFT)
|
||||
new_button = CURSOR_LEFT;
|
||||
|
||||
if(new_buttons & PSP_CTRL_RIGHT)
|
||||
new_button = CURSOR_RIGHT;
|
||||
|
||||
if(new_buttons & PSP_CTRL_UP)
|
||||
new_button = CURSOR_UP;
|
||||
|
||||
if(new_buttons & PSP_CTRL_DOWN)
|
||||
new_button = CURSOR_DOWN;
|
||||
|
||||
if(new_buttons & PSP_CTRL_START)
|
||||
new_button = CURSOR_SELECT;
|
||||
|
||||
if(new_buttons & PSP_CTRL_CIRCLE)
|
||||
new_button = CURSOR_SELECT;
|
||||
|
||||
if(new_buttons & PSP_CTRL_CROSS)
|
||||
new_button = CURSOR_EXIT;
|
||||
|
||||
if(new_buttons & PSP_CTRL_SQUARE)
|
||||
new_button = CURSOR_BACK;
|
||||
|
||||
if(new_button != CURSOR_NONE)
|
||||
{
|
||||
get_ticks_us(&button_repeat_timestamp);
|
||||
button_repeat_state = BUTTON_HELD_INITIAL;
|
||||
button_repeat = new_buttons;
|
||||
cursor_repeat = new_button;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ctrl_data.Buttons & button_repeat)
|
||||
{
|
||||
u64 new_ticks;
|
||||
get_ticks_us(&new_ticks);
|
||||
|
||||
if(button_repeat_state == BUTTON_HELD_INITIAL)
|
||||
{
|
||||
if((new_ticks - button_repeat_timestamp) >
|
||||
BUTTON_REPEAT_START)
|
||||
{
|
||||
new_button = cursor_repeat;
|
||||
button_repeat_timestamp = new_ticks;
|
||||
button_repeat_state = BUTTON_HELD_REPEAT;
|
||||
}
|
||||
}
|
||||
|
||||
if(button_repeat_state == BUTTON_HELD_REPEAT)
|
||||
{
|
||||
if((new_ticks - button_repeat_timestamp) >
|
||||
BUTTON_REPEAT_CONTINUE)
|
||||
{
|
||||
new_button = cursor_repeat;
|
||||
button_repeat_timestamp = new_ticks;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new_button;
|
||||
}
|
||||
|
||||
#define PSP_CTRL_ANALOG_UP (1 << 28)
|
||||
#define PSP_CTRL_ANALOG_DOWN (1 << 29)
|
||||
#define PSP_CTRL_ANALOG_LEFT (1 << 30)
|
||||
#define PSP_CTRL_ANALOG_RIGHT (1 << 31)
|
||||
|
||||
u32 button_psp_mask_to_config[] =
|
||||
{
|
||||
PSP_CTRL_TRIANGLE,
|
||||
PSP_CTRL_CIRCLE,
|
||||
PSP_CTRL_CROSS,
|
||||
PSP_CTRL_SQUARE,
|
||||
PSP_CTRL_LTRIGGER,
|
||||
PSP_CTRL_RTRIGGER,
|
||||
PSP_CTRL_DOWN,
|
||||
PSP_CTRL_LEFT,
|
||||
PSP_CTRL_UP,
|
||||
PSP_CTRL_RIGHT,
|
||||
PSP_CTRL_SELECT,
|
||||
PSP_CTRL_START,
|
||||
PSP_CTRL_ANALOG_UP,
|
||||
PSP_CTRL_ANALOG_DOWN,
|
||||
PSP_CTRL_ANALOG_LEFT,
|
||||
PSP_CTRL_ANALOG_RIGHT
|
||||
};
|
||||
|
||||
u32 button_id_to_gba_mask[] =
|
||||
{
|
||||
BUTTON_UP,
|
||||
BUTTON_DOWN,
|
||||
BUTTON_LEFT,
|
||||
BUTTON_RIGHT,
|
||||
BUTTON_A,
|
||||
BUTTON_B,
|
||||
BUTTON_L,
|
||||
BUTTON_R,
|
||||
BUTTON_START,
|
||||
BUTTON_SELECT,
|
||||
BUTTON_NONE,
|
||||
BUTTON_NONE,
|
||||
BUTTON_NONE,
|
||||
BUTTON_NONE
|
||||
};
|
||||
|
||||
gui_action_type get_gui_input_fs_hold(u32 button_id)
|
||||
{
|
||||
gui_action_type new_button = get_gui_input();
|
||||
if((last_buttons & button_psp_mask_to_config[button_id]) == 0)
|
||||
return CURSOR_BACK;
|
||||
|
||||
return new_button;
|
||||
}
|
||||
|
||||
u32 rapidfire_flag = 1;
|
||||
|
||||
u32 update_input()
|
||||
{
|
||||
SceCtrlData ctrl_data;
|
||||
u32 buttons;
|
||||
u32 non_repeat_buttons;
|
||||
u32 button_id;
|
||||
u32 i;
|
||||
u32 new_key = 0;
|
||||
u32 analog_sensitivity = 92 - (analog_sensitivity_level * 4);
|
||||
u32 inv_analog_sensitivity = 256 - analog_sensitivity;
|
||||
|
||||
sceCtrlPeekBufferPositive(&ctrl_data, 1);
|
||||
|
||||
buttons = ctrl_data.Buttons;
|
||||
|
||||
if(global_enable_analog)
|
||||
{
|
||||
if(ctrl_data.Lx < analog_sensitivity)
|
||||
buttons |= PSP_CTRL_ANALOG_LEFT;
|
||||
|
||||
if(ctrl_data.Lx > inv_analog_sensitivity)
|
||||
buttons |= PSP_CTRL_ANALOG_RIGHT;
|
||||
|
||||
if(ctrl_data.Ly < analog_sensitivity)
|
||||
buttons |= PSP_CTRL_ANALOG_UP;
|
||||
|
||||
if(ctrl_data.Ly > inv_analog_sensitivity)
|
||||
buttons |= PSP_CTRL_ANALOG_DOWN;
|
||||
}
|
||||
|
||||
non_repeat_buttons = (last_buttons ^ buttons) & buttons;
|
||||
last_buttons = buttons;
|
||||
|
||||
for(i = 0; i < 16; i++)
|
||||
{
|
||||
if(non_repeat_buttons & button_psp_mask_to_config[i])
|
||||
button_id = gamepad_config_map[i];
|
||||
else
|
||||
button_id = BUTTON_ID_NONE;
|
||||
|
||||
switch(button_id)
|
||||
{
|
||||
case BUTTON_ID_MENU:
|
||||
{
|
||||
u16 *screen_copy = copy_screen();
|
||||
u32 ret_val = menu(screen_copy);
|
||||
free(screen_copy);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
case BUTTON_ID_LOADSTATE:
|
||||
{
|
||||
u8 current_savestate_filename[512];
|
||||
get_savestate_filename_noshot(savestate_slot,
|
||||
current_savestate_filename);
|
||||
load_state(current_savestate_filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case BUTTON_ID_SAVESTATE:
|
||||
{
|
||||
u8 current_savestate_filename[512];
|
||||
u16 *current_screen = copy_screen();
|
||||
get_savestate_filename_noshot(savestate_slot,
|
||||
current_savestate_filename);
|
||||
save_state(current_savestate_filename, current_screen);
|
||||
free(current_screen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case BUTTON_ID_FASTFORWARD:
|
||||
print_string("FASTFORWARD", 0xFFFF, 0x0000, 0, 50);
|
||||
synchronize_flag ^= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(buttons & button_psp_mask_to_config[i])
|
||||
{
|
||||
button_id = gamepad_config_map[i];
|
||||
if(button_id < BUTTON_ID_MENU)
|
||||
{
|
||||
new_key |= button_id_to_gba_mask[button_id];
|
||||
}
|
||||
else
|
||||
|
||||
if((button_id >= BUTTON_ID_RAPIDFIRE_A) &&
|
||||
(button_id <= BUTTON_ID_RAPIDFIRE_L))
|
||||
{
|
||||
rapidfire_flag ^= 1;
|
||||
if(rapidfire_flag)
|
||||
{
|
||||
new_key |= button_id_to_gba_mask[button_id -
|
||||
BUTTON_ID_RAPIDFIRE_A + BUTTON_ID_A];
|
||||
}
|
||||
else
|
||||
{
|
||||
new_key &= ~button_id_to_gba_mask[button_id -
|
||||
BUTTON_ID_RAPIDFIRE_A + BUTTON_ID_A];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if((new_key | key) != key)
|
||||
trigger_key(new_key);
|
||||
|
||||
key = new_key;
|
||||
|
||||
io_registers[REG_P1] = (~key) & 0x3FF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void init_input()
|
||||
{
|
||||
sceCtrlSetSamplingCycle(0);
|
||||
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
|
||||
// GP2X SDL requires a user made input method
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include "gp2x/gp2x.h"
|
||||
|
||||
u32 gamepad_config_map[16] =
|
||||
{
|
||||
BUTTON_ID_UP, // Up
|
||||
BUTTON_ID_LEFT, // Left
|
||||
BUTTON_ID_DOWN, // Down
|
||||
BUTTON_ID_RIGHT, // Right
|
||||
BUTTON_ID_START, // Start
|
||||
BUTTON_ID_SELECT, // Select
|
||||
BUTTON_ID_L, // Ltrigger
|
||||
BUTTON_ID_R, // Rtrigger
|
||||
BUTTON_ID_NONE, // A
|
||||
BUTTON_ID_A, // B
|
||||
BUTTON_ID_B, // X
|
||||
BUTTON_ID_NONE, // Y
|
||||
BUTTON_ID_VOLDOWN, // Vol down
|
||||
BUTTON_ID_VOLUP, // Vol up
|
||||
BUTTON_ID_FPS, // Push
|
||||
BUTTON_ID_MENU // Vol middle
|
||||
};
|
||||
|
||||
extern u32 gp2x_fps_debug;
|
||||
|
||||
u32 gpsp_gp2x_joystick_read(void)
|
||||
{
|
||||
u32 value = (gpsp_gp2x_memregs[0x1198 >> 1] & 0x00FF);
|
||||
|
||||
if(value == 0xFD)
|
||||
value = 0xFA;
|
||||
if(value == 0xF7)
|
||||
value = 0xEB;
|
||||
if(value == 0xDF)
|
||||
value = 0xAF;
|
||||
if(value == 0x7F)
|
||||
value = 0xBE;
|
||||
|
||||
return ~((gpsp_gp2x_memregs[0x1184 >> 1] & 0xFF00) | value |
|
||||
(gpsp_gp2x_memregs[0x1186 >> 1] << 16));
|
||||
}
|
||||
|
||||
gui_action_type get_gui_input()
|
||||
{
|
||||
gui_action_type new_button = CURSOR_NONE;
|
||||
u32 buttons = gpsp_gp2x_joystick_read();
|
||||
u32 new_buttons;
|
||||
|
||||
static u32 last_buttons = 0;
|
||||
static u64 button_repeat_timestamp;
|
||||
|
||||
delay_us(25000);
|
||||
|
||||
new_buttons = (last_buttons ^ buttons) & buttons;
|
||||
last_buttons = buttons;
|
||||
|
||||
if(new_buttons & GP2X_A)
|
||||
new_button = CURSOR_BACK;
|
||||
|
||||
if(new_buttons & GP2X_X)
|
||||
new_button = CURSOR_EXIT;
|
||||
|
||||
if(new_buttons & GP2X_B)
|
||||
new_button = CURSOR_SELECT;
|
||||
|
||||
if(new_buttons & GP2X_UP)
|
||||
new_button = CURSOR_UP;
|
||||
|
||||
if(new_buttons & GP2X_DOWN)
|
||||
new_button = CURSOR_DOWN;
|
||||
|
||||
if(new_buttons & GP2X_LEFT)
|
||||
new_button = CURSOR_LEFT;
|
||||
|
||||
if(new_buttons & GP2X_RIGHT)
|
||||
new_button = CURSOR_RIGHT;
|
||||
|
||||
|
||||
if(new_button != CURSOR_NONE)
|
||||
{
|
||||
get_ticks_us(&button_repeat_timestamp);
|
||||
button_repeat_state = BUTTON_HELD_INITIAL;
|
||||
button_repeat = new_buttons;
|
||||
cursor_repeat = new_button;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(buttons & button_repeat)
|
||||
{
|
||||
u64 new_ticks;
|
||||
get_ticks_us(&new_ticks);
|
||||
|
||||
if(button_repeat_state == BUTTON_HELD_INITIAL)
|
||||
{
|
||||
if((new_ticks - button_repeat_timestamp) >
|
||||
BUTTON_REPEAT_START)
|
||||
{
|
||||
new_button = cursor_repeat;
|
||||
button_repeat_timestamp = new_ticks;
|
||||
button_repeat_state = BUTTON_HELD_REPEAT;
|
||||
}
|
||||
}
|
||||
|
||||
if(button_repeat_state == BUTTON_HELD_REPEAT)
|
||||
{
|
||||
if((new_ticks - button_repeat_timestamp) >
|
||||
BUTTON_REPEAT_CONTINUE)
|
||||
{
|
||||
new_button = cursor_repeat;
|
||||
button_repeat_timestamp = new_ticks;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new_button;
|
||||
}
|
||||
|
||||
#define GP2X_VOL_MIDDLE (1 << 24)
|
||||
|
||||
u32 button_gp2x_mask_to_config[] =
|
||||
{
|
||||
GP2X_UP,
|
||||
GP2X_LEFT,
|
||||
GP2X_DOWN,
|
||||
GP2X_RIGHT,
|
||||
GP2X_START,
|
||||
GP2X_SELECT,
|
||||
GP2X_L,
|
||||
GP2X_R,
|
||||
GP2X_A,
|
||||
GP2X_B,
|
||||
GP2X_X,
|
||||
GP2X_Y,
|
||||
GP2X_VOL_DOWN,
|
||||
GP2X_VOL_UP,
|
||||
GP2X_PUSH,
|
||||
GP2X_VOL_MIDDLE
|
||||
};
|
||||
|
||||
u32 button_id_to_gba_mask[] =
|
||||
{
|
||||
BUTTON_UP,
|
||||
BUTTON_DOWN,
|
||||
BUTTON_LEFT,
|
||||
BUTTON_RIGHT,
|
||||
BUTTON_A,
|
||||
BUTTON_B,
|
||||
BUTTON_L,
|
||||
BUTTON_R,
|
||||
BUTTON_START,
|
||||
BUTTON_SELECT,
|
||||
BUTTON_NONE,
|
||||
BUTTON_NONE,
|
||||
BUTTON_NONE,
|
||||
BUTTON_NONE
|
||||
};
|
||||
|
||||
u32 update_input()
|
||||
{
|
||||
static u32 rapidfire_flag = 1;
|
||||
static u32 last_buttons;
|
||||
u32 non_repeat_buttons;
|
||||
u32 button_id;
|
||||
u32 new_key = 0;
|
||||
u32 buttons = gpsp_gp2x_joystick_read();
|
||||
u32 i;
|
||||
|
||||
if((buttons & GP2X_VOL_DOWN) && (buttons & GP2X_VOL_UP))
|
||||
{
|
||||
buttons &= ~(GP2X_VOL_DOWN | GP2X_VOL_UP);
|
||||
buttons |= GP2X_VOL_MIDDLE;
|
||||
}
|
||||
|
||||
non_repeat_buttons = (last_buttons ^ buttons) & buttons;
|
||||
last_buttons = buttons;
|
||||
|
||||
for(i = 0; i < 16; i++)
|
||||
{
|
||||
if(non_repeat_buttons & button_gp2x_mask_to_config[i])
|
||||
button_id = gamepad_config_map[i];
|
||||
else
|
||||
button_id = BUTTON_ID_NONE;
|
||||
|
||||
switch(button_id)
|
||||
{
|
||||
case BUTTON_ID_MENU:
|
||||
{
|
||||
u16 *screen_copy = copy_screen();
|
||||
u32 ret_val = menu(screen_copy);
|
||||
free(screen_copy);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
case BUTTON_ID_LOADSTATE:
|
||||
{
|
||||
u8 current_savestate_filename[512];
|
||||
get_savestate_filename_noshot(savestate_slot,
|
||||
current_savestate_filename);
|
||||
load_state(current_savestate_filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case BUTTON_ID_SAVESTATE:
|
||||
{
|
||||
u8 current_savestate_filename[512];
|
||||
u16 *current_screen = copy_screen();
|
||||
get_savestate_filename_noshot(savestate_slot,
|
||||
current_savestate_filename);
|
||||
save_state(current_savestate_filename, current_screen);
|
||||
free(current_screen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case BUTTON_ID_FASTFORWARD:
|
||||
print_string("FASTFORWARD", 0xFFFF, 0x0000, 0, 50);
|
||||
synchronize_flag ^= 1;
|
||||
return 0;
|
||||
|
||||
case BUTTON_ID_VOLUP:
|
||||
gp2x_sound_volume(1);
|
||||
break;
|
||||
|
||||
case BUTTON_ID_VOLDOWN:
|
||||
gp2x_sound_volume(0);
|
||||
break;
|
||||
|
||||
case BUTTON_ID_FPS:
|
||||
gp2x_fps_debug ^= 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(buttons & button_gp2x_mask_to_config[i])
|
||||
{
|
||||
button_id = gamepad_config_map[i];
|
||||
if(button_id < BUTTON_ID_MENU)
|
||||
{
|
||||
new_key |= button_id_to_gba_mask[button_id];
|
||||
}
|
||||
else
|
||||
|
||||
if((button_id >= BUTTON_ID_RAPIDFIRE_A) &&
|
||||
(button_id <= BUTTON_ID_RAPIDFIRE_L))
|
||||
{
|
||||
rapidfire_flag ^= 1;
|
||||
if(rapidfire_flag)
|
||||
{
|
||||
new_key |= button_id_to_gba_mask[button_id -
|
||||
BUTTON_ID_RAPIDFIRE_A + BUTTON_ID_A];
|
||||
}
|
||||
else
|
||||
{
|
||||
new_key &= ~button_id_to_gba_mask[button_id -
|
||||
BUTTON_ID_RAPIDFIRE_A + BUTTON_ID_A];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if((new_key | key) != key)
|
||||
trigger_key(new_key);
|
||||
|
||||
key = new_key;
|
||||
|
||||
io_registers[REG_P1] = (~key) & 0x3FF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void init_input()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef PC_BUILD
|
||||
|
||||
u32 key_map(SDLKey key_sym)
|
||||
{
|
||||
switch(key_sym)
|
||||
{
|
||||
case SDLK_LSHIFT:
|
||||
return BUTTON_L;
|
||||
|
||||
case SDLK_x:
|
||||
return BUTTON_R;
|
||||
|
||||
case SDLK_DOWN:
|
||||
return BUTTON_DOWN;
|
||||
|
||||
case SDLK_UP:
|
||||
return BUTTON_UP;
|
||||
|
||||
case SDLK_LEFT:
|
||||
return BUTTON_LEFT;
|
||||
|
||||
case SDLK_RIGHT:
|
||||
return BUTTON_RIGHT;
|
||||
|
||||
case SDLK_RETURN:
|
||||
return BUTTON_START;
|
||||
|
||||
case SDLK_RSHIFT:
|
||||
return BUTTON_SELECT;
|
||||
|
||||
case SDLK_LCTRL:
|
||||
return BUTTON_B;
|
||||
|
||||
case SDLK_LALT:
|
||||
return BUTTON_A;
|
||||
|
||||
default:
|
||||
return BUTTON_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
u32 joy_map(u32 button)
|
||||
{
|
||||
switch(button)
|
||||
{
|
||||
case 4:
|
||||
return BUTTON_L;
|
||||
|
||||
case 5:
|
||||
return BUTTON_R;
|
||||
|
||||
case 9:
|
||||
return BUTTON_START;
|
||||
|
||||
case 8:
|
||||
return BUTTON_SELECT;
|
||||
|
||||
case 0:
|
||||
return BUTTON_B;
|
||||
|
||||
case 1:
|
||||
return BUTTON_A;
|
||||
|
||||
default:
|
||||
return BUTTON_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
gui_action_type get_gui_input()
|
||||
{
|
||||
SDL_Event event;
|
||||
gui_action_type gui_action = CURSOR_NONE;
|
||||
|
||||
delay_us(30000);
|
||||
|
||||
while(SDL_PollEvent(&event))
|
||||
{
|
||||
switch(event.type)
|
||||
{
|
||||
case SDL_QUIT:
|
||||
quit();
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
{
|
||||
switch(event.key.keysym.sym)
|
||||
{
|
||||
case SDLK_ESCAPE:
|
||||
gui_action = CURSOR_EXIT;
|
||||
break;
|
||||
|
||||
case SDLK_DOWN:
|
||||
gui_action = CURSOR_DOWN;
|
||||
break;
|
||||
|
||||
case SDLK_UP:
|
||||
gui_action = CURSOR_UP;
|
||||
break;
|
||||
|
||||
case SDLK_LEFT:
|
||||
gui_action = CURSOR_LEFT;
|
||||
break;
|
||||
|
||||
case SDLK_RIGHT:
|
||||
gui_action = CURSOR_RIGHT;
|
||||
break;
|
||||
|
||||
case SDLK_RETURN:
|
||||
gui_action = CURSOR_SELECT;
|
||||
break;
|
||||
|
||||
case SDLK_BACKSPACE:
|
||||
gui_action = CURSOR_BACK;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return gui_action;
|
||||
}
|
||||
|
||||
u32 update_input()
|
||||
{
|
||||
SDL_Event event;
|
||||
|
||||
while(SDL_PollEvent(&event))
|
||||
{
|
||||
switch(event.type)
|
||||
{
|
||||
case SDL_QUIT:
|
||||
quit();
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
{
|
||||
if(event.key.keysym.sym == SDLK_ESCAPE)
|
||||
{
|
||||
quit();
|
||||
}
|
||||
|
||||
if(event.key.keysym.sym == SDLK_BACKSPACE)
|
||||
{
|
||||
u16 *screen_copy = copy_screen();
|
||||
u32 ret_val = menu(screen_copy);
|
||||
free(screen_copy);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
else
|
||||
|
||||
if(event.key.keysym.sym == SDLK_F1)
|
||||
{
|
||||
debug_on();
|
||||
}
|
||||
else
|
||||
|
||||
if(event.key.keysym.sym == SDLK_F2)
|
||||
{
|
||||
FILE *fp = fopen("palette_ram.bin", "wb");
|
||||
printf("writing palette RAM\n");
|
||||
fwrite(palette_ram, 1024, 1, fp);
|
||||
fclose(fp);
|
||||
printf("writing palette VRAM\n");
|
||||
fp = fopen("vram.bin", "wb");
|
||||
fwrite(vram, 1024 * 96, 1, fp);
|
||||
fclose(fp);
|
||||
printf("writing palette OAM RAM\n");
|
||||
fp = fopen("oam_ram.bin", "wb");
|
||||
fwrite(oam_ram, 1024, 1, fp);
|
||||
fclose(fp);
|
||||
printf("writing palette I/O registers\n");
|
||||
fp = fopen("io_registers.bin", "wb");
|
||||
fwrite(io_registers, 1024, 1, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
|
||||
if(event.key.keysym.sym == SDLK_F3)
|
||||
{
|
||||
dump_translation_cache();
|
||||
}
|
||||
else
|
||||
|
||||
if(event.key.keysym.sym == SDLK_F5)
|
||||
{
|
||||
u8 current_savestate_filename[512];
|
||||
u16 *current_screen = copy_screen();
|
||||
get_savestate_filename_noshot(savestate_slot,
|
||||
current_savestate_filename);
|
||||
save_state(current_savestate_filename, current_screen);
|
||||
free(current_screen);
|
||||
}
|
||||
else
|
||||
|
||||
if(event.key.keysym.sym == SDLK_F7)
|
||||
{
|
||||
u8 current_savestate_filename[512];
|
||||
get_savestate_filename_noshot(savestate_slot,
|
||||
current_savestate_filename);
|
||||
load_state(current_savestate_filename);
|
||||
debug_on();
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
||||
if(event.key.keysym.sym == SDLK_BACKQUOTE)
|
||||
{
|
||||
synchronize_flag ^= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
key |= key_map(event.key.keysym.sym);
|
||||
trigger_key(key);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_KEYUP:
|
||||
{
|
||||
key &= ~(key_map(event.key.keysym.sym));
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
{
|
||||
key |= joy_map(event.jbutton.button);
|
||||
trigger_key(key);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_JOYBUTTONUP:
|
||||
{
|
||||
key &= ~(joy_map(event.jbutton.button));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
io_registers[REG_P1] = (~key) & 0x3FF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void init_input()
|
||||
{
|
||||
u32 joystick_count = SDL_NumJoysticks();
|
||||
|
||||
if(joystick_count > 0)
|
||||
{
|
||||
SDL_JoystickOpen(0);
|
||||
SDL_JoystickEventState(SDL_ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define input_savestate_builder(type) \
|
||||
void input_##type##_savestate(file_tag_type savestate_file) \
|
||||
{ \
|
||||
file_##type##_variable(savestate_file, key); \
|
||||
} \
|
||||
|
||||
input_savestate_builder(read);
|
||||
input_savestate_builder(write_mem);
|
||||
|
92
input.h
Normal file
92
input.h
Normal file
@ -0,0 +1,92 @@
|
||||
/* gameplaySP
|
||||
*
|
||||
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef INPUT_H
|
||||
#define INPUT_H
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BUTTON_L = 0x200,
|
||||
BUTTON_R = 0x100,
|
||||
BUTTON_DOWN = 0x80,
|
||||
BUTTON_UP = 0x40,
|
||||
BUTTON_LEFT = 0x20,
|
||||
BUTTON_RIGHT = 0x10,
|
||||
BUTTON_START = 0x08,
|
||||
BUTTON_SELECT = 0x04,
|
||||
BUTTON_B = 0x02,
|
||||
BUTTON_A = 0x01,
|
||||
BUTTON_NONE = 0x00
|
||||
} input_buttons_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BUTTON_ID_UP,
|
||||
BUTTON_ID_DOWN,
|
||||
BUTTON_ID_LEFT,
|
||||
BUTTON_ID_RIGHT,
|
||||
BUTTON_ID_A,
|
||||
BUTTON_ID_B,
|
||||
BUTTON_ID_L,
|
||||
BUTTON_ID_R,
|
||||
BUTTON_ID_START,
|
||||
BUTTON_ID_SELECT,
|
||||
BUTTON_ID_MENU,
|
||||
BUTTON_ID_FASTFORWARD,
|
||||
BUTTON_ID_LOADSTATE,
|
||||
BUTTON_ID_SAVESTATE,
|
||||
BUTTON_ID_RAPIDFIRE_A,
|
||||
BUTTON_ID_RAPIDFIRE_B,
|
||||
BUTTON_ID_RAPIDFIRE_L,
|
||||
BUTTON_ID_RAPIDFIRE_R,
|
||||
BUTTON_ID_VOLUP,
|
||||
BUTTON_ID_VOLDOWN,
|
||||
BUTTON_ID_FPS,
|
||||
BUTTON_ID_NONE
|
||||
} input_buttons_id_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CURSOR_UP,
|
||||
CURSOR_DOWN,
|
||||
CURSOR_LEFT,
|
||||
CURSOR_RIGHT,
|
||||
CURSOR_SELECT,
|
||||
CURSOR_BACK,
|
||||
CURSOR_EXIT,
|
||||
CURSOR_NONE
|
||||
} gui_action_type;
|
||||
|
||||
void init_input();
|
||||
u32 update_input();
|
||||
gui_action_type get_gui_input();
|
||||
gui_action_type get_gui_input_fs_hold(u32 button_id);
|
||||
void input_write_mem_savestate(file_tag_type savestate_file);
|
||||
void input_read_savestate(file_tag_type savestate_file);
|
||||
|
||||
extern u32 gamepad_config_map[16];
|
||||
extern u32 global_enable_analog;
|
||||
extern u32 analog_sensitivity_level;
|
||||
|
||||
#if defined(GP2X_BUILD)
|
||||
u32 gpsp_gp2x_joystick_read(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
202
main.h
Normal file
202
main.h
Normal file
@ -0,0 +1,202 @@
|
||||
/* gameplaySP
|
||||
*
|
||||
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TIMER_INACTIVE,
|
||||
TIMER_PRESCALE,
|
||||
TIMER_CASCADE
|
||||
} timer_status_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TIMER_NO_IRQ,
|
||||
TIMER_TRIGGER_IRQ
|
||||
} timer_irq_type;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TIMER_DS_CHANNEL_NONE,
|
||||
TIMER_DS_CHANNEL_A,
|
||||
TIMER_DS_CHANNEL_B,
|
||||
TIMER_DS_CHANNEL_BOTH
|
||||
} timer_ds_channel_type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
s32 count;
|
||||
u32 reload;
|
||||
u32 prescale;
|
||||
u32 stop_cpu_ticks;
|
||||
fixed16_16 frequency_step;
|
||||
timer_ds_channel_type direct_sound_channels;
|
||||
timer_irq_type irq;
|
||||
timer_status_type status;
|
||||
} timer_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
auto_frameskip,
|
||||
manual_frameskip,
|
||||
no_frameskip
|
||||
} frameskip_type;
|
||||
|
||||
extern u32 cpu_ticks;
|
||||
extern u32 frame_ticks;
|
||||
extern u32 execute_cycles;
|
||||
extern frameskip_type current_frameskip_type;
|
||||
extern u32 frameskip_value;
|
||||
extern u32 random_skip;
|
||||
extern u32 global_cycles_per_instruction;
|
||||
extern u32 synchronize_flag;
|
||||
extern u32 skip_next_frame;
|
||||
|
||||
extern timer_type timer[4];
|
||||
static u32 prescale_table[] = { 0, 6, 8, 10 };
|
||||
|
||||
extern u32 cycle_memory_access;
|
||||
extern u32 cycle_pc_relative_access;
|
||||
extern u32 cycle_sp_relative_access;
|
||||
extern u32 cycle_block_memory_access;
|
||||
extern u32 cycle_block_memory_sp_access;
|
||||
extern u32 cycle_block_memory_words;
|
||||
extern u32 cycle_dma16_words;
|
||||
extern u32 cycle_dma32_words;
|
||||
extern u32 flush_ram_count;
|
||||
|
||||
extern u64 base_timestamp;
|
||||
|
||||
extern u8 main_path[512];
|
||||
|
||||
extern u32 update_backup_flag;
|
||||
extern u32 clock_speed;
|
||||
|
||||
u32 update_gba();
|
||||
void reset_gba();
|
||||
void synchronize();
|
||||
void quit();
|
||||
void delay_us(u32 us_count);
|
||||
void get_ticks_us(u64 *tick_return);
|
||||
void game_name_ext(u8 *src, u8 *buffer, u8 *extension);
|
||||
void main_write_mem_savestate(file_tag_type savestate_file);
|
||||
void main_read_savestate(file_tag_type savestate_file);
|
||||
|
||||
|
||||
#ifdef PSP_BUILD
|
||||
|
||||
u32 file_length(u8 *filename, s32 dummy);
|
||||
|
||||
extern u32 real_frame_count;
|
||||
extern u32 virtual_frame_count;
|
||||
extern u32 max_frameskip;
|
||||
extern u32 num_skipped_frames;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
|
||||
extern u64 frame_count_initial_timestamp;
|
||||
extern u32 real_frame_count;
|
||||
extern u32 virtual_frame_count;
|
||||
extern u32 max_frameskip;
|
||||
extern u32 num_skipped_frames;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PC_BUILD
|
||||
|
||||
u32 file_length(u8 *dummy, FILE *fp);
|
||||
|
||||
#endif
|
||||
|
||||
#define count_timer(timer_number) \
|
||||
timer[timer_number].reload = 0x10000 - value; \
|
||||
if(timer_number < 2) \
|
||||
{ \
|
||||
u32 timer_reload = \
|
||||
timer[timer_number].reload << timer[timer_number].prescale; \
|
||||
sound_update_frequency_step(timer_number); \
|
||||
} \
|
||||
|
||||
#define adjust_sound_buffer(timer_number, channel) \
|
||||
if(timer[timer_number].direct_sound_channels & (0x01 << channel)) \
|
||||
{ \
|
||||
direct_sound_channel[channel].buffer_index = \
|
||||
(direct_sound_channel[channel].buffer_index + buffer_adjust) % \
|
||||
BUFFER_SIZE; \
|
||||
} \
|
||||
|
||||
#define trigger_timer(timer_number) \
|
||||
if(value & 0x80) \
|
||||
{ \
|
||||
if(timer[timer_number].status == TIMER_INACTIVE) \
|
||||
{ \
|
||||
u32 prescale = prescale_table[value & 0x03]; \
|
||||
u32 timer_reload = timer[timer_number].reload; \
|
||||
\
|
||||
if((value >> 2) & 0x01) \
|
||||
timer[timer_number].status = TIMER_CASCADE; \
|
||||
else \
|
||||
timer[timer_number].status = TIMER_PRESCALE; \
|
||||
\
|
||||
timer[timer_number].prescale = prescale; \
|
||||
timer[timer_number].irq = (value >> 6) & 0x01; \
|
||||
\
|
||||
address16(io_registers, 0x100 + (timer_number * 4)) = \
|
||||
-timer_reload; \
|
||||
\
|
||||
timer_reload <<= prescale; \
|
||||
timer[timer_number].count = timer_reload; \
|
||||
\
|
||||
if(timer_reload < execute_cycles) \
|
||||
execute_cycles = timer_reload; \
|
||||
\
|
||||
if(timer_number < 2) \
|
||||
{ \
|
||||
u32 buffer_adjust = \
|
||||
(u32)(((float)(cpu_ticks - timer[timer_number].stop_cpu_ticks) * \
|
||||
sound_frequency) / 16777216.0) * 2; \
|
||||
\
|
||||
sound_update_frequency_step(timer_number); \
|
||||
adjust_sound_buffer(timer_number, 0); \
|
||||
adjust_sound_buffer(timer_number, 1); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if(timer[timer_number].status != TIMER_INACTIVE) \
|
||||
{ \
|
||||
timer[timer_number].status = TIMER_INACTIVE; \
|
||||
timer[timer_number].stop_cpu_ticks = cpu_ticks; \
|
||||
} \
|
||||
} \
|
||||
address16(io_registers, 0x102 + (timer_number * 4)) = value; \
|
||||
|
||||
void change_ext(u8 *src, u8 *buffer, u8 *extension);
|
||||
|
||||
#endif
|
||||
|
||||
|
219
memory.h
Normal file
219
memory.h
Normal file
@ -0,0 +1,219 @@
|
||||
/* gameplaySP
|
||||
*
|
||||
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MEMORY_H
|
||||
#define MEMORY_H
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DMA_START_IMMEDIATELY,
|
||||
DMA_START_VBLANK,
|
||||
DMA_START_HBLANK,
|
||||
DMA_START_SPECIAL,
|
||||
DMA_INACTIVE
|
||||
} dma_start_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DMA_16BIT,
|
||||
DMA_32BIT
|
||||
} dma_length_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DMA_NO_REPEAT,
|
||||
DMA_REPEAT
|
||||
} dma_repeat_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DMA_INCREMENT,
|
||||
DMA_DECREMENT,
|
||||
DMA_FIXED,
|
||||
DMA_RELOAD
|
||||
} dma_increment_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DMA_NO_IRQ,
|
||||
DMA_TRIGGER_IRQ
|
||||
} dma_irq_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DMA_DIRECT_SOUND_A,
|
||||
DMA_DIRECT_SOUND_B,
|
||||
DMA_NO_DIRECT_SOUND
|
||||
} dma_ds_type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 dma_channel;
|
||||
u32 source_address;
|
||||
u32 dest_address;
|
||||
u32 length;
|
||||
dma_repeat_type repeat_type;
|
||||
dma_ds_type direct_sound_channel;
|
||||
dma_increment_type source_direction;
|
||||
dma_increment_type dest_direction;
|
||||
dma_length_type length_type;
|
||||
dma_start_type start_type;
|
||||
dma_irq_type irq;
|
||||
} dma_transfer_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
REG_DISPCNT = 0x000,
|
||||
REG_DISPSTAT = 0x002,
|
||||
REG_VCOUNT = 0x003,
|
||||
REG_BG0CNT = 0x004,
|
||||
REG_BG1CNT = 0x005,
|
||||
REG_BG2CNT = 0x006,
|
||||
REG_BG3CNT = 0x007,
|
||||
REG_BG0HOFS = 0x08,
|
||||
REG_BG0VOFS = 0x09,
|
||||
REG_BG1HOFS = 0x0A,
|
||||
REG_BG1VOFS = 0x0B,
|
||||
REG_BG2HOFS = 0x0C,
|
||||
REG_BG2VOFS = 0x0D,
|
||||
REG_BG3HOFS = 0x0E,
|
||||
REG_BG3VOFS = 0x0F,
|
||||
REG_BG2PA = 0x10,
|
||||
REG_BG2PB = 0x11,
|
||||
REG_BG2PC = 0x12,
|
||||
REG_BG2PD = 0x13,
|
||||
REG_BG2X_L = 0x14,
|
||||
REG_BG2X_H = 0x15,
|
||||
REG_BG2Y_L = 0x16,
|
||||
REG_BG2Y_H = 0x17,
|
||||
REG_BG3PA = 0x18,
|
||||
REG_BG3PB = 0x19,
|
||||
REG_BG3PC = 0x1A,
|
||||
REG_BG3PD = 0x1B,
|
||||
REG_BG3X_L = 0x1C,
|
||||
REG_BG3X_H = 0x1D,
|
||||
REG_BG3Y_L = 0x1E,
|
||||
REG_BG3Y_H = 0x1F,
|
||||
REG_WIN0H = 0x20,
|
||||
REG_WIN1H = 0x21,
|
||||
REG_WIN0V = 0x22,
|
||||
REG_WIN1V = 0x23,
|
||||
REG_WININ = 0x24,
|
||||
REG_WINOUT = 0x25,
|
||||
REG_BLDCNT = 0x28,
|
||||
REG_BLDALPHA = 0x29,
|
||||
REG_BLDY = 0x2A,
|
||||
REG_TM0D = 0x80,
|
||||
REG_TM0CNT = 0x81,
|
||||
REG_TM1D = 0x82,
|
||||
REG_TM1CNT = 0x83,
|
||||
REG_TM2D = 0x84,
|
||||
REG_TM2CNT = 0x85,
|
||||
REG_TM3D = 0x86,
|
||||
REG_TM3CNT = 0x87,
|
||||
REG_P1 = 0x098,
|
||||
REG_P1CNT = 0x099,
|
||||
REG_RCNT = 0x9A,
|
||||
REG_IE = 0x100,
|
||||
REG_IF = 0x101,
|
||||
REG_IME = 0x104,
|
||||
REG_HALTCNT = 0x180
|
||||
} hardware_register;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FLASH_DEVICE_MACRONIX_64KB = 0x1C,
|
||||
FLASH_DEVICE_AMTEL_64KB = 0x3D,
|
||||
FLASH_DEVICE_SST_64K = 0xD4,
|
||||
FLASH_DEVICE_PANASONIC_64KB = 0x1B,
|
||||
FLASH_DEVICE_MACRONIX_128KB = 0x09
|
||||
} flash_device_id_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FLASH_MANUFACTURER_MACRONIX = 0xC2,
|
||||
FLASH_MANUFACTURER_AMTEL = 0x1F,
|
||||
FLASH_MANUFACTURER_PANASONIC = 0x32,
|
||||
FLASH_MANUFACTURER_SST = 0xBF
|
||||
} flash_manufacturer_id_type;
|
||||
|
||||
u8 function_cc read_memory8(u32 address);
|
||||
u32 function_cc read_memory16(u32 address);
|
||||
u16 function_cc read_memory16_signed(u32 address);
|
||||
u32 function_cc read_memory32(u32 address);
|
||||
cpu_alert_type function_cc write_memory8(u32 address, u8 value);
|
||||
cpu_alert_type function_cc write_memory16(u32 address, u16 value);
|
||||
cpu_alert_type function_cc write_memory32(u32 address, u32 value);
|
||||
|
||||
extern u8 *memory_regions[16];
|
||||
extern u32 memory_limits[16];
|
||||
|
||||
/* EDIT: Shouldn't this be extern ?! */
|
||||
extern u32 waitstate_cycles_sequential[16][3];
|
||||
|
||||
extern u32 gamepak_size;
|
||||
extern u8 gamepak_title[13];
|
||||
extern u8 gamepak_code[5];
|
||||
extern u8 gamepak_maker[3];
|
||||
extern u8 gamepak_filename[512];
|
||||
|
||||
cpu_alert_type dma_transfer(dma_transfer_type *dma);
|
||||
u8 *memory_region(u32 address, u32 *memory_limit);
|
||||
u32 load_gamepak(char *name);
|
||||
u32 load_backup(char *name);
|
||||
s32 load_bios(char *name);
|
||||
void update_backup();
|
||||
void update_backup_force();
|
||||
void init_memory();
|
||||
void init_gamepak_buffer();
|
||||
void bios_region_read_allow();
|
||||
void bios_region_read_protect();
|
||||
u8 *load_gamepak_page(u32 physical_index);
|
||||
void memory_write_mem_savestate(file_tag_type savestate_file);
|
||||
void memory_read_savestate(file_tag_type savestate_file);
|
||||
void load_state(char *savestate_filename);
|
||||
void save_state(char *savestate_filename, u16 *screen_capture);
|
||||
|
||||
extern u8 *gamepak_rom;
|
||||
extern u32 gamepak_ram_buffer_size;
|
||||
extern u32 oam_update;
|
||||
extern u32 gbc_sound_update;
|
||||
extern u32 gbc_sound_wave_update;
|
||||
extern dma_transfer_type dma[4];
|
||||
|
||||
extern u8 *write_mem_ptr;
|
||||
|
||||
extern u16 palette_ram[512];
|
||||
extern u16 oam_ram[512];
|
||||
extern u16 palette_ram_converted[512];
|
||||
extern u16 io_registers[1024 * 16];
|
||||
extern u8 ewram[1024 * 256 * 2];
|
||||
extern u8 iwram[1024 * 32 * 2];
|
||||
extern u8 vram[1024 * 96 * 2];
|
||||
|
||||
extern u8 bios_rom[1024 * 32];
|
||||
extern u32 bios_read_protect;
|
||||
|
||||
extern u8 *memory_map_read[8 * 1024];
|
||||
extern u32 *reg;
|
||||
extern u8 *memory_map_write[8 * 1024];
|
||||
|
||||
extern flash_device_id_type flash_device_id;
|
||||
|
||||
#endif
|
26
psp/Makefile
Normal file
26
psp/Makefile
Normal file
@ -0,0 +1,26 @@
|
||||
# -x assembler-with-cpp
|
||||
# gpSP makefile
|
||||
# Gilead Kutnick - Exophase
|
||||
|
||||
# Global definitions
|
||||
|
||||
PSPSDK = ${shell psp-config --pspsdk-path}
|
||||
PREFIX = ${shell psp-config --psp-prefix}
|
||||
|
||||
OBJS = main.o cpu.o video.o memory.o sound.o input.o \
|
||||
cpu_threaded.o gui.o zip.o cheats.o mips_stub.o
|
||||
|
||||
TARGET = gpSP
|
||||
|
||||
VPATH += ..
|
||||
CFLAGS += -O3 -DPSP_BUILD -G0 -funsigned-char
|
||||
CFLAGS += ${shell ${PREFIX}/bin/sdl-config --cflags}
|
||||
ASFLAGS = ${CFLAGS}
|
||||
PSP_EBOOT_TITLE = gpSP
|
||||
EXTRA_TARGETS = EBOOT.PBP
|
||||
|
||||
LIBS += ${shell ${PREFIX}/bin/sdl-config --libs} -lpsppower \
|
||||
-lz
|
||||
|
||||
include ${PSPSDK}/lib/build.mak
|
||||
|
2531
psp/mips_emit.h
Normal file
2531
psp/mips_emit.h
Normal file
File diff suppressed because it is too large
Load Diff
3427
psp/mips_stub.S
Normal file
3427
psp/mips_stub.S
Normal file
File diff suppressed because it is too large
Load Diff
880
readme.txt
Normal file
880
readme.txt
Normal file
@ -0,0 +1,880 @@
|
||||
-- gameplaySP Gameboy Advance emulator for Playstation Portable --
|
||||
|
||||
|
||||
-- Release log --
|
||||
|
||||
v0.91 (minor cleanup release)
|
||||
|
||||
NOTE: I don't usually do minor releases but I rewrote a ton of
|
||||
things in gpSP 0.9, much of it during the last few days, and although
|
||||
I spent a lot of time debugging a few bugs inevitably crept in.
|
||||
|
||||
# Fixed some issues in the new memory handlers that crept up, hopefully
|
||||
should fix the problems between 0.8 and 0.9.
|
||||
# Fixed a bug introduced in 0.9 that could cause crashes when selecting
|
||||
things in the menu (I hope, at least).
|
||||
# Fixed a bug with a certain invalid opcode causing a jump to be scanned
|
||||
when there isn't one (fixes Sabre Wulf).
|
||||
# Removed 2048 option for audio buffer.
|
||||
|
||||
v0.9 (yes, it's still beta)
|
||||
|
||||
NOTE: As some of you may be aware I'm pretty much tired of these
|
||||
unofficial releases by people (okay, mostly single person) who
|
||||
don't wish to follow my wishes. I'm in the process of asking this
|
||||
person to stop, in his own language. However, I want to make
|
||||
something clear. Look at the last six new features in this
|
||||
changelog. I added these TODAY. I could have done them at any
|
||||
time. But I didn't, because I spent many (dozens, quite possibly
|
||||
hundreds) hours debugging games that people want to play. I have
|
||||
always believed that this is far more important than spending time
|
||||
on new features. Frankly, I'm tired of my emulator being hacked on
|
||||
by other people, and if it doesn't stop I'm going to make this
|
||||
project closed source.
|
||||
|
||||
Since I know this information is most visible when updated on the
|
||||
major sites, note that it is the news posters I am especially
|
||||
talking to. Next time you upload unofficial releases of my
|
||||
emulator (without even knowing what's changed) bear in mind that
|
||||
you're only encouraging me to stop working on this. If you want
|
||||
to pick sides between me and unofficial devs, be my guest. I'll
|
||||
let you decide by the contents of this release who's doing more
|
||||
for my emulator.
|
||||
|
||||
Oh, and if you downloaded a version of gpSP that has more than
|
||||
"gpSP" in its name then you're using one of their versions. Shame
|
||||
on them for not even removing this threatening message, and shame
|
||||
on you. Unless you're using a port I endorse (GP2X, Dreamcast, etc),
|
||||
in which case everything's good.
|
||||
|
||||
|
||||
# Fixed stereo output being reversed.
|
||||
# Fixed a bug causing misaligned errors on 8bit writes to the gbc
|
||||
audio channel 3 wave data (fixes various Super Robot Wars games)
|
||||
# Fixed DMA with garbage in their upper 4 bits (fixes a crash in
|
||||
Zelda: Minish Cap)
|
||||
# Added double buffering to the rendering, removes line artifacts.
|
||||
Big thanks to Brunni for the idea.
|
||||
# Fixed a bug preventing some SRAM based games from saving (fixes
|
||||
MMBN4-6)
|
||||
# Fixed a bug causing part of EWRAM to potentially get corrupted if
|
||||
code segments loaded in EWRAM cross 32KB boundaries (fixes
|
||||
Phantasy Star 2)
|
||||
# Fixed a bug causing games using movs pc in user mode (very bad
|
||||
behavior) to crash. Fixes Colin McRae Rally 2.0.
|
||||
# Improved timing a bit more. Fixes GTA Advance.
|
||||
# Fixed a sprite clipping bug (fixes crash in third boss of Zelda:
|
||||
Minish cap)
|
||||
# Increased translation buffer size significantly (fixes Donkey Kong:
|
||||
King of Swing)
|
||||
# Fixed a dynarec bug causing add pc, reg to not work in Thumb code
|
||||
(fixes crash in DBZ:LoZ, seems to fix crashes in battle in Golden
|
||||
Sun, probably fixes other games)
|
||||
# Made sprites using tiles < 512 not display in modes 3-5 (fixes
|
||||
a couple minor graphical bugs)
|
||||
# Removed abort on instruction 0x00000000 hack, was breaking a
|
||||
certain bugged up game (Scurge)
|
||||
# Fixed bug in flags generating variable logical shifts (fixes
|
||||
SD Gundam Force)
|
||||
# Fixed unaligned 16bit reads (fixes DBZ:LoZ in game)
|
||||
# Redid contiguous block flag modification checking AGAIN and
|
||||
hopefully got it right this time (fixes Mario vs. Donkey Kong)
|
||||
# Redid ldm/stm instructions, fixing some cases (along with the
|
||||
timing improvements fixes Mario & Luigi)
|
||||
# Fixed 14bit EEPROM addressing (hopefully fixes saving in a lot
|
||||
of games)
|
||||
# Completely redid memory handlers, accurately emulates open and
|
||||
BIOS reads now. Fixes Zelda: Minish Cap (roll bug, last dungeon),
|
||||
Rayman, MMBN 1 (last dungeon), probably others.
|
||||
# Fixed a minor graphical glitch on the edges of the screen
|
||||
(thanks Brunni and hlide for the help!)
|
||||
# Fixed crash on loading savestates from files of games not currently
|
||||
loaded, but be sure you have the exact file you loaded it from or
|
||||
gpSP will exit.
|
||||
@ New memory handlers should provide performance boost for games
|
||||
that access VRAM significantly (ie 3D games)
|
||||
@ Added dead flag elimination checking for logical shifts, probably
|
||||
doesn't make a noticeable difference but should have been there
|
||||
anyway.
|
||||
+ Added rapidfire to the button mappings.
|
||||
+ Added auto frameskip. Removed fractional frameskip (don't think
|
||||
it's very useful with auto anyway). Select auto in the graphics/
|
||||
sound menu to activate it; frameskip value will act as the
|
||||
maximum (auto is by default on). Thanks again to Brunni for some
|
||||
help with this. Frameskip options are game specific.
|
||||
+ Added vsync to the rendering. Only occurs when frames aren't
|
||||
skipped. Seems to reduce tearing at least some of the time.
|
||||
+ Added non-filtered video option.
|
||||
+ Cheat support (Gameshark/Pro Action Replay v1-v3 only), still
|
||||
in early stages, doesn't support everything; codes may cause
|
||||
the game to crash, haven't determined yet if the codes are bad
|
||||
or the implementation is. See cheat section for more information.
|
||||
+ Added ability to change audio buffer size. Does not take affect
|
||||
until you restart the game.
|
||||
+ Added analog config options.
|
||||
+ Added ability to set analog sensitivity and turn off analog.
|
||||
+ Added ability to change the clock speed. This is a game specific
|
||||
option. Try lower speeds w/auto frameskip to save battery life.
|
||||
+ Fixed savestate speed on crappy Sony sticks.
|
||||
|
||||
(legend: # bug fix, + feature addition, @ optimization)
|
||||
|
||||
v0.8 - ("unlocked" beta)
|
||||
|
||||
NOTE 1: It has come to my attention that there are actually BIOSes
|
||||
out there that are being used that cause some games to not work.
|
||||
The BIOS md5sum listed here is for the BIOS actually in GBAs and
|
||||
is as accurate as you'll get, (if you have a GBA and a flashcart
|
||||
you can dump it yourself, see http://wiki.pocketheaven.com/GBA_BIOS)
|
||||
|
||||
NOTE 2: Since I know this is as far as a lot of people here I have a
|
||||
little request. Please, please, (I'd italicize this if I could)
|
||||
please stop constantly asking me when the next release will be,
|
||||
what it'll have, etc. And while you're at it, please stop asking me
|
||||
to implement wi-fi multiplayer, cheat support, or fix all of your
|
||||
games. Some things will happen in due time, other things might not
|
||||
ever happen. I devote about as much time as I can to this emulator
|
||||
and I carefully include as much as I can in releases to try to
|
||||
minimize the number of people who will nag me next time (erm, I
|
||||
mean, to make the most people happy), so I don't release every other
|
||||
day or anything like that. Sorry that I can't release once a week,
|
||||
but I'm a lot busier now than I was when I was first developing this
|
||||
emulator. Good thing I got the first version out before that, wasn't
|
||||
it?
|
||||
|
||||
Congratulations, you made it this far! Now read the rest of the this
|
||||
thing. *_*
|
||||
|
||||
|
||||
# Fixed bug in dead flag elimination, "alt" version no longer needed.
|
||||
# Fixed EEPROM saves being saved as 32kb instead of 512bytes/8kb
|
||||
+ 32MB ROM support has been added. ROMS are "demand loaded" as
|
||||
necessary and page swapped out; there might be a small loading lag,
|
||||
but I have yet to ever really notice anything.
|
||||
NOTE: 32MB ROM support only works for unzipped ROMs.
|
||||
+ Save states have been added. See the save state menu for save/load
|
||||
options.
|
||||
+ Support for the real-time clock (RTC) chip in Pokemon cartridegs
|
||||
and other games. The implementation is based off of VBA's, whatever
|
||||
notes on gbadev I could find, and some of my own reverse engineering
|
||||
of what the games do... it might not be totally correct. Also,
|
||||
setting the time does not work.
|
||||
+ Per-game configuration. Currently this only saves frameskip and
|
||||
frameskip variation options.
|
||||
+ Removed the flash type option from the menu and instead added it
|
||||
to game_config.txt. Hopefully got everything - let me know if you
|
||||
find something that isn't there. It's pretty easy to add them if you
|
||||
have to.
|
||||
+ Added a display in the upper left-hand corner to indicate when
|
||||
fast-forward is on.
|
||||
+ Added button bindings for save/load state.
|
||||
@ Found a fix of StrmnNrmn proportion: far too much unnecessary mutex
|
||||
synchronization was going on. Removing the two offending lines of
|
||||
code gave a massive speed boost for free. Enjoy.
|
||||
|
||||
v0.7 - (beta than ever)
|
||||
|
||||
# Fixed a dynarec bug involving flags generating functions in
|
||||
contiguous conditional blocks. Fixes music in Super Mario
|
||||
Advance 2-4.
|
||||
# Fixed a dynarec bug where Thumb mov imm instructions wouldn't
|
||||
set flags. Fixes Zelda: Minish Cap, Megaman Battle Network,
|
||||
probably others. Comes at a slight speed cost.
|
||||
# Fixed a MIPS dynarec bug where some delay slots might not
|
||||
get filled rarely, causing chaos. Don't know if it improves
|
||||
any games.
|
||||
# Improved self-modifying code detection. Makes Golden Sun,
|
||||
Golden Sun 2, and Madden 2007 sorta work but excrutiatingly
|
||||
slowly. Looking for a game-specific workaround for this - if you
|
||||
want to play these games you'll have to wait for now :(
|
||||
# Fixed a bug causing the interrupt disable flag to go down
|
||||
when SWIs are entered, causing crashes/resets. Fixes
|
||||
Super Mario Advance 2-4.
|
||||
# Fixed menu crashing when strings with certain characters are
|
||||
printed (for instance going to the menu after loading the
|
||||
BIOS)
|
||||
# Accidentally forgot to render win0 + win1 + objwin when all
|
||||
active at the same time, many weeks ago. Added that, should fix
|
||||
some parts in games that had frozen screens.
|
||||
# Fixed some issues with gpsp.cfg needing to be present and
|
||||
corrupting, hopefully. At the very least sanity checks are
|
||||
performed on the config file.
|
||||
# Made it so assigning the frameskip button to something besides
|
||||
triangle actually worked as expected.
|
||||
# Fixed ability to restart current game if nothing is loaded
|
||||
(ie, crash)
|
||||
# Added interrupt on cpsr modification support to the dynarec
|
||||
(fixes backgrounds in Castlevania: Harmony of Dissonance)
|
||||
# Added open addressing for ldm/stm instructions (fixes
|
||||
Super Mario Advance 3)
|
||||
# Improved cycle accuracy a little. Don't know of anything this
|
||||
fixes, but games with idle loops will run a little better w/o
|
||||
idle loop elimination (but should still be added when possible)
|
||||
# Fixed some bugs causing sound to play sometimes when it shouldn't.
|
||||
@ Added dead flag elimination for Thumb code. May possibly have
|
||||
noticeable performance increases (Thumb emited coded size can
|
||||
have a reduction of 20% or more)
|
||||
@ Added code generation for divide SWI. May have a small speed
|
||||
increase in some games.
|
||||
+ Added analog nub support (special thanks to psp298 for the
|
||||
code)
|
||||
+ Added fractional frameskip. Go below 0 to get them. A frameskip
|
||||
of 1/2 for instance means render 2 out of every 3 frames, 2/3
|
||||
means render 3 out of every 4 frames, etc. Possibly useful for
|
||||
games that are not quite fast enough at fs0 but fullspeed at
|
||||
fs1...
|
||||
|
||||
v0.6 - (still beta quality, look out for new bugs)
|
||||
|
||||
NOTE: Please include gpsp.cfg with EBOOT.PBP, this shouldn't be
|
||||
necessary but I think it is right now.
|
||||
|
||||
# Fixed a nasty bug that shouldn't have made it into the initial
|
||||
release; a lot of games that TECM.. erm.. crash won't anymore.
|
||||
NOTE: This doesn't mean that no game will ever crash, freeze,
|
||||
otherwise not work.
|
||||
# Fixed some crashes in the GUI and the ability to "go up" past
|
||||
ms0:/PSP. Made the "go up" button square like it was supposed to
|
||||
be (instead of cross).
|
||||
+ There's now a menu that you can access, by default press right
|
||||
while holding down triangle for the frameskip bar.
|
||||
+ Menu option: resize screen aspect ratio, the default is now
|
||||
"scaled 3:2" which makes it look more like a normal GBA. You
|
||||
can use "fullscreen" (what it was like before) or "unscaled 3:2"
|
||||
(tiny but pixel for pixel like a GBA)
|
||||
+ Menu option: You can now load new games while the current one
|
||||
is running.
|
||||
+ Menu option: You can now restart the currently running game.
|
||||
+ Menu option: Frameskip variation - this defaults to "uniform"
|
||||
whereas it defaulted to "random" last release. Basically, turn
|
||||
it on random if you find that frameskip causes flickering
|
||||
animations to make things disappear. Other than that it will
|
||||
generally look better on uniform.
|
||||
+ GUI and file loading now have "auto repeat" on the buttons so
|
||||
they're not such a pain to navigate.
|
||||
+ Menu option: Added support for 128KB flash ROM, some games
|
||||
require it (Pokemon Firered/Leaf Green, Super Mario Advance 4),
|
||||
turn it on before running the game to make sure it works.
|
||||
NOTE: There are some versions of these ROMs that have been
|
||||
hacked to get around their 128KB flash, and may not even work
|
||||
properly at all. Look out for them, these games should save
|
||||
128KB save files after you set the setting to it, IF they use
|
||||
128KB flash.
|
||||
+ Menu option: Added ability to make the .sav files only update
|
||||
when you exit the emulator, use with extreme caution (in other
|
||||
words, it's not a good idea to use something like this in beta
|
||||
quality software if you care about your saves). Does NOT update
|
||||
if you exit through the home button, don't use the home button
|
||||
if you can help it.
|
||||
+ Zip support thanks to SiberianSTAR. It will load the first file
|
||||
with the extension .gba or .bin that it finds.
|
||||
+ Menu options are saved to gpsp.cfg. Note that it does not save
|
||||
frameskip options or flash ROM options because these are very
|
||||
per game particular.
|
||||
+ The emulator will now try to save backup files to something
|
||||
more matching the backup size than a fixed 64KB.
|
||||
@ Loading ROMs and the auto save of the .sav files is MUCH faster
|
||||
now. Thanks for the heads up on how to improve this from pollux!
|
||||
@ While coding for the screen resize code I found that SDL just
|
||||
wasn't cutting it and had to code for the GU myself. Turns out
|
||||
the new code is faster (but because it is render code any
|
||||
improvement will be diminished to nothing as frameskip is
|
||||
increased). Special thanks to Zx-81 for the tips on this one
|
||||
and for his GU code in the PSPVBA source as an example.
|
||||
@ Added some games to game_config.txt. Note that not all versions
|
||||
of these ROMs will work with these options, try to use the USA
|
||||
version if possible.
|
||||
|
||||
8-19-2006 v0.5 - Initial release (public beta quality)
|
||||
|
||||
|
||||
-- About --
|
||||
|
||||
gameplaySP (gpSP for short) is a GBA emulator written completely from
|
||||
scratch. It is still pretty young (only having started a 3 months prior
|
||||
to the first release) and thus rather immature, but it does a decent
|
||||
job of playing a number of games, and is being improved upon somewhat
|
||||
regularly. It is currently somewhat minimalistic, in the sourcecode,
|
||||
presentation, and features. Its number one focus is to deliver a GBA
|
||||
gaming experience in the most playable way that PSP can manage, with
|
||||
frills being secondary (although still a consideration, at least for
|
||||
some of them).
|
||||
|
||||
Having said that, optimization was the important way in achieving this
|
||||
goal, with overall compatability being a near second. Because of this
|
||||
some games may not run at the favor of running more games significantly
|
||||
better. Of course, the compatability will improve with time. The
|
||||
compatability in the current version (0.8) is perhaps around 80%
|
||||
(assuming the correct BIOS image is used).
|
||||
|
||||
Many games will run at their best out of the box, but some games will
|
||||
run very slowly unless idle loops are taken care of. There is a supplied
|
||||
ROM database, game_config.txt, that gives idle loop targets and other
|
||||
settings that may help a game to run better (or at all) on a per-game
|
||||
basis. Currently (as of version 0.8) a few dozen games are on this list,
|
||||
mostly only USA versions. This list will continue to be updated; there's
|
||||
no real telling exactly how many of the ~2500 GBA games will need to
|
||||
appear here.
|
||||
|
||||
gpSP currently requires an authentic GBA BIOS image file to run. It will
|
||||
make no effort to run without one present; this file is 16kb and should
|
||||
be called gba_bios.bin and present in the same location as the EBOOT.PBP
|
||||
file. Please do not ask me where to obtain this, you'll have to look
|
||||
online or grab it from a GBA. Note that it is not legal to have this file
|
||||
unless you own a GBA, and even then it's rather gray area.
|
||||
|
||||
|
||||
|
||||
-- Features --
|
||||
|
||||
gpSP mostly emulates the core Gameboy Advance system. As of right now it
|
||||
does not emulate any special hardware present on various GBA cartridges.
|
||||
|
||||
|
||||
What it emulates:
|
||||
|
||||
GBA CPU: All ARM7TDMI ARM and Thumb mode opcodes except block memory w/
|
||||
s-bit (probably aren't used in GBA games)
|
||||
Video: Modes 0, 1, 2 almost completely, basic 3-5 support, sprites,
|
||||
windows/OBJ windows
|
||||
Interrupts: HBlank, VBlank, all timers, all DMA channels, keypad
|
||||
DMA: Immediate, HBlank, VBlank, sound timer triggered
|
||||
Sound: Both DirectSound channels and all 4 GBC audio channels
|
||||
Input: Basic GBA input delivered through PSP controls
|
||||
Cartridges: Currently supports ROMs up to 32MB in size (the maximum for
|
||||
GBA) with the technique of ROM page swapping to fit within PSP's RAM.
|
||||
Backup: 32/64kb SRAM, 64/128kb flash, 512bit/8kb EEPROM
|
||||
RTC: The real-time clock present in cartridges such as most of the
|
||||
Pokemon games and some others.
|
||||
|
||||
|
||||
What it lacks:
|
||||
|
||||
Video: No mosaic, bitmap modes lack color effects (alpha, fades),
|
||||
there might be some minor inaccuracies in blending...
|
||||
Cycle accuracy: Very cycle innacurate; CPU is effectively somewhat
|
||||
overclocked, meaning games with rampant idle loops will probably run
|
||||
rather poorly. DMA transfers effectively happen for free (0 cycle).
|
||||
Please do NOT use gpSP as a first source for developing GBA homebrew,
|
||||
try No$GBA instead.
|
||||
|
||||
|
||||
Additional features it has:
|
||||
- The ability to attempt to run games at faster than GBA speed (sometimes
|
||||
they can end up a lot faster, other times not so much)
|
||||
- Savestates: the ability to save a game's state to a file and resume
|
||||
playing where you left off later.
|
||||
- Mild cheat support
|
||||
|
||||
|
||||
Features that it doesn't have (please don't ask me to implement these!)
|
||||
- Wi-fi multiplayer
|
||||
|
||||
|
||||
-- Controls --
|
||||
|
||||
The default control scheme is very simple. If you don't like it you can
|
||||
change it in the configuration menu.
|
||||
|
||||
At the ROM selection screen:
|
||||
|
||||
Up/down: navigate current selection window.
|
||||
Left/right: switch between file window and directory window.
|
||||
Circle/start: select current entry.
|
||||
Square: go one directory up.
|
||||
|
||||
In game:
|
||||
|
||||
Up/down/left/right: GBA d-pad
|
||||
Circle: GBA A button
|
||||
Cross: GBA B button
|
||||
Square/start: GBA start button
|
||||
Select: GBA select button
|
||||
Left trigger: GBA left trigger
|
||||
Right trigger: GBA right trigger
|
||||
Triangle: Adjust frameksip
|
||||
|
||||
In frameskip adjustment:
|
||||
|
||||
Hold down triangle to keep up, press up/down to increase/decrease
|
||||
frameskip, respectively. Press down at 0 to change to auto, and up
|
||||
at auto to change to 0.
|
||||
|
||||
In the menu:
|
||||
|
||||
Up/down: navigate current menu.
|
||||
Left/right: change value in current menu selection (if a value is present)
|
||||
Circle/start: select current entry (see help for entry to see what this means)
|
||||
Square: exit the current menu.
|
||||
|
||||
|
||||
-- Frameskip --
|
||||
|
||||
The purpose behind frameskip is to cause the emulator to not render every
|
||||
frame of graphics to make the emulation closer to fullspeed. Many games will
|
||||
run fullspeed without skipping any frames, however, some (particularly more
|
||||
graphically demanding ones) will require this.
|
||||
|
||||
Frameskip can be set to two forms, either auto or manual. Auto will attempt
|
||||
to skip only as many frames as necessary to make the game full speed, and
|
||||
will not skip more than 4 in a row no matter what speed the game runs at
|
||||
(at this point the benefits of frameskip yield diminishing returns).
|
||||
|
||||
It is recommended that you keep frameskip on auto, but manual is maintained
|
||||
as an option if you want it and works as follows:
|
||||
|
||||
Manual frameskip will only render one out of every (n + 1) frames, where n
|
||||
is the current frameskip value (so 0 will render everything). Increasing
|
||||
the frameskip can improve speed, especially with very graphically
|
||||
intensive games.
|
||||
|
||||
|
||||
-- Cheats --
|
||||
|
||||
Currently, gpSP supports some functionality of Gameshark/Pro Action Replay
|
||||
cheat codes. To use these, you must first make a file with the same name
|
||||
as the ROM you want the cheat code to apply to, but with the extension .cht.
|
||||
Put this file in the same directory as the ROM. To make it use a normal
|
||||
text editor like notepad or wordpad if you're on Windows.
|
||||
|
||||
To write a code, write the type of model it is, gameshark_v1, gameshark_v3,
|
||||
PAR_v1, or PAR_v3. gameshark_v1/PAR_v1 and gameshark_v3/PAR_v3 respectively
|
||||
are interchangeable, but v1 and v3 are not! So if you don't know which
|
||||
version it is, try both to see if it'll work.
|
||||
|
||||
Then, after that, put a space and put the name you'd like to give the cheat.
|
||||
|
||||
On the next several lines, put each cheat code pair, which should look like
|
||||
this:
|
||||
|
||||
AAAAAAAA BBBBBBBB
|
||||
|
||||
Then put a blank line when you're done with that code, and start a new code
|
||||
immediately after it. Here's an example of what a cheat file should look
|
||||
like:
|
||||
|
||||
|
||||
gameshark_v3 MarioInfHP
|
||||
995fa0d9 0c6720d2
|
||||
|
||||
gameshark_v3 MarioMaxHP
|
||||
21d58888 c5d0e432
|
||||
|
||||
gameshark_v3 InfHlthBat
|
||||
6f4feadb 0581b00e
|
||||
79af5dc6 5ce0d2b1
|
||||
dbbd5995 44b801c9
|
||||
65f8924d 2fbcd3c4
|
||||
|
||||
gameshark_v3 StopTimer
|
||||
2b399ca4 ec81f071
|
||||
|
||||
|
||||
After you have written the .cht file, you have to enable the cheats
|
||||
individually in the game menu. Go to the Cheats/Misc menu, and you will
|
||||
see the cheats; turn them on here. You may turn them on and off as you
|
||||
please, but note that some cheats may still hold after you turn them off,
|
||||
due to the nature of the system. Restart to completely get rid of them.
|
||||
|
||||
IMPORTANT NOTES:
|
||||
|
||||
This is still very work in progress! I basically added this in only 1.5
|
||||
or so hours, and I don't have a lot of time right now to work on it
|
||||
before releasing. So I'll probably improve it later.
|
||||
|
||||
Not all of gameshark's features are supported, especially for v3. Only
|
||||
basic cheats will work, more or less.
|
||||
|
||||
Cheats may be unstable and may crash your game. If you're having problems
|
||||
turn the cheats off.
|
||||
|
||||
Really, there's no guarantee that ANY cheats will work; I tried a few and
|
||||
some seem to work, others are questionable. Try for yourself, but don't
|
||||
expect anything to actually work right now. Do expect this feature to
|
||||
improve in future versions.
|
||||
|
||||
|
||||
|
||||
-- Frequently Asked Questions --
|
||||
|
||||
Q) How do I run this on my PSP?
|
||||
|
||||
A) Provided is an EBOOT.PBP which will run as is on a 1.0 firmware
|
||||
PSP or custom firmware that can run unsigned EBOOTs. On 1.5 firmwares
|
||||
you must use a kxploit tool to run it (try SeiPSPtool). On 2.0
|
||||
firmwares and higher further exploits must be used - see
|
||||
http://pspupdates.qj.net/ for more information. Note that I have NOT
|
||||
tested this emulator on any firmware version besides 1.5, and it's
|
||||
very possible that it doesn't run well, or at all on higher versions.
|
||||
Therefore I strongly recommend you downgrade if possible, and use
|
||||
Devhook to run games that require > 1.5 version firmwares.
|
||||
|
||||
Be sure to include in the same directory as the EBOOT.PBP file the
|
||||
game_config.txt file included and the gba_bios.bin file which you
|
||||
must provide yourself.
|
||||
|
||||
gpSP does not run on PSPs with version 2.71 or higher firmware yet,
|
||||
nor does any other homebrew executable.
|
||||
|
||||
|
||||
Q) What is a BIOS image file? Why do I need it to run gpSP? Other GBA
|
||||
emulators don't require this...
|
||||
|
||||
A) The GBA BIOS image file is a copy of a ROM on the GBA system that
|
||||
has code for starting up the GBA (it shows the logo), verifying the
|
||||
game, and most importantly, providing utility functions for the games
|
||||
to use. It is the latter that gpSP needs the BIOS present for. It's
|
||||
possible to replace all of these functions with equivilent code, but
|
||||
this will take time - in the future gpSP may not require a BIOS image.
|
||||
|
||||
|
||||
Q) I can't find this BIOS image.. please send it to me.
|
||||
|
||||
A) Sorry, but you're on your own. I won't send you a BIOS or tell you
|
||||
where to get one (unless you want to rip it from a GBA yourself, in
|
||||
which case I'll just give you the same link at the top). I can't do
|
||||
this because it's not legal to send it around and I don't want to
|
||||
get a reputation for illegally distributing BIOS images.
|
||||
|
||||
|
||||
Q) How do I know I have the right BIOS?
|
||||
|
||||
A) If you have md5sum you can check if it has this hash:
|
||||
a860e8c0b6d573d191e4ec7db1b1e4f6
|
||||
That BIOS should work fine. I think that some others work fine too,
|
||||
although I haven't confirmed this with absolute certainty. It's also
|
||||
theoretically possible to use custom (and free) BIOS replacements,
|
||||
but I don't know of any publically availablone ones.
|
||||
|
||||
As far as I'm aware there are two BIOSes floating around, I doubt
|
||||
you'll get one that isn't one of those two. There's a very easy way
|
||||
to determine which one you have - just look at the very first byte in
|
||||
a hex editor. The correct BIOS begins with 0x18, the buggy BIOS begins
|
||||
with 0x14.
|
||||
|
||||
|
||||
Q) My favorite game won't run.
|
||||
|
||||
A) There probably isn't anything you can do about this, although a
|
||||
change to game_config.txt might help. gpSP is still an emulator in
|
||||
its infancy so the compatability is not superb. I don't have time
|
||||
to test too many games so I'm releasing it as a public beta to get
|
||||
a feel for some things that don't work. The next version could
|
||||
perhaps fix it, or it might never run. There are always other
|
||||
emulators of course, please try one.
|
||||
|
||||
However, before nagging me there is one thing I recommend you try,
|
||||
and that is to add the option "iwram_stack_optimize = no" for the
|
||||
game in game_config.txt. See the file itself for more information
|
||||
on how to do this. If this fixes your game (and it's not already
|
||||
in the game_config.txt) please tell me about it.
|
||||
|
||||
|
||||
Q) My favorite game is very slow.
|
||||
|
||||
A) Emulating GBA takes a number of resources and getting it done well
|
||||
on PSP is no simple task by any means. Some games are just going to
|
||||
overwhelm the emulator completely. Of course, there is one special
|
||||
case of game (a lot of early generation games fall under this
|
||||
category) that can be made much faster by a simple addition to the
|
||||
game_config.txt file. Wait for a new version of this file or the
|
||||
next version of the emulator and the game may be improved.
|
||||
|
||||
That aside, there are still numerous optimizations that can be done,
|
||||
and I sure you future versions will be faster (I just can't tell you
|
||||
how much)
|
||||
|
||||
Also, a lot of games will be sped up considerably by adding an
|
||||
idle_loop_eliminate_target line for it in game_config.txt. There
|
||||
are some more obscurer options there that can improve speed too. If
|
||||
the game is VERY slow there might be something wrong with its
|
||||
emulation that can be improved. For instance, if you can't get a game
|
||||
to run fullspeed on any frameskip you should e-mail me about it.
|
||||
|
||||
|
||||
Q) Some games run fullspeed but the sound is messed up. Why?
|
||||
|
||||
A) At least 9 out of 10 times it means the game isn't really running
|
||||
full speed, but just that you can't notice the difference. Increasing
|
||||
frameskip will almost always improve sound quality in these
|
||||
situations, to a certain point (after around frameskip 3 you
|
||||
probably won't be seeing many more returns if it isn't already
|
||||
fullspeed). The rest of the time it means there's a bug somewhere else
|
||||
in the emulator, probably in the CPU core. Chances are that all you
|
||||
can do is wait for it to be fixed in a later release.
|
||||
|
||||
|
||||
Q) The emulator crashed!
|
||||
|
||||
A) Most games that don't run will probably take the emulator down with
|
||||
it, or it could be an emulator bug completely unrelated to the game
|
||||
(but unlikely). Press home and wait for the next version.
|
||||
|
||||
There is some information that comes up when the game crashes. This
|
||||
information may be slightly useful to me, but chances are it
|
||||
usually won't be all that interesting.
|
||||
|
||||
These days games are more likely to exit with a "bad crash" error.
|
||||
This number is possibly useful to me, but to debug a game I'll have
|
||||
to reproduce the crash anyway. When this happens it's probably due to
|
||||
a bug in the CPU core that hasn't been fixed yet.
|
||||
|
||||
|
||||
Q) Why won't my game save?
|
||||
|
||||
A) The game might need 128KB flash turned on and might not be listed in
|
||||
game_config.txt. See game_config.txt for more information regarding
|
||||
this. Be sure to include game_config.txt with the EBOOT.PBP file.
|
||||
|
||||
Other games might simply have bugs in the save support. For now, use
|
||||
savestates as an alternative if you can't save.
|
||||
|
||||
|
||||
Q) How do I change sound quality?
|
||||
|
||||
A) Right now, you can't. For those wondering, sound is locked at 44.1KHz
|
||||
(sounds a bit high? It is, but it's currently necessary to play
|
||||
everything correctly). I don't have any plans to allow changing this
|
||||
right now, because I don't think there's really much reason to be
|
||||
able to (it'd be a tiny speed boost at best and I don't think SDL even
|
||||
allows for anything besides this sampling rate on PSP)
|
||||
|
||||
|
||||
Q) What is this emulator's name?
|
||||
|
||||
A) Um.. what? It's gameplaySP, isn't it? You call it gpSP for short.
|
||||
Somehow the name can't have the acronyms gbSP, gbapSP, or really
|
||||
just about anything else you feel like giving it. Oh, and if you
|
||||
really want to make me happy get the capitalization right too.
|
||||
That's gpSP, not gPSP, GPsp.. you get the idea.
|
||||
|
||||
|
||||
Q) Does gpSP run Gameboy/Gameboy Color games? Will it later?
|
||||
|
||||
A) No. Even though GBA can run these games it uses separate hardware
|
||||
that proper GBA games have no access to (save for the audio chip),
|
||||
and thus there's no point including it in a GBA emulator (it
|
||||
doesn't help run GBA games). I recommend using a GB/GBC emulator
|
||||
like Rin for playing these games. It'll probably give you a lot
|
||||
more options anyway. gpSP will never actually emulate GB/GBC
|
||||
games. You'd may as well be waiting for it to emulate PS2 games...
|
||||
(that was an analogy. gpSP won't ever emulate PS2 games. >_>)
|
||||
|
||||
|
||||
Q) Other emulators use the PSP's graphical hardware to accelerate the
|
||||
video emulation. Is this possible for gpSP?
|
||||
|
||||
A) I'm honestly not too sure at this point. It's definitely a rather
|
||||
complicated procedure, and I don't think it'll be possible to
|
||||
accurately accelerate alpha blending. On the other hand, affine
|
||||
transformations could perhaps receive a speed boost this way. Any
|
||||
solution would have to be hybrid hardware/software, which might be
|
||||
possible due to the nature of the PSP's VRAM. Maybe someone will
|
||||
be willing to help me think of possibilities here?
|
||||
|
||||
But don't bother of you're just going to tell me to render a list
|
||||
of quads...
|
||||
|
||||
|
||||
Q) Other emulators use the PSP's second CPU to offload the sound
|
||||
emulation. Is this possible for gpSP?
|
||||
|
||||
A) Yes, but it wouldn't improve it nearly as much as say, SNES9x TYL.
|
||||
This is because most of the processing that goes into sound on a GBA
|
||||
game is done in the CPU, not in dedicated audio hardware. It could
|
||||
help a little, but probably not a lot. Maybe enough to be worthwhile.
|
||||
It might also be possible to split the video rendering to the main
|
||||
CPU and the main emulation to the secondary one, but there are a lot
|
||||
of coherency issues involved.
|
||||
|
||||
|
||||
Q) I heard gpSP can only load games 16MB or smaller in size. Is this
|
||||
true? What about zipped games?
|
||||
|
||||
A) As of version 0.8 gpSP can play 32MB ROMs. However, they must be
|
||||
unzipped. The reason for this is that parts of the ROM are constantly
|
||||
loaded to memory as needed, and for this to be as fast as possible the
|
||||
ROM has to be present on the memory stick in raw format.
|
||||
|
||||
You might be wondering, why not just have gpSP unzip the ROM to a file
|
||||
then delete the file when it is done? The reason why is because this
|
||||
would impose a "hidden" requirement of 32MB on the user that very
|
||||
likely may not be there. Furthermore, there are only a few 32MB games
|
||||
that anyone actually wants to play. If you only have one 32MB game on
|
||||
your memstick then it'd actually require signifnicantly more free space
|
||||
to hold both the ROM and the 32MB raw file. With 2 32MB ROMs you only
|
||||
gain a around 10-25MB of free space, depending on how effective the
|
||||
compression is.
|
||||
|
||||
|
||||
Q) Savestates? From other emulators??
|
||||
|
||||
A) See the savestates option in main menu. gpSP will probably never
|
||||
support savestates from other emulators, there's just too much in the
|
||||
way of emulator specific data in them.
|
||||
|
||||
Savestates are currently 506,943 bytes. They would be a little smaller
|
||||
without the snapshot, but I find that very useful and it wouldn't help
|
||||
size immensely. Compression would help, but I wanted the size to be
|
||||
constant so you knew exactly how much you could hold and to improve
|
||||
save/load speed.
|
||||
|
||||
|
||||
Q) What's with the zip support?
|
||||
|
||||
A) I hear stories that some games work unzipped and not zipped, so you
|
||||
might want to try unzipping them if it gives you problems. You also
|
||||
might want to try making fresh zips with WinRAR - users have
|
||||
reported some higher success rates doing this.
|
||||
|
||||
|
||||
Q) What's with the config file? Should I make it read only?
|
||||
|
||||
A) There was a bug in version 0.6 that caused the config file to not
|
||||
get updated or get corrupted sometimes. Hopefully this is fixed now,
|
||||
but if it DOES get corrupted making it read only can prevent this
|
||||
from happening in the future.
|
||||
|
||||
|
||||
Q) So when WILL the next version be released?
|
||||
|
||||
A) Sorry, but I almost never announce release dates. Furthermore, I'll
|
||||
probably be pretty hush hush on internal development, just to keep
|
||||
people from nagging me about it and building too much suspense.
|
||||
|
||||
|
||||
Q) I don't like this emulator. Are there other alternatives?
|
||||
|
||||
A) Yes. Try PSPVBA by Zx-81 (http://zx81.dcemu.co.uk/). Overall I doubt
|
||||
the compatability is significantly higher than gpSP's anymore, but
|
||||
I'm sure there are some games it runs that gpSP doesn't.
|
||||
|
||||
|
||||
Q) I heard there was a version of gpSP for PCs. Is that true?
|
||||
|
||||
A) I developed this emulator internally on PC. It might have a speed
|
||||
advantage over other PC GBA emulators, although the PSP version has
|
||||
more sophisticated optimizations. Most people have fast enough
|
||||
computers to run better GBA emulators for PC and gpSP lacks some
|
||||
important features (screen resizing) that the PSP version kinda
|
||||
hides. Even though gpSP spent a majority of its development
|
||||
gestation as a PC app it was always developed with the PSP in mind,
|
||||
so the PC version will probably not see the light of the day unless
|
||||
I get overwhelming demand for it. It is, however, possible to
|
||||
build it from the source. But I request that you don't distribute
|
||||
such builds. If you happen to find one, bear in mind that I don't
|
||||
offer any support for it, and as far as I'm concerned it won't
|
||||
exist.
|
||||
|
||||
|
||||
Q) I hear there's a version of gpSP for other platforms too, like
|
||||
Dreamcast. And I hear they're slow! What gives?
|
||||
|
||||
These are ports, done by other people (or maybe myself?). This is
|
||||
possible because gpSP is open source and its base version is fairly
|
||||
portable, but to run fast enough on anything but platforms quite a
|
||||
bit faster than PSP it at least needs a CPU specific dynarec backend.
|
||||
|
||||
I don't (necessarily) maintain all builds of gpSP, so you'll have to
|
||||
contact the authors of these ports for more information. That
|
||||
notwithstanding, I try to get as involved in other ports of gpSP as
|
||||
I can.
|
||||
|
||||
|
||||
Q) I want to modify gpSP. How can I do this, and am I at liberty to do
|
||||
so?
|
||||
|
||||
A) Yes, you are, under the terms of the GPL (see the included
|
||||
COPYING.DOC). You can download the sourcecode from whereever you
|
||||
downloaded this; if you can't find it please e-mail me and I'll give
|
||||
you a link to it. I would vastly appreciate it if you contacted me first
|
||||
before forking my project, especially if you're just looking to gain
|
||||
recognition without adding much to it. It's better to keep all changes
|
||||
tidy in one branch of development.
|
||||
|
||||
I would like to stress this a little more seriously (hopefully those
|
||||
interested are reading this). Although you are legally entitled to
|
||||
release your own forks of gpSP it would be much more benficial to me,
|
||||
to you, and to the users of this program if you instead tried working
|
||||
with me to get your changes incorporated into the next version. I
|
||||
really don't feel like competing with other builds of my source
|
||||
anymore, so please do me a big favor and send me an e-mail if you want
|
||||
to work with gpSP.
|
||||
|
||||
|
||||
Q) How do I build gpSP?
|
||||
|
||||
A) make will build it. You need to have SDL for PSP installed, as well
|
||||
as the standard PSP toolchain/PSPSDK and zlib. gpSP isn't much of a
|
||||
"build it yourself" program so please don't bother me much about how to
|
||||
build it unless you have a good reason for wanting to do so.
|
||||
|
||||
|
||||
Q) What is with the version numbers?
|
||||
|
||||
A) Anything less than 1.0 means beta. Beta means that I still have major
|
||||
plans for working on it, and that I don't fully back it as being
|
||||
stable or reliable software. Of course, if it does hit 1.0, that doesn't
|
||||
mean it'll be perfect. It just means I'll have spent a lot of cumulative
|
||||
time working things out. The closer it gets to 0.9, the happier I am with
|
||||
it overall.
|
||||
|
||||
|
||||
Q) Donations?
|
||||
|
||||
A) Very appreciated. exophase@gmail.com on PayPal. <3
|
||||
|
||||
|
||||
Q) How can I contact you?
|
||||
|
||||
A) exophase@gmail.com, Exophase on AIM, exophase@adelphia.net on MSN. I
|
||||
welcome IMs, but if you nag me a lot you'll make me sad inside. And
|
||||
don't ask me for ROMs or the GBA BIOS. I figured this was common sense
|
||||
but apparently not.
|
||||
|
||||
|
||||
-- Credits --
|
||||
|
||||
Exophase: main developer
|
||||
siberianSTAR: zip support
|
||||
psp298: analog nub code
|
||||
|
||||
Beta testers for 0.7:
|
||||
theohsoawesome1
|
||||
thisnamesucks837
|
||||
blackdragonwave9
|
||||
dagreatpeewee
|
||||
xsgenji
|
||||
|
||||
Beta testers for 0.8:
|
||||
Runaway_prisoner
|
||||
theohsoawesome1
|
||||
tanyareimyoko
|
||||
spynghotoh2020
|
||||
|
||||
Beta testers for 0.9:
|
||||
RunawayPrisoner (my right hand man)
|
||||
Veskgar (my left hand man)
|
||||
qasim
|
||||
|
||||
-- Special thanks --
|
||||
|
||||
Quasar84: He's helped me in so many ways with this. We both kinda learned
|
||||
GBA together, he did little demos for me and I got them emulated. It was
|
||||
great trying out your more advanced code for your own projects once you
|
||||
got to them, it was equally rewarding to see your work and to be able to
|
||||
run it at the same time. Least of all I wouldn't have been able to do any
|
||||
of this without your constant support and presence. I really owe this
|
||||
release to you.
|
||||
|
||||
gladius: You are an amazing GBA coder. I wouldn't have been able to get
|
||||
through some tough parts without your help. Its been good talking about
|
||||
ideas with you.. I'm sure you're glad to see that there's finally a GBA
|
||||
emulator with dynarec ;)
|
||||
|
||||
|
||||
Many, many others of course, probably too many to name, and I don't want
|
||||
to make anyone feel bad by putting others above them (well, except those
|
||||
two, heh) so if you think you should be on here, you probably should be!
|
||||
Just pretend you are for now, and maybe I'll put you here next time.
|
||||
|
812
sound.c
Normal file
812
sound.c
Normal file
@ -0,0 +1,812 @@
|
||||
/* gameplaySP
|
||||
*
|
||||
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "common.h"
|
||||
#include <SDL.h>
|
||||
u32 global_enable_audio = 1;
|
||||
|
||||
direct_sound_struct direct_sound_channel[2];
|
||||
gbc_sound_struct gbc_sound_channel[4];
|
||||
|
||||
#if defined(GP2X_BUILD) || defined(TAVI_BUILD)
|
||||
u32 sound_frequency = 44100;
|
||||
#else
|
||||
u32 sound_frequency = 44100;
|
||||
#endif
|
||||
|
||||
SDL_AudioSpec sound_settings;
|
||||
SDL_mutex *sound_mutex;
|
||||
SDL_cond *sound_cv;
|
||||
|
||||
#ifndef PSP_BUILD
|
||||
u32 audio_buffer_size_number = 7;
|
||||
#else
|
||||
u32 audio_buffer_size_number = 1;
|
||||
#endif
|
||||
|
||||
u32 audio_buffer_size;
|
||||
u32 sound_on = 0;
|
||||
s16 sound_buffer[BUFFER_SIZE];
|
||||
u32 sound_buffer_base = 0;
|
||||
|
||||
u32 sound_last_cpu_ticks = 0;
|
||||
fixed16_16 gbc_sound_tick_step;
|
||||
|
||||
// Queue 1, 2, or 4 samples to the top of the DS FIFO, wrap around circularly
|
||||
|
||||
#define sound_timer_queue(size, value) \
|
||||
*((s##size *)(ds->fifo + ds->fifo_top)) = value; \
|
||||
ds->fifo_top = (ds->fifo_top + 1) % 32; \
|
||||
|
||||
void sound_timer_queue8(u32 channel, u8 value)
|
||||
{
|
||||
direct_sound_struct *ds = direct_sound_channel + channel;
|
||||
sound_timer_queue(8, value);
|
||||
}
|
||||
|
||||
void sound_timer_queue16(u32 channel, u16 value)
|
||||
{
|
||||
direct_sound_struct *ds = direct_sound_channel + channel;
|
||||
sound_timer_queue(8, value & 0xFF);
|
||||
sound_timer_queue(8, value >> 8);
|
||||
}
|
||||
|
||||
void sound_timer_queue32(u32 channel, u32 value)
|
||||
{
|
||||
direct_sound_struct *ds = direct_sound_channel + channel;
|
||||
|
||||
sound_timer_queue(8, value & 0xFF);
|
||||
sound_timer_queue(8, (value >> 8) & 0xFF);
|
||||
sound_timer_queue(8, (value >> 16) & 0xFF);
|
||||
sound_timer_queue(8, value >> 24);
|
||||
}
|
||||
|
||||
// Unqueue 1 sample from the base of the DS FIFO and place it on the audio
|
||||
// buffer for as many samples as necessary. If the DS FIFO is 16 bytes or
|
||||
// smaller and if DMA is enabled for the sound channel initiate a DMA transfer
|
||||
// to the DS FIFO.
|
||||
|
||||
#define render_sample_null() \
|
||||
|
||||
#define render_sample_left() \
|
||||
sound_buffer[buffer_index] += current_sample + \
|
||||
fp16_16_to_u32((next_sample - current_sample) * fifo_fractional) \
|
||||
|
||||
#define render_sample_right() \
|
||||
sound_buffer[buffer_index + 1] += current_sample + \
|
||||
fp16_16_to_u32((next_sample - current_sample) * fifo_fractional) \
|
||||
|
||||
#define render_sample_both() \
|
||||
dest_sample = current_sample + \
|
||||
fp16_16_to_u32((next_sample - current_sample) * fifo_fractional); \
|
||||
sound_buffer[buffer_index] += dest_sample; \
|
||||
sound_buffer[buffer_index + 1] += dest_sample \
|
||||
|
||||
#define render_samples(type) \
|
||||
while(fifo_fractional <= 0xFFFF) \
|
||||
{ \
|
||||
render_sample_##type(); \
|
||||
fifo_fractional += frequency_step; \
|
||||
buffer_index = (buffer_index + 2) % BUFFER_SIZE; \
|
||||
} \
|
||||
|
||||
void sound_timer(fixed16_16 frequency_step, u32 channel)
|
||||
{
|
||||
direct_sound_struct *ds = direct_sound_channel + channel;
|
||||
|
||||
fixed16_16 fifo_fractional = ds->fifo_fractional;
|
||||
u32 buffer_index = ds->buffer_index;
|
||||
s16 current_sample, next_sample, dest_sample;
|
||||
|
||||
current_sample = ds->fifo[ds->fifo_base] << 4;
|
||||
ds->fifo_base = (ds->fifo_base + 1) % 32;
|
||||
next_sample = ds->fifo[ds->fifo_base] << 4;
|
||||
|
||||
if(sound_on == 1)
|
||||
{
|
||||
if(ds->volume == DIRECT_SOUND_VOLUME_50)
|
||||
{
|
||||
current_sample >>= 1;
|
||||
next_sample >>= 1;
|
||||
}
|
||||
|
||||
switch(ds->status)
|
||||
{
|
||||
case DIRECT_SOUND_INACTIVE:
|
||||
render_samples(null);
|
||||
break;
|
||||
|
||||
case DIRECT_SOUND_RIGHT:
|
||||
render_samples(right);
|
||||
break;
|
||||
|
||||
case DIRECT_SOUND_LEFT:
|
||||
render_samples(left);
|
||||
break;
|
||||
|
||||
case DIRECT_SOUND_LEFTRIGHT:
|
||||
render_samples(both);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
render_samples(null);
|
||||
}
|
||||
|
||||
ds->buffer_index = buffer_index;
|
||||
ds->fifo_fractional = fp16_16_fractional_part(fifo_fractional);
|
||||
|
||||
if(((ds->fifo_top - ds->fifo_base) % 32) <= 16)
|
||||
{
|
||||
if(dma[1].direct_sound_channel == channel)
|
||||
dma_transfer(dma + 1);
|
||||
|
||||
if(dma[2].direct_sound_channel == channel)
|
||||
dma_transfer(dma + 2);
|
||||
}
|
||||
}
|
||||
|
||||
void sound_reset_fifo(u32 channel)
|
||||
{
|
||||
direct_sound_struct *ds = direct_sound_channel;
|
||||
|
||||
memset(ds->fifo, 0, 32);
|
||||
}
|
||||
|
||||
// Initial pattern data = 4bits (signed)
|
||||
// Channel volume = 12bits
|
||||
// Envelope volume = 14bits
|
||||
// Master volume = 2bits
|
||||
|
||||
// Recalculate left and right volume as volume changes.
|
||||
// To calculate the current sample, use (sample * volume) >> 16
|
||||
|
||||
// Square waves range from -8 (low) to 7 (high)
|
||||
|
||||
s8 square_pattern_duty[4][8] =
|
||||
{
|
||||
{ 0xF8, 0xF8, 0xF8, 0xF8, 0x07, 0xF8, 0xF8, 0xF8 },
|
||||
{ 0xF8, 0xF8, 0xF8, 0xF8, 0x07, 0x07, 0xF8, 0xF8 },
|
||||
{ 0xF8, 0xF8, 0x07, 0x07, 0x07, 0x07, 0xF8, 0xF8 },
|
||||
{ 0x07, 0x07, 0x07, 0x07, 0xF8, 0xF8, 0x07, 0x07 },
|
||||
};
|
||||
|
||||
s8 wave_samples[64];
|
||||
|
||||
u32 noise_table15[1024];
|
||||
u32 noise_table7[4];
|
||||
|
||||
u32 gbc_sound_master_volume_table[4] = { 1, 2, 4, 0 };
|
||||
|
||||
u32 gbc_sound_channel_volume_table[8] =
|
||||
{
|
||||
fixed_div(0, 7, 12),
|
||||
fixed_div(1, 7, 12),
|
||||
fixed_div(2, 7, 12),
|
||||
fixed_div(3, 7, 12),
|
||||
fixed_div(4, 7, 12),
|
||||
fixed_div(5, 7, 12),
|
||||
fixed_div(6, 7, 12),
|
||||
fixed_div(7, 7, 12)
|
||||
};
|
||||
|
||||
u32 gbc_sound_envelope_volume_table[16] =
|
||||
{
|
||||
fixed_div(0, 15, 14),
|
||||
fixed_div(1, 15, 14),
|
||||
fixed_div(2, 15, 14),
|
||||
fixed_div(3, 15, 14),
|
||||
fixed_div(4, 15, 14),
|
||||
fixed_div(5, 15, 14),
|
||||
fixed_div(6, 15, 14),
|
||||
fixed_div(7, 15, 14),
|
||||
fixed_div(8, 15, 14),
|
||||
fixed_div(9, 15, 14),
|
||||
fixed_div(10, 15, 14),
|
||||
fixed_div(11, 15, 14),
|
||||
fixed_div(12, 15, 14),
|
||||
fixed_div(13, 15, 14),
|
||||
fixed_div(14, 15, 14),
|
||||
fixed_div(15, 15, 14)
|
||||
};
|
||||
|
||||
u32 gbc_sound_buffer_index = 0;
|
||||
u32 gbc_sound_last_cpu_ticks = 0;
|
||||
u32 gbc_sound_partial_ticks = 0;
|
||||
|
||||
u32 gbc_sound_master_volume_left;
|
||||
u32 gbc_sound_master_volume_right;
|
||||
u32 gbc_sound_master_volume;
|
||||
|
||||
#define update_volume_channel_envelope(channel) \
|
||||
volume_##channel = gbc_sound_envelope_volume_table[envelope_volume] * \
|
||||
gbc_sound_channel_volume_table[gbc_sound_master_volume_##channel] * \
|
||||
gbc_sound_master_volume_table[gbc_sound_master_volume] \
|
||||
|
||||
#define update_volume_channel_noenvelope(channel) \
|
||||
volume_##channel = gs->wave_volume * \
|
||||
gbc_sound_channel_volume_table[gbc_sound_master_volume_##channel] * \
|
||||
gbc_sound_master_volume_table[gbc_sound_master_volume] \
|
||||
|
||||
#define update_volume(type) \
|
||||
update_volume_channel_##type(left); \
|
||||
update_volume_channel_##type(right) \
|
||||
|
||||
#define update_tone_sweep() \
|
||||
if(gs->sweep_status) \
|
||||
{ \
|
||||
u32 sweep_ticks = gs->sweep_ticks - 1; \
|
||||
\
|
||||
if(sweep_ticks == 0) \
|
||||
{ \
|
||||
u32 rate = gs->rate; \
|
||||
\
|
||||
if(gs->sweep_direction) \
|
||||
rate = rate - (rate >> gs->sweep_shift); \
|
||||
else \
|
||||
rate = rate + (rate >> gs->sweep_shift); \
|
||||
\
|
||||
if(rate > 2048) \
|
||||
rate = 2048; \
|
||||
\
|
||||
frequency_step = float_to_fp16_16(((131072.0 / (2048 - rate)) * 8.0) / \
|
||||
sound_frequency); \
|
||||
\
|
||||
gs->frequency_step = frequency_step; \
|
||||
gs->rate = rate; \
|
||||
\
|
||||
sweep_ticks = gs->sweep_initial_ticks; \
|
||||
} \
|
||||
gs->sweep_ticks = sweep_ticks; \
|
||||
} \
|
||||
|
||||
#define update_tone_nosweep() \
|
||||
|
||||
#define update_tone_envelope() \
|
||||
if(gs->envelope_status) \
|
||||
{ \
|
||||
u32 envelope_ticks = gs->envelope_ticks - 1; \
|
||||
envelope_volume = gs->envelope_volume; \
|
||||
\
|
||||
if(envelope_ticks == 0) \
|
||||
{ \
|
||||
if(gs->envelope_direction) \
|
||||
{ \
|
||||
if(envelope_volume != 15) \
|
||||
envelope_volume = gs->envelope_volume + 1; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if(envelope_volume != 0) \
|
||||
envelope_volume = gs->envelope_volume - 1; \
|
||||
} \
|
||||
\
|
||||
update_volume(envelope); \
|
||||
\
|
||||
gs->envelope_volume = envelope_volume; \
|
||||
gs->envelope_ticks = gs->envelope_initial_ticks; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
gs->envelope_ticks = envelope_ticks; \
|
||||
} \
|
||||
} \
|
||||
|
||||
#define update_tone_noenvelope() \
|
||||
|
||||
#define gbc_sound_synchronize() \
|
||||
while(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) > \
|
||||
(audio_buffer_size * 2)) \
|
||||
{ \
|
||||
SDL_CondWait(sound_cv, sound_mutex); \
|
||||
} \
|
||||
|
||||
#define update_tone_counters(envelope_op, sweep_op) \
|
||||
tick_counter += gbc_sound_tick_step; \
|
||||
if(tick_counter > 0xFFFF) \
|
||||
{ \
|
||||
if(gs->length_status) \
|
||||
{ \
|
||||
u32 length_ticks = gs->length_ticks - 1; \
|
||||
gs->length_ticks = length_ticks; \
|
||||
\
|
||||
if(length_ticks == 0) \
|
||||
{ \
|
||||
gs->active_flag = 0; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
update_tone_##envelope_op(); \
|
||||
update_tone_##sweep_op(); \
|
||||
\
|
||||
tick_counter &= 0xFFFF; \
|
||||
} \
|
||||
|
||||
#define gbc_sound_render_sample_right() \
|
||||
sound_buffer[buffer_index + 1] += (current_sample * volume_right) >> 22 \
|
||||
|
||||
#define gbc_sound_render_sample_left() \
|
||||
sound_buffer[buffer_index] += (current_sample * volume_left) >> 22 \
|
||||
|
||||
#define gbc_sound_render_sample_both() \
|
||||
gbc_sound_render_sample_right(); \
|
||||
gbc_sound_render_sample_left() \
|
||||
|
||||
#define gbc_sound_render_samples(type, sample_length, envelope_op, sweep_op) \
|
||||
for(i = 0; i < buffer_ticks; i++) \
|
||||
{ \
|
||||
current_sample = \
|
||||
sample_data[fp16_16_to_u32(sample_index) % sample_length]; \
|
||||
gbc_sound_render_sample_##type(); \
|
||||
\
|
||||
sample_index += frequency_step; \
|
||||
buffer_index = (buffer_index + 2) % BUFFER_SIZE; \
|
||||
\
|
||||
update_tone_counters(envelope_op, sweep_op); \
|
||||
} \
|
||||
|
||||
#define gbc_noise_wrap_full 32767
|
||||
|
||||
#define gbc_noise_wrap_half 126
|
||||
|
||||
#define get_noise_sample_full() \
|
||||
current_sample = \
|
||||
((s32)(noise_table15[fp16_16_to_u32(sample_index) >> 5] << \
|
||||
(fp16_16_to_u32(sample_index) & 0x1F)) >> 31) & 0x0F \
|
||||
|
||||
#define get_noise_sample_half() \
|
||||
current_sample = \
|
||||
((s32)(noise_table7[fp16_16_to_u32(sample_index) >> 5] << \
|
||||
(fp16_16_to_u32(sample_index) & 0x1F)) >> 31) & 0x0F \
|
||||
|
||||
#define gbc_sound_render_noise(type, noise_type, envelope_op, sweep_op) \
|
||||
for(i = 0; i < buffer_ticks; i++) \
|
||||
{ \
|
||||
get_noise_sample_##noise_type(); \
|
||||
gbc_sound_render_sample_##type(); \
|
||||
\
|
||||
sample_index += frequency_step; \
|
||||
\
|
||||
if(sample_index >= u32_to_fp16_16(gbc_noise_wrap_##noise_type)) \
|
||||
sample_index -= u32_to_fp16_16(gbc_noise_wrap_##noise_type); \
|
||||
\
|
||||
buffer_index = (buffer_index + 2) % BUFFER_SIZE; \
|
||||
update_tone_counters(envelope_op, sweep_op); \
|
||||
} \
|
||||
|
||||
#define gbc_sound_render_channel(type, sample_length, envelope_op, sweep_op) \
|
||||
buffer_index = gbc_sound_buffer_index; \
|
||||
sample_index = gs->sample_index; \
|
||||
frequency_step = gs->frequency_step; \
|
||||
tick_counter = gs->tick_counter; \
|
||||
\
|
||||
update_volume(envelope_op); \
|
||||
\
|
||||
switch(gs->status) \
|
||||
{ \
|
||||
case GBC_SOUND_INACTIVE: \
|
||||
break; \
|
||||
\
|
||||
case GBC_SOUND_LEFT: \
|
||||
gbc_sound_render_##type(left, sample_length, envelope_op, sweep_op); \
|
||||
break; \
|
||||
\
|
||||
case GBC_SOUND_RIGHT: \
|
||||
gbc_sound_render_##type(right, sample_length, envelope_op, sweep_op); \
|
||||
break; \
|
||||
\
|
||||
case GBC_SOUND_LEFTRIGHT: \
|
||||
gbc_sound_render_##type(both, sample_length, envelope_op, sweep_op); \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
gs->sample_index = sample_index; \
|
||||
gs->tick_counter = tick_counter; \
|
||||
|
||||
#define gbc_sound_load_wave_ram(bank) \
|
||||
wave_bank = wave_samples + (bank * 32); \
|
||||
for(i = 0, i2 = 0; i < 16; i++, i2 += 2) \
|
||||
{ \
|
||||
current_sample = wave_ram[i]; \
|
||||
wave_bank[i2] = (((current_sample >> 4) & 0x0F) - 8); \
|
||||
wave_bank[i2 + 1] = ((current_sample & 0x0F) - 8); \
|
||||
} \
|
||||
|
||||
void synchronize_sound()
|
||||
{
|
||||
SDL_LockMutex(sound_mutex);
|
||||
|
||||
gbc_sound_synchronize();
|
||||
|
||||
SDL_UnlockMutex(sound_mutex);
|
||||
}
|
||||
|
||||
void update_gbc_sound(u32 cpu_ticks)
|
||||
{
|
||||
fixed16_16 buffer_ticks = float_to_fp16_16(((float)(cpu_ticks -
|
||||
gbc_sound_last_cpu_ticks) * sound_frequency) / 16777216.0);
|
||||
u32 i, i2;
|
||||
gbc_sound_struct *gs = gbc_sound_channel;
|
||||
fixed16_16 sample_index, frequency_step;
|
||||
fixed16_16 tick_counter;
|
||||
u32 buffer_index;
|
||||
s32 volume_left, volume_right;
|
||||
u32 envelope_volume;
|
||||
s32 current_sample;
|
||||
u32 sound_status = address16(io_registers, 0x84) & 0xFFF0;
|
||||
s8 *sample_data;
|
||||
s8 *wave_bank;
|
||||
u8 *wave_ram = ((u8 *)io_registers) + 0x90;
|
||||
|
||||
gbc_sound_partial_ticks += fp16_16_fractional_part(buffer_ticks);
|
||||
buffer_ticks = fp16_16_to_u32(buffer_ticks);
|
||||
|
||||
if(gbc_sound_partial_ticks > 0xFFFF)
|
||||
{
|
||||
buffer_ticks += 1;
|
||||
gbc_sound_partial_ticks &= 0xFFFF;
|
||||
}
|
||||
|
||||
SDL_LockMutex(sound_mutex);
|
||||
if(synchronize_flag)
|
||||
{
|
||||
if(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) >
|
||||
(audio_buffer_size * 3 / 2))
|
||||
{
|
||||
while(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) >
|
||||
(audio_buffer_size * 3 / 2))
|
||||
{
|
||||
SDL_CondWait(sound_cv, sound_mutex);
|
||||
}
|
||||
|
||||
#ifdef PSP_BUILD
|
||||
if(current_frameskip_type == auto_frameskip)
|
||||
{
|
||||
sceDisplayWaitVblankStart();
|
||||
real_frame_count = 0;
|
||||
virtual_frame_count = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
#ifdef GP2X_BUILD
|
||||
if(current_frameskip_type == auto_frameskip)
|
||||
{
|
||||
u64 current_ticks;
|
||||
u64 next_ticks;
|
||||
get_ticks_us(¤t_ticks);
|
||||
|
||||
next_ticks = ((current_ticks + 16666) / 16667) * 16667;
|
||||
delay_us(next_ticks - current_ticks);
|
||||
|
||||
get_ticks_us(&frame_count_initial_timestamp);
|
||||
real_frame_count = 0;
|
||||
virtual_frame_count = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
*/
|
||||
}
|
||||
}
|
||||
if(sound_on == 1)
|
||||
{
|
||||
gs = gbc_sound_channel + 0;
|
||||
if(gs->active_flag)
|
||||
{
|
||||
sound_status |= 0x01;
|
||||
sample_data = gs->sample_data;
|
||||
envelope_volume = gs->envelope_volume;
|
||||
gbc_sound_render_channel(samples, 8, envelope, sweep);
|
||||
}
|
||||
|
||||
gs = gbc_sound_channel + 1;
|
||||
if(gs->active_flag)
|
||||
{
|
||||
sound_status |= 0x02;
|
||||
sample_data = gs->sample_data;
|
||||
envelope_volume = gs->envelope_volume;
|
||||
gbc_sound_render_channel(samples, 8, envelope, nosweep);
|
||||
}
|
||||
|
||||
gs = gbc_sound_channel + 2;
|
||||
if(gbc_sound_wave_update)
|
||||
{
|
||||
if(gs->wave_bank == 1)
|
||||
{
|
||||
gbc_sound_load_wave_ram(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
gbc_sound_load_wave_ram(0);
|
||||
}
|
||||
|
||||
gbc_sound_wave_update = 0;
|
||||
}
|
||||
|
||||
if((gs->active_flag) && (gs->master_enable))
|
||||
{
|
||||
sound_status |= 0x04;
|
||||
sample_data = wave_samples;
|
||||
if(gs->wave_type == 0)
|
||||
{
|
||||
if(gs->wave_bank == 1)
|
||||
sample_data += 32;
|
||||
|
||||
gbc_sound_render_channel(samples, 32, noenvelope, nosweep);
|
||||
}
|
||||
else
|
||||
{
|
||||
gbc_sound_render_channel(samples, 64, noenvelope, nosweep);
|
||||
}
|
||||
}
|
||||
|
||||
gs = gbc_sound_channel + 3;
|
||||
if(gs->active_flag)
|
||||
{
|
||||
sound_status |= 0x08;
|
||||
envelope_volume = gs->envelope_volume;
|
||||
|
||||
if(gs->noise_type == 1)
|
||||
{
|
||||
gbc_sound_render_channel(noise, half, envelope, nosweep);
|
||||
}
|
||||
else
|
||||
{
|
||||
gbc_sound_render_channel(noise, full, envelope, nosweep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
address16(io_registers, 0x84) = sound_status;
|
||||
|
||||
SDL_CondSignal(sound_cv);
|
||||
|
||||
SDL_UnlockMutex(sound_mutex);
|
||||
|
||||
gbc_sound_last_cpu_ticks = cpu_ticks;
|
||||
gbc_sound_buffer_index =
|
||||
(gbc_sound_buffer_index + (buffer_ticks * 2)) % BUFFER_SIZE;
|
||||
}
|
||||
|
||||
#define sound_copy_normal() \
|
||||
current_sample = source[i] \
|
||||
|
||||
#define sound_copy(source_offset, length, render_type) \
|
||||
_length = (length) / 2; \
|
||||
source = (s16 *)(sound_buffer + source_offset); \
|
||||
for(i = 0; i < _length; i++) \
|
||||
{ \
|
||||
sound_copy_##render_type(); \
|
||||
if(current_sample > 2047) \
|
||||
current_sample = 2047; \
|
||||
if(current_sample < -2048) \
|
||||
current_sample = -2048; \
|
||||
\
|
||||
stream_base[i] = current_sample << 4; \
|
||||
source[i] = 0; \
|
||||
} \
|
||||
|
||||
#define sound_copy_null(source_offset, length) \
|
||||
_length = (length) / 2; \
|
||||
source = (s16 *)(sound_buffer + source_offset); \
|
||||
for(i = 0; i < _length; i++) \
|
||||
{ \
|
||||
stream_base[i] = 0; \
|
||||
source[i] = 0; \
|
||||
} \
|
||||
|
||||
|
||||
void sound_callback(void *userdata, Uint8 *stream, int length)
|
||||
{
|
||||
u32 sample_length = length / 2;
|
||||
u32 _length;
|
||||
u32 i;
|
||||
s16 *stream_base = (s16 *)stream;
|
||||
s16 *source;
|
||||
s32 current_sample;
|
||||
|
||||
SDL_LockMutex(sound_mutex);
|
||||
|
||||
while(((gbc_sound_buffer_index - sound_buffer_base) % BUFFER_SIZE) <
|
||||
length)
|
||||
{
|
||||
SDL_CondWait(sound_cv, sound_mutex);
|
||||
}
|
||||
|
||||
if(global_enable_audio)
|
||||
{
|
||||
if((sound_buffer_base + sample_length) >= BUFFER_SIZE)
|
||||
{
|
||||
u32 partial_length = (BUFFER_SIZE - sound_buffer_base) * 2;
|
||||
sound_copy(sound_buffer_base, partial_length, normal);
|
||||
source = (s16 *)sound_buffer;
|
||||
sound_copy(0, length - partial_length, normal);
|
||||
sound_buffer_base = (length - partial_length) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
sound_copy(sound_buffer_base, length, normal);
|
||||
sound_buffer_base += sample_length;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if((sound_buffer_base + sample_length) >= BUFFER_SIZE)
|
||||
{
|
||||
u32 partial_length = (BUFFER_SIZE - sound_buffer_base) * 2;
|
||||
sound_copy_null(sound_buffer_base, partial_length);
|
||||
source = (s16 *)sound_buffer;
|
||||
sound_copy(0, length - partial_length, normal);
|
||||
sound_buffer_base = (length - partial_length) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
sound_copy_null(sound_buffer_base, length);
|
||||
sound_buffer_base += sample_length;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_CondSignal(sound_cv);
|
||||
|
||||
SDL_UnlockMutex(sound_mutex);
|
||||
}
|
||||
|
||||
// Special thanks to blarrg for the LSFR frequency used in Meridian, as posted
|
||||
// on the forum at http://meridian.overclocked.org:
|
||||
// http://meridian.overclocked.org/cgi-bin/wwwthreads/showpost.pl?Board=merid
|
||||
// angeneraldiscussion&Number=2069&page=0&view=expanded&mode=threaded&sb=4
|
||||
// Hope you don't mind me borrowing it ^_-
|
||||
|
||||
void init_noise_table(u32 *table, u32 period, u32 bit_length)
|
||||
{
|
||||
u32 shift_register = 0xFF;
|
||||
u32 mask = ~(1 << bit_length);
|
||||
s32 table_pos, bit_pos;
|
||||
u32 current_entry;
|
||||
u32 table_period = (period + 31) / 32;
|
||||
|
||||
// Bits are stored in reverse order so they can be more easily moved to
|
||||
// bit 31, for sign extended shift down.
|
||||
|
||||
for(table_pos = 0; table_pos < table_period; table_pos++)
|
||||
{
|
||||
current_entry = 0;
|
||||
for(bit_pos = 31; bit_pos >= 0; bit_pos--)
|
||||
{
|
||||
current_entry |= (shift_register & 0x01) << bit_pos;
|
||||
|
||||
shift_register =
|
||||
((1 & (shift_register ^ (shift_register >> 1))) << bit_length) |
|
||||
((shift_register >> 1) & mask);
|
||||
}
|
||||
|
||||
table[table_pos] = current_entry;
|
||||
}
|
||||
}
|
||||
|
||||
void reset_sound()
|
||||
{
|
||||
direct_sound_struct *ds = direct_sound_channel;
|
||||
gbc_sound_struct *gs = gbc_sound_channel;
|
||||
u32 i;
|
||||
|
||||
sound_on = 0;
|
||||
sound_buffer_base = 0;
|
||||
sound_last_cpu_ticks = 0;
|
||||
memset(sound_buffer, 0, audio_buffer_size);
|
||||
|
||||
for(i = 0; i < 2; i++, ds++)
|
||||
{
|
||||
ds->buffer_index = 0;
|
||||
ds->status = DIRECT_SOUND_INACTIVE;
|
||||
ds->fifo_top = 0;
|
||||
ds->fifo_base = 0;
|
||||
ds->fifo_fractional = 0;
|
||||
ds->last_cpu_ticks = 0;
|
||||
memset(ds->fifo, 0, 32);
|
||||
}
|
||||
|
||||
gbc_sound_buffer_index = 0;
|
||||
gbc_sound_last_cpu_ticks = 0;
|
||||
gbc_sound_partial_ticks = 0;
|
||||
|
||||
gbc_sound_master_volume_left = 0;
|
||||
gbc_sound_master_volume_right = 0;
|
||||
gbc_sound_master_volume = 0;
|
||||
memset(wave_samples, 0, 64);
|
||||
|
||||
for(i = 0; i < 4; i++, gs++)
|
||||
{
|
||||
gs->status = GBC_SOUND_INACTIVE;
|
||||
gs->sample_data = square_pattern_duty[2];
|
||||
gs->active_flag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void sound_exit()
|
||||
{
|
||||
gbc_sound_buffer_index =
|
||||
(sound_buffer_base + audio_buffer_size) % BUFFER_SIZE;
|
||||
SDL_PauseAudio(1);
|
||||
SDL_CondSignal(sound_cv);
|
||||
}
|
||||
|
||||
void init_sound()
|
||||
{
|
||||
#ifdef PSP_BUILD
|
||||
audio_buffer_size = (audio_buffer_size_number * 1024) + 3072;
|
||||
#elif defined(TAVI_BUILD) || defined(ARM_ARCH)
|
||||
audio_buffer_size = 16 << audio_buffer_size_number;
|
||||
// audio_buffer_size = 16384;
|
||||
#else
|
||||
audio_buffer_size = 16384;
|
||||
#endif
|
||||
|
||||
SDL_AudioSpec desired_spec =
|
||||
{
|
||||
sound_frequency,
|
||||
AUDIO_S16,
|
||||
2,
|
||||
0,
|
||||
audio_buffer_size / 4,
|
||||
0,
|
||||
0,
|
||||
sound_callback,
|
||||
NULL
|
||||
};
|
||||
|
||||
gbc_sound_tick_step =
|
||||
float_to_fp16_16(256.0 / sound_frequency);
|
||||
|
||||
init_noise_table(noise_table15, 32767, 14);
|
||||
init_noise_table(noise_table7, 127, 6);
|
||||
|
||||
reset_sound();
|
||||
|
||||
SDL_OpenAudio(&desired_spec, &sound_settings);
|
||||
sound_frequency = sound_settings.freq;
|
||||
sound_mutex = SDL_CreateMutex();
|
||||
sound_cv = SDL_CreateCond();
|
||||
SDL_PauseAudio(0);
|
||||
}
|
||||
|
||||
#define sound_savestate_builder(type) \
|
||||
void sound_##type##_savestate(file_tag_type savestate_file) \
|
||||
{ \
|
||||
file_##type##_variable(savestate_file, sound_on); \
|
||||
file_##type##_variable(savestate_file, sound_buffer_base); \
|
||||
file_##type##_variable(savestate_file, sound_last_cpu_ticks); \
|
||||
file_##type##_variable(savestate_file, gbc_sound_buffer_index); \
|
||||
file_##type##_variable(savestate_file, gbc_sound_last_cpu_ticks); \
|
||||
file_##type##_variable(savestate_file, gbc_sound_partial_ticks); \
|
||||
file_##type##_variable(savestate_file, gbc_sound_master_volume_left); \
|
||||
file_##type##_variable(savestate_file, gbc_sound_master_volume_right); \
|
||||
file_##type##_variable(savestate_file, gbc_sound_master_volume); \
|
||||
file_##type##_array(savestate_file, wave_samples); \
|
||||
file_##type##_array(savestate_file, direct_sound_channel); \
|
||||
file_##type##_array(savestate_file, gbc_sound_channel); \
|
||||
} \
|
||||
|
||||
sound_savestate_builder(read);
|
||||
sound_savestate_builder(write_mem);
|
||||
|
328
sound.h
Normal file
328
sound.h
Normal file
@ -0,0 +1,328 @@
|
||||
/* gameplaySP
|
||||
*
|
||||
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SOUND_H
|
||||
#define SOUND_H
|
||||
|
||||
#define BUFFER_SIZE 65536
|
||||
|
||||
// A lot of sound cards on PC can't handle such small buffers but this
|
||||
// seems to work well on PSP.
|
||||
|
||||
#ifdef PSP_BUILD
|
||||
|
||||
#define SOUND_BUFFER_SIZE 4096
|
||||
|
||||
#else
|
||||
|
||||
#define SOUND_BUFFER_SIZE 16384
|
||||
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DIRECT_SOUND_INACTIVE,
|
||||
DIRECT_SOUND_RIGHT,
|
||||
DIRECT_SOUND_LEFT,
|
||||
DIRECT_SOUND_LEFTRIGHT
|
||||
} direct_sound_status_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DIRECT_SOUND_VOLUME_50,
|
||||
DIRECT_SOUND_VOLUME_100
|
||||
} direct_sound_volume_type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
s8 fifo[32];
|
||||
u32 fifo_base;
|
||||
u32 fifo_top;
|
||||
fixed16_16 fifo_fractional;
|
||||
// The + 1 is to give some extra room for linear interpolation
|
||||
// when wrapping around.
|
||||
u32 buffer_index;
|
||||
direct_sound_status_type status;
|
||||
direct_sound_volume_type volume;
|
||||
u32 last_cpu_ticks;
|
||||
} direct_sound_struct;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GBC_SOUND_INACTIVE,
|
||||
GBC_SOUND_RIGHT,
|
||||
GBC_SOUND_LEFT,
|
||||
GBC_SOUND_LEFTRIGHT
|
||||
} gbc_sound_status_type;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 rate;
|
||||
fixed16_16 frequency_step;
|
||||
fixed16_16 sample_index;
|
||||
fixed16_16 tick_counter;
|
||||
u32 total_volume;
|
||||
u32 envelope_initial_volume;
|
||||
u32 envelope_volume;
|
||||
u32 envelope_direction;
|
||||
u32 envelope_status;
|
||||
u32 envelope_step;
|
||||
u32 envelope_ticks;
|
||||
u32 envelope_initial_ticks;
|
||||
u32 sweep_status;
|
||||
u32 sweep_direction;
|
||||
u32 sweep_ticks;
|
||||
u32 sweep_initial_ticks;
|
||||
u32 sweep_shift;
|
||||
u32 length_status;
|
||||
u32 length_ticks;
|
||||
u32 noise_type;
|
||||
u32 wave_type;
|
||||
u32 wave_bank;
|
||||
u32 wave_volume;
|
||||
gbc_sound_status_type status;
|
||||
u32 active_flag;
|
||||
u32 master_enable;
|
||||
s8 *sample_data;
|
||||
} gbc_sound_struct;
|
||||
|
||||
extern direct_sound_struct direct_sound_channel[2];
|
||||
extern gbc_sound_struct gbc_sound_channel[4];
|
||||
extern s8 square_pattern_duty[4][8];
|
||||
extern u32 gbc_sound_master_volume_left;
|
||||
extern u32 gbc_sound_master_volume_right;
|
||||
extern u32 gbc_sound_master_volume;
|
||||
|
||||
extern u32 sound_frequency;
|
||||
extern u32 sound_on;
|
||||
|
||||
extern u32 global_enable_audio;
|
||||
extern u32 enable_low_pass_filter;
|
||||
extern u32 audio_buffer_size_number;
|
||||
|
||||
extern SDL_mutex *sound_mutex;
|
||||
extern SDL_cond *sound_cv;
|
||||
|
||||
void sound_timer_queue8(u32 channel, u8 value);
|
||||
void sound_timer_queue16(u32 channel, u16 value);
|
||||
void sound_timer_queue32(u32 channel, u32 value);
|
||||
void sound_timer(fixed16_16 frequency_step, u32 channel);
|
||||
void sound_reset_fifo(u32 channel);
|
||||
void update_gbc_sound(u32 cpu_ticks);
|
||||
void init_sound();
|
||||
void sound_write_mem_savestate(file_tag_type savestate_file);
|
||||
void sound_read_savestate(file_tag_type savestate_file);
|
||||
|
||||
#define gbc_sound_tone_control_low(channel, address) \
|
||||
{ \
|
||||
u32 initial_volume = (value >> 12) & 0x0F; \
|
||||
u32 envelope_ticks = ((value >> 8) & 0x07) * 4; \
|
||||
gbc_sound_channel[channel].length_ticks = 64 - (value & 0x3F); \
|
||||
gbc_sound_channel[channel].sample_data = \
|
||||
square_pattern_duty[(value >> 6) & 0x03]; \
|
||||
gbc_sound_channel[channel].envelope_direction = (value >> 11) & 0x01; \
|
||||
gbc_sound_channel[channel].envelope_initial_volume = initial_volume; \
|
||||
gbc_sound_channel[channel].envelope_volume = initial_volume; \
|
||||
gbc_sound_channel[channel].envelope_initial_ticks = envelope_ticks; \
|
||||
gbc_sound_channel[channel].envelope_ticks = envelope_ticks; \
|
||||
gbc_sound_channel[channel].envelope_status = (envelope_ticks != 0); \
|
||||
gbc_sound_channel[channel].envelope_volume = initial_volume; \
|
||||
gbc_sound_update = 1; \
|
||||
address16(io_registers, address) = value; \
|
||||
} \
|
||||
|
||||
#define gbc_sound_tone_control_high(channel, address) \
|
||||
{ \
|
||||
u32 rate = value & 0x7FF; \
|
||||
gbc_sound_channel[channel].rate = rate; \
|
||||
gbc_sound_channel[channel].frequency_step = \
|
||||
float_to_fp16_16(((131072.0 / (2048 - rate)) * 8.0) / sound_frequency); \
|
||||
gbc_sound_channel[channel].length_status = (value >> 14) & 0x01; \
|
||||
if(value & 0x8000) \
|
||||
{ \
|
||||
gbc_sound_channel[channel].active_flag = 1; \
|
||||
gbc_sound_channel[channel].sample_index -= float_to_fp16_16(1.0 / 12.0); \
|
||||
gbc_sound_channel[channel].envelope_ticks = \
|
||||
gbc_sound_channel[channel].envelope_initial_ticks; \
|
||||
gbc_sound_channel[channel].envelope_volume = \
|
||||
gbc_sound_channel[channel].envelope_initial_volume; \
|
||||
} \
|
||||
\
|
||||
gbc_sound_update = 1; \
|
||||
address16(io_registers, address) = value; \
|
||||
} \
|
||||
|
||||
#define gbc_sound_tone_control_sweep() \
|
||||
{ \
|
||||
u32 sweep_ticks = ((value >> 4) & 0x07) * 2; \
|
||||
gbc_sound_channel[0].sweep_shift = value & 0x07; \
|
||||
gbc_sound_channel[0].sweep_direction = (value >> 3) & 0x01; \
|
||||
gbc_sound_channel[0].sweep_status = (value != 8); \
|
||||
gbc_sound_channel[0].sweep_ticks = sweep_ticks; \
|
||||
gbc_sound_channel[0].sweep_initial_ticks = sweep_ticks; \
|
||||
gbc_sound_update = 1; \
|
||||
address16(io_registers, 0x60) = value; \
|
||||
} \
|
||||
|
||||
#define gbc_sound_wave_control() \
|
||||
{ \
|
||||
gbc_sound_channel[2].wave_type = (value >> 5) & 0x01; \
|
||||
gbc_sound_channel[2].wave_bank = (value >> 6) & 0x01; \
|
||||
if(value & 0x80) \
|
||||
{ \
|
||||
gbc_sound_channel[2].master_enable = 1; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
gbc_sound_channel[2].master_enable = 0; \
|
||||
} \
|
||||
\
|
||||
gbc_sound_update = 1; \
|
||||
address16(io_registers, 0x70) = value; \
|
||||
} \
|
||||
|
||||
static u32 gbc_sound_wave_volume[4] = { 0, 16384, 8192, 4096 };
|
||||
|
||||
#define gbc_sound_tone_control_low_wave() \
|
||||
{ \
|
||||
gbc_sound_channel[2].length_ticks = 256 - (value & 0xFF); \
|
||||
if((value >> 15) & 0x01) \
|
||||
{ \
|
||||
gbc_sound_channel[2].wave_volume = 12288; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
gbc_sound_channel[2].wave_volume = \
|
||||
gbc_sound_wave_volume[(value >> 13) & 0x03]; \
|
||||
} \
|
||||
gbc_sound_update = 1; \
|
||||
address16(io_registers, 0x72) = value; \
|
||||
} \
|
||||
|
||||
#define gbc_sound_tone_control_high_wave() \
|
||||
{ \
|
||||
u32 rate = value & 0x7FF; \
|
||||
gbc_sound_channel[2].rate = rate; \
|
||||
gbc_sound_channel[2].frequency_step = \
|
||||
float_to_fp16_16((2097152.0 / (2048 - rate)) / sound_frequency); \
|
||||
gbc_sound_channel[2].length_status = (value >> 14) & 0x01; \
|
||||
if(value & 0x8000) \
|
||||
{ \
|
||||
gbc_sound_channel[2].sample_index = 0; \
|
||||
gbc_sound_channel[2].active_flag = 1; \
|
||||
} \
|
||||
gbc_sound_update = 1; \
|
||||
address16(io_registers, 0x74) = value; \
|
||||
} \
|
||||
|
||||
#define gbc_sound_noise_control() \
|
||||
{ \
|
||||
u32 dividing_ratio = value & 0x07; \
|
||||
u32 frequency_shift = (value >> 4) & 0x0F; \
|
||||
if(dividing_ratio == 0) \
|
||||
{ \
|
||||
gbc_sound_channel[3].frequency_step = \
|
||||
float_to_fp16_16(1048576.0 / (1 << (frequency_shift + 1)) / \
|
||||
sound_frequency); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
gbc_sound_channel[3].frequency_step = \
|
||||
float_to_fp16_16(524288.0 / (dividing_ratio * \
|
||||
(1 << (frequency_shift + 1))) / sound_frequency); \
|
||||
} \
|
||||
gbc_sound_channel[3].noise_type = (value >> 3) & 0x01; \
|
||||
gbc_sound_channel[3].length_status = (value >> 14) & 0x01; \
|
||||
if(value & 0x8000) \
|
||||
{ \
|
||||
gbc_sound_channel[3].sample_index = 0; \
|
||||
gbc_sound_channel[3].active_flag = 1; \
|
||||
gbc_sound_channel[3].envelope_ticks = \
|
||||
gbc_sound_channel[3].envelope_initial_ticks; \
|
||||
gbc_sound_channel[3].envelope_volume = \
|
||||
gbc_sound_channel[3].envelope_initial_volume; \
|
||||
} \
|
||||
gbc_sound_update = 1; \
|
||||
address16(io_registers, 0x7C) = value; \
|
||||
} \
|
||||
|
||||
#define gbc_trigger_sound_channel(channel) \
|
||||
gbc_sound_master_volume_right = value & 0x07; \
|
||||
gbc_sound_master_volume_left = (value >> 4) & 0x07; \
|
||||
gbc_sound_channel[channel].status = ((value >> (channel + 8)) & 0x01) | \
|
||||
((value >> (channel + 11)) & 0x03) \
|
||||
|
||||
#define gbc_trigger_sound() \
|
||||
{ \
|
||||
gbc_trigger_sound_channel(0); \
|
||||
gbc_trigger_sound_channel(1); \
|
||||
gbc_trigger_sound_channel(2); \
|
||||
gbc_trigger_sound_channel(3); \
|
||||
address16(io_registers, 0x80) = value; \
|
||||
} \
|
||||
|
||||
#define trigger_sound() \
|
||||
{ \
|
||||
timer[0].direct_sound_channels = (((value >> 10) & 0x01) == 0) | \
|
||||
((((value >> 14) & 0x01) == 0) << 1); \
|
||||
timer[1].direct_sound_channels = (((value >> 10) & 0x01) == 1) | \
|
||||
((((value >> 14) & 0x01) == 1) << 1); \
|
||||
direct_sound_channel[0].volume = (value >> 2) & 0x01; \
|
||||
direct_sound_channel[0].status = (value >> 8) & 0x03; \
|
||||
direct_sound_channel[1].volume = (value >> 3) & 0x01; \
|
||||
direct_sound_channel[1].status = (value >> 12) & 0x03; \
|
||||
gbc_sound_master_volume = value & 0x03; \
|
||||
\
|
||||
if((value >> 11) & 0x01) \
|
||||
sound_reset_fifo(0); \
|
||||
if((value >> 15) & 0x01) \
|
||||
sound_reset_fifo(1); \
|
||||
address16(io_registers, 0x82) = value; \
|
||||
} \
|
||||
|
||||
#define sound_on() \
|
||||
if(value & 0x80) \
|
||||
{ \
|
||||
if(sound_on != 1) \
|
||||
{ \
|
||||
sound_on = 1; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
u32 i; \
|
||||
for(i = 0; i < 4; i++) \
|
||||
{ \
|
||||
gbc_sound_channel[i].active_flag = 0; \
|
||||
} \
|
||||
sound_on = 0; \
|
||||
} \
|
||||
address16(io_registers, 0x84) = \
|
||||
(address16(io_registers, 0x84) & 0x000F) | (value & 0xFFF0); \
|
||||
|
||||
#define sound_update_frequency_step(timer_number) \
|
||||
timer[timer_number].frequency_step = \
|
||||
float_to_fp16_16(16777216.0 / (timer_reload * sound_frequency)) \
|
||||
|
||||
|
||||
void reset_sound();
|
||||
void sound_exit();
|
||||
|
||||
#endif
|
94
video.h
Normal file
94
video.h
Normal file
@ -0,0 +1,94 @@
|
||||
/* gameplaySP
|
||||
*
|
||||
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef VIDEO_H
|
||||
#define VIDEO_H
|
||||
|
||||
void update_scanline();
|
||||
void update_screen();
|
||||
void init_video();
|
||||
void video_resolution_large();
|
||||
void video_resolution_small();
|
||||
void print_string(const char *str, u16 fg_color, u16 bg_color,
|
||||
u32 x, u32 y);
|
||||
void print_string_pad(const char *str, u16 fg_color, u16 bg_color,
|
||||
u32 x, u32 y, u32 pad);
|
||||
void print_string_ext(const char *str, u16 fg_color, u16 bg_color,
|
||||
u32 x, u32 y, void *_dest_ptr, u32 pitch, u32 pad);
|
||||
void clear_screen(u16 color);
|
||||
void blit_to_screen(u16 *src, u32 w, u32 h, u32 x, u32 y);
|
||||
u16 *copy_screen();
|
||||
void flip_screen();
|
||||
void video_write_mem_savestate(file_tag_type savestate_file);
|
||||
void video_read_savestate(file_tag_type savestate_file);
|
||||
|
||||
void debug_screen_clear();
|
||||
void debug_screen_start();
|
||||
void debug_screen_end();
|
||||
void debug_screen_printf(const char *format, ...);
|
||||
void debug_screen_printl(const char *format, ...);
|
||||
void debug_screen_newline(u32 count);
|
||||
void debug_screen_update();
|
||||
|
||||
extern u32 frame_speed;
|
||||
|
||||
extern s32 affine_reference_x[2];
|
||||
extern s32 affine_reference_y[2];
|
||||
|
||||
typedef void (* tile_render_function)(u32 layer_number, u32 start, u32 end,
|
||||
void *dest_ptr);
|
||||
typedef void (* bitmap_render_function)(u32 start, u32 end, void *dest_ptr);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
tile_render_function normal_render_base;
|
||||
tile_render_function normal_render_transparent;
|
||||
tile_render_function alpha_render_base;
|
||||
tile_render_function alpha_render_transparent;
|
||||
tile_render_function color16_render_base;
|
||||
tile_render_function color16_render_transparent;
|
||||
tile_render_function color32_render_base;
|
||||
tile_render_function color32_render_transparent;
|
||||
} tile_layer_render_struct;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bitmap_render_function normal_render;
|
||||
} bitmap_layer_render_struct;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
unscaled,
|
||||
scaled_aspect,
|
||||
fullscreen,
|
||||
} video_scale_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
filter_nearest,
|
||||
filter_bilinear
|
||||
} video_filter_type;
|
||||
|
||||
extern video_scale_type screen_scale;
|
||||
extern video_scale_type current_scale;
|
||||
extern video_filter_type screen_filter;
|
||||
|
||||
void set_gba_resolution(video_scale_type scale);
|
||||
|
||||
#endif
|
38
x86/Makefile
Normal file
38
x86/Makefile
Normal file
@ -0,0 +1,38 @@
|
||||
# gpSP makefile
|
||||
# Gilead Kutnick - Exophase
|
||||
|
||||
# Global definitions
|
||||
|
||||
CC = gcc
|
||||
STRIP = strip
|
||||
AS = as
|
||||
|
||||
PREFIX = /usr
|
||||
OBJS = main.o cpu.o memory.o video.o input.o sound.o \
|
||||
cpu_threaded.o gui.o x86_stub.o cheats.o zip.o
|
||||
BIN ?= gpsp.exe
|
||||
|
||||
# Platform specific definitions
|
||||
|
||||
VPATH += ..
|
||||
CFLAGS += -DPC_BUILD
|
||||
INCLUDES = -I${PREFIX}/include `sdl-config --cflags`
|
||||
LIBS = -L${PREFIX}/lib `sdl-config --libs` -mconsole -lz
|
||||
|
||||
# Compilation:
|
||||
|
||||
.SUFFIXES: .c .S
|
||||
|
||||
%.o: %.c
|
||||
${CC} ${CFLAGS} ${INCLUDES} -c -o $@ $<
|
||||
|
||||
%.o: %.S
|
||||
${AS} -o $@ $<
|
||||
|
||||
all: ${OBJS}
|
||||
${CC} ${OBJS} ${LIBS} -o ${BIN}
|
||||
${STRIP} ${BIN}
|
||||
|
||||
clean:
|
||||
rm -f *.o ${BIN}
|
||||
|
2327
x86/x86_emit.h
Normal file
2327
x86/x86_emit.h
Normal file
File diff suppressed because it is too large
Load Diff
501
x86/x86_stub.S
Normal file
501
x86/x86_stub.S
Normal file
@ -0,0 +1,501 @@
|
||||
# gameplaySP
|
||||
#
|
||||
# Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
.align 4
|
||||
|
||||
.global _x86_update_gba
|
||||
.global _x86_indirect_branch_arm
|
||||
.global _x86_indirect_branch_thumb
|
||||
.global _x86_indirect_branch_dual
|
||||
.global _execute_store_u8
|
||||
.global _execute_store_u16
|
||||
.global _execute_store_u32
|
||||
.global _execute_store_cpsr
|
||||
.global _execute_arm_translate
|
||||
.global _step_debug_x86
|
||||
|
||||
.global _memory_map_read
|
||||
.global _memory_map_write
|
||||
.global _reg
|
||||
|
||||
.global _oam_update
|
||||
|
||||
.global _iwram
|
||||
.global _ewram
|
||||
.global _vram
|
||||
.global _oam_ram
|
||||
.global _bios_rom
|
||||
.global _io_registers
|
||||
|
||||
.extern _spsr
|
||||
|
||||
.equ REG_SP, (13 * 4)
|
||||
.equ REG_LR, (14 * 4)
|
||||
.equ REG_PC, (15 * 4)
|
||||
.equ REG_N_FLAG, (16 * 4)
|
||||
.equ REG_Z_FLAG, (17 * 4)
|
||||
.equ REG_C_FLAG, (18 * 4)
|
||||
.equ REG_V_FLAG, (19 * 4)
|
||||
.equ REG_CPSR, (20 * 4)
|
||||
.equ REG_SAVE, (21 * 4)
|
||||
.equ REG_SAVE2, (22 * 4)
|
||||
.equ REG_SAVE3, (23 * 4)
|
||||
.equ CPU_MODE, (29 * 4)
|
||||
.equ CPU_HALT_STATE, (30 * 4)
|
||||
.equ CHANGED_PC_STATUS, (31 * 4)
|
||||
|
||||
# destroys ecx and edx
|
||||
|
||||
.macro collapse_flag offset, shift
|
||||
mov \offset(%ebx), %ecx
|
||||
shl $\shift, %ecx
|
||||
or %ecx, %edx
|
||||
.endm
|
||||
|
||||
.macro collapse_flags_no_update
|
||||
xor %edx, %edx
|
||||
collapse_flag REG_N_FLAG, 31
|
||||
collapse_flag REG_Z_FLAG, 30
|
||||
collapse_flag REG_C_FLAG, 29
|
||||
collapse_flag REG_V_FLAG, 28
|
||||
mov REG_CPSR(%ebx), %ecx
|
||||
and $0xFF, %ecx
|
||||
or %ecx, %edx
|
||||
.endm
|
||||
|
||||
|
||||
.macro collapse_flags
|
||||
collapse_flags_no_update
|
||||
mov %edx, REG_CPSR(%ebx)
|
||||
.endm
|
||||
|
||||
.macro extract_flag shift, offset
|
||||
mov REG_CPSR(%ebx), %edx
|
||||
shr $\shift, %edx
|
||||
and $0x01, %edx
|
||||
mov %edx, _reg + \offset
|
||||
.endm
|
||||
|
||||
.macro extract_flags
|
||||
extract_flag 31, REG_N_FLAG
|
||||
extract_flag 30, REG_Z_FLAG
|
||||
extract_flag 29, REG_C_FLAG
|
||||
extract_flag 28, REG_V_FLAG
|
||||
.endm
|
||||
|
||||
# Process a hardware event. Since an interrupt might be
|
||||
# raised we have to check if the PC has changed.
|
||||
|
||||
# eax: current address
|
||||
|
||||
st:
|
||||
.asciz "u\n"
|
||||
|
||||
_x86_update_gba:
|
||||
mov %eax, REG_PC(%ebx) # current PC = eax
|
||||
collapse_flags # update cpsr, trashes ecx and edx
|
||||
|
||||
call _update_gba # process the next event
|
||||
|
||||
mov %eax, %edi # edi = new cycle count
|
||||
# did the PC change?
|
||||
cmpl $1, CHANGED_PC_STATUS(%ebx)
|
||||
je lookup_pc
|
||||
ret # if not, go back to caller
|
||||
|
||||
# Perform this on an indirect branch that will definitely go to
|
||||
# ARM code, IE anything that changes the PC in ARM mode except
|
||||
# for BX and data processing to PC with the S bit set.
|
||||
|
||||
# eax: GBA address to branch to
|
||||
# edi: Cycle counter
|
||||
|
||||
_x86_indirect_branch_arm:
|
||||
call _block_lookup_address_arm
|
||||
jmp *%eax
|
||||
|
||||
# For indirect branches that'll definitely go to Thumb. In
|
||||
# Thumb mode any indirect branches except for BX.
|
||||
|
||||
_x86_indirect_branch_thumb:
|
||||
call _block_lookup_address_thumb
|
||||
jmp *%eax
|
||||
|
||||
# For indirect branches that can go to either Thumb or ARM,
|
||||
# mainly BX (also data processing to PC with S bit set, be
|
||||
# sure to adjust the target with a 1 in the lowest bit for this)
|
||||
|
||||
_x86_indirect_branch_dual:
|
||||
call _block_lookup_address_dual
|
||||
jmp *%eax
|
||||
|
||||
|
||||
# General ext memory routines
|
||||
|
||||
ext_store_ignore:
|
||||
ret # ignore these writes
|
||||
|
||||
write_epilogue:
|
||||
cmp $0, %eax # 0 return means nothing happened
|
||||
jz no_alert # if so we can leave
|
||||
|
||||
collapse_flags # make sure flags are good for function call
|
||||
cmp $2, %eax # see if it was an SMC trigger
|
||||
je smc_write
|
||||
|
||||
alert_loop:
|
||||
call _update_gba # process the next event
|
||||
|
||||
# see if the halt status has changed
|
||||
mov CPU_HALT_STATE(%ebx), %edx
|
||||
|
||||
cmp $0, %edx # 0 means it has
|
||||
jnz alert_loop # if not go again
|
||||
|
||||
mov %eax, %edi # edi = new cycle count
|
||||
jmp lookup_pc # pc has definitely changed
|
||||
|
||||
no_alert:
|
||||
ret
|
||||
|
||||
ext_store_eeprom:
|
||||
jmp _write_eeprom # perform eeprom write
|
||||
|
||||
|
||||
# 8bit ext memory routines
|
||||
|
||||
ext_store_io8:
|
||||
and $0x3FF, %eax # wrap around address
|
||||
and $0xFF, %edx
|
||||
call _write_io_register8 # perform 8bit I/O register write
|
||||
jmp write_epilogue # see if it requires any system update
|
||||
|
||||
ext_store_palette8:
|
||||
and $0x3FE, %eax # wrap around address and align to 16bits
|
||||
jmp ext_store_palette16b # perform 16bit palette write
|
||||
|
||||
ext_store_vram8:
|
||||
and $0x1FFFE, %eax # wrap around address and align to 16bits
|
||||
mov %dl, %dh # copy lower 8bits of value into full 16bits
|
||||
cmp $0x18000, %eax # see if address is in upper region
|
||||
jb ext_store_vram8b
|
||||
sub $0x8000, %eax # if so wrap down
|
||||
|
||||
ext_store_vram8b:
|
||||
mov %dx, _vram(%eax) # perform 16bit store
|
||||
ret
|
||||
|
||||
ext_store_oam8:
|
||||
movl $1, _oam_update # flag OAM update
|
||||
and $0x3FE, %eax # wrap around address and align to 16bits
|
||||
mov %dl, %dh # copy lower 8bits of value into full 16bits
|
||||
mov %dx, _oam_ram(%eax) # perform 16bit store
|
||||
ret
|
||||
|
||||
ext_store_backup:
|
||||
and $0xFF, %edx # make value 8bit
|
||||
and $0xFFFF, %eax # mask address
|
||||
jmp _write_backup # perform backup write
|
||||
|
||||
ext_store_u8_jtable:
|
||||
.long ext_store_ignore # 0x00 BIOS, ignore
|
||||
.long ext_store_ignore # 0x01 invalid, ignore
|
||||
.long ext_store_ignore # 0x02 EWRAM, should have been hit already
|
||||
.long ext_store_ignore # 0x03 IWRAM, should have been hit already
|
||||
.long ext_store_io8 # 0x04 I/O registers
|
||||
.long ext_store_palette8 # 0x05 Palette RAM
|
||||
.long ext_store_vram8 # 0x06 VRAM
|
||||
.long ext_store_oam8 # 0x07 OAM RAM
|
||||
.long ext_store_ignore # 0x08 gamepak (no RTC accepted in 8bit)
|
||||
.long ext_store_ignore # 0x09 gamepak, ignore
|
||||
.long ext_store_ignore # 0x0A gamepak, ignore
|
||||
.long ext_store_ignore # 0x0B gamepak, ignore
|
||||
.long ext_store_ignore # 0x0C gamepak, ignore
|
||||
.long ext_store_eeprom # 0x0D EEPROM (possibly)
|
||||
.long ext_store_backup # 0x0E Flash ROM/SRAM
|
||||
|
||||
ext_store_u8:
|
||||
mov %eax, %ecx # ecx = address
|
||||
shr $24, %ecx # ecx = address >> 24
|
||||
cmp $15, %ecx
|
||||
ja ext_store_ignore
|
||||
# ecx = ext_store_u8_jtable[address >> 24]
|
||||
mov ext_store_u8_jtable(, %ecx, 4), %ecx
|
||||
jmp *%ecx # jump to table index
|
||||
|
||||
# eax: address to write to
|
||||
# edx: value to write
|
||||
# ecx: current pc
|
||||
|
||||
_execute_store_u8:
|
||||
mov %ecx, REG_PC(%ebx) # write out the PC
|
||||
mov %eax, %ecx # ecx = address
|
||||
test $0xF0000000, %ecx # check address range
|
||||
jnz ext_store_u8 # if above perform an extended write
|
||||
shr $15, %ecx # ecx = page number of address
|
||||
# load the corresponding memory map offset
|
||||
mov _memory_map_write(, %ecx, 4), %ecx
|
||||
test %ecx, %ecx # see if it's NULL
|
||||
jz ext_store_u8 # if so perform an extended write
|
||||
and $0x7FFF, %eax # isolate the lower 15bits of the address
|
||||
mov %dl, (%eax, %ecx) # store the value
|
||||
# check for self-modifying code
|
||||
testb $0xFF, -32768(%eax, %ecx)
|
||||
jne smc_write
|
||||
ret # return
|
||||
|
||||
_execute_store_u16:
|
||||
mov %ecx, REG_PC(%ebx) # write out the PC
|
||||
and $~0x01, %eax # fix alignment
|
||||
mov %eax, %ecx # ecx = address
|
||||
test $0xF0000000, %ecx # check address range
|
||||
jnz ext_store_u16 # if above perform an extended write
|
||||
shr $15, %ecx # ecx = page number of address
|
||||
# load the corresponding memory map offset
|
||||
mov _memory_map_write(, %ecx, 4), %ecx
|
||||
test %ecx, %ecx # see if it's NULL
|
||||
jz ext_store_u16 # if so perform an extended write
|
||||
and $0x7FFF, %eax # isolate the lower 15bits of the address
|
||||
mov %dx, (%eax, %ecx) # store the value
|
||||
# check for self-modifying code
|
||||
testw $0xFFFF, -32768(%eax, %ecx)
|
||||
jne smc_write
|
||||
ret # return
|
||||
|
||||
# 16bit ext memory routines
|
||||
|
||||
ext_store_io16:
|
||||
and $0x3FF, %eax # wrap around address
|
||||
and $0xFFFF, %edx
|
||||
call _write_io_register16 # perform 16bit I/O register write
|
||||
jmp write_epilogue # see if it requires any system update
|
||||
|
||||
ext_store_palette16:
|
||||
and $0x3FF, %eax # wrap around address
|
||||
|
||||
ext_store_palette16b: # entry point for 8bit write
|
||||
mov %dx, _palette_ram(%eax) # write out palette value
|
||||
mov %edx, %ecx # cx = dx
|
||||
shl $11, %ecx # cx <<= 11 (red component is in high bits)
|
||||
mov %dh, %cl # bottom bits of cx = top bits of dx
|
||||
shr $2, %cl # move the blue component to the bottom of cl
|
||||
and $0x03E0, %dx # isolate green component of dx
|
||||
shl $1, %dx # make green component 6bits
|
||||
or %edx, %ecx # combine green component into ecx
|
||||
# write out the freshly converted palette value
|
||||
mov %cx, _palette_ram_converted(%eax)
|
||||
ret # done
|
||||
|
||||
ext_store_vram16:
|
||||
and $0x1FFFF, %eax # wrap around address
|
||||
cmp $0x18000, %eax # see if address is in upper region
|
||||
jb ext_store_vram16b
|
||||
sub $0x8000, %eax # if so wrap down
|
||||
|
||||
ext_store_vram16b:
|
||||
mov %dx, _vram(%eax) # perform 16bit store
|
||||
ret
|
||||
|
||||
ext_store_oam16:
|
||||
movl $1, _oam_update # flag OAM update
|
||||
and $0x3FF, %eax # wrap around address
|
||||
mov %dx, _oam_ram(%eax) # perform 16bit store
|
||||
ret
|
||||
|
||||
ext_store_rtc:
|
||||
and $0xFFFF, %edx # make value 16bit
|
||||
and $0xFF, %eax # mask address
|
||||
jmp _write_rtc # write out RTC register
|
||||
|
||||
ext_store_u16_jtable:
|
||||
.long ext_store_ignore # 0x00 BIOS, ignore
|
||||
.long ext_store_ignore # 0x01 invalid, ignore
|
||||
.long ext_store_ignore # 0x02 EWRAM, should have been hit already
|
||||
.long ext_store_ignore # 0x03 IWRAM, should have been hit already
|
||||
.long ext_store_io16 # 0x04 I/O registers
|
||||
.long ext_store_palette16 # 0x05 Palette RAM
|
||||
.long ext_store_vram16 # 0x06 VRAM
|
||||
.long ext_store_oam16 # 0x07 OAM RAM
|
||||
.long ext_store_rtc # 0x08 gamepak or RTC
|
||||
.long ext_store_ignore # 0x09 gamepak, ignore
|
||||
.long ext_store_ignore # 0x0A gamepak, ignore
|
||||
.long ext_store_ignore # 0x0B gamepak, ignore
|
||||
.long ext_store_ignore # 0x0C gamepak, ignore
|
||||
.long ext_store_eeprom # 0x0D EEPROM (possibly)
|
||||
.long ext_store_ignore # 0x0E Flash ROM/SRAM must be 8bit
|
||||
|
||||
ext_store_u16:
|
||||
mov %eax, %ecx # ecx = address
|
||||
shr $24, %ecx # ecx = address >> 24
|
||||
cmp $15, %ecx
|
||||
ja ext_store_ignore
|
||||
# ecx = ext_store_u16_jtable[address >> 24]
|
||||
mov ext_store_u16_jtable(, %ecx, 4), %ecx
|
||||
jmp *%ecx # jump to table index
|
||||
|
||||
_execute_store_u32:
|
||||
mov %ecx, REG_PC(%ebx) # write out the PC
|
||||
and $~0x03, %eax # fix alignment
|
||||
mov %eax, %ecx # ecx = address
|
||||
test $0xF0000000, %ecx # check address range
|
||||
jnz ext_store_u32 # if above perform an extended write
|
||||
shr $15, %ecx # ecx = page number of address
|
||||
# load the corresponding memory map offset
|
||||
mov _memory_map_write(, %ecx, 4), %ecx
|
||||
test %ecx, %ecx # see if it's NULL
|
||||
jz ext_store_u32 # if so perform an extended write
|
||||
and $0x7FFF, %eax # isolate the lower 15bits of the address
|
||||
mov %edx, (%eax, %ecx) # store the value
|
||||
# check for self-modifying code
|
||||
testl $0xFFFFFFFF, -32768(%eax, %ecx)
|
||||
jne smc_write
|
||||
ret # return it
|
||||
|
||||
# 32bit ext memory routines
|
||||
|
||||
ext_store_io32:
|
||||
and $0x3FF, %eax # wrap around address
|
||||
call _write_io_register32 # perform 32bit I/O register write
|
||||
jmp write_epilogue # see if it requires any system update
|
||||
|
||||
ext_store_palette32:
|
||||
and $0x3FF, %eax # wrap around address
|
||||
call ext_store_palette16b # write first 16bits
|
||||
add $2, %eax # go to next address
|
||||
shr $16, %edx # go to next 16bits
|
||||
jmp ext_store_palette16b # write next 16bits
|
||||
|
||||
ext_store_vram32:
|
||||
and $0x1FFFF, %eax # wrap around address
|
||||
cmp $0x18000, %eax # see if address is in upper region
|
||||
jb ext_store_vram32b
|
||||
sub $0x8000, %eax # if so wrap down
|
||||
|
||||
ext_store_vram32b:
|
||||
mov %edx, _vram(%eax) # perform 32bit store
|
||||
ret
|
||||
|
||||
ext_store_oam32:
|
||||
movl $1, _oam_update # flag OAM update
|
||||
and $0x3FF, %eax # wrap around address
|
||||
mov %edx, _oam_ram(%eax) # perform 32bit store
|
||||
ret
|
||||
|
||||
ext_store_u32_jtable:
|
||||
.long ext_store_ignore # 0x00 BIOS, ignore
|
||||
.long ext_store_ignore # 0x01 invalid, ignore
|
||||
.long ext_store_ignore # 0x02 EWRAM, should have been hit already
|
||||
.long ext_store_ignore # 0x03 IWRAM, should have been hit already
|
||||
.long ext_store_io32 # 0x04 I/O registers
|
||||
.long ext_store_palette32 # 0x05 Palette RAM
|
||||
.long ext_store_vram32 # 0x06 VRAM
|
||||
.long ext_store_oam32 # 0x07 OAM RAM
|
||||
.long ext_store_ignore # 0x08 gamepak, ignore (no RTC in 32bit)
|
||||
.long ext_store_ignore # 0x09 gamepak, ignore
|
||||
.long ext_store_ignore # 0x0A gamepak, ignore
|
||||
.long ext_store_ignore # 0x0B gamepak, ignore
|
||||
.long ext_store_ignore # 0x0C gamepak, ignore
|
||||
.long ext_store_eeprom # 0x0D EEPROM (possibly)
|
||||
.long ext_store_ignore # 0x0E Flash ROM/SRAM must be 8bit
|
||||
|
||||
|
||||
ext_store_u32:
|
||||
mov %eax, %ecx # ecx = address
|
||||
shr $24, %ecx # ecx = address >> 24
|
||||
cmp $15, %ecx
|
||||
ja ext_store_ignore
|
||||
# ecx = ext_store_u32_jtable[address >> 24]
|
||||
mov ext_store_u32_jtable(, %ecx, 4), %ecx
|
||||
jmp *%ecx
|
||||
|
||||
# %eax = new_cpsr
|
||||
# %edx = store_mask
|
||||
|
||||
_execute_store_cpsr:
|
||||
mov %edx, REG_SAVE(%ebx) # save store_mask
|
||||
mov %ecx, REG_SAVE2(%ebx) # save PC too
|
||||
|
||||
mov %eax, %ecx # ecx = new_cpsr
|
||||
and %edx, %ecx # ecx = new_cpsr & store_mask
|
||||
mov REG_CPSR(%ebx), %eax # eax = cpsr
|
||||
not %edx # edx = ~store_mask
|
||||
and %edx, %eax # eax = cpsr & ~store_mask
|
||||
or %ecx, %eax # eax = new cpsr combined with old
|
||||
|
||||
call _execute_store_cpsr_body # do the dirty work in this C function
|
||||
|
||||
extract_flags # pull out flag vars from new CPSR
|
||||
|
||||
cmp $0, %eax # see if return value is 0
|
||||
jnz changed_pc_cpsr # might have changed the PC
|
||||
|
||||
ret # return
|
||||
|
||||
changed_pc_cpsr:
|
||||
add $4, %esp # get rid of current return address
|
||||
call _block_lookup_address_arm # lookup new PC
|
||||
jmp *%eax
|
||||
|
||||
smc_write:
|
||||
call _flush_translation_cache_ram
|
||||
|
||||
lookup_pc:
|
||||
add $4, %esp
|
||||
movl $0, CHANGED_PC_STATUS(%ebx)
|
||||
mov REG_PC(%ebx), %eax
|
||||
testl $0x20, REG_CPSR(%ebx)
|
||||
jz lookup_pc_arm
|
||||
|
||||
lookup_pc_thumb:
|
||||
call _block_lookup_address_thumb
|
||||
jmp *%eax
|
||||
|
||||
lookup_pc_arm:
|
||||
call _block_lookup_address_arm
|
||||
jmp *%eax
|
||||
|
||||
# eax: cycle counter
|
||||
|
||||
_execute_arm_translate:
|
||||
movl $_reg, %ebx # load base register
|
||||
extract_flags # load flag variables
|
||||
movl %eax, %edi # load edi cycle counter
|
||||
|
||||
movl REG_PC(%ebx), %eax # load PC
|
||||
|
||||
testl $0x20, REG_CPSR(%ebx)
|
||||
jnz 1f
|
||||
|
||||
call _block_lookup_address_arm
|
||||
jmp *%eax # jump to it
|
||||
|
||||
1:
|
||||
call _block_lookup_address_thumb
|
||||
jmp *%eax
|
||||
|
||||
_step_debug_x86:
|
||||
collapse_flags
|
||||
# mov $100, %edi
|
||||
mov %edi, %edx
|
||||
jmp _step_debug
|
||||
|
||||
.comm _memory_map_read 0x8000
|
||||
.comm _memory_map_write 0x8000
|
||||
.comm _reg 0x100
|
||||
|
||||
|
155
zip.c
Normal file
155
zip.c
Normal file
@ -0,0 +1,155 @@
|
||||
/* gameplaySP
|
||||
*
|
||||
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||
* Copyright (C) 2006 SiberianSTAR
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <zlib.h>
|
||||
#include "common.h"
|
||||
|
||||
#define ZIP_BUFFER_SIZE (128 * 1024)
|
||||
|
||||
struct SZIPFileDataDescriptor
|
||||
{
|
||||
s32 CRC32;
|
||||
s32 CompressedSize;
|
||||
s32 UncompressedSize;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct SZIPFileHeader
|
||||
{
|
||||
char Sig[4]; // EDIT: Used to be s32 Sig;
|
||||
s16 VersionToExtract;
|
||||
s16 GeneralBitFlag;
|
||||
s16 CompressionMethod;
|
||||
s16 LastModFileTime;
|
||||
s16 LastModFileDate;
|
||||
struct SZIPFileDataDescriptor DataDescriptor;
|
||||
s16 FilenameLength;
|
||||
s16 ExtraFieldLength;
|
||||
} __attribute__((packed));
|
||||
|
||||
u32 load_file_zip(char *filename)
|
||||
{
|
||||
struct SZIPFileHeader data;
|
||||
u8 tmp[1024];
|
||||
s32 retval = -1;
|
||||
u8 *buffer = NULL;
|
||||
u8 *cbuffer;
|
||||
u8 *ext;
|
||||
|
||||
file_open(fd, filename, read);
|
||||
|
||||
if(!file_check_valid(fd))
|
||||
return -1;
|
||||
|
||||
#if 0 // EDIT: Why this while(1) is used is unknown and can cause a crash.
|
||||
while(1)
|
||||
#endif
|
||||
{
|
||||
file_read(fd, &data, sizeof(struct SZIPFileHeader));
|
||||
|
||||
// EDIT: Check if this is a zip file without worrying about endian
|
||||
// It checks for the following: 0x50 0x4B 0x03 0x04 (PK..)
|
||||
// Used to be: if(data.Sig != 0x04034b50) break;
|
||||
if( data.Sig[0] != 0x50 || data.Sig[1] != 0x4B ||
|
||||
data.Sig[2] != 0x03 || data.Sig[3] != 0x04 )
|
||||
{
|
||||
goto outcode;
|
||||
}
|
||||
|
||||
file_read(fd, tmp, data.FilenameLength);
|
||||
tmp[data.FilenameLength] = 0; // end string
|
||||
|
||||
if(data.ExtraFieldLength)
|
||||
file_seek(fd, data.ExtraFieldLength, SEEK_CUR);
|
||||
|
||||
if(data.GeneralBitFlag & 0x0008)
|
||||
{
|
||||
file_read(fd, &data.DataDescriptor,
|
||||
sizeof(struct SZIPFileDataDescriptor));
|
||||
}
|
||||
|
||||
ext = strrchr(tmp, '.') + 1;
|
||||
|
||||
// file is too big
|
||||
if(data.DataDescriptor.UncompressedSize > gamepak_ram_buffer_size)
|
||||
goto outcode;
|
||||
|
||||
if(!strcasecmp(ext, "bin") || !strcasecmp(ext, "gba"))
|
||||
{
|
||||
buffer = gamepak_rom;
|
||||
|
||||
// ok, found
|
||||
switch(data.CompressionMethod)
|
||||
{
|
||||
case 0:
|
||||
retval = data.DataDescriptor.UncompressedSize;
|
||||
file_read(fd, buffer, retval);
|
||||
|
||||
goto outcode;
|
||||
|
||||
case 8:
|
||||
{
|
||||
z_stream stream;
|
||||
s32 err;
|
||||
|
||||
cbuffer = malloc(ZIP_BUFFER_SIZE);
|
||||
|
||||
stream.next_in = (Bytef*)cbuffer;
|
||||
stream.avail_in = (u32)ZIP_BUFFER_SIZE;
|
||||
|
||||
stream.next_out = (Bytef*)buffer;
|
||||
|
||||
// EDIT: Now uses proper conversion of data types for retval.
|
||||
retval = (u32)data.DataDescriptor.UncompressedSize;
|
||||
stream.avail_out = data.DataDescriptor.UncompressedSize;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
|
||||
err = inflateInit2(&stream, -MAX_WBITS);
|
||||
|
||||
file_read(fd, cbuffer, ZIP_BUFFER_SIZE);
|
||||
|
||||
if(err == Z_OK)
|
||||
{
|
||||
while(err != Z_STREAM_END)
|
||||
{
|
||||
err = inflate(&stream, Z_SYNC_FLUSH);
|
||||
if(err == Z_BUF_ERROR)
|
||||
{
|
||||
stream.avail_in = ZIP_BUFFER_SIZE;
|
||||
stream.next_in = (Bytef*)cbuffer;
|
||||
file_read(fd, cbuffer, ZIP_BUFFER_SIZE);
|
||||
}
|
||||
}
|
||||
err = Z_OK;
|
||||
inflateEnd(&stream);
|
||||
}
|
||||
free(cbuffer);
|
||||
goto outcode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outcode:
|
||||
file_close(fd);
|
||||
|
||||
return retval;
|
||||
}
|
26
zip.h
Normal file
26
zip.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* gameplaySP
|
||||
*
|
||||
* Copyright (C) 2006 Exophase <exophase@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
u32 load_file_zip(char *filename);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user