Removing p7os (non fonctionnel)
220
src/p7os/args.c
|
@ -1,220 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* p7os/args.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project: p7utils | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2017/01/16 23:55:54 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include "main.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Help and version messages */
|
||||
/* ************************************************************************** */
|
||||
/* The version message - that's when the President comes in */
|
||||
static const char version_message[] =
|
||||
QUOTE(BIN) " - from " QUOTE(NAME) " v" QUOTE(VERSION) " (licensed under GPLv2)\n"
|
||||
"Maintained by " QUOTE(MAINTAINER) ".\n"
|
||||
"\n"
|
||||
"This is free software; see the source for copying conditions.\n"
|
||||
"There is NO warranty; not even for MERCHANTABILITY or\n"
|
||||
"FITNESS FOR A PARTICULAR PURPOSE.";
|
||||
|
||||
/* Main help message */
|
||||
static const char help_main[] =
|
||||
"Usage: " QUOTE(BIN) " [--version|-v] [--help|-h] [--com <port>]\n"
|
||||
" [--no-prepare] [--uexe <path>]\n"
|
||||
" <subcommand> [options...]\n"
|
||||
"\n"
|
||||
"Subcommands you can use are :\n"
|
||||
" prepare-only Set-up the update program, but leave it for other programs\n"
|
||||
" to interact with it.\n"
|
||||
" get Get the OS image.\n"
|
||||
"\n"
|
||||
"General options:\n"
|
||||
" -h, --help Display the help page of the (sub)command and quit.\n"
|
||||
" -v, --version Display the version message and quit.\n"
|
||||
" --com <port> The USB-serial port, if you want to communicate with a\n"
|
||||
" calculator connected using a USB-to-serial cable. (1 to 20)\n"
|
||||
" If this option isn't used, the program will look for a\n"
|
||||
" directly connected USB calculator.\n"
|
||||
" --no-prepare Use the current environment, instead of uploading one.\n"
|
||||
" --uexe <path> Use a custom update program.\n"
|
||||
"\n"
|
||||
"Type \"" QUOTE(BIN) " <subcommand> --help\" for some help about a subcommand.\n"
|
||||
"Report bugs to " QUOTE(MAINTAINER) ".";
|
||||
|
||||
/* Subcommands help messages footer */
|
||||
#define FOOT \
|
||||
"\nType \"" QUOTE(BIN) " --help\" for other subcommands and general options."
|
||||
|
||||
/* Help message for prepare subcommand */
|
||||
static const char help_prepare_only[] =
|
||||
"Usage: " QUOTE(BIN) " prepare-only\n"
|
||||
"Send the P7 server on the calculator for further operations.\n"
|
||||
"This must be used before any other p7os operation.\n"
|
||||
FOOT;
|
||||
|
||||
/* Help message for get subcommand */
|
||||
static const char help_get[] =
|
||||
"Usage: " QUOTE(BIN) " get [-o <os.bin>]\n"
|
||||
"Get the calculator OS image.\n"
|
||||
"You must have \"p7os prepare\"-ed before.\n"
|
||||
"\n"
|
||||
"Options are :\n"
|
||||
" -o <os.bin> Where to store the image (default is \"os.bin\")\n"
|
||||
FOOT;
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Main function */
|
||||
/* ************************************************************************** */
|
||||
/* Help macro */
|
||||
#define sub_init(CMD, NARGS) { \
|
||||
args->menu = mn_##CMD; \
|
||||
if (help || pc != (NARGS)) { \
|
||||
puts(help_##CMD); \
|
||||
return (1); \
|
||||
}}
|
||||
|
||||
/**
|
||||
* parse_args:
|
||||
* Args parsing main function.
|
||||
*
|
||||
* Based on my very first experiment with getopt.
|
||||
*
|
||||
* @arg ac the arguments count
|
||||
* @arg av the arguments values
|
||||
* @arg args the parsed args pointer
|
||||
* @return if has been parsed successfully
|
||||
*/
|
||||
|
||||
int parse_args(int ac, char **av, args_t *args)
|
||||
{
|
||||
/* initialize args */
|
||||
*args = (args_t){
|
||||
.menu = 0,
|
||||
.com = 0, .noprepare = 0,
|
||||
.uexe = NULL,
|
||||
.local = NULL, .localpath = NULL
|
||||
};
|
||||
|
||||
/* define options */
|
||||
const char shopts[] = "hvo:#";
|
||||
const struct option longopts[] = {
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
{"com", required_argument, NULL, 'c'},
|
||||
{"no-prepare", no_argument, NULL, 'n'},
|
||||
{"uexe", required_argument, NULL, 'u'},
|
||||
{"output", required_argument, NULL, 'o'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/* get all options */
|
||||
int c; opterr = 0;
|
||||
int help = 0, version = 0;
|
||||
const char *s_out = "os.bin", *s_com = 0, *s_uexe = NULL;
|
||||
while ((c = getopt_long(ac, av, shopts, longopts, NULL)) != -1) switch (c) {
|
||||
/* help */
|
||||
case 'h': help = 1; break;
|
||||
/* version */
|
||||
case 'v': version = 1; break;
|
||||
/* com port */
|
||||
case 'c': s_com = optarg; break;
|
||||
/* no prepare */
|
||||
case 'n': args->noprepare = 1; break;
|
||||
/* uexe */
|
||||
case 'u': s_uexe = optarg; break;
|
||||
/* output */
|
||||
case 'o': s_out = optarg; break;
|
||||
|
||||
/* error */
|
||||
case '?':
|
||||
if (optopt == 'o')
|
||||
log("-o, --output: expected an argument\n");
|
||||
else if (optopt == 'c')
|
||||
log("--com: expected an argument\n");
|
||||
else if (optopt == 'u')
|
||||
log("--uexe: expected an argument\n");
|
||||
else
|
||||
break;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* check for version */
|
||||
if (version) {
|
||||
puts(version_message);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* get non-option arguments (subcommand and parameters) */
|
||||
int pc = ac - optind;
|
||||
char **pv = &av[optind];
|
||||
char *sub = pc ? pv[0] : NULL;
|
||||
pc--; pv++;
|
||||
|
||||
/* subcommand. */
|
||||
char fpmode[2] = "r";
|
||||
if (!sub || !strcmp(sub, "help")) {
|
||||
puts(help_main);
|
||||
return (1);
|
||||
} else if (!strcmp(sub, "version")) {
|
||||
puts(version_message);
|
||||
return (1);
|
||||
} else if (!strcmp(sub, "prepare-only")) {
|
||||
sub_init(prepare_only, 0)
|
||||
|
||||
if (args->noprepare) {
|
||||
log("So we should prepare but we should not prepare? Duh!\n");
|
||||
return (1);
|
||||
}
|
||||
} else if (!strcmp(sub, "get")) {
|
||||
sub_init(get, 0)
|
||||
args->localpath = s_out;
|
||||
fpmode[0] = 'w';
|
||||
} else {
|
||||
log("Unknown subcommand '%s'.\n", sub);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* check com port */
|
||||
if (s_com) {
|
||||
if (!isdigit(s_com[0])) {
|
||||
log("-c, --com: expected a number\n");
|
||||
return (0);
|
||||
}
|
||||
args->com = atoi(s_com);
|
||||
if (args->com < 1 || args->com > 20) {
|
||||
log("-c, --com: COM port number should be between 1 and 20\n");
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* open destination file */
|
||||
if (args->localpath) {
|
||||
args->local = fopen(args->localpath, fpmode);
|
||||
if (!args->local) {
|
||||
log("Could not open local file: %s\n", strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* open update.exe file */
|
||||
if (s_uexe) {
|
||||
args->uexe = fopen(s_uexe, "r");
|
||||
if (!args->uexe) {
|
||||
log("Could not open update program: %s\n", strerror(errno));
|
||||
if (args->local) fclose(args->local);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* everything went well :) */
|
||||
return (0);
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
/Makefile.cfg
|
||||
/obj
|
||||
/update.exe.elf
|
||||
/update.exe.bin
|
||||
/cake.exe.elf
|
||||
/cake.exe.bin
|
|
@ -1,3 +0,0 @@
|
|||
[submodule "libgint"]
|
||||
path = libgint
|
||||
url = http://git.planet-casio.com/lephe/gint.git
|
|
@ -1,336 +0,0 @@
|
|||
GNU General Public License
|
||||
==========================
|
||||
|
||||
_Version 2, June 1991_
|
||||
_Copyright © 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.
|
||||
|
||||
### 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.
|
|
@ -1,136 +0,0 @@
|
|||
#!/usr/bin/make -f
|
||||
#******************************************************************************#
|
||||
# Include variables and message subsystem #
|
||||
#******************************************************************************#
|
||||
include Makefile.vars Makefile.msg
|
||||
|
||||
#******************************************************************************#
|
||||
# General targets #
|
||||
#******************************************************************************#
|
||||
# Build everything.
|
||||
all: all-bin
|
||||
|
||||
# Mostly clean everything (remove everything but the end results).
|
||||
mostlyclean: mostlyclean-bin
|
||||
mclean: mostlyclean
|
||||
|
||||
# Clean everything.
|
||||
clean: clean-bin clean-gint
|
||||
fclean: clean
|
||||
|
||||
# Clean everything with configuration.
|
||||
mrproper: clean
|
||||
$(call rmsg,Removing configuration.)
|
||||
$(call qcmd,$(RM) Makefile.cfg)
|
||||
distclean: mrproper
|
||||
|
||||
# Remake everything (clean and build).
|
||||
re: mostlyclean all
|
||||
|
||||
.PHONY: all mostlyclean mclean clean fclean distclean mrproper re
|
||||
#******************************************************************************#
|
||||
# Configuration (version) checking dependencies #
|
||||
#******************************************************************************#
|
||||
# Define the dependencies.
|
||||
CHECKCFG := $(if $(shell test -f Makefile.cfg || echo y),check-config, \
|
||||
$(if $(shell [ "$(VERSION)" = "$(CONFIG_VERSION)" ] || echo y), \
|
||||
check-config-version))
|
||||
|
||||
# Define the rules.
|
||||
check-config:
|
||||
@printf "\033[1;31mNo configuration file found!\n"
|
||||
@printf "You should configure before re-running this target.\033[0m\n"
|
||||
@false
|
||||
check-config-version:
|
||||
@printf "\033[1;31mConfiguration version is incorrect!\n"
|
||||
@printf "You should re-configure before re-running this target.\033[0m\n"
|
||||
@false
|
||||
|
||||
.PHONY: check-config check-config-version
|
||||
#******************************************************************************#
|
||||
# Information getting from the Makefile variables #
|
||||
#******************************************************************************#
|
||||
# Get the project name.
|
||||
getname:
|
||||
@echo $(NAME)
|
||||
|
||||
# Get the project version.
|
||||
getversion:
|
||||
@echo $(VERSION)
|
||||
|
||||
# Get the project maintainer.
|
||||
getmaintainer:
|
||||
@echo "$(MAINTAINER_NAME) <$(MAINTAINER_MAIL)>"
|
||||
|
||||
.PHONY: getname getmaintainer getversion
|
||||
#******************************************************************************#
|
||||
# gint-related targets #
|
||||
#******************************************************************************#
|
||||
# Main gint target
|
||||
all-gint: $(GLIBDIR)/libgint.a
|
||||
|
||||
# Configure gint libraries.
|
||||
$(GLIBDIR)/gcc.cfg:
|
||||
-$(call qcmd,test -e .git && ! test -e $(GLIBDIR)/.git && \
|
||||
git submodule update --init $(GLIBDIR))
|
||||
$(call bmsg,Configuring gint.)
|
||||
$(call qcmd,cd $(GLIBDIR) && ./configure --no-syscalls)
|
||||
|
||||
# Make gint libraries.
|
||||
$(GLIBDIR)/libgint.a $(GLIBDIR)/libc.a: $(GLIBDIR)/gcc.cfg
|
||||
$(call bmsg,Making gint.)
|
||||
$(call bcmd,make,gint,$(MAKE) $(GLIBDIR) libgint.a libc.a | sed 's/^/ /')
|
||||
|
||||
# Clean gint libraries.
|
||||
clean-gint:
|
||||
$(call rmsg,Cleaning gint.)
|
||||
-$(call qcmd,test -e $(GLIBDIR)/Makefile && \
|
||||
$(MAKE) $(GLIBDIR) distclean | sed 's/^/ /')
|
||||
|
||||
.PHONY: all-gint clean-gint
|
||||
#******************************************************************************#
|
||||
# Binary-related targets #
|
||||
#******************************************************************************#
|
||||
# Make the binary.
|
||||
all-bin: $(CHECKCFG) $(NAME).bin
|
||||
|
||||
# Make the object directory.
|
||||
$(OBJDIR):
|
||||
$(call bcmd,mkdir,$@,$(MD) $@)
|
||||
|
||||
# Make an object file out of an assembly source file.
|
||||
$(OBJDIR)/%.o: $(SRCDIR)/%.s | $(OBJDIR)
|
||||
$(call bcmd,as,$@,$(AS) -c -o $@ $<)
|
||||
|
||||
# Make an object file out of a C source file.
|
||||
$(OBJDIR)/%.o: $(SRCDIR)/%.c | $(OBJDIR)
|
||||
$(call bcmd,cc,$@,$(CC) -c -o $@ $< $(CFLAGS))
|
||||
|
||||
# Make the ELF file.
|
||||
$(NAME).elf: all-gint $(SRC:%=$(OBJDIR)/%.o)
|
||||
$(call bcmd,ld,$@,$(LD) -o $@ $(SRC:%=$(OBJDIR)/%.o) $(LDFLAGS))
|
||||
|
||||
# Make the binary file.
|
||||
$(NAME).bin: $(NAME).elf
|
||||
$(call bcmd,objcopy,$@,$(OBJCOPY) -R .comment -R .bss -O binary $< $@)
|
||||
|
||||
# Removing the objects directory.
|
||||
mostlyclean-bin:
|
||||
$(call rmsg,Removing the objects directory.)
|
||||
$(call qcmd,$(RM) -r $(OBJDIR))
|
||||
$(call rmsg,Removing the ELF file.)
|
||||
$(call qcmd,$(RM) *.elf)
|
||||
|
||||
mclean-bin: mostlyclean-bin
|
||||
|
||||
# Remove everything that was built.
|
||||
clean-bin: mostlyclean-bin
|
||||
$(call rmsg,Removing the final binary.)
|
||||
$(call qcmd,$(RM) *.bin)
|
||||
fclean-bin: clean-bin
|
||||
|
||||
# Remake the binary.
|
||||
re-bin: clean-bin all-bin
|
||||
|
||||
.PHONY: all-bin mostlyclean-bin mclean-bin clean-bin fclean-bin re-bin
|
||||
# End of file.
|
|
@ -1,63 +0,0 @@
|
|||
#!/usr/bin/make -f
|
||||
# The Makefile message subsystem.
|
||||
# For nice logs. 5 dollars per log only.
|
||||
#******************************************************************************#
|
||||
# Colors and misc #
|
||||
#******************************************************************************#
|
||||
# Used colors ANSI modifiers escape codes
|
||||
color_green := 32
|
||||
color_red := 31
|
||||
color_yellow := 33
|
||||
|
||||
# Newline - comes handy in some situations
|
||||
define \n
|
||||
|
||||
|
||||
endef
|
||||
|
||||
#******************************************************************************#
|
||||
# General messages #
|
||||
#******************************************************************************#
|
||||
# Command message - display basic info about the command, and run it.
|
||||
define cmd
|
||||
@$(if $(MAKE_FULL_LOG),,printf "\033[1;""$4""m>\033[0m \033[1m%s\033[0m %s\n" "$1" "$2";)
|
||||
$(if $(MAKE_FULL_LOG),,@)$3
|
||||
endef
|
||||
|
||||
# Quiet command - make it non-quiet if full log is enabled.
|
||||
define qcmd
|
||||
$(if $(MAKE_FULL_LOG),,@)$1
|
||||
endef
|
||||
|
||||
# Normal message - display it.
|
||||
define msg
|
||||
$(if $(MAKE_FULL_LOG),,@printf "\033[1;""$2""m>\033[0m \033[1m%s\033[0m\n" "$1")
|
||||
endef
|
||||
|
||||
#******************************************************************************#
|
||||
# Commands #
|
||||
#******************************************************************************#
|
||||
# Build command
|
||||
define bcmd
|
||||
$(call cmd,$1,$2,$3,$(color_green))
|
||||
endef
|
||||
|
||||
#******************************************************************************#
|
||||
# Messages #
|
||||
#******************************************************************************#
|
||||
# Build message
|
||||
define bmsg
|
||||
$(call msg,$1,$(color_green))
|
||||
endef
|
||||
|
||||
# Remove message
|
||||
define rmsg
|
||||
$(call msg,$1,$(color_red))
|
||||
endef
|
||||
|
||||
# Install message
|
||||
define imsg
|
||||
$(call msg,$1,$(color_yellow))
|
||||
endef
|
||||
|
||||
# End of file.
|
|
@ -1,81 +0,0 @@
|
|||
#!/usr/bin/make -f
|
||||
#******************************************************************************#
|
||||
# Include configuration #
|
||||
#******************************************************************************#
|
||||
-include Makefile.cfg
|
||||
|
||||
#******************************************************************************#
|
||||
# Project main information #
|
||||
#******************************************************************************#
|
||||
# Project name.
|
||||
NAME := cake.exe
|
||||
|
||||
# Maintainer information
|
||||
MAINTAINER_NAME := Thomas \"Cakeisalie5\" Touhey
|
||||
MAINTAINER_MAIL := thomas@touhey.fr
|
||||
|
||||
# Project license
|
||||
LICENSE := GPLv2
|
||||
|
||||
# Project version
|
||||
VERSION_MAJOR := 0
|
||||
VERSION_MINOR := 1
|
||||
INDEV := yes
|
||||
VERSION := $(VERSION_MAJOR).$(VERSION_MINOR)$(if $(INDEV),-indev)
|
||||
|
||||
#******************************************************************************#
|
||||
# Project directories #
|
||||
#******************************************************************************#
|
||||
# Headers directory - where all the headers are.
|
||||
INCDIR := ./include
|
||||
|
||||
# Sources directory - where all the source files are.
|
||||
SRCDIR := ./src
|
||||
|
||||
# Objects directory - where the objects will be put.
|
||||
OBJDIR := ./obj
|
||||
|
||||
# Gint lib directory
|
||||
GLIBDIR := ./libgint
|
||||
|
||||
# Gint include directory
|
||||
GINCDIR := ./libgint/include
|
||||
|
||||
#******************************************************************************#
|
||||
# Binary utilities #
|
||||
#******************************************************************************#
|
||||
# C Compiler
|
||||
CC := sh3eb-elf-gcc
|
||||
# - Check flags (for warnings enabling)
|
||||
CHKFLAGS := -Wall -Wextra
|
||||
# - More flags (for profiling, ...)
|
||||
#CMOREFLAGS :=
|
||||
# - All of the C compiler flags
|
||||
CFLAGS := -m3 -mb -Os -ffreestanding -I $(INCDIR) -I $(GINCDIR) $(CHKFLAGS) \
|
||||
-D AUTHOR="$(AUTHOR_NAME)" -D AUTHOR_MAIL="$(AUTHOR_MAIL)" \
|
||||
-D LICENSE="$(LICENSE)" -D VERSION="$(VERSION)" \
|
||||
$(CMOREFLAGS)
|
||||
|
||||
# Assembler
|
||||
AS := sh3eb-elf-as
|
||||
# Linker
|
||||
LD := sh3eb-elf-gcc
|
||||
# - Linker flags
|
||||
LDFLAGS := -nostdlib -T osupd.ld -L $(GLIBDIR) -lgint -lc -lgcc
|
||||
|
||||
# Maker.
|
||||
MAKE := make --no-print-directory -C
|
||||
# Object copier
|
||||
OBJCOPY := sh3eb-elf-objcopy
|
||||
# Directory maker
|
||||
MD := mkdir -p
|
||||
# File remover
|
||||
RM := rm -f
|
||||
|
||||
#******************************************************************************#
|
||||
# Look for sources #
|
||||
#******************************************************************************#
|
||||
# SOURCES
|
||||
SRC := $(basename $(notdir $(shell find $(SRCDIR) -name "*.[cs]")))
|
||||
|
||||
# END OF FILE
|
|
@ -1,40 +0,0 @@
|
|||
# cake.exe - communautary Update.Exe for CASIO calculators
|
||||
## Introduction
|
||||
There is a special command in CASIO's Communication Protocol 7.00: the 0x56
|
||||
command, considered by the community to be the "upload and run" command.
|
||||
|
||||
CASIO uses it to modify the OS on the calculator:
|
||||
- The tools uploads an UpdateExe kernel;
|
||||
- The OS checks the UpdateExe, transfers it to RAM and transfers
|
||||
full machine control to it;
|
||||
- The kernel sets up a Protocol 7 server;
|
||||
- The tool communicates with this server to make operations on the calculator
|
||||
(mainly on flash memory): backup the OS, flash a new OS, ...
|
||||
|
||||
Simon Lothar made his own for fxRemote, using bootcode functions for displaying
|
||||
and communicating (USB, Protocol 7).
|
||||
This project is a community-made update.exe to imitate proprietary CASIO ones
|
||||
and Simon Lothar's one.
|
||||
|
||||
## Restrictions
|
||||
In order to be SH3 and SH4 compatible, the size of the kernel musn't be
|
||||
greater than 64Kio. Also, a full independence from the OS and the bootcode
|
||||
should be seeked, so that this update.exe can also serve for flash-erasure
|
||||
operations - which may come in a very very long time.
|
||||
|
||||
Also, the binary should finish with an identification block --
|
||||
see `src/endblock.c` for details.
|
||||
|
||||
## Making dependencies
|
||||
| Name | Version |
|
||||
| -------------------------------------------------- | ------- |
|
||||
| [sh3eb-elf-gcc](https://gcc.gnu.org/) | >= 4.9 |
|
||||
| [binutils](https://www.gnu.org/software/binutils/) | >= 2.25 |
|
||||
|
||||
## Building
|
||||
|
||||
Just `make`.
|
||||
|
||||
Other useful targets:
|
||||
- `mostlyclean`, `clean`: remove built files.
|
||||
- `re`: remake.
|
|
@ -1,8 +0,0 @@
|
|||
# TODO in Update.exe
|
||||
## As soon as possible
|
||||
- Integrate gint (with USB implemented)
|
||||
- Make a P7 server
|
||||
|
||||
## Later
|
||||
- Find out update.exe-specific commands
|
||||
- Implement flash commands
|
|
@ -1,97 +0,0 @@
|
|||
#!/bin/sh
|
||||
cd "$(dirname "$0")"
|
||||
#******************************************************************************#
|
||||
# Defaults #
|
||||
#******************************************************************************#
|
||||
# Project variables
|
||||
name="$(make -s getname)"
|
||||
version="$(make -s getversion)"
|
||||
|
||||
# Maintainer
|
||||
maintainer="$(make -s getmaintainer)"
|
||||
|
||||
# Make options
|
||||
make_full_log=
|
||||
|
||||
#******************************************************************************#
|
||||
# Help message #
|
||||
#******************************************************************************#
|
||||
usage() {
|
||||
cat <<EOF
|
||||
\`configure\` configures ${name} to adapt to systems that aren't mine.
|
||||
Usage: $0 [OPTION]
|
||||
|
||||
Defaults for the options are specified in brackets.
|
||||
|
||||
General options:
|
||||
--help display this help and exit
|
||||
--version display version information and quit
|
||||
--make-full-log display full commands while making
|
||||
|
||||
Report bugs to ${maintainer}.
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
#******************************************************************************#
|
||||
# Version message #
|
||||
#******************************************************************************#
|
||||
version() {
|
||||
cat <<EOF
|
||||
${name} configure script v${version}
|
||||
Hand-written by Thomas "Cakeisalie5" Touhey.
|
||||
|
||||
This configure script is free software.
|
||||
There is NO warranty; not even for MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE.
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
#******************************************************************************#
|
||||
# Check for help and version #
|
||||
#******************************************************************************#
|
||||
put_version=
|
||||
put_help=
|
||||
for arg ; do case "$arg" in
|
||||
--help|-h) put_help=1 ;;
|
||||
--version|-v) put_version=1 ;;
|
||||
esac; done
|
||||
[ $put_version ] && version
|
||||
[ $put_help ] && usage
|
||||
|
||||
#******************************************************************************#
|
||||
# Parse arguments #
|
||||
#******************************************************************************#
|
||||
for arg ; do case "$arg" in
|
||||
--make-full-log) make_full_log=yes ;;
|
||||
*) echo "$arg: didn't read" ;;
|
||||
esac; done
|
||||
|
||||
#******************************************************************************#
|
||||
# Create Makefile configuration #
|
||||
#******************************************************************************#
|
||||
# Clean
|
||||
make mrproper MAKE_FULL_LOG=y 1>/dev/null
|
||||
|
||||
# Write
|
||||
exec 3>&1 1>Makefile.cfg
|
||||
cat <<EOF
|
||||
#!/usr/bin/make -f
|
||||
#******************************************************************************#
|
||||
# Makefile configuration generated by ./configure #
|
||||
#******************************************************************************#
|
||||
# Configuration version and messages configuration
|
||||
CONFIG_VERSION := $version
|
||||
MAKE_FULL_LOG := $make_full_log
|
||||
|
||||
# End of file.
|
||||
EOF
|
||||
exec 1>&3 3>&-
|
||||
chmod +x Makefile.cfg
|
||||
|
||||
# Finish
|
||||
echo "Configuration loaded, you can make now."
|
||||
|
||||
# End of file.
|
|
@ -1,10 +0,0 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* main.h |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project: cake.exe | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2017/01/16 18:05:44 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
# Build directory
|
||||
build/**
|
||||
|
||||
# Sublime Text files
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
|
||||
# Object files.
|
||||
*.o
|
||||
|
||||
# Some notes.
|
||||
LIBC
|
||||
|
||||
# Output files
|
||||
libc.a
|
||||
libgint.a
|
||||
gintdemo.g1a
|
||||
|
||||
# Configuration files
|
||||
gcc.cfg
|
|
@ -1,210 +0,0 @@
|
|||
#! /usr/bin/make -f
|
||||
#---
|
||||
#
|
||||
# gint project Makefile.
|
||||
#
|
||||
#---
|
||||
|
||||
|
||||
|
||||
#---
|
||||
# Project variables.
|
||||
#---
|
||||
|
||||
# Modules
|
||||
modules-gint = core clock keyboard mmu mpu rtc screen timer \
|
||||
bopti display gray tales events
|
||||
modules-libc = setjmp string stdio stdlib time
|
||||
|
||||
# Targets
|
||||
target-g1a = gintdemo.g1a
|
||||
target-lib = libgint.a
|
||||
target-std = libc.a
|
||||
|
||||
# Tools
|
||||
cc = sh3eb-elf-gcc
|
||||
as = sh3eb-elf-as
|
||||
ar = sh3eb-elf-ar
|
||||
ob = sh3eb-elf-objcopy
|
||||
wr = g1a-wrapper
|
||||
|
||||
# Flags
|
||||
cflags = -m3 -mb -nostdlib -I include -ffreestanding -std=c11 -Os \
|
||||
-W -Wall -Wextra -pedantic @gcc.cfg
|
||||
|
||||
# Demo application (could be done better)
|
||||
demo-src = $(notdir $(wildcard demo/*.[cs]))
|
||||
demo-dep = $(wildcard demo/*.h)
|
||||
demo-ld = demo/gintdemo.ld
|
||||
demo-icon = demo/icon.bmp
|
||||
demo-res = $(notdir $(wildcard demo/resources/*))
|
||||
demo-obj = $(patsubst %,build/demo_%.o,$(demo-src) $(demo-res))
|
||||
demo-elf = build/gintdemo.elf
|
||||
demo-bin = build/gintdemo.bin
|
||||
demo-libs = -L. -lgint -lc -lgcc
|
||||
|
||||
# Specific objects
|
||||
obj-lib-spec = build/display_font_system.bmp.o
|
||||
obj-std-spec =
|
||||
|
||||
# Configuration files
|
||||
config = gcc.cfg
|
||||
|
||||
#---
|
||||
# Automatic variables.
|
||||
#---
|
||||
|
||||
# Modules are subfolders of src/.
|
||||
modules = $(modules-gint) $(modules-libc)
|
||||
|
||||
define n
|
||||
# This is a newline character.
|
||||
|
||||
endef
|
||||
|
||||
ifeq ("$(wildcard $(config))","")
|
||||
$(error "Configuration files are missing. Did you ./configure?")
|
||||
endif
|
||||
|
||||
# Module-scope variables.
|
||||
$(foreach mod, $(modules), $(eval \
|
||||
mod-$(mod)-c = $(notdir $(wildcard src/$(mod)/*.c)) $n\
|
||||
mod-$(mod)-asm = $(notdir $(wildcard src/$(mod)/*.s)) $n\
|
||||
mod-$(mod)-src = $$(mod-$(mod)-c)$$(mod-$(mod)-asm) $n\
|
||||
mod-$(mod)-obj = $$(patsubst %,build/$(mod)_%.o,$$(mod-$(mod)-src)) \
|
||||
))
|
||||
|
||||
# Target-scope variables.
|
||||
obj-std = $(foreach mod,$(modules-libc),$(mod-$(mod)-obj)) $(obj-std-spec)
|
||||
obj-lib = $(foreach mod,$(modules-gint),$(mod-$(mod)-obj)) $(obj-lib-spec)
|
||||
|
||||
# Dependencies
|
||||
hdr-dep = $(wildcard include/*.h include/internals/*.h)
|
||||
|
||||
|
||||
|
||||
#---
|
||||
# Rule templates.
|
||||
#---
|
||||
|
||||
#ifndef VERBOSE
|
||||
#$(note "default full log")
|
||||
#VERBOSE =
|
||||
#endif
|
||||
|
||||
# C source file template:
|
||||
# $1 module name
|
||||
# $2 filename
|
||||
# $3 dependencies
|
||||
define rule-c-source
|
||||
build/$1_$2.o: src/$1/$2 $3 $(config)
|
||||
$(if $(VERBOSE),,@ printf '\e[34;1msrc \u00bb\e[0m cc $$<\n')
|
||||
$(if $(VERBOSE),,@) $(cc) -c $$< -o $$@ $(cflags) -I src/$1
|
||||
endef
|
||||
|
||||
# asm source file template:
|
||||
# $1 module name
|
||||
# $2 filename
|
||||
define rule-asm-source
|
||||
build/$1_$2.o: src/$1/$2 $(config)
|
||||
$(if $(VERBOSE),,@ printf '\e[34;1msrc \u00bb\e[0m as $$<\n')
|
||||
$(if $(VERBOSE),,@) $(as) -c $$< -o $$@
|
||||
endef
|
||||
|
||||
|
||||
|
||||
#---
|
||||
# Building.
|
||||
#---
|
||||
|
||||
# Generic rules
|
||||
|
||||
all: $(config) $(target-std) $(target-lib) $(target-g1a)
|
||||
@ printf '\e[32;1mmsg \u00bb\e[0m All done!\n'
|
||||
|
||||
build:
|
||||
$(if $(VERBOSE),,@ printf '\e[35;1mdir \u00bb\e[0m mkdir $@\n')
|
||||
$(if $(VERBOSE),,@) mkdir -p $@
|
||||
|
||||
$(obj-std) $(obj-lib) $(demo-obj): | build
|
||||
|
||||
$(target-std): $(config) $(obj-std)
|
||||
$(if $(VERBOSE),,@ printf '\e[35;1mlib \u00bb\e[0m ar $@\n')
|
||||
$(if $(VERBOSE),,@) $(ar) rcs $@ $(obj-std)
|
||||
@ printf '\e[32;1mmsg \u00bb\e[0m Succesfully built libc ('
|
||||
@ printf $$(stat -c %s $@)
|
||||
@ printf ' bytes)\n\n'
|
||||
|
||||
$(target-lib): $(config) $(target-std) $(obj-lib)
|
||||
$(if $(VERBOSE),,@ printf '\e[35;1mlib \u00bb\e[0m ar $@\n')
|
||||
$(if $(VERBOSE),,@) $(ar) rcs $@ $(obj-lib)
|
||||
@ printf '\e[32;1mmsg \u00bb\e[0m Succesfully built libgint ('
|
||||
@ printf $$(stat -c %s $@)
|
||||
@ printf ' bytes)\n\n'
|
||||
|
||||
$(target-g1a): $(config) $(target-std) $(target-lib) $(demo-obj)
|
||||
$(if $(VERBOSE),,@ printf '\e[35;1mexe \u00bb\e[0m ld -o $(demo-elf)\n')
|
||||
$(if $(VERBOSE),,@) $(cc) -o $(demo-elf) $(cflags) -T $(demo-ld) $(demo-obj) $(demo-libs)
|
||||
$(if $(VERBOSE),,@ printf '\e[35;1mexe \u00bb\e[0m objcopy -o $(demo-bin)\n')
|
||||
$(if $(VERBOSE),,@) $(ob) -R .comment -R .bss -O binary $(demo-elf) $(demo-bin)
|
||||
$(if $(VERBOSE),,@ printf '\e[35;1mexe \u00bb\e[0m g1a-wrapper -o $@\n')
|
||||
$(if $(VERBOSE),,@) $(wr) $(demo-bin) -o $@ -i $(demo-icon)
|
||||
@ printf '\e[32;1mmsg \u00bb\e[0m Succesfully built demo application ('
|
||||
@ printf $$(stat -c %s $@)
|
||||
@ printf ' bytes)\n\n'
|
||||
|
||||
# Automated rules
|
||||
|
||||
$(foreach mod,$(modules), \
|
||||
$(foreach source,$(mod-$(mod)-c), $(eval \
|
||||
$(call rule-c-source,$(mod),$(source),$(hdr-dep)))) \
|
||||
$(foreach source,$(mod-$(mod)-asm), $(eval \
|
||||
$(call rule-asm-source,$(mod),$(source)))) \
|
||||
)
|
||||
|
||||
# Specific rules
|
||||
|
||||
# This one should not be optimized. It makes __attribute__((interrupt_handler))
|
||||
# buggy... maybe. Anyway there's some bug in this file that I can't fix now.
|
||||
build/core_gint.c.o: src/core/gint.c $(mod-core-dep) $(config)
|
||||
$(if $(VERBOSE),,@ printf '\e[34;1msrc \u00bb\e[0m cc $<\n')
|
||||
$(if $(VERBOSE),,@) $(cc) -c $< -o $@ $(cflags) -I src/core -O0
|
||||
|
||||
build/display_font_system.bmp.o: src/display/font_system.bmp
|
||||
$(if $(VERBOSE),,@ printf '\e[36;1mres \u00bb\e[0m fxconv $<\n')
|
||||
$(if $(VERBOSE),,@) fxconv $< -o $@ --font -n gint_font_system
|
||||
|
||||
# Demo application
|
||||
|
||||
build/demo_%.c.o: demo/%.c $(hdr-dep) $(demo-dep) $(config)
|
||||
$(if $(VERBOSE),,@ printf '\e[34;1msrc \u00bb\e[0m cc $<\n')
|
||||
$(if $(VERBOSE),,@) $(cc) -c $< -o $@ $(cflags)
|
||||
|
||||
build/demo_font_%.bmp.o: demo/resources/font_%.bmp
|
||||
$(if $(VERBOSE),,@ printf '\e[36;1mres \u00bb\e[0m fxconv $<\n')
|
||||
$(if $(VERBOSE),,@) fxconv $< -o $@ --font -n $(patsubst demo/resources/%.bmp,res_%,$<)
|
||||
|
||||
build/demo_%.bmp.o: demo/resources/%.bmp
|
||||
$(if $(VERBOSE),,@ printf '\e[36;1mres \u00bb\e[0m fxconv $<\n')
|
||||
$(if $(VERBOSE),,@) fxconv $< -o $@ -n $(patsubst demo/resources/%.bmp,res_%,$<)
|
||||
|
||||
|
||||
|
||||
#---
|
||||
# Cleaning and others.
|
||||
#---
|
||||
|
||||
clean:
|
||||
@ rm -rf build
|
||||
|
||||
mrproper: clean
|
||||
@ rm -f $(target-g1a) $(target-lib) $(target-std)
|
||||
@ rm -f $(config)
|
||||
|
||||
distclean: mrproper
|
||||
|
||||
install:
|
||||
p7 send -f $(target-g1a)
|
||||
|
||||
|
||||
.PHONY: all clean mrproper distclean install help
|
|
@ -1,72 +0,0 @@
|
|||
gint project
|
||||
============
|
||||
|
||||
gint (pronounce 'guin') is a low-level library for fx-9860G calculators. It
|
||||
provides the tools needed to develop programs under Linux using the gcc
|
||||
toolchain (sh3eb-elf).
|
||||
|
||||
By the way, gint is free software; you may use it for any purpose, share it,
|
||||
modify it and share you changes. No credit of any kind is needed, though
|
||||
appreciated.
|
||||
|
||||
|
||||
|
||||
Interrupt handler
|
||||
-----------------
|
||||
|
||||
The interrupt handler is the lowest-level part of the library. It directly
|
||||
accesses the peripheral modules and performs keyboard analyzes, swaps screen
|
||||
buffers, etc.
|
||||
|
||||
gint does not allow user programs to use their own handlers. However, it is
|
||||
possible to map interrupt-driven events to user callbacks using the public API
|
||||
(which is not possible with the system's interrupt handler). This may be
|
||||
particularly useful for timers and RTC (the 16 Hz interrupt can be used as a
|
||||
basis for a physical engine).
|
||||
|
||||
|
||||
|
||||
Public Interface
|
||||
----------------
|
||||
|
||||
gint's API provides access to keyboard, timers, clock and more. It does some
|
||||
powerful drawing and offers reliable multi-getkey, a gray engine, facilitates
|
||||
register access and implements a few standard functions.
|
||||
|
||||
|
||||
|
||||
Building and installing
|
||||
-----------------------
|
||||
|
||||
There are some dependencies:
|
||||
* The `sh3eb-elf` toolchain somewhere in the PATH
|
||||
* The fxSDK installed and available in the PATH
|
||||
|
||||
The easiest way to build gint is simply to enter a terminal and execute `make`.
|
||||
This will build the following components :
|
||||
* `libgint.a`, the gint library
|
||||
* `libc.a`, a (very) few standard procedures
|
||||
* `gintdemo.g1a`, a test application
|
||||
|
||||
The common `clean`, `mrproper`, and `distclean` rules will clean the directory.
|
||||
|
||||
|
||||
|
||||
Source organization
|
||||
-------------------
|
||||
|
||||
gint is made of *modules*. Each module may have any of the following
|
||||
components:
|
||||
* A header file in `/include`
|
||||
* An internal header file in `/include/internals`
|
||||
* Single-function source files in `/src/module`: to avoid linking against the
|
||||
whole library, some functions have their own object files. Their names are
|
||||
those of the functions.
|
||||
* Other source files in `/src/module`: contain multiple functions that always
|
||||
work together, or are lightweight enough not to be separated. Their names
|
||||
often begin with `module_`.
|
||||
* Other files in `/src/module`: the `display` module contains a font, I think.
|
||||
|
||||
The demo application is in the `demo` directory.
|
||||
|
||||
The `doc` folder contains some documentation.
|
|
@ -1,33 +0,0 @@
|
|||
Bugs to fix:
|
||||
- Left-vram overflow when rendering text
|
||||
- A few key hits ignored after leaving the application (could not reproduce)
|
||||
- Lost keyboard control at startup (could not reproduce)
|
||||
- Back-light issues (0xa400012c on SH3, 0xa4050138 on SH4)
|
||||
|
||||
Simple improvements:
|
||||
- bopti: Monochrome bitmaps blending modes
|
||||
- bopti: Partial transparency
|
||||
- demo: Try 284x124 at (-60, -28) (all disadvantages)
|
||||
- display: Rectangle-based drawing functions
|
||||
- tales: Test all font encodings
|
||||
- time: Compute CLOCKS_PER_SEC
|
||||
- timer: Add duration and frequency settings
|
||||
- core: Add VBR handlers debugging information (if possible)
|
||||
- core: Implement all callbacks and a complete user API
|
||||
|
||||
Modules to implement:
|
||||
- Serial communication
|
||||
- Sound playback and synthesizing
|
||||
- Handle errors within errno
|
||||
|
||||
Things to investigate:
|
||||
- Packed bit fields alignment
|
||||
- Registers that may need to be saved within setjmp()
|
||||
- Registers that may need to be saved and restored by gint
|
||||
- Possible bug when optimizing __attribute__((interrupt_handler))
|
||||
|
||||
Configuration:
|
||||
- ATEXIT_MAX (16)
|
||||
- RTC_CB_ARRAY_SIZE (5)
|
||||
- EVENTS_QUEUE_SIZE (64)
|
||||
- GINT_NO_SYSCALLS (undefined)
|
|
@ -1,78 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
declare -A conf
|
||||
conf[ATEXIT_MAX]=16
|
||||
conf[RTC_CB_ARRAY_SIZE]=5
|
||||
conf[EVENTS_QUEUE_SIZE]=64
|
||||
conf[GINT_NO_SYSCALLS]=
|
||||
fail=false
|
||||
output="gcc.cfg"
|
||||
|
||||
help()
|
||||
{
|
||||
cat << EOF
|
||||
Configuration script for the gint library.
|
||||
|
||||
Options that affect the behavior of the library:
|
||||
--no-syscalls [default: false]
|
||||
Never use syscalls. Expect some trouble with the malloc() function...
|
||||
Do not trigger this option unless you know what you are doing.
|
||||
|
||||
Options that customize size limits:
|
||||
--atexit-max=<integer> [default: 16]
|
||||
Number of exit handlers that can be registered by atexit().
|
||||
--rtc-callbacks=<integer> [default: 5]
|
||||
Number of RTC callbacks that can be registered.
|
||||
--events-queue-size=<integer> [default: 64]
|
||||
Number of events simultaneously stored in the event queue.
|
||||
EOF
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
for arg; do case "$arg" in
|
||||
-h | --help) help;;
|
||||
--no-syscalls) conf[GINT_NO_SYSCALLS]=true;;
|
||||
|
||||
--atexit-max=*)
|
||||
size=${arg#*=}
|
||||
if [[ $size == +([0-9]) ]]; then
|
||||
conf[ATEXIT_MAX]=$size
|
||||
else echo "error: --atexit-max expects an integer value"
|
||||
fail=true; fi;;
|
||||
--rtc-callbacks=*)
|
||||
size=${arg#*=}
|
||||
if [[ $size == +([0-9]) ]]; then
|
||||
conf[RTC_CB_ARRAY_SIZE]=$size
|
||||
else echo "error: --rtc-callbacks expects an integer value"
|
||||
fail=true; fi;;
|
||||
--events-queue-size=*)
|
||||
size=${arg#*=}
|
||||
if [[ $size == +([0-9]) ]]; then
|
||||
conf[EVENTS_QUEUE_SIZE]=$size
|
||||
else echo "error: --events-queue-size expects an integer value"
|
||||
fail=true; fi;;
|
||||
|
||||
--atexit-max | --rtc-callbacks | --events-queue-size)
|
||||
echo "error: syntax for $arg is $arg=<integer-value>";;
|
||||
|
||||
*)
|
||||
echo "error: unrecognized argument '$arg'"; fail=true;;
|
||||
esac; done
|
||||
|
||||
output_config()
|
||||
{
|
||||
echo "-D ATEXIT_MAX=${conf[ATEXIT_MAX]}"
|
||||
echo "-D RTC_CB_ARRAY_SIZE=${conf[RTC_CB_ARRAY_SIZE]}"
|
||||
echo "-D EVENTS_QUEUE_SIZE=${conf[EVENTS_QUEUE_SIZE]}"
|
||||
if [ "${conf[GINT_NO_SYSCALLS]}" != "" ]; then
|
||||
echo "-D GINT_NO_SYSCALLS"
|
||||
fi
|
||||
}
|
||||
|
||||
if $fail; then
|
||||
echo "Configuration has not been modified."
|
||||
else
|
||||
output_config > $output
|
||||
echo "Configuration details have been output to file $output."
|
||||
fi
|
|
@ -1,531 +0,0 @@
|
|||
#include "gintdemo.h"
|
||||
|
||||
#include <mpu.h>
|
||||
#include <gint.h>
|
||||
#include <keyboard.h>
|
||||
#include <display.h>
|
||||
#include <gray.h>
|
||||
|
||||
#include <internals/stdio.h>
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// A few procedures for displaying text aligned on a 21*8 grid.
|
||||
// Not really beautiful... but this will do.
|
||||
//---
|
||||
|
||||
void locate(int x, int y, const char *str)
|
||||
{
|
||||
if(x < 1 || x > 21 || y < 1 || y > 8) return;
|
||||
if(gray_runs()) gtext(x * 6 - 5, y * 8 - 8, str);
|
||||
else dtext(x * 6 - 5, y * 8 - 8, str);
|
||||
}
|
||||
|
||||
void print(int x, int y, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
__printf(0, format, args);
|
||||
va_end(args);
|
||||
|
||||
locate(x, y, __stdio_buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
printf_test()
|
||||
Tests formatting functions.
|
||||
|
||||
void printf_test(void)
|
||||
{
|
||||
dclear();
|
||||
locate(1, 1, "Formatted printing");
|
||||
|
||||
print(2, 3, "%%4.2d 5 :\"%4.2d\"", 5);
|
||||
print(2, 4, "%%-3c '&':\"%-3c\"", '&');
|
||||
print(2, 5, "%%#05x 27 :\"%#05x\"", 27);
|
||||
print(2, 6, "%%1s \"tr\":\"%1s\"", "tr");
|
||||
print(2, 7, "%%6p NULL :\"%6p\"", NULL);
|
||||
|
||||
dupdate();
|
||||
while(getkey() != KEY_EXIT);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
static const unsigned char screen[1024] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 7, 159, 0, 0, 1, 192, 0, 0, 0, 0, 0, 121, 240, 0, 0, 0,
|
||||
31, 191, 192, 0, 3, 224, 27, 216, 0, 0, 1, 251, 252, 0, 0, 0, 57, 247, 222,
|
||||
30, 7, 240, 36, 36, 62, 25, 131, 159, 24, 255, 129, 224, 0, 227, 142, 126, 1,
|
||||
192, 45, 172, 127, 127, 192, 14, 1, 255, 199, 224, 0, 227, 140, 240, 1, 192,
|
||||
26, 88, 115, 127, 224, 14, 57, 221, 207, 0, 0, 227, 13, 192, 1, 192, 34, 68,
|
||||
120, 30, 0, 14, 25, 156, 220, 0, 0, 227, 253, 252, 1, 192, 36, 36, 126, 28,
|
||||
0, 14, 219, 156, 223, 192, 0, 227, 253, 252, 1, 192, 36, 36, 31, 12, 0, 46,
|
||||
27, 140, 223, 192, 0, 227, 141, 193, 193, 192, 40, 20, 7, 140, 0, 206, 25, 140,
|
||||
220, 28, 0, 227, 140, 225, 129, 199, 24, 24, 99, 156, 1, 14, 25, 204, 206, 24,
|
||||
0, 227, 142, 127, 1, 195, 39, 228, 255, 156, 2, 14, 24, 237, 199, 240, 1, 247,
|
||||
222, 62, 1, 198, 44, 44, 223, 30, 2, 31, 28, 237, 131, 224, 1, 224, 0, 0, 3,
|
||||
254, 27, 216, 0, 0, 4, 30, 0, 0, 0, 0, 3, 192, 0, 0, 7, 252, 0, 0, 0, 0, 4,
|
||||
60, 1, 249, 240, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 4, 0, 97, 240, 56, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 224, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
4, 0, 47, 192, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 32, 255, 128, 63, 128,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 32, 255, 0, 48, 78, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 15, 176, 255, 0, 112, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 8, 56, 255, 0,
|
||||
96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 8, 60, 255, 0, 224, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 130, 56, 126, 255, 3, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 192,
|
||||
62, 255, 15, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 14, 191, 255, 192, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 6, 129, 255, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 6, 0, 255, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 7, 128, 63, 192,
|
||||
0, 0, 96, 1, 224, 1, 0, 0, 0, 2, 0, 0, 7, 0, 31, 192, 0, 0, 95, 1, 11, 68, 88,
|
||||
0, 0, 4, 0, 0, 7, 128, 31, 192, 0, 1, 192, 129, 204, 85, 100, 0, 0, 8, 0, 0,
|
||||
15, 128, 63, 224, 0, 0, 95, 1, 8, 85, 68, 0, 1, 144, 0, 0, 31, 128, 143, 224,
|
||||
64, 0, 96, 1, 232, 41, 68, 0, 2, 96, 0, 31, 255, 129, 7, 248, 96, 0, 0, 0, 0,
|
||||
0, 0, 0, 4, 0, 0, 96, 254, 129, 7, 254, 96, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 128,
|
||||
254, 131, 135, 255, 224, 0, 0, 1, 192, 64, 16, 0, 8, 0, 7, 0, 254, 131, 255,
|
||||
63, 224, 0, 0, 1, 38, 113, 208, 0, 8, 0, 13, 0, 222, 147, 254, 31, 224, 0, 0,
|
||||
1, 41, 74, 80, 0, 8, 0, 25, 0, 222, 67, 254, 31, 160, 0, 0, 1, 41, 74, 80, 0,
|
||||
12, 0, 49, 0, 222, 19, 254, 62, 48, 0, 0, 1, 198, 113, 208, 0, 2, 0, 32, 128,
|
||||
222, 195, 255, 252, 56, 0, 0, 0, 0, 0, 0, 0, 2, 0, 124, 64, 220, 151, 135, 248,
|
||||
127, 0, 0, 0, 0, 0, 0, 0, 2, 0, 66, 32, 221, 223, 7, 240, 255, 0, 0, 0, 0, 0,
|
||||
0, 0, 2, 0, 129, 23, 93, 159, 15, 241, 131, 0, 0, 0, 0, 0, 0, 0, 4, 0, 128,
|
||||
136, 217, 95, 3, 226, 9, 0, 0, 1, 240, 0, 0, 0, 4, 0, 128, 72, 89, 95, 129,
|
||||
228, 18, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 72, 73, 127, 128, 224, 36, 0, 0, 0, 0,
|
||||
0, 0, 0, 28, 1, 0, 76, 129, 127, 192, 96, 8, 0, 0, 0, 0, 0, 0, 0, 16, 1, 0,
|
||||
231, 203, 124, 96, 64, 0, 0, 0, 0, 0, 0, 0, 0, 16, 1, 1, 28, 123, 240, 12, 64,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 16, 1, 2, 28, 143, 128, 15, 192, 7, 0, 0, 0, 0, 0, 0,
|
||||
0, 16, 1, 4, 17, 143, 24, 15, 192, 14, 0, 0, 0, 0, 0, 0, 0, 28, 1, 4, 1, 135,
|
||||
24, 31, 192, 24, 0, 0, 0, 0, 0, 0, 0, 18, 1, 62, 1, 135, 248, 63, 224, 192,
|
||||
0, 0, 0, 0, 0, 0, 0, 35, 1, 195, 1, 135, 128, 254, 126, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 35, 193, 131, 195, 135, 255, 248, 112, 1, 0, 0, 0, 0, 0, 0, 0, 67, 241, 131,
|
||||
14, 207, 255, 192, 224, 3, 0, 0, 0, 0, 0, 0, 3, 67, 15, 143, 56, 255, 7, 1,
|
||||
224, 7, 0, 0, 0, 0, 0, 0, 28, 130, 7, 255, 112, 204, 7, 131, 224, 31, 0, 0,
|
||||
0, 0, 0, 0, 32, 134, 30, 29, 120, 156, 7, 255, 224, 127, 0, 0, 0, 0, 0, 63,
|
||||
197, 206, 60, 56, 192, 248, 15, 255, 248, 255, 0, 0, 0, 0, 0, 120, 5, 227, 248,
|
||||
56, 195, 248, 127, 191, 254, 63, 0, 0, 0, 0, 7, 254, 255, 193, 255, 15, 193,
|
||||
255, 15, 31, 252, 31 };
|
||||
|
||||
void ML_bmp_or_cl(const unsigned char *bmp, int x, int y, int width, int height)
|
||||
{
|
||||
unsigned short line;
|
||||
char shift, *screen, *p;
|
||||
int i, j, real_width, begin_x, end_x, begin_y, end_y;
|
||||
char bool1=1, bool2=1, bool3;
|
||||
if(!bmp || x<1-width || x>127 || y<1-height || y>63 || height<1 || width<1) return;
|
||||
p = (char*)&line;
|
||||
real_width = (width-1>>3<<3)+8;
|
||||
if(y < 0) begin_y = -y;
|
||||
else begin_y = 0;
|
||||
if(y+height > 64) end_y = 64-y;
|
||||
else end_y = height;
|
||||
shift = 8-(x&7);
|
||||
if(x<0)
|
||||
{
|
||||
begin_x = -x>>3;
|
||||
if(shift != 8) bool1 = 0;
|
||||
} else begin_x = 0;
|
||||
if(x+real_width > 128) end_x = 15-(x>>3), bool2 = 0;
|
||||
else end_x = real_width-1>>3;
|
||||
bool3 = (end_x == real_width-1>>3);
|
||||
screen = display_getCurrentVRAM()+(y+begin_y<<4)+(x>>3);
|
||||
|
||||
for(i=begin_y ; i<end_y ; i++)
|
||||
{
|
||||
if(begin_x < end_x)
|
||||
{
|
||||
line = bmp[i*(real_width>>3)+begin_x] << shift;
|
||||
if(bool1) screen[begin_x] |= *p;
|
||||
if(shift!=8) screen[begin_x+1] |= *(p+1);
|
||||
for(j=begin_x+1 ; j<end_x ; j++)
|
||||
{
|
||||
line = bmp[i*(real_width>>3)+j] << shift;
|
||||
screen[j] |= *p;
|
||||
if(shift!=8) screen[j+1] |= *(p+1);
|
||||
}
|
||||
}
|
||||
line = bmp[i*(real_width>>3)+end_x];
|
||||
if(bool3) line &= -1<<real_width-width;
|
||||
line <<= shift;
|
||||
if(begin_x < end_x || bool1) screen[end_x] |= *p;
|
||||
if(bool2) screen[end_x+1] |= *(p+1);
|
||||
screen += 16;
|
||||
}
|
||||
}
|
||||
|
||||
#include <internals/timer.h>
|
||||
void debug(void)
|
||||
{
|
||||
extern Image res_screen_start;
|
||||
struct mod_tmu *timer;
|
||||
int time1, time2;
|
||||
int i;
|
||||
|
||||
timer_get(TIMER_USER, &timer, NULL);
|
||||
|
||||
dclear();
|
||||
ML_bmp_or_cl(screen, 1, 1, 128, 64);
|
||||
dupdate();
|
||||
getkey();
|
||||
|
||||
dclear();
|
||||
dimage(&res_screen_start, 1, 1);
|
||||
dupdate();
|
||||
getkey();
|
||||
|
||||
dclear();
|
||||
dtext("ML...", 2, 2);
|
||||
dupdate();
|
||||
|
||||
timer_start(TIMER_USER, 0x0fffffff, TIMER_Po_4, NULL, 0);
|
||||
for(i = 0; i < 1000; i++) ML_bmp_or_cl(screen, 1, 1, 128, 64);
|
||||
time1 = timer->TCNT;
|
||||
timer_stop(TIMER_USER);
|
||||
time1 = 0x0fffffff - time1;
|
||||
|
||||
dclear();
|
||||
dtext("gint...", 2, 2);
|
||||
dupdate();
|
||||
|
||||
timer_start(TIMER_USER, 0x0fffffff, TIMER_Po_4, NULL, 0);
|
||||
for(i = 0; i < 1000; i++) dimage(&res_screen_start, 1, 1);
|
||||
time2 = timer->TCNT;
|
||||
timer_stop(TIMER_USER);
|
||||
time2 = 0x0fffffff - time2;
|
||||
|
||||
dclear();
|
||||
print_hex(time1, 2, 2);
|
||||
print_hex(time2, 2, 9);
|
||||
dupdate();
|
||||
while(getkey() != KEY_EXIT);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
tlb_debug()
|
||||
Displays the TLB contents and some information. Only available for
|
||||
SH7705, because the SH7305's TLB is much more complicated.
|
||||
|
||||
void tlb_debug(void)
|
||||
{
|
||||
// Entry address address (pointer in the address array), entry data
|
||||
// address (pointer in the data address), and their contents.
|
||||
unsigned int address, data, a, d;
|
||||
// Virtual page number and physical page number.
|
||||
unsigned int vpn, ppn;
|
||||
// Contents of register MMUCR.
|
||||
unsigned mmucr;
|
||||
|
||||
int i, r, key = 0;
|
||||
int way = 0, entry = 0;
|
||||
int pointer_base;
|
||||
|
||||
const char *protection[] = { "pr", "prw", "ar", "arw" };
|
||||
mmucr = *((volatile unsigned int *)gint_reg(Register_MMUCR));
|
||||
|
||||
dclear();
|
||||
locate("MMU register info", 1, 1);
|
||||
locate("MMUCR.IX = ", 2, 3);
|
||||
locate(mmucr & 0x02 ? "1" : "0", 13, 3);
|
||||
dupdate();
|
||||
getkey();
|
||||
|
||||
while(key != KEY_EXIT && way < 4)
|
||||
{
|
||||
dclear();
|
||||
|
||||
print(1, 1, "TLB way=%d %d-%d", way, entry,
|
||||
entry > 29 ? 31 : entry + 2);
|
||||
|
||||
for(i = 0; i < 3 && entry < 32; i++, entry++)
|
||||
{
|
||||
address = 0xf2000000 | (entry << 12) | (way << 8);
|
||||
data = 0xf3000000 | (entry << 12) | (way << 8);
|
||||
|
||||
a = *((volatile unsigned int *)address);
|
||||
d = *((volatile unsigned int *)data);
|
||||
|
||||
ppn = (d >> 10) & 0x00007ffff;
|
||||
// 4-kbyte page
|
||||
if(d & 0x08)
|
||||
{
|
||||
vpn = (a >> 12) | entry;
|
||||
pointer_base = vpn << 12;
|
||||
}
|
||||
// 1-kbyte page
|
||||
else
|
||||
{
|
||||
vpn = (a >> 10) | (entry << 2);
|
||||
pointer_base = vpn << 10;
|
||||
}
|
||||
|
||||
r = 2 * i + 3;
|
||||
print(1, r, "%08x :%08x", pointer_base, ppn << 10);
|
||||
|
||||
r++;
|
||||
locate((d & 0x08) ? "4k" : "1k", 1, r);
|
||||
print(5, r, "pr=%s", protection[(d >> 5) & 3]);
|
||||
locate((d & 0x02) ? "shared" : "exclusive", 13, r);
|
||||
}
|
||||
|
||||
if(entry == 32) entry = 0, way++;
|
||||
|
||||
dupdate();
|
||||
key = getkey();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
main_menu()
|
||||
Displays the main menu and returns user's choice: 0 for [EXIT],
|
||||
application numbers otherwise. Sets the ctaegory and application
|
||||
number.
|
||||
*/
|
||||
void main_menu(int *category, int *app)
|
||||
{
|
||||
//---
|
||||
// Quite a few things to declare...
|
||||
//---
|
||||
|
||||
extern Image res_opt_menu;
|
||||
|
||||
const char *mpu, *mpu_names[] = {
|
||||
"Unknown",
|
||||
"SH7337",
|
||||
"SH7355",
|
||||
"SH7305",
|
||||
"SH7724",
|
||||
"[error]"
|
||||
};
|
||||
|
||||
const char *list_tests[] = {
|
||||
"Keyboard",
|
||||
"Gray engine",
|
||||
"Image rendering",
|
||||
"Text rendering",
|
||||
"Real-time clock",
|
||||
"Clocks and timers",
|
||||
NULL
|
||||
};
|
||||
const char *list_perfs[] = {
|
||||
"Image rendering",
|
||||
"Text rendering",
|
||||
NULL
|
||||
};
|
||||
const char *list_debug[] = {
|
||||
"View TLB (SH3 only)",
|
||||
NULL
|
||||
};
|
||||
const char **list = NULL;
|
||||
int list_len = 0;
|
||||
|
||||
extern unsigned int bgint, egint;
|
||||
extern unsigned int romdata;
|
||||
int gint_size = (char *)&egint - (char *)&bgint;
|
||||
|
||||
|
||||
|
||||
static int tab = 0, index = 0, scroll = 0;
|
||||
// Set to 1 when interface has to be redrawn.
|
||||
int leave = 1;
|
||||
int i;
|
||||
|
||||
mpu = mpu_names[MPU_CURRENT < 5 ? MPU_CURRENT : 5];
|
||||
text_configure(NULL, Color_Black);
|
||||
|
||||
while(1)
|
||||
{
|
||||
//---
|
||||
// Displaying the current tab.
|
||||
//---
|
||||
|
||||
dclear();
|
||||
dupdate();
|
||||
|
||||
switch(tab)
|
||||
{
|
||||
case 0:
|
||||
locate(1, 1, "Demo application");
|
||||
print(2, 3, "gint version: %5s", GINT_VERSION_STR);
|
||||
print(2, 4, "handler size: %5d", gint_size);
|
||||
print(2, 5, "mpu type: %7s", mpu);
|
||||
print(2, 6, "romdata: %08x", &romdata);
|
||||
|
||||
list = NULL;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
locate(1, 1, "Test list");
|
||||
list = list_tests;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
locate(1, 1, "Performance");
|
||||
list = list_perfs;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
locate(1, 1, "Debug");
|
||||
list = list_debug;
|
||||
break;
|
||||
|
||||
default:
|
||||
print(1, 1, "Tab %d", tab);
|
||||
break;
|
||||
}
|
||||
dimage(0, 56, &res_opt_menu);
|
||||
|
||||
if(list)
|
||||
{
|
||||
list_len = 0;
|
||||
while(list[list_len]) list_len++;
|
||||
|
||||
for(i = scroll; list[i] && i < scroll + 6; i++)
|
||||
locate(2, i - scroll + 2, list[i]);
|
||||
|
||||
if(scroll > 0) locate(20, 2, "\x0d");
|
||||
if(scroll + 6 < list_len) locate(20, 7, "\x0e");
|
||||
|
||||
dreverse_area(0, 8 * (index - scroll) + 8, 127,
|
||||
8 * (index - scroll) + 15);
|
||||
}
|
||||
dupdate();
|
||||
|
||||
//---
|
||||
// Waiting for events.
|
||||
//---
|
||||
|
||||
do
|
||||
{
|
||||
leave = 1;
|
||||
|
||||
switch(getkey())
|
||||
{
|
||||
case KEY_F1:
|
||||
tab = 0;
|
||||
index = 0;
|
||||
break;
|
||||
case KEY_F2:
|
||||
tab = 1;
|
||||
index = 0;
|
||||
scroll = 0;
|
||||
break;
|
||||
case KEY_F3:
|
||||
tab = 2;
|
||||
index = 0;
|
||||
scroll = 0;
|
||||
break;
|
||||
case KEY_F4:
|
||||
tab = 3;
|
||||
index = 0;
|
||||
scroll = 0;
|
||||
break;
|
||||
|
||||
case KEY_UP:
|
||||
if(list && list_len > 1)
|
||||
{
|
||||
if(index)
|
||||
{
|
||||
index--;
|
||||
if(index < scroll) scroll--;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = list_len - 1;
|
||||
scroll = list_len - 6;
|
||||
if(scroll < 0) scroll = 0;
|
||||
}
|
||||
}
|
||||
else leave = 0;
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
if(list && list_len > 1)
|
||||
{
|
||||
if(list[index + 1])
|
||||
{
|
||||
index++;
|
||||
if(index >= scroll + 6)
|
||||
scroll++;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = 0;
|
||||
scroll = 0;
|
||||
}
|
||||
}
|
||||
else leave = 0;
|
||||
break;
|
||||
|
||||
case KEY_EXE:
|
||||
if(!tab) break;
|
||||
if(category) *category = tab;
|
||||
if(app) *app = index + 1;
|
||||
return;
|
||||
|
||||
case KEY_MENU:
|
||||
if(category) *category = 0;
|
||||
if(app) *app = 0;
|
||||
return;
|
||||
|
||||
default:
|
||||
leave = 0;
|
||||
}
|
||||
}
|
||||
while(!leave);
|
||||
}
|
||||
|
||||
if(category) *category = 0;
|
||||
if(app) *app = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
main()
|
||||
No need for description.
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
int category, app;
|
||||
|
||||
while(1)
|
||||
{
|
||||
main_menu(&category, &app);
|
||||
if(!category) break;
|
||||
|
||||
switch((category << 8) | app)
|
||||
{
|
||||
case 0x0101:
|
||||
test_keyboard();
|
||||
break;
|
||||
case 0x0102:
|
||||
test_gray();
|
||||
break;
|
||||
case 0x0103:
|
||||
test_bopti();
|
||||
break;
|
||||
case 0x0104:
|
||||
test_tales();
|
||||
break;
|
||||
case 0x0105:
|
||||
test_rtc();
|
||||
break;
|
||||
case 0x0106:
|
||||
test_timer();
|
||||
break;
|
||||
|
||||
case 0x0201:
|
||||
// perf_bopti();
|
||||
break;
|
||||
case 0x0202:
|
||||
// perf_tales();
|
||||
break;
|
||||
|
||||
case 0x0301:
|
||||
// if(isSH3()) debug_tlb();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// gint demo application
|
||||
//
|
||||
// Displays some tests cases for many features of the library.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _GINTDEMO_H
|
||||
#define _GINTDEMO_H
|
||||
|
||||
//---
|
||||
// Main routines and common functions.
|
||||
//---
|
||||
|
||||
/*
|
||||
main()
|
||||
No need for description.
|
||||
*/
|
||||
int main(void);
|
||||
|
||||
/*
|
||||
main_menu()
|
||||
Displays the main menu and returns user's choice by setting the
|
||||
category and application. Category is 0 when the user leaves the
|
||||
application.
|
||||
*/
|
||||
void main_menu(int *category, int *app);
|
||||
|
||||
/*
|
||||
locate()
|
||||
Displays text using a system-like monospaced font on a 21*8 grid.
|
||||
*/
|
||||
void locate(int x, int y, const char *str);
|
||||
|
||||
/*
|
||||
print()
|
||||
Locates a string using formatted printing.
|
||||
*/
|
||||
void print(int x, int y, const char *format, ...);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Test applications.
|
||||
//---
|
||||
|
||||
/*
|
||||
test_keyboard()
|
||||
Displays a real-time multigetkey() and the keyboard state.
|
||||
*/
|
||||
void test_keyboard(void);
|
||||
|
||||
/*
|
||||
test_gray()
|
||||
Lets the user set the gray delays and see the results.
|
||||
*/
|
||||
void test_gray(void);
|
||||
|
||||
/*
|
||||
test_bopti()
|
||||
Displays and moves many kinds of bitmaps.
|
||||
*/
|
||||
void test_bopti(void);
|
||||
|
||||
/*
|
||||
test_tales()
|
||||
Displays some text using different modes and clipping options.
|
||||
*/
|
||||
void test_tales(void);
|
||||
|
||||
/*
|
||||
test_rtc()
|
||||
Just a clock.
|
||||
*/
|
||||
void test_rtc(void);
|
||||
|
||||
/*
|
||||
test_timer()
|
||||
Clock timer and timer precision.
|
||||
*/
|
||||
void test_timer(void);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Performance applications.
|
||||
//---
|
||||
|
||||
/*
|
||||
perf_bopti()
|
||||
Compares bopti and MonochromeLib.
|
||||
*/
|
||||
void perf_bopti(void);
|
||||
|
||||
/*
|
||||
perf_tales()
|
||||
Compares tales and the system's text rendering functions.
|
||||
*/
|
||||
void perf_tales(void);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Debug applications.
|
||||
//---
|
||||
|
||||
/*
|
||||
debug_tlb()
|
||||
On SH7705, displays the TLB contents. Does nothing on SH7305.
|
||||
*/
|
||||
void debug_tlb(void);
|
||||
|
||||
#endif // _GINTDEMO_H
|
|
@ -1,110 +0,0 @@
|
|||
/*
|
||||
This linker script links the object files when generating the ELF
|
||||
output. Note how symbols romdata, bbss, ebss, bdata and edata are used
|
||||
in the initialization routine (crt0.c) to initialize the application.
|
||||
|
||||
Two ram areas are specified. The "real ram" is accessed direcly while
|
||||
the other area is virtualized. It is not possible to execute code in
|
||||
virtualized ram.
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH(sh3)
|
||||
ENTRY(_start)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
rom : o = 0x00300200, l = 512k
|
||||
/* 0x0810000 is apparently mapped to 0x8801c0000. */
|
||||
ram : o = 0x08100000, l = 8k
|
||||
realram : o = 0x8800d000, l = 12k
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/*
|
||||
ROM sections : binary code and read-only data.
|
||||
*/
|
||||
|
||||
.text : {
|
||||
/* Initialization code. */
|
||||
*(.pretext.entry)
|
||||
*(.pretext)
|
||||
|
||||
_bctors = . ;
|
||||
*(.ctors)
|
||||
_ectors = . ;
|
||||
_bdtors = . ;
|
||||
*(.dtors)
|
||||
_edtors = . ;
|
||||
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
} > rom
|
||||
|
||||
.rodata : {
|
||||
*(.rodata.fxconv);
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
|
||||
_romdata = ALIGN(4) ;
|
||||
} > rom
|
||||
|
||||
|
||||
|
||||
/*
|
||||
RAM sections : bss section and read/write data.
|
||||
The BSS section is meant to be stripped from the ELF file (to
|
||||
reduce the binary size) and initialized with zeros in the
|
||||
initialization routine, therefore its location is undefined.
|
||||
*/
|
||||
|
||||
.bss : {
|
||||
_bbss = . ;
|
||||
*(.bss)
|
||||
_ebss = . ;
|
||||
} > ram
|
||||
|
||||
.data : AT(_romdata) ALIGN(4) {
|
||||
_bdata = . ;
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
_edata = . ;
|
||||
} > ram
|
||||
|
||||
.cc : AT(_romdata + SIZEOF(.data)) ALIGN(4) {
|
||||
*(.eh_frame)
|
||||
*(.jcr)
|
||||
|
||||
_gint_data = _romdata + SIZEOF(.data) + SIZEOF(.cc) ;
|
||||
} > ram
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Real RAM : interrupt, exception and TLB miss handlers.
|
||||
*/
|
||||
|
||||
.gint : AT(_gint_data) ALIGN(4) {
|
||||
/* The vbr needs to be 0x100-aligned because of an ld issue. */
|
||||
. = ALIGN(0x100) ;
|
||||
_gint_vbr = . ;
|
||||
_bgint = . ;
|
||||
|
||||
/* Exception handler. */
|
||||
. = _gint_vbr + 0x100 ;
|
||||
*(.gint.exc.entry)
|
||||
*(.gint.exc)
|
||||
|
||||
/* TLB miss handler. */
|
||||
. = _gint_vbr + 0x400 ;
|
||||
*(.gint.tlb.entry)
|
||||
*(.gint.tlb)
|
||||
|
||||
/* Interrupt handler. */
|
||||
. = _gint_vbr + 0x600 ;
|
||||
*(.gint.int.entry)
|
||||
*(.gint.int)
|
||||
|
||||
_egint = . ;
|
||||
} > realram
|
||||
}
|
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 71 KiB |
|
@ -1,221 +0,0 @@
|
|||
#include "gintdemo.h"
|
||||
#include <display.h>
|
||||
#include <gray.h>
|
||||
#include <keyboard.h>
|
||||
|
||||
#include <internals/bopti.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
test_bopti()
|
||||
Displays and moves many kinds of bitmaps. Here are the images used:
|
||||
|
||||
Name Size Color Alpha
|
||||
---------------------------------------------------------
|
||||
items.bmp 266 * 124 Gray -
|
||||
sprites.bmp 66 * 33 Gray -
|
||||
swords.bmp 88 * 16 Gray Full
|
||||
---------------------------------------------------------
|
||||
zelda.bmp 86 * 280 Mono -
|
||||
isometric.bmp 37 * 27 Mono Full
|
||||
Mono Greater
|
||||
---------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void getwh(Image *img, int *width, int *height)
|
||||
{
|
||||
const unsigned char *data;
|
||||
|
||||
if(!img)
|
||||
{
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
return;
|
||||
}
|
||||
*width = img->width;
|
||||
*height = img->height;
|
||||
if(*width && *height) return;
|
||||
|
||||
data = img->data;
|
||||
*width = (data[0] << 8) | data[1];
|
||||
*height = (data[2] << 8) | data[3];
|
||||
}
|
||||
|
||||
static void getxy(Image *img, int *x, int *y)
|
||||
{
|
||||
int width, height;
|
||||
|
||||
getwh(img, &width, &height);
|
||||
*x = 64 - (width >> 1);
|
||||
*y = 28 - (height >> 1);
|
||||
}
|
||||
|
||||
static Image *select(Image *current)
|
||||
{
|
||||
extern Image res_bopti_thumbs;
|
||||
extern Image
|
||||
res_items,
|
||||
res_sprites,
|
||||
res_swords,
|
||||
res_zelda,
|
||||
res_isometric;
|
||||
|
||||
struct {
|
||||
Image *img;
|
||||
const char *name;
|
||||
const char *info;
|
||||
} images[] = {
|
||||
{ &res_items, "Items", "Gray" },
|
||||
{ &res_sprites, "Sprites", "Gray" },
|
||||
{ &res_swords, "Swords", "Gray Alpha" },
|
||||
{ &res_zelda, "Zelda", "Mono" },
|
||||
{ &res_isometric, "Isometric", "Mono Alpha" },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
Image *thumbs = &res_bopti_thumbs;
|
||||
int items = 0;
|
||||
static int row = 0;
|
||||
int leave = 1, i;
|
||||
|
||||
while(images[items].img) items++;
|
||||
|
||||
gray_start();
|
||||
|
||||
while(1)
|
||||
{
|
||||
gclear();
|
||||
locate(1, 1, "Select an image:");
|
||||
|
||||
for(i = 0; i < items && i < 7; i++)
|
||||
{
|
||||
locate(2, 2 + i + (i > row), images[i].name);
|
||||
gimage_part(100, 8 + 8 * (i + (i > row)), thumbs, 0,
|
||||
8 * i, 7, 7);
|
||||
if(i == row)
|
||||
{
|
||||
int width, height;
|
||||
getwh(images[i].img, &width, &height);
|
||||
print(2, 2 + i + 1, "%d\x04%d", width, height);
|
||||
locate(10, 2 + i + 1, images[i].info);
|
||||
}
|
||||
}
|
||||
|
||||
greverse_area(0, 8 * row + 8, 128, 8 * row + 23);
|
||||
gupdate();
|
||||
|
||||
do
|
||||
{
|
||||
leave = 1;
|
||||
|
||||
switch(getkey())
|
||||
{
|
||||
case KEY_UP:
|
||||
row = (row + items - 1) % items;
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
row = (row + 1) % items;
|
||||
break;
|
||||
case KEY_EXE:
|
||||
return images[row].img;
|
||||
case KEY_EXIT:
|
||||
return current;
|
||||
default:
|
||||
leave = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(!leave);
|
||||
}
|
||||
|
||||
gray_stop();
|
||||
}
|
||||
|
||||
void test_bopti(void)
|
||||
{
|
||||
extern Image res_opt_bitmap;
|
||||
Image *img = NULL;
|
||||
|
||||
int leave = 1;
|
||||
int black_bg = 0;
|
||||
int x = 0, y = 0;
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(img && (img->format & Channel_Light))
|
||||
{
|
||||
gray_start();
|
||||
gclear();
|
||||
|
||||
if(black_bg) greverse_area(0, 0, 127, 63);
|
||||
if(img) gimage(x, y, img);
|
||||
|
||||
gclear_area(0, 55, 127, 63);
|
||||
gimage(0, 56, &res_opt_bitmap);
|
||||
gupdate();
|
||||
}
|
||||
else if(img)
|
||||
{
|
||||
gray_stop();
|
||||
dclear();
|
||||
|
||||
if(black_bg) dreverse_area(0, 0, 127, 63);
|
||||
if(img) dimage(x, y, img);
|
||||
|
||||
dclear_area(0, 55, 127, 63);
|
||||
dimage(0, 56, &res_opt_bitmap);
|
||||
dupdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
gray_stop();
|
||||
|
||||
dclear();
|
||||
locate(3, 3, "No image selected");
|
||||
|
||||
dimage(0, 56, &res_opt_bitmap);
|
||||
dupdate();
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
leave = 1;
|
||||
|
||||
switch(getkey())
|
||||
{
|
||||
case KEY_EXIT:
|
||||
gray_stop();
|
||||
return;
|
||||
|
||||
case KEY_F1:
|
||||
img = select(img);
|
||||
getxy(img, &x, &y);
|
||||
break;
|
||||
case KEY_F5:
|
||||
black_bg = !black_bg;
|
||||
break;
|
||||
|
||||
case KEY_UP:
|
||||
y--;
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
y++;
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
x--;
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
x++;
|
||||
break;
|
||||
|
||||
default:
|
||||
leave = 0;
|
||||
}
|
||||
}
|
||||
while(!leave);
|
||||
}
|
||||
|
||||
gray_stop();
|
||||
return;
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
#include "gintdemo.h"
|
||||
#include <gray.h>
|
||||
#include <keyboard.h>
|
||||
#include <mpu.h>
|
||||
|
||||
/*
|
||||
test_gray()
|
||||
Lets the user set the gray delays and see the results.
|
||||
*/
|
||||
|
||||
static void draw(int delay1, int delay2, int selected)
|
||||
{
|
||||
extern Image res_opt_gray;
|
||||
unsigned int *vl = gray_lightVRAM();
|
||||
unsigned int *vd = gray_darkVRAM();
|
||||
|
||||
gclear();
|
||||
locate(1, 1, "Gray engine");
|
||||
|
||||
for(int i = 0; i < 36; i++)
|
||||
{
|
||||
int o = ((i + 12) << 2) + 2;
|
||||
unsigned light = -((i % 24) < 12);
|
||||
unsigned dark = -(i < 24);
|
||||
vl[o] = light >> 8;
|
||||
vl[o + 1] = light << 8;
|
||||
vd[o] = dark >> 8;
|
||||
vd[o + 1] = dark << 8;
|
||||
}
|
||||
|
||||
locate(3, 3, "light");
|
||||
print(4, 4, "%d", delay1);
|
||||
|
||||
locate(3, 5, "dark");
|
||||
print(4, 6, "%d", delay2);
|
||||
|
||||
locate(3, selected ? 6 : 4, "\x02");
|
||||
|
||||
gimage(0, 56, &res_opt_gray);
|
||||
gupdate();
|
||||
}
|
||||
|
||||
void test_gray(void)
|
||||
{
|
||||
int delays[2]; // { light, dark }
|
||||
int key, changed = 1;
|
||||
int selected = 0;
|
||||
|
||||
gray_getDelays(delays, delays + 1);
|
||||
gray_start();
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(changed)
|
||||
{
|
||||
gray_setDelays(delays[0], delays[1]);
|
||||
draw(delays[0], delays[1], selected);
|
||||
}
|
||||
changed = 0;
|
||||
|
||||
key = getkey_opt(Getkey_RepeatArrowKeys, 1);
|
||||
if(key == KEY_EXIT) break;
|
||||
|
||||
changed = 1;
|
||||
|
||||
switch(key)
|
||||
{
|
||||
case KEY_F1:
|
||||
selected = !selected;
|
||||
break;
|
||||
case KEY_F2:
|
||||
delays[0] = 912;
|
||||
delays[1] = 1343;
|
||||
break;
|
||||
case KEY_F3:
|
||||
delays[0] = 993;
|
||||
delays[1] = 1609;
|
||||
break;
|
||||
case KEY_F4:
|
||||
delays[0] = 860;
|
||||
delays[1] = 1298;
|
||||
break;
|
||||
case KEY_UP:
|
||||
delays[selected] += 10;
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
if(delays[selected] >= 110) delays[selected] -= 10;
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
delays[selected]++;
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
if(delays[selected] >= 101) delays[selected]--;
|
||||
break;
|
||||
default:
|
||||
changed = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gray_stop();
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
#include "gintdemo.h"
|
||||
#include <display.h>
|
||||
#include <keyboard.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
test_keyboard()
|
||||
Displays a real-time multigetkey() and the keyboard state.
|
||||
*/
|
||||
|
||||
static void draw(volatile unsigned char *state)
|
||||
{
|
||||
int i, j, k, l;
|
||||
int x, y;
|
||||
|
||||
for(i = 0; i < 10; i++) for(j = 1; j < 8; j++)
|
||||
{
|
||||
// Eliminating keys that do not exist.
|
||||
if(!i && j != 7) continue;
|
||||
if(i && j == 7) continue;
|
||||
if(i <= 4 && j == 6) continue;
|
||||
if(i == 4 && j == 5) continue;
|
||||
|
||||
x = 5 * j + 1;
|
||||
y = 61 - 5 * i;
|
||||
// Moving the [AC/ON] key.
|
||||
if(!i) x = 5 * (5) + 1, y = 61 - 5 * (4);
|
||||
|
||||
// Drawing a filled shape when the key is pressed.
|
||||
if(state[i] & (128 >> j))
|
||||
{
|
||||
for(k = -2; k <= 2; k++) for(l = -2; l <= 2; l++)
|
||||
if(abs(k) + abs(l) <= 2)
|
||||
dpixel(x + k, y + l, Color_Black);
|
||||
}
|
||||
// Drawing a square border otherwise.
|
||||
else
|
||||
{
|
||||
for(k = -1; k <= 1; k++) for(l = -1; l <= 1; l++)
|
||||
if(k || l) dpixel(x + k, y + l, Color_Black);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_keyboard(void)
|
||||
{
|
||||
const char *key_names[] = {
|
||||
"F1", "F2", "F3", "F4", "F5", "F6",
|
||||
"SHIFT", "OPTN", "VARS", "MENU", "Left", "Up",
|
||||
"ALPHA", "x^2", "^", "EXIT", "Down", "Right",
|
||||
"X,\x1d,T", "log", "ln", "sin", "cos", "tan",
|
||||
"[frac]", "F\x0f\x09" "D", "(", ")", ",", "\x09",
|
||||
"7", "8", "9", "DEL", "AC/ON", NULL,
|
||||
"4", "5", "6", "\x04", "\x05", NULL,
|
||||
"1", "2", "3", "+", "-", NULL,
|
||||
"0", ".", "\x08", "(-)", "EXE", NULL
|
||||
};
|
||||
|
||||
volatile unsigned char *state = keystate();
|
||||
int keys[4] = { 0 };
|
||||
int i;
|
||||
|
||||
while(1)
|
||||
{
|
||||
dclear();
|
||||
locate(1, 1, "Keyboard driver");
|
||||
locate(8, 3, "Pressed keys:");
|
||||
draw(state);
|
||||
|
||||
if(keys[0] == KEY_NONE) locate(9, 4, ":None");
|
||||
else for(i = 0; i < 4 && keys[i] != KEY_NONE; i++)
|
||||
{
|
||||
locate( 9, i + 4, ":");
|
||||
locate(10, i + 4, key_names[keyid(keys[i])]);
|
||||
}
|
||||
|
||||
dupdate();
|
||||
|
||||
multigetkey(keys, 4, 1);
|
||||
if(keys[0] == KEY_EXIT && keys[1] == KEY_NONE) break;
|
||||
}
|
||||
}
|
|
@ -1,262 +0,0 @@
|
|||
#include "gintdemo.h"
|
||||
#include <display.h>
|
||||
#include <rtc.h>
|
||||
#include <keyboard.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
test_rtc()
|
||||
Just a clock. Of course using all this RTCTime conversion and this / 10
|
||||
is awfully un-optimized, but it's a test case so it's made to check the
|
||||
values in the structure are correct.
|
||||
*/
|
||||
|
||||
#include <internals/rtc.h>
|
||||
#include <mpu.h>
|
||||
|
||||
static void draw(struct RTCTime time)
|
||||
{
|
||||
extern Image res_rtc_segments;
|
||||
|
||||
const char *days[7] = {
|
||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||
}, *months[12] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
|
||||
"Oct", "Nov", "Dec"
|
||||
};
|
||||
int x[6] = { 20, 33, 52, 65, 84, 97 };
|
||||
int digits[6];
|
||||
int i;
|
||||
|
||||
digits[0] = time.hours / 10;
|
||||
digits[1] = time.hours % 10;
|
||||
digits[2] = time.minutes / 10;
|
||||
digits[3] = time.minutes % 10;
|
||||
digits[4] = time.seconds / 10;
|
||||
digits[5] = time.seconds % 10;
|
||||
|
||||
// Drawing digits.
|
||||
for(i = 0; i < 6; i++) dimage_part(x[i], 8, &res_rtc_segments,
|
||||
12 * digits[i], 0, 11, 19);
|
||||
// Drawing ':' between pairs of digits.
|
||||
for(i = 0; i < 16; i++) dpixel(47 + 32 * (i >= 8) + (i & 1),
|
||||
14 + 5 * !!(i & 4) + !!(i & 2), Color_Black);
|
||||
|
||||
// This should print time.year + 1900 but for the sake of this demo we
|
||||
// have tweaked the field so that it already contains time.year + 1900.
|
||||
print(4, 6, "%s %s %02d %4d", days[time.week_day],
|
||||
months[time.month], time.month_day, time.year);
|
||||
}
|
||||
|
||||
static void callback(void)
|
||||
{
|
||||
extern Image res_opt_rtc;
|
||||
struct RTCTime time = rtc_getTime();
|
||||
time.year += 1900;
|
||||
|
||||
dclear();
|
||||
draw(time);
|
||||
dimage_part(0, 56, &res_opt_rtc, 0, 0, 19, 8);
|
||||
dupdate();
|
||||
}
|
||||
|
||||
static void set_region(struct RTCTime *time, int region, int value)
|
||||
{
|
||||
switch(region)
|
||||
{
|
||||
case 0:
|
||||
time->hours = 10 * value + (time->hours % 10);
|
||||
break;
|
||||
case 1:
|
||||
time->hours = time->hours - (time->hours % 10) + value;
|
||||
break;
|
||||
case 2:
|
||||
time->minutes = 10 * value + (time->minutes % 10);
|
||||
break;
|
||||
case 3:
|
||||
time->minutes = time->minutes - (time->minutes % 10) + value;
|
||||
break;
|
||||
case 4:
|
||||
time->seconds = 10 * value + (time->seconds % 10);
|
||||
break;
|
||||
case 5:
|
||||
time->seconds = time->seconds - (time->seconds % 10) + value;
|
||||
break;
|
||||
case 6:
|
||||
time->week_day = value;
|
||||
break;
|
||||
case 7:
|
||||
time->month = value;
|
||||
break;
|
||||
case 8:
|
||||
time->month_day = 10 * value + (time->month_day % 10);
|
||||
break;
|
||||
case 9:
|
||||
time->month_day = time->month_day - (time->month_day % 10)
|
||||
+ value;
|
||||
break;
|
||||
case 10:
|
||||
time->year = 1000 * value + (time->year % 1000);
|
||||
break;
|
||||
case 11:
|
||||
time->year = time->year - (time->year % 1000) + 100 * value
|
||||
+ (time->year % 100);
|
||||
break;
|
||||
case 12:
|
||||
time->year = time->year - (time->year % 100) + 10 * value
|
||||
+ (time->year % 10);
|
||||
break;
|
||||
case 13:
|
||||
time->year = time->year - (time->year % 10) + value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void set(void)
|
||||
{
|
||||
extern Image res_opt_rtc;
|
||||
Image *opt = &res_opt_rtc;
|
||||
|
||||
struct {
|
||||
int x, y;
|
||||
int w, h;
|
||||
} regions[] = {
|
||||
{ 19, 7, 13, 21 }, { 32, 7, 13, 21 }, { 51, 7, 13, 21 },
|
||||
{ 64, 7, 13, 21 }, { 83, 7, 13, 21 }, { 96, 7, 13, 21 },
|
||||
{ 18, 39, 19, 9 }, { 42, 39, 19, 9 }, { 66, 39, 7, 9 },
|
||||
{ 72, 39, 7, 9 }, { 84, 39, 7, 9 }, { 90, 39, 7, 9 },
|
||||
{ 96, 39, 7, 9 }, { 102, 39, 7, 9 },
|
||||
};
|
||||
struct RTCTime time = rtc_getTime();
|
||||
int region_count = 14;
|
||||
int n = 0, slide = 0, key, leave;
|
||||
|
||||
time.year += 1900;
|
||||
|
||||
while(1)
|
||||
{
|
||||
dclear();
|
||||
draw(time);
|
||||
dreverse_area(regions[n].x, regions[n].y, regions[n].x
|
||||
+ regions[n].w - 1, regions[n].y + regions[n].h - 1);
|
||||
|
||||
if(n == 6) dimage_part(0, 56, opt, 0, 9 * (1 + slide), 128, 8);
|
||||
if(n == 7) dimage_part(0, 56, opt, 0, 9 * (3 + slide), 128, 8);
|
||||
else dimage_part(0, 56, opt, 22 + 22 * (n == region_count - 1),
|
||||
0, 19, 8);
|
||||
|
||||
dupdate();
|
||||
|
||||
do
|
||||
{
|
||||
leave = 1;
|
||||
key = getkey();
|
||||
if(key == KEY_EXIT) return;
|
||||
|
||||
else if(key == KEY_F1 || key == KEY_EXE)
|
||||
{
|
||||
n++;
|
||||
slide = 0;
|
||||
if(n == region_count)
|
||||
{
|
||||
time.year -= 1900;
|
||||
rtc_setTime(time);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
else if(key == KEY_F6)
|
||||
{
|
||||
if(n == 6) slide = (slide + 1) % 2;
|
||||
if(n == 7) slide = (slide + 1) % 3;
|
||||
}
|
||||
|
||||
else if((key & 0x0f) == 9) // Other F-keys
|
||||
{
|
||||
int k = 7 - (key >> 4); // Number of F-key
|
||||
|
||||
if(n == 7)
|
||||
{
|
||||
int month = k + 4 * slide - 2;
|
||||
set_region(&time, n, month);
|
||||
n++;
|
||||
slide = 0;
|
||||
}
|
||||
|
||||
else if(n == 6 && (slide != 1 || k != 5))
|
||||
{
|
||||
int day = k + 4 * slide - 1;
|
||||
set_region(&time, n, day);
|
||||
n++;
|
||||
slide = 0;
|
||||
}
|
||||
|
||||
else leave = 0;
|
||||
}
|
||||
|
||||
else if(isdigit(keychar(key))) // Numbers
|
||||
{
|
||||
int val = keychar(key) - '0';
|
||||
int ok = 1;
|
||||
|
||||
if(n == 0) ok = (val <= 2);
|
||||
if(n == 1)
|
||||
{
|
||||
int max = time.hours >= 20 ? 3 : 9;
|
||||
ok = (val <= max);
|
||||
}
|
||||
if(n == 2 || n == 4) ok = (val <= 5);
|
||||
if(n == 8) ok = (val <= 3);
|
||||
if(n == 9)
|
||||
{
|
||||
int max = time.month_day >= 30 ? 1 : 9;
|
||||
ok = (val <= max);
|
||||
}
|
||||
|
||||
if(ok)
|
||||
{
|
||||
set_region(&time, n, val);
|
||||
n++;
|
||||
if(n == region_count)
|
||||
{
|
||||
time.year -= 1900;
|
||||
rtc_setTime(time);
|
||||
return;
|
||||
}
|
||||
slide = 0;
|
||||
}
|
||||
else leave = 0;
|
||||
}
|
||||
|
||||
else leave = 0;
|
||||
} while(!leave);
|
||||
}
|
||||
|
||||
while(getkey() != KEY_EXIT);
|
||||
}
|
||||
|
||||
void test_rtc(void)
|
||||
{
|
||||
int key, cb_id;
|
||||
|
||||
cb_id = rtc_cb_add(RTCFreq_1Hz, callback, 0);
|
||||
callback();
|
||||
|
||||
while(1)
|
||||
{
|
||||
key = getkey();
|
||||
|
||||
if(key == KEY_EXIT) break;
|
||||
if(key == KEY_F1)
|
||||
{
|
||||
rtc_cb_edit(cb_id, RTCFreq_None, NULL);
|
||||
set();
|
||||
callback();
|
||||
rtc_cb_edit(cb_id, RTCFreq_1Hz, callback);
|
||||
}
|
||||
}
|
||||
|
||||
rtc_cb_end(cb_id);
|
||||
}
|
|
@ -1,158 +0,0 @@
|
|||
#include "gintdemo.h"
|
||||
#include <display.h>
|
||||
#include <keyboard.h>
|
||||
#include <gray.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
test_tales()
|
||||
Displays some text using different modes and clipping options.
|
||||
*/
|
||||
|
||||
static Font *select(Font *current)
|
||||
{
|
||||
extern Font res_font_modern;
|
||||
struct {
|
||||
Font *font;
|
||||
const char *name;
|
||||
} fonts[] = {
|
||||
{ NULL, "gint default" },
|
||||
{ &res_font_modern, "Modern" },
|
||||
};
|
||||
int font_number = 2;
|
||||
|
||||
static int row = 0;
|
||||
int i, leave;
|
||||
|
||||
while(1)
|
||||
{
|
||||
text_configure(NULL, Color_Black);
|
||||
|
||||
dclear();
|
||||
locate(1, 1, "Select a font:");
|
||||
|
||||
for(i = 0; i < font_number && i < 6; i++)
|
||||
{
|
||||
if(fonts[i].font)
|
||||
{
|
||||
int height = fonts[i].font->line_height;
|
||||
int y = (i + 2) * 8 - 8 + ((7 - height) >> 1);
|
||||
|
||||
text_configure(fonts[i].font, Color_Black);
|
||||
dtext(7, y, fonts[i].name);
|
||||
}
|
||||
else
|
||||
{
|
||||
text_configure(NULL, Color_Black);
|
||||
locate(2, i + 2, fonts[i].name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dreverse_area(0, 8 * row + 8, 128, 8 * row + 15);
|
||||
dupdate();
|
||||
|
||||
do
|
||||
{
|
||||
leave = 1;
|
||||
|
||||
switch(getkey())
|
||||
{
|
||||
case KEY_UP:
|
||||
row = (row + font_number - 1) % font_number;
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
row = (row + 1) % font_number;
|
||||
break;
|
||||
case KEY_EXE:
|
||||
return fonts[row].font;
|
||||
case KEY_EXIT:
|
||||
return current;
|
||||
default:
|
||||
leave = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(!leave);
|
||||
}
|
||||
}
|
||||
|
||||
void test_tales(void)
|
||||
{
|
||||
enum Color colors[] = { Color_Black, Color_Dark, Color_Light,
|
||||
Color_White, Color_Invert };
|
||||
extern Image res_opt_tales;
|
||||
Font *font = NULL;
|
||||
|
||||
int black_bg = 0;
|
||||
int color = 0;
|
||||
int i, x, height;
|
||||
int leave;
|
||||
|
||||
gray_start();
|
||||
while(1)
|
||||
{
|
||||
gclear();
|
||||
if(black_bg) greverse_area(0, 0, 127, 54);
|
||||
|
||||
if(font)
|
||||
{
|
||||
text_configure(font, colors[color]);
|
||||
height = font->line_height + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
text_configure(NULL, colors[color]);
|
||||
height = 8;
|
||||
}
|
||||
|
||||
for(i = 0; i < 6 && 2 + (i + 1) * height < 56; i++)
|
||||
{
|
||||
char str[17];
|
||||
for(int j = 0; j < 16; j++) str[j] = 32 + (i << 4) + j;
|
||||
str[16] = 0;
|
||||
|
||||
gtext(2, 2 + i * height, str);
|
||||
}
|
||||
|
||||
gimage(0, 56, &res_opt_tales);
|
||||
|
||||
x = 45 + 8 * color;
|
||||
gline(x, 57, x + 5, 57, Color_Black);
|
||||
gline(x, 57, x, 62, Color_Black);
|
||||
gline(x + 5, 57, x + 5, 62, Color_Black);
|
||||
gline(x, 62, x + 5, 62, Color_Black);
|
||||
|
||||
gupdate();
|
||||
|
||||
do
|
||||
{
|
||||
leave = 1;
|
||||
|
||||
switch(getkey())
|
||||
{
|
||||
case KEY_F1:
|
||||
gray_stop();
|
||||
font = select(font);
|
||||
gray_start();
|
||||
break;
|
||||
case KEY_F2:
|
||||
color = (color + 1) % 5;
|
||||
break;
|
||||
case KEY_F5:
|
||||
black_bg = !black_bg;
|
||||
break;
|
||||
|
||||
case KEY_EXIT:
|
||||
gray_stop();
|
||||
text_configure(NULL, Color_Black);
|
||||
return;
|
||||
default:
|
||||
leave = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!leave);
|
||||
}
|
||||
}
|
|
@ -1,272 +0,0 @@
|
|||
#include "gintdemo.h"
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <internals/timer.h>
|
||||
#include <timer.h>
|
||||
#include <display.h>
|
||||
#include <keyboard.h>
|
||||
#include <clock.h>
|
||||
#include <mpu.h>
|
||||
#include <rtc.h>
|
||||
|
||||
static void draw(int new_tab);
|
||||
static struct ClockConfig conf;
|
||||
|
||||
//---
|
||||
// Timer-RTC comparison.
|
||||
// The precision of the timer is measured by comparing it to the RTC.
|
||||
//---
|
||||
|
||||
static volatile int elapsed_timer = -1;
|
||||
static volatile int elapsed_rtc = -1;
|
||||
static int cb_id = -1;
|
||||
|
||||
static void timing_rtc(void)
|
||||
{
|
||||
elapsed_rtc++;
|
||||
}
|
||||
|
||||
static void timing_timer(void)
|
||||
{
|
||||
elapsed_timer++;
|
||||
}
|
||||
|
||||
static void timing_start(void)
|
||||
{
|
||||
timer_start(TIMER_USER, clock_setting(16, Clock_Hz), TIMER_Po_4,
|
||||
timing_timer, 0);
|
||||
rtc_cb_edit(cb_id, RTCFreq_16Hz, timing_rtc);
|
||||
|
||||
elapsed_timer = 0;
|
||||
elapsed_rtc = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Drawing.
|
||||
//---
|
||||
|
||||
/*
|
||||
small_text()
|
||||
Renders small text using a minimalist bitmap-based font.
|
||||
*/
|
||||
static void small_text(int x, int y, const char *text, int alignment)
|
||||
{
|
||||
extern Image res_clock_chars;
|
||||
Image *chars = &res_clock_chars;
|
||||
const char *table = "0123456789kMHz*/";
|
||||
|
||||
if(alignment) x -= 2 * strlen(text) - 1, y -= 2;
|
||||
int c;
|
||||
|
||||
while(*text)
|
||||
{
|
||||
const char *ptr = strchr(table, *text++);
|
||||
if(!ptr) continue;
|
||||
c = ptr - table;
|
||||
|
||||
dimage_part(x, y, chars, c << 2, 0, 3, 5);
|
||||
x += 4;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
getFreq()
|
||||
Prints the given frequency in a string on the form:
|
||||
332kHz
|
||||
There are 1, 2 or 3 characters for the value, and 2 or 3
|
||||
characters for the unit. The string is compacted.
|
||||
*/
|
||||
void getFreq(char *str, int freq)
|
||||
{
|
||||
if(freq < 1000) sprintf(str, "%dHz", freq);
|
||||
else if(freq < 1000000) sprintf(str, "%dkHz", (freq + 500) / 1000);
|
||||
else sprintf(str, "%dMHz", (freq + 500000) / 1000000);
|
||||
}
|
||||
|
||||
/*
|
||||
dislay_freq()
|
||||
Displays a frequency value a unit, in an simple form.
|
||||
*/
|
||||
static void display_freq(int x, int y, int freq)
|
||||
{
|
||||
int ratio, letter, dot, i;
|
||||
char buffer[10];
|
||||
|
||||
if(freq <= 0)
|
||||
{
|
||||
dtext(x, y, "Unknown");
|
||||
return;
|
||||
}
|
||||
if(freq < 10000)
|
||||
{
|
||||
dprint(x, y, "%5d", freq);
|
||||
small_text(x + 31, y + 2, "Hz", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(freq < 10000000) ratio = 1, letter = 'k';
|
||||
else ratio = 1000, letter = 'M';
|
||||
|
||||
dot = 1 + (freq >= 10000 * ratio) + (freq >= 100000 * ratio);
|
||||
freq += (ratio * (1 + 9 * (dot >= 2) + 90 * (dot >= 3))) / 2;
|
||||
snprintf(buffer, 6, "%d", freq);
|
||||
|
||||
for(i = 4; i > dot; i--) buffer[i] = buffer[i - 1];
|
||||
buffer[dot] = '.';
|
||||
|
||||
dprint(x, y, buffer);
|
||||
sprintf(buffer, "%cHz", letter);
|
||||
small_text(x + 31, y + 2, buffer, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
draw()
|
||||
Draws the test interface.
|
||||
*/
|
||||
static void draw(int tab)
|
||||
{
|
||||
extern Image res_opt_timer;
|
||||
extern Image res_clock_7705;
|
||||
extern Image res_clock_7305;
|
||||
|
||||
char buffer[16];
|
||||
|
||||
dclear();
|
||||
dimage(0, 56, &res_opt_timer);
|
||||
|
||||
if(!tab)
|
||||
{
|
||||
locate(1, 1, "Clock frequency");
|
||||
dtext(7, 20, "B\x1e");
|
||||
display_freq(24, 20, conf.Bphi_f);
|
||||
dtext(7, 28, "I\x1e");
|
||||
display_freq(24, 28, conf.Iphi_f);
|
||||
dtext(7, 36, "P\x1e");
|
||||
display_freq(24, 36, conf.Pphi_f);
|
||||
|
||||
if(isSH3())
|
||||
{
|
||||
dimage(64, 0, &res_clock_7705);
|
||||
|
||||
getFreq(buffer, conf.CKIO_f);
|
||||
small_text(84, 16, buffer, 1);
|
||||
|
||||
sprintf(buffer, "*%d", conf.PLL1);
|
||||
small_text(84, 34, buffer, 1);
|
||||
|
||||
if(conf.Iphi_div1 == 1)
|
||||
dline(85, 43, 99, 43, Color_Black);
|
||||
else
|
||||
{
|
||||
sprintf(buffer, "/%d", conf.Iphi_div1);
|
||||
small_text(89, 41, buffer, 0);
|
||||
}
|
||||
if(conf.Pphi_div1 == 1)
|
||||
dline(85, 50, 99, 50, Color_Black);
|
||||
else
|
||||
{
|
||||
sprintf(buffer, "/%d", conf.Pphi_div1);
|
||||
small_text(89, 48, buffer, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dimage(64, 0, &res_clock_7305);
|
||||
|
||||
getFreq(buffer, conf.RTCCLK_f);
|
||||
small_text(84, 14, buffer, 1);
|
||||
|
||||
sprintf(buffer, "*%d", conf.FLL);
|
||||
small_text(84, 25, buffer, 1);
|
||||
|
||||
sprintf(buffer, "*%d", conf.PLL);
|
||||
small_text(84, 36, buffer, 1);
|
||||
|
||||
sprintf(buffer, "/%d", conf.Bphi_div1);
|
||||
small_text(89, 43, buffer, 0);
|
||||
sprintf(buffer, "/%d", conf.Iphi_div1);
|
||||
small_text(89, 50, buffer, 0);
|
||||
sprintf(buffer, "/%d", conf.Pphi_div1);
|
||||
small_text(89, 57, buffer, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int timer = elapsed_timer, rtc = elapsed_rtc; // just in case
|
||||
|
||||
locate(1, 1, "Timer/RTC comparison");
|
||||
|
||||
locate(2, 3, "Timer");
|
||||
if(timer >= 0) print(12, 3, "%04x", timer);
|
||||
else locate(12, 3, "...");
|
||||
|
||||
locate(2, 4, "RTC");
|
||||
if(rtc >= 0) print(12, 4, "%04x", rtc);
|
||||
else locate(12, 4, "...");
|
||||
|
||||
// We define the accuracy of the timer as the ratio between the
|
||||
// two counters.
|
||||
locate(2, 5, "Accuracy");
|
||||
if(rtc > 0 && timer > 0)
|
||||
{
|
||||
int ratio;
|
||||
if(timer <= rtc) ratio = (10000 * timer) / rtc;
|
||||
else ratio = (10000 * rtc) / timer;
|
||||
|
||||
print(12, 5, "%d.%02d %%", ratio / 100, ratio % 100);
|
||||
}
|
||||
else locate(12, 5, "...");
|
||||
}
|
||||
|
||||
dupdate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Timer/clock test.
|
||||
//---
|
||||
|
||||
/*
|
||||
test_timer()
|
||||
Clock timer and timer precision.
|
||||
*/
|
||||
void test_timer(void)
|
||||
{
|
||||
int tab = 0;
|
||||
|
||||
clock_measure();
|
||||
clock_measure_end();
|
||||
|
||||
conf = clock_config();
|
||||
|
||||
elapsed_timer = -1;
|
||||
elapsed_rtc = -1;
|
||||
cb_id = rtc_cb_add(RTCFreq_16Hz, timing_start, 0);
|
||||
|
||||
text_configure(NULL, Color_Black);
|
||||
|
||||
while(1)
|
||||
{
|
||||
draw(tab);
|
||||
|
||||
switch(getkey_opt(Getkey_NoOption, 1))
|
||||
{
|
||||
case KEY_EXIT:
|
||||
timer_stop(TIMER_USER);
|
||||
rtc_cb_end(cb_id);
|
||||
return;
|
||||
|
||||
case KEY_F1:
|
||||
tab = 0;
|
||||
break;
|
||||
case KEY_F2:
|
||||
tab = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,306 +0,0 @@
|
|||
|
||||
# gint documentation: bitmap rendering #
|
||||
|
||||
|
||||
*Warning: this is a draft. The current implementation of bopti is different*
|
||||
*from this description, though similar.*
|
||||
|
||||
|
||||
|
||||
## Basics
|
||||
|
||||
The bitmap drawing module, *bopti*, is based on video-ram (vram) bitwise
|
||||
operations. The images are made of layers that describe (more or less) which
|
||||
pixels of the image an operation applies to. Rendering the image consists in
|
||||
applying an operation function to the existing vram pixels.
|
||||
|
||||
*bopti* makes an extensive use of longword operations and 4-alignment to take
|
||||
advantage of the bit-based structure of the monochrome vram and enhance
|
||||
performance. Among all possible optimizations, avoiding direct pixel access has
|
||||
proven to be the most efficient.
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## Operations
|
||||
|
||||
Operations are functions applied to update a vram longword in accordance with
|
||||
an operation mask. Bits that are set in the mask indicate pixels which have to
|
||||
be updated by the operation. Bits that are reset indicate pixels that must not
|
||||
be changed.
|
||||
|
||||
All the point is, the functions must not access the bit information in the mask
|
||||
or the vram data individually. They must operate globally using longword
|
||||
bitwise instructions, so that performance is maintained.
|
||||
|
||||
Consider for instance a logical and operation (`(a, b) -> a & b`).
|
||||
Operating on pixels would need to move some data, test the value of a bit in
|
||||
the mask, edit the vram data, and eventually shift both the data and the mask,
|
||||
for all of the 32 pixels.
|
||||
One could not expect this from happening in less than 150 processor cycles
|
||||
(in comparison, using generic-purpose `setPixel()`-like functions would be at
|
||||
least 10 times as long). The smarter method operates directly on the longword
|
||||
parameters, and performs `data = data & ~mask`, which is 2 processor cycles
|
||||
long.
|
||||
|
||||
The following operations are defined by *bopti*:
|
||||
|
||||
- `Draw `: Draws black pixels.
|
||||
- `Alpha `: Erases non-transparent pixels.
|
||||
- `Change `: Changes the pixels' color.
|
||||
- `Lighten `: Lightens gray pixels.
|
||||
- `Lighten2`: Lightens gray pixels more.
|
||||
- `Darken `: Darkens gray pixels.
|
||||
- `Darken2 `: Darkens gray pixels more.
|
||||
|
||||
To perform an operation, *bopti* uses the mask data, which is taken from a
|
||||
layer, and calls the associated operation function. Every operation has its
|
||||
default layer mask (except `change`), but this setting may be overridden.
|
||||
*bopti* allows user programs to use any monochrome image as a mask for an
|
||||
operation. For instance, a black rectangle may be drawn by any of the operation
|
||||
functions, resulting in various results.
|
||||
|
||||
An additional operation, `fill`, is defined by the library. It does all the job
|
||||
necessary to render the full image, which often falls back to performing the
|
||||
operations that correspond to the kind of image.
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## Operation on gray pixels
|
||||
|
||||
*Detailed article: [Gray engine](gray-engine)*
|
||||
|
||||
Gray pixels are made of four colors represented by pairs of bits. Arguments
|
||||
`light` and `dark` of gray operation functions are longwords containing the
|
||||
least significant and most significant of these bits, respectively.
|
||||
|
||||
white = 0 [00]
|
||||
lightgray = 1 [01]
|
||||
darkgray = 2 [10]
|
||||
black = 3 [11]
|
||||
|
||||
The `Lighten` operation affects pixels as if decrementing their value (white
|
||||
pixels are not changed), and `darken` does the opposite (black pixels are not
|
||||
changed).
|
||||
Operations `Lighten2` and `darken2` do the same two times.
|
||||
|
||||
From this description, and considering two bits `light` and `dark`, it follows
|
||||
that:
|
||||
|
||||
```c
|
||||
lighten2 (light, dark) = (0, light & dark)
|
||||
lighten (light, dark) = (light & dark, light & ~dark)
|
||||
darken (light, dark) = (light | dark, light | ~dark)
|
||||
darken2 (light, dark) = (1, light | dark)
|
||||
```
|
||||
|
||||
This does not take account of a possible operation mask. See section
|
||||
[Operation functions](#operation-functions) for more flexible functions.
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## Partial transparency
|
||||
|
||||
*bopti* allows monochrome images to have semi-transparent pixels. Consider for
|
||||
example a white background. An opaque black pixel will render black, while a
|
||||
1/3-transparent black pixel will render dark gray, and a 2/3-transparent black
|
||||
pixel will render light gray. Which means that:
|
||||
|
||||
* 1/3-transparent white pixels form the mask for `lighten2`
|
||||
* 2/3-transparent white pixels form the mask for `lighten`
|
||||
* 2/3-transparent black pixels form the mask for `darken`
|
||||
* 1/3-transparent black pixels form the mask for `darken2`
|
||||
|
||||
Partial transparency on gray pixels is not allowed. Apart from the complexity
|
||||
of the generic partial transparency rendering operation, semi-transparent gray
|
||||
pixels are not of any use.
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## Operation functions
|
||||
|
||||
Operations on monochrome buffers are defined as functions of two parameters:
|
||||
the vram data longword to update, `data`, and the operation mask, `x`. Every
|
||||
of these functions must satisfy `f(data, 0) = data`.
|
||||
|
||||
Operations on gray buffers take three arguments: `light` and `dark`, which are
|
||||
longwords from the [gray buffers](gray-engine), and the operation mask `x`.
|
||||
They update both longwords and return them. These functions must satisfy
|
||||
`f(light, dark, 0) = (light, dark)`.
|
||||
|
||||
The functions for each of the operations are the following:
|
||||
|
||||
~~~c
|
||||
# Draw function
|
||||
draw(data, x) = data | x
|
||||
|
||||
# Alpha function
|
||||
alpha(data, x) = data & ~x
|
||||
|
||||
# Change function
|
||||
change(data, x) = data ^ x
|
||||
|
||||
# Lighten function
|
||||
lighten(light, dark, x) = (light & (dark | ~x), (light | ~x) & (x ^ dark))
|
||||
|
||||
# Lighten2 function
|
||||
lighten2(light, dark, x) = (light & ~x, (light | ~x) & dark)
|
||||
|
||||
# Darken function
|
||||
darken(light, dark, x) = (light | (dark & x), (light & x) | (x ^ dark))
|
||||
|
||||
# Darken2 function
|
||||
darken2(light, dark, x) = (light | x, (light & x) | dark)
|
||||
~~~
|
||||
|
||||
One could easily check that these functions do their jobs when `x = 1` and
|
||||
leave the data unchanged when `x = 0`.
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## Image format
|
||||
|
||||
Images are made of *layers*, each of which describe the mask for an operation.
|
||||
When an image is rendered, *bopti* draws some of those layers in the vram
|
||||
using the operation functions.
|
||||
|
||||
* Non-transparent monochrome images only have one layer, which describes the
|
||||
mask for the `draw` operation.
|
||||
* Transparent monochrome images have two layers. The first describes the mask
|
||||
for the `draw` operation, while the other is the `alpha` operation mask (which
|
||||
means that it indicates which pixels are not transparent).
|
||||
* Non-transparent gray images also have two layers: one for each
|
||||
[gray buffer](gray-engine). Both are for the `draw` operation.
|
||||
* Transparent gray images have three layers. Two of them constitute the two-bit
|
||||
color information for the `draw` operation, and the third is the `alpha`
|
||||
operation mask.
|
||||
* Semi-transparent monochrome images also have three layers. Two are used to
|
||||
store the two-bit transparency level information (0 is opaque, 3 is fully
|
||||
transparent), and the third indicates the color.
|
||||
|
||||
Layers are encoded as a bit map. The image is split into a *grid*, which is
|
||||
made of 32-pixel *columns*, and an *end*.
|
||||
|
||||
32 32 32 end
|
||||
+------+------+------+---+
|
||||
| | | | |
|
||||
| | | | |
|
||||
| | | | |
|
||||
+------+------+------+---+
|
||||
|
||||
Bitmap
|
||||
|
||||
The first bytes of the layer data is the column data. Each column is encoded
|
||||
as a 32-bit integer array from top to bottom. Columns are written from left to
|
||||
right. The end is encoded as an 8-bit or 16-bit integer array depending on its
|
||||
size, and written from top to bottom. Additionally, 0 to 3 NUL (0x00) bytes are
|
||||
added to make the layer size a multiple of 4 (to allow 32-bit access to the
|
||||
column data of the following layer).
|
||||
|
||||
In case of big images (see the image structure below), the end is expanded to
|
||||
a 32-pixel column to improve performance.
|
||||
|
||||
The image itself is a structure of the following kind (in case of small
|
||||
images):
|
||||
|
||||
```c
|
||||
struct Image
|
||||
{
|
||||
unsigned char magic;
|
||||
unsigned char format;
|
||||
|
||||
unsigned char width;
|
||||
unsigned char height;
|
||||
|
||||
const uint32_t data[];
|
||||
|
||||
} __attribute__((aligned(4)));
|
||||
```
|
||||
|
||||
For bigger images (`width` > 255 or `height` > 255), both `width` and `height`
|
||||
are set to `0` and the actual size information is written on two shorts just
|
||||
where the data resides:
|
||||
|
||||
```c
|
||||
struct BigImage
|
||||
{
|
||||
unsigned char magic;
|
||||
unsigned char format;
|
||||
|
||||
unsigned char null_width; /* contains 0 */
|
||||
unsigned char null_height; /* contains 0 */
|
||||
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
|
||||
const uint32_t data[];
|
||||
|
||||
} __attribute__((aligned(4)));
|
||||
```
|
||||
|
||||
This does not create a memory loss because a two-byte gap was needed to make
|
||||
the data 4-aligned.
|
||||
|
||||
* The `magic` number, which is common to all the file formats of *gint*,
|
||||
identifies the file type and version of the structure. *bopti* will not render
|
||||
an image which is not encoded for its specific version.
|
||||
|
||||
* The `format` attribute describes the layer distribution, as specified by the
|
||||
following enum:
|
||||
|
||||
```c
|
||||
enum ImageFormat
|
||||
{
|
||||
ImageFormat_Mono = 0x01,
|
||||
ImageFormat_MonoAlpha = 0x09,
|
||||
ImageFormat_Gray = 0x06,
|
||||
ImageFormat_GrayAlpha = 0x0e,
|
||||
ImageFormat_GreaterAlpha = 0x31,
|
||||
|
||||
ImageFormat_ColorMask = 0x07,
|
||||
ImageFormat_AlphaMask = 0x38,
|
||||
};
|
||||
```
|
||||
|
||||
`Alpha` refers to uniform transparency. The only format that supports
|
||||
partial transparency is `GreaterAlpha`, and it is always encoded as
|
||||
monochrome (because using gray pixels would lead to 9 different colors,
|
||||
which is rather unoptimized). Gray images with partial transparency
|
||||
will be refused by *fxconv*.
|
||||
|
||||
|
||||
* The `width` and `height` attributes are exactly what you expect.
|
||||
|
||||
* The `data` is simply made of all the layers put one after another. Layers are
|
||||
put in the following order:
|
||||
|
||||
[0] Monochrome `draw` layer
|
||||
[1] Dark gray `draw` layer
|
||||
[2] Light gray `draw` layer
|
||||
[3] Uniform `alpha` layer
|
||||
[4] First semi-`alpha` layer
|
||||
[5] Second semi-`alpha` layer
|
||||
|
||||
Not every format uses the six layers, of course. The layers used by
|
||||
each format may be found by reading the position of the `1`'s in the
|
||||
corresponding `enum ImageFormat` entry. Layers that are not needed are
|
||||
skipped.
|
|
@ -1,673 +0,0 @@
|
|||
#ifndef _7305_H
|
||||
#define _7305_H 1
|
||||
|
||||
/*
|
||||
Double-underscore prefixed structures (e.g. __st_rtc_counter) are used
|
||||
internally but are not meant to be used in user programs.
|
||||
|
||||
Underscore-prefixed names (e.g. _R64CNT) are used to avoid name
|
||||
conflicts (e.g. STRUCTURE.RTC would expand to STRUCTURE.((T *)0x...)).
|
||||
*/
|
||||
|
||||
#pragma pack(push, 1)
|
||||
#define gap(n) unsigned: n << 3
|
||||
|
||||
//---
|
||||
// Interrupt controller, part 1.
|
||||
//---
|
||||
|
||||
struct _st_intc
|
||||
{
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned const NMIL :1;
|
||||
unsigned MAI :1;
|
||||
unsigned :4;
|
||||
unsigned NMIB :1;
|
||||
unsigned NMIE :1;
|
||||
unsigned :2;
|
||||
unsigned LVLMODE :1;
|
||||
unsigned :5;
|
||||
};
|
||||
} ICR0;
|
||||
|
||||
char gap1[14];
|
||||
|
||||
union {
|
||||
unsigned int LONG;
|
||||
struct {
|
||||
unsigned IRQ0 :4;
|
||||
unsigned IRQ1 :4;
|
||||
unsigned IRQ2 :4;
|
||||
unsigned IRQ3 :4;
|
||||
unsigned IRQ4 :4;
|
||||
unsigned IRQ5 :4;
|
||||
unsigned IRQ6 :4;
|
||||
unsigned IRQ7 :4;
|
||||
};
|
||||
} INTPRI00;
|
||||
|
||||
char gap2[8];
|
||||
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned IRQ0S :2;
|
||||
unsigned IRQ1S :2;
|
||||
unsigned IRQ2S :2;
|
||||
unsigned IRQ3S :2;
|
||||
unsigned IRQ4S :2;
|
||||
unsigned IRQ5S :2;
|
||||
unsigned IRQ6S :2;
|
||||
unsigned IRQ7S :2;
|
||||
};
|
||||
} ICR1;
|
||||
|
||||
char gap3[6];
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned IRQ0 :1;
|
||||
unsigned IRQ1 :1;
|
||||
unsigned IRQ2 :1;
|
||||
unsigned IRQ3 :1;
|
||||
unsigned IRQ4 :1;
|
||||
unsigned IRQ5 :1;
|
||||
unsigned IRQ6 :1;
|
||||
unsigned IRQ7 :1;
|
||||
};
|
||||
} INTREQ00;
|
||||
|
||||
char gap4[31];
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned IRQ0 :1;
|
||||
unsigned IRQ1 :1;
|
||||
unsigned IRQ2 :1;
|
||||
unsigned IRQ3 :1;
|
||||
unsigned IRQ4 :1;
|
||||
unsigned IRQ5 :1;
|
||||
unsigned IRQ6 :1;
|
||||
unsigned IRQ7 :1;
|
||||
};
|
||||
} INTMSK00;
|
||||
|
||||
char gap5[31];
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned _IRQ0 :1;
|
||||
unsigned _IRQ1 :1;
|
||||
unsigned _IRQ2 :1;
|
||||
unsigned _IRQ3 :1;
|
||||
unsigned _IRQ4 :1;
|
||||
unsigned _IRQ5 :1;
|
||||
unsigned _IRQ6 :1;
|
||||
unsigned _IRQ7 :1;
|
||||
};
|
||||
} INTMSKCLR00;
|
||||
|
||||
char gap6[91];
|
||||
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned const NMIL :1;
|
||||
unsigned :14;
|
||||
unsigned NMIFL :1;
|
||||
};
|
||||
} NMIFCR;
|
||||
|
||||
char gap7[6029118];
|
||||
|
||||
union {
|
||||
unsigned int LONG;
|
||||
struct {
|
||||
unsigned HEXA_A5 :8;
|
||||
unsigned :16;
|
||||
unsigned UIMASK :4;
|
||||
unsigned :4;
|
||||
};
|
||||
} USERIMSK;
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Interrupt controller, part 2.
|
||||
//---
|
||||
|
||||
struct _st_intx
|
||||
{
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned TMU0_0 :4;
|
||||
unsigned TMU0_1 :4;
|
||||
unsigned TMU0_2 :4;
|
||||
unsigned IrDA :4;
|
||||
};
|
||||
} IPRA;
|
||||
gap(2);
|
||||
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned JPU :4;
|
||||
unsigned LCDC :4;
|
||||
unsigned DMAC1A :4;
|
||||
unsigned BEU2_1 :4;
|
||||
};
|
||||
} IPRB;
|
||||
gap(2);
|
||||
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned TMU1_0 :4;
|
||||
unsigned TMU1_1 :4;
|
||||
unsigned TMU1_2 :4;
|
||||
unsigned SPU :4;
|
||||
};
|
||||
} IPRC;
|
||||
gap(2);
|
||||
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned :4;
|
||||
unsigned MMCIF :4;
|
||||
unsigned :4;
|
||||
unsigned ATAPI :4;
|
||||
};
|
||||
} IPRD;
|
||||
gap(2);
|
||||
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned DMAC0A :4;
|
||||
unsigned VARIOUS :4;
|
||||
unsigned SCIFA3 :4;
|
||||
unsigned VPU5F :4;
|
||||
};
|
||||
} IPRE;
|
||||
gap(2);
|
||||
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned _KEYSC :4;
|
||||
unsigned DMAC0B :4;
|
||||
unsigned USB01 :4;
|
||||
unsigned CMT :4;
|
||||
};
|
||||
} IPRF;
|
||||
gap(2);
|
||||
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned SCIF0 :4;
|
||||
unsigned SCIF1 :4;
|
||||
unsigned SCIF2 :4;
|
||||
unsigned VEU3F0 :4;
|
||||
};
|
||||
} IPRG;
|
||||
gap(2);
|
||||
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned MSIOF0 :4;
|
||||
unsigned MSIOF1 :4;
|
||||
unsigned I2C1 :4;
|
||||
unsigned I2C0 :4;
|
||||
};
|
||||
} IPRH;
|
||||
gap(2);
|
||||
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned SCIFA4 :4;
|
||||
unsigned ICB :4;
|
||||
unsigned TSIF :4;
|
||||
unsigned _2DG_ICB :4;
|
||||
};
|
||||
} IPRI;
|
||||
gap(2);
|
||||
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned CEU2_1 :4;
|
||||
unsigned EtherMAC :4;
|
||||
unsigned FSI :4;
|
||||
unsigned SDHI1 :4;
|
||||
};
|
||||
} IPRJ;
|
||||
gap(2);
|
||||
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned _RTC :4;
|
||||
unsigned DMAC1B :4;
|
||||
unsigned ICB :4;
|
||||
unsigned SDHI0 :4;
|
||||
};
|
||||
} IPRK;
|
||||
gap(2);
|
||||
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned SCIFA5 :4;
|
||||
unsigned :4;
|
||||
unsigned TPU :4;
|
||||
unsigned _2DDMAC :4;
|
||||
};
|
||||
} IPRL;
|
||||
char gap1[82];
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :1;
|
||||
unsigned TUNI2 :1;
|
||||
unsigned TUNI1 :1;
|
||||
unsigned TUNI0 :1;
|
||||
unsigned SDHII3 :1;
|
||||
unsigned SDHII2 :1;
|
||||
unsigned SDHII1 :1;
|
||||
unsigned SDHII0 :1;
|
||||
};
|
||||
} IMR0;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned VOUI :1;
|
||||
unsigned VEU1I :1;
|
||||
unsigned BEU0I :1;
|
||||
unsigned CEUOI :1;
|
||||
unsigned DEI3 :1;
|
||||
unsigned DEI2 :1;
|
||||
unsigned DEI1 :1;
|
||||
unsigned DEI0 :1;
|
||||
};
|
||||
} IMR1;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :3;
|
||||
unsigned VPUI :1;
|
||||
unsigned ATAPI :1;
|
||||
unsigned EtherMAC :1;
|
||||
unsigned :1;
|
||||
unsigned SCIFA0 :1;
|
||||
};
|
||||
} IMR2;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned DEI3 :1;
|
||||
unsigned DEI2 :1;
|
||||
unsigned DEI1 :1;
|
||||
unsigned DEI0 :1;
|
||||
unsigned :3;
|
||||
unsigned IRDAI :1;
|
||||
};
|
||||
} IMR3;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :1;
|
||||
unsigned TUNI2 :1;
|
||||
unsigned TUNI1 :1;
|
||||
unsigned TUNI0 :1;
|
||||
unsigned JPUI :1;
|
||||
unsigned :2;
|
||||
unsigned LCDCI :1;
|
||||
};
|
||||
} IMR4;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned KEYI :1;
|
||||
unsigned DADERR :1;
|
||||
unsigned DEI5 :1;
|
||||
unsigned DEI4 :1;
|
||||
unsigned VEU0I :1;
|
||||
unsigned SCIF2 :1;
|
||||
unsigned SCIF1 :1;
|
||||
unsigned SCIF0 :1;
|
||||
};
|
||||
} IMR5;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :2;
|
||||
unsigned ICBI :1;
|
||||
unsigned SCIFA4 :1;
|
||||
unsigned CEU1I :1;
|
||||
unsigned :1;
|
||||
unsigned MSIOFI0 :1;
|
||||
unsigned MSIOFI1 :1;
|
||||
};
|
||||
} IMR6;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned DTE0I :1;
|
||||
unsigned WAITOI :1;
|
||||
unsigned TACK0I :1;
|
||||
unsigned AL0I :1;
|
||||
unsigned DTE1I :1;
|
||||
unsigned WAIT1I :1;
|
||||
unsigned TACK1I :1;
|
||||
unsigned AL1I :1;
|
||||
};
|
||||
} IMR7;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned SDHII3 :1;
|
||||
unsigned SDHII2 :1;
|
||||
unsigned SDHII1 :1;
|
||||
unsigned SDHII0 :1;
|
||||
unsigned :2;
|
||||
unsigned SCFIA5 :1;
|
||||
unsigned FSI :1;
|
||||
};
|
||||
} IMR8;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :3;
|
||||
unsigned CMTI :1;
|
||||
unsigned :1;
|
||||
unsigned USI1 :1;
|
||||
unsigned USI0 :1;
|
||||
unsigned :1;
|
||||
};
|
||||
} IMR9;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :1;
|
||||
unsigned DADERR :1;
|
||||
unsigned DEI5 :1;
|
||||
unsigned DEI4 :1;
|
||||
unsigned :1;
|
||||
unsigned ATI :1;
|
||||
unsigned PRI :1;
|
||||
unsigned CUI :1;
|
||||
};
|
||||
} IMR10;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned BRK :1;
|
||||
unsigned CEI :1;
|
||||
unsigned INI :1;
|
||||
unsigned TRI :1;
|
||||
unsigned :1;
|
||||
unsigned TPUI :1;
|
||||
unsigned LMBI :1;
|
||||
unsigned TSIFI :1;
|
||||
};
|
||||
} IMR11;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :7;
|
||||
unsigned _2DDMAC :1;
|
||||
};
|
||||
} IMR12;
|
||||
char gap2[15];
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :1;
|
||||
unsigned TUNI2 :1;
|
||||
unsigned TUNI1 :1;
|
||||
unsigned TUNI0 :1;
|
||||
unsigned SDHII3 :1;
|
||||
unsigned SDHII2 :1;
|
||||
unsigned SDHII1 :1;
|
||||
unsigned SDHII0 :1;
|
||||
};
|
||||
} _IMCR0;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned VOUI :1;
|
||||
unsigned VEU1I :1;
|
||||
unsigned BEU0I :1;
|
||||
unsigned CEUOI :1;
|
||||
unsigned DEI3 :1;
|
||||
unsigned DEI2 :1;
|
||||
unsigned DEI1 :1;
|
||||
unsigned DEI0 :1;
|
||||
};
|
||||
} _IMCR1;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :3;
|
||||
unsigned VPUI :1;
|
||||
unsigned ATAPI :1;
|
||||
unsigned EtherMAC :1;
|
||||
unsigned :1;
|
||||
unsigned SCIFA0 :1;
|
||||
};
|
||||
} _IMCR2;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned DEI3 :1;
|
||||
unsigned DEI2 :1;
|
||||
unsigned DEI1 :1;
|
||||
unsigned DEI0 :1;
|
||||
unsigned :3;
|
||||
unsigned IRDAI :1;
|
||||
};
|
||||
} _IMCR3;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :1;
|
||||
unsigned TUNI2 :1;
|
||||
unsigned TUNI1 :1;
|
||||
unsigned TUNI0 :1;
|
||||
unsigned JPUI :1;
|
||||
unsigned :2;
|
||||
unsigned LCDCI :1;
|
||||
};
|
||||
} _IMCR4;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned KEYI :1;
|
||||
unsigned DADERR :1;
|
||||
unsigned DEI5 :1;
|
||||
unsigned DEI4 :1;
|
||||
unsigned VEU0I :1;
|
||||
unsigned SCIF2 :1;
|
||||
unsigned SCIF1 :1;
|
||||
unsigned SCIF0 :1;
|
||||
};
|
||||
} _IMCR5;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :2;
|
||||
unsigned ICBI :1;
|
||||
unsigned SCIFA4 :1;
|
||||
unsigned CEU1I :1;
|
||||
unsigned :1;
|
||||
unsigned MSIOFI0 :1;
|
||||
unsigned MSIOFI1 :1;
|
||||
};
|
||||
} _IMCR6;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned DTE0I :1;
|
||||
unsigned WAITOI :1;
|
||||
unsigned TACK0I :1;
|
||||
unsigned AL0I :1;
|
||||
unsigned DTE1I :1;
|
||||
unsigned WAIT1I :1;
|
||||
unsigned TACK1I :1;
|
||||
unsigned AL1I :1;
|
||||
};
|
||||
} _IMCR7;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned SDHII3 :1;
|
||||
unsigned SDHII2 :1;
|
||||
unsigned SDHII1 :1;
|
||||
unsigned SDHII0 :1;
|
||||
unsigned :2;
|
||||
unsigned SCFIA5 :1;
|
||||
unsigned FSI :1;
|
||||
};
|
||||
} _IMCR8;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :3;
|
||||
unsigned CMTI :1;
|
||||
unsigned :1;
|
||||
unsigned USI1 :1;
|
||||
unsigned USI0 :1;
|
||||
unsigned :1;
|
||||
};
|
||||
} _IMCR9;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :1;
|
||||
unsigned DADERR :1;
|
||||
unsigned DEI5 :1;
|
||||
unsigned DEI4 :1;
|
||||
unsigned :1;
|
||||
unsigned ATI :1;
|
||||
unsigned PRI :1;
|
||||
unsigned CUI :1;
|
||||
};
|
||||
} _IMCR10;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned BRK :1;
|
||||
unsigned CEI :1;
|
||||
unsigned INI :1;
|
||||
unsigned TRI :1;
|
||||
unsigned :1;
|
||||
unsigned TPUI :1;
|
||||
unsigned LMBI :1;
|
||||
unsigned TSIFI :1;
|
||||
};
|
||||
} _IMCR11;
|
||||
gap(3);
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :7;
|
||||
unsigned _2DDMAC :1;
|
||||
};
|
||||
} _IMCR12;
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
|
||||
#define INTC (*(volatile struct _st_intc *)0xa4140000)
|
||||
#define INTX (*(volatile struct _st_intx *)0xa4080000)
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif // _7305_H
|
|
@ -1,23 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// standard library module: alloca
|
||||
//
|
||||
// Allows dynamic memory allocation on the stack. Memory is automatically
|
||||
// freed when the calling function exits.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _ALLOCA_H
|
||||
#define _ALLOCA_H 1
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
alloca()
|
||||
Allocates a memory block on the stack.
|
||||
*/
|
||||
void *alloca(size_t size);
|
||||
|
||||
#define alloca(size) __builtin_alloca(size)
|
||||
|
||||
#endif // _ALLOCA_H
|
|
@ -1,128 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// gint core module: clock
|
||||
//
|
||||
// Measures the frequency of the MPU clocks. This module assumes that the
|
||||
// clock mode is 3 on SH7305 (as does FTune).
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _CLOCK_H
|
||||
#define _CLOCK_H
|
||||
|
||||
//---
|
||||
// Some type declarations.
|
||||
//---
|
||||
|
||||
enum Clock
|
||||
{
|
||||
Clock_CKIO = 0, // SH7705
|
||||
Clock_RTCCLK = 1, // SH7305
|
||||
Clock_Bphi = 2,
|
||||
Clock_Iphi = 3,
|
||||
Clock_Pphi = 4,
|
||||
};
|
||||
|
||||
enum ClockUnit
|
||||
{
|
||||
Clock_us = 0,
|
||||
Clock_ms = 1,
|
||||
Clock_s = 2,
|
||||
|
||||
Clock_Hz = 10,
|
||||
Clock_kHz = 11,
|
||||
Clock_MHz = 12,
|
||||
};
|
||||
|
||||
struct ClockConfig
|
||||
{
|
||||
union
|
||||
{
|
||||
int PLL1; // SH7705
|
||||
int FLL; // SH7305
|
||||
};
|
||||
union
|
||||
{
|
||||
int PLL2; // SH7705
|
||||
int PLL; // SH7305
|
||||
};
|
||||
|
||||
int Bphi_div1;
|
||||
int Iphi_div1;
|
||||
int Pphi_div1;
|
||||
|
||||
union
|
||||
{
|
||||
int CKIO_f; // SH7705
|
||||
int RTCCLK_f; // SH7305
|
||||
};
|
||||
|
||||
int Bphi_f;
|
||||
int Iphi_f;
|
||||
int Pphi_f;
|
||||
};
|
||||
|
||||
//---
|
||||
// Public API.
|
||||
//---
|
||||
|
||||
/*
|
||||
clock_frequency()
|
||||
Returns the approximate frequency, in Hz, of the given clock. The
|
||||
measurements need to have been done. Returns a negative number on
|
||||
error.
|
||||
*/
|
||||
int clock_frequency(enum Clock clock);
|
||||
|
||||
/*
|
||||
clock_setting()
|
||||
Returns the P_phi / 4 timer setting that will last for the given time.
|
||||
Several units can be used. Be aware that the result is approximate, and
|
||||
very high frequencies or very short delays will yield important errors.
|
||||
*/
|
||||
int clock_setting(int duration, enum ClockUnit unit);
|
||||
|
||||
/*
|
||||
clock_config()
|
||||
Returns a copy of the clock configuration.
|
||||
*/
|
||||
struct ClockConfig clock_config(void);
|
||||
|
||||
/*
|
||||
sleep()
|
||||
Sleeps until an interrupt is accepted.
|
||||
*/
|
||||
void sleep(void);
|
||||
|
||||
/*
|
||||
sleep_us()
|
||||
Sleeps for the given number of us using the user timer. The result will
|
||||
always be slightly less than required.
|
||||
*/
|
||||
void sleep_us(int us_delay);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Internal API.
|
||||
// Referenced for documentation purposes only. Do not use.
|
||||
//---
|
||||
|
||||
/*
|
||||
clock_measure()
|
||||
Begins the frequency measurements. The measurements will end
|
||||
automatically. While doing measurements, do not use the RTC interrupt
|
||||
or the user timer.
|
||||
Call clock_measure_end() to wait until the measurements are finished.
|
||||
It is possible to execute code during the measurements, so that less
|
||||
time is spent.
|
||||
*/
|
||||
void clock_measure(void);
|
||||
|
||||
/*
|
||||
clock_measure_end()
|
||||
Waits until the measurements are finished. This may be immediate.
|
||||
*/
|
||||
void clock_measure_end(void);
|
||||
|
||||
#endif // _CLOCK_H
|
|
@ -1,35 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// standard library module: ctype
|
||||
//
|
||||
// Some character manipulation.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _CTYPE_H
|
||||
#define _CTYPE_H 1
|
||||
|
||||
// Character definition macros.
|
||||
#define isalnum(c) (isdigit(c) || isalpha(c))
|
||||
#define isalpha(c) (islower(c) || isupper(c))
|
||||
|
||||
#define iscntrl(c) ((c) <= 0x1f || (c) == 0x7f)
|
||||
#define isdigit(c) ((c) >= '0' && (c) <= '9')
|
||||
#define isgraph(c) ((c) > ' ' && (c) < 0x7f)
|
||||
#define islower(c) ((c) >= 'a' && (c) <= 'z')
|
||||
#define isprint(c) ((c) >= ' ' && (c) < 0x7f)
|
||||
#define ispunct(c) (((c) >= '!' && (c) <= '/') || \
|
||||
((c) >= ':' && (c) <= '@') || \
|
||||
((c) >= '[' && (c) <= '`') || \
|
||||
((c) >= '{' && (c) <= '~'))
|
||||
#define isspace(c) (((c) >= '\t' && (c) <= '\r') || (c) == ' ')
|
||||
#define isupper(c) ((c) >= 'A' && (c) <= 'Z')
|
||||
#define isxdigit(c) (((c) >= '0' && (c) <= '9') || \
|
||||
((c) >= 'A' && (c) <= 'F') || \
|
||||
((c) >= 'a' && (c) <= 'f'))
|
||||
|
||||
// Character manipulation macros.
|
||||
#define tolower(c) (isupper(c) ? (c) | 32 : (c))
|
||||
#define toupper(c) (islower(c) ? (c) & ~32 : (c))
|
||||
|
||||
#endif // _CTYPE_H
|
|
@ -1,161 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// gint drawing module: display
|
||||
//
|
||||
// Handles vram manipulation and drawing for plain monochrome display.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _DISPLAY_H
|
||||
#define _DISPLAY_H 1
|
||||
|
||||
|
||||
//---
|
||||
// Heading declarations.
|
||||
//---
|
||||
|
||||
enum Color
|
||||
{
|
||||
Color_White = 0,
|
||||
Color_Light = 1,
|
||||
Color_Dark = 2,
|
||||
Color_Black = 3,
|
||||
Color_None = 4,
|
||||
Color_Invert = 5,
|
||||
};
|
||||
|
||||
// This header needs enum Color to be defined.
|
||||
#include <tales.h>
|
||||
|
||||
/*
|
||||
struct Image
|
||||
This structure holds information about a bitmap encoded with fxconv.
|
||||
Data is accessed using longword operations, which *requires* many
|
||||
sizes to be multiples of 4 (structure alignment, data alignment, layer
|
||||
size, ...).
|
||||
*/
|
||||
struct Image
|
||||
{
|
||||
unsigned char magic;
|
||||
unsigned char format;
|
||||
|
||||
unsigned char width;
|
||||
unsigned char height;
|
||||
|
||||
const unsigned char __attribute__((aligned(4))) data[];
|
||||
|
||||
} __attribute__((aligned(4)));
|
||||
// Useful shorthand for user code.
|
||||
typedef struct Image Image;
|
||||
|
||||
|
||||
|
||||
// A few other constants.
|
||||
#define DISPLAY_WIDTH 128
|
||||
#define DISPLAY_HEIGHT 64
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Generic functions.
|
||||
//---
|
||||
|
||||
/*
|
||||
display_getLocalVRAM()
|
||||
Returns the local video ram address. This function always return the
|
||||
same address.
|
||||
The buffer returned by this function should not be used directly when
|
||||
running the gray engine.
|
||||
*/
|
||||
void *display_getLocalVRAM(void);
|
||||
|
||||
/*
|
||||
display_getCurrentVRAM()
|
||||
Returns the current video ram. This function usually returns the
|
||||
parameter of the last call to display_useVRAM(), unless the gray engine
|
||||
is running (in which case the result is undefined). Returns the local
|
||||
vram address by default.
|
||||
*/
|
||||
void *display_getCurrentVRAM(void);
|
||||
|
||||
/*
|
||||
display_useVRAM()
|
||||
Changes the current video ram address. The argument MUST be a 4-
|
||||
aligned 1024-byte buffer; otherwise any drawing operation will crash
|
||||
the program.
|
||||
This function will most likely have no effect when running the gray
|
||||
engine.
|
||||
*/
|
||||
void display_useVRAM(void *vram);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Global drawing functions.
|
||||
//---
|
||||
|
||||
/*
|
||||
dupdate()
|
||||
Displays the vram on the physical screen. Does nothing when the gray
|
||||
engine is running.
|
||||
*/
|
||||
void dupdate(void);
|
||||
|
||||
/*
|
||||
dclear()
|
||||
Clears the whole video ram.
|
||||
*/
|
||||
void dclear(void);
|
||||
|
||||
/*
|
||||
dclear_area()
|
||||
Clears an area of the video ram. Both (x1, y1) and (x2, y2) are
|
||||
cleared.
|
||||
*/
|
||||
void dclear_area(int x1, int y1, int x2, int y2);
|
||||
|
||||
/*
|
||||
dreverse_area()
|
||||
Reverses an area of the vram. (x1, y1) and (x2, y2) are reversed as
|
||||
well.
|
||||
*/
|
||||
void dreverse_area(int x1, int y1, int x2, int y2);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Local drawing functions.
|
||||
//---
|
||||
|
||||
/*
|
||||
dpixel()
|
||||
Puts a pixel in the vram.
|
||||
*/
|
||||
void dpixel(int x, int y, enum Color color);
|
||||
|
||||
/*
|
||||
dline()
|
||||
Draws a line in the vram. Automatically optimizes horizontal and
|
||||
vertical lines.
|
||||
|
||||
Uses an algorithm written by PierrotLL for MonochromeLib.
|
||||
*/
|
||||
void dline(int x1, int y1, int x2, int y2, enum Color color);
|
||||
|
||||
/*
|
||||
dimage()
|
||||
Displays a monochrome image in the vram. Does a real lot of
|
||||
optimization.
|
||||
*/
|
||||
void dimage(int x, int y, struct Image *image);
|
||||
|
||||
/*
|
||||
dimage_part()
|
||||
Draws a portion of an image, defined by its bounding rectangle.
|
||||
Point (left, top) is included, but (left + width, top + height) is
|
||||
excluded.
|
||||
*/
|
||||
void dimage_part(int x, int y, struct Image *img, int left, int top,
|
||||
int width, int height);
|
||||
|
||||
#endif // _DISPLAY_H
|
|
@ -1,84 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// gint core module: events
|
||||
//
|
||||
// Finally some user-friendly API.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _EVENTS_H
|
||||
#define _EVENTS_H
|
||||
|
||||
//---
|
||||
// Type definitions.
|
||||
//---
|
||||
|
||||
/*
|
||||
enum EventType
|
||||
Something user programs will surely use most often.
|
||||
*/
|
||||
enum EventType
|
||||
{
|
||||
EventType_None = 0,
|
||||
ET_None = EventType_None,
|
||||
|
||||
EventType_User = 1,
|
||||
ET_User = EventType_User,
|
||||
|
||||
EventType_KeyPressed = 2,
|
||||
ET_KeyPress = EventType_KeyPressed,
|
||||
|
||||
EventType_KeyReleased = 3,
|
||||
ET_KeyRel = EventType_KeyReleased,
|
||||
};
|
||||
|
||||
/*
|
||||
struct Event
|
||||
Wake up, something's going on. The union member that holds information
|
||||
about the event is implicitly defined by the type attribute.
|
||||
*/
|
||||
struct Event
|
||||
{
|
||||
enum EventType type;
|
||||
|
||||
union
|
||||
{
|
||||
// For ET_User.
|
||||
void *data;
|
||||
// For ET_KeyPress and ET_KeyRel.
|
||||
int key;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Event management.
|
||||
//---
|
||||
|
||||
/*
|
||||
event_push()
|
||||
Queues a user-defined event, allowing it to be retrieved by getevent()
|
||||
or pollevent() later. Most often you will not need to use this, as
|
||||
system events are automatically queued. Pushing ET_None events is not
|
||||
allowed.
|
||||
Returns non-zero on error.
|
||||
*/
|
||||
int event_push(struct Event event);
|
||||
|
||||
/*
|
||||
getevent()
|
||||
Returns the next event. If no one is available, waits for something to
|
||||
happen. This function uses low-level sleep and should be preferred to
|
||||
active waiting using loops.
|
||||
*/
|
||||
struct Event getevent(void);
|
||||
|
||||
/*
|
||||
pollevent()
|
||||
Returns the next event. If no one is available, returns an event whose
|
||||
type is ET_None. This function always returns immediately.
|
||||
*/
|
||||
struct Event pollevent(void);
|
||||
|
||||
#endif // _EVENTS_H
|
|
@ -1,192 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// gint core module: interrupt handler
|
||||
//
|
||||
// Central point of the library. Controls the interrupt handler and
|
||||
// defines a few functions to configure callbacks for some interrupts.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _GINT_H
|
||||
#define _GINT_H 1
|
||||
|
||||
#define GINT_VERSION 0x01000000
|
||||
#define GINT_VERSION_STR "01.00"
|
||||
|
||||
//---
|
||||
// Interrupt handler control.
|
||||
//---
|
||||
|
||||
/*
|
||||
gint_getVBR()
|
||||
Returns the current vbr address.
|
||||
*/
|
||||
unsigned int gint_getVBR(void);
|
||||
|
||||
/*
|
||||
gint_systemVBR()
|
||||
Returns the vbr address used by the system (saved when execution
|
||||
starts).
|
||||
*/
|
||||
unsigned int gint_systemVBR(void);
|
||||
|
||||
/*
|
||||
gint_setDefaultHandler()
|
||||
In case gint receives an interrupt it doesn't recognize, it can fall
|
||||
back to a user-provided interrupt handler. Set it to NULL to disable
|
||||
this feature.
|
||||
Be aware that the event code passed to the default handler will either
|
||||
be INTEVT2 (SH7705) or INTEVT (SH7305), but its value for each
|
||||
interrupt source is completely platform-dependent. Remember to handle
|
||||
both platforms for increased portability, if possible.
|
||||
*/
|
||||
void gint_setDefaultHandler(void (*default_handler)(int event_code));
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Register access.
|
||||
//---
|
||||
|
||||
/*
|
||||
enum Register
|
||||
Represents common registers. Used as identifiers to retrieve their
|
||||
values using gint_register().
|
||||
*/
|
||||
enum Register
|
||||
{
|
||||
Register_EXPEVT,
|
||||
Register_MMUCR,
|
||||
Register_TEA,
|
||||
};
|
||||
|
||||
/*
|
||||
gint_register()
|
||||
Returns the address of a common register. All common registers exist
|
||||
on both platforms but they may hold different values for the same
|
||||
information (f.i. EXPEVT may not return the same value for a given
|
||||
exception on both 7705 and 7305).
|
||||
*/
|
||||
volatile void *gint_reg(enum Register reg);
|
||||
|
||||
/*
|
||||
gint_strerror()
|
||||
Returns a string that describe the error set in EXPEVT in case of
|
||||
general exception of TLB miss exception. This string is platform-
|
||||
independent.
|
||||
Some exception codes represent different errors when invoked inside the
|
||||
general exception handler and the TLB error handler. Parameter 'is_tlb'
|
||||
should be set to zero for general exception meanings, and anything non-
|
||||
zero for TLB error meanings.
|
||||
*/
|
||||
const char *gint_strerror(int is_tlb);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Internal API.
|
||||
// Referenced here for documentation purposes only.
|
||||
// Do NOT call these functions, you'll most probably screw up the whole
|
||||
// interrupt handling system.
|
||||
//---
|
||||
|
||||
/*
|
||||
gint_setVBR()
|
||||
Sets the vbr address and calls the configuration function while
|
||||
interrupts are disabled.
|
||||
*/
|
||||
void gint_setVBR(unsigned int new_vbr_address, void (*setup)(void));
|
||||
|
||||
/*
|
||||
gint_callDefaultHandler()
|
||||
Calls the user-provided default interrupt handler.
|
||||
*/
|
||||
void gint_callDefaultHandler(int event_code);
|
||||
|
||||
/*
|
||||
gint_init()
|
||||
Initializes gint. Loads the interrupt handler into the memory and sets
|
||||
the new vbr address.
|
||||
*/
|
||||
void gint_init(void);
|
||||
|
||||
/*
|
||||
gint_quit()
|
||||
Stops gint. Restores the system's configuration and vbr address.
|
||||
*/
|
||||
void gint_quit(void);
|
||||
|
||||
/*
|
||||
gint_setup()
|
||||
Configures interrupt priorities and some parameters to allow gint to
|
||||
take control of the interrupt flow.
|
||||
*/
|
||||
void gint_setup_7705(void);
|
||||
void gint_setup_7305(void);
|
||||
|
||||
/*
|
||||
gint_stop()
|
||||
Un-configures the interrupt flow to give back the interrupt control to
|
||||
the system.
|
||||
*/
|
||||
void gint_stop_7705(void);
|
||||
void gint_stop_7305(void);
|
||||
|
||||
/*
|
||||
gint_reg()
|
||||
gint_strerror()
|
||||
See "Register access" section.
|
||||
*/
|
||||
volatile void *gint_reg_7705(enum Register reg);
|
||||
volatile void *gint_reg_7305(enum Register reg);
|
||||
const char *gint_strerror_7705(int is_tlb);
|
||||
const char *gint_strerror_7305(void);
|
||||
|
||||
|
||||
//---
|
||||
// Exception handling.
|
||||
//---
|
||||
|
||||
/*
|
||||
gint_exc()
|
||||
Handles exceptions.
|
||||
*/
|
||||
void gint_exc(void) __attribute__((section(".gint.exc.entry"),
|
||||
interrupt_handler));
|
||||
void gint_exc_7705(void) __attribute__((section(".gint.exc")));
|
||||
void gint_exc_7305(void) __attribute__((section(".gint.exc")));
|
||||
|
||||
/*
|
||||
gint_tlb()
|
||||
Handles TLB misses.
|
||||
*/
|
||||
void gint_tlb(void) __attribute__((section(".gint.tlb.entry"),
|
||||
interrupt_handler));
|
||||
void gint_tlb_7705(void) __attribute__((section(".gint.tlb")));
|
||||
void gint_tlb_7305(void) __attribute__((section(".gint.tlb")));
|
||||
|
||||
/*
|
||||
gint_int()
|
||||
Handles interrupts.
|
||||
*/
|
||||
void gint_int(void) __attribute__((section(".gint.int.entry"),
|
||||
interrupt_handler));
|
||||
void gint_int_7705(void) __attribute__((section(".gint.int")));
|
||||
void gint_int_7305(void) __attribute__((section(".gint.int")));
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Internal platform-independent definitions.
|
||||
//---
|
||||
|
||||
#define GINT_INTP_WDT 4
|
||||
#define GINT_INTP_RTC 12
|
||||
|
||||
#define GINT_INTP_GRAY 15
|
||||
#define GINT_INTP_KEY 8
|
||||
#define GINT_INTP_TIMER 10
|
||||
|
||||
|
||||
|
||||
#endif // _GINT_H
|
|
@ -1,160 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// gint core/drawing module: gray
|
||||
//
|
||||
// Runs the gray engine and handles drawing for the dual-buffer system.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _GRAY_H
|
||||
#define _GRAY_H 1
|
||||
|
||||
#include <display.h>
|
||||
|
||||
//---
|
||||
// Engine control.
|
||||
//---
|
||||
|
||||
/*
|
||||
gray_runs()
|
||||
Returns 1 if the gray engine is running, 0 otherwise.
|
||||
*/
|
||||
int gray_runs(void);
|
||||
|
||||
/*
|
||||
gray_start()
|
||||
Starts the gray engine. The control of the screen is transferred to the
|
||||
gray engine.
|
||||
*/
|
||||
void gray_start(void);
|
||||
|
||||
/*
|
||||
gray_stop()
|
||||
Stops the gray engine. The monochrome display system takes control of
|
||||
the video ram.
|
||||
*/
|
||||
void gray_stop(void);
|
||||
|
||||
/*
|
||||
gray_lightVRAM()
|
||||
Returns the module's light gray vram address.
|
||||
*/
|
||||
void *gray_lightVRAM(void);
|
||||
|
||||
/*
|
||||
gray_darkVRAM()
|
||||
Returns the module's dark gray vram address.
|
||||
*/
|
||||
void *gray_darkVRAM(void);
|
||||
|
||||
/*
|
||||
gray_getDelays()
|
||||
Returns the gray engine delays. Pointers are not set if NULL.
|
||||
*/
|
||||
void gray_getDelays(int *light, int *dark);
|
||||
|
||||
/*
|
||||
gray_setDelays()
|
||||
Changes the gray engine delays. Usually you don't need to call this,
|
||||
because the engine has its default values.
|
||||
Finding values that give proper grays is quite the hard part of the
|
||||
gray engine. Usual values are about 1000, with light being between 75
|
||||
and 90% of dark.
|
||||
|
||||
Typical values:
|
||||
|
||||
values stability stripes colors
|
||||
---------------------------------------------------------
|
||||
860, 1298 excellent worst static good
|
||||
912, 1343 bad none very good (default)
|
||||
993, 1609 medium light fast good
|
||||
1325, 1607 bad light fast excellent
|
||||
---------------------------------------------------------
|
||||
*/
|
||||
void gray_setDelays(int light, int dark);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Global drawing functions.
|
||||
//---
|
||||
|
||||
/*
|
||||
gupdate()
|
||||
Swaps the vram buffer sets.
|
||||
*/
|
||||
void gupdate(void);
|
||||
|
||||
/*
|
||||
gclear()
|
||||
Clears the video ram.
|
||||
*/
|
||||
void gclear(void);
|
||||
|
||||
/*
|
||||
gclear_area()
|
||||
Clears an area of the video ram. End points (x1, y1) and (x2, y2) are
|
||||
included.
|
||||
*/
|
||||
void gclear_area(int x1, int y1, int x2, int y2);
|
||||
|
||||
/*
|
||||
greverse_area()
|
||||
Reverses an area of the vram. End points (x1, y1) and (x2, y2) are
|
||||
included.
|
||||
*/
|
||||
void greverse_area(int x1, int y1, int x2, int y2);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Local drawing functions.
|
||||
//---
|
||||
|
||||
/*
|
||||
gpixel()
|
||||
Puts a pixel in the vram.
|
||||
*/
|
||||
void gpixel(int x, int y, enum Color color);
|
||||
|
||||
/*
|
||||
gline()
|
||||
Draws a line in the vram. Automatically optimizes special cases.
|
||||
*/
|
||||
void gline(int x1, int y1, int x2, int y2, enum Color color);
|
||||
|
||||
/*
|
||||
gimage()
|
||||
Displays a gray image in the vram.
|
||||
*/
|
||||
void gimage(int x, int y, struct Image *image);
|
||||
|
||||
/*
|
||||
gimage_part()
|
||||
Draws a portion of a gray image, defined by its bounding rectangle.
|
||||
Point (left, top) is included, but (left + width, top + height) is
|
||||
excluded.
|
||||
*/
|
||||
void gimage_part(int x, int y, struct Image *image, int left, int top,
|
||||
int width, int height);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Internal API.
|
||||
// Referenced here for documentation purposes only. Do not call.
|
||||
//--
|
||||
|
||||
/*
|
||||
gray_interrupt()
|
||||
Answers a timer interrupt. Swaps the two buffers.
|
||||
*/
|
||||
void gray_interrupt(void) __attribute__((section(".gint.int")));
|
||||
|
||||
/*
|
||||
gray_init()
|
||||
Initializes the gray engine.
|
||||
*/
|
||||
void gray_init(void) __attribute__((constructor));
|
||||
|
||||
#endif // _GRAY_H
|
|
@ -1,160 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// gint drawing module: bopti
|
||||
//
|
||||
// bopti does every job related to display images. There is only one
|
||||
// public function, but there are lots of internal optimizations.
|
||||
//
|
||||
// Some bit-manipulation expressions may look written out of nowhere. The
|
||||
// idea is always the same: get a part of the image in an 'operator',
|
||||
// which is a 32-bit variable, shift this operator so that its bits
|
||||
// correspond to the desired position for the bitmap on the screen, and
|
||||
// edit the video-ram long entry which correspond to this position using
|
||||
// a 'mask' that indicates which bits of the operator contain information.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _INTERNALS_BOPTI_H
|
||||
#define _INTERNALS_BOPTI_H 1
|
||||
|
||||
#include <stdint.h>
|
||||
#include <display.h>
|
||||
|
||||
/*
|
||||
enum Channel
|
||||
Determines the kind of information written into a layer. Every image is
|
||||
made of one or more channels.
|
||||
*/
|
||||
enum Channel
|
||||
{
|
||||
Channel_FullAlpha = 0x01,
|
||||
Channel_LightAlpha = 0x02,
|
||||
Channel_DarkAlpha = 0x04,
|
||||
|
||||
Channel_Mono = 0x08,
|
||||
Channel_Light = 0x10,
|
||||
Channel_Dark = 0x20,
|
||||
};
|
||||
|
||||
/*
|
||||
enum Format
|
||||
Describes the various combination of channels allowed by bopti.
|
||||
*/
|
||||
enum Format
|
||||
{
|
||||
Format_Mono = Channel_Mono,
|
||||
Format_MonoAlpha = Format_Mono | Channel_FullAlpha,
|
||||
Format_Gray = Channel_Light | Channel_Dark,
|
||||
Format_GrayAlpha = Format_Gray | Channel_FullAlpha,
|
||||
Format_GreaterAlpha = Format_Mono | Channel_LightAlpha |
|
||||
Channel_DarkAlpha
|
||||
};
|
||||
|
||||
/*
|
||||
struct Structure
|
||||
Describes an image's structure.
|
||||
*/
|
||||
struct Structure
|
||||
{
|
||||
int width, height;
|
||||
int layer_size;
|
||||
|
||||
const unsigned char *data;
|
||||
int columns;
|
||||
int end_size, end_bytes;
|
||||
};
|
||||
|
||||
/*
|
||||
struct Command
|
||||
Contains a drawing operation's parameters.
|
||||
*/
|
||||
struct Command
|
||||
{
|
||||
// Channel being drawn.
|
||||
enum Channel channel;
|
||||
// Operation used (whether bopti_op_mono() or bopti_op_gray()).
|
||||
void (*op)(int offset, uint32_t operator, struct Command *command);
|
||||
// Portion of the bitmap which is drawn. 'top' and 'bottom' refer to
|
||||
// lines where 'left' and 'right' refer to column ids.
|
||||
int left, right, top, bottom;
|
||||
// Position of the bitmap on the screen.
|
||||
int x, y;
|
||||
// Rectangle masks.
|
||||
uint32_t masks[4];
|
||||
};
|
||||
|
||||
// The video ram addresses are set by the public functions and used internally
|
||||
// by the module.
|
||||
// Monochrome video ram, light and dark buffers (in this order).
|
||||
extern int *bopti_vram, *bopti_v1, *bopti_v2;
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Some bopti routines.
|
||||
//---
|
||||
|
||||
/*
|
||||
bopti_op()
|
||||
Operates on a vram long. The operator will often not contain 32 bits of
|
||||
image information. Since neutral bits are not the same for all
|
||||
operations, a mask is used to indicate which bits should be used for
|
||||
the operation. This mask is taken for the image's rectangle masks (see
|
||||
module display for more information on rectangle masks).
|
||||
Which operation is performed is determined by the channel setting.
|
||||
*/
|
||||
void bopti_op_mono(int offset, uint32_t operator, struct Command *c);
|
||||
void bopti_op_gray(int offset, uint32_t operator, struct Command *c);
|
||||
|
||||
/*
|
||||
bopti_grid() -- general form
|
||||
bopti_grid_a32() -- when x is a multiple of 32
|
||||
|
||||
Draws the grid at the beginning of a layer's data. The length of this
|
||||
grid is always a multiple of 32.
|
||||
The need for bopti_grid_a32() is not only linked to optimization,
|
||||
because bopti_grid() will perform a 32-bit shift when x is a multiple
|
||||
of 32, which is undefined behavior.
|
||||
bopti_grid() calls bopti_grid_32() by default.
|
||||
*/
|
||||
void bopti_grid_a32(const uint32_t *layer, int columns, int height,
|
||||
struct Command *c);
|
||||
void bopti_grid(const uint32_t *layer, int columns, int height,
|
||||
struct Command *c);
|
||||
/*
|
||||
bopti_end_get()
|
||||
Returns an operator for the end of a line, whose width is lower than 32
|
||||
(by design: otherwise, it would have been a column). The given pointer
|
||||
is read and updated so that it points to the next line at the end of
|
||||
the operation.
|
||||
*/
|
||||
uint32_t bopti_end_get1(const unsigned char **data);
|
||||
uint32_t bopti_end_get2(const unsigned char **data);
|
||||
|
||||
/*
|
||||
bopti_rest() -- general form
|
||||
bopti_rest_nover() -- when the end does not overlap two vram longs
|
||||
|
||||
Draws the end of a layer, which can be considered as a whole layer
|
||||
whose with is lower than 32. (Actually is it lower or equal to 16;
|
||||
otherwise it would have been a column and the end would be empty). The
|
||||
'size' arguments is in bytes.
|
||||
Unlike bopti_grid_a32(), bopti_end_nover() is not called automatically
|
||||
by bopti_end().
|
||||
*/
|
||||
void bopti_end_nover(const unsigned char *end, int size, struct Command *c);
|
||||
void bopti_end(const unsigned char *end, int size, struct Command *c);
|
||||
|
||||
/*
|
||||
bopti()
|
||||
Draws a layer in the video ram.
|
||||
*/
|
||||
void bopti(const unsigned char *layer, struct Structure *s, struct Command *c);
|
||||
|
||||
/*
|
||||
getStructure()
|
||||
Determines the image size and data pointer.
|
||||
*/
|
||||
void getStructure(struct Image *img, struct Structure *structure);
|
||||
|
||||
#endif // _INTERNALS_BOPTI_H
|
|
@ -1,56 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// gint drawing module: display
|
||||
//
|
||||
// Handles vram manipulation and drawing.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _INTERNALS_DISPLAY_H
|
||||
#define _INTERNALS_DISPLAY_H 1
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern int *vram;
|
||||
|
||||
//---
|
||||
// Rectangle masks.
|
||||
//
|
||||
// The concept of 'rectangle masks' is used several times in this module.
|
||||
// It is based on the fact that an operation that affects a rectangle acts
|
||||
// the same on all its lines. Therefore the behavior of the operation is
|
||||
// determined by its behavior on a single line, which is represented using
|
||||
// 'masks' whose bits indicate whether a pixel is affected (1) or not (0).
|
||||
//
|
||||
// For example when clearing the screen rectangle (16, 16, 112, 48), the
|
||||
// masks will represent information '16 to 112 on x-axis', and will hold
|
||||
// the following values : 0000ffff, ffffffff, ffffffff and ffff0000. These
|
||||
// masks can then be used by setting vram[offset] &= ~masks[i]. This
|
||||
// appears to be very flexible : for instance, vram[offset] ^= masks[i]
|
||||
// will reverse the pixels in the same rectangle.
|
||||
//
|
||||
// This technique can also be used in more subtle cases with more complex
|
||||
// patterns, but within this module it is unlikely to happen.
|
||||
//
|
||||
//---
|
||||
|
||||
/*
|
||||
adjustRectangle()
|
||||
Adjusts the given rectangle coordinates to ensure that :
|
||||
- the rectangle is entirely contained in the screen
|
||||
- x1 < x2
|
||||
- y1 < y2
|
||||
which is needed when working with screen rectangles.
|
||||
Returns non-zero if the rectangle is outside the screen.
|
||||
*/
|
||||
int adjustRectangle(int *x1, int *y1, int *x2, int *y2);
|
||||
|
||||
/*
|
||||
getMasks()
|
||||
Computes the rectangle masks needed to affect pixels located between x1
|
||||
and x2 (both included). The four masks are stored in the third argument
|
||||
(seen as an array).
|
||||
*/
|
||||
void getMasks(int x1, int x2, uint32_t *masks);
|
||||
|
||||
#endif // _INTERNALS_DISPLAY_H
|
|
@ -1,19 +0,0 @@
|
|||
#ifndef _INTERNALS_EVENTS_H
|
||||
#define _INTERNALS_EVENTS_H
|
||||
|
||||
#include <events.h>
|
||||
|
||||
#ifndef EVENTS_QUEUE_SIZE
|
||||
#define EVENTS_QUEUE_SIZE 64
|
||||
#endif
|
||||
|
||||
/*
|
||||
This module is just a circular-array queue that pushes and pops events
|
||||
like any other queue. Trying to add an event when the queue is full
|
||||
fails, and the operation is ignored.
|
||||
*/
|
||||
extern volatile struct Event event_queue[];
|
||||
extern volatile int queue_start;
|
||||
extern volatile int queue_size;
|
||||
|
||||
#endif // _INTERNALS_EVENT_H
|
|
@ -1,30 +0,0 @@
|
|||
#ifndef _INTERNALS_GINT_H
|
||||
#define _INTERNALS_GINT_H 1
|
||||
|
||||
//---
|
||||
// Exception code strings.
|
||||
//---
|
||||
|
||||
extern const char *gint_str[];
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Register access.
|
||||
//---
|
||||
|
||||
/*
|
||||
gint_spc()
|
||||
Returns the saved program counter, which is the last state of execution
|
||||
saved by interrupt processing.
|
||||
*/
|
||||
unsigned int gint_spc(void);
|
||||
|
||||
/*
|
||||
gint_ssr()
|
||||
Returns the saved status register, which is the last configuration
|
||||
saved by interrupt processing.
|
||||
*/
|
||||
unsigned int gint_ssr(void);
|
||||
|
||||
#endif // _INTERNALS_GINT_H
|
|
@ -1,39 +0,0 @@
|
|||
#ifndef _INTERNALS_KEYBOARD_H
|
||||
#define _INTERNALS_KEYBOARD_H
|
||||
|
||||
#include <keyboard.h>
|
||||
|
||||
// Keyboard variables.
|
||||
extern volatile unsigned char keyboard_state[10];
|
||||
extern volatile int interrupt_flag;
|
||||
|
||||
// Key statistics.
|
||||
extern int repeat_first, repeat_next;
|
||||
extern int last_key, last_repeats, last_events;
|
||||
|
||||
// RTC callback id.
|
||||
extern unsigned cb_id;
|
||||
|
||||
/*
|
||||
sleep()
|
||||
Puts the CPU into sleep until an interrupt request is accepted.
|
||||
*/
|
||||
void sleep(void);
|
||||
|
||||
/*
|
||||
getPressedKey()
|
||||
Finds a pressed key in the keyboard state and returns it.
|
||||
*/
|
||||
int getPressedKey(volatile unsigned char *keyboard_state);
|
||||
|
||||
/*
|
||||
getPressedKeys()
|
||||
Find 'count' pressed keys in the keyboard state and fills the 'keys'
|
||||
array. Returns the number of keys found.
|
||||
WARNING: keyboard artifacts make this function read as pressed keys
|
||||
that aren't (typically, LEFT + DOWN + SHIFT => ALPHA).
|
||||
*/
|
||||
int getPressedKeys(volatile unsigned char *keyboard_state, int *keys,
|
||||
int count);
|
||||
|
||||
#endif // _INTERNALS_KEYBOARD_H
|
|
@ -1,21 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// gint core module: mmu
|
||||
//
|
||||
// A wise application should avoid tampering with the system's
|
||||
// configuration of the MMU and the TLB. This module implicitly calls the
|
||||
// system but does nothing by itself.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _MMU_H
|
||||
#define _MMU_H 1
|
||||
|
||||
/*
|
||||
mmu_pseudoTLBInit()
|
||||
Tries to have the system load enough data into TLB to allow add-in to
|
||||
execute.
|
||||
*/
|
||||
void mmu_pseudoTLBInit(void);
|
||||
|
||||
#endif // _MMU_H
|
|
@ -1,141 +0,0 @@
|
|||
#ifndef _INTERNALS_RTC_H
|
||||
#define _INTERNALS_RTC_H
|
||||
|
||||
#include <rtc.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef RTC_CB_ARRAY_SIZE
|
||||
#define RTC_CB_ARRAY_SIZE 5
|
||||
#endif
|
||||
|
||||
/*
|
||||
struct rtc_cb
|
||||
An RTC callback.
|
||||
*/
|
||||
struct rtc_cb
|
||||
{
|
||||
enum RTCFrequency freq;
|
||||
int id;
|
||||
|
||||
void (*callback)(void);
|
||||
int repeats;
|
||||
};
|
||||
|
||||
// The callback array.
|
||||
struct rtc_cb cb_array[RTC_CB_ARRAY_SIZE];
|
||||
|
||||
/*
|
||||
struct mod_rtc
|
||||
This structure describes the arrangement of RTC register in the memory.
|
||||
Curious thing, on SH7705, registers RYRAR and RCR3 are at a completely
|
||||
different address than the other ones. This module does not use these
|
||||
registers, so they were not included in the structure.
|
||||
*/
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct mod_rtc
|
||||
{
|
||||
unsigned char const R64CNT;
|
||||
unsigned char _1;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :1;
|
||||
unsigned TENS :3;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RSECCNT;
|
||||
unsigned char _2;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :1;
|
||||
unsigned TENS :3;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RMINCNT;
|
||||
unsigned char _3;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :2;
|
||||
unsigned TENS :2;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RHRCNT;
|
||||
unsigned char _4;
|
||||
|
||||
// 0 = Sunday, 1 = Monday, ..., 6 = Saturday, 7 = prohibited setting.
|
||||
unsigned char RWKCNT;
|
||||
unsigned char _5;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :2;
|
||||
unsigned TENS :2;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RDAYCNT;
|
||||
unsigned char _6;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned :3;
|
||||
unsigned TENS :1;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RMONCNT;
|
||||
unsigned char _7;
|
||||
|
||||
union {
|
||||
unsigned short WORD;
|
||||
struct {
|
||||
unsigned THOUSANDS :4;
|
||||
unsigned HUNDREDS :4;
|
||||
unsigned TENS :4;
|
||||
unsigned ONES :4;
|
||||
};
|
||||
} RYRCNT;
|
||||
unsigned char _8[12];
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned CF :1;
|
||||
unsigned :2;
|
||||
unsigned CIE :1;
|
||||
unsigned AIE :1;
|
||||
unsigned :2;
|
||||
unsigned AF :1;
|
||||
};
|
||||
} RCR1;
|
||||
unsigned char _9;
|
||||
|
||||
union {
|
||||
unsigned char BYTE;
|
||||
struct {
|
||||
unsigned PEF :1;
|
||||
unsigned PES :3;
|
||||
unsigned :1;
|
||||
unsigned ADJ :1;
|
||||
unsigned RESET :1;
|
||||
unsigned START :1;
|
||||
};
|
||||
} RCR2;
|
||||
} __attribute__((packed));
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/*
|
||||
We don't need to access the registers in a complicated way like the
|
||||
function of the timer module. Let's make it simple.
|
||||
*/
|
||||
#define RTC_SH7705 ((volatile struct mod_rtc *)0xfffffec0)
|
||||
#define RTC_SH7305 ((volatile struct mod_rtc *)0xa413fec0)
|
||||
|
||||
#endif // _INTERNALS_RTC_H
|
|
@ -1,32 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// standard library module: stdio
|
||||
//
|
||||
// Handles most input/output for the program. This module does not
|
||||
// interact with the file system directly.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _INTERNALS_STDIO_H
|
||||
#define _INTERNALS_STDIO_H 1
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
//---
|
||||
// Formatted printing.
|
||||
//---
|
||||
|
||||
#ifndef __stdio_buffer_size
|
||||
#define __stdio_buffer_size 256
|
||||
#endif
|
||||
|
||||
extern char __stdio_buffer[];
|
||||
|
||||
/*
|
||||
__printf()
|
||||
Formatted printing to the stdio buffer.
|
||||
*/
|
||||
int __printf(size_t size, const char *format, va_list args);
|
||||
|
||||
#endif // _INTERNALS_STDIO_H
|
|
@ -1,55 +0,0 @@
|
|||
#ifndef _INTERNALS_TALES_H
|
||||
#define _INTERNALS_TALES_H 1
|
||||
|
||||
#include <tales.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define OPERATE_ARGS uint32_t *operators, int height, int x, int y
|
||||
|
||||
extern struct Font *font;
|
||||
extern enum Color color;
|
||||
|
||||
/*
|
||||
tales_init()
|
||||
Configures tales with the default font (which is part of gint).
|
||||
*/
|
||||
void tales_init(void) __attribute__((constructor));
|
||||
|
||||
/*
|
||||
getCharacterIndex()
|
||||
Returns the index of a character in a font data area depending on the
|
||||
font format and the size of the characters. Returns the index in the
|
||||
data area, as long array, or -1 when the character does not belong to
|
||||
the font format set.
|
||||
*/
|
||||
int getCharacterIndex(int c);
|
||||
|
||||
/*
|
||||
operate()
|
||||
Operates on the vram using the given operators. The x-coordinate should
|
||||
be a multiple of 32. There should be `height` operators.
|
||||
*/
|
||||
void operate_mono(OPERATE_ARGS);
|
||||
void operate_gray(OPERATE_ARGS);
|
||||
|
||||
/*
|
||||
update()
|
||||
Updates the operators using the given glyph. The operation will not be
|
||||
complete if there are not enough bits available in the operator data.
|
||||
In this case the offset will become negative, which means that the
|
||||
calling procedure has to call operate() and re-call update().
|
||||
`available` represents the number of free bits in the operators (lower
|
||||
bits).
|
||||
Returns the number of bits available after the operation. If it's
|
||||
negative, call operate() and update() again.
|
||||
*/
|
||||
int update(uint32_t *operators, int height, int available, uint32_t *glyph);
|
||||
|
||||
/*
|
||||
render()
|
||||
Renders text without any formatting analysis, using the given operation
|
||||
function.
|
||||
*/
|
||||
void render(int x, int y, const char *str, void (*op)(OPERATE_ARGS));
|
||||
|
||||
#endif // _INTERNALS_TALES_H
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef _INTERNALS_TIME_H
|
||||
#define _INTERNALS_TIME_H 1
|
||||
|
||||
/*
|
||||
isLeap()
|
||||
Determines whether the given year is a leap year.
|
||||
*/
|
||||
int isLeap(int year);
|
||||
|
||||
/*
|
||||
daysInMonth()
|
||||
Returns number of days for the given month (between 0 and 11) and year.
|
||||
*/
|
||||
int daysInMonth(int month, int year);
|
||||
|
||||
#endif // _INTERNALS_TIME_H
|
|
@ -1,48 +0,0 @@
|
|||
#ifndef _INTERNALS_TIMER_H
|
||||
#define _INTERNALS_TIMER_H 1
|
||||
|
||||
/*
|
||||
struct Timer
|
||||
This structure holds information for a running timer.
|
||||
*/
|
||||
struct Timer
|
||||
{
|
||||
void (*callback)(void);
|
||||
int repeats;
|
||||
};
|
||||
|
||||
extern struct Timer timers[3];
|
||||
|
||||
/*
|
||||
struct mod_tmu
|
||||
This structure holds information about the timer unit (peripheral
|
||||
module) registers.
|
||||
*/
|
||||
struct mod_tmu
|
||||
{
|
||||
unsigned int TCOR; // Timer constant register.
|
||||
unsigned int TCNT; // Timer counter.
|
||||
|
||||
union
|
||||
{
|
||||
unsigned short WORD;
|
||||
struct
|
||||
{
|
||||
unsigned :7;
|
||||
unsigned UNF :1; // Underflow flag.
|
||||
unsigned :2;
|
||||
unsigned UNIE :1; // Underflow interrupt enable.
|
||||
unsigned CKEG :2; // Clock edge (SH7705 only).
|
||||
unsigned TPSC :3; // Timer prescaler.
|
||||
};
|
||||
} TCR; // Timer control register.
|
||||
};
|
||||
|
||||
/*
|
||||
timer_get()
|
||||
Returns the timer and TSTR register addresses.
|
||||
*/
|
||||
void timer_get(int timer, volatile struct mod_tmu **tmu,
|
||||
volatile unsigned char **tstr);
|
||||
|
||||
#endif // _INTERNALS_TIMER_H
|
|
@ -1,303 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// gint core module: keyboard analyzer
|
||||
//
|
||||
// Probably the most difficult hardware interaction. There is very few
|
||||
// documentation on how the system actually analyzes the keyboard. While
|
||||
// disassembling syscalls reveals the following procedure (which was
|
||||
// already documented by SimonLothar), there is nothing about the
|
||||
// detection problems of the multi-getkey system.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _KEYBOARD_H
|
||||
#define _KEYBOARD_H 1
|
||||
|
||||
#include <rtc.h>
|
||||
|
||||
//---
|
||||
// Keycodes and related.
|
||||
//---
|
||||
|
||||
// The following codes are gint matrix codes. They are not compatible with the
|
||||
// system's.
|
||||
|
||||
#define KEY_F1 0x69
|
||||
#define KEY_F2 0x59
|
||||
#define KEY_F3 0x49
|
||||
#define KEY_F4 0x39
|
||||
#define KEY_F4 0x39
|
||||
#define KEY_F5 0x29
|
||||
#define KEY_F6 0x19
|
||||
|
||||
#define KEY_SHIFT 0x68
|
||||
#define KEY_OPTN 0x58
|
||||
#define KEY_VARS 0x48
|
||||
#define KEY_MENU 0x38
|
||||
#define KEY_LEFT 0x28
|
||||
#define KEY_UP 0x18
|
||||
|
||||
#define KEY_ALPHA 0x67
|
||||
#define KEY_SQUARE 0x57
|
||||
#define KEY_POWER 0x47
|
||||
#define KEY_EXIT 0x37
|
||||
#define KEY_DOWN 0x27
|
||||
#define KEY_RIGHT 0x17
|
||||
|
||||
#define KEY_XOT 0x66
|
||||
#define KEY_LOG 0x56
|
||||
#define KEY_LN 0x46
|
||||
#define KEY_SIN 0x36
|
||||
#define KEY_COS 0x26
|
||||
#define KEY_TAN 0x16
|
||||
|
||||
#define KEY_FRAC 0x65
|
||||
#define KEY_FD 0x55
|
||||
#define KEY_LEFTP 0x45
|
||||
#define KEY_RIGHTP 0x35
|
||||
#define KEY_COMMA 0x25
|
||||
#define KEY_ARROW 0x15
|
||||
|
||||
#define KEY_7 0x64
|
||||
#define KEY_8 0x54
|
||||
#define KEY_9 0x44
|
||||
#define KEY_DEL 0x34
|
||||
#define KEY_AC_ON 0x24
|
||||
|
||||
#define KEY_4 0x63
|
||||
#define KEY_5 0x53
|
||||
#define KEY_6 0x43
|
||||
#define KEY_MUL 0x33
|
||||
#define KEY_DIV 0x23
|
||||
|
||||
#define KEY_1 0x62
|
||||
#define KEY_2 0x52
|
||||
#define KEY_3 0x42
|
||||
#define KEY_PLUS 0x32
|
||||
#define KEY_MINUS 0x22
|
||||
|
||||
#define KEY_0 0x61
|
||||
#define KEY_DOT 0x51
|
||||
#define KEY_EXP 0x41
|
||||
#define KEY_NEG 0x31
|
||||
#define KEY_EXE 0x21
|
||||
|
||||
// Key modifiers.
|
||||
#define MOD_SHIFT 0x80
|
||||
#define MOD_ALPHA 0x100
|
||||
#define MOD_CLEAR ~(MOD_SHIFT | MOD_ALPHA)
|
||||
|
||||
// Key events.
|
||||
#define KEY_NONE 0x00
|
||||
#define KEY_NOEVENT 0xff
|
||||
|
||||
/*
|
||||
enum KeyboardFrequency
|
||||
Possible values for the keyboard frequency.
|
||||
*/
|
||||
enum KeyboardFrequency
|
||||
{
|
||||
KeyboardFreq_500mHz = RTCFreq_500mHz,
|
||||
KeyboardFreq_1Hz = RTCFreq_1Hz,
|
||||
KeyboardFreq_2Hz = RTCFreq_2Hz,
|
||||
KeyboardFreq_4Hz = RTCFreq_4Hz,
|
||||
KeyboardFreq_16Hz = RTCFreq_16Hz,
|
||||
KeyboardFreq_64Hz = RTCFreq_64Hz,
|
||||
KeyboardFreq_256Hz = RTCFreq_256Hz,
|
||||
};
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Keyboard configuration.
|
||||
//---
|
||||
|
||||
/*
|
||||
keyboard_setFrequency()
|
||||
Sets the keyboard frequency. The default frequency is 16 Hz. Very few
|
||||
applications will need to change this setting.
|
||||
At low frequencies, you will miss key hits. At high frequencies, you
|
||||
may lose execution power.
|
||||
*/
|
||||
void keyboard_setFrequency(enum KeyboardFrequency frequency);
|
||||
|
||||
/*
|
||||
keyboard_setRepeatRate()
|
||||
Sets the default repeat rate for key events. The delay before the first
|
||||
repeat may have a different value (usually longer). The unit for the
|
||||
argument is the keyboard period. For example at 32 Hz, values of
|
||||
(20, 4) will imitate the system default.
|
||||
Set to 0 to disable repetition. If first = 0, no repetition will be
|
||||
allowed. If first != 0 and next = 0, only one repetition will be
|
||||
allowed.
|
||||
*/
|
||||
void keyboard_setRepeatRate(int first, int next);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Keyboard access.
|
||||
//---
|
||||
|
||||
/*
|
||||
enum GetKeyOpt
|
||||
Options available for use with getkey_opt().
|
||||
*/
|
||||
enum GetkeyOpt
|
||||
{
|
||||
Getkey_NoOption = 0x00,
|
||||
|
||||
// Consider [SHIFT] and [ALPHA] as modifiers instead of returning
|
||||
// KEY_SHIFT and KEY_ALPHA.
|
||||
Getkey_ShiftModifier = 0x01,
|
||||
Getkey_AlphaModifier = 0x02,
|
||||
|
||||
// Key repetition. Notice that modifiers will never be repeated.
|
||||
Getkey_RepeatArrowKeys = 0x10,
|
||||
Getkey_RepeatCharKeys = 0x20,
|
||||
Getkey_RepeatCtrlKeys = 0x40,
|
||||
Getkey_RepeatFuncKeys = 0x80,
|
||||
// Shorthand for the four previous properties.
|
||||
Getkey_RepeatAllKeys = 0xf0,
|
||||
};
|
||||
|
||||
/*
|
||||
keylast()
|
||||
Returns the matrix code of the last pressed key. If repeat_count is
|
||||
non-NULL, it is set to the number of repetitions.
|
||||
*/
|
||||
int keylast(int *repeat_count);
|
||||
|
||||
/*
|
||||
keystate()
|
||||
Returns the address of the keyboard state array. The keyboard state
|
||||
consists in 10 bytes, in which every key is represented as a bit.
|
||||
The returned address is the original buffer address. You should avoid
|
||||
editing the array. It wouldn't influence the behavior of the keyboard
|
||||
functions, but the buffer data is very volatile. Therefore, data
|
||||
written to the buffer could be replaced anytime.
|
||||
*/
|
||||
volatile unsigned char *keystate(void);
|
||||
|
||||
/*
|
||||
getkey()
|
||||
Blocking function with auto-repeat and SHIFT modifying functionalities.
|
||||
Reproduces the behavior of the system's GetKey(). Returns the matrix
|
||||
code with a possible MOD_SHIFT bit.
|
||||
*/
|
||||
int getkey(void);
|
||||
|
||||
/*
|
||||
getkey_opt()
|
||||
Enhances getkey() with most general functionalities. An OR-combination
|
||||
of options may be given as second argument.
|
||||
If max_cycles is non-zero and positive, getkey_opt() will return
|
||||
KEY_NOEVENT if no event occurs during max_cycle analysis.
|
||||
As getkey(), returns the pressed key matrix code, possibly with
|
||||
modifiers depending on the options.
|
||||
*/
|
||||
int getkey_opt(enum GetkeyOpt options, int max_cycles);
|
||||
|
||||
/*
|
||||
multigetkey()
|
||||
|
||||
Listens the keyboard for simultaneous key hits. This functions fills
|
||||
array `keys` with `count` keycodes, adding KEY_NONE at the end if
|
||||
less than `count` keys are pressed.
|
||||
If `max_cycles` is non-zero and nothing happens after `max_cycles`
|
||||
cycles, this function returns an array of KEY_NONE.
|
||||
|
||||
WARNING:
|
||||
Because of hardware limitations, this function generally yields poor
|
||||
results. Rectangle and column effects make it read unpressed keys as
|
||||
pressed (see documentation for more information). The more pressed
|
||||
keys, the more errors.
|
||||
|
||||
The results are guaranteed to be exact if two keys or less are pressed.
|
||||
With three keys or more, column effects (on SH4) and rectangle effects
|
||||
(on both platforms) mess up the results by making this function think
|
||||
that some keys, which are actually unpressed, are pressed.
|
||||
|
||||
This function is designed to make combinations of one or two arrow keys
|
||||
with another key as viable as possible. On SH4, this works pretty well
|
||||
even if combinations like Left + Down + SHIFT trigger ALPHA sometimes.
|
||||
On SH3, rectangle effects are *always* present, making it impossible to
|
||||
use Left + Down or Up + Right with any other key in their rows without
|
||||
having this function return junk.
|
||||
|
||||
Any other combination of keys may quite randomly result in variably
|
||||
incorrect results. Please do not expect multigetkey() to work as an
|
||||
ideal multi-key analyzer.
|
||||
*/
|
||||
void multigetkey(int *keys, int count, int max_cycles);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Key analysis.
|
||||
//---
|
||||
|
||||
enum KeyType
|
||||
{
|
||||
KeyType_Arrow = 1,
|
||||
KeyType_Character = 2,
|
||||
KeyType_Control = 4,
|
||||
KeyType_Function = 8,
|
||||
};
|
||||
|
||||
/*
|
||||
keyid()
|
||||
Returns a non-matrix key code that can be used for array subscript.
|
||||
Ignores modifiers.
|
||||
*/
|
||||
int keyid(int key);
|
||||
|
||||
/*
|
||||
keychar()
|
||||
Returns the ASCII character associated with a character key; 0 for
|
||||
other keys.
|
||||
*/
|
||||
int keychar(int key);
|
||||
|
||||
/*
|
||||
keytype()
|
||||
Returns a key's type. Ignores modifiers.
|
||||
*/
|
||||
enum KeyType keytype(int key);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Internal API.
|
||||
// Reference here for documentation purposes only. Do not call.
|
||||
//---
|
||||
|
||||
/*
|
||||
keyboard_interrupt()
|
||||
Notifies the keyboard module that an interrupt request has been issued,
|
||||
and updates the keyboard state.
|
||||
*/
|
||||
void keyboard_interrupt(void) __attribute__((section(".gint.int")));
|
||||
|
||||
/*
|
||||
keyboard_updateState()
|
||||
Updates the keyboard state.
|
||||
*/
|
||||
void keyboard_updateState_7705(volatile unsigned char *state)
|
||||
__attribute__((section(".gint.int")));
|
||||
void keyboard_updateState_7305(volatile unsigned char *state)
|
||||
__attribute__((section(".gint.int")));
|
||||
|
||||
/*
|
||||
keyboard_init()
|
||||
Starts the keyboard timer.
|
||||
*/
|
||||
void keyboard_init(void) __attribute__((constructor));
|
||||
|
||||
/*
|
||||
keyboard_quit()
|
||||
Stops the keyboard timer.
|
||||
*/
|
||||
void keyboard_quit(void) __attribute__((destructor));
|
||||
|
||||
#endif // _KEYBOARD_H
|
|
@ -1,76 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// gint core module: mpu
|
||||
//
|
||||
// Determines which kind of MPU is running the program. This module
|
||||
// provides macro tests isSH3(), isSH4(), and the identifier of the MPU,
|
||||
// which is stored in a global variable MPU_CURRENT.
|
||||
//
|
||||
// If you need to do MPU-dependant jobs, prefer the following alternative:
|
||||
//
|
||||
// if(isSH3())
|
||||
// {
|
||||
// ...
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _MPU_H
|
||||
#define _MPU_H 1
|
||||
|
||||
/*
|
||||
enum MPU
|
||||
This type holds information about the calculator's MPU.
|
||||
*/
|
||||
enum MPU
|
||||
{
|
||||
MPU_Unknown = 0,
|
||||
// fx-9860G SH3.
|
||||
MPU_SH7337 = 1,
|
||||
// fx-9860G II SH3.
|
||||
MPU_SH7355 = 2,
|
||||
// fx-9860G II SH4.
|
||||
MPU_SH7305 = 3,
|
||||
// Just for reference.
|
||||
MPU_SH7724 = 4
|
||||
};
|
||||
|
||||
// Global MPU variable, accessible for direct tests. Initialized at the
|
||||
// beginning of execution.
|
||||
extern enum MPU MPU_CURRENT;
|
||||
|
||||
// Quick SH3 test. It is safer to assume that an unknown model is SH4 because
|
||||
// SH3-based models are not produced anymore.
|
||||
#define isSH3() (MPU_CURRENT == MPU_SH7337 || MPU_CURRENT == MPU_SH7355)
|
||||
#define isSH4() !isSH3()
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Public API.
|
||||
//---
|
||||
|
||||
/*
|
||||
getMPU()
|
||||
Determines the MPU type and returns it. MPU_CURRENT is not updated.
|
||||
*/
|
||||
enum MPU getMPU(void);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Internal API.
|
||||
// Referenced here for documentation purposes only. Do not call.
|
||||
//---
|
||||
|
||||
/*
|
||||
mpu_init()
|
||||
Determines the MPU type and stores the result into MPU_CURRENT.
|
||||
*/
|
||||
void mpu_init(void) __attribute__((constructor));
|
||||
|
||||
#endif // _MPU_H
|
|
@ -1,121 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// gint core module: rtc
|
||||
//
|
||||
// Manages RTC. This module is used behind standard module time.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _RTC_H
|
||||
#define _RTC_H 1
|
||||
|
||||
//---
|
||||
// Time access.
|
||||
//---
|
||||
|
||||
/*
|
||||
struct RTCTime
|
||||
Defines a point in time.
|
||||
*/
|
||||
struct RTCTime
|
||||
{
|
||||
int seconds; // Seconds in range 0-59
|
||||
int minutes; // Minutes in range 0-59
|
||||
int hours; // Hours in range 0-23
|
||||
int month_day; // Day of month in range 1-31
|
||||
int month; // Month in range 0-11
|
||||
int year; // Years (full value)
|
||||
int week_day; // Day of week in range 0(Sunday)-6(Saturday).
|
||||
};
|
||||
|
||||
/*
|
||||
rtc_getTime()
|
||||
Reads the current time from the RTC. There is no guarantee that the
|
||||
week day is correct (use the time API for that).
|
||||
*/
|
||||
struct RTCTime rtc_getTime(void);
|
||||
|
||||
/*
|
||||
rtc_setTime()
|
||||
Sets the time in the RTC registers. The week day is set to 0 if greater
|
||||
than 6. Other fields are not checked.
|
||||
*/
|
||||
void rtc_setTime(struct RTCTime time);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Callback API.
|
||||
//---
|
||||
|
||||
/*
|
||||
enum RTCFrequency
|
||||
Describes the possible frequencies available for the real-time clock
|
||||
interrupt.
|
||||
*/
|
||||
enum RTCFrequency
|
||||
{
|
||||
RTCFreq_500mHz = 7,
|
||||
RTCFreq_1Hz = 6,
|
||||
RTCFreq_2Hz = 5,
|
||||
RTCFreq_4Hz = 4,
|
||||
RTCFreq_16Hz = 3,
|
||||
RTCFreq_64Hz = 2,
|
||||
RTCFreq_256Hz = 1,
|
||||
RTCFreq_None = 0,
|
||||
};
|
||||
|
||||
/*
|
||||
rtc_cb_add()
|
||||
Registers a new callback for the RTC. Returns the callback id on
|
||||
success (positive integer), or one of the following error codes:
|
||||
-1 Array is full
|
||||
-2 Invalid parameter
|
||||
The number of repeats may be set to 0, in which case the callback is
|
||||
called indefinitely unless the user calls rtc_cb_end().
|
||||
*/
|
||||
int rtc_cb_add(enum RTCFrequency freq, void (*function)(void), int repeats);
|
||||
|
||||
/*
|
||||
rtc_cb_end()
|
||||
Removes the callback with the given id (as returned by rtc_cb_add())
|
||||
from the callback array.
|
||||
*/
|
||||
void rtc_cb_end(int id);
|
||||
|
||||
/*
|
||||
rtc_cb_edit()
|
||||
Changes information related to a callback. This function returns 0 on
|
||||
success, or one of the following error codes:
|
||||
-1 Callback does not exist
|
||||
-2 Invalid parameters
|
||||
This function never removes a callback. Call rtc_cb_end() for this. One
|
||||
can set the function to NULL or the frequency to RTCFreq_None to
|
||||
temporarily disable the callback.
|
||||
*/
|
||||
int rtc_cb_edit(int id, enum RTCFrequency new_freq,
|
||||
void (*new_function)(void));
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Internal API.
|
||||
// Referenced here for documentation purposes only. Do not call.
|
||||
//---
|
||||
|
||||
/*
|
||||
rtc_interrupt()
|
||||
Handles an RTC interrupt by calling the callback.
|
||||
*/
|
||||
void rtc_interrupt(void) __attribute__((section(".gint.int")));
|
||||
void rtc_interrupt_7705(void) __attribute__((section(".gint.int")));
|
||||
void rtc_interrupt_7305(void) __attribute__((section(".gint.int")));
|
||||
|
||||
/*
|
||||
rtc_cb_interrupt()
|
||||
Handles an RTC interrupt. Calls the RTC callbacks if necessary, and
|
||||
updates the repeat counts.
|
||||
*/
|
||||
void rtc_cb_interrupt(void);
|
||||
|
||||
#endif // _RTC_H
|
|
@ -1,23 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// gint display module: screen
|
||||
//
|
||||
// Interacts with the physical screen. See other display modules for video
|
||||
// ram management and drawing.
|
||||
//
|
||||
// The screen basically has two input values, which are a register
|
||||
// selector and the selected register's value. What this module does is
|
||||
// essentially selecting registers by setting *selector and assigning them
|
||||
// values by setting *data.
|
||||
//---
|
||||
|
||||
#ifndef _SCREEN_H
|
||||
#define _SCREEN_H 1
|
||||
|
||||
/*
|
||||
screen_display()
|
||||
Displays contents on the full screen. Expects a 1024-byte buffer.
|
||||
*/
|
||||
void screen_display(const void *vram);
|
||||
|
||||
#endif
|
|
@ -1,35 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// gint standard module: setjmp
|
||||
//
|
||||
// Long jumps. The register contents are saved in a buffer when setjmp()
|
||||
// is called and restored at any time when longjmp() performs the jump.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _SETJMP_H
|
||||
#define _SETJMP_H 1
|
||||
|
||||
// There are 16 CPU registers that *must* be saved to ensure a basically
|
||||
// safe jump.
|
||||
typedef unsigned int jmp_buf[16];
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Long jump functions.
|
||||
//---
|
||||
|
||||
/*
|
||||
setjmp() O(1)
|
||||
Configures a jump by saving data to the given jump buffer.
|
||||
*/
|
||||
int setjmp(jmp_buf env);
|
||||
|
||||
/*
|
||||
longjmp() O(1)
|
||||
Performs a long jump.
|
||||
*/
|
||||
void longjmp(jmp_buf env, int value);
|
||||
|
||||
#endif // _SETJMP_H
|
|
@ -1,44 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// standard library module: stdio
|
||||
//
|
||||
// Handles most input/output for the program. This module does not
|
||||
// interact with the file system directly.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _STDIO_H
|
||||
#define _STDIO_H 1
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
//---
|
||||
// Formatted printing.
|
||||
//---
|
||||
|
||||
/*
|
||||
sprintf()
|
||||
Prints to a string.
|
||||
*/
|
||||
int sprintf(char *str, const char *format, ...);
|
||||
|
||||
/*
|
||||
snprintf()
|
||||
Prints to a string with a size limit.
|
||||
*/
|
||||
int snprintf(char *str, size_t size, const char *format, ...);
|
||||
|
||||
/*
|
||||
vsprintf()
|
||||
Prints to a string from an argument list.
|
||||
*/
|
||||
int vsprintf(char *str, const char *format, va_list args);
|
||||
|
||||
/*
|
||||
vsnprintf()
|
||||
The most generic formatted printing function around there.
|
||||
*/
|
||||
int vsnprintf(char *str, size_t size, const char *format, va_list args);
|
||||
|
||||
#endif // _STDIO_H
|
|
@ -1,149 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// standard library module: stdlib
|
||||
//
|
||||
// Provides standard functionalities such as dynamic allocation,
|
||||
// string/numeric conversion, and abort calls.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _STDLIB_H
|
||||
#define _STDLIB_H 1
|
||||
|
||||
//---
|
||||
// Common definitions.
|
||||
//---
|
||||
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
|
||||
// Common exit codes.
|
||||
#define EXIT_SUCCESS 1
|
||||
#define EXIT_FAILURE 0
|
||||
|
||||
// Number of atexit() registrations guaranteed.
|
||||
#ifndef ATEXIT_MAX
|
||||
#define ATEXIT_MAX 16
|
||||
#endif
|
||||
|
||||
// Maximum value returned by rand().
|
||||
#define RAND_MAX INT_MAX
|
||||
|
||||
// Integer division result.
|
||||
typedef struct
|
||||
{
|
||||
int quot, rem;
|
||||
} div_t;
|
||||
typedef struct
|
||||
{
|
||||
long quot, rem;
|
||||
} ldiv_t;
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Program exit functions.
|
||||
//---
|
||||
|
||||
/*
|
||||
abort()
|
||||
Aborts the program execution without calling the exit handlers.
|
||||
*/
|
||||
void abort(void);
|
||||
|
||||
/*
|
||||
exit()
|
||||
Stops the program execution with the given status code, after calling
|
||||
the exit handlers.
|
||||
*/
|
||||
void exit(int status);
|
||||
|
||||
/*
|
||||
atexit()
|
||||
Registers a function to be called at normal program termination.
|
||||
*/
|
||||
int atexit(void (*function)(void));
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Dynamic storage allocation.
|
||||
//---
|
||||
|
||||
/*
|
||||
malloc()
|
||||
Allocates 'size' bytes and returns a pointer to a free memory area.
|
||||
Returns NULL on error.
|
||||
*/
|
||||
void *malloc(size_t size);
|
||||
|
||||
/*
|
||||
calloc()
|
||||
Allocates 'n' elements of size 'size' and wipes the memory area.
|
||||
Returns NULL on error.
|
||||
*/
|
||||
void *calloc(size_t n, size_t size);
|
||||
|
||||
/*
|
||||
realloc()
|
||||
Reallocates a memory block and moves its data.
|
||||
*/
|
||||
void *realloc(void *ptr, size_t size);
|
||||
|
||||
/*
|
||||
free()
|
||||
Frees a memory block allocated by malloc(), calloc() or realloc().
|
||||
*/
|
||||
void free(void *ptr);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Random number generation.
|
||||
//---
|
||||
|
||||
/*
|
||||
rand()
|
||||
Returns a pseudo-random number.
|
||||
*/
|
||||
int rand(void);
|
||||
|
||||
/*
|
||||
srand()
|
||||
Changes the seed used by rand().
|
||||
*/
|
||||
void srand(unsigned int seed);
|
||||
|
||||
//---
|
||||
// Integer arithmetic.
|
||||
//---
|
||||
|
||||
/*
|
||||
abs()
|
||||
Returns the absolute value of an integer.
|
||||
*/
|
||||
int abs(int x);
|
||||
// Use a macro instead, when possible.
|
||||
#define abs(x) ((x) < 0 ? -(x) : (x))
|
||||
|
||||
/*
|
||||
labs()
|
||||
Returns the absolute value of a long integer.
|
||||
*/
|
||||
long labs(long x);
|
||||
// Use a macro instead.
|
||||
#define labs(x) ((x) < 0 ? -(x) : (x))
|
||||
|
||||
/*
|
||||
div()
|
||||
Computes the integer division of numerator by denominator.
|
||||
*/
|
||||
div_t div(int numerator, int denominator);
|
||||
|
||||
/*
|
||||
ldiv()
|
||||
Computes the integer division of two long integers.
|
||||
*/
|
||||
ldiv_t ldiv(long numerator, long denominator);
|
||||
|
||||
#endif // _STDLIB_H
|
|
@ -1,63 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// standard library module: string
|
||||
//
|
||||
// String manipulation using NUL-terminated byte arrays, without extended
|
||||
// characters.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _STRING_H
|
||||
#define _STRING_H 1
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
//---
|
||||
// Memory manipulation.
|
||||
//---
|
||||
|
||||
/*
|
||||
memcpy() O(byte_number)
|
||||
Copies a memory area. The two areas must not overlap (if they do, use
|
||||
memmove()). A smart copy is performed when possible. To enhance
|
||||
performance, make sure than destination and source are both 4-aligned.
|
||||
*/
|
||||
void *memcpy(void *destination, const void *source, size_t byte_number);
|
||||
|
||||
/*
|
||||
memset() O(byte_number)
|
||||
Sets the contents of a memory area. A smart copy is performed.
|
||||
*/
|
||||
void *memset(void *destination, int byte, size_t byte_number);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// String manipulation.
|
||||
//---
|
||||
|
||||
/*
|
||||
strlen() O(len(str))
|
||||
Returns the length of a string.
|
||||
*/
|
||||
size_t strlen(const char *str);
|
||||
|
||||
/*
|
||||
strcpy() O(len(source))
|
||||
Copies a string to another.
|
||||
*/
|
||||
char *strcpy(char *destination, const char *source);
|
||||
|
||||
/*
|
||||
strchr() O(len(str))
|
||||
Searches a character in a string.
|
||||
*/
|
||||
const char *strchr(const char *str, int value);
|
||||
|
||||
/*
|
||||
strncpy() O(min(len(source), size))
|
||||
Copies part of a string to another.
|
||||
*/
|
||||
char *strncpy(char *destination, const char *source, size_t size);
|
||||
|
||||
#endif // _STRING_H
|
|
@ -1,123 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// gint drawing module: tales
|
||||
//
|
||||
// Text displaying. Does some pretty good optimization, though requires
|
||||
// dynamic allocation. The stack is used.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _TALES_H
|
||||
#define _TALES_H 1
|
||||
|
||||
#include <display.h>
|
||||
#include <stdint.h>
|
||||
|
||||
//---
|
||||
// Types and constants.
|
||||
//---
|
||||
|
||||
/*
|
||||
enum ImageFormat
|
||||
This type holds information about the characters in the font. Each bit
|
||||
represents various characters, and the type itself is a combination of
|
||||
several of those bits.
|
||||
Bits represent the following characters (lsb right):
|
||||
-- -- -- non-print | special capitals lower numbers
|
||||
*/
|
||||
enum FontFormat
|
||||
{
|
||||
FontFormat_Unknown = 0x00,
|
||||
FontFormat_Numeric = 0x01,
|
||||
FontFormat_LowerCase = 0x02,
|
||||
FontFormat_UpperCase = 0x04,
|
||||
FontFormat_Letters = 0x06,
|
||||
FontFormat_Common = 0x07,
|
||||
FontFormat_Print = 0x0f,
|
||||
FontFormat_Ascii = 0x1f,
|
||||
};
|
||||
|
||||
/*
|
||||
struct FontGlyph
|
||||
Holds a glyph's data. The width is used for spacing, and the raw data
|
||||
is encoded line after line, from to to bottom, by appending bits
|
||||
without consideration of the byte boundaries.
|
||||
This structure is actually never used, because data is read directly
|
||||
as a longword array (hence the 4-byte alignment).
|
||||
*/
|
||||
struct FontGlyph
|
||||
{
|
||||
unsigned char width;
|
||||
|
||||
const unsigned char data[];
|
||||
} __attribute__((aligned(4)));
|
||||
|
||||
/*
|
||||
struct Font
|
||||
Holds a font's data. Data is accessed using longword operations, hence
|
||||
the 4-alignment attributes. The line height is the one given in the
|
||||
font image header line, which may be used by applications that write
|
||||
strings on several lines. The data height is the height of the biggest
|
||||
glyph. Every glyph is encoded on 'data_height' lines, for optimization
|
||||
considerations.
|
||||
The index field is used to reduce character access time.
|
||||
The name field may not be NUL-terminated when the name contains 28
|
||||
characters. When the name is shorter, the field is padded with zeros.
|
||||
*/
|
||||
struct Font
|
||||
{
|
||||
unsigned char magic;
|
||||
|
||||
unsigned char format;
|
||||
unsigned char line_height;
|
||||
unsigned char data_height;
|
||||
|
||||
// Warning : this field may not be NUL-terminated.
|
||||
char name[28];
|
||||
|
||||
uint16_t index[16];
|
||||
|
||||
__attribute__((aligned(4))) const uint32_t glyphs[];
|
||||
|
||||
} __attribute__((aligned(4)));
|
||||
// Useful shorthand for user code.
|
||||
typedef struct Font Font;
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Generic functions.
|
||||
//---
|
||||
|
||||
/*
|
||||
text_configure()
|
||||
Sets the font and color to use for subsequent text operations. Pass
|
||||
font = NULL to use the default font.
|
||||
*/
|
||||
void text_configure(struct Font *font, enum Color color);
|
||||
|
||||
/*
|
||||
dtext()
|
||||
Prints the given string, without any analysis.
|
||||
*/
|
||||
void dtext(int x, int y, const char *str);
|
||||
|
||||
/*
|
||||
gtext()
|
||||
Prints the given raw string.
|
||||
*/
|
||||
void gtext(int x, int y, const char *str);
|
||||
|
||||
/*
|
||||
dprint()
|
||||
Prints a formatted string. Works the same as printf().
|
||||
*/
|
||||
void dprint(int x, int y, const char *format, ...);
|
||||
|
||||
/*
|
||||
gprint()
|
||||
Prints a formatted string. Works the same as printf().
|
||||
*/
|
||||
void gprint(int x, int y, const char *format, ...);
|
||||
|
||||
#endif // _TALES_H
|
|
@ -1,126 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// standard library module: time
|
||||
//
|
||||
// Provides time manipulation and representation functions.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _TIME_H
|
||||
#define _TIME_H 1
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
//---
|
||||
// Some related types.
|
||||
//---
|
||||
|
||||
/*
|
||||
struct tm
|
||||
Represents a point in time and gives some date information.
|
||||
*/
|
||||
struct tm
|
||||
{
|
||||
int tm_sec; // Seconds in range 0-59
|
||||
int tm_min; // Minutes in range 0-59
|
||||
int tm_hour; // Hours in range 0-23
|
||||
int tm_mday; // Day of month in range 1-31
|
||||
int tm_mon; // Month in range 0-11
|
||||
int tm_year; // Number of years since 1900
|
||||
int tm_wday; // Day of week in range 0(Sunday)-6(Saturday).
|
||||
int tm_yday; // Day of the year in range 0-365.
|
||||
int tm_isdst; // This will always be 0.
|
||||
};
|
||||
|
||||
/*
|
||||
clock_t
|
||||
Only used by clock().
|
||||
*/
|
||||
typedef signed int clock_t;
|
||||
|
||||
/*
|
||||
time_t
|
||||
Number of seconds elapsed since 1970-01-01 00:00:00.
|
||||
*/
|
||||
typedef signed int time_t;
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Time access.
|
||||
//---
|
||||
|
||||
/*
|
||||
clock()
|
||||
Should return elapsed CPU time since beginning of program execution.
|
||||
This is currently not implemented and returns -1.
|
||||
*/
|
||||
clock_t clock(void);
|
||||
|
||||
/*
|
||||
time()
|
||||
Returns the current time as calendar time. If you need a broken-down
|
||||
time, either use the RTC API or gmtime(). However, this function is
|
||||
already based on mktime() (for hardware reasons) so it would be much
|
||||
faster to use the RTC API if possible.
|
||||
If timeptr is not NULL, it is set to the current time, that is, the
|
||||
value that is returned.
|
||||
*/
|
||||
time_t time(time_t *timeptr);
|
||||
|
||||
/*
|
||||
difftime()
|
||||
Returns the number of seconds between the given points.
|
||||
*/
|
||||
double difftime(time_t end, time_t beginning);
|
||||
// But this macro should do.
|
||||
#define difftime(end, beginning) ((double)((end) - (beginning)))
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Time representation.
|
||||
//---
|
||||
|
||||
/*
|
||||
asctime()
|
||||
Converts broken-down time to string representation on the form
|
||||
"Wed Jun 30 21:49:08 1993\n". The returned string is statically
|
||||
allocated and may be overwritten by any subsequent call to a time
|
||||
function.
|
||||
*/
|
||||
char *asctime(const struct tm *time);
|
||||
|
||||
/*
|
||||
ctime()
|
||||
Converts calendar time to string representation on the form
|
||||
"Wed Jun 30 21:49:08 1993\n". The returned string is statically
|
||||
allocated and may be overwritten by any subsequent call to a time
|
||||
function.
|
||||
*/
|
||||
char *ctime(const time_t *timer);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Time conversion.
|
||||
//---
|
||||
|
||||
/*
|
||||
mktime()
|
||||
Converts broken-down time to calendar time. Computes structure fields
|
||||
tm_wday and tm_yday using the other fields. Member structures outside
|
||||
their range are normalized (e.g. 40 October becomes 9 November) and
|
||||
tm_isdst is set.
|
||||
*/
|
||||
time_t mktime(struct tm *time);
|
||||
|
||||
/*
|
||||
gmtime()
|
||||
Converts calendar time to broken-down time. The returned pointer is
|
||||
statically allocated and may be overwritten by any subsequent call to
|
||||
a time function.
|
||||
*/
|
||||
struct tm *gmtime(const time_t *t);
|
||||
|
||||
#endif // _TIME_H
|
|
@ -1,89 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// gint core module: timer
|
||||
//
|
||||
// Basic timer unit manipulation. Starts and stops timers with variable
|
||||
// number of repeats, and allows timer reloads without pause.
|
||||
//
|
||||
//---
|
||||
|
||||
#ifndef _TIMER_H
|
||||
#define _TIMER_H 1
|
||||
|
||||
#include <clock.h>
|
||||
|
||||
//---
|
||||
// Constants.
|
||||
//---
|
||||
|
||||
// Timer identifiers.
|
||||
#define TIMER_0 0
|
||||
#define TIMER_TMU0 TIMER_0
|
||||
#define TIMER_1 1
|
||||
#define TIMER_TMU1 TIMER_1
|
||||
#define TIMER_2 2
|
||||
#define TIMER_TMU2 TIMER_2
|
||||
// Timer function identifiers.
|
||||
#define TIMER_KEYBOARD TIMER_TMU0
|
||||
#define TIMER_GRAY TIMER_TMU1
|
||||
#define TIMER_USER TIMER_TMU2
|
||||
|
||||
// Timer prescalers.
|
||||
#define TIMER_Po_4 0
|
||||
#define TIMER_Po_16 1
|
||||
#define TIMER_Po_64 2
|
||||
#define TIMER_Po_256 3
|
||||
#define TIMER_TCLK 5
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Public API.
|
||||
//---
|
||||
|
||||
/*
|
||||
timer_start()
|
||||
Configures and starts a timer. The timer argument expects a timer name.
|
||||
You can use TIMER_USER anytime. You may also use TIMER_GRAY if you're
|
||||
not running the gray engine.
|
||||
The delay is in clock counts unit. The possible values for the
|
||||
prescaler are dividers of the peripheral clock frequency Po:
|
||||
- TIMER_Po_4
|
||||
- TIMER_Po_16
|
||||
- TIMER_Po_64
|
||||
- TIMER_Po_256
|
||||
- TIMER_TCLK
|
||||
The number of repeats may to set to 0. In this case, the timer will not
|
||||
stop until timer_stop() is explicitly called.
|
||||
*/
|
||||
void timer_start(int timer, int delay, int prescaler, void (*callback)(void),
|
||||
int repeats);
|
||||
|
||||
/*
|
||||
timer_stop()
|
||||
Stops the given timer. This function may be called even if the timer is
|
||||
not running.
|
||||
*/
|
||||
void timer_stop(int timer);
|
||||
|
||||
/*
|
||||
timer_reload()
|
||||
Reloads the given timer with the given constant. Starts the timer if
|
||||
it was stopped. The new delay uses the same unit as in timer_start().
|
||||
*/
|
||||
void timer_reload(int timer, int new_delay);
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Internal API.
|
||||
// Referenced for documentation purposes only. Do not call.
|
||||
//---
|
||||
|
||||
/*
|
||||
timer_interrupt()
|
||||
Handles the interrupt for the given timer.
|
||||
*/
|
||||
void timer_interrupt(int timer) __attribute__((section(".gint.int")));
|
||||
|
||||
#endif // _TIMER_H
|
|
@ -1,329 +0,0 @@
|
|||
#include <internals/bopti.h>
|
||||
|
||||
// Monochrome video ram, light and dark buffers (in this order).
|
||||
int *bopti_vram, *bopti_v1, *bopti_v2;
|
||||
|
||||
/*
|
||||
bopti_op()
|
||||
Operates on a vram long. The operator will often not contain 32 bits of
|
||||
image information. Since neutral bits are not the same for all
|
||||
operations, a mask is used to indicate which bits should be used for
|
||||
the operation. This mask is taken for the image's rectangle masks (see
|
||||
module display for more information on rectangle masks).
|
||||
Which operation is performed is determined by the channel setting.
|
||||
*/
|
||||
void bopti_op_mono(int offset, uint32_t operator, struct Command *c)
|
||||
{
|
||||
operator &= c->masks[offset & 3];
|
||||
|
||||
switch(c->channel)
|
||||
{
|
||||
case Channel_FullAlpha:
|
||||
bopti_vram[offset] &= ~operator;
|
||||
break;
|
||||
|
||||
case Channel_Mono:
|
||||
bopti_vram[offset] |= operator;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void bopti_op_gray(int offset, uint32_t operator, struct Command *c)
|
||||
{
|
||||
operator &= c->masks[offset & 3];
|
||||
|
||||
switch(c->channel)
|
||||
{
|
||||
case Channel_FullAlpha:
|
||||
bopti_v1[offset] &= ~operator;
|
||||
bopti_v2[offset] &= ~operator;
|
||||
break;
|
||||
|
||||
case Channel_LightAlpha:
|
||||
case Channel_DarkAlpha:
|
||||
break;
|
||||
|
||||
case Channel_Mono:
|
||||
bopti_v1[offset] |= operator;
|
||||
bopti_v2[offset] |= operator;
|
||||
break;
|
||||
|
||||
case Channel_Light:
|
||||
bopti_v1[offset] |= operator;
|
||||
break;
|
||||
|
||||
case Channel_Dark:
|
||||
bopti_v2[offset] |= operator;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
bopti_grid() -- general form
|
||||
bopti_grid_a32() -- when x is a multiple of 32
|
||||
|
||||
Draws the grid at the beginning of a layer's data. The length of this
|
||||
grid is always a multiple of 32.
|
||||
The need for bopti_grid_a32() is not only linked to optimization,
|
||||
because bopti_grid() will perform a 32-bit shift when x is a multiple
|
||||
of 32, which is undefined behavior.
|
||||
*/
|
||||
void bopti_grid_a32(const uint32_t *layer, int column_count, int height,
|
||||
struct Command *c)
|
||||
{
|
||||
int vram_column_offset = (c->y << 2) + (c->x >> 5);
|
||||
int vram_offset = vram_column_offset;
|
||||
int column, row;
|
||||
|
||||
for(column = 0; column < column_count; column++)
|
||||
{
|
||||
for(row = c->top; row < c->bottom; row++)
|
||||
{
|
||||
(*c->op)(vram_offset, layer[row], c);
|
||||
vram_offset += 4;
|
||||
}
|
||||
|
||||
vram_column_offset++;
|
||||
vram_offset = vram_column_offset;
|
||||
layer += height;
|
||||
}
|
||||
}
|
||||
void bopti_grid(const uint32_t *layer, int column_count, int height,
|
||||
struct Command *c)
|
||||
{
|
||||
if(!column_count) return;
|
||||
if(!(c->x & 31))
|
||||
{
|
||||
bopti_grid_a32(layer, column_count, height, c);
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t *p1, *p2;
|
||||
uint32_t l1, l2, operator;
|
||||
int right_column, line;
|
||||
int actual_column_count;
|
||||
|
||||
int vram_column_offset = (c->y << 2) + (c->x >> 5) + (c->x < 0);
|
||||
int vram_offset = vram_column_offset;
|
||||
|
||||
int shift1 = 32 - (c->x & 31);
|
||||
int shift2 = (c->x & 31);
|
||||
|
||||
// Initializing two pointers. They will read two adjacent columns at
|
||||
// the same time (p2 is column ahead of p1). Since the columns are
|
||||
// written one after another, incrementing them will suffice when
|
||||
// reaching the end of two columns, to move them to the next ones.
|
||||
p1 = layer - height;
|
||||
p2 = layer;
|
||||
|
||||
// We don't want to write the first vram column when x is negative
|
||||
// because it's outside the screen.
|
||||
if(c->x < 0) p1 += height, p2 += height;
|
||||
right_column = (c->x < 0);
|
||||
// For the same reason, we don't to draw the additional rightmost
|
||||
// column when it begins after 96.
|
||||
if(c->x + (column_count << 5) > 128)
|
||||
actual_column_count = column_count - 1;
|
||||
else
|
||||
actual_column_count = column_count;
|
||||
|
||||
// Drawing vram longwords, using pairs of columns.
|
||||
while(right_column <= actual_column_count)
|
||||
{
|
||||
for(line = c->top; line < c->bottom; line++)
|
||||
{
|
||||
l1 = (right_column > 0) ? p1[line] : (0);
|
||||
l2 = (right_column < column_count) ? p2[line] : (0);
|
||||
|
||||
operator = (l1 << shift1) | (l2 >> shift2);
|
||||
(*c->op)(vram_offset, operator, c);
|
||||
vram_offset += 4;
|
||||
}
|
||||
|
||||
p1 += height;
|
||||
p2 += height;
|
||||
vram_column_offset++;
|
||||
vram_offset = vram_column_offset;
|
||||
right_column++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
bopti_end_get()
|
||||
Returns an operator for the end of a line, whose width is lower than 32
|
||||
(by design: otherwise, it would have been a column). The given pointer
|
||||
is read and updated so that it points to the next line at the end of
|
||||
the operation.
|
||||
*/
|
||||
uint32_t bopti_end_get1(const unsigned char **data)
|
||||
{
|
||||
uint32_t operator = **data;
|
||||
*data += 1;
|
||||
return operator;
|
||||
}
|
||||
uint32_t bopti_end_get2(const unsigned char **data)
|
||||
{
|
||||
uint32_t operator = *((uint16_t *)*data);
|
||||
*data += 2;
|
||||
return operator;
|
||||
}
|
||||
|
||||
/*
|
||||
bopti_rest() -- general form
|
||||
bopti_rest_nover() -- when the end does not overlap two vram longs
|
||||
|
||||
Draws the end of a layer, which can be considered as a whole layer
|
||||
whose with is lower than 32. (Actually is it lower or equal to 16;
|
||||
otherwise it would have been a column and the end would be empty).
|
||||
*/
|
||||
void bopti_end_nover(const unsigned char *end, int size, struct Command *c)
|
||||
{
|
||||
uint32_t (*get)(const unsigned char **data) =
|
||||
(size == 2) ? bopti_end_get2 : bopti_end_get1;
|
||||
|
||||
// We *have* shift >= 0 because of this function's 'no overlap'
|
||||
// requirement.
|
||||
int shift = (32 - (size << 3)) - (c->x & 31);
|
||||
int vram_offset = (c->y << 2) + (c->x >> 5);
|
||||
uint32_t operator;
|
||||
int row;
|
||||
|
||||
// Skipping c->top lines (because get() function only allows sequential
|
||||
// access).
|
||||
end += c->top * size;
|
||||
|
||||
for(row = c->top; row < c->bottom; row++)
|
||||
{
|
||||
operator = (*get)(&end);
|
||||
operator <<= shift;
|
||||
|
||||
(*c->op)(vram_offset, operator, c);
|
||||
vram_offset += 4;
|
||||
}
|
||||
}
|
||||
void bopti_end(const unsigned char *end, int size, struct Command *c)
|
||||
{
|
||||
uint32_t (*get)(const unsigned char **data) =
|
||||
(size == 2) ? (bopti_end_get2) : (bopti_end_get1);
|
||||
|
||||
int vram_offset = (c->y << 2) + (c->x >> 5);
|
||||
uint32_t row_data, operator;
|
||||
int row;
|
||||
|
||||
int shift_base = (32 - (size << 3));
|
||||
int shift1 = (c->x & 31) - shift_base;
|
||||
int shift2 = shift_base + 32 - (c-> x & 31);
|
||||
|
||||
// Skipping c->top lines (because get() function only allows sequential
|
||||
// access).
|
||||
end += c->top * size;
|
||||
|
||||
for(row = c->top; row < c->bottom; row++)
|
||||
{
|
||||
row_data = (*get)(&end);
|
||||
|
||||
operator = row_data >> shift1;
|
||||
(*c->op)(vram_offset, operator, c);
|
||||
|
||||
operator = row_data << shift2;
|
||||
(*c->op)(vram_offset + 1, operator, c);
|
||||
|
||||
vram_offset += 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Wrappers and various functions.
|
||||
//---
|
||||
|
||||
/*
|
||||
bopti()
|
||||
Draws a layer in the video ram.
|
||||
*/
|
||||
void bopti(const unsigned char *layer, struct Structure *s, struct Command *c)
|
||||
{
|
||||
const unsigned char *grid, *end;
|
||||
int grid_columns, has_end;
|
||||
|
||||
// Skipping columns at the beginning.
|
||||
grid = layer + ((c->left * s->height) << 2);
|
||||
|
||||
// Updating the command arguments to eliminate some information about
|
||||
// parts that are not being drawn.
|
||||
c->x += (c->left << 5);
|
||||
c->y += c->top;
|
||||
|
||||
// Columns are identified by ids 0 to s->columns - 1, and the end has
|
||||
// id s->columns. So the end is drawn if this last column is included.
|
||||
has_end = (c->right == s->columns);
|
||||
// Computing number of grid columns to draw.
|
||||
grid_columns = c->right - c->left + 1 - has_end;
|
||||
|
||||
bopti_grid((const uint32_t *)grid, grid_columns, s->height, c);
|
||||
|
||||
if(has_end)
|
||||
{
|
||||
end = layer + ((s->columns * s->height) << 2);
|
||||
c->x += (grid_columns << 5);
|
||||
|
||||
if((c->x & 31) + s->end_size <= 32)
|
||||
bopti_end_nover(end, s->end_bytes, c);
|
||||
else
|
||||
bopti_end(end, s->end_bytes, c);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
getStructure()
|
||||
Determines the image size and data pointer.
|
||||
*/
|
||||
void getStructure(struct Image *img, struct Structure *s)
|
||||
{
|
||||
int column_count, end, end_bytes, layer;
|
||||
|
||||
// Large images.
|
||||
if(!img->width && !img->height)
|
||||
{
|
||||
s->width = (img->data[0] << 8) | img->data[1];
|
||||
s->height = (img->data[2] << 8) | img->data[3];
|
||||
s->data = img->data + 4;
|
||||
|
||||
column_count = (s->width + 31) >> 5;
|
||||
end = 0;
|
||||
end_bytes = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->width = img->width;
|
||||
s->height = img->height;
|
||||
s->data = img->data;
|
||||
|
||||
column_count = img->width >> 5;
|
||||
end = img->width & 31;
|
||||
end_bytes =
|
||||
!end ? 0 :
|
||||
end <= 8 ? 1 :
|
||||
end <= 16 ? 2 :
|
||||
4;
|
||||
|
||||
if(end_bytes == 4)
|
||||
{
|
||||
column_count++;
|
||||
end = 0;
|
||||
end_bytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// The layer size must be rounded to a multiple of 4.
|
||||
layer = s->height * ((column_count << 2) + end_bytes);
|
||||
if(layer & 3) layer += 4 - (layer & 3);
|
||||
|
||||
s->columns = column_count;
|
||||
s->end_bytes = end_bytes;
|
||||
s->end_size = end;
|
||||
s->layer_size = layer;
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
#include <internals/bopti.h>
|
||||
#include <internals/display.h>
|
||||
|
||||
/*
|
||||
dimage()
|
||||
Displays a monochrome image in the video ram.
|
||||
*/
|
||||
void dimage(int x, int y, struct Image *img)
|
||||
{
|
||||
if(!img || img->magic != 0xb7) return;
|
||||
|
||||
struct Structure s;
|
||||
struct Command command;
|
||||
int actual_width;
|
||||
int format = img->format, i = 0;
|
||||
|
||||
if(format != Format_Mono && format != Format_MonoAlpha) return;
|
||||
getStructure(img, &s);
|
||||
|
||||
//---
|
||||
// Adjusting image parameters.
|
||||
//---
|
||||
|
||||
if(x + s.width < 0 || x > 127 || y + s.height < 0 || y > 63) return;
|
||||
|
||||
command.top = (y < 0) ? (-y) : (0);
|
||||
command.bottom = (y + s.height > 64) ? (64 - y) : (s.height);
|
||||
command.left = ((x < 0) ? (-x) : (0)) >> 5;
|
||||
actual_width = (x + s.width > 128) ? (128 - x) : (s.width);
|
||||
command.right = ((actual_width + 31) >> 5) - 1;
|
||||
|
||||
command.op = bopti_op_mono;
|
||||
|
||||
if(x >= 0) getMasks(x, x + actual_width - 1, command.masks);
|
||||
else getMasks(0, actual_width + x - 1, command.masks);
|
||||
|
||||
bopti_vram = display_getCurrentVRAM();
|
||||
|
||||
while(format)
|
||||
{
|
||||
// Drawing every layer, in order of formats.
|
||||
if(format & 1)
|
||||
{
|
||||
// These members are modified by bopti()!
|
||||
command.x = x;
|
||||
command.y = y;
|
||||
command.channel = (1 << i);
|
||||
|
||||
bopti(s.data, &s, &command);
|
||||
s.data += s.layer_size;
|
||||
}
|
||||
|
||||
format >>= 1;
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
#include <internals/bopti.h>
|
||||
#include <internals/display.h>
|
||||
|
||||
/*
|
||||
dimage_part()
|
||||
Draws a portion of an image, defined by its bounding rectangle.
|
||||
Point (left, top) is included, but (left + width, top + height) is
|
||||
excluded.
|
||||
*/
|
||||
void dimage_part(int x, int y, struct Image *img, int left, int top,
|
||||
int width, int height)
|
||||
{
|
||||
if(!img || img->magic != 0xb7) return;
|
||||
|
||||
struct Structure s;
|
||||
struct Command command;
|
||||
int actual_width;
|
||||
int format = img->format, i = 0;
|
||||
|
||||
if(format != Format_Mono && format != Format_MonoAlpha) return;
|
||||
getStructure(img, &s);
|
||||
|
||||
//---
|
||||
// Adjusting the bounding rectangle.
|
||||
//---
|
||||
|
||||
// This is what happens when the bounding rectangle overflows from the
|
||||
// image...
|
||||
if(left < 0) left = 0;
|
||||
if(top < 0) top = 0;
|
||||
if(left + width > s.width) width = s.width - left;
|
||||
if(top + height > s.height) height = s.height - top;
|
||||
|
||||
if(x + left + width <= 0 || x > 127 || y + top + height <= 0 || y > 63)
|
||||
return;
|
||||
|
||||
command.top = (y < 0) ? (top - y) : top;
|
||||
command.bottom = top + ((y + height > 64) ? (64 - y) : height);
|
||||
command.left = ((x < 0) ? (left - x) : left) >> 5;
|
||||
actual_width = (x + width > 128) ? (128 - x) : width;
|
||||
command.right = ((left + actual_width + 31) >> 5) - 1;
|
||||
|
||||
command.op = bopti_op_mono;
|
||||
|
||||
if(x >= 0) getMasks(x, x + actual_width - 1, command.masks);
|
||||
else getMasks(0, actual_width + x - 1, command.masks);
|
||||
|
||||
bopti_vram = display_getCurrentVRAM();
|
||||
|
||||
while(format)
|
||||
{
|
||||
if(format & 1)
|
||||
{
|
||||
command.x = x - left;
|
||||
command.y = y - top;
|
||||
command.channel = (1 << i);
|
||||
|
||||
bopti(s.data, &s, &command);
|
||||
s.data += s.layer_size;
|
||||
}
|
||||
|
||||
format >>= 1;
|
||||
i++;
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
#include <internals/bopti.h>
|
||||
#include <internals/display.h>
|
||||
#include <gray.h>
|
||||
|
||||
/*
|
||||
gimage()
|
||||
Displays a gray image in the video ram.
|
||||
*/
|
||||
void gimage(int x, int y, struct Image *img)
|
||||
{
|
||||
if(!img || img->magic != 0xb7) return;
|
||||
|
||||
struct Structure s;
|
||||
struct Command command;
|
||||
int actual_width;
|
||||
int format = img->format, i = 0;
|
||||
|
||||
getStructure(img, &s);
|
||||
|
||||
//---
|
||||
// Adjusting image parameters.
|
||||
//---
|
||||
|
||||
if(x + s.width <= 0 || x > 127 || y + s.height <= 0 || y > 63) return;
|
||||
|
||||
command.top = (y < 0) ? (-y) : (0);
|
||||
command.bottom = (y + s.height > 64) ? (64 - y) : (s.height);
|
||||
command.left = ((x < 0) ? (-x) : (0)) >> 5;
|
||||
actual_width = (x + s.width > 128) ? (128 - x) : (s.width);
|
||||
command.right = ((actual_width + 31) >> 5) - 1;
|
||||
|
||||
command.op = bopti_op_gray;
|
||||
|
||||
if(x >= 0) getMasks(x, x + actual_width - 1, command.masks);
|
||||
else getMasks(0, actual_width + x - 1, command.masks);
|
||||
|
||||
bopti_v1 = gray_lightVRAM();
|
||||
bopti_v2 = gray_darkVRAM();
|
||||
|
||||
while(format)
|
||||
{
|
||||
// Drawing every layer, in order of formats.
|
||||
if(format & 1)
|
||||
{
|
||||
// These members are modified by bopti()!
|
||||
command.x = x;
|
||||
command.y = y;
|
||||
command.channel = (1 << i);
|
||||
|
||||
bopti(s.data, &s, &command);
|
||||
s.data += s.layer_size;
|
||||
}
|
||||
|
||||
format >>= 1;
|
||||
i++;
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
#include <internals/bopti.h>
|
||||
#include <internals/display.h>
|
||||
#include <gray.h>
|
||||
|
||||
/*
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
struct Rect
|
||||
{
|
||||
int top, bottom;
|
||||
int left, right;
|
||||
};
|
||||
struct Rect intersect(struct Rect r1, struct Rect r2)
|
||||
{
|
||||
struct Rect result;
|
||||
result.top = max(r1.top, r2.top);
|
||||
result.bottom = min(r1.bottom, r2.bottom);
|
||||
result.left = max(r1.left, r2.left);
|
||||
result.right = min(r1.right, r2.right);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
gimage_part()
|
||||
Draws a portion of a gray image, defined by its bounding rectangle.
|
||||
Point (left, top) is included, but (left + width, top + height) is
|
||||
excluded.
|
||||
*/
|
||||
void gimage_part(int x, int y, struct Image *img, int left, int top,
|
||||
int width, int height)
|
||||
{
|
||||
if(!img || img->magic != 0xb7) return;
|
||||
|
||||
struct Structure s;
|
||||
struct Command command;
|
||||
int actual_width;
|
||||
int format = img->format, i = 0;
|
||||
|
||||
getStructure(img, &s);
|
||||
|
||||
//---
|
||||
// Adjusting the bounding rectangle.
|
||||
//---
|
||||
|
||||
// This is what happens when the bounding rectangle overflows from the
|
||||
// image...
|
||||
if(left < 0) left = 0;
|
||||
if(top < 0) top = 0;
|
||||
if(left + width > s.width) width = s.width - left;
|
||||
if(top + height > s.height) height = s.height - top;
|
||||
|
||||
if(x + left + width <= 0 || x > 127 || y + top + height <= 0 || y > 63)
|
||||
return;
|
||||
|
||||
command.top = (y < 0) ? (top - y) : top;
|
||||
command.bottom = top + ((y + height > 64) ? (64 - y) : height);
|
||||
command.left = ((x < 0) ? (left - x) : left) >> 5;
|
||||
actual_width = (x + width > 128) ? (128 - x) : width;
|
||||
command.right = ((left + actual_width + 31) >> 5) - 1;
|
||||
|
||||
command.op = bopti_op_gray;
|
||||
|
||||
if(x >= 0) getMasks(x, x + actual_width - 1, command.masks);
|
||||
else getMasks(0, actual_width + x - 1, command.masks);
|
||||
|
||||
bopti_v1 = gray_lightVRAM();
|
||||
bopti_v2 = gray_darkVRAM();
|
||||
|
||||
while(format)
|
||||
{
|
||||
if(format & 1)
|
||||
{
|
||||
command.x = x - left;
|
||||
command.y = y - top;
|
||||
command.channel = (1 << i);
|
||||
|
||||
bopti(s.data, &s, &command);
|
||||
s.data += s.layer_size;
|
||||
}
|
||||
|
||||
format >>= 1;
|
||||
i++;
|
||||
}
|
||||
}
|
|
@ -1,288 +0,0 @@
|
|||
#include <clock.h>
|
||||
#include <timer.h>
|
||||
#include <internals/timer.h>
|
||||
#include <rtc.h>
|
||||
#include <stddef.h>
|
||||
#include <mpu.h>
|
||||
|
||||
static struct ClockConfig conf = {
|
||||
.FLL = -1, .PLL = -1,
|
||||
.Bphi_div1 = -1, .Iphi_div1 = -1, .Pphi_div1 = -1,
|
||||
.CKIO_f = -1,
|
||||
.Bphi_f = -1, .Iphi_f = -1, .Pphi_f = -1
|
||||
};
|
||||
|
||||
/*
|
||||
clock_frequency()
|
||||
Returns the approximate frequency, in Hz, of the given clock. The
|
||||
measurements need to have been done. Returns a negative number on
|
||||
error.
|
||||
*/
|
||||
int clock_frequency(enum Clock clock)
|
||||
{
|
||||
switch(clock)
|
||||
{
|
||||
case Clock_CKIO:
|
||||
return conf.CKIO_f;
|
||||
case Clock_RTCCLK:
|
||||
return conf.RTCCLK_f;
|
||||
case Clock_Bphi:
|
||||
return conf.Bphi_f;
|
||||
case Clock_Iphi:
|
||||
return conf.Iphi_f;
|
||||
case Clock_Pphi:
|
||||
return conf.Pphi_f;
|
||||
|
||||
default:
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
clock_setting()
|
||||
Returns the P_phi / 4 timer setting that will last for the given time.
|
||||
Several units can be used. Be aware that the result is approximate, and
|
||||
very high frequencies or very short delays will yield important errors.
|
||||
*/
|
||||
int clock_setting(int duration, enum ClockUnit unit)
|
||||
{
|
||||
if(conf.Pphi_f <= 0) return -1;
|
||||
int f = conf.Pphi_f >> 2;
|
||||
|
||||
switch(unit)
|
||||
{
|
||||
case Clock_us:
|
||||
return (duration * f) / 1000000;
|
||||
case Clock_ms:
|
||||
return (duration * f) / 1000;
|
||||
case Clock_s:
|
||||
return (duration * f);
|
||||
|
||||
case Clock_Hz:
|
||||
return f / duration;
|
||||
case Clock_kHz:
|
||||
return f / (duration * 1000);
|
||||
case Clock_MHz:
|
||||
return f / (duration * 1000000);
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
clock_config()
|
||||
Returns a copy of the clock configuration.
|
||||
*/
|
||||
struct ClockConfig clock_config(void)
|
||||
{
|
||||
return conf;
|
||||
}
|
||||
|
||||
/*
|
||||
sleep()
|
||||
Sleeps until an interrupt is accepted.
|
||||
*/
|
||||
void sleep(void)
|
||||
{
|
||||
__asm__(
|
||||
"sleep\n\t"
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
sleep_us()
|
||||
Sleeps for the given number of us using the user timer. The result will
|
||||
always be slightly less than required.
|
||||
*/
|
||||
|
||||
static volatile int sleep_us_done = 0;
|
||||
|
||||
static void sleep_us_callback(void)
|
||||
{
|
||||
sleep_us_done = 1;
|
||||
}
|
||||
|
||||
void sleep_us(int us_delay)
|
||||
{
|
||||
sleep_us_done = 0;
|
||||
timer_start(TIMER_USER, clock_setting(us_delay, Clock_us), TIMER_Po_4,
|
||||
sleep_us_callback, 1);
|
||||
do sleep();
|
||||
while(!sleep_us_done);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Clock frequency measurements -- Public API.
|
||||
//---
|
||||
|
||||
// Indicates whether the measurements are finished.
|
||||
static volatile int clock_measure_done = 0;
|
||||
// Once again SH7705 and SH7305 need different methods...
|
||||
static int cb_id_7705 = -1;
|
||||
static void clock_measure_7705();
|
||||
static void clock_compute_7305();
|
||||
|
||||
/*
|
||||
clock_measure()
|
||||
Measures or computes the clock frequencies.
|
||||
*/
|
||||
void clock_measure(void)
|
||||
{
|
||||
// On SH7705 we cannot have the value of CKIO simply, so we measure
|
||||
// P_phi using a timer/RTC combination, and we deduce CKIO.
|
||||
if(isSH3())
|
||||
{
|
||||
// We prepare the timer manually, without starting it, so that
|
||||
// we only have to push the running bit to start it when the
|
||||
// measurements begin. This might look of little effect but it
|
||||
// makes the precision jump from ~97% to more than 99%.
|
||||
volatile struct mod_tmu *tmu;
|
||||
timer_get(TIMER_USER, &tmu, NULL);
|
||||
|
||||
tmu->TCOR = 0xffffffff;
|
||||
tmu->TCNT = tmu->TCOR;
|
||||
tmu->TCR.TPSC = TIMER_Po_4;
|
||||
|
||||
tmu->TCR.UNF = 0;
|
||||
tmu->TCR.UNIE = 1;
|
||||
tmu->TCR.CKEG = 0;
|
||||
|
||||
timers[TIMER_USER].callback = NULL;
|
||||
timers[TIMER_USER].repeats = 0;
|
||||
|
||||
cb_id_7705 = rtc_cb_add(RTCFreq_256Hz, clock_measure_7705, 0);
|
||||
}
|
||||
|
||||
// On SH7305, assuming clock mode 3, we can compute the clock
|
||||
// frequencies because we know that RTC_CLK oscillates at 32768 Hz.
|
||||
else
|
||||
{
|
||||
clock_compute_7305();
|
||||
clock_measure_done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
clock_measure_end()
|
||||
Waits until the measurements are finished. This may be immediate.
|
||||
*/
|
||||
void clock_measure_end(void)
|
||||
{
|
||||
while(!clock_measure_done) sleep();
|
||||
}
|
||||
|
||||
//---
|
||||
// Clock frequency measurements -- SH7305.
|
||||
//---
|
||||
|
||||
/*
|
||||
clock_compute_7305()
|
||||
Computes the clock frequencies according to the CPG parameters.
|
||||
*/
|
||||
static void clock_compute_7305(void)
|
||||
{
|
||||
volatile unsigned int *FRQCRA = (void *)0xa4150000;
|
||||
volatile unsigned int *PLLCR = (void *)0xa4150024;
|
||||
volatile unsigned int *FLLFRQ = (void *)0xa4150050;
|
||||
|
||||
// Surely the documentation of SH7724 does not meet the specification
|
||||
// of SH7305 for the PLL setting, because the register accepts other
|
||||
// values than the ones specified for SH7724. The relation given by
|
||||
// Sentaro21 (thanks again!) yields good results.
|
||||
int pll = (*FRQCRA >> 24) & 0x3f; // Raw setting
|
||||
pll = pll + 1; // Resulting multiplier
|
||||
conf.PLL = pll;
|
||||
|
||||
// This one is simpler. The FLL ratio is actually the setting value.
|
||||
int fll = *FLLFRQ & 0x7ff; // Raw setting = multiplier
|
||||
if(*FLLFRQ & (1 << 14)) fll >>= 1; // Halve-output flag
|
||||
conf.FLL = fll;
|
||||
|
||||
// The divider1 ratios are NOT those of SH7724. The relation between
|
||||
// the values below and the divider ratios is given by Sentaro21
|
||||
// (thanks to him!) and satisfies ratio = 1 / (2 ** (setting + 1)).
|
||||
int div1_bphi = (*FRQCRA >> 8) & 0xf;
|
||||
int div1_iphi = (*FRQCRA >> 20) & 0xf;
|
||||
int div1_pphi = (*FRQCRA ) & 0xf;
|
||||
|
||||
conf.Bphi_div1 = 1 << (div1_bphi + 1);
|
||||
conf.Iphi_div1 = 1 << (div1_iphi + 1);
|
||||
conf.Pphi_div1 = 1 << (div1_pphi + 1);
|
||||
|
||||
// Computing the frequency of the signal, which is input to divider 1.
|
||||
int base = 32768;
|
||||
if(*PLLCR & (1 << 12)) base *= fll;
|
||||
if(*PLLCR & (1 << 14)) base *= pll;
|
||||
|
||||
conf.RTCCLK_f = 32768;
|
||||
conf.Bphi_f = base >> (div1_bphi + 1);
|
||||
conf.Iphi_f = base >> (div1_iphi + 1);
|
||||
conf.Pphi_f = base >> (div1_pphi + 1);
|
||||
}
|
||||
|
||||
//---
|
||||
// Clock frequency measurements -- SH7705.
|
||||
//---
|
||||
|
||||
/*
|
||||
clock_measure_7705_finalize()
|
||||
Given the number of P_phi / 4 timer ticks elapsed between two RTC
|
||||
256 Hz interrupts, determines the clock configuration.
|
||||
*/
|
||||
static void clock_measure_7705_finalize(int elapsed)
|
||||
{
|
||||
volatile unsigned int *FRQCR = (void *)0xffffff80;
|
||||
|
||||
conf.Pphi_f = elapsed * 4 * 256;
|
||||
if(conf.Pphi_f <= 0) return;
|
||||
|
||||
conf.PLL1 = ((*FRQCR >> 8) & 0x03) + 1;
|
||||
conf.PLL2 = -1;
|
||||
|
||||
conf.Bphi_div1 = 0;
|
||||
conf.Iphi_div1 = ((*FRQCR >> 4) & 0x03) + 1;
|
||||
conf.Pphi_div1 = ((*FRQCR ) & 0x03) + 1;
|
||||
|
||||
conf.CKIO_f = (conf.Pphi_f * conf.Pphi_div1) / conf.PLL1;
|
||||
conf.Bphi_f = conf.CKIO_f;
|
||||
conf.Iphi_f = (conf.CKIO_f * conf.PLL1) / conf.Iphi_div1;
|
||||
}
|
||||
|
||||
/*
|
||||
clock_measure_7705_callback()
|
||||
Starts measurements. Measurements will end automatically. Do not use
|
||||
RTC interrupt or the user timer will doing measurements.
|
||||
Call clock_measure_end() when you need to use those, to ensure
|
||||
measurements are finished.
|
||||
*/
|
||||
static void clock_measure_7705_callback(void)
|
||||
{
|
||||
timer_stop(TIMER_USER);
|
||||
rtc_cb_end(cb_id_7705);
|
||||
|
||||
volatile struct mod_tmu *tmu;
|
||||
timer_get(TIMER_USER, &tmu, NULL);
|
||||
int elapsed = 0xffffffff - tmu->TCNT;
|
||||
|
||||
clock_measure_7705_finalize(elapsed);
|
||||
clock_measure_done = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
clock_measure_7705()
|
||||
Programs the clock measurements. We need to have the user timer and the
|
||||
RTC synchronized for this operation, so we wait for an RTC interrupt
|
||||
and we prepare the timer beforehand to avoid losing processor time in
|
||||
configuring the registers.
|
||||
*/
|
||||
static void clock_measure_7705(void)
|
||||
{
|
||||
volatile unsigned char *tstr;
|
||||
timer_get(TIMER_USER, NULL, &tstr);
|
||||
|
||||
*tstr |= (1 << TIMER_USER);
|
||||
rtc_cb_edit(cb_id_7705, RTCFreq_256Hz, clock_measure_7705_callback);
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include <gint.h>
|
||||
#include <clock.h>
|
||||
#include <internals/mmu.h>
|
||||
|
||||
int main(void);
|
||||
|
||||
static void init(void);
|
||||
static void fini(void);
|
||||
|
||||
// Symbols imported from the linker script.
|
||||
extern unsigned int
|
||||
romdata,
|
||||
bbss, ebss,
|
||||
bdata, edata;
|
||||
|
||||
// This variable should be overwritten before being returned, so the default
|
||||
// value doesn't matter much.
|
||||
static int exit_code = EXIT_SUCCESS;
|
||||
static jmp_buf env;
|
||||
|
||||
// Exit handlers.
|
||||
void (*atexit_handlers[ATEXIT_MAX])(void);
|
||||
int atexit_index = 0;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
start()
|
||||
Program entry point. Loads the data section into the memory and invokes
|
||||
main(). Also prepares the execution environment by initializing all the
|
||||
modules.
|
||||
*/
|
||||
|
||||
int start(void)
|
||||
__attribute__((
|
||||
section(".pretext.entry")
|
||||
));
|
||||
|
||||
int start(void)
|
||||
{
|
||||
// Linker symbols.
|
||||
unsigned int *bss = &bbss;
|
||||
unsigned int *data = &bdata, *src = &romdata;
|
||||
int x;
|
||||
|
||||
// Clearing the .bss section.
|
||||
while(bss < &ebss) *bss++ = 0;
|
||||
// Copying the .data section.
|
||||
while(data < &edata) *data++ = *src++;
|
||||
|
||||
mmu_pseudoTLBInit();
|
||||
|
||||
// Initializing gint.
|
||||
gint_init();
|
||||
|
||||
// Measure clock frequencies.
|
||||
clock_measure();
|
||||
clock_measure_end();
|
||||
|
||||
// Calling global constructors.
|
||||
init();
|
||||
|
||||
|
||||
|
||||
// Saving the execution state there.
|
||||
x = setjmp(env);
|
||||
// If the program has just started, executing main(). Otherwise, the
|
||||
// exit code has already been set by abort() or similar.
|
||||
if(!x) exit_code = main();
|
||||
|
||||
|
||||
|
||||
// Remember to flush and close opened streams.
|
||||
|
||||
// Calling exit handlers.
|
||||
while(atexit_index > 0) (*atexit_handlers[--atexit_index])();
|
||||
|
||||
// Un-initializing everything.
|
||||
fini();
|
||||
gint_quit();
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
/*
|
||||
init()
|
||||
Calls the constructors.
|
||||
*/
|
||||
static void init(void)
|
||||
{
|
||||
extern void
|
||||
(*bctors)(void),
|
||||
(*ectors)(void);
|
||||
void (**func)(void) = &bctors;
|
||||
|
||||
while(func < &ectors)
|
||||
{
|
||||
(*(*func))();
|
||||
func++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
fini()
|
||||
Calls the destructors.
|
||||
*/
|
||||
static void fini(void)
|
||||
{
|
||||
extern void
|
||||
(*bdtors)(void),
|
||||
(*edtors)(void);
|
||||
void (**func)(void) = &bdtors;
|
||||
|
||||
while(func < &edtors)
|
||||
{
|
||||
(*(*func))();
|
||||
func++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
abort()
|
||||
Immediately ends the program without invoking the exit handlers.
|
||||
*/
|
||||
void abort(void)
|
||||
{
|
||||
exit_code = EXIT_FAILURE;
|
||||
|
||||
// Avoiding any exit handler call.
|
||||
atexit_index = 0;
|
||||
|
||||
longjmp(env, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
exit()
|
||||
Ends the program and returns the given exit code status. Calls exit
|
||||
handlers before returning.
|
||||
Usually exit() would ask the operating system to stop the process but
|
||||
the fx-9860G executes only one program at a time and calls it as a
|
||||
function. Reaching the program end point is therefore an efficient way
|
||||
of achieving this goal while minimizing interaction with the operating
|
||||
system.
|
||||
*/
|
||||
void exit(int status)
|
||||
{
|
||||
exit_code = status;
|
||||
longjmp(env, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
atexit()
|
||||
Registers a function to be called at normal program termination.
|
||||
*/
|
||||
int atexit(void (*function)(void))
|
||||
{
|
||||
if(atexit_index >= ATEXIT_MAX) return 1;
|
||||
|
||||
atexit_handlers[atexit_index++] = function;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,285 +0,0 @@
|
|||
//---
|
||||
//
|
||||
// gint core module: interrupt handler
|
||||
//
|
||||
// Central point of the library. Controls the interrupt handler and
|
||||
// defines a few functions to configure callbacks for some interrupts.
|
||||
//
|
||||
//---
|
||||
|
||||
#include <internals/gint.h>
|
||||
#include <gint.h>
|
||||
#include <mpu.h>
|
||||
#include <stddef.h>
|
||||
|
||||
static unsigned int
|
||||
new_vbr,
|
||||
sys_vbr;
|
||||
|
||||
static void (*default_handler)(int event_code) = NULL;
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Local functions.
|
||||
//---
|
||||
|
||||
/*
|
||||
gint_setup()
|
||||
Configures interrupt priorities and some parameters to allow gint to
|
||||
take control of the interrupt flow.
|
||||
*/
|
||||
static void gint_setup(void)
|
||||
{
|
||||
if(isSH3())
|
||||
gint_setup_7705();
|
||||
else
|
||||
gint_setup_7305();
|
||||
}
|
||||
|
||||
/*
|
||||
gint_stop()
|
||||
Un-configures the interrupt flow to give back the interrupt control to
|
||||
the system.
|
||||
*/
|
||||
static void gint_stop(void)
|
||||
{
|
||||
if(isSH3())
|
||||
gint_stop_7705();
|
||||
else
|
||||
gint_stop_7305();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Public API.
|
||||
//---
|
||||
|
||||
/*
|
||||
gint_systemVBR()
|
||||
Returns the vbr address used by the system (saved when execution
|
||||
starts).
|
||||
*/
|
||||
inline unsigned int gint_systemVBR(void)
|
||||
{
|
||||
return sys_vbr;
|
||||
}
|
||||
|
||||
/*
|
||||
gint_setDefaultHandler()
|
||||
In case gint receives an interrupt it doesn't recognize, it can fall
|
||||
back to a user-provided interrupt handler. Set it to NULL to disable
|
||||
this feature.
|
||||
Be aware that the event code passed to the default handler will either
|
||||
be INTEVT2 (SH7705) or INTEVT (SH7305), but its value for each
|
||||
interrupt case is completely platform-dependent. Remember to handle
|
||||
both platforms for increased portability, if possible.
|
||||
*/
|
||||
void gint_setDefaultHandler(void (*new_handler)(int event_code))
|
||||
{
|
||||
default_handler = new_handler;
|
||||
}
|
||||
|
||||
/*
|
||||
gint_init()
|
||||
Initializes gint. Loads the interrupt handler into the memory and sets
|
||||
the new vbr address.
|
||||
*/
|
||||
void gint_init(void)
|
||||
{
|
||||
// Linker script symbols -- gint.
|
||||
extern unsigned int
|
||||
gint_vbr,
|
||||
gint_data,
|
||||
bgint, egint;
|
||||
|
||||
unsigned int *ptr = &bgint;
|
||||
unsigned int *src = &gint_data;
|
||||
|
||||
// This initialization routine is usually called before any
|
||||
// constructor. We want to ensure that the MPU type is detected, but
|
||||
// mpu_init() hasn't been called yet.
|
||||
mpu_init();
|
||||
|
||||
// Loading the interrupt handler into the memory.
|
||||
while(ptr < &egint) *ptr++ = *src++;
|
||||
|
||||
sys_vbr = gint_getVBR();
|
||||
new_vbr = (unsigned int)&gint_vbr;
|
||||
|
||||
gint_setVBR(new_vbr, gint_setup);
|
||||
}
|
||||
|
||||
/*
|
||||
gint_quit()
|
||||
Stops gint. Restores the system's configuration and vbr address.
|
||||
*/
|
||||
void gint_quit(void)
|
||||
{
|
||||
gint_setVBR(sys_vbr, gint_stop);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// VBR space.
|
||||
//---
|
||||
|
||||
#include <display.h>
|
||||
#define print(str, x, y) dtext(6 * (x) - 5, 8 * (y) - 7, str)
|
||||
#define hexdigit(n) ((n) + '0' + 39 * ((n) > 9))
|
||||
|
||||
static void hex(unsigned int x, int digits, char *str)
|
||||
{
|
||||
str[0] = '0';
|
||||
str[1] = 'x';
|
||||
str[digits + 2] = 0;
|
||||
|
||||
while(digits)
|
||||
{
|
||||
str[digits + 1] = hexdigit(x & 0xf);
|
||||
x >>= 4;
|
||||
digits--;
|
||||
}
|
||||
}
|
||||
|
||||
static void reverse(void)
|
||||
{
|
||||
int *vram = display_getCurrentVRAM();
|
||||
int i;
|
||||
for(i = 0; i < 36; i++) vram[i] = ~vram[i];
|
||||
}
|
||||
|
||||
/*
|
||||
gint_exc()
|
||||
Handles exceptions.
|
||||
*/
|
||||
void gint_exc(void)
|
||||
{
|
||||
volatile unsigned int *expevt = gint_reg(Register_EXPEVT);
|
||||
volatile unsigned int *tea = gint_reg(Register_TEA);
|
||||
unsigned int spc;
|
||||
char str[11];
|
||||
|
||||
text_configure(NULL, Color_Black);
|
||||
|
||||
__asm__("\tstc spc, %0" : "=r"(spc));
|
||||
|
||||
dclear();
|
||||
print("Exception raised!", 3, 1);
|
||||
reverse();
|
||||
print(gint_strerror(0), 2, 3);
|
||||
|
||||
print("expevt", 2, 4);
|
||||
hex(*expevt, 3, str);
|
||||
print(str, 16, 4);
|
||||
|
||||
print("pc", 2, 5);
|
||||
hex(spc, 8, str);
|
||||
print(str, 11, 5);
|
||||
|
||||
print("tea", 2, 6);
|
||||
hex(*tea, 8, str);
|
||||
print(str, 11, 6);
|
||||
|
||||
print("Please reset.", 2, 7);
|
||||
dupdate();
|
||||
while(1);
|
||||
}
|
||||
|
||||
/*
|
||||
gint_tlb()
|
||||
Handles TLB misses.
|
||||
*/
|
||||
void gint_tlb(void)
|
||||
{
|
||||
volatile unsigned int *expevt = gint_reg(Register_EXPEVT);
|
||||
volatile unsigned int *tea = gint_reg(Register_TEA);
|
||||
unsigned int spc;
|
||||
char str[11];
|
||||
|
||||
text_configure(NULL, Color_Black);
|
||||
|
||||
__asm__("\tstc spc, %0" : "=r"(spc));
|
||||
|
||||
dclear();
|
||||
print("TLB error!", 6, 1);
|
||||
reverse();
|
||||
print(gint_strerror(1), 2, 3);
|
||||
|
||||
print("expevt", 2, 4);
|
||||
hex(*expevt, 3, str);
|
||||
print(str, 16, 4);
|
||||
|
||||
print("pc", 2, 5);
|
||||
hex(spc, 8, str);
|
||||
print(str, 11, 5);
|
||||
|
||||
print("tea", 2, 6);
|
||||
hex(*tea, 8, str);
|
||||
print(str, 11, 6);
|
||||
|
||||
print("Please reset.", 2, 7);
|
||||
dupdate();
|
||||
while(1);
|
||||
}
|
||||
|
||||
/*
|
||||
gint_int()
|
||||
Handles interrupts.
|
||||
*/
|
||||
void gint_int(void)
|
||||
{
|
||||
if(isSH3())
|
||||
gint_int_7705();
|
||||
else
|
||||
gint_int_7305();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Internal API.
|
||||
//---
|
||||
|
||||
/*
|
||||
gint_callDefaultHandler()
|
||||
Calls the user-provided default interrupt handler.
|
||||
*/
|
||||
void gint_callDefaultHandler(int event_code)
|
||||
{
|
||||
if(default_handler) default_handler(event_code);
|
||||
}
|
||||
|
||||
/*
|
||||
gint_reg()
|
||||
Returns the address of a common register. All common registers exist
|
||||
on both platforms but they may hold different values for the same
|
||||
information (f.i. EXPEVT may not return the same value for a given
|
||||
exception on both 7705 and 7305).
|
||||
*/
|
||||
inline volatile void *gint_reg(enum Register reg)
|
||||
{
|
||||
if(isSH3())
|
||||
return gint_reg_7705(reg);
|
||||
else
|
||||
return gint_reg_7305(reg);
|
||||
}
|
||||
|
||||
/*
|
||||
gint_strerror()
|
||||
Returns a string that describe the error set in EXPEVT. This string is
|
||||
not platform-dependent.
|
||||
Some exception codes represent different errors when invoked inside the
|
||||
general exception handler and the TLB error handler. Parameter 'is_tlb'
|
||||
should be set to zero for general exception meanings, and anything non-
|
||||
zero for TLB error meanings.
|
||||
*/
|
||||
const char *gint_strerror(int is_tlb)
|
||||
{
|
||||
if(isSH3())
|
||||
return gint_strerror_7705(is_tlb);
|
||||
else
|
||||
return gint_strerror_7305();
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
#include <internals/gint.h>
|
||||
|
||||
const char *gint_str[] = {
|
||||
"Unknown",
|
||||
|
||||
// User breaks.
|
||||
"User break (before)",
|
||||
"User break (after)",
|
||||
"User breakpoint",
|
||||
|
||||
// General.
|
||||
"Inst. address error",
|
||||
"Data access error",
|
||||
"Illegal instruction",
|
||||
"Illegal slot",
|
||||
"Data address (r)",
|
||||
"Data address (w)",
|
||||
|
||||
// Instruction TLB.
|
||||
"Inst. TLB miss",
|
||||
"Inst. TLB invalid",
|
||||
"Inst. TLB protect.",
|
||||
|
||||
// Data TLB.
|
||||
"Data TLB miss",
|
||||
"Data TLB miss (r)",
|
||||
"Data TLB miss (w)",
|
||||
"Data TLB protection",
|
||||
"Data TLB prot. (r)",
|
||||
"Data TLB prot. (w)",
|
||||
"Data TLB invalid",
|
||||
|
||||
// Others.
|
||||
"Initial page write",
|
||||
"Trap",
|
||||
"DMA address error",
|
||||
};
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
gint_vbr
|
||||
|
||||
Some of the work, especially related to setting and un-setting the vbr
|
||||
address needs to be done in assembler.
|
||||
*/
|
||||
|
||||
.global _gint_getVBR
|
||||
.global _gint_setVBR
|
||||
|
||||
|
||||
|
||||
/*
|
||||
gint_getVBR()
|
||||
Returns the current vbr address.
|
||||
*/
|
||||
_gint_getVBR:
|
||||
rts
|
||||
stc vbr, r0
|
||||
|
||||
|
||||
|
||||
/*
|
||||
gint_setVBR()
|
||||
|
||||
This is quite the hard part when modifying the vbr. We need to set
|
||||
immediately the interrupt priorities of our own handler, or restore
|
||||
the ones used by the system ; otherwise we may receive interrupts
|
||||
requests that the new handler doesn't handle, which will cause the
|
||||
whole program to freeze.
|
||||
|
||||
Therefore, we must set vbr *and* change interrupt priorities while
|
||||
having disabled all the interrupts in the status register. That's why
|
||||
this function takes as parameter the priority management function.
|
||||
*/
|
||||
_gint_setVBR:
|
||||
sts.l pr, @-r15
|
||||
|
||||
/* Blocking all interrupts. */
|
||||
mov.l sr_block, r0
|
||||
stc sr, r3
|
||||
or r0, r3
|
||||
ldc r3, sr
|
||||
|
||||
/* Setting the vbr address. */
|
||||
ldc r4, vbr
|
||||
|
||||
/* Calling the priority manager. */
|
||||
jsr @r5
|
||||
nop
|
||||
|
||||
/* Activating interrupts again. */
|
||||
mov.l sr_block, r0
|
||||
not r0, r0
|
||||
stc sr, r3
|
||||
and r0, r3
|
||||
ldc r3, sr
|
||||
|
||||
lds.l @r15+, pr
|
||||
rts
|
||||
nop
|
||||
|
||||
.align 4
|
||||
|
||||
sr_block:
|
||||
.long (1 << 28)
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
gint core module: syscalls
|
||||
|
||||
All the system calls used by the library. Somehow "the less, the
|
||||
better".
|
||||
We have finally gotten rid of every obscure system-related syscalls!
|
||||
Looks like an important step towards being completely free-standing :)
|
||||
*/
|
||||
|
||||
.global ___malloc
|
||||
.global ___free
|
||||
.global ___realloc
|
||||
|
||||
|
||||
|
||||
___malloc:
|
||||
mov.l syscall_table, r2
|
||||
mov.l 1f, r0
|
||||
jmp @r2
|
||||
nop
|
||||
1: .long 0xacd
|
||||
|
||||
___free:
|
||||
mov.l syscall_table, r2
|
||||
mov.l 1f, r0
|
||||
jmp @r2
|
||||
nop
|
||||
1: .long 0xacc
|
||||
|
||||
___realloc:
|
||||
mov.l syscall_table, r2
|
||||
mov.l 1f, r0
|
||||
jmp @r2
|
||||
nop
|
||||
1: .long 0xe6d
|
||||
|
||||
|
||||
.align 4
|
||||
|
||||
syscall_table:
|
||||
.long 0x80010070
|
|
@ -1,29 +0,0 @@
|
|||
#include <internals/display.h>
|
||||
|
||||
/*
|
||||
adjustRectangle()
|
||||
Adjusts the given rectangle coordinates to ensure that :
|
||||
- the rectangle is entirely contained in the screen
|
||||
- x1 < x2
|
||||
- y1 < y2
|
||||
which is needed when working with screen rectangles.
|
||||
Returns non-zero if the rectangle is outside the screen.
|
||||
*/
|
||||
int adjustRectangle(int *x1, int *y1, int *x2, int *y2)
|
||||
{
|
||||
#define swap(a, b) tmp = a, a = b, b = tmp
|
||||
int tmp;
|
||||
|
||||
if(*x2 < *x1) swap(*x1, *x2);
|
||||
if(*y2 < *y1) swap(*y1, *y2);
|
||||
|
||||
if(*x1 > 127 || *y1 > 63 || *x2 < 0 || *y2 < 0) return 1;
|
||||
|
||||
if(*x1 < 0) *x1 = 0;
|
||||
if(*y1 < 0) *y1 = 0;
|
||||
if(*x2 > 127) *x2 = 127;
|
||||
if(*y2 > 63) *y2 = 63;
|
||||
|
||||
return 0;
|
||||
#undef swap
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
#include <internals/display.h>
|
||||
#include <display.h>
|
||||
|
||||
/*
|
||||
dclear()
|
||||
Clears the whole vram.
|
||||
*/
|
||||
void dclear(void)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < 256; i++) vram[i] = 0;
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
#include <internals/display.h>
|
||||
#include <display.h>
|
||||
|
||||
/*
|
||||
dclear_area()
|
||||
Clears an area of the vram using rectangle masks. Both (x1, y1) and
|
||||
(x2, y2) are cleared.
|
||||
*/
|
||||
void dclear_area(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
uint32_t masks[4];
|
||||
if(adjustRectangle(&x1, &y1, &x2, &y2)) return;
|
||||
getMasks(x1, x2, masks);
|
||||
|
||||
int begin = y1 << 2;
|
||||
int end = (y2 + 1) << 2;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 4; i++) masks[i] = ~masks[i];
|
||||
for(i = begin; i < end; i++) vram[i] &= masks[i & 3];
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
#include <display.h>
|
||||
|
||||
// Program video ram. It resides in .bss section, therefore it is cleared at
|
||||
// program initialization and stripped from the executable file.
|
||||
static int local_vram[256];
|
||||
int *vram = local_vram;
|
||||
|
||||
/*
|
||||
display_getLocalVRAM()
|
||||
Returns the local video ram address. This function always return the
|
||||
same address.
|
||||
The buffer returned by this function should not be used directly when
|
||||
running the gray engine.
|
||||
*/
|
||||
inline void *display_getLocalVRAM(void)
|
||||
{
|
||||
return (void *)local_vram;
|
||||
}
|
||||
|
||||
/*
|
||||
display_getCurrentVRAM()
|
||||
Returns the current video ram. This function usually returns the
|
||||
parameter of the last call to display_useVRAM(), unless the gray engine
|
||||
is running (in which case the result is undefined). Returns the local
|
||||
vram address by default.
|
||||
*/
|
||||
inline void *display_getCurrentVRAM(void)
|
||||
{
|
||||
return (void *)vram;
|
||||
}
|
||||
|
||||
/*
|
||||
display_useVRAM()
|
||||
Changes the current video ram address. The argument MUST be a 4-
|
||||
aligned 1024-byte buffer ; otherwise any drawing operation will crash
|
||||
the program.
|
||||
This function will most likely have no effect when running the gray
|
||||
engine.
|
||||
*/
|
||||
inline void display_useVRAM(void *ptr)
|
||||
{
|
||||
vram = (int *)ptr;
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
#include <internals/display.h>
|
||||
#include <display.h>
|
||||
|
||||
#define sgn(x) ((x) < 0 ? -1 : 1)
|
||||
#define abs(x) ((x) < 0 ? -(x) : (x))
|
||||
#define rnd(x) ((int)((x) + 0.5))
|
||||
|
||||
/*
|
||||
dline()
|
||||
Draws a line on the screen. Automatically optimizes horizontal and
|
||||
vertical lines.
|
||||
*/
|
||||
|
||||
static void dhline(int x1, int x2, int y, enum Color color)
|
||||
{
|
||||
uint32_t masks[4];
|
||||
int offset = y << 2;
|
||||
int i;
|
||||
|
||||
// Swapping x1 and x2 if needed.
|
||||
if(x1 > x2) x1 ^= x2, x2 ^= x1, x1 ^= x2;
|
||||
getMasks(x1, x2, masks);
|
||||
|
||||
switch(color)
|
||||
{
|
||||
case Color_White:
|
||||
for(i = 0; i < 4; i++) vram[offset + i] &= ~masks[i];
|
||||
break;
|
||||
|
||||
case Color_Black:
|
||||
for(i = 0; i < 4; i++) vram[offset + i] |= masks[i];
|
||||
break;
|
||||
|
||||
case Color_Invert:
|
||||
for(i = 0; i < 4; i++) vram[offset + i] ^= masks[i];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void dvline(int y1, int y2, int x, enum Color color)
|
||||
{
|
||||
int offset = (y1 << 2) + (x >> 5);
|
||||
int end = (y2 << 2) + (x >> 5);
|
||||
int mask = 0x80000000 >> (x & 31);
|
||||
|
||||
switch(color)
|
||||
{
|
||||
case Color_White:
|
||||
while(offset <= end) vram[offset] &= ~mask, offset += 4;
|
||||
break;
|
||||
|
||||
case Color_Black:
|
||||
while(offset <= end) vram[offset] |= mask, offset += 4;
|
||||
break;
|
||||
|
||||
case Color_Invert:
|
||||
while(offset <= end) vram[offset] ^= mask, offset += 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dline(int x1, int y1, int x2, int y2, enum Color color)
|
||||
{
|
||||
if(adjustRectangle(&x1, &y1, &x2, &y2)) return;
|
||||
|
||||
// Possible optimizations.
|
||||
if(y1 == y2)
|
||||
{
|
||||
dhline(x1, x2, y1, color);
|
||||
return;
|
||||
}
|
||||
if(x1 == x2)
|
||||
{
|
||||
dvline(y1, y2, x1, color);
|
||||
return;
|
||||
}
|
||||
|
||||
int i, x = x1, y = y1, cumul;
|
||||
int dx = x2 - x1, dy = y2 - y1;
|
||||
int sx = sgn(dx), sy = sgn(dy);
|
||||
|
||||
dx = abs(dx), dy = abs(dy);
|
||||
|
||||
dpixel(x1, y1, color);
|
||||
|
||||
if(dx >= dy)
|
||||
{
|
||||
cumul = dx >> 1;
|
||||
for(i = 1; i < dx; i++)
|
||||
{
|
||||
x += sx;
|
||||
cumul += dy;
|
||||
if(cumul > dx) cumul -= dx, y += sy;
|
||||
dpixel(x, y, color);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cumul = dy >> 1;
|
||||
for(i = 1; i < dy; i++)
|
||||
{
|
||||
y += sy;
|
||||
cumul += dx;
|
||||
if(cumul > dy) cumul -= dy, x += sx;
|
||||
dpixel(x, y, color);
|
||||
}
|
||||
}
|
||||
|
||||
dpixel(x2, y2, color);
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
#include <internals/display.h>
|
||||
#include <display.h>
|
||||
|
||||
/*
|
||||
dpixel()
|
||||
Puts a pixel in the vram.
|
||||
*/
|
||||
void dpixel(int x, int y, enum Color color)
|
||||
{
|
||||
if((unsigned int)x > 127 || (unsigned int)y > 63) return;
|
||||
|
||||
int offset = (y << 2) + (x >> 5);
|
||||
int mask = 0x80000000 >> (x & 31);
|
||||
|
||||
switch(color)
|
||||
{
|
||||
case Color_White:
|
||||
vram[offset] &= ~mask;
|
||||
break;
|
||||
|
||||
case Color_Black:
|
||||
vram[offset] |= mask;
|
||||
break;
|
||||
|
||||
case Color_Invert:
|
||||
vram[offset] ^= mask;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
#include <internals/display.h>
|
||||
#include <display.h>
|
||||
|
||||
/*
|
||||
dreverse_area()
|
||||
Reverses an area of the vram. This function is a simple application of
|
||||
the rectangle masks concept. (x1, y1) and (x2, y2) are reversed as
|
||||
well.
|
||||
*/
|
||||
void dreverse_area(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
uint32_t masks[4];
|
||||
if(adjustRectangle(&x1, &y1, &x2, &y2)) return;
|
||||
getMasks(x1, x2, masks);
|
||||
|
||||
int begin = y1 << 2;
|
||||
int end = (y2 + 1) << 2;
|
||||
int i;
|
||||
|
||||
for(i = begin; i < end; i++) vram[i] ^= masks[i & 3];
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
#include <internals/display.h>
|
||||
#include <display.h>
|
||||
#include <screen.h>
|
||||
#include <gray.h>
|
||||
|
||||
/*
|
||||
dupdate()
|
||||
Displays the vram on the physical screen.
|
||||
*/
|
||||
void dupdate(void)
|
||||
{
|
||||
if(gray_runs()) return;
|
||||
screen_display((const void *)vram);
|
||||
}
|
Before Width: | Height: | Size: 32 KiB |
|
@ -1,33 +0,0 @@
|
|||
#include <display.h>
|
||||
|
||||
/*
|
||||
getMasks()
|
||||
Computes the rectangle masks needed to affect pixels located between x1
|
||||
and x2 (both included). The four masks are stored in the third argument
|
||||
(seen as an array).
|
||||
*/
|
||||
void getMasks(int x1, int x2, uint32_t *masks)
|
||||
{
|
||||
// Indexes of the first and last longs that are non-blank.
|
||||
int l1 = x1 >> 5;
|
||||
int l2 = x2 >> 5;
|
||||
int i = 0;
|
||||
|
||||
// Setting the base masks. Those are the final values, except for the
|
||||
// longs with indexes l1 and l2, that still need to be adjusted.
|
||||
while(i < l1) masks[i++] = 0x00000000;
|
||||
while(i <= l2) masks[i++] = 0xffffffff;
|
||||
while(i < 4) masks[i++] = 0x00000000;
|
||||
|
||||
// Removing the long number information in x1 and x2 (that is, the
|
||||
// multiples of 32) to keep only the interesting information -- the
|
||||
// number of null bits to add in l1 and l2.
|
||||
x1 &= 31;
|
||||
// Inverting x2 is here the same as computing 32 - x, since 32 is a
|
||||
// power of 2 (positive bits at the left are removed by the mask).
|
||||
x2 = ~x2 & 31;
|
||||
|
||||
// Setting the first and last masks.
|
||||
masks[l1] &= (0xffffffff >> x1);
|
||||
masks[l2] &= (0xffffffff << x2);
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
#include <internals/events.h>
|
||||
#include <events.h>
|
||||
#include <clock.h>
|
||||
|
||||
/*
|
||||
pollevent()
|
||||
Returns the next event. If no one is available, returns an event whose
|
||||
type is ET_None. This function always returns immediately.
|
||||
*/
|
||||
struct Event pollevent(void)
|
||||
{
|
||||
struct Event event = {
|
||||
.type = ET_None
|
||||
};
|
||||
if(queue_size <= 0) return event;
|
||||
|
||||
event = event_queue[queue_start];
|
||||
|
||||
queue_size--;
|
||||
if(queue_start == EVENTS_QUEUE_SIZE - 1) queue_start = 0;
|
||||
else queue_start++;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/*
|
||||
getevent()
|
||||
Returns the next event. If no one is available, waits for something to
|
||||
happen. This function uses low-level sleep and should be preferred to
|
||||
active waiting using loops.
|
||||
*/
|
||||
struct Event getevent(void)
|
||||
{
|
||||
struct Event event;
|
||||
|
||||
while((event = pollevent()).type == ET_None) sleep();
|
||||
return event;
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
#include <internals/events.h>
|
||||
#include <events.h>
|
||||
|
||||
volatile struct Event event_queue[EVENTS_QUEUE_SIZE];
|
||||
volatile int queue_start = 0;
|
||||
volatile int queue_size = 0;
|
||||
|
||||
/*
|
||||
event_push()
|
||||
Queues a user-defined event, allowing it to be retrieved by getevent()
|
||||
or pollevent() later. Pushing ET_None events is not allowed.
|
||||
Returns non-zero on error.
|
||||
*/
|
||||
int event_push(struct Event event)
|
||||
{
|
||||
if(queue_size >= EVENTS_QUEUE_SIZE) return 1;
|
||||
if(event.type == ET_None) return 2;
|
||||
|
||||
int index = queue_start + queue_size;
|
||||
if(index >= EVENTS_QUEUE_SIZE) index -= EVENTS_QUEUE_SIZE;
|
||||
|
||||
event_queue[index] = event;
|
||||
queue_size++;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
#include <gray.h>
|
||||
|
||||
/*
|
||||
gclear()
|
||||
Clears the video ram.
|
||||
*/
|
||||
void gclear(void)
|
||||
{
|
||||
int *v1 = gray_lightVRAM();
|
||||
int *v2 = gray_darkVRAM();
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 256; i++) v1[i] = v2[i] = 0;
|
||||
}
|