summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2005-03-02 23:49:38 +0000
committerJens Arnold <amiconn@rockbox.org>2005-03-02 23:49:38 +0000
commit384de102469fee4e0792df8fe38586d3206774ed (patch)
treeee5342103e17738acfb8421328ea7c57433f55e6 /apps
parent48dad47df98bdec632e8930b6a97359dc2c428f5 (diff)
downloadrockbox-384de102469fee4e0792df8fe38586d3206774ed.zip
rockbox-384de102469fee4e0792df8fe38586d3206774ed.tar.gz
rockbox-384de102469fee4e0792df8fe38586d3206774ed.tar.bz2
rockbox-384de102469fee4e0792df8fe38586d3206774ed.tar.xz
Rockboy - gameboy emulation for rockbox, based on gnuboy. Still a bit early, but already playable on iRiver H1xx and the simulators. The archos recorder version is currently rather slow...
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6104 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/Makefile14
-rw-r--r--apps/plugins/SOURCES4
-rw-r--r--apps/plugins/rockboy.c81
-rwxr-xr-xapps/plugins/rockboy/COPYING339
-rw-r--r--apps/plugins/rockboy/Makefile106
-rwxr-xr-xapps/plugins/rockboy/README199
-rwxr-xr-xapps/plugins/rockboy/Version5
-rwxr-xr-xapps/plugins/rockboy/archos.lds46
-rw-r--r--apps/plugins/rockboy/cpu.c880
-rw-r--r--apps/plugins/rockboy/cpu.h41
-rw-r--r--apps/plugins/rockboy/cpucore.h290
-rw-r--r--apps/plugins/rockboy/cpuregs.h56
-rw-r--r--apps/plugins/rockboy/debug.c699
-rw-r--r--apps/plugins/rockboy/defs.h36
-rw-r--r--apps/plugins/rockboy/emu.c117
-rw-r--r--apps/plugins/rockboy/emu.h2
-rw-r--r--apps/plugins/rockboy/events.c61
-rw-r--r--apps/plugins/rockboy/exports.c42
-rw-r--r--apps/plugins/rockboy/exports.h2
-rw-r--r--apps/plugins/rockboy/fastmem.c138
-rw-r--r--apps/plugins/rockboy/fastmem.h22
-rw-r--r--apps/plugins/rockboy/fb.h35
-rw-r--r--apps/plugins/rockboy/hw.c183
-rw-r--r--apps/plugins/rockboy/hw.h47
-rw-r--r--apps/plugins/rockboy/inflate.c514
-rw-r--r--apps/plugins/rockboy/input.h24
-rw-r--r--apps/plugins/rockboy/lcd.c956
-rw-r--r--apps/plugins/rockboy/lcd.h74
-rw-r--r--apps/plugins/rockboy/lcdc.c180
-rw-r--r--apps/plugins/rockboy/lcdc.h4
-rw-r--r--apps/plugins/rockboy/loader.c383
-rw-r--r--apps/plugins/rockboy/loader.h28
-rw-r--r--apps/plugins/rockboy/main.c83
-rw-r--r--apps/plugins/rockboy/mem.c578
-rw-r--r--apps/plugins/rockboy/mem.h80
-rw-r--r--apps/plugins/rockboy/noise.h532
-rw-r--r--apps/plugins/rockboy/nosound.c43
-rw-r--r--apps/plugins/rockboy/palette.c153
-rw-r--r--apps/plugins/rockboy/palette.h6
-rw-r--r--apps/plugins/rockboy/pcm.h21
-rw-r--r--apps/plugins/rockboy/rc.h71
-rw-r--r--apps/plugins/rockboy/rccmds.c122
-rw-r--r--apps/plugins/rockboy/rcvars.c233
-rw-r--r--apps/plugins/rockboy/regs.h181
-rw-r--r--apps/plugins/rockboy/rockboy.c137
-rw-r--r--apps/plugins/rockboy/rockmacros.h88
-rw-r--r--apps/plugins/rockboy/rtc.c135
-rw-r--r--apps/plugins/rockboy/rtc.h25
-rw-r--r--apps/plugins/rockboy/save.c286
-rw-r--r--apps/plugins/rockboy/save.h4
-rw-r--r--apps/plugins/rockboy/sound.c466
-rw-r--r--apps/plugins/rockboy/sound.h41
-rw-r--r--apps/plugins/rockboy/split.c59
-rw-r--r--apps/plugins/rockboy/split.h1
-rw-r--r--apps/plugins/rockboy/sys_rockbox.c271
-rw-r--r--apps/plugins/viewers.config2
56 files changed, 9225 insertions, 1 deletions
diff --git a/apps/plugins/Makefile b/apps/plugins/Makefile
index 3e56510..6c3917c 100644
--- a/apps/plugins/Makefile
+++ b/apps/plugins/Makefile
@@ -34,7 +34,13 @@ OBJS := $(SRC:%.c=$(OBJDIR)/%.o)
DEFS := $(SRC:%.c=$(OBJDIR)/%.def)
DIRS = .
-all: $(OBJDIR)/libplugin.a $(ROCKS) $(DEPFILE)
+#for any recorder and iRiver model
+ifneq (,$(strip $(foreach tgt,RECORDER IRIVER,$(findstring $(tgt),$(TARGET)))))
+ SUBDIRS += rockboy
+endif
+
+.PHONY: $(SUBDIRS)
+all: $(OBJDIR)/libplugin.a $(ROCKS) $(SUBDIRS) $(DEPFILE)
ifndef SIMVER
$(OBJDIR)/%.elf: $(OBJDIR)/%.o $(LINKFILE) $(OBJDIR)/libplugin.a
@@ -95,10 +101,16 @@ $(LINKFILE): $(LDS)
@echo "build $@"
@cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) $(DEFINES) -E -P - >$@
+$(SUBDIRS):
+ @echo "MAKE in $@"
+ @mkdir -p $(OBJDIR)/$@
+ @$(MAKE) -C $@ TARGET=$(TARGET) DEBUG=$(DEBUG) OUTDIR=$(OBJDIR) OBJDIR=$(OBJDIR)/$@ VERSION=$(VERSION) EXTRA_DEFINES="$(EXTRA_DEFINES)" MEM=${MEMORYSIZE}
+
clean:
@echo "cleaning plugins"
@rm -f $(ROCKS) $(LINKFILE) $(OBJDIR)/*.rock $(DEPFILE) $(ELFS) \
$(OBJS) $(DEFS)
@$(MAKE) -C lib clean
+ @$(MAKE) -C rockboy clean
-include $(DEPFILE)
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index 643fc0c..581d164 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -29,6 +29,10 @@ oscillograph.c
oscilloscope.c
pong.c
rockblox.c
+#if (CONFIG_KEYPAD == RECORDER_PAD) && !defined(SIMULATOR)
+/* loader, only needed for Archos */
+rockboy.c
+#endif
sliding_puzzle.c
snake.c
snake2.c
diff --git a/apps/plugins/rockboy.c b/apps/plugins/rockboy.c
new file mode 100644
index 0000000..4778fa8
--- /dev/null
+++ b/apps/plugins/rockboy.c
@@ -0,0 +1,81 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 Jens Arnold
+ *
+ * Overlay loader for rockboy on Archos
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "plugin.h"
+
+#if MEM <= 8 && !defined(SIMULATOR)
+
+#define OVL_NAME "/.rockbox/viewers/rockboy.ovl"
+#define OVL_DISPLAYNAME "RockBoy"
+
+struct plugin_api* rb;
+unsigned char *mp3buf;
+int mp3buf_size;
+
+/* this is the plugin entry point */
+enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
+{
+ int fh, readsize;
+ struct {
+ unsigned long magic;
+ unsigned char *start_addr;
+ unsigned char *end_addr;
+ enum plugin_status(*entry_point)(struct plugin_api*, void*);
+ } header;
+
+ /* this macro should be called as the first thing you do in the plugin.
+ it test that the api version and model the plugin was compiled for
+ matches the machine it is running on */
+ TEST_PLUGIN_API(api);
+ rb = api;
+
+ fh = rb->open(OVL_NAME, O_RDONLY);
+ if (fh < 0)
+ {
+ rb->splash(2*HZ, true, "Couldn't open " OVL_DISPLAYNAME " overlay.");
+ return PLUGIN_ERROR;
+ }
+ readsize = rb->read(fh, &header, sizeof(header));
+ if (readsize != sizeof(header) || header.magic != 0x524f564c)
+ {
+ rb->close(fh);
+ rb->splash(2*HZ, true, OVL_NAME " is not a valid Rockbox overlay.");
+ return PLUGIN_ERROR;
+ }
+
+ mp3buf = rb->plugin_get_mp3_buffer(&mp3buf_size);
+ if (header.start_addr < mp3buf || header.end_addr > mp3buf + mp3buf_size)
+ {
+ rb->close(fh);
+ rb->splash(2*HZ, true, OVL_DISPLAYNAME
+ " overlay doesn't fit into memory.");
+ return PLUGIN_ERROR;
+ }
+ rb->lseek(fh, 0, SEEK_SET);
+ readsize = rb->read(fh, header.start_addr, header.end_addr - header.start_addr);
+ rb->close(fh);
+ if (readsize != header.end_addr - header.start_addr)
+ {
+ rb->splash(2*HZ, true, "Error loading " OVL_DISPLAYNAME " overlay.");
+ return PLUGIN_ERROR;
+ }
+ return header.entry_point(api, parameter);
+}
+#endif
diff --git a/apps/plugins/rockboy/COPYING b/apps/plugins/rockboy/COPYING
new file mode 100755
index 0000000..a43ea21
--- /dev/null
+++ b/apps/plugins/rockboy/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, 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 Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: 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) 19yy <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., 675 Mass Ave, Cambridge, MA 02139, 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) 19yy 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 Library General
+Public License instead of this License.
diff --git a/apps/plugins/rockboy/Makefile b/apps/plugins/rockboy/Makefile
new file mode 100644
index 0000000..f6042a4
--- /dev/null
+++ b/apps/plugins/rockboy/Makefile
@@ -0,0 +1,106 @@
+# __________ __ ___.
+# Open \______ \ ____ ____ | | _\_ |__ _______ ___
+# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+# \/ \/ \/ \/ \/
+# $Id$
+#
+
+INCLUDES = -I$(APPSDIR) -I.. -I. -I$(FIRMDIR)/include -I$(FIRMDIR)/export \
+ -I$(FIRMDIR)/common -I$(FIRMDIR)/drivers
+CFLAGS = $(GCCOPTS) -O3 $(INCLUDES) $(TARGET) $(EXTRA_DEFINES) \
+ -DMEM=${MEMORYSIZE} -DPLUGIN
+
+ifdef APPEXTRA
+ INCLUDES += -I$(APPSDIR)/$(APPEXTRA)
+endif
+
+LINKFILE := $(OBJDIR)/link.lds
+DEPFILE = $(OBJDIR)/dep-rockboy
+SRC = cpu.c emu.c events.c exports.c fastmem.c hw.c lcd.c lcdc.c loader.c \
+ main.c mem.c nosound.c rccmds.c rcvars.c rtc.c save.c sound.c split.c \
+ sys_rockbox.c rockboy.c
+SOURCES = $(SRC)
+OBJS := $(SRC:%.c=$(OBJDIR)/%.o)
+DIRS = .
+
+ifndef SIMVER
+ifneq (,$(findstring RECORDER,$(TARGET))) ## Archos recorder targets
+ LDS := archos.lds
+ OUTPUT = $(OUTDIR)/rockboy.ovl
+else ## iRiver target
+ LDS := ../plugin.lds
+ OUTPUT = $(OUTDIR)/rockboy.rock
+endif
+else ## simulators
+ OUTPUT = $(OUTDIR)/rockboy.rock
+endif
+
+all: $(OUTPUT)
+
+ifndef SIMVER
+$(OBJDIR)/rockboy.elf: $(OBJS) $(LINKFILE) $(OUTDIR)/libplugin.a
+ @echo "LD $@"
+ @$(CC) $(GCCOPTS) -O -nostdlib -o $@ $(OBJS) -L$(OUTDIR) -lplugin -lgcc \
+ -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/rockboy.map
+
+$(OUTPUT): $(OBJDIR)/rockboy.elf
+ @echo "OBJCOPY $<"
+ @$(OC) -O binary $< $@
+else
+
+ifeq ($(SIMVER), x11)
+###################################################
+# This is the X11 simulator version
+
+$(OUTPUT): $(OBJS) $(OUTDIR)/libplugin.a
+ @echo "LD $@"
+ @$(CC) $(CFLAGS) -shared $(OBJS) -L$(OUTDIR) -lplugin -o $@
+ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
+# 'x' must be kept or you'll have "Win32 error 5"
+# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
+# #define ERROR_ACCESS_DENIED 5L
+else
+ @chmod -x $@
+endif
+
+else # end of x11-simulator
+###################################################
+# This is the win32 simulator version
+DLLTOOLFLAGS = --export-all
+DLLWRAPFLAGS = -s --entry _DllMain@12 --target=i386-mingw32 -mno-cygwin
+
+$(OUTPUT): $(OBJS) $(OUTDIR)/libplugin.a
+ @echo "DLL $@"
+ @$(DLLTOOL) $(DLLTOOLFLAGS) -z $(OBJDIR)/$*.def $(OBJS)
+ @$(DLLWRAP) $(DLLWRAPFLAGS) --def $(OBJDIR)/$*.def $(OBJS) \
+ $(OUTDIR)/libplugin.a -o $@
+ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
+# 'x' must be kept or you'll have "Win32 error 5"
+# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
+# #define ERROR_ACCESS_DENIED 5L
+else
+ @chmod -x $@
+endif
+endif # end of win32-simulator
+
+endif # end of simulator section
+
+
+include $(TOOLSDIR)/make.inc
+
+# MEM should be passed on to this makefile with the chosen memory size given
+# in number of MB
+$(LINKFILE): $(LDS)
+ @echo "build $@"
+ @cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) $(DEFINES) \
+ -E -P - >$@
+
+clean:
+ @echo "cleaning rockboy"
+ @rm -rf $(OBJDIR)/rockboy
+ @rm -f $(OBJDIR)/rockboy.*
+
+-include $(DEPFILE)
+
diff --git a/apps/plugins/rockboy/README b/apps/plugins/rockboy/README
new file mode 100755
index 0000000..f10a5f0
--- /dev/null
+++ b/apps/plugins/rockboy/README
@@ -0,0 +1,199 @@
+
+GNUBOY README
+
+
+ INTRO
+
+Welcome to gnuboy, one of the few pieces of Free Software to emulate
+the Game Boy handheld game console. Written in ANSI C with a few
+optional assembler optimizations for particular cpus, gnuboy supports
+a wide range of host systems, and has been tested successfully on:
+
+ GNU/Linux
+ FreeBSD
+ OpenBSD
+ BeOS
+ Linux/390 (IBM S/390 Mainframe)
+ SunOS/Sun Ultra60
+ IRIX/SGI O2
+ IRIX/SGI Indy
+ AIX/Unknown
+ DR-DOS
+ MS-DOS
+ Windows DOS box
+ Windows 9x/NT/2k
+
+Additionally, gnuboy should run on any other *nix variants that have
+ANSI C compilers and that are remotely POSIX compliant. As gnuboy is
+Free Software, you're welcome to fix any problems you encounter
+building it for a particular system, or to port it to entirely new
+systems.
+
+
+ EMULATION
+
+gnuboy emulates nearly all aspects of the (Color) Gameboy, including
+all of the following and much more:
+
+ Full GBZ80 instruction set.
+ Scanline-based LCD engine.
+ Ten sprites per scanline limit.
+ Support for all CGB graphics extensions.
+ Sprite DMA, HDMA, and GDMA.
+ All four sound channels including digital samples.
+ MBC1, MBC2, MBC3 (including clock), and MBC5 mappers.
+ Wave pattern memory corruption when sound channel 3 is played.
+ Pad, timer, divide counter, and other basic hardware registers.
+ CGB double-speed CPU mode.
+
+Aspects not emulated at this time include:
+
+* Serial IO (link cable).
+ Undocumented 'extra' ram in OAM space on Gameboy Color.
+ All Super Gameboy extensions.
+* GBC, HuC1, and HuC3 IR ports.
+* Obscure mappers such as TAMA5.
+ Sorting sprites by X coordinate in DMG mode.
+ HALT instruction skipping in DMG mode.
+ CPU stalls during HDMA and GDMA.
+
+Only the two marked by * are known to affect the playability of
+actual games or demos; the rest are just listed for completeness'
+sake.
+
+
+ FEATURES
+
+In addition to basic emulation, gnuboy provides the following
+features:
+
+ Highly flexible keybinding and configuration subsystem.
+ State saving and loading at any point.
+ Very precise timing/synchronization, preserved across save/load.
+ Joystick support on Linux, DOS, and all SDL-based ports.
+ Fully customizable palettes for DMG games.
+ Screen scaling by a factor of 2, 3, or 4 in all ports.
+ Hardware-based screen scaling on platforms where it's available.
+ Debug traces to stdout.
+ Dynamic palette allocation when run in 256-color modes...
+ OR simulated 3/3/2 bits per channel in 256-color modes.
+
+For information on configuring and using these features, see the
+additional documentation in the "docs" directory.
+
+
+ COMPATIBILITY
+
+Out of over 300 results reported by testers, all games are known to
+work perfectly on gnuboy with the following exceptions:
+
+ Fighting Phoenix (Japanese) may or may not work since it uses the
+ HuC1 memory controller, which is not implemented properly. There has
+ been no report either way so far.
+
+ Pocket Bomberman (Japanese version, which uses HuC1) runs, but can
+ be made to crash if the player jumps into the ceiling in the first
+ level. It's not clear whether this bug is MBC-related, something
+ else, or an actual bug in the original game.
+
+ Monster Go! Go! Go! (Japanese) is unplayable. The cause of the
+ problem is not fully known, but it's either a very bad dump or it's
+ using some sort of specialized MBC that's not documented.
+
+ Final Fantasy Adventure has visual problems with the fade between
+ screens. Does not affect gameplay.
+
+ Bubble Bobble 2 has some minor tile glitches right before gameplay
+ actually begins. Cause unknown. Does not affect gameplay.
+
+ Alone in the Dark is reported to have minor visual glitches. I
+ haven't seen it myself so I can't judge their severity.
+
+ Both new Zelda games are reported to have a visual glitch at the
+ beginning of the game, and on certain other screens. I haven't seen
+ the problem myself, but supposedly it impacts gameplay to some
+ extent.
+
+Please report any other incompatibilities discovered directly to
+gnuboy@unix-fu.org, so that they can be documented and hopefully
+fixed.
+
+
+ FUTURE / WISHLIST
+
+Here's a brief list of what may appear in gnuboy in the future:
+
+ Screenshots.
+ Integrated debugger.
+ Super Gameboy support.
+ Serial link over the internet.
+ Serial link to a real Gameboy with a custom cable.
+ Configurable color filters to provide more authentic LCD look.
+ Custom colorization of DMG games on a per-tile basis.
+ Support for more colorspaces in the hardware scaler.
+ Recording audio.
+ GBS player built from the same source tree.
+ Full recording and playback of emulation.
+ So-called "high level emulation" of certain typical dumb loops.
+
+Features that are not likely to appear soon or at all include:
+
+ Rumble support - this would be nice, but SDL doesn't seem to support
+ force-feedback yet. We'll see about it in the long-term though.
+
+ Eagle/2xSaI/etc. - probably not feasible since these libraries don't
+ appear to be compatible with the terms of the GPL. We might work on
+ our own interpolation engine eventually, but that's low priority.
+
+ GUI/GUI-like features - such things are best handled by external
+ front-ends. We might eventually add a mechanism for external
+ programs to communicate with gnuboy and reconfigure it while it's
+ running, however.
+
+ Plugins - NO! The way I see it, plugins are just an attempt to work
+ around the GPL. In any case, even if you are adding plugin support
+ yourself, you are bound by the terms of the GPL when linking ANY
+ code to gnuboy, including dynamic-linked modules. However we'd
+ rather not deal with this mess to begin with.
+
+ Compressed ROMs/Saves - this one is very iffy. On most systems, this
+ is redundant; *nix users can just pipe the rom through a
+ decompression program, and Windows users can just double-click or
+ drag files from their favorite GUI unzipper program. Linking to zlib
+ isn't really acceptable since it's massively bloated and we don't
+ want to include it with gnuboy or add external dependencies. We may,
+ however, write our own tiny decompressor to use at some point.
+
+Ideas and suggestions for other features are welcome, but won't
+necessarily be used. You're of course also free to add features
+yourself, and if they fit well into the main tree they may eventually
+get included in the official release. See the file HACKING for more
+details on modifying and/or contributing.
+
+
+ THANKS
+
+Thanks goes out to everyone who's expressed interest in gnuboy by
+writing -- users, porters, authors of other emulators, and so forth.
+Apologies if we don't get a personal response out to everyone, but
+either way, consider your feedback appreciated.
+
+
+ EPILOGUE
+
+OK, that looks like about it. More to come, stick around...
+
+
+
+ -Laguna <laguna@aerifal.cx>
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/plugins/rockboy/Version b/apps/plugins/rockboy/Version
new file mode 100755
index 0000000..0b12c42
--- /dev/null
+++ b/apps/plugins/rockboy/Version
@@ -0,0 +1,5 @@
+#define VERSION "1.0.3" /*
+VERSION = 1.0.3
+# */
+
+
diff --git a/apps/plugins/rockboy/archos.lds b/apps/plugins/rockboy/archos.lds
new file mode 100755
index 0000000..23d03c6
--- /dev/null
+++ b/apps/plugins/rockboy/archos.lds
@@ -0,0 +1,46 @@
+#include "config.h"
+
+/* linker script for rockboy as an overlay,
+ * only used/ necessary for SH-based archos targets */
+
+OUTPUT_FORMAT(elf32-sh)
+
+#define DRAMORIG 0x09000000
+#define PLUGIN_LENGTH 0x8000
+
+#define OVERLAY_LENGTH 0x68000
+#define OVERLAY_ORIGIN (DRAMORIG + (MEMORYSIZE * 0x100000) - PLUGIN_LENGTH - OVERLAY_LENGTH)
+
+MEMORY
+{
+ OVERLAY_RAM : ORIGIN = OVERLAY_ORIGIN, LENGTH = OVERLAY_LENGTH
+}
+
+SECTIONS
+{
+ .header : {
+ _ovl_start_addr = .;
+ *(.header)
+ } > OVERLAY_RAM
+
+ .text : {
+ *(.entry)
+ *(.text)
+ } > OVERLAY_RAM
+
+ .data : {
+ *(.data)
+ } > OVERLAY_RAM
+
+ .bss : {
+ *(.bss)
+ } > OVERLAY_RAM
+
+ .rodata : {
+ *(.rodata)
+ *(.rodata.str1.1)
+ *(.rodata.str1.4)
+ . = ALIGN(0x4);
+ _ovl_end_addr = .;
+ } > OVERLAY_RAM
+}
diff --git a/apps/plugins/rockboy/cpu.c b/apps/plugins/rockboy/cpu.c
new file mode 100644
index 0000000..44a870a
--- /dev/null
+++ b/apps/plugins/rockboy/cpu.c
@@ -0,0 +1,880 @@
+
+
+
+#include "rockmacros.h"
+#include "defs.h"
+#include "regs.h"
+#include "hw.h"
+#include "cpu.h"
+#include "lcdc.h"
+#include "mem.h"
+#include "fastmem.h"
+#include "cpuregs.h"
+#include "cpucore.h"
+
+#ifdef USE_ASM
+#include "asm.h"
+#endif
+
+
+struct cpu cpu;
+
+
+
+
+#define ZFLAG(n) ( (n) ? 0 : FZ )
+
+
+#define PUSH(w) ( (SP -= 2), (writew(xSP, (w))) )
+#define POP(w) ( ((w) = readw(xSP)), (SP += 2) )
+
+
+#define FETCH_OLD ( mbc.rmap[PC>>12] \
+? mbc.rmap[PC>>12][PC++] \
+: mem_read(PC++) )
+
+#define FETCH (readb(PC++))
+
+
+#define INC(r) { ((r)++); \
+F = (F & (FL|FC)) | incflag_table[(r)]; }
+
+#define DEC(r) { ((r)--); \
+F = (F & (FL|FC)) | decflag_table[(r)]; }
+
+#define INCW(r) ( (r)++ )
+
+#define DECW(r) ( (r)-- )
+
+#define ADD(n) { \
+W(acc) = (un16)A + (un16)(n); \
+F = (ZFLAG(LB(acc))) \
+| (FH & ((A ^ (n) ^ LB(acc)) << 1)) \
+| (HB(acc) << 4); \
+A = LB(acc); }
+
+#define ADC(n) { \
+W(acc) = (un16)A + (un16)(n) + (un16)((F&FC)>>4); \
+F = (ZFLAG(LB(acc))) \
+| (FH & ((A ^ (n) ^ LB(acc)) << 1)) \
+| (HB(acc) << 4); \
+A = LB(acc); }
+
+#define ADDW(n) { \
+DW(acc) = (un32)HL + (un32)(n); \
+F = (F & (FZ)) \
+| (FH & ((H ^ ((n)>>8) ^ HB(acc)) << 1)) \
+| (acc.b[HI][LO] << 4); \
+HL = W(acc); }
+
+#define ADDSP(n) { \
+DW(acc) = (un32)SP + (un32)(n8)(n); \
+F = (FH & (((SP>>8) ^ ((n)>>8) ^ HB(acc)) << 1)) \
+| (acc.b[HI][LO] << 4); \
+SP = W(acc); }
+
+#define LDHLSP(n) { \
+DW(acc) = (un32)SP + (un32)(n8)(n); \
+F = (FH & (((SP>>8) ^ ((n)>>8) ^ HB(acc)) << 1)) \
+| (acc.b[HI][LO] << 4); \
+HL = W(acc); }
+
+#define CP(n) { \
+W(acc) = (un16)A - (un16)(n); \
+F = FN \
+| (ZFLAG(LB(acc))) \
+| (FH & ((A ^ (n) ^ LB(acc)) << 1)) \
+| ((un8)(-(n8)HB(acc)) << 4); }
+
+#define SUB(n) { CP((n)); A = LB(acc); }
+
+#define SBC(n) { \
+W(acc) = (un16)A - (un16)(n) - (un16)((F&FC)>>4); \
+F = FN \
+| (ZFLAG((n8)LB(acc))) \
+| (FH & ((A ^ (n) ^ LB(acc)) << 1)) \
+| ((un8)(-(n8)HB(acc)) << 4); \
+A = LB(acc); }
+
+#define AND(n) { A &= (n); \
+F = ZFLAG(A) | FH; }
+
+#define XOR(n) { A ^= (n); \
+F = ZFLAG(A); }
+
+#define OR(n) { A |= (n); \
+F = ZFLAG(A); }
+
+#define RLCA(r) { (r) = ((r)>>7) | ((r)<<1); \
+F = (((r)&0x01)<<4); }
+
+#define RRCA(r) { (r) = ((r)<<7) | ((r)>>1); \
+F = (((r)&0x80)>>3); }
+
+#define RLA(r) { \
+LB(acc) = (((r)&0x80)>>3); \
+(r) = ((r)<<1) | ((F&FC)>>4); \
+F = LB(acc); }
+
+#define RRA(r) { \
+LB(acc) = (((r)&0x01)<<4); \
+(r) = ((r)>>1) | ((F&FC)<<3); \
+F = LB(acc); }
+
+#define RLC(r) { RLCA(r); F |= ZFLAG(r); }
+#define RRC(r) { RRCA(r); F |= ZFLAG(r); }
+#define RL(r) { RLA(r); F |= ZFLAG(r); }
+#define RR(r) { RRA(r); F |= ZFLAG(r); }
+
+#define SLA(r) { \
+LB(acc) = (((r)&0x80)>>3); \
+(r) <<= 1; \
+F = ZFLAG((r)) | LB(acc); }
+
+#define SRA(r) { \
+LB(acc) = (((r)&0x01)<<4); \
+(r) = (un8)(((n8)(r))>>1); \
+F = ZFLAG((r)) | LB(acc); }
+
+#define SRL(r) { \
+LB(acc) = (((r)&0x01)<<4); \
+(r) >>= 1; \
+F = ZFLAG((r)) | LB(acc); }
+
+#define CPL(r) { \
+(r) = ~(r); \
+F |= (FH|FN); }
+
+#define SCF { F = (F & (FZ)) | FC; }
+
+#define CCF { F = (F & (FZ|FC)) ^ FC; }
+
+#define DAA { \
+A += (LB(acc) = daa_table[((((int)F)&0x70)<<4) | A]); \
+F = (F & (FN)) | ZFLAG(A) | daa_carry_table[LB(acc)>>2]; }
+
+#define SWAP(r) { \
+(r) = swap_table[(r)]; \
+F = ZFLAG((r)); }
+
+#define BIT(n,r) { F = (F & FC) | ZFLAG(((r) & (1 << (n)))) | FH; }
+#define RES(n,r) { (r) &= ~(1 << (n)); }
+#define SET(n,r) { (r) |= (1 << (n)); }
+
+#define CB_REG_CASES(r, n) \
+case 0x00|(n): RLC(r); break; \
+case 0x08|(n): RRC(r); break; \
+case 0x10|(n): RL(r); break; \
+case 0x18|(n): RR(r); break; \
+case 0x20|(n): SLA(r); break; \
+case 0x28|(n): SRA(r); break; \
+case 0x30|(n): SWAP(r); break; \
+case 0x38|(n): SRL(r); break; \
+case 0x40|(n): BIT(0, r); break; \
+case 0x48|(n): BIT(1, r); break; \
+case 0x50|(n): BIT(2, r); break; \
+case 0x58|(n): BIT(3, r); break; \
+case 0x60|(n): BIT(4, r); break; \
+case 0x68|(n): BIT(5, r); break; \
+case 0x70|(n): BIT(6, r); break; \
+case 0x78|(n): BIT(7, r); break; \
+case 0x80|(n): RES(0, r); break; \
+case 0x88|(n): RES(1, r); break; \
+case 0x90|(n): RES(2, r); break; \
+case 0x98|(n): RES(3, r); break; \
+case 0xA0|(n): RES(4, r); break; \
+case 0xA8|(n): RES(5, r); break; \
+case 0xB0|(n): RES(6, r); break; \
+case 0xB8|(n): RES(7, r); break; \
+case 0xC0|(n): SET(0, r); break; \
+case 0xC8|(n): SET(1, r); break; \
+case 0xD0|(n): SET(2, r); break; \
+case 0xD8|(n): SET(3, r); break; \
+case 0xE0|(n): SET(4, r); break; \
+case 0xE8|(n): SET(5, r); break; \
+case 0xF0|(n): SET(6, r); break; \
+case 0xF8|(n): SET(7, r); break;
+
+
+#define ALU_CASES(base, imm, op, label) \
+case (imm): b = FETCH; goto label; \
+case (base): b = B; goto label; \
+case (base)+1: b = C; goto label; \
+case (base)+2: b = D; goto label; \
+case (base)+3: b = E; goto label; \
+case (base)+4: b = H; goto label; \
+case (base)+5: b = L; goto label; \
+case (base)+6: b = readb(HL); goto label; \
+case (base)+7: b = A; \
+label: op(b); break;
+
+
+
+
+
+
+
+
+#define JR ( PC += 1+(n8)readb(PC) )
+#define JP ( PC = readw(PC) )
+
+#define CALL ( PUSH(PC+2), JP )
+
+#define NOJR ( clen--, PC++ )
+#define NOJP ( clen--, PC+=2 )
+#define NOCALL ( clen-=3, PC+=2 )
+#define NORET ( clen-=3 )
+
+#define RST(n) { PUSH(PC); PC = (n); }
+
+#define RET ( POP(PC) )
+
+#define EI ( IMA = 1 )
+#define DI ( cpu.halt = IMA = IME = 0 )
+
+
+
+#define PRE_INT ( DI, PUSH(PC) )
+#define THROW_INT(n) ( (IF &= ~(1<<(n))), (PC = 0x40+((n)<<3)) )
+
+
+
+
+void cpu_reset(void)
+{
+ cpu.speed = 0;
+ cpu.halt = 0;
+ cpu.div = 0;
+ cpu.tim = 0;
+ cpu.lcdc = 40;
+
+ IME = 0;
+ IMA = 0;
+
+ PC = 0x0100;
+ SP = 0xFFFE;
+ AF = 0x01B0;
+ BC = 0x0013;
+ DE = 0x00D8;
+ HL = 0x014D;
+
+ if (hw.cgb) A = 0x11;
+ if (hw.gba) B = 0x01;
+}
+
+
+void div_advance(int cnt)
+{
+ cpu.div += (cnt<<1);
+ if (cpu.div >= 256)
+ {
+ R_DIV += (cpu.div >> 8);
+ cpu.div &= 0xff;
+ }
+}
+
+void timer_advance(int cnt)
+{
+ int unit, tima;
+
+ if (!(R_TAC & 0x04)) return;
+
+ unit = ((-R_TAC) & 3) << 1;
+ cpu.tim += (cnt<<unit);
+
+ if (cpu.tim >= 512)
+ {
+ tima = R_TIMA + (cpu.tim >> 9);
+ cpu.tim &= 0x1ff;
+ if (tima >= 256)
+ {
+ hw_interrupt(IF_TIMER, IF_TIMER);
+ hw_interrupt(0, IF_TIMER);
+ }
+ while (tima >= 256)
+ tima = tima - 256 + R_TMA;
+ R_TIMA = tima;
+ }
+}
+
+void lcdc_advance(int cnt)
+{
+ cpu.lcdc -= cnt;
+ if (cpu.lcdc <= 0) lcdc_trans();
+}
+
+void sound_advance(int cnt)
+{
+ cpu.snd += cnt;
+}
+
+void cpu_timers(int cnt)
+{
+ div_advance(cnt << cpu.speed);
+ timer_advance(cnt << cpu.speed);
+ lcdc_advance(cnt);
+ sound_advance(cnt);
+}
+
+int cpu_idle(int max)
+{
+ int cnt, unit;
+
+ if (!(cpu.halt && IME)) return 0;
+ if (R_IF & R_IE)
+ {
+ cpu.halt = 0;
+ return 0;
+ }
+
+ /* Make sure we don't miss lcdc status events! */
+ if ((R_IE & (IF_VBLANK | IF_STAT)) && (max > cpu.lcdc))
+ max = cpu.lcdc;
+
+ /* If timer interrupt cannot happen, this is very simple! */
+ if (!((R_IE & IF_TIMER) && (R_TAC & 0x04)))
+ {
+ cpu_timers(max);
+ return max;
+ }
+
+ /* Figure out when the next timer interrupt will happen */
+ unit = ((-R_TAC) & 3) << 1;
+ cnt = (511 - cpu.tim + (1<<unit)) >> unit;
+ cnt += (255 - R_TIMA) << (9 - unit);
+
+ if (max < cnt)
+ cnt = max;
+
+ cpu_timers(cnt);
+ return cnt;
+}
+
+#ifndef ASM_CPU_EMULATE
+
+extern int debug_trace;
+
+int cpu_emulate(int cycles)
+{
+ int i;
+ byte op, cbop;
+ int clen;
+ static union reg acc;
+ static byte b;
+ static word w;
+
+ i = cycles;
+next:
+ if ((clen = cpu_idle(i)))
+ {
+ i -= clen;
+ if (i > 0) goto next;
+ return cycles-i;
+ }
+
+ if (IME && (IF & IE))
+ {
+ PRE_INT;
+ switch ((byte)(IF & IE))
+ {
+ case 0x01: case 0x03: case 0x05: case 0x07:
+ case 0x09: case 0x0B: case 0x0D: case 0x0F:
+ case 0x11: case 0x13: case 0x15: case 0x17:
+ case 0x19: case 0x1B: case 0x1D: case 0x1F:
+ THROW_INT(0); break;
+ case 0x02: case 0x06: case 0x0A: case 0x0E:
+ case 0x12: case 0x16: case 0x1A: case 0x1E:
+ THROW_INT(1); break;
+ case 0x04: case 0x0C: case 0x14: case 0x1C:
+ THROW_INT(2); break;
+ case 0x08: case 0x18:
+ THROW_INT(3); break;
+ case 0x10:
+ THROW_INT(4); break;
+ }
+ }
+ IME = IMA;
+
+// if (debug_trace) debug_disassemble(PC, 1);
+
+ op = FETCH;
+ clen = cycles_table[op];
+
+ switch(op)
+ {
+ case 0x00: /* NOP */
+ case 0x40: /* LD B,B */
+ case 0x49: /* LD C,C */
+ case 0x52: /* LD D,D */
+ case 0x5B: /* LD E,E */
+ case 0x64: /* LD H,H */
+ case 0x6D: /* LD L,L */
+ case 0x7F: /* LD A,A */
+ break;
+
+ case 0x41: /* LD B,C */
+ B = C; break;
+ case 0x42: /* LD B,D */
+ B = D; break;
+ case 0x43: /* LD B,E */
+ B = E; break;
+ case 0x44: /* LD B,H */
+ B = H; break;
+ case 0x45: /* LD B,L */
+ B = L; break;
+ case 0x46: /* LD B,(HL) */
+ B = readb(xHL); break;
+ case 0x47: /* LD B,A */
+ B = A; break;
+
+ case 0x48: /* LD C,B */
+ C = B; break;
+ case 0x4A: /* LD C,D */
+ C = D; break;
+ case 0x4B: /* LD C,E */
+ C = E; break;
+ case 0x4C: /* LD C,H */
+ C = H; break;
+ case 0x4D: /* LD C,L */
+ C = L; break;
+ case 0x4E: /* LD C,(HL) */
+ C = readb(xHL); break;
+ case 0x4F: /* LD C,A */
+ C = A; break;
+
+ case 0x50: /* LD D,B */
+ D = B; break;
+ case 0x51: /* LD D,C */
+ D = C; break;
+ case 0x53: /* LD D,E */
+ D = E; break;
+ case 0x54: /* LD D,H */
+ D = H; break;
+ case 0x55: /* LD D,L */
+ D = L; break;
+ case 0x56: /* LD D,(HL) */
+ D = readb(xHL); break;
+ case 0x57: /* LD D,A */
+ D = A; break;
+
+ case 0x58: /* LD E,B */
+ E = B; break;
+ case 0x59: /* LD E,C */
+ E = C; break;
+ case 0x5A: /* LD E,D */
+ E = D; break;
+ case 0x5C: /* LD E,H */
+ E = H; break;
+ case 0x5D: /* LD E,L */
+ E = L; break;
+ case 0x5E: /* LD E,(HL) */
+ E = readb(xHL); break;
+ case 0x5F: /* LD E,A */
+ E = A; break;
+
+ case 0x60: /* LD H,B */
+ H = B; break;
+ case 0x61: /* LD H,C */
+ H = C; break;
+ case 0x62: /* LD H,D */
+ H = D; break;
+ case 0x63: /* LD H,E */
+ H = E; break;
+ case 0x65: /* LD H,L */
+ H = L; break;
+ case 0x66: /* LD H,(HL) */
+ H = readb(xHL); break;
+ case 0x67: /* LD H,A */
+ H = A; break;
+
+ case 0x68: /* LD L,B */
+ L = B; break;
+ case 0x69: /* LD L,C */
+ L = C; break;
+ case 0x6A: /* LD L,D */
+ L = D; break;
+ case 0x6B: /* LD L,E */
+ L = E; break;
+ case 0x6C: /* LD L,H */
+ L = H; break;
+ case 0x6E: /* LD L,(HL) */
+ L = readb(xHL); break;
+ case 0x6F: /* LD L,A */
+ L = A; break;
+
+ case 0x70: /* LD (HL),B */
+ b = B; goto __LD_HL;
+ case 0x71: /* LD (HL),C */
+ b = C; goto __LD_HL;
+ case 0x72: /* LD (HL),D */
+ b = D; goto __LD_HL;
+ case 0x73: /* LD (HL),E */
+ b = E; goto __LD_HL;
+ case 0x74: /* LD (HL),H */
+ b = H; goto __LD_HL;
+ case 0x75: /* LD (HL),L */
+ b = L; goto __LD_HL;
+ case 0x77: /* LD (HL),A */
+ b = A;
+ __LD_HL:
+ writeb(xHL,b);
+ break;
+
+ case 0x78: /* LD A,B */
+ A = B; break;
+ case 0x79: /* LD A,C */
+ A = C; break;
+ case 0x7A: /* LD A,D */
+ A = D; break;
+ case 0x7B: /* LD A,E */
+ A = E; break;
+ case 0x7C: /* LD A,H */
+ A = H; break;
+ case 0x7D: /* LD A,L */
+ A = L; break;
+ case 0x7E: /* LD A,(HL) */
+ A = readb(xHL); break;
+
+ case 0x01: /* LD BC,imm */
+ BC = readw(xPC); PC += 2; break;
+ case 0x11: /* LD DE,imm */
+ DE = readw(xPC); PC += 2; break;
+ case 0x21: /* LD HL,imm */
+ HL = readw(xPC); PC += 2; break;
+ case 0x31: /* LD SP,imm */
+ SP = readw(xPC); PC += 2; break;
+
+ case 0x02: /* LD (BC),A */
+ writeb(xBC, A); break;
+ case 0x0A: /* LD A,(BC) */
+ A = readb(xBC); break;
+ case 0x12: /* LD (DE),A */
+ writeb(xDE, A); break;
+ case 0x1A: /* LD A,(DE) */
+ A = readb(xDE); break;
+
+ case 0x22: /* LDI (HL),A */
+ writeb(xHL, A); HL++; break;
+ case 0x2A: /* LDI A,(HL) */
+ A = readb(xHL); HL++; break;
+ case 0x32: /* LDD (HL),A */
+ writeb(xHL, A); HL--; break;
+ case 0x3A: /* LDD A,(HL) */
+ A = readb(xHL); HL--; break;
+
+ case 0x06: /* LD B,imm */
+ B = FETCH; break;
+ case 0x0E: /* LD C,imm */
+ C = FETCH; break;
+ case 0x16: /* LD D,imm */
+ D = FETCH; break;
+ case 0x1E: /* LD E,imm */
+ E = FETCH; break;
+ case 0x26: /* LD H,imm */
+ H = FETCH; break;
+ case 0x2E: /* LD L,imm */
+ L = FETCH; break;
+ case 0x36: /* LD (HL),imm */
+ b = FETCH; writeb(xHL, b); break;
+ case 0x3E: /* LD A,imm */
+ A = FETCH; break;
+
+ case 0x08: /* LD (imm),SP */
+ writew(readw(xPC), SP); PC += 2; break;
+ case 0xEA: /* LD (imm),A */
+ writeb(readw(xPC), A); PC += 2; break;
+
+ case 0xE0: /* LDH (imm),A */
+ writehi(FETCH, A); break;
+ case 0xE2: /* LDH (C),A */
+ writehi(C, A); break;
+ case 0xF0: /* LDH A,(imm) */
+ A = readhi(FETCH); break;
+ case 0xF2: /* LDH A,(C) (undocumented) */
+ A = readhi(C); break;
+
+
+ case 0xF8: /* LD HL,SP+imm */
+ b = FETCH; LDHLSP(b); break;
+ case 0xF9: /* LD SP,HL */
+ SP = HL; break;
+ case 0xFA: /* LD A,(imm) */
+ A = readb(readw(xPC)); PC += 2; break;
+
+ ALU_CASES(0x80, 0xC6, ADD, __ADD)
+ ALU_CASES(0x88, 0xCE, ADC, __ADC)
+ ALU_CASES(0x90, 0xD6, SUB, __SUB)
+ ALU_CASES(0x98, 0xDE, SBC, __SBC)
+ ALU_CASES(0xA0, 0xE6, AND, __AND)
+ ALU_CASES(0xA8, 0xEE, XOR, __XOR)
+ ALU_CASES(0xB0, 0xF6, OR, __OR)
+ ALU_CASES(0xB8, 0xFE, CP, __CP)
+
+ case 0x09: /* ADD HL,BC */
+ w = BC; goto __ADDW;
+ case 0x19: /* ADD HL,DE */
+ w = DE; goto __ADDW;
+ case 0x39: /* ADD HL,SP */
+ w = SP; goto __ADDW;
+ case 0x29: /* ADD HL,HL */
+ w = HL;
+ __ADDW:
+ ADDW(w);
+ break;
+
+ case 0x04: /* INC B */
+ INC(B); break;
+ case 0x0C: /* INC C */
+ INC(C); break;
+ case 0x14: /* INC D */
+ INC(D); break;
+ case 0x1C: /* INC E */
+ INC(E); break;
+ case 0x24: /* INC H */
+ INC(H); break;
+ case 0x2C: /* INC L */
+ INC(L); break;
+ case 0x34: /* INC (HL) */
+ b = readb(xHL);
+ INC(b);
+ writeb(xHL, b);
+ break;
+ case 0x3C: /* INC A */
+ INC(A); break;
+
+ case 0x03: /* INC BC */
+ INCW(BC); break;
+ case 0x13: /* INC DE */
+ INCW(DE); break;
+ case 0x23: /* INC HL */
+ INCW(HL); break;
+ case 0x33: /* INC SP */
+ INCW(SP); break;
+
+ case 0x05: /* DEC B */
+ DEC(B); break;
+ case 0x0D: /* DEC C */
+ DEC(C); break;
+ case 0x15: /* DEC D */
+ DEC(D); break;
+ case 0x1D: /* DEC E */
+ DEC(E); break;
+ case 0x25: /* DEC H */
+ DEC(H); break;
+ case 0x2D: /* DEC L */
+ DEC(L); break;
+ case 0x35: /* DEC (HL) */
+ b = readb(xHL);
+ DEC(b);
+ writeb(xHL, b);
+ break;
+ case 0x3D: /* DEC A */
+ DEC(A); break;
+
+ case 0x0B: /* DEC BC */
+ DECW(BC); break;
+ case 0x1B: /* DEC DE */
+ DECW(DE); break;
+ case 0x2B: /* DEC HL */
+ DECW(HL); break;
+ case 0x3B: /* DEC SP */
+ DECW(SP); break;
+
+ case 0x07: /* RLCA */
+ RLCA(A); break;
+ case 0x0F: /* RRCA */
+ RRCA(A); break;
+ case 0x17: /* RLA */
+ RLA(A); break;
+ case 0x1F: /* RRA */
+ RRA(A); break;
+
+ case 0x27: /* DAA */
+ DAA; break;
+ case 0x2F: /* CPL */
+ CPL(A); break;
+
+ case 0x18: /* JR */
+ __JR:
+ JR; break;
+ case 0x20: /* JR NZ */
+ if (!(F&FZ)) goto __JR; NOJR; break;
+ case 0x28: /* JR Z */
+ if (F&FZ) goto __JR; NOJR; break;
+ case 0x30: /* JR NC */
+ if (!(F&FC)) goto __JR; NOJR; break;
+ case 0x38: /* JR C */
+ if (F&FC) goto __JR; NOJR; break;
+
+ case 0xC3: /* JP */
+ __JP:
+ JP; break;
+ case 0xC2: /* JP NZ */
+ if (!(F&FZ)) goto __JP; NOJP; break;
+ case 0xCA: /* JP Z */
+ if (F&FZ) goto __JP; NOJP; break;
+ case 0xD2: /* JP NC */
+ if (!(F&FC)) goto __JP; NOJP; break;
+ case 0xDA: /* JP C */
+ if (F&FC) goto __JP; NOJP; break;
+ case 0xE9: /* JP HL */
+ PC = HL; break;
+
+ case 0xC9: /* RET */
+ __RET:
+ RET; break;
+ case 0xC0: /* RET NZ */
+ if (!(F&FZ)) goto __RET; NORET; break;
+ case 0xC8: /* RET Z */
+ if (F&FZ) goto __RET; NORET; break;
+ case 0xD0: /* RET NC */
+ if (!(F&FC)) goto __RET; NORET; break;
+ case 0xD8: /* RET C */
+ if (F&FC) goto __RET; NORET; break;
+ case 0xD9: /* RETI */
+ IME = IMA = 1; goto __RET;
+
+ case 0xCD: /* CALL */
+ __CALL:
+ CALL; break;
+ case 0xC4: /* CALL NZ */
+ if (!(F&FZ)) goto __CALL; NOCALL; break;
+ case 0xCC: /* CALL Z */
+ if (F&FZ) goto __CALL; NOCALL; break;
+ case 0xD4: /* CALL NC */
+ if (!(F&FC)) goto __CALL; NOCALL; break;
+ case 0xDC: /* CALL C */
+ if (F&FC) goto __CALL; NOCALL; break;
+
+ case 0xC7: /* RST 0 */
+ b = 0x00; goto __RST;
+ case 0xCF: /* RST 8 */
+ b = 0x08; goto __RST;
+ case 0xD7: /* RST 10 */
+ b = 0x10; goto __RST;
+ case 0xDF: /* RST 18 */
+ b = 0x18; goto __RST;
+ case 0xE7: /* RST 20 */
+ b = 0x20; goto __RST;
+ case 0xEF: /* RST 28 */
+ b = 0x28; goto __RST;
+ case 0xF7: /* RST 30 */
+ b = 0x30; goto __RST;
+ case 0xFF: /* RST 38 */
+ b = 0x38;
+ __RST:
+ RST(b); break;
+
+ case 0xC1: /* POP BC */
+ POP(BC); break;
+ case 0xC5: /* PUSH BC */
+ PUSH(BC); break;
+ case 0xD1: /* POP DE */
+ POP(DE); break;
+ case 0xD5: /* PUSH DE */
+ PUSH(DE); break;
+ case 0xE1: /* POP HL */
+ POP(HL); break;
+ case 0xE5: /* PUSH HL */
+ PUSH(HL); break;
+ case 0xF1: /* POP AF */
+ POP(AF); break;
+ case 0xF5: /* PUSH AF */
+ PUSH(AF); break;
+
+ case 0xE8: /* ADD SP,imm */
+ b = FETCH; ADDSP(b); break;
+
+ case 0xF3: /* DI */
+ DI; break;
+ case 0xFB: /* EI */
+ EI; break;
+
+ case 0x37: /* SCF */
+ SCF; break;
+ case 0x3F: /* CCF */
+ CCF; break;
+
+ case 0x10: /* STOP */
+ PC++;
+ if (R_KEY1 & 1)
+ {
+ cpu.speed = cpu.speed ^ 1;
+ R_KEY1 = (R_KEY1 & 0x7E) | (cpu.speed << 7);
+ break;
+ }
+ /* NOTE - we do not implement dmg STOP whatsoever */
+ break;
+
+ case 0x76: /* HALT */
+ cpu.halt = 1;
+ break;
+
+ case 0xCB: /* CB prefix */
+ cbop = FETCH;
+ clen = cb_cycles_table[cbop];
+ switch (cbop)
+ {
+ CB_REG_CASES(B, 0);
+ CB_REG_CASES(C, 1);
+ CB_REG_CASES(D, 2);
+ CB_REG_CASES(E, 3);
+ CB_REG_CASES(H, 4);
+ CB_REG_CASES(L, 5);
+ CB_REG_CASES(A, 7);
+ default:
+ b = readb(xHL);
+ switch(cbop)
+ {
+ CB_REG_CASES(b, 6);
+ }
+ if ((cbop & 0xC0) != 0x40) /* exclude BIT */
+ writeb(xHL, b);
+ break;
+ }
+ break;
+
+ default:
+ die(
+ "invalid opcode 0x%02X at address 0x%04X, rombank = %d\n",
+ op, (PC-1) & 0xffff, mbc.rombank);
+ break;
+ }
+
+ clen <<= 1;
+ div_advance(clen);
+ timer_advance(clen);
+ clen >>= cpu.speed;
+ lcdc_advance(clen);
+ sound_advance(clen);
+
+ i -= clen;
+ if (i > 0) goto next;
+ return cycles-i;
+}
+
+#endif /* ASM_CPU_EMULATE */
+
+
+#ifndef ASM_CPU_STEP
+
+int cpu_step(int max)
+{
+ int cnt;
+ if ((cnt = cpu_idle(max))) return cnt;
+ return cpu_emulate(1);
+}
+
+#endif /* ASM_CPU_STEP */
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/plugins/rockboy/cpu.h b/apps/plugins/rockboy/cpu.h
new file mode 100644
index 0000000..22d58b0
--- /dev/null
+++ b/apps/plugins/rockboy/cpu.h
@@ -0,0 +1,41 @@
+
+
+#ifndef __CPU_H__
+#define __CPU_H__
+
+
+
+#include "defs.h"
+
+
+union reg
+{
+ byte b[2][2];
+ word w[2];
+ un32 d; /* padding for alignment, carry */
+};
+
+struct cpu
+{
+ union reg pc, sp, bc, de, hl, af;
+ int ime, ima;
+ int speed;
+ int halt;
+ int div, tim;
+ int lcdc;
+ int snd;
+};
+
+extern struct cpu cpu;
+
+
+void cpu_reset(void);
+void div_advance(int cnt);
+void timer_advance(int cnt);
+void lcdc_advance(int cnt);
+void sound_advance(int cnt);
+void cpu_timers(int cnt);
+int cpu_emulate(int cycles);
+
+
+#endif
diff --git a/apps/plugins/rockboy/cpucore.h b/apps/plugins/rockboy/cpucore.h
new file mode 100644
index 0000000..361c106
--- /dev/null
+++ b/apps/plugins/rockboy/cpucore.h
@@ -0,0 +1,290 @@
+
+#include "defs.h"
+
+
+static const byte cycles_table[256] =
+{
+ 1, 3, 2, 2, 1, 1, 2, 1, 5, 2, 2, 2, 1, 1, 2, 1,
+ 1, 3, 2, 2, 1, 1, 2, 1, 3, 2, 2, 2, 1, 1, 2, 1,
+ 3, 3, 2, 2, 1, 1, 2, 1, 3, 2, 2, 2, 1, 1, 2, 1,
+ 3, 3, 2, 2, 1, 3, 3, 3, 3, 2, 2, 2, 1, 1, 2, 1,
+
+ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
+ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
+ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
+ 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1,
+
+ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
+ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
+ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
+ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1,
+
+ 5, 3, 4, 4, 6, 4, 2, 4, 5, 4, 4, 1, 6, 6, 2, 4,
+ 5, 3, 4, 0, 6, 4, 2, 4, 5, 4, 4, 0, 6, 0, 2, 4,
+ 3, 3, 2, 0, 0, 4, 2, 4, 4, 1, 4, 0, 0, 0, 2, 4,
+ 3, 3, 2, 1, 0, 4, 2, 4, 3, 2, 4, 1, 0, 0, 2, 4,
+};
+
+static const byte cb_cycles_table[256] =
+{
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,
+
+ 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2,
+ 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2,
+ 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2,
+ 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2,
+
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,
+
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,
+ 2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 4, 2,
+};
+
+
+
+static const byte zflag_table[256] =
+{
+ FZ, 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, 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, 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, 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, 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, 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, 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, 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
+};
+
+static const byte incflag_table[256] =
+{
+ FZ|FH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ FH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ FH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ FH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ FH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ FH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ FH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ FH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ FH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ FH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ FH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ FH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ FH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ FH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ FH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ FH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const byte decflag_table[256] =
+{
+ FZ|FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN|FH,
+ FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN|FH,
+ FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN|FH,
+ FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN|FH,
+ FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN|FH,
+ FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN|FH,
+ FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN|FH,
+ FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN|FH,
+ FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN|FH,
+ FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN|FH,
+ FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN|FH,
+ FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN|FH,
+ FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN|FH,
+ FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN|FH,
+ FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN|FH,
+ FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN, FN|FH
+};
+
+static const byte swap_table[256] =
+{
+ 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
+ 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
+ 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
+ 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
+ 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
+ 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
+ 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
+ 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
+ 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
+ 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
+ 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
+ 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
+ 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
+ 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
+ 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
+ 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF,
+};
+
+static const byte daa_table[4096] =
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+ 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0,
+
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+ 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA,
+
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+ 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A,
+};
+
+static const byte daa_carry_table[64] =
+{
+ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
+ 00, 00, 00, 00, 00, 00, 00, 00, FC, FC, 00, 00, 00, 00, 00, 00,
+ FC, FC, FC, FC, FC, FC, FC, FC, FC, FC, FC, FC, FC, FC, FC, FC,
+ FC, FC, FC, FC, FC, FC, FC, FC, FC, FC, FC, FC, FC, FC, 00, FC,
+};
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/plugins/rockboy/cpuregs.h b/apps/plugins/rockboy/cpuregs.h
new file mode 100644
index 0000000..0d09908
--- /dev/null
+++ b/apps/plugins/rockboy/cpuregs.h
@@ -0,0 +1,56 @@
+
+
+#ifndef __CPUREGS_H__
+
+#define __CPUREGS_H__
+
+
+
+#include "defs.h"
+#include "cpu.h"
+
+#define LB(r) ((r).b[LO][LO])
+#define HB(r) ((r).b[LO][HI])
+#define W(r) ((r).w[LO])
+#define DW(r) ((r).d)
+
+#define A HB(cpu.af)
+#define F LB(cpu.af)
+#define B HB(cpu.bc)
+#define C LB(cpu.bc)
+#define D HB(cpu.de)
+#define E LB(cpu.de)
+#define H HB(cpu.hl)
+#define L LB(cpu.hl)
+
+#define AF W(cpu.af)
+#define BC W(cpu.bc)
+#define DE W(cpu.de)
+#define HL W(cpu.hl)
+
+#define PC W(cpu.pc)
+#define SP W(cpu.sp)
+
+#define xAF DW(cpu.af)
+#define xBC DW(cpu.bc)
+#define xDE DW(cpu.de)
+#define xHL DW(cpu.hl)
+
+#define xPC DW(cpu.pc)
+#define xSP DW(cpu.sp)
+
+#define IMA cpu.ima
+#define IME cpu.ime
+#define IF R_IF
+#define IE R_IE
+
+#define FZ 0x80
+#define FN 0x40
+#define FH 0x20
+#define FC 0x10
+#define FL 0x0F /* low unused portion of flags */
+
+
+#endif /* __CPUREGS_H__ */
+
+
diff --git a/apps/plugins/rockboy/debug.c b/apps/plugins/rockboy/debug.c
new file mode 100644
index 0000000..d0e106b
--- /dev/null
+++ b/apps/plugins/rockboy/debug.c
@@ -0,0 +1,699 @@
+
+
+#include <stdio.h>
+
+#include "rockmacros.h"
+#include "defs.h"
+#include "cpu.h"
+#include "mem.h"
+#include "fastmem.h"
+#include "regs.h"
+#include "rc.h"
+
+#include "cpuregs.h"
+
+
+static char *mnemonic_table[256] =
+{
+ "NOP",
+ "LD BC,%w",
+ "LD (BC),A",
+ "INC BC",
+ "INC B",
+ "DEC B",
+ "LD B,%b",
+ "RLCA",
+ "LD (%w),SP",
+ "ADD HL,BC",
+ "LD A,(BC)",
+ "DEC BC",
+ "INC C",
+ "DEC C",
+ "LD C,%b",
+ "RRCA",
+ "STOP",
+ "LD DE,%w",
+ "LD (DE),A",
+ "INC DE",
+ "INC D",
+ "DEC D",
+ "LD D,%b",
+ "RLA",
+ "JR %o",
+ "ADD HL,DE",
+ "LD A,(DE)",
+ "DEC DE",
+ "INC E",
+ "DEC E",
+ "LD E,%b",
+ "RRA",
+ "JR NZ,%o",
+ "LD HL,%w",
+ "LD (HLI),A",
+ "INC HL",
+ "INC H",
+ "DEC H",
+ "LD H,%b",
+ "DAA",
+ "JR Z,%o",
+ "ADD HL,HL",
+ "LD A,(HLI)",
+ "DEC HL",
+ "INC L",
+ "DEC L",
+ "LD L,%b",
+ "CPL",
+ "JR NC,%o",
+ "LD SP,%w",
+ "LD (HLD),A",
+ "INC SP",
+ "INC (HL)",
+ "DEC (HL)",
+ "LD (HL),%b",
+ "SCF",
+ "JR C,%o",
+ "ADD HL,SP",
+ "LD A,(HLD)",
+ "DEC SP",
+ "INC A",
+ "DEC A",
+ "LD A,%b",
+ "CCF",
+ "LD B,B",
+ "LD B,C",
+ "LD B,D",
+ "LD B,E",
+ "LD B,H",
+ "LD B,L",
+ "LD B,(HL)",
+ "LD B,A",
+ "LD C,B",
+ "LD C,C",
+ "LD C,D",
+ "LD C,E",
+ "LD C,H",
+ "LD C,L",
+ "LD C,(HL)",
+ "LD C,A",
+ "LD D,B",
+ "LD D,C",
+ "LD D,D",
+ "LD D,E",
+ "LD D,H",
+ "LD D,L",
+ "LD D,(HL)",
+ "LD D,A",
+ "LD E,B",
+ "LD E,C",
+ "LD E,D",
+ "LD E,E",
+ "LD E,H",
+ "LD E,L",
+ "LD E,(HL)",
+ "LD E,A",
+ "LD H,B",
+ "LD H,C",
+ "LD H,D",
+ "LD H,E",
+ "LD H,H",
+ "LD H,L",
+ "LD H,(HL)",
+ "LD H,A",
+ "LD L,B",
+ "LD L,C",
+ "LD L,D",
+ "LD L,E",
+ "LD L,H",
+ "LD L,L",
+ "LD L,(HL)",
+ "LD L,A",
+ "LD (HL),B",
+ "LD (HL),C",
+ "LD (HL),D",
+ "LD (HL),E",
+ "LD (HL),H",
+ "LD (HL),L",
+ "HALT",
+ "LD (HL),A",
+ "LD A,B",
+ "LD A,C",
+ "LD A,D",
+ "LD A,E",
+ "LD A,H",
+ "LD A,L",
+ "LD A,(HL)",
+ "LD A,A",
+ "ADD A,B",
+ "ADD A,C",
+ "ADD A,D",
+ "ADD A,E",
+ "ADD A,H",
+ "ADD A,L",
+ "ADD A,(HL)",
+ "ADD A,A",
+ "ADC A,B",
+ "ADC A,C",
+ "ADC A,D",
+ "ADC A,E",
+ "ADC A,H",
+ "ADC A,L",
+ "ADC A,(HL)",
+ "ADC A",
+ "SUB B",
+ "SUB C",
+ "SUB D",
+ "SUB E",
+ "SUB H",
+ "SUB L",
+ "SUB (HL)",
+ "SUB A",
+ "SBC A,B",
+ "SBC A,C",
+ "SBC A,D",
+ "SBC A,E",
+ "SBC A,H",
+ "SBC A,L",
+ "SBC A,(HL)",
+ "SBC A,A",
+ "AND B",
+ "AND C",
+ "AND D",
+ "AND E",
+ "AND H",
+ "AND L",
+ "AND (HL)",
+ "AND A",
+ "XOR B",
+ "XOR C",
+ "XOR D",
+ "XOR E",
+ "XOR H",
+ "XOR L",
+ "XOR (HL)",
+ "XOR A",
+ "OR B",
+ "OR C",
+ "OR D",
+ "OR E",
+ "OR H",
+ "OR L",
+ "OR (HL)",
+ "OR A",
+ "CP B",
+ "CP C",
+ "CP D",
+ "CP E",
+ "CP H",
+ "CP L",
+ "CP (HL)",
+ "CP A",
+ "RET NZ",
+ "POP BC",
+ "JP NZ,%w",
+ "JP %w",
+ "CALL NZ,%w",
+ "PUSH BC",
+ "ADD A,%b",
+ "RST 0h",
+ "RET Z",
+ "RET",
+ "JP Z,%w",
+ NULL,
+ "CALL Z,%w",
+ "CALL %w",
+ "ADC A,%b",
+ "RST 8h",
+ "RET NC",
+ "POP DE",
+ "JP NC,%w",
+ NULL,
+ "CALL NC,%w",
+ "PUSH DE",
+ "SUB %b",
+ "RST 10h",
+ "RET C",
+ "RETI",
+ "JP C,%w",
+ NULL,
+ "CALL C,%w",
+ NULL,
+ "SBC A,%b",
+ "RST 18h",
+ "LD (FF00+%b),A",
+ "POP HL",
+ "LD (FF00+C),A",
+ NULL,
+ NULL,
+ "PUSH HL",
+ "AND %b",
+ "RST 20h",
+ "ADD SP,%o",
+ "JP HL",
+ "LD (%w),A",
+ NULL,
+ NULL,
+ NULL,
+ "XOR %b",
+ "RST 28h",
+ "LD A,(FF00+%b)",
+ "POP AF",
+ "LD A,(FF00+C)",
+ "DI",
+ NULL,
+ "PUSH AF",
+ "OR %b",
+ "RST 30h",
+ "LD HL,SP%o",
+ "LD SP,HL",
+ "LD A,(%w)",
+ "EI",
+ NULL,
+ NULL,
+ "CP %b",
+ "RST 38h"
+};
+
+static char *cb_mnemonic_table[256] =
+{
+ "RLC B",
+ "RLC C",
+ "RLC D",
+ "RLC E",
+ "RLC H",
+ "RLC L",
+ "RLC (HL)",
+ "RLC A",
+ "RRC B",
+ "RRC C",
+ "RRC D",
+ "RRC E",
+ "RRC H",
+ "RRC L",
+ "RRC (HL)",
+ "RRC A",
+ "RL B",
+ "RL C",
+ "RL D",
+ "RL E",
+ "RL H",
+ "RL L",
+ "RL (HL)",
+ "RL A",
+ "RR B",
+ "RR C",
+ "RR D",
+ "RR E",
+ "RR H",
+ "RR L",
+ "RR (HL)",
+ "RR A",
+ "SLA B",
+ "SLA C",
+ "SLA D",
+ "SLA E",
+ "SLA H",
+ "SLA L",
+ "SLA (HL)",
+ "SLA A",
+ "SRA B",
+ "SRA C",
+ "SRA D",
+ "SRA E",
+ "SRA H",
+ "SRA L",
+ "SRA (HL)",
+ "SRA A",
+ "SWAP B",
+ "SWAP C",
+ "SWAP D",
+ "SWAP E",
+ "SWAP H",
+ "SWAP L",
+ "SWAP (HL)",
+ "SWAP A",
+ "SRL B",
+ "SRL C",
+ "SRL D",
+ "SRL E",
+ "SRL H",
+ "SRL L",
+ "SRL (HL)",
+ "SRL A",
+ "BIT 0,B",
+ "BIT 0,C",
+ "BIT 0,D",
+ "BIT 0,E",
+ "BIT 0,H",
+ "BIT 0,L",
+ "BIT 0,(HL)",
+ "BIT 0,A",
+ "BIT 1,B",
+ "BIT 1,C",
+ "BIT 1,D",
+ "BIT 1,E",
+ "BIT 1,H",
+ "BIT 1,L",
+ "BIT 1,(HL)",
+ "BIT 1,A",
+ "BIT 2,B",
+ "BIT 2,C",
+ "BIT 2,D",
+ "BIT 2,E",
+ "BIT 2,H",
+ "BIT 2,L",
+ "BIT 2,(HL)",
+ "BIT 2,A",
+ "BIT 3,B",
+ "BIT 3,C",
+ "BIT 3,D",
+ "BIT 3,E",
+ "BIT 3,H",
+ "BIT 3,L",
+ "BIT 3,(HL)",
+ "BIT 3,A",
+ "BIT 4,B",
+ "BIT 4,C",
+ "BIT 4,D",
+ "BIT 4,E",
+ "BIT 4,H",
+ "BIT 4,L",
+ "BIT 4,(HL)",
+ "BIT 4,A",
+ "BIT 5,B",
+ "BIT 5,C",
+ "BIT 5,D",
+ "BIT 5,E",
+ "BIT 5,H",
+ "BIT 5,L",
+ "BIT 5,(HL)",
+ "BIT 5,A",
+ "BIT 6,B",
+ "BIT 6,C",
+ "BIT 6,D",
+ "BIT 6,E",
+ "BIT 6,H",
+ "BIT 6,L",
+ "BIT 6,(HL)",
+ "BIT 6,A",
+ "BIT 7,B",
+ "BIT 7,C",
+ "BIT 7,D",
+ "BIT 7,E",
+ "BIT 7,H",
+ "BIT 7,L",
+ "BIT 7,(HL)",
+ "BIT 7,A",
+ "RES 0,B",
+ "RES 0,C",
+ "RES 0,D",
+ "RES 0,E",
+ "RES 0,H",
+ "RES 0,L",
+ "RES 0,(HL)",
+ "RES 0,A",
+ "RES 1,B",
+ "RES 1,C",
+ "RES 1,D",
+ "RES 1,E",
+ "RES 1,H",
+ "RES 1,L",
+ "RES 1,(HL)",
+ "RES 1,A",
+ "RES 2,B",
+ "RES 2,C",
+ "RES 2,D",
+ "RES 2,E",
+ "RES 2,H",
+ "RES 2,L",
+ "RES 2,(HL)",
+ "RES 2,A",
+ "RES 3,B",
+ "RES 3,C",
+ "RES 3,D",
+ "RES 3,E",
+ "RES 3,H",
+ "RES 3,L",
+ "RES 3,(HL)",
+ "RES 3,A",
+ "RES 4,B",
+ "RES 4,C",
+ "RES 4,D",
+ "RES 4,E",
+ "RES 4,H",
+ "RES 4,L",
+ "RES 4,(HL)",
+ "RES 4,A",
+ "RES 5,B",
+ "RES 5,C",
+ "RES 5,D",
+ "RES 5,E",
+ "RES 5,H",
+ "RES 5,L",
+ "RES 5,(HL)",
+ "RES 5,A",
+ "RES 6,B",
+ "RES 6,C",
+ "RES 6,D",
+ "RES 6,E",
+ "RES 6,H",
+ "RES 6,L",
+ "RES 6,(HL)",
+ "RES 6,A",
+ "RES 7,B",
+ "RES 7,C",
+ "RES 7,D",
+ "RES 7,E",
+ "RES 7,H",
+ "RES 7,L",
+ "RES 7,(HL)",
+ "RES 7,A",
+ "SET 0,B",
+ "SET 0,C",
+ "SET 0,D",
+ "SET 0,E",
+ "SET 0,H",
+ "SET 0,L",
+ "SET 0,(HL)",
+ "SET 0,A",
+ "SET 1,B",
+ "SET 1,C",
+ "SET 1,D",
+ "SET 1,E",
+ "SET 1,H",
+ "SET 1,L",
+ "SET 1,(HL)",
+ "SET 1,A",
+ "SET 2,B",
+ "SET 2,C",
+ "SET 2,D",
+ "SET 2,E",
+ "SET 2,H",
+ "SET 2,L",
+ "SET 2,(HL)",
+ "SET 2,A",
+ "SET 3,B",
+ "SET 3,C",
+ "SET 3,D",
+ "SET 3,E",
+ "SET 3,H",
+ "SET 3,L",
+ "SET 3,(HL)",
+ "SET 3,A",
+ "SET 4,B",
+ "SET 4,C",
+ "SET 4,D",
+ "SET 4,E",
+ "SET 4,H",
+ "SET 4,L",
+ "SET 4,(HL)",
+ "SET 4,A",
+ "SET 5,B",
+ "SET 5,C",
+ "SET 5,D",
+ "SET 5,E",
+ "SET 5,H",
+ "SET 5,L",
+ "SET 5,(HL)",
+ "SET 5,A",
+ "SET 6,B",
+ "SET 6,C",
+ "SET 6,D",
+ "SET 6,E",
+ "SET 6,H",
+ "SET 6,L",
+ "SET 6,(HL)",
+ "SET 6,A",
+ "SET 7,B",
+ "SET 7,C",
+ "SET 7,D",
+ "SET 7,E",
+ "SET 7,H",
+ "SET 7,L",
+ "SET 7,(HL)",
+ "SET 7,A"
+};
+
+static byte operand_count[256] =
+{
+ 1, 3, 1, 1, 1, 1, 2, 1, 3, 1, 1, 1, 1, 1, 2, 1,
+ 1, 3, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1,
+ 2, 3, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1,
+ 2, 3, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 3, 3, 3, 1, 2, 1, 1, 1, 3, 2, 3, 3, 2, 1,
+ 1, 1, 3, 1, 3, 1, 2, 1, 1, 1, 3, 1, 3, 1, 2, 1,
+ 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 1, 1, 2, 1,
+ 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 1, 1, 2, 1
+};
+
+
+/* replace with a real interactive debugger eventually... */
+
+int debug_trace = 0;
+
+rcvar_t debug_exports[] =
+{
+ RCV_BOOL("trace", &debug_trace),
+ RCV_END
+};
+
+void debug_disassemble(addr a, int c)
+{
+ static int i, j, k;
+ static byte code;
+ static byte ops[3];
+ static int opaddr;
+ static char mnemonic[256];
+ static char *pattern;
+ char meow[500],buf[300];
+// int fd;
+ if(!debug_trace) return;
+// fd=open("/rockboy.trace",O_WRONLY|O_APPEND);
+// if(fd<0)
+// return;
+
+ while (c > 0)
+ {
+ k = 0;
+ opaddr = a;
+ code = ops[k++] = readb(a); a++;
+ if (code != 0xCB)
+ {
+ pattern = mnemonic_table[code];
+ if (!pattern)
+ pattern = "***INVALID***";
+ }
+ else
+ {
+ code = ops[k++] = readb(a); a++;
+ pattern = cb_mnemonic_table[code];
+ }
+ i = j = 0;
+ while (pattern[i])
+ {
+ if (pattern[i] == '%')
+ {
+ switch (pattern[++i])
+ {
+ case 'B':
+ case 'b':
+ ops[k] = readb(a); a++;
+ j += snprintf(mnemonic + j,255-j,
+ "%02Xh", ops[k++]);
+ break;
+ case 'W':
+ case 'w':
+ ops[k] = readb(a); a++;
+ ops[k+1] = readb(a); a++;
+ j += snprintf(mnemonic + j, 255-j,"%04Xh",
+ ((ops[k+1] << 8) | ops[k]));
+ k += 2;
+ break;
+ case 'O':
+ case 'o':
+ ops[k] = readb(a); a++;
+ j += snprintf(mnemonic + j, 255-j,"%+d",
+ (n8)(ops[k++]));
+ break;
+ }
+ i++;
+ }
+ else
+ {
+ mnemonic[j++] = pattern[i++];
+ }
+ }
+ mnemonic[j] = 0;
+ snprintf(buf,299,"%04X ", opaddr);
+ strcpy(meow,buf);
+ switch (operand_count[ops[0]]) {
+ case 1:
+ snprintf(buf,299,"%02X ", ops[0]);
+ strcat(meow,buf);
+ break;
+ case 2:
+ snprintf(buf,299,"%02X %02X ", ops[0], ops[1]);
+ strcat(meow,buf);
+ break;
+ case 3:
+ snprintf(buf,299,"%02X %02X %02X ", ops[0], ops[1], ops[2]);
+ strcat(meow,buf);
+ break;
+ }
+ snprintf(buf,"%-16.16s", mnemonic);
+ strcat(meow,buf);
+ rb->lcd_putsxy(0,0,meow);
+ rb->lcd_update();
+/* fprintf(fd,
+ " SP=%04X.%04X BC=%04X.%02X.%02X DE=%04X.%02X "
+ "HL=%04X.%02X A=%02X F=%02X %c%c%c%c%c",
+ SP, readw(SP),
+ BC, readb(BC), readb(0xFF00 | C),
+ DE, readb(DE),
+ HL, readb(HL), A,
+ F, (IME ? 'I' : '-'),
+ ((F & 0x80) ? 'Z' : '-'),
+ ((F & 0x40) ? 'N' : '-'),
+ ((F & 0x20) ? 'H' : '-'),
+ ((F & 0x10) ? 'C' : '-')
+ );
+ fprintf(fd,
+ " IE=%02X IF=%02X LCDC=%02X STAT=%02X LY=%02X LYC=%02X",
+ R_IE, R_IF, R_LCDC, R_STAT, R_LY, R_LYC
+ );*/
+ c--;
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/plugins/rockboy/defs.h b/apps/plugins/rockboy/defs.h
new file mode 100644
index 0000000..4c520ef
--- /dev/null
+++ b/apps/plugins/rockboy/defs.h
@@ -0,0 +1,36 @@
+
+
+
+#ifndef __DEFS_H__
+#define __DEFS_H__
+
+#include "rockmacros.h"
+
+#ifdef LITTLE_ENDIAN
+#define LO 0
+#define HI 1
+#else
+#define LO 1
+#define HI 0
+#endif
+
+
+typedef unsigned char byte;
+
+typedef unsigned char un8;
+typedef unsigned short un16;
+typedef unsigned int un32;
+
+typedef signed char n8;
+typedef signed short n16;
+typedef signed int n32;
+
+typedef un16 word;
+typedef word addr;
+
+
+
+
+
+#endif
+
diff --git a/apps/plugins/rockboy/emu.c b/apps/plugins/rockboy/emu.c
new file mode 100644
index 0000000..b6f2de7
--- /dev/null
+++ b/apps/plugins/rockboy/emu.c
@@ -0,0 +1,117 @@
+
+
+
+#include "rockmacros.h"
+#include "defs.h"
+#include "regs.h"
+#include "hw.h"
+#include "cpu.h"
+#include "mem.h"
+#include "lcd.h"
+#include "rc.h"
+#include "sound.h"
+#include "rtc.h"
+
+static int framelen = 16743;
+static int framecount;
+
+rcvar_t emu_exports[] =
+{
+ RCV_INT("framelen", &framelen),
+ RCV_INT("framecount", &framecount),
+ RCV_END
+};
+
+
+
+
+
+
+
+void emu_init(void)
+{
+
+}
+
+
+/*
+ * emu_reset is called to initialize the state of the emulated
+ * system. It should set cpu registers, hardware registers, etc. to
+ * their appropriate values at powerup time.
+ */
+
+void emu_reset(void)
+{
+ hw_reset();
+ lcd_reset();
+ cpu_reset();
+ mbc_reset();
+ sound_reset();
+}
+
+
+
+
+
+void emu_step(void)
+{
+ cpu_emulate(cpu.lcdc);
+}
+
+
+
+/* This mess needs to be moved to another module; it's just here to
+ * make things work in the mean time. */
+
+void emu_run(void)
+{
+ void *timer = sys_timer();
+ char meow[500];
+ int delay;
+ int framecount=0;
+
+ vid_begin();
+ lcd_begin();
+ while(shut==0)
+ {
+ cpu_emulate(2280);
+ while (R_LY > 0 && R_LY < 144)
+ emu_step();
+
+ vid_end();
+ rtc_tick();
+ sound_mix();
+ if (!pcm_submit())
+ {
+ delay = framelen - sys_elapsed(timer);
+ sys_sleep(delay);
+ sys_elapsed(timer);
+ }
+ doevents();
+ vid_begin();
+// if (framecount) { if (!--framecount) die("finished\n"); }
+
+ if (!(R_LCDC & 0x80))
+ cpu_emulate(32832);
+
+ while (R_LY > 0) /* wait for next frame */
+ emu_step();
+ framecount++;
+ snprintf(meow,499,"%d",framecount);
+ rb->lcd_putsxy(0,0,meow);
+ rb->lcd_update_rect(0,0,LCD_WIDTH,8);
+ rb->yield();
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/plugins/rockboy/emu.h b/apps/plugins/rockboy/emu.h
new file mode 100644
index 0000000..979b33c
--- /dev/null
+++ b/apps/plugins/rockboy/emu.h
@@ -0,0 +1,2 @@
+void emu_reset(void);
+void emu_run(void);
diff --git a/apps/plugins/rockboy/events.c b/apps/plugins/rockboy/events.c
new file mode 100644
index 0000000..5558dd8
--- /dev/null
+++ b/apps/plugins/rockboy/events.c
@@ -0,0 +1,61 @@
+/*
+ * events.c
+ *
+ * Event queue.
+ */
+
+
+#include "rockmacros.h"
+#include "input.h"
+
+
+char keystates[MAX_KEYS];
+int nkeysdown;
+
+#define MAX_EVENTS 32
+
+static event_t eventqueue[MAX_EVENTS];
+static int eventhead, eventpos;
+
+
+int ev_postevent(event_t *ev)
+{
+ int nextevent;
+ nextevent = (eventhead+1)%MAX_EVENTS;
+ if (nextevent == eventpos)
+ return 0;
+ eventqueue[eventhead] = *ev;
+ eventhead = nextevent;
+ return 1;
+}
+
+int ev_getevent(event_t *ev)
+{
+ if (eventpos == eventhead)
+ {
+ ev->type = EV_NONE;
+ return 0;
+ }
+ *ev = eventqueue[eventpos];
+ eventpos = (eventpos+1)%MAX_EVENTS;
+ if (ev->type == EV_PRESS)
+ {
+ keystates[ev->code] = 1;
+ nkeysdown++;
+ }
+ if (ev->type == EV_RELEASE)
+ {
+ keystates[ev->code] = 0;
+ nkeysdown--;
+ if (nkeysdown < 0) nkeysdown = 0;
+ }
+ return 1;
+}
+
+
+
+
+
+
+
+
diff --git a/apps/plugins/rockboy/exports.c b/apps/plugins/rockboy/exports.c
new file mode 100644
index 0000000..43504f4
--- /dev/null
+++ b/apps/plugins/rockboy/exports.c
@@ -0,0 +1,42 @@
+
+
+#include "rockmacros.h"
+
+#include "rc.h"
+
+extern rcvar_t emu_exports[], loader_exports[],
+ lcd_exports[], rtc_exports[], sound_exports[],
+ vid_exports[], joy_exports[], pcm_exports[];
+
+
+rcvar_t *sources[] =
+{
+ emu_exports,
+ loader_exports,
+ lcd_exports,
+ rtc_exports,
+ sound_exports,
+ vid_exports,
+ joy_exports,
+ pcm_exports,
+ NULL
+};
+
+
+void init_exports(void)
+{
+ rcvar_t **s = sources;
+
+ while (*s)
+ rc_exportvars(*(s++));
+}
+
+
+void show_exports(void)
+{
+ // TODO
+ /*int i, j;
+ for (i = 0; sources[i]; i++)
+ for (j = 0; sources[i][j].name; j++)
+ printf("%s\n", sources[i][j].name);*/
+}
diff --git a/apps/plugins/rockboy/exports.h b/apps/plugins/rockboy/exports.h
new file mode 100644
index 0000000..8d787c0
--- /dev/null
+++ b/apps/plugins/rockboy/exports.h
@@ -0,0 +1,2 @@
+void init_exports(void);
+void show_exports(void);
diff --git a/apps/plugins/rockboy/fastmem.c b/apps/plugins/rockboy/fastmem.c
new file mode 100644
index 0000000..ffb0ed5
--- /dev/null
+++ b/apps/plugins/rockboy/fastmem.c
@@ -0,0 +1,138 @@
+
+
+#include "rockmacros.h"
+#include "fastmem.h"
+
+
+#define D 0 /* direct */
+#define C 1 /* direct cgb-only */
+#define R 2 /* io register */
+#define S 3 /* sound register */
+#define W 4 /* wave pattern */
+
+#define F 0xFF /* fail */
+
+const byte himask[256];
+
+const byte hi_rmap[256] =
+{
+ 0, 0, R, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+ 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, C, 0, C,
+ 0, C, C, C, C, C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, C, C, C, C, 0, 0, 0, 0,
+ C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+const byte hi_wmap[256] =
+{
+ R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R,
+ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+ S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S,
+ R, R, R, R, R, R, R, R, R, R, R, R, 0, R, 0, R,
+ 0, C, C, C, C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, R, R, R, R, 0, 0, 0, 0,
+ R, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, R
+};
+
+
+byte readb(int a)
+{
+ byte *p = mbc.rmap[a>>12];
+ if (p) return p[a];
+ else return mem_read(a);
+}
+
+void writeb(int a, byte b)
+{
+ byte *p = mbc.wmap[a>>12];
+ if (p) p[a] = b;
+ else mem_write(a, b);
+}
+
+int readw(int a)
+{
+ if ((a+1) & 0xfff)
+ {
+ byte *p = mbc.rmap[a>>12];
+ if (p)
+ {
+#ifdef LITTLE_ENDIAN
+#ifndef ALLOW_UNALIGNED_IO
+ if (a&1) return p[a] | (p[a+1]<<8);
+#endif
+ return *(word *)(p+a);
+#else
+ return p[a] | (p[a+1]<<8);
+#endif
+ }
+ }
+ return mem_read(a) | (mem_read(a+1)<<8);
+}
+
+void writew(int a, int w)
+{
+ if ((a+1) & 0xfff)
+ {
+ byte *p = mbc.wmap[a>>12];
+ if (p)
+ {
+#ifdef LITTLE_ENDIAN
+#ifndef ALLOW_UNALIGNED_IO
+ if (a&1)
+ {
+ p[a] = w;
+ p[a+1] = w >> 8;
+ return;
+ }
+#endif
+ *(word *)(p+a) = w;
+ return;
+#else
+ p[a] = w;
+ p[a+1] = w >> 8;
+ return;
+#endif
+ }
+ }
+ mem_write(a, w);
+ mem_write(a+1, w>>8);
+}
+
+byte readhi(int a)
+{
+ return readb(a | 0xff00);
+}
+
+void writehi(int a, byte b)
+{
+ writeb(a | 0xff00, b);
+}
+
+#if 0
+byte readhi(int a)
+{
+ byte (*rd)() = hi_read[a];
+ return rd ? rd(a) : (ram.hi[a] | himask[a]);
+}
+
+void writehi(int a, byte b)
+{
+ byte (*wr)() = hi_write[a];
+ if (wr) wr(a, b);
+ else ram.hi[a] = b & ~himask[a];
+}
+#endif
+
diff --git a/apps/plugins/rockboy/fastmem.h b/apps/plugins/rockboy/fastmem.h
new file mode 100644
index 0000000..7ab447f
--- /dev/null
+++ b/apps/plugins/rockboy/fastmem.h
@@ -0,0 +1,22 @@
+
+#ifndef __FASTMEM_H__
+#define __FASTMEM_H__
+
+
+#include "defs.h"
+#include "mem.h"
+
+
+byte readb(int a);
+void writeb(int a, byte b);
+int readw(int a);
+void writew(int a, int w);
+byte readhi(int a);
+void writehi(int a, byte b);
+#if 0
+byte readhi(int a);
+void writehi(int a, byte b);
+#endif
+
+
+#endif
diff --git a/apps/plugins/rockboy/fb.h b/apps/plugins/rockboy/fb.h
new file mode 100644
index 0000000..97d16ae
--- /dev/null
+++ b/apps/plugins/rockboy/fb.h
@@ -0,0 +1,35 @@
+
+
+#ifndef __FB_H__
+#define __FB_H__
+
+
+#include "defs.h"
+
+
+
+struct fb
+{
+ byte *ptr;
+ int w, h;
+ int pelsize;
+ int pitch;
+ int indexed;
+ struct
+ {
+ int l, r;
+ } cc[4];
+ int yuv;
+ int enabled;
+ int dirty;
+};
+
+
+extern struct fb fb;
+
+
+#endif
+
+
+
+
diff --git a/apps/plugins/rockboy/hw.c b/apps/plugins/rockboy/hw.c
new file mode 100644
index 0000000..c287e24
--- /dev/null
+++ b/apps/plugins/rockboy/hw.c
@@ -0,0 +1,183 @@
+
+
+
+#include "rockmacros.h"
+#include "defs.h"
+#include "cpu.h"
+#include "hw.h"
+#include "regs.h"
+#include "lcd.h"
+#include "mem.h"
+#include "fastmem.h"
+
+
+struct hw hw;
+
+
+
+/*
+ * hw_interrupt changes the virtual interrupt lines included in the
+ * specified mask to the values the corresponding bits in i take, and
+ * in doing so, raises the appropriate bit of R_IF for any interrupt
+ * lines that transition from low to high.
+ */
+
+void hw_interrupt(byte i, byte mask)
+{
+ byte oldif = R_IF;
+ i &= 0x1F & mask;
+ R_IF |= i & (hw.ilines ^ i);
+
+ /* FIXME - is this correct? not sure the docs understand... */
+ if ((R_IF & (R_IF ^ oldif) & R_IE) && cpu.ime) cpu.halt = 0;
+ /* if ((i & (hw.ilines ^ i) & R_IE) && cpu.ime) cpu.halt = 0; */
+ /* if ((i & R_IE) && cpu.ime) cpu.halt = 0; */
+
+ hw.ilines &= ~mask;
+ hw.ilines |= i;
+}
+
+
+/*
+ * hw_dma performs plain old memory-to-oam dma, the original dmg
+ * dma. Although on the hardware it takes a good deal of time, the cpu
+ * continues running during this mode of dma, so no special tricks to
+ * stall the cpu are necessary.
+ */
+
+void hw_dma(byte b)
+{
+ int i;
+ addr a;
+
+ a = ((addr)b) << 8;
+ for (i = 0; i < 160; i++, a++)
+ lcd.oam.mem[i] = readb(a);
+}
+
+
+
+void hw_hdma_cmd(byte c)
+{
+ int cnt;
+ addr sa;
+ int da;
+
+ /* Begin or cancel HDMA */
+ if ((hw.hdma|c) & 0x80)
+ {
+ hw.hdma = c;
+ R_HDMA5 = c & 0x7f;
+ return;
+ }
+
+ /* Perform GDMA */
+ sa = ((addr)R_HDMA1 << 8) | (R_HDMA2&0xf0);
+ da = 0x8000 | ((int)(R_HDMA3&0x1f) << 8) | (R_HDMA4&0xf0);
+ cnt = ((int)c)+1;
+ /* FIXME - this should use cpu time! */
+ /*cpu_timers(102 * cnt);*/
+ cnt <<= 4;
+ while (cnt--)
+ writeb(da++, readb(sa++));
+ R_HDMA1 = sa >> 8;
+ R_HDMA2 = sa & 0xF0;
+ R_HDMA3 = 0x1F & (da >> 8);
+ R_HDMA4 = da & 0xF0;
+ R_HDMA5 = 0xFF;
+}
+
+
+void hw_hdma(void)
+{
+ int cnt;
+ addr sa;
+ int da;
+
+ sa = ((addr)R_HDMA1 << 8) | (R_HDMA2&0xf0);
+ da = 0x8000 | ((int)(R_HDMA3&0x1f) << 8) | (R_HDMA4&0xf0);
+ cnt = 16;
+ while (cnt--)
+ writeb(da++, readb(sa++));
+ R_HDMA1 = sa >> 8;
+ R_HDMA2 = sa & 0xF0;
+ R_HDMA3 = 0x1F & (da >> 8);
+ R_HDMA4 = da & 0xF0;
+ R_HDMA5--;
+ hw.hdma--;
+}
+
+
+/*
+ * pad_refresh updates the P1 register from the pad states, generating
+ * the appropriate interrupts (by quickly raising and lowering the
+ * interrupt line) if a transition has been made.
+ */
+
+void pad_refresh()
+{
+ byte oldp1;
+ oldp1 = R_P1;
+ R_P1 &= 0x30;
+ R_P1 |= 0xc0;
+ if (!(R_P1 & 0x10))
+ R_P1 |= (hw.pad & 0x0F);
+ if (!(R_P1 & 0x20))
+ R_P1 |= (hw.pad >> 4);
+ R_P1 ^= 0x0F;
+ if (oldp1 & ~R_P1 & 0x0F)
+ {
+ hw_interrupt(IF_PAD, IF_PAD);
+ hw_interrupt(0, IF_PAD);
+ }
+}
+
+
+/*
+ * These simple functions just update the state of a button on the
+ * pad.
+ */
+
+void pad_press(byte k)
+{
+ if (hw.pad & k)
+ return;
+ hw.pad |= k;
+ pad_refresh();
+}
+
+void pad_release(byte k)
+{
+ if (!(hw.pad & k))
+ return;
+ hw.pad &= ~k;
+ pad_refresh();
+}
+
+void pad_set(byte k, int st)
+{
+ st ? pad_press(k) : pad_release(k);
+}
+
+void hw_reset()
+{
+ hw.ilines = hw.pad = 0;
+
+ memset(ram.hi, 0, sizeof ram.hi);
+
+ R_P1 = 0xFF;
+ R_LCDC = 0x91;
+ R_BGP = 0xFC;
+ R_OBP0 = 0xFF;
+ R_OBP1 = 0xFF;
+ R_SVBK = 0x01;
+ R_HDMA5 = 0xFF;
+ R_VBK = 0xFE;
+}
+
+
+
+
+
+
+
diff --git a/apps/plugins/rockboy/hw.h b/apps/plugins/rockboy/hw.h
new file mode 100644
index 0000000..d05fb51
--- /dev/null
+++ b/apps/plugins/rockboy/hw.h
@@ -0,0 +1,47 @@
+
+
+
+#ifndef __HW_H__
+#define __HW_H__
+
+
+#include "defs.h"
+
+
+#define PAD_RIGHT 0x01
+#define PAD_LEFT 0x02
+#define PAD_UP 0x04
+#define PAD_DOWN 0x08
+#define PAD_A 0x10
+#define PAD_B 0x20
+#define PAD_SELECT 0x40
+#define PAD_START 0x80
+
+#define IF_VBLANK 0x01
+#define IF_STAT 0x02
+#define IF_TIMER 0x04
+#define IF_SERIAL 0x08
+#define IF_PAD 0x10
+
+struct hw
+{
+ byte ilines;
+ byte pad;
+ int hdma;
+ int cgb,gba;
+};
+
+
+extern struct hw hw;
+
+void hw_interrupt(byte i, byte mask);
+void hw_dma(byte b);
+void hw_hdma_cmd(byte c);
+void hw_hdma(void);
+void pad_refresh(void);
+void pad_press(byte k);
+void pad_release(byte k);
+void pad_set(byte k, int st);
+void hw_reset(void);
+
+#endif
diff --git a/apps/plugins/rockboy/inflate.c b/apps/plugins/rockboy/inflate.c
new file mode 100644
index 0000000..6818749
--- /dev/null
+++ b/apps/plugins/rockboy/inflate.c
@@ -0,0 +1,514 @@
+
+/* Slightly modified from its original form so as not to exit the
+ * program on errors. The resulting file remains in the public
+ * domain for all to use. */
+
+/* --- GZIP file format uncompression routines --- */
+
+/* The following routines (notably the unzip()) function below
+ * uncompress gzipped data. They are terribly slow at the task, but
+ * it is presumed that they work reasonably well. They don't do any
+ * error checking, but they're probably not too vulnerable to buggy
+ * data either. Another important limitation (but it would be pretty
+ * easy to get around) is that the data must reside in memory, it is
+ * not read as a stream. They have been very little tested. Anyway,
+ * whatever these functions are good for, I put them in the public
+ * domain. -- David Madore <david.madore@ens.fr> 1999/11/21 */
+
+#include "rockmacros.h"
+
+static unsigned int
+peek_bits (const unsigned char *data, long p, int q)
+ /* Read q bits starting from bit p from the data pointed to by
+ * data. Data is in little-endian format. */
+{
+ unsigned int answer;
+ int cnt; /* Number of bits already placed in answer */
+ char ob, lb; /* Offset and length of bit field within current byte */
+
+ answer = 0;
+ for ( cnt=0 ; cnt<q ; /* cnt updated in body */ )
+ {
+ ob = (p+cnt)%8;
+ lb = 8-ob;
+ if ( cnt+lb > q )
+ lb = q-cnt;
+ answer |= ((unsigned int)((data[(p+cnt)/8]>>ob)&((1U<<lb)-1)))<<cnt;
+ cnt += lb;
+ }
+ return answer;
+}
+
+static unsigned int
+read_bits (const unsigned char *data, long *p, int q)
+ /* Read q bits as per peek_bits(), but also increase p by q. */
+{
+ unsigned int answer;
+
+ answer = peek_bits (data, *p, q);
+ *p += q;
+ return answer;
+}
+
+static void
+make_code_table (const char size_table[], int table_length,
+ unsigned int code_table[], int maxbits)
+ /* Make a code table from a length table. See rfc1951, section
+ * 3.2.2, for details on what this means. The size_table
+ * contains the length of the Huffman codes for each letter, and
+ * the code_table receives the computed codes themselves.
+ * table_length is the size of the tables (alphabet length) and
+ * maxbits is the maximal allowed code length. */
+{
+ int i, j;
+ unsigned int code;
+
+ code = 0;
+ for ( i=1 ; i<=maxbits ; i++ )
+ {
+ for ( j=0 ; j<table_length ; j++ )
+ {
+ if ( size_table[j]==i )
+ code_table[j] = code++;
+ }
+ code <<= 1;
+ }
+}
+
+static int
+decode_one (const unsigned char *data, long *p,
+ const char size_table[], int table_length,
+ const unsigned int code_table[], int maxbits)
+ /* Decode one alphabet letter from the data, starting at bit p
+ * (which will be increased by the appropriate amount) using
+ * size_table and code_table to decipher the Huffman encoding. */
+{
+ unsigned int code;
+ int i, j;
+
+ code = 0;
+ /* Read as many bits as are likely to be necessary - backward, of
+ * course. */
+ for ( i=0 ; i<maxbits ; i++ )
+ code = (code<<1) + peek_bits (data, (*p)+i, 1);
+ /* Now examine each symbol of the table to find one that matches the
+ * first bits of the code read. */
+ for ( j=0 ; j<table_length ; j++ )
+ {
+ if ( size_table[j]
+ && ( (code>>(maxbits-size_table[j])) == code_table[j] ) )
+ {
+ *p += size_table[j];
+ return j;
+ }
+ }
+ return -1;
+}
+
+/* I don't know what these should be. The rfc1951 doesn't seem to say
+ * (it only mentions them in the last paragraph of section 3.2.1). 15
+ * is almost certainly safe, and it is the largest I can put given the
+ * constraints on the size of integers in the C standard. */
+#define CLEN_MAXBITS 15
+#define HLIT_MAXBITS 15
+#define HDIST_MAXBITS 15
+
+/* The magical table sizes... */
+#define CLEN_TSIZE 19
+#define HLIT_TSIZE 288
+#define HDIST_TSIZE 30
+
+static int
+get_tables (const unsigned char *data, long *p,
+ char hlit_size_table[HLIT_TSIZE],
+ unsigned int hlit_code_table[HLIT_TSIZE],
+ char hdist_size_table[HDIST_TSIZE],
+ unsigned int hdist_code_table[HDIST_TSIZE])
+ /* Fill the Huffman tables (first the code lengths table, and
+ * then, using it, the literal/length table and the distance
+ * table). See section 3.2.7 of rfc1951 for details. */
+{
+ char hlit, hdist, hclen;
+ const int clen_weird_tangle[CLEN_TSIZE]
+ = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
+ char clen_size_table[CLEN_TSIZE];
+ unsigned int clen_code_table[CLEN_TSIZE];
+ int j;
+ unsigned int b;
+ int remainder; /* See note at end of section 3.2.7 of rfc1951. */
+ char rem_val;
+
+ hlit = read_bits (data, p, 5);
+ hdist = read_bits (data, p, 5);
+ hclen = read_bits (data, p, 4);
+ for ( j=0 ; j<4+hclen ; j++ )
+ clen_size_table[clen_weird_tangle[j]]
+ = read_bits (data, p, 3);
+ for ( ; j<CLEN_TSIZE ; j++ )
+ clen_size_table[clen_weird_tangle[j]] = 0;
+ make_code_table (clen_size_table, CLEN_TSIZE,
+ clen_code_table, CLEN_MAXBITS);
+ remainder = 0;
+ rem_val = 0;
+ for ( j=0 ; j<257+hlit ; j++ )
+ {
+ b = decode_one (data, p, clen_size_table, CLEN_TSIZE,
+ clen_code_table, CLEN_MAXBITS);
+ if ( b<0 ) return -1;
+ if ( b<16 )
+ hlit_size_table[j] = b;
+ else if ( b == 16 )
+ {
+ int k, l;
+
+ k = read_bits (data, p, 2);
+ for ( l=0 ; l<k+3 && j+l<257+hlit ; l++ )
+ hlit_size_table[j+l] = hlit_size_table[j-1];
+ j += l-1;
+ remainder = k+3-l; /* THIS IS SO UGLY! */
+ rem_val = hlit_size_table[j-1];
+ }
+ else if ( b == 17 )
+ {
+ int k, l;
+
+ k = read_bits (data, p, 3);
+ for ( l=0 ; l<k+3 && j+l<257+hlit ; l++ )
+ hlit_size_table[j+l] = 0;
+ j += l-1;
+ remainder = k+3-l;
+ rem_val = 0;
+ }
+ else if ( b == 18 )
+ {
+ int k, l;
+
+ k = read_bits (data, p, 7);
+ for ( l=0 ; l<k+11 && j+l<257+hlit ; l++ )
+ hlit_size_table[j+l] = 0;
+ j += l-1;
+ remainder = k+11-l;
+ rem_val = 0;
+ }
+ }
+ for ( ; j<HLIT_TSIZE ; j++ )
+ hlit_size_table[j] = 0;
+ make_code_table (hlit_size_table, HLIT_TSIZE,
+ hlit_code_table, HLIT_MAXBITS);
+ for ( j=0 ; j<remainder ; j++ )
+ hdist_size_table[j] = rem_val;
+ for ( ; j<1+hdist ; j++ )
+ /* Can you spell: ``copy-paste''? */
+ {
+ b = decode_one (data, p, clen_size_table, CLEN_TSIZE,
+ clen_code_table, CLEN_MAXBITS);
+ if ( b<0 ) return -1;
+ if ( b<16 )
+ hdist_size_table[j] = b;
+ else if ( b == 16 )
+ {
+ int k, l;
+
+ k = read_bits (data, p, 2);
+ for ( l=0 ; l<k+3 && j+l<1+hdist ; l++ )
+ hdist_size_table[j+l] = hdist_size_table[j-1];
+ j += l-1;
+ }
+ else if ( b == 17 )
+ {
+ int k, l;
+
+ k = read_bits (data, p, 3);
+ for ( l=0 ; l<k+3 && j+l<1+hdist ; l++ )
+ hdist_size_table[j+l] = 0;
+ j += l-1;
+ }
+ else if ( b == 18 )
+ {
+ int k, l;
+
+ k = read_bits (data, p, 7);
+ for ( l=0 ; l<k+11 && j+l<1+hdist ; l++ )
+ hdist_size_table[j+l] = 0;
+ j += l-1;
+ }
+ }
+ for ( ; j<HDIST_TSIZE ; j++ )
+ hdist_size_table[j] = 0;
+ make_code_table (hdist_size_table, HDIST_TSIZE,
+ hdist_code_table, HDIST_MAXBITS);
+ return 0;
+}
+
+/* The (circular) output buffer. This lets us track
+ * backreferences. */
+
+/* Minimal buffer size. Also the only useful value. */
+#define BUFFER_SIZE 32768
+
+/* Pointer to the character to be added to the buffer */
+static unsigned int buffer_ptr = 0;
+
+/* The buffer itself */
+static unsigned char buffer[BUFFER_SIZE];
+
+static void
+pushout (unsigned char ch)
+ /* Store one byte in the output buffer so it may be retrieved if
+ * it is referenced again. */
+{
+ buffer[buffer_ptr++] = ch;
+ buffer_ptr %= BUFFER_SIZE;
+}
+
+static unsigned char
+pushin (unsigned int dist)
+ /* Retrieve one byte, dist bytes away, from the output buffer. */
+{
+ return buffer[(buffer_ptr+(BUFFER_SIZE-dist))%BUFFER_SIZE];
+}
+
+static int
+get_data (const unsigned char *data, long *p,
+ const char hlit_size_table[HLIT_TSIZE],
+ const unsigned int hlit_code_table[HLIT_TSIZE],
+ const char hdist_size_table[HDIST_TSIZE],
+ const unsigned int hdist_code_table[HDIST_TSIZE],
+ void (* callback) (unsigned char d))
+ /* Do the actual uncompressing. Call callback on each character
+ * uncompressed. */
+{
+ unsigned int b;
+
+ while ( 1 ) {
+ b = decode_one (data, p, hlit_size_table, HLIT_TSIZE,
+ hlit_code_table, HLIT_MAXBITS);
+ if ( b<0 ) return -1;
+ if ( b < 256 )
+ /* Literal */
+ {
+ pushout ((unsigned char) b);
+ callback ((unsigned char) b);
+ }
+ else if ( b == 256 )
+ /* End of block */
+ return 0;
+ else if ( b >= 257 )
+ /* Back reference */
+ {
+ unsigned int bb;
+ unsigned int length, dist;
+ unsigned int l;
+
+ switch ( b )
+ {
+ case 257: length = 3; break;
+ case 258: length = 4; break;
+ case 259: length = 5; break;
+ case 260: length = 6; break;
+ case 261: length = 7; break;
+ case 262: length = 8; break;
+ case 263: length = 9; break;
+ case 264: length = 10; break;
+ case 265: length = 11 + read_bits (data, p, 1); break;
+ case 266: length = 13 + read_bits (data, p, 1); break;
+ case 267: length = 15 + read_bits (data, p, 1); break;
+ case 268: length = 17 + read_bits (data, p, 1); break;
+ case 269: length = 19 + read_bits (data, p, 2); break;
+ case 270: length = 23 + read_bits (data, p, 2); break;
+ case 271: length = 27 + read_bits (data, p, 2); break;
+ case 272: length = 31 + read_bits (data, p, 2); break;
+ case 273: length = 35 + read_bits (data, p, 3); break;
+ case 274: length = 43 + read_bits (data, p, 3); break;
+ case 275: length = 51 + read_bits (data, p, 3); break;
+ case 276: length = 59 + read_bits (data, p, 3); break;
+ case 277: length = 67 + read_bits (data, p, 4); break;
+ case 278: length = 83 + read_bits (data, p, 4); break;
+ case 279: length = 99 + read_bits (data, p, 4); break;
+ case 280: length = 115 + read_bits (data, p, 4); break;
+ case 281: length = 131 + read_bits (data, p, 5); break;
+ case 282: length = 163 + read_bits (data, p, 5); break;
+ case 283: length = 195 + read_bits (data, p, 5); break;
+ case 284: length = 227 + read_bits (data, p, 5); break;
+ case 285: length = 258; break;
+ default:
+ return -1;
+ }
+ bb = decode_one (data, p, hdist_size_table, HDIST_TSIZE,
+ hdist_code_table, HDIST_MAXBITS);
+ switch ( bb )
+ {
+ case 0: dist = 1; break;
+ case 1: dist = 2; break;
+ case 2: dist = 3; break;
+ case 3: dist = 4; break;
+ case 4: dist = 5 + read_bits (data, p, 1); break;
+ case 5: dist = 7 + read_bits (data, p, 1); break;
+ case 6: dist = 9 + read_bits (data, p, 2); break;
+ case 7: dist = 13 + read_bits (data, p, 2); break;
+ case 8: dist = 17 + read_bits (data, p, 3); break;
+ case 9: dist = 25 + read_bits (data, p, 3); break;
+ case 10: dist = 33 + read_bits (data, p, 4); break;
+ case 11: dist = 49 + read_bits (data, p, 4); break;
+ case 12: dist = 65 + read_bits (data, p, 5); break;
+ case 13: dist = 97 + read_bits (data, p, 5); break;
+ case 14: dist = 129 + read_bits (data, p, 6); break;
+ case 15: dist = 193 + read_bits (data, p, 6); break;
+ case 16: dist = 257 + read_bits (data, p, 7); break;
+ case 17: dist = 385 + read_bits (data, p, 7); break;
+ case 18: dist = 513 + read_bits (data, p, 8); break;
+ case 19: dist = 769 + read_bits (data, p, 8); break;
+ case 20: dist = 1025 + read_bits (data, p, 9); break;
+ case 21: dist = 1537 + read_bits (data, p, 9); break;
+ case 22: dist = 2049 + read_bits (data, p, 10); break;
+ case 23: dist = 3073 + read_bits (data, p, 10); break;
+ case 24: dist = 4097 + read_bits (data, p, 11); break;
+ case 25: dist = 6145 + read_bits (data, p, 11); break;
+ case 26: dist = 8193 + read_bits (data, p, 12); break;
+ case 27: dist = 12289 + read_bits (data, p, 12); break;
+ case 28: dist = 16385 + read_bits (data, p, 13); break;
+ case 29: dist = 24577 + read_bits (data, p, 13); break;
+ default:
+ return -1;
+ }
+ for ( l=0 ; l<length ; l++ )
+ {
+ unsigned char ch;
+
+ ch = pushin (dist);
+ pushout (ch);
+ callback (ch);
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+inflate (const unsigned char *data, long *p,
+ void (* callback) (unsigned char d))
+ /* Main uncompression function for the deflate method */
+{
+ char blast, btype;
+ char hlit_size_table[HLIT_TSIZE];
+ unsigned int hlit_code_table[HLIT_TSIZE];
+ char hdist_size_table[HDIST_TSIZE];
+ unsigned int hdist_code_table[HDIST_TSIZE];
+
+ again:
+ blast = read_bits (data, p, 1);
+ btype = read_bits (data, p, 2);
+ if ( btype == 1 || btype == 2 )
+ {
+ if ( btype == 2 )
+ {
+ /* Dynamic Huffman tables */
+ if (get_tables (data, p,
+ hlit_size_table, hlit_code_table,
+ hdist_size_table, hdist_code_table) < 0) return -1;
+ }
+ else
+ /* Fixed Huffman codes */
+ {
+ int j;
+
+ for ( j=0 ; j<144 ; j++ )
+ hlit_size_table[j] = 8;
+ for ( ; j<256 ; j++ )
+ hlit_size_table[j] = 9;
+ for ( ; j<280 ; j++ )
+ hlit_size_table[j] = 7;
+ for ( ; j<HLIT_TSIZE ; j++ )
+ hlit_size_table[j] = 8;
+ make_code_table (hlit_size_table, HLIT_TSIZE,
+ hlit_code_table, HLIT_MAXBITS);
+ for ( j=0 ; j<HDIST_TSIZE ; j++ )
+ hdist_size_table[j] = 5;
+ make_code_table (hdist_size_table, HDIST_TSIZE,
+ hdist_code_table, HDIST_MAXBITS);
+ }
+ if (get_data (data, p,
+ hlit_size_table, hlit_code_table,
+ hdist_size_table, hdist_code_table,
+ callback) < 0) return -1;;
+ }
+ else if ( btype == 0 )
+ /* Non compressed block */
+ {
+ unsigned int len, nlen;
+ unsigned int l;
+ unsigned char b;
+
+ *p = (*p+7)/8; /* Jump to next byte boundary */
+ len = read_bits (data, p, 16);
+ nlen = read_bits (data, p, 16);
+ for ( l=0 ; l<len ; l++ )
+ {
+ b = read_bits (data, p, 8);
+ pushout (b);
+ callback (b);
+ }
+ }
+ else
+ {
+ return -1;
+ }
+ if ( ! blast )
+ goto again;
+ return 0;
+}
+
+int
+unzip (const unsigned char *data, long *p,
+ void (* callback) (unsigned char d))
+ /* Uncompress gzipped data. data is a pointer to the data, p is
+ * a pointer to a long that is initialized to 0 (unless for some
+ * reason you want to start uncompressing further down the data),
+ * and callback is a function taking an unsigned char and
+ * returning void that will be called successively for every
+ * uncompressed byte. */
+{
+ unsigned char cm, flg;
+
+ if ( read_bits (data, p, 8) != 0x1f
+ || read_bits (data, p, 8) != 0x8b )
+ {
+ return -1;
+ }
+ cm = read_bits (data, p, 8);
+ if ( cm != 0x8 )
+ {
+ return -1;
+ }
+ flg = read_bits (data, p, 8);
+ if ( flg & 0xe0 )
+ /* fprintf (stderr, "Warning: unknown bits are set in flags.\n") */ ;
+ read_bits (data, p, 32); /* Ignore modification time */
+ read_bits (data, p, 8); /* Ignore extra flags */
+ read_bits (data, p, 8); /* Ignore OS type */
+ if ( flg & 0x4 )
+ {
+ /* Skip over extra data */
+ unsigned int xlen;
+
+ xlen = read_bits (data, p, 16);
+ *p += ((long)xlen)*8;
+ }
+ if ( flg & 0x8 )
+ {
+ /* Skip over file name */
+ while ( read_bits (data, p, 8) );
+ }
+ if ( flg & 0x10 )
+ {
+ /* Skip over comment */
+ while ( read_bits (data, p, 8) );
+ }
+ if ( flg & 0x2 )
+ /* Ignore CRC16 */
+ read_bits (data, p, 16);
+ return inflate (data, p, callback);
+ /* CRC32 and ISIZE are at the end. We don't even bother to look at
+ * them. */
+}
+
diff --git a/apps/plugins/rockboy/input.h b/apps/plugins/rockboy/input.h
new file mode 100644
index 0000000..8c5fdf9
--- /dev/null
+++ b/apps/plugins/rockboy/input.h
@@ -0,0 +1,24 @@
+/*
+ * input.h
+ *
+ * Definitions for input device stuff - buttons, keys, etc.
+ */
+
+
+#define MAX_KEYS 10
+
+typedef struct event_s
+{
+ int type;
+ int code;
+} event_t;
+
+#define EV_NONE 0
+#define EV_PRESS 1
+#define EV_RELEASE 2
+#define EV_REPEAT 3
+
+int ev_postevent(event_t *ev);
+int ev_getevent(event_t *ev);
+
+
diff --git a/apps/plugins/rockboy/lcd.c b/apps/plugins/rockboy/lcd.c
new file mode 100644
index 0000000..6351cb9
--- /dev/null
+++ b/apps/plugins/rockboy/lcd.c
@@ -0,0 +1,956 @@
+
+
+#include "config.h"
+#include "rockmacros.h"
+#include "defs.h"
+#include "regs.h"
+#include "hw.h"
+#include "mem.h"
+#include "lcd.h"
+#include "rc.h"
+#include "fb.h"
+#include "palette.h"
+#ifdef USE_ASM
+#include "asm.h"
+#endif
+
+struct lcd lcd;
+
+struct scan scan;
+
+#define BG (scan.bg)
+#define WND (scan.wnd)
+#define BUF (scan.buf[scanline_ind])
+#define PRI (scan.pri)
+
+#define PAL1 (scan.pal1)
+#define PAL2 (scan.pal2)
+#define PAL4 (scan.pal4)
+
+#define VS (scan.vs) /* vissprites */
+#define NS (scan.ns)
+
+#define L (scan.l) /* line */
+#define X (scan.x) /* screen position */
+#define Y (scan.y)
+#define S (scan.s) /* tilemap position */
+#define T (scan.t)
+#define U (scan.u) /* position within tile */
+#define V (scan.v)
+#define WX (scan.wx)
+#define WY (scan.wy)
+#define WT (scan.wt)
+#define WV (scan.wv)
+
+byte patpix[4096][8][8];
+byte patdirty[1024];
+byte anydirty;
+
+// static int scale = 1;
+
+static int rgb332;
+
+static int sprsort = 1;
+static int sprdebug;
+static int scanline_ind=0;
+
+#define DEF_PAL { 0x98d0e0, 0x68a0b0, 0x60707C, 0x2C3C3C }
+
+static int dmg_pal[4][4] = { DEF_PAL, DEF_PAL, DEF_PAL, DEF_PAL };
+
+static int usefilter, filterdmg;
+static int filter[3][4] = {
+ { 195, 25, 0, 35 },
+ { 25, 170, 25, 35 },
+ { 25, 60, 125, 40 }
+ };
+
+rcvar_t lcd_exports[] =
+ {
+ RCV_BOOL("rgb332", &rgb332),
+ RCV_VECTOR("dmg_bgp", dmg_pal[0], 4),
+ RCV_VECTOR("dmg_wndp", dmg_pal[1], 4),
+ RCV_VECTOR("dmg_obp0", dmg_pal[2], 4),
+ RCV_VECTOR("dmg_obp1", dmg_pal[3], 4),
+ RCV_BOOL("sprsort", &sprsort),
+ RCV_BOOL("sprdebug", &sprdebug),
+ RCV_BOOL("colorfilter", &usefilter),
+ RCV_BOOL("filterdmg", &filterdmg),
+ RCV_VECTOR("red", filter[0], 4),
+ RCV_VECTOR("green", filter[1], 4),
+ RCV_VECTOR("blue", filter[2], 4),
+ RCV_END
+ };
+
+static byte *vdest;
+
+#ifdef ALLOW_UNALIGNED_IO /* long long is ok since this is i386-only anyway? */
+#define MEMCPY8(d, s) ((*(long long *)(d)) = (*(long long *)(s)))
+#else
+#define MEMCPY8(d, s) memcpy((d), (s), 8)
+#endif
+
+
+
+
+#ifndef ASM_UPDATEPATPIX
+void updatepatpix(void)
+{
+ int i, j;
+#if CONFIG_CPU != SH7034 || defined(SIMULATOR)
+ int k, a, c;
+#endif
+ byte *vram = lcd.vbank[0];
+
+ if (!anydirty) return;
+ for (i = 0; i < 1024; i++)
+ {
+ if (i == 384) i = 512;
+ if (i == 896) break;
+ if (!patdirty[i]) continue;
+ patdirty[i] = 0;
+ for (j = 0; j < 8; j++)
+ {
+#if CONFIG_CPU == SH7034 && !defined(SIMULATOR)
+ asm volatile (
+ "mov.w @%2,r1 \n"
+ "swap.b r1,r2 \n"
+
+ "mov #0,r0 \n"
+ "shlr r1 \n"
+ "rotcl r0 \n"
+ "shlr r2 \n"
+ "rotcl r0 \n"
+ "mov.b r0,@%0 \n"
+ "mov.b r0,@(7,%1) \n"
+ "mov #0,r0 \n"
+ "shlr r1 \n"
+ "rotcl r0 \n"
+ "shlr r2 \n"
+ "rotcl r0 \n"
+ "mov.b r0,@(1,%0) \n"
+ "mov.b r0,@(6,%1) \n"
+ "mov #0,r0 \n"
+ "shlr r1 \n"
+ "rotcl r0 \n"
+ "shlr r2 \n"
+ "rotcl r0 \n"
+ "mov.b r0,@(2,%0) \n"
+ "mov.b r0,@(5,%1) \n"
+ "mov #0,r0 \n"
+ "shlr r1 \n"
+ "rotcl r0 \n"
+ "shlr r2 \n"
+ "rotcl r0 \n"
+ "mov.b r0,@(3,%0) \n"
+ "mov.b r0,@(4,%1) \n"
+ "mov #0,r0 \n"
+ "shlr r1 \n"
+ "rotcl r0 \n"
+ "shlr r2 \n"
+ "rotcl r0 \n"
+ "mov.b r0,@(4,%0) \n"
+ "mov.b r0,@(3,%1) \n"
+ "mov #0,r0 \n"
+ "shlr r1 \n"
+ "rotcl r0 \n"
+ "shlr r2 \n"
+ "rotcl r0 \n"
+ "mov.b r0,@(5,%0) \n"
+ "mov.b r0,@(2,%1) \n"
+ "mov #0,r0 \n"
+ "shlr r1 \n"
+ "rotcl r0 \n"
+ "shlr r2 \n"
+ "rotcl r0 \n"
+ "mov.b r0,@(6,%0) \n"
+ "mov.b r0,@(1,%1) \n"
+ "mov #0,r0 \n"
+ "shlr r1 \n"
+ "rotcl r0 \n"
+ "shlr r2 \n"
+ "rotcl r0 \n"
+ "mov.b r0,@(7,%0) \n"
+ "mov.b r0,@%1 \n"
+ : /* outputs */
+ : /* inputs */
+ /* %0 */ "r"(patpix[i+1024][j]),
+ /* %1 */ "r"(patpix[i][j]),
+ /* %2 */ "r"(&vram[(i<<4)|(j<<1)])
+ : /* clobbers */
+ "r0", "r1", "r2"
+ );
+#else
+ a = ((i<<4) | (j<<1));
+ for (k = 0; k < 8; k++)
+ {
+ c = vram[a] & (1<<k) ? 1 : 0;
+ c |= vram[a+1] & (1<<k) ? 2 : 0;
+ patpix[i+1024][j][k] = c;
+ }
+ for (k = 0; k < 8; k++)
+ patpix[i][j][k] =
+ patpix[i+1024][j][7-k];
+#endif
+ }
+#if CONFIG_CPU == SH7034 && !defined(SIMULATOR)
+ asm volatile (
+ "mov.l @%0,r0 \n"
+ "mov.l @(4,%0),r1 \n"
+ "mov.l r0,@(56,%1) \n"
+ "mov.l r1,@(60,%1) \n"
+ "mov.l @(8,%0),r0 \n"
+ "mov.l @(12,%0),r1 \n"
+ "mov.l r0,@(48,%1) \n"
+ "mov.l r1,@(52,%1) \n"
+ "mov.l @(16,%0),r0 \n"
+ "mov.l @(20,%0),r1 \n"
+ "mov.l r0,@(40,%1) \n"
+ "mov.l r1,@(44,%1) \n"
+ "mov.l @(24,%0),r0 \n"
+ "mov.l @(28,%0),r1 \n"
+ "mov.l r0,@(32,%1) \n"
+ "mov.l r1,@(36,%1) \n"
+ "mov.l @(32,%0),r0 \n"
+ "mov.l @(36,%0),r1 \n"
+ "mov.l r0,@(24,%1) \n"
+ "mov.l r1,@(28,%1) \n"
+ "mov.l @(40,%0),r0 \n"
+ "mov.l @(44,%0),r1 \n"
+ "mov.l r0,@(16,%1) \n"
+ "mov.l r1,@(20,%1) \n"
+ "mov.l @(48,%0),r0 \n"
+ "mov.l @(52,%0),r1 \n"
+ "mov.l r0,@(8,%1) \n"
+ "mov.l r1,@(12,%1) \n"
+ "mov.l @(56,%0),r0 \n"
+ "mov.l @(60,%0),r1 \n"
+ "mov.l r0,@%1 \n"
+ "mov.l r1,@(4,%1) \n"
+
+ "add %2,%0 \n"
+ "add %2,%1 \n"
+
+ "mov.l @%0,r0 \n"
+ "mov.l @(4,%0),r1 \n"
+ "mov.l r0,@(56,%1) \n"
+ "mov.l r1,@(60,%1) \n"
+ "mov.l @(8,%0),r0 \n"
+ "mov.l @(12,%0),r1 \n"
+ "mov.l r0,@(48,%1) \n"
+ "mov.l r1,@(52,%1) \n"
+ "mov.l @(16,%0),r0 \n"
+ "mov.l @(20,%0),r1 \n"
+ "mov.l r0,@(40,%1) \n"
+ "mov.l r1,@(44,%1) \n"
+ "mov.l @(24,%0),r0 \n"
+ "mov.l @(28,%0),r1 \n"
+ "mov.l r0,@(32,%1) \n"
+ "mov.l r1,@(36,%1) \n"
+ "mov.l @(32,%0),r0 \n"
+ "mov.l @(36,%0),r1 \n"
+ "mov.l r0,@(24,%1) \n"
+ "mov.l r1,@(28,%1) \n"
+ "mov.l @(40,%0),r0 \n"
+ "mov.l @(44,%0),r1 \n"
+ "mov.l r0,@(16,%1) \n"
+ "mov.l r1,@(20,%1) \n"
+ "mov.l @(48,%0),r0 \n"
+ "mov.l @(52,%0),r1 \n"
+ "mov.l r0,@(8,%1) \n"
+ "mov.l r1,@(12,%1) \n"
+ "mov.l @(56,%0),r0 \n"
+ "mov.l @(60,%0),r1 \n"
+ "mov.l r0,@%1 \n"
+ "mov.l r1,@(4,%1) \n"
+ : /* outputs */
+ : /* inputs */
+ /* %0 */ "r"(patpix[i][0]),
+ /* %1 */ "r"(patpix[i+2048][0]),
+ /* %2 */ "r"(1024*64)
+ : /* clobbers */
+ "r0", "r1"
+ );
+#else
+ for (j = 0; j < 8; j++)
+ {
+ for (k = 0; k < 8; k++)
+ {
+ patpix[i+2048][j][k] =
+ patpix[i][7-j][k];
+ patpix[i+3072][j][k] =
+ patpix[i+1024][7-j][k];
+ }
+ }
+#endif
+ }
+ anydirty = 0;
+}
+#endif /* ASM_UPDATEPATPIX */
+
+
+
+void tilebuf(void)
+{
+ int i, cnt;
+ int base;
+ byte *tilemap, *attrmap;
+ int *tilebuf;
+ int *wrap;
+ static int wraptable[64] =
+ {
+ 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,-32
+ };
+
+ base = ((R_LCDC&0x08)?0x1C00:0x1800) + (T<<5) + S;
+ tilemap = lcd.vbank[0] + base;
+ attrmap = lcd.vbank[1] + base;
+ tilebuf = BG;
+ wrap = wraptable + S;
+ cnt = ((WX + 7) >> 3) + 1;
+
+ if (hw.cgb) {
+ if (R_LCDC & 0x10)
+ for (i = cnt; i > 0; i--)
+ {
+ *(tilebuf++) = *tilemap
+ | (((int)*attrmap & 0x08) << 6)
+ | (((int)*attrmap & 0x60) << 5);
+ *(tilebuf++) = (((int)*attrmap & 0x07) << 2);
+ attrmap += *wrap + 1;
+ tilemap += *(wrap++) + 1;
+ }
+ else
+ for (i = cnt; i > 0; i--)
+ {
+ *(tilebuf++) = (256 + ((n8)*tilemap))
+ | (((int)*attrmap & 0x08) << 6)
+ | (((int)*attrmap & 0x60) << 5);
+ *(tilebuf++) = (((int)*attrmap & 0x07) << 2);
+ attrmap += *wrap + 1;
+ tilemap += *(wrap++) + 1;
+ }
+ }
+ else
+ {
+ if (R_LCDC & 0x10)
+ for (i = cnt; i > 0; i--)
+ {
+ *(tilebuf++) = *(tilemap++);
+ tilemap += *(wrap++);
+ }
+ else
+ for (i = cnt; i > 0; i--)
+ {
+ *(tilebuf++) = (256 + ((n8)*(tilemap++)));
+ tilemap += *(wrap++);
+ }
+ }
+
+ if (WX >= 160) return;
+
+ base = ((R_LCDC&0x40)?0x1C00:0x1800) + (WT<<5);
+ tilemap = lcd.vbank[0] + base;
+ attrmap = lcd.vbank[1] + base;
+ tilebuf = WND;
+ cnt = ((160 - WX) >> 3) + 1;
+
+ if (hw.cgb)
+ {
+ if (R_LCDC & 0x10)
+ for (i = cnt; i > 0; i--)
+ {
+ *(tilebuf++) = *(tilemap++)
+ | (((int)*attrmap & 0x08) << 6)
+ | (((int)*attrmap & 0x60) << 5);
+ *(tilebuf++) = (((int)*(attrmap++)&7) << 2);
+ }
+ else
+ for (i = cnt; i > 0; i--)
+ {
+ *(tilebuf++) = (256 + ((n8)*(tilemap++)))
+ | (((int)*attrmap & 0x08) << 6)
+ | (((int)*attrmap & 0x60) << 5);
+ *(tilebuf++) = (((int)*(attrmap++)&7) << 2);
+ }
+ }
+ else
+
+ {
+ if (R_LCDC & 0x10)
+ for (i = cnt; i > 0; i--)
+ *(tilebuf++) = *(tilemap++);
+ else
+ for (i = cnt; i > 0; i--)
+ *(tilebuf++) = (256 + ((n8)*(tilemap++)));
+ }
+}
+
+
+// V = vertical line
+// WX = WND start (if 0, no need to do anything) -> WY
+// U = start...something...thingy... 7 at most
+void bg_scan(void)
+{
+ int cnt;
+ byte *src, *dest;
+ int *tile;
+
+ if (WX <= 0) return;
+ cnt = WX;
+ tile = BG;
+ dest = BUF;
+
+ src = patpix[*(tile++)][V] + U;
+ memcpy(dest, src, 8-U);
+ dest += 8-U;
+ cnt -= 8-U;
+ if (cnt <= 0) return;
+ while (cnt >= 8)
+ {
+ src = patpix[*(tile++)][V];
+ MEMCPY8(dest, src);
+ dest += 8;
+ cnt -= 8;
+ }
+ src = patpix[*tile][V];
+ while (cnt--)
+ *(dest++) = *(src++);
+}
+
+void wnd_scan(void)
+{
+ int cnt;
+ byte *src, *dest;
+ int *tile;
+
+ if (WX >= 160) return;
+ cnt = 160 - WX;
+ tile = WND;
+ dest = BUF + WX;
+
+ while (cnt >= 8)
+ {
+ src = patpix[*(tile++)][WV];
+ MEMCPY8(dest, src);
+ dest += 8;
+ cnt -= 8;
+ }
+ src = patpix[*tile][WV];
+ while (cnt--)
+ *(dest++) = *(src++);
+}
+
+static void blendcpy(byte *dest, byte *src, byte b, int cnt)
+{
+ while (cnt--) *(dest++) = *(src++) | b;
+}
+
+static int priused(void *attr)
+{
+ un32 *a = attr;
+ return (int)((a[0]|a[1]|a[2]|a[3]|a[4]|a[5]|a[6]|a[7])&0x80808080);
+}
+
+void bg_scan_pri(void)
+{
+ int cnt, i;
+ byte *src, *dest;
+
+ if (WX <= 0) return;
+ i = S;
+ cnt = WX;
+ dest = PRI;
+ src = lcd.vbank[1] + ((R_LCDC&0x08)?0x1C00:0x1800) + (T<<5);
+
+ if (!priused(src))
+ {
+ memset(dest, 0, cnt);
+ return;
+ }
+
+ memset(dest, src[i++&31]&128, 8-U);
+ dest += 8-U;
+ cnt -= 8-U;
+ if (cnt <= 0) return;
+ while (cnt >= 8)
+ {
+ memset(dest, src[i++&31]&128, 8);
+ dest += 8;
+ cnt -= 8;
+ }
+ memset(dest, src[i&31]&128, cnt);
+}
+
+void wnd_scan_pri(void)
+{
+ int cnt, i;
+ byte *src, *dest;
+
+ if (WX >= 160) return;
+ i = 0;
+ cnt = 160 - WX;
+ dest = PRI + WX;
+ src = lcd.vbank[1] + ((R_LCDC&0x40)?0x1C00:0x1800) + (WT<<5);
+
+ if (!priused(src))
+ {
+ memset(dest, 0, cnt);
+ return;
+ }
+
+ while (cnt >= 8)
+ {
+ memset(dest, src[i++]&128, 8);
+ dest += 8;
+ cnt -= 8;
+ }
+ memset(dest, src[i]&128, cnt);
+}
+
+void bg_scan_color(void)
+{
+ int cnt;
+ byte *src, *dest;
+ int *tile;
+
+ if (WX <= 0) return;
+ cnt = WX;
+ tile = BG;
+ dest = BUF;
+
+ src = patpix[*(tile++)][V] + U;
+ blendcpy(dest, src, *(tile++), 8-U);
+ dest += 8-U;
+ cnt -= 8-U;
+ if (cnt <= 0) return;
+ while (cnt >= 8)
+ {
+ src = patpix[*(tile++)][V];
+ blendcpy(dest, src, *(tile++), 8);
+ dest += 8;
+ cnt -= 8;
+ }
+ src = patpix[*(tile++)][V];
+ blendcpy(dest, src, *(tile++), cnt);
+}
+
+// blend in window source WND target BUF
+// WX = starting X in buf where WND starts
+// WV = vertical line selected for this scanline
+// reverse:
+// WY = starting y in buf where WND starts ?
+// W?? = horizontal line selected for this scanline
+void wnd_scan_color(void)
+{
+ int cnt;
+ byte *src, *dest;
+ int *tile;
+
+ if (WX >= 160) return;
+ cnt = 160 - WX;
+ tile = WND;
+ dest = BUF + WX;
+
+ while (cnt >= 8)
+ {
+ src = patpix[*(tile++)][WV];
+ blendcpy(dest, src, *(tile++), 8);
+ dest += 8;
+ cnt -= 8;
+ }
+ src = patpix[*(tile++)][WV];
+ blendcpy(dest, src, *(tile++), cnt);
+}
+
+static void recolor(byte *buf, byte fill, int cnt)
+{
+ while (cnt--) *(buf++) |= fill;
+}
+
+void spr_count(void)
+{
+ int i;
+ struct obj *o;
+
+ NS = 0;
+ if (!(R_LCDC & 0x02)) return;
+
+ o = lcd.oam.obj;
+
+ for (i = 40; i; i--, o++)
+ {
+ if (L >= o->y || L + 16 < o->y)
+ continue;
+ if (L + 8 >= o->y && !(R_LCDC & 0x04))
+ continue;
+ if (++NS == 10) break;
+ }
+}
+
+void spr_enum(void)
+{
+ int i, j;
+ struct obj *o;
+ struct vissprite ts[10];
+ int v, pat;
+ int l, x;
+
+ NS = 0;
+ if (!(R_LCDC & 0x02)) return;
+
+ o = lcd.oam.obj;
+
+ for (i = 40; i; i--, o++)
+ {
+ if (L >= o->y || L + 16 < o->y)
+ continue;
+ if (L + 8 >= o->y && !(R_LCDC & 0x04))
+ continue;
+ VS[NS].x = (int)o->x - 8;
+ v = L - (int)o->y + 16;
+ if (hw.cgb)
+ {
+ pat = o->pat | (((int)o->flags & 0x60) << 5)
+ | (((int)o->flags & 0x08) << 6);
+ VS[NS].pal = 32 + ((o->flags & 0x07) << 2);
+ }
+ else
+ {
+ pat = o->pat | (((int)o->flags & 0x60) << 5);
+ VS[NS].pal = 32 + ((o->flags & 0x10) >> 2);
+ }
+ VS[NS].pri = (o->flags & 0x80) >> 7;
+ if ((R_LCDC & 0x04))
+ {
+ pat &= ~1;
+ if (v >= 8)
+ {
+ v -= 8;
+ pat++;
+ }
+ if (o->flags & 0x40) pat ^= 1;
+ }
+ VS[NS].buf = patpix[pat][v];
+ if (++NS == 10) break;
+ }
+ if (!sprsort||hw.cgb) return;
+ /* not quite optimal but it finally works! */
+ for (i = 0; i < NS; i++)
+ {
+ l = 0;
+ x = VS[0].x;
+ for (j = 1; j < NS; j++)
+ {
+ if (VS[j].x < x)
+ {
+ l = j;
+ x = VS[j].x;
+ }
+ }
+ ts[i] = VS[l];
+ VS[l].x = 160;
+ }
+ memcpy(VS, ts, sizeof VS);
+}
+
+void spr_scan(void)
+{
+ int i, x;
+ byte pal, b, ns = NS;
+ byte *src, *dest, *bg, *pri;
+ struct vissprite *vs;
+ static byte bgdup[256];
+
+ if (!ns) return;
+
+ memcpy(bgdup, BUF, 256);
+ vs = &VS[ns-1];
+
+ for (; ns; ns--, vs--)
+ {
+ x = vs->x;
+ if (x >= 160) continue;
+ if (x <= -8) continue;
+ if (x < 0)
+ {
+ src = vs->buf - x;
+ dest = BUF;
+ i = 8 + x;
+ }
+ else
+ {
+ src = vs->buf;
+ dest = BUF + x;
+ if (x > 152) i = 160 - x;
+ else i = 8;
+ }
+ pal = vs->pal;
+ if (vs->pri)
+ {
+ bg = bgdup + (dest - BUF);
+ while (i--)
+ {
+ b = src[i];
+ if (b && !(bg[i]&3)) dest[i] = pal|b;
+ }
+ }
+ else if (hw.cgb)
+ {
+ bg = bgdup + (dest - BUF);
+ pri = PRI + (dest - BUF);
+ while (i--)
+ {
+ b = src[i];
+ if (b && (!pri[i] || !(bg[i]&3)))
+ dest[i] = pal|b;
+ }
+ }
+ else while (i--) if (src[i]) dest[i] = pal|src[i];
+ /* else while (i--) if (src[i]) dest[i] = 31 + ns; */
+ }
+// if (sprdebug) for (i = 0; i < NS; i++) BUF[i<<1] = 36;
+}
+
+
+
+
+
+
+void lcd_begin(void)
+{
+/* if (fb.indexed)
+ {
+ if (rgb332) pal_set332();
+ else pal_expire();
+ }
+ while (scale * 160 > fb.w || scale * 144 > fb.h) scale--; */
+ vdest = fb.ptr + ((fb.w*fb.pelsize)>>1)
+ - (80*fb.pelsize)
+ + ((fb.h>>1) - 72) * fb.pitch;
+ WY = R_WY;
+}
+
+void lcd_refreshline(void)
+{
+ if (!fb.enabled) return;
+
+ if (!(R_LCDC & 0x80))
+ return; /* should not happen... */
+
+#if LCD_HEIGHT == 64
+ if (R_LY >= 128 || R_LY & 1) /* calculate only even lines */
+#else
+ if (R_LY >= 128)
+#endif
+ return;
+
+ updatepatpix();
+
+ L = R_LY;
+#if LCD_HEIGHT == 64
+ scanline_ind = (L/2) % 8;
+#else
+ scanline_ind = L % 8;
+#endif
+ X = R_SCX;
+ Y = (R_SCY + L) & 0xff;
+ S = X >> 3;
+ T = Y >> 3;
+ U = X & 7;
+ V = Y & 7;
+
+ WX = R_WX - 7;
+ if (WY>L || WY<0 || WY>143 || WX<-7 || WX>159 || !(R_LCDC&0x20))
+ WX = 160;
+ WT = (L - WY) >> 3;
+ WV = (L - WY) & 7;
+
+ spr_enum();
+
+ tilebuf();
+ if (hw.cgb)
+ {
+ bg_scan_color();
+ wnd_scan_color();
+ if (NS)
+ {
+ bg_scan_pri();
+ wnd_scan_pri();
+ }
+ }
+ else
+ {
+
+ bg_scan();
+ wnd_scan();
+ recolor(BUF+WX, 0x04, 160-WX);
+ }
+ spr_scan();
+/*
+ if (fb.dirty) memset(fb.ptr, 0, fb.pitch * fb.h);
+ fb.dirty = 0;
+ if (density > scale) density = scale;
+ if (scale == 1) density = 1;
+ dest = vdest;
+*/
+ if (scanline_ind == 7)
+ vid_update(L);
+ // vdest += fb.pitch * scale;
+}
+
+
+
+
+
+
+/*
+static void updatepalette(int i)
+{
+ int c, r, g, b, y, u, v, rr, gg;
+
+ c = (lcd.pal[i<<1] | ((int)lcd.pal[(i<<1)|1] << 8)) & 0x7FFF;
+ r = (c & 0x001F) << 3;
+ g = (c & 0x03E0) >> 2;
+ b = (c & 0x7C00) >> 7;
+ r |= (r >> 5);
+ g |= (g >> 5);
+ b |= (b >> 5);
+
+ if (usefilter && (filterdmg||hw.cgb))
+ {
+ rr = ((r * filter[0][0] + g * filter[0][1] + b * filter[0][2]) >> 8) + filter[0][3];
+ gg = ((r * filter[1][0] + g * filter[1][1] + b * filter[1][2]) >> 8) + filter[1][3];
+ b = ((r * filter[2][0] + g * filter[2][1] + b * filter[2][2]) >> 8) + filter[2][3];
+ r = rr;
+ g = gg;
+ }
+
+ if (fb.yuv)
+ {
+ y = (((r * 263) + (g * 516) + (b * 100)) >> 10) + 16;
+ u = (((r * 450) - (g * 377) - (b * 73)) >> 10) + 128;
+ v = (((r * -152) - (g * 298) + (b * 450)) >> 10) + 128;
+ if (y < 0) y = 0; if (y > 255) y = 255;
+ if (u < 0) u = 0; if (u > 255) u = 255;
+ if (v < 0) v = 0; if (v > 255) v = 255;
+ PAL4[i] = (y<<fb.cc[0].l) | (y<<fb.cc[3].l)
+ | (u<<fb.cc[1].l) | (v<<fb.cc[2].l);
+ return;
+ }
+
+ if (fb.indexed)
+ {
+ pal_release(PAL1[i]);
+ c = pal_getcolor(c, r, g, b);
+ PAL1[i] = c;
+ PAL2[i] = (c<<8) | c;
+ PAL4[i] = (c<<24) | (c<<16) | (c<<8) | c;
+ return;
+ }
+
+ r = (r >> fb.cc[0].r) << fb.cc[0].l;
+ g = (g >> fb.cc[1].r) << fb.cc[1].l;
+ b = (b >> fb.cc[2].r) << fb.cc[2].l;
+ c = r|g|b;
+
+ switch (fb.pelsize)
+ {
+ case 1:
+ PAL1[i] = c;
+ PAL2[i] = (c<<8) | c;
+ PAL4[i] = (c<<24) | (c<<16) | (c<<8) | c;
+ break;
+ case 2:
+ PAL2[i] = c;
+ PAL4[i] = (c<<16) | c;
+ break;
+ case 3:
+ case 4:
+ PAL4[i] = c;
+ break;
+ }
+}*/
+
+void pal_write(int i, byte b)
+{
+ if (lcd.pal[i] == b) return;
+ lcd.pal[i] = b;
+// updatepalette(i>>1);
+}
+
+void pal_write_dmg(int i, int mapnum, byte d)
+{
+ int j;
+ int *cmap = dmg_pal[mapnum];
+ int c, r, g, b;
+
+ if (hw.cgb) return;
+
+ /* if (mapnum >= 2) d = 0xe4; */
+ for (j = 0; j < 8; j += 2)
+ {
+ c = cmap[(d >> j) & 3];
+ r = (c & 0xf8) >> 3;
+ g = (c & 0xf800) >> 6;
+ b = (c & 0xf80000) >> 9;
+ c = r|g|b;
+ /* FIXME - handle directly without faking cgb */
+ pal_write(i+j, c & 0xff);
+ pal_write(i+j+1, c >> 8);
+ }
+}
+
+void vram_write(int a, byte b)
+{
+ lcd.vbank[R_VBK&1][a] = b;
+ if (a >= 0x1800) return;
+ patdirty[((R_VBK&1)<<9)+(a>>4)] = 1;
+ anydirty = 1;
+}
+
+void vram_dirty(void)
+{
+ anydirty = 1;
+ memset(patdirty, 1, sizeof patdirty);
+}
+
+void pal_dirty(void)
+{
+// int i;
+ if (!hw.cgb)
+ {
+
+ pal_write_dmg(0, 0, R_BGP);
+ pal_write_dmg(8, 1, R_BGP);
+ pal_write_dmg(64, 2, R_OBP0);
+ pal_write_dmg(72, 3, R_OBP1);
+ }
+// for (i = 0; i < 64; i++)
+// updatepalette(i);
+}
+
+void lcd_reset(void)
+{
+ memset(&lcd, 0, sizeof lcd);
+ lcd_begin();
+ vram_dirty();
+ pal_dirty();
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/plugins/rockboy/lcd.h b/apps/plugins/rockboy/lcd.h
new file mode 100644
index 0000000..9442b56
--- /dev/null
+++ b/apps/plugins/rockboy/lcd.h
@@ -0,0 +1,74 @@
+
+
+#ifndef __LCD_H__
+#define __LCD_H__
+
+#include "defs.h"
+
+struct vissprite
+{
+ byte *buf;
+ int x;
+ byte pal, pri, pad[6];
+};
+
+struct scan
+{
+ int bg[64];
+ int wnd[64];
+ byte buf[8][256];
+ byte pal1[128];
+ un16 pal2[64];
+ un32 pal4[64];
+ byte pri[256];
+ struct vissprite vs[16];
+ int ns, l, x, y, s, t, u, v, wx, wy, wt, wv;
+};
+
+struct obj
+{
+ byte y;
+ byte x;
+ byte pat;
+ byte flags;
+};
+
+struct lcd
+{
+ byte vbank[2][8192];
+ union
+ {
+ byte mem[256];
+ struct obj obj[40];
+ } oam;
+ byte pal[128];
+};
+
+extern struct lcd lcd;
+extern struct scan scan;
+
+
+
+
+
+#endif
+
+
+
+void updatepatpix(void);
+void tilebuf(void);
+void bg_scan(void);
+void wnd_scan(void);
+void bg_scan_pri(void);
+void wnd_scan_pri(void);
+void spr_count(void);
+void spr_enum(void);
+void spr_scan(void);
+void lcd_begin(void);
+void lcd_refreshline(void);
+void pal_write(int i, byte b);
+void pal_write_dmg(int i, int mapnum, byte d);
+void vram_write(int a, byte b);
+void vram_dirty(void);
+void pal_dirty(void);
+void lcd_reset(void);
diff --git a/apps/plugins/rockboy/lcdc.c b/apps/plugins/rockboy/lcdc.c
new file mode 100644
index 0000000..c82b828
--- /dev/null
+++ b/apps/plugins/rockboy/lcdc.c
@@ -0,0 +1,180 @@
+
+
+#include "rockmacros.h"
+
+#include "defs.h"
+#include "hw.h"
+#include "cpu.h"
+#include "regs.h"
+#include "lcd.h"
+
+
+#define C (cpu.lcdc)
+
+
+/*
+ * stat_trigger updates the STAT interrupt line to reflect whether any
+ * of the conditions set to be tested (by bits 3-6 of R_STAT) are met.
+ * This function should be called whenever any of the following occur:
+ * 1) LY or LYC changes.
+ * 2) A state transition affects the low 2 bits of R_STAT (see below).
+ * 3) The program writes to the upper bits of R_STAT.
+ * stat_trigger also updates bit 2 of R_STAT to reflect whether LY=LYC.
+ */
+
+void stat_trigger(void)
+{
+ static const int condbits[4] = { 0x08, 0x30, 0x20, 0x00 };
+ int flag = 0;
+
+ if ((R_LY < 0x91) && (R_LY == R_LYC))
+ {
+ R_STAT |= 0x04;
+ if (R_STAT & 0x40) flag = IF_STAT;
+ }
+ else R_STAT &= ~0x04;
+
+ if (R_STAT & condbits[R_STAT&3]) flag = IF_STAT;
+
+ if (!(R_LCDC & 0x80)) flag = 0;
+
+ hw_interrupt(flag, IF_STAT);
+}
+
+void stat_write(byte b)
+{
+ R_STAT = (R_STAT & 0x07) | (b & 0x78);
+ if (!hw.cgb &&!(R_STAT & 2)) /* DMG STAT write bug => interrupt */
+ hw_interrupt(IF_STAT, IF_STAT);
+ stat_trigger();
+}
+
+
+/*
+ * stat_change is called when a transition results in a change to the
+ * LCD STAT condition (the low 2 bits of R_STAT). It raises or lowers
+ * the VBLANK interrupt line appropriately and calls stat_trigger to
+ * update the STAT interrupt line.
+ */
+
+static void stat_change(int stat)
+{
+ stat &= 3;
+ R_STAT = (R_STAT & 0x7C) | stat;
+
+ if (stat != 1) hw_interrupt(0, IF_VBLANK);
+ /* hw_interrupt((stat == 1) ? IF_VBLANK : 0, IF_VBLANK); */
+ stat_trigger();
+}
+
+
+void lcdc_change(byte b)
+{
+ byte old = R_LCDC;
+ R_LCDC = b;
+ if ((R_LCDC ^ old) & 0x80) /* lcd on/off change */
+ {
+ R_LY = 0;
+ stat_change(2);
+ C = 40;
+ lcd_begin();
+ }
+}
+
+
+void lcdc_trans(void)
+{
+ if (!(R_LCDC & 0x80))
+ {
+ while (C <= 0)
+ {
+ switch ((byte)(R_STAT & 3))
+ {
+ case 0:
+ case 1:
+ stat_change(2);
+ C += 40;
+ break;
+ case 2:
+ stat_change(3);
+ C += 86;
+ break;
+ case 3:
+ stat_change(0);
+ if (hw.hdma & 0x80)
+ hw_hdma();
+ else
+ C += 102;
+ break;
+ }
+ return;
+ }
+ }
+ while (C <= 0)
+ {
+ switch ((byte)(R_STAT & 3))
+ {
+ case 1:
+ if (!(hw.ilines & IF_VBLANK))
+ {
+ C += 218;
+ hw_interrupt(IF_VBLANK, IF_VBLANK);
+ break;
+ }
+ if (R_LY == 0)
+ {
+ lcd_begin();
+ stat_change(2);
+ C += 40;
+ break;
+ }
+ else if (R_LY < 152)
+ C += 228;
+ else if (R_LY == 152)
+ C += 28;
+ else
+ {
+ R_LY = -1;
+ C += 200;
+ }
+ R_LY++;
+ stat_trigger();
+ break;
+ case 2:
+ lcd_refreshline();
+ stat_change(3);
+ C += 86;
+ break;
+ case 3:
+ stat_change(0);
+ if (hw.hdma & 0x80)
+ hw_hdma();
+ /* FIXME -- how much of the hblank does hdma use?? */
+ /* else */
+ C += 102;
+ break;
+ case 0:
+ if (++R_LY >= 144)
+ {
+ if (cpu.halt)
+ {
+ hw_interrupt(IF_VBLANK, IF_VBLANK);
+ C += 228;
+ }
+ else C += 10;
+ stat_change(1);
+ break;
+ }
+ stat_change(2);
+ C += 40;
+ break;
+ }
+ }
+}
+
+
+
+
+
+
+
diff --git a/apps/plugins/rockboy/lcdc.h b/apps/plugins/rockboy/lcdc.h
new file mode 100644
index 0000000..c5edc6c
--- /dev/null
+++ b/apps/plugins/rockboy/lcdc.h
@@ -0,0 +1,4 @@
+void stat_trigger(void);
+void stat_write(byte b);
+void lcdc_change(byte b);
+void lcdc_trans(void);
diff --git a/apps/plugins/rockboy/loader.c b/apps/plugins/rockboy/loader.c
new file mode 100644
index 0000000..ad7c309
--- /dev/null
+++ b/apps/plugins/rockboy/loader.c
@@ -0,0 +1,383 @@
+
+#include <stdio.h>
+#include <string.h>
+
+
+#include "rockmacros.h"
+#include "defs.h"
+#include "regs.h"
+#include "mem.h"
+#include "hw.h"
+#include "rtc.h"
+#include "rc.h"
+#include "save.h"
+#include "sound.h"
+
+
+static int mbc_table[256] =
+{
+ 0, 1, 1, 1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 3,
+ 3, 3, 3, 3, 0, 0, 0, 0, 0, 5, 5, 5, MBC_RUMBLE, MBC_RUMBLE, MBC_RUMBLE, 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, 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, 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, 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, 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, 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, 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, MBC_HUC3, MBC_HUC1
+};
+
+static int rtc_table[256] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0
+};
+
+static int batt_table[256] =
+{
+ 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0,
+ 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
+ 0
+};
+
+static int romsize_table[256] =
+{
+ 2, 4, 8, 16, 32, 64, 128, 256, 512,
+ 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,
+ 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,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 128, 128, 128
+ /* 0, 0, 72, 80, 96 -- actual values but bad to use these! */
+};
+
+static int ramsize_table[256] =
+{
+ 1, 1, 1, 4, 16,
+ 4 /* FIXME - what value should this be?! */
+};
+
+
+static char *romfile;
+static char sramfile[500];
+static char rtcfile[500];
+static char saveprefix[500];
+
+static char *savename;
+static char *savedir = "/.rockbox/rockboy";
+
+static int saveslot;
+
+static int forcebatt, nobatt;
+static int forcedmg;
+
+static int memfill = -1, memrand = -1;
+
+//static byte romMemory[4*1025*1024];
+int mp3_buffer_size;
+void *bufferpos;
+
+static void initmem(void *mem, int size)
+{
+ char *p = mem;
+ if (memrand >= 0)
+ {
+ srand(memrand ? memrand : -6 ); //time(0));
+ while(size--) *(p++) = rand();
+ }
+ else if (memfill >= 0)
+ memset(p, memfill, size);
+}
+
+static byte *loadfile(int fd, int *len)
+{
+ int c, l = 0, p = 0;
+
+ byte *d, buf[512];
+ d=malloc(32768);
+ for(;;)
+ {
+ c = read(fd, buf, sizeof buf);
+ if (c <= 0) break;
+ l += c;
+ memcpy(d+p, buf, c);
+ p += c;
+ }
+ setmallocpos(d+p+64);
+ *len = l;
+ return d;
+}
+
+//static byte sram[65536];
+
+int rom_load(void)
+{
+ int fd;
+ byte c, *data, *header;
+ int len = 0, rlen;
+
+ fd = open(romfile, O_RDONLY);
+
+ if (fd<0) {
+ die("cannot open rom file");
+ die(romfile);
+ return 1;
+ }
+
+ data = loadfile(fd, &len);
+ header = data; // no zip. = decompress(data, &len);
+
+ memcpy(rom.name, header+0x0134, 16);
+ if (rom.name[14] & 0x80) rom.name[14] = 0;
+ if (rom.name[15] & 0x80) rom.name[15] = 0;
+ rom.name[16] = 0;
+
+ c = header[0x0147];
+ mbc.type = mbc_table[c];
+ mbc.batt = (batt_table[c] && !nobatt) || forcebatt;
+// mbc.batt = 1; // always store savegame mem.
+ rtc.batt = rtc_table[c];
+ mbc.romsize = romsize_table[header[0x0148]];
+ mbc.ramsize = ramsize_table[header[0x0149]];
+
+ if (!mbc.romsize) {
+ die("unknown ROM size %02X\n", header[0x0148]);
+ return 1;
+ }
+ if (!mbc.ramsize) {
+ die("unknown SRAM size %02X\n", header[0x0149]);
+ return 1;
+ }
+
+ rlen = 16384 * mbc.romsize;
+ rom.bank = (void *) data; //realloc(data, rlen);
+ if (rlen > len) memset(rom.bank[0]+len, 0xff, rlen - len);
+
+ ram.sbank = malloc(8192 * mbc.ramsize);
+ //ram.ibank = malloc(4096*8);
+
+ initmem(ram.sbank, 8192 * mbc.ramsize);
+ initmem(ram.ibank, 4096 * 8);
+
+ mbc.rombank = 1;
+ mbc.rambank = 0;
+
+ c = header[0x0143];
+ hw.cgb = ((c == 0x80) || (c == 0xc0)) && !forcedmg;
+ hw.gba = 0; //(hw.cgb && gbamode);
+
+ close(fd);
+
+ return 0;
+}
+
+int sram_load(void)
+{
+ int fd;
+ char meow[500];
+
+ if (!mbc.batt || !sramfile || !*sramfile) return -1;
+
+ /* Consider sram loaded at this point, even if file doesn't exist */
+ ram.loaded = 1;
+
+ fd = open(sramfile, O_RDONLY);
+ snprintf(meow,499,"Opening %s %d",sramfile,fd);
+ rb->splash(HZ*2, true, meow);
+ if (fd<0) return -1;
+ snprintf(meow,499,"Loading savedata from %s",sramfile);
+ rb->splash(HZ*2, true, meow);
+ read(fd,ram.sbank, 8192*mbc.ramsize);
+ close(fd);
+
+ return 0;
+}
+
+
+int sram_save(void)
+{
+ int fd;
+ char meow[500];
+
+ /* If we crash before we ever loaded sram, DO NOT SAVE! */
+ if (!mbc.batt || !sramfile || !ram.loaded || !mbc.ramsize)
+ return -1;
+ fd = open(sramfile, O_WRONLY|O_CREAT);
+// snprintf(meow,499,"Opening %s %d",sramfile,fd);
+// rb->splash(HZ*2, true, meow);
+ if (fd<0) return -1;
+ snprintf(meow,499,"Saving savedata to %s",sramfile);
+ rb->splash(HZ*2, true, meow);
+ write(fd,ram.sbank, 8192*mbc.ramsize);
+ close(fd);
+
+ return 0;
+}
+
+
+void state_save(int n)
+{
+ int fd;
+ char name[500];
+
+ if (n < 0) n = saveslot;
+ if (n < 0) n = 0;
+ snprintf(name, 499,"%s.%03d", saveprefix, n);
+
+ if ((fd = open(name, O_WRONLY|O_CREAT)>=0))
+ {
+ savestate(fd);
+ close(fd);
+ }
+}
+
+
+void state_load(int n)
+{
+ int fd;
+ char name[500];
+
+ if (n < 0) n = saveslot;
+ if (n < 0) n = 0;
+ snprintf(name, 499, "%s.%03d", saveprefix, n);
+
+ if ((fd = open(name, O_RDONLY)>=0))
+ {
+ loadstate(fd);
+ close(fd);
+ vram_dirty();
+ pal_dirty();
+ sound_dirty();
+ mem_updatemap();
+ }
+}
+
+void rtc_save(void)
+{
+ int fd;
+ if (!rtc.batt) return;
+ if ((fd = open(rtcfile, O_WRONLY|O_CREAT))<0) return;
+ rtc_save_internal(fd);
+ close(fd);
+}
+
+void rtc_load(void)
+{
+ int fd;
+ if (!rtc.batt) return;
+ if ((fd = open(rtcfile, O_RDONLY))<0) return;
+ rtc_load_internal(fd);
+ close(fd);
+}
+
+
+void loader_unload(void)
+{
+ sram_save();
+// if (romfile) free(romfile);
+// if (sramfile) free(sramfile);
+// if (saveprefix) free(saveprefix);
+// if (rom.bank) free(rom.bank);
+// if (ram.sbank) free(ram.sbank);
+ romfile = 0;
+ rom.bank = 0;
+ ram.sbank = 0;
+ mbc.type = mbc.romsize = mbc.ramsize = mbc.batt = 0;
+}
+
+/*
+static char *base(char *s)
+{
+ char *p;
+ p = strrchr(s, '/');
+ if (p) return p+1;
+ return s;
+}
+
+
+static char *ldup(char *s)
+{
+ int i;
+ char *n, *p;
+ p = n = malloc(strlen(s));
+ for (i = 0; s[i]; i++) if (isalnum(s[i])) *(p++) = tolower(s[i]);
+ *p = 0;
+ return n;
+}*/
+
+void cleanup(void)
+{
+ sram_save();
+ rtc_save();
+ // IDEA - if error, write emergency savestate..?
+}
+
+void loader_init(char *s)
+{
+ char *name;
+ DIR* dir;
+
+// sys_checkdir(savedir, 1); /* needs to be writable */
+ dir=opendir(savedir);
+ if(!dir)
+ mkdir(savedir,0);
+ else
+ closedir(dir);
+
+ romfile = s;
+ if(rom_load())
+ return;
+ vid_settitle(rom.name);
+ name = rom.name;
+
+ snprintf(saveprefix, 499, "%s/%s", savedir, name);
+
+ strcpy(sramfile, saveprefix);
+ strcat(sramfile, ".sav");
+
+ strcpy(rtcfile, saveprefix);
+ strcat(rtcfile, ".rtc");
+
+ sram_load();
+ rtc_load();
+
+ //atexit(cleanup);
+}
+
+rcvar_t loader_exports[] =
+{
+ RCV_STRING("savedir", &savedir),
+ RCV_STRING("savename", &savename),
+ RCV_INT("saveslot", &saveslot),
+ RCV_BOOL("forcebatt", &forcebatt),
+ RCV_BOOL("nobatt", &nobatt),
+ RCV_BOOL("forcedmg", &forcedmg),
+ RCV_INT("memfill", &memfill),
+ RCV_INT("memrand", &memrand),
+ RCV_END
+};
+
+
+
+
+
+
+
+
+
diff --git a/apps/plugins/rockboy/loader.h b/apps/plugins/rockboy/loader.h
new file mode 100644
index 0000000..45ee5e7
--- /dev/null
+++ b/apps/plugins/rockboy/loader.h
@@ -0,0 +1,28 @@
+
+
+#ifndef __LOADER_H__
+#define __LOADER_H__
+
+
+typedef struct loader_s
+{
+ char *rom;
+ char *base;
+ char *sram;
+ char *state;
+ int ramloaded;
+} loader_t;
+
+
+extern loader_t loader;
+
+
+int rom_load(void);
+int sram_load(void);
+int sram_save(void);
+void loader_init(char *s);
+void cleanup(void);
+
+#endif
+
+
diff --git a/apps/plugins/rockboy/main.c b/apps/plugins/rockboy/main.c
new file mode 100644
index 0000000..ea5d628
--- /dev/null
+++ b/apps/plugins/rockboy/main.c
@@ -0,0 +1,83 @@
+#include <stdio.h>
+#include <string.h>
+
+#include "rockmacros.h"
+#include "input.h"
+#include "rc.h"
+#include "exports.h"
+#include "emu.h"
+#include "loader.h"
+#include "hw.h"
+
+//#include "Version"
+
+
+static char *defaultconfig[] =
+{
+ "bind up +up",
+ "bind down +down",
+ "bind left +left",
+ "bind right +right",
+ "bind joy0 +b",
+ "bind joy1 +a",
+ "bind joy2 +select",
+ "bind joy3 +start",
+ "bind ins savestate",
+ "bind del loadstate",
+ NULL
+};
+
+
+void doevents()
+{
+ event_t ev;
+ int st;
+
+ ev_poll();
+ while (ev_getevent(&ev))
+ {
+ if (ev.type != EV_PRESS && ev.type != EV_RELEASE)
+ continue;
+ st = (ev.type != EV_RELEASE);
+ pad_set(ev.code, st);
+ }
+}
+
+
+
+int gnuboy_main(char *rom)
+{
+ int i;
+
+ // Avoid initializing video if we don't have to
+ // If we have special perms, drop them ASAP!
+ rb->splash(HZ*1, true, "Init exports");
+ init_exports();
+
+ rb->splash(HZ*1, true, "Loading default config");
+ for (i = 0; defaultconfig[i]; i++)
+ rc_command(defaultconfig[i]);
+
+// sprintf(cmd, "source %s", rom);
+// s = strchr(cmd, '.');
+// if (s) *s = 0;
+// strcat(cmd, ".rc");
+// rc_command(cmd);
+
+ // FIXME - make interface modules responsible for atexit()
+ rb->splash(HZ*1, true, "Init video");
+ vid_init();
+ rb->splash(HZ*1, true, "Init sound (nosound)");
+ pcm_init();
+ rb->splash(HZ*1, true, "Loading rom");
+ loader_init(rom);
+ if(shut)
+ return PLUGIN_ERROR;
+ rb->splash(HZ*1, true, "Emu reset");
+ emu_reset();
+ rb->splash(HZ*1, true, "Emu run");
+ emu_run();
+
+ // never reached
+ return PLUGIN_OK;
+}
diff --git a/apps/plugins/rockboy/mem.c b/apps/plugins/rockboy/mem.c
new file mode 100644
index 0000000..2e1e0e7
--- /dev/null
+++ b/apps/plugins/rockboy/mem.c
@@ -0,0 +1,578 @@
+
+
+#include "rockmacros.h"
+
+#include "defs.h"
+#include "hw.h"
+#include "regs.h"
+#include "mem.h"
+#include "rtc.h"
+#include "lcd.h"
+#include "lcdc.h"
+#include "sound.h"
+
+struct mbc mbc;
+struct rom rom;
+struct ram ram;
+
+
+/*
+ * In order to make reads and writes efficient, we keep tables
+ * (indexed by the high nibble of the address) specifying which
+ * regions can be read/written without a function call. For such
+ * ranges, the pointer in the map table points to the base of the
+ * region in host system memory. For ranges that require special
+ * processing, the pointer is NULL.
+ *
+ * mem_updatemap is called whenever bank changes or other operations
+ * make the old maps potentially invalid.
+ */
+
+void mem_updatemap()
+{
+ int n;
+ byte **map;
+
+ map = mbc.rmap;
+ map[0x0] = rom.bank[0];
+ map[0x1] = rom.bank[0];
+ map[0x2] = rom.bank[0];
+ map[0x3] = rom.bank[0];
+ if (mbc.rombank < mbc.romsize)
+ {
+ map[0x4] = rom.bank[mbc.rombank] - 0x4000;
+ map[0x5] = rom.bank[mbc.rombank] - 0x4000;
+ map[0x6] = rom.bank[mbc.rombank] - 0x4000;
+ map[0x7] = rom.bank[mbc.rombank] - 0x4000;
+ }
+ else map[0x4] = map[0x5] = map[0x6] = map[0x7] = NULL;
+ if (0 && (R_STAT & 0x03) == 0x03)
+ {
+ map[0x8] = NULL;
+ map[0x9] = NULL;
+ }
+ else
+ {
+ map[0x8] = lcd.vbank[R_VBK & 1] - 0x8000;
+ map[0x9] = lcd.vbank[R_VBK & 1] - 0x8000;
+ }
+ if (mbc.enableram && !(rtc.sel&8))
+ {
+ map[0xA] = ram.sbank[mbc.rambank] - 0xA000;
+ map[0xB] = ram.sbank[mbc.rambank] - 0xA000;
+ }
+ else map[0xA] = map[0xB] = NULL;
+ map[0xC] = ram.ibank[0] - 0xC000;
+ n = R_SVBK & 0x07;
+ map[0xD] = ram.ibank[n?n:1] - 0xD000;
+ map[0xE] = ram.ibank[0] - 0xE000;
+ map[0xF] = NULL;
+
+ map = mbc.wmap;
+ map[0x0] = map[0x1] = map[0x2] = map[0x3] = NULL;
+ map[0x4] = map[0x5] = map[0x6] = map[0x7] = NULL;
+ map[0x8] = map[0x9] = NULL;
+ if (mbc.enableram && !(rtc.sel&8))
+ {
+ map[0xA] = ram.sbank[mbc.rambank] - 0xA000;
+ map[0xB] = ram.sbank[mbc.rambank] - 0xA000;
+ }
+ else map[0xA] = map[0xB] = NULL;
+ map[0xC] = ram.ibank[0] - 0xC000;
+ n = R_SVBK & 0x07;
+ map[0xD] = ram.ibank[n?n:1] - 0xD000;
+ map[0xE] = ram.ibank[0] - 0xE000;
+ map[0xF] = NULL;
+}
+
+
+/*
+ * ioreg_write handles output to io registers in the FF00-FF7F,FFFF
+ * range. It takes the register number (low byte of the address) and a
+ * byte value to be written.
+ */
+
+void ioreg_write(byte r, byte b)
+{
+ if (!hw.cgb)
+ {
+
+ switch (r)
+ {
+ case RI_VBK:
+ case RI_BCPS:
+ case RI_OCPS:
+ case RI_BCPD:
+ case RI_OCPD:
+ case RI_SVBK:
+ case RI_KEY1:
+ case RI_HDMA1:
+ case RI_HDMA2:
+ case RI_HDMA3:
+ case RI_HDMA4:
+ case RI_HDMA5:
+ return;
+ }
+ }
+ switch(r)
+ {
+ case RI_TIMA:
+ case RI_TMA:
+ case RI_TAC:
+ case RI_SCY:
+ case RI_SCX:
+ case RI_WY:
+ case RI_WX:
+ REG(r) = b;
+ break;
+ case RI_BGP:
+ if (R_BGP == b) break;
+ pal_write_dmg(0, 0, b);
+ pal_write_dmg(8, 1, b);
+ R_BGP = b;
+ break;
+ case RI_OBP0:
+ if (R_OBP0 == b) break;
+ pal_write_dmg(64, 2, b);
+ R_OBP0 = b;
+ break;
+ case RI_OBP1:
+ if (R_OBP1 == b) break;
+ pal_write_dmg(72, 3, b);
+ R_OBP1 = b;
+ break;
+ case RI_IF:
+ case RI_IE:
+ REG(r) = b & 0x1F;
+ break;
+ case RI_P1:
+ REG(r) = b;
+ pad_refresh();
+ break;
+ case RI_SC:
+ /* FIXME - this is a hack for stupid roms that probe serial */
+ if ((b & 0x81) == 0x81)
+ {
+ R_SB = 0xff;
+ hw_interrupt(IF_SERIAL, IF_SERIAL);
+ hw_interrupt(0, IF_SERIAL);
+ }
+ R_SC = b; /* & 0x7f; */
+ break;
+ case RI_DIV:
+ REG(r) = 0;
+ break;
+ case RI_LCDC:
+ lcdc_change(b);
+ break;
+ case RI_STAT:
+ stat_write(b);
+ break;
+ case RI_LYC:
+ REG(r) = b;
+ stat_trigger();
+ break;
+ case RI_VBK:
+ REG(r) = b | 0xFE;
+ mem_updatemap();
+ break;
+ case RI_BCPS:
+ R_BCPS = b & 0xBF;
+ R_BCPD = lcd.pal[b & 0x3F];
+ break;
+ case RI_OCPS:
+ R_OCPS = b & 0xBF;
+ R_OCPD = lcd.pal[64 + (b & 0x3F)];
+ break;
+ case RI_BCPD:
+ R_BCPD = b;
+ pal_write(R_BCPS & 0x3F, b);
+ if (R_BCPS & 0x80) R_BCPS = (R_BCPS+1) & 0xBF;
+ break;
+ case RI_OCPD:
+ R_OCPD = b;
+ pal_write(64 + (R_OCPS & 0x3F), b);
+ if (R_OCPS & 0x80) R_OCPS = (R_OCPS+1) & 0xBF;
+ break;
+ case RI_SVBK:
+ REG(r) = b & 0x07;
+ mem_updatemap();
+ break;
+ case RI_DMA:
+ hw_dma(b);
+ break;
+ case RI_KEY1:
+ REG(r) = (REG(r) & 0x80) | (b & 0x01);
+ break;
+ case RI_HDMA1:
+ REG(r) = b;
+ break;
+ case RI_HDMA2:
+ REG(r) = b & 0xF0;
+ break;
+ case RI_HDMA3:
+ REG(r) = b & 0x1F;
+ break;
+ case RI_HDMA4:
+ REG(r) = b & 0xF0;
+ break;
+ case RI_HDMA5:
+ hw_hdma_cmd(b);
+ break;
+ }
+ switch (r)
+ {
+ case RI_BGP:
+ case RI_OBP0:
+ case RI_OBP1:
+ /* printf("palette reg %02X write %02X at LY=%02X\n", r, b, R_LY); */
+ case RI_HDMA1:
+ case RI_HDMA2:
+ case RI_HDMA3:
+ case RI_HDMA4:
+ case RI_HDMA5:
+ /* printf("HDMA %d: %02X\n", r - RI_HDMA1 + 1, b); */
+ break;
+ }
+ /* printf("reg %02X => %02X (%02X)\n", r, REG(r), b); */
+}
+
+
+byte ioreg_read(byte r)
+{
+ switch(r)
+ {
+ case RI_SC:
+ r = R_SC;
+ R_SC &= 0x7f;
+ return r;
+ case RI_P1:
+ case RI_SB:
+ case RI_DIV:
+ case RI_TIMA:
+ case RI_TMA:
+ case RI_TAC:
+ case RI_LCDC:
+ case RI_STAT:
+ case RI_SCY:
+ case RI_SCX:
+ case RI_LY:
+ case RI_LYC:
+ case RI_BGP:
+ case RI_OBP0:
+ case RI_OBP1:
+ case RI_WY:
+ case RI_WX:
+ case RI_IE:
+ case RI_IF:
+ return REG(r);
+ case RI_VBK:
+ case RI_BCPS:
+ case RI_OCPS:
+ case RI_BCPD:
+ case RI_OCPD:
+ case RI_SVBK:
+ case RI_KEY1:
+ case RI_HDMA1:
+ case RI_HDMA2:
+ case RI_HDMA3:
+ case RI_HDMA4:
+ case RI_HDMA5:
+ if (hw.cgb) return REG(r);
+ default:
+ return 0xff;
+ }
+}
+
+
+
+/*
+ * Memory bank controllers typically intercept write attempts to
+ * 0000-7FFF, using the address and byte written as instructions to
+ * change rom or sram banks, control special hardware, etc.
+ *
+ * mbc_write takes an address (which should be in the proper range)
+ * and a byte value written to the address.
+ */
+
+void mbc_write(int a, byte b)
+{
+ byte ha = (a>>12);
+
+ /* printf("mbc %d: rom bank %02X -[%04X:%02X]-> ", mbc.type, mbc.rombank, a, b); */
+ switch (mbc.type)
+ {
+ case MBC_MBC1:
+ switch (ha & 0xE)
+ {
+ case 0x0:
+ mbc.enableram = ((b & 0x0F) == 0x0A);
+ break;
+ case 0x2:
+ if ((b & 0x1F) == 0) b = 0x01;
+ mbc.rombank = (mbc.rombank & 0x60) | (b & 0x1F);
+ break;
+ case 0x4:
+ if (mbc.model)
+ {
+ mbc.rambank = b & 0x03;
+ break;
+ }
+ mbc.rombank = (mbc.rombank & 0x1F) | ((int)(b&3)<<5);
+ break;
+ case 0x6:
+ mbc.model = b & 0x1;
+ break;
+ }
+ break;
+ case MBC_MBC2: /* is this at all right? */
+ if ((a & 0x0100) == 0x0000)
+ {
+ mbc.enableram = ((b & 0x0F) == 0x0A);
+ break;
+ }
+ if ((a & 0xE100) == 0x2100)
+ {
+ mbc.rombank = b & 0x0F;
+ break;
+ }
+ break;
+ case MBC_MBC3:
+ switch (ha & 0xE)
+ {
+ case 0x0:
+ mbc.enableram = ((b & 0x0F) == 0x0A);
+ break;
+ case 0x2:
+ if ((b & 0x7F) == 0) b = 0x01;
+ mbc.rombank = b & 0x7F;
+ break;
+ case 0x4:
+ rtc.sel = b & 0x0f;
+ mbc.rambank = b & 0x03;
+ break;
+ case 0x6:
+ rtc_latch(b);
+ break;
+ }
+ break;
+ case MBC_RUMBLE:
+ switch (ha & 0xF)
+ {
+ case 0x4:
+ case 0x5:
+ /* FIXME - save high bit as rumble state */
+ /* mask off high bit */
+ b &= 0x7;
+ break;
+ }
+ /* fall thru */
+ case MBC_MBC5:
+ switch (ha & 0xF)
+ {
+ case 0x0:
+ case 0x1:
+ mbc.enableram = ((b & 0x0F) == 0x0A);
+ break;
+ case 0x2:
+ if ((b & 0xFF) == 0) b = 0x01;
+ mbc.rombank = (mbc.rombank & 0x100) | (b & 0xFF);
+ break;
+ case 0x3:
+ mbc.rombank = (mbc.rombank & 0xFF) | ((int)(b&1)<<8);
+ break;
+ case 0x4:
+ case 0x5:
+ mbc.rambank = b & 0x0f;
+ break;
+ }
+ break;
+ case MBC_HUC1: /* FIXME - this is all guesswork -- is it right??? */
+ switch (ha & 0xE)
+ {
+ case 0x0:
+ mbc.enableram = ((b & 0x0F) == 0x0A);
+ break;
+ case 0x2:
+ if ((b & 0x1F) == 0) b = 0x01;
+ mbc.rombank = (mbc.rombank & 0x60) | (b & 0x1F);
+ break;
+ case 0x4:
+ if (mbc.model)
+ {
+ mbc.rambank = b & 0x03;
+ break;
+ }
+ mbc.rombank = (mbc.rombank & 0x1F) | ((int)(b&3)<<5);
+ break;
+ case 0x6:
+ mbc.model = b & 0x1;
+ break;
+ }
+ break;
+ case MBC_HUC3:
+ switch (ha & 0xE)
+ {
+ case 0x0:
+ mbc.enableram = ((b & 0x0F) == 0x0A);
+ break;
+ case 0x2:
+ b &= 0x7F;
+ mbc.rombank = b ? b : 1;
+ break;
+ case 0x4:
+ rtc.sel = b & 0x0f;
+ mbc.rambank = b & 0x03;
+ break;
+ case 0x6:
+ rtc_latch(b);
+ break;
+ }
+ break;
+ }
+ mbc.rombank &= (mbc.romsize - 1);
+ mbc.rambank &= (mbc.ramsize - 1);
+ /* printf("%02X\n", mbc.rombank); */
+ mem_updatemap();
+}
+
+
+/*
+ * mem_write is the basic write function. Although it should only be
+ * called when the write map contains a NULL for the requested address
+ * region, it accepts writes to any address.
+ */
+
+void mem_write(int a, byte b)
+{
+ int n;
+ byte ha = (a>>12) & 0xE;
+
+ /* printf("write to 0x%04X: 0x%02X\n", a, b); */
+ switch (ha)
+ {
+ case 0x0:
+ case 0x2:
+ case 0x4:
+ case 0x6:
+ mbc_write(a, b);
+ break;
+ case 0x8:
+ /* if ((R_STAT & 0x03) == 0x03) break; */
+ vram_write(a & 0x1FFF, b);
+ break;
+ case 0xA:
+ if (!mbc.enableram) break;
+ if (rtc.sel&8)
+ {
+ rtc_write(b);
+ break;
+ }
+ ram.sbank[mbc.rambank][a & 0x1FFF] = b;
+ break;
+ case 0xC:
+ if ((a & 0xF000) == 0xC000)
+ {
+ ram.ibank[0][a & 0x0FFF] = b;
+ break;
+ }
+ n = R_SVBK & 0x07;
+ ram.ibank[n?n:1][a & 0x0FFF] = b;
+ break;
+ case 0xE:
+ if (a < 0xFE00)
+ {
+ mem_write(a & 0xDFFF, b);
+ break;
+ }
+ if ((a & 0xFF00) == 0xFE00)
+ {
+ /* if (R_STAT & 0x02) break; */
+ if (a < 0xFEA0) lcd.oam.mem[a & 0xFF] = b;
+ break;
+ }
+ /* return writehi(a & 0xFF, b); */
+ if (a >= 0xFF10 && a <= 0xFF3F)
+ {
+ sound_write(a & 0xFF, b);
+ break;
+ }
+ if ((a & 0xFF80) == 0xFF80 && a != 0xFFFF)
+ {
+ ram.hi[a & 0xFF] = b;
+ break;
+ }
+ ioreg_write(a & 0xFF, b);
+ }
+}
+
+
+/*
+ * mem_read is the basic read function...not useful for much anymore
+ * with the read map, but it's still necessary for the final messy
+ * region.
+ */
+
+byte mem_read(int a)
+{
+ int n;
+ byte ha = (a>>12) & 0xE;
+
+ /* printf("read %04x\n", a); */
+ switch (ha)
+ {
+ case 0x0:
+ case 0x2:
+ return rom.bank[0][a];
+ case 0x4:
+ case 0x6:
+ return rom.bank[mbc.rombank][a & 0x3FFF];
+ case 0x8:
+ /* if ((R_STAT & 0x03) == 0x03) return 0xFF; */
+ return lcd.vbank[R_VBK&1][a & 0x1FFF];
+ case 0xA:
+ if (!mbc.enableram && mbc.type == MBC_HUC3)
+ return 0x01;
+ if (!mbc.enableram)
+ return 0xFF;
+ if (rtc.sel&8)
+ return rtc.regs[rtc.sel&7];
+ return ram.sbank[mbc.rambank][a & 0x1FFF];
+ case 0xC:
+ if ((a & 0xF000) == 0xC000)
+ return ram.ibank[0][a & 0x0FFF];
+ n = R_SVBK & 0x07;
+ return ram.ibank[n?n:1][a & 0x0FFF];
+ case 0xE:
+ if (a < 0xFE00) return mem_read(a & 0xDFFF);
+ if ((a & 0xFF00) == 0xFE00)
+ {
+ /* if (R_STAT & 0x02) return 0xFF; */
+ if (a < 0xFEA0) return lcd.oam.mem[a & 0xFF];
+ return 0xFF;
+ }
+ /* return readhi(a & 0xFF); */
+ if (a == 0xFFFF) return REG(0xFF);
+ if (a >= 0xFF10 && a <= 0xFF3F)
+ return sound_read(a & 0xFF);
+ if ((a & 0xFF80) == 0xFF80)
+ return ram.hi[a & 0xFF];
+ return ioreg_read(a & 0xFF);
+ }
+ return 0xff; /* not reached */
+}
+
+void mbc_reset(void)
+{
+ mbc.rombank = 1;
+ mbc.rambank = 0;
+ mbc.enableram = 0;
+ mem_updatemap();
+}
+
+
+
+
+
+
+
diff --git a/apps/plugins/rockboy/mem.h b/apps/plugins/rockboy/mem.h
new file mode 100644
index 0000000..7926e2e
--- /dev/null
+++ b/apps/plugins/rockboy/mem.h
@@ -0,0 +1,80 @@
+
+#ifndef __MEM_H__
+#define __MEM_H__
+
+
+#include "defs.h"
+
+
+
+#define MBC_NONE 0
+#define MBC_MBC1 1
+#define MBC_MBC2 2
+#define MBC_MBC3 3
+#define MBC_MBC5 5
+#define MBC_RUMBLE 15
+#define MBC_HUC1 0xC1
+#define MBC_HUC3 0xC3
+
+struct mbc
+{
+ int type;
+ int model;
+ int rombank;
+ int rambank;
+ int romsize;
+ int ramsize;
+ int enableram;
+ int batt;
+ byte *rmap[0x10], *wmap[0x10];
+};
+
+struct rom
+{
+ byte (*bank)[16384];
+ char name[20];
+};
+
+struct ram
+{
+ byte hi[256];
+ byte ibank[8][4096];
+ byte (*sbank)[8192];
+ int loaded;
+};
+
+
+extern struct mbc mbc;
+extern struct rom rom;
+extern struct ram ram;
+
+
+
+
+
+void mem_updatemap(void);
+void ioreg_write(byte r, byte b);
+void mbc_write(int a, byte b);
+void mem_write(int a, byte b);
+byte mem_read(int a);
+void mbc_reset(void);
+
+
+
+#define READB(a) ( mbc.rmap[(a)>>12] \
+? mbc.rmap[(a)>>12][(a)] \
+: mem_read((a)) )
+#define READW(a) ( READB((a)) | ((word)READB((a)+1)<<8) )
+
+#define WRITEB(a, b) ( mbc.wmap[(a)>>12] \
+? ( mbc.wmap[(a)>>12][(a)] = (b) ) \
+: ( mem_write((a), (b)), (b) ) )
+#define WRITEW(a, w) ( WRITEB((a), (w)&0xFF), WRITEB((a)+1, (w)>>8) )
+
+
+
+
+#endif
+
+
+
diff --git a/apps/plugins/rockboy/noise.h b/apps/plugins/rockboy/noise.h
new file mode 100644
index 0000000..037499e
--- /dev/null
+++ b/apps/plugins/rockboy/noise.h
@@ -0,0 +1,532 @@
+
+#ifndef __NOISE_H__
+#define __NOISE_H__
+
+
+#include "defs.h"
+
+static byte noise7[] =
+{
+ 0xfd,0xf3,0xd7,0x0d,0xd3,0x15,0x82,0xf1,
+ 0xdb,0x25,0x21,0x39,0x68,0x8c,0xd5,0x00,
+};
+
+static byte noise15[] =
+{
+ 0xff,0xfd,0xff,0xf3,0xff,0xd7,0xff,0x0f,
+ 0xfd,0xdf,0xf3,0x3f,0xd5,0x7f,0x00,0xfd,
+ 0xfd,0xf3,0xf3,0xd7,0xd7,0x0f,0x0d,0xdd,
+ 0xd3,0x33,0x15,0x55,0x80,0x02,0xff,0xf1,
+ 0xff,0xdb,0xff,0x27,0xfd,0x2f,0xf1,0x1f,
+ 0xd9,0xbf,0x2a,0x7d,0x02,0xf1,0xf1,0xdb,
+ 0xdb,0x27,0x25,0x2d,0x21,0x11,0x39,0x99,
+ 0x6a,0xa8,0x80,0x0c,0xff,0xd5,0xff,0x03,
+ 0xfd,0xf7,0xf3,0xcf,0xd7,0x5f,0x0c,0x3d,
+ 0xd7,0x73,0x0c,0xd5,0xd5,0x03,0x01,0xf5,
+ 0xfb,0xc3,0xe7,0x77,0xac,0xce,0x15,0x5b,
+ 0x80,0x26,0xff,0x29,0xfd,0x0b,0xf1,0xc7,
+ 0xdb,0x6f,0x24,0x9d,0x24,0xb1,0x24,0x59,
+ 0x26,0x29,0x2b,0x09,0x05,0xc9,0xe3,0x4b,
+ 0xb4,0x46,0x46,0x6a,0x6a,0x82,0x80,0xf0,
+ 0xfd,0xdd,0xf3,0x33,0xd5,0x57,0x00,0x0d,
+ 0xff,0xd3,0xff,0x17,0xfd,0x8f,0xf2,0xdf,
+ 0xd1,0x3f,0x19,0x7d,0xa8,0xf2,0x0d,0xd3,
+ 0xd3,0x17,0x15,0x8d,0x82,0xd2,0xf1,0x11,
+ 0xd9,0x9b,0x2a,0xa5,0x00,0x21,0xff,0x3b,
+ 0xfd,0x67,0xf0,0xaf,0xdc,0x1f,0x37,0xbd,
+ 0x4e,0x70,0x5a,0xde,0x21,0x3b,0x39,0x65,
+ 0x68,0xa0,0x8c,0x3c,0xd7,0x75,0x0c,0xc1,
+ 0xd5,0x7b,0x00,0xe5,0xfd,0xa3,0xf2,0x37,
+ 0xd3,0x4f,0x14,0x5d,0x86,0x32,0xeb,0x51,
+ 0x84,0x1a,0xe7,0xa1,0xae,0x3a,0x1b,0x63,
+ 0xa4,0xb6,0x24,0x4b,0x26,0x45,0x2a,0x61,
+ 0x02,0xb9,0xf0,0x6b,0xde,0x87,0x38,0xed,
+ 0x6d,0x90,0x92,0x9c,0x90,0xb4,0x9c,0x44,
+ 0xb6,0x64,0x4a,0xa6,0x40,0x2a,0x7f,0x02,
+ 0xfd,0xf1,0xf3,0xdb,0xd7,0x27,0x0d,0x2d,
+ 0xd1,0x13,0x19,0x95,0xaa,0x82,0x00,0xf3,
+ 0xfd,0xd7,0xf3,0x0f,0xd5,0xdf,0x03,0x3d,
+ 0xf5,0x73,0xc0,0xd7,0x7d,0x0c,0xf1,0xd5,
+ 0xdb,0x03,0x25,0xf5,0x23,0xc1,0x37,0x79,
+ 0x4c,0xe8,0x55,0x8e,0x02,0xdb,0xf1,0x27,
+ 0xd9,0x2f,0x29,0x1d,0x09,0xb1,0xca,0x5b,
+ 0x42,0x24,0x73,0x26,0xd5,0x29,0x01,0x09,
+ 0xf9,0xcb,0xeb,0x47,0x84,0x6e,0xe6,0x99,
+ 0xa8,0xaa,0x0c,0x03,0xd7,0xf7,0x0f,0xcd,
+ 0xdf,0x53,0x3c,0x15,0x77,0x80,0xce,0xfd,
+ 0x59,0xf0,0x2b,0xdf,0x07,0x3d,0xed,0x73,
+ 0x90,0xd6,0x9d,0x08,0xb1,0xcc,0x5b,0x56,
+ 0x24,0x0b,0x27,0xc5,0x2f,0x61,0x1c,0xb9,
+ 0xb4,0x6a,0x46,0x82,0x68,0xf2,0x8d,0xd0,
+ 0xd3,0x1d,0x15,0xb1,0x82,0x5a,0xf2,0x21,
+ 0xd3,0x3b,0x15,0x65,0x80,0xa2,0xfc,0x31,
+ 0xf7,0x5b,0xcc,0x27,0x57,0x2c,0x0d,0x17,
+ 0xd1,0x8f,0x1a,0xdd,0xa1,0x32,0x39,0x53,
+ 0x68,0x14,0x8f,0x84,0xde,0xe5,0x39,0xa1,
+ 0x6a,0x38,0x83,0x6c,0xf4,0x95,0xc4,0x83,
+ 0x64,0xf4,0xa5,0xc4,0x23,0x67,0x34,0xad,
+ 0x44,0x10,0x67,0x9e,0xae,0xb8,0x18,0x6f,
+ 0xae,0x9e,0x18,0xbb,0xac,0x66,0x16,0xab,
+ 0x88,0x06,0xcf,0xe9,0x5f,0x88,0x3e,0xcf,
+ 0x79,0x5c,0xe8,0x35,0x8f,0x42,0xdc,0x71,
+ 0x36,0xd9,0x49,0x28,0x49,0x0e,0x49,0xda,
+ 0x4b,0x22,0x45,0x32,0x61,0x52,0xb8,0x10,
+ 0x6f,0x9e,0x9e,0xb8,0xb8,0x6c,0x6e,0x96,
+ 0x98,0x88,0xac,0xcc,0x15,0x57,0x80,0x0e,
+ 0xff,0xd9,0xff,0x2b,0xfd,0x07,0xf1,0xef,
+ 0xdb,0x9f,0x26,0xbd,0x28,0x71,0x0e,0xd9,
+ 0xd9,0x2b,0x29,0x05,0x09,0xe1,0xcb,0xbb,
+ 0x46,0x64,0x6a,0xa6,0x80,0x28,0xff,0x0d,
+ 0xfd,0xd3,0xf3,0x17,0xd5,0x8f,0x02,0xdd,
+ 0xf1,0x33,0xd9,0x57,0x28,0x0d,0x0f,0xd1,
+ 0xdf,0x1b,0x3d,0xa5,0x72,0x20,0xd3,0x3d,
+ 0x15,0x71,0x80,0xda,0xfd,0x21,0xf1,0x3b,
+ 0xd9,0x67,0x28,0xad,0x0c,0x11,0xd7,0x9b,
+ 0x0e,0xa5,0xd8,0x23,0x2f,0x35,0x1d,0x41,
+ 0xb0,0x7a,0x5e,0xe2,0x39,0xb3,0x6a,0x54,
+ 0x82,0x04,0xf3,0xe5,0xd7,0xa3,0x0e,0x35,
+ 0xdb,0x43,0x24,0x75,0x26,0xc1,0x29,0x79,
+ 0x08,0xe9,0xcd,0x8b,0x52,0xc4,0x11,0x67,
+ 0x98,0xae,0xac,0x18,0x17,0xaf,0x8e,0x1e,
+ 0xdb,0xb9,0x26,0x69,0x2a,0x89,0x00,0xc9,
+ 0xfd,0x4b,0xf0,0x47,0xde,0x6f,0x3a,0x9d,
+ 0x60,0xb0,0xbc,0x5c,0x76,0x36,0xcb,0x49,
+ 0x44,0x48,0x66,0x4e,0xaa,0x58,0x02,0x2f,
+ 0xf3,0x1f,0xd5,0xbf,0x02,0x7d,0xf2,0xf3,
+ 0xd1,0xd7,0x1b,0x0d,0xa5,0xd2,0x23,0x13,
+ 0x35,0x95,0x42,0x80,0x70,0xfe,0xdd,0xf9,
+ 0x33,0xe9,0x57,0x88,0x0e,0xcf,0xd9,0x5f,
+ 0x28,0x3d,0x0f,0x71,0xdc,0xdb,0x35,0x25,
+ 0x41,0x20,0x79,0x3e,0xe9,0x79,0x88,0xea,
+ 0xcd,0x81,0x52,0xf8,0x11,0xef,0x9b,0x9e,
+ 0xa6,0xb8,0x28,0x6f,0x0e,0x9d,0xd8,0xb3,
+ 0x2c,0x55,0x16,0x01,0x8b,0xfa,0xc7,0xe1,
+ 0x6f,0xb8,0x9e,0x6c,0xba,0x94,0x60,0x86,
+ 0xbc,0xe8,0x75,0x8e,0xc2,0xd9,0x71,0x28,
+ 0xd9,0x0d,0x29,0xd1,0x0b,0x19,0xc5,0xab,
+ 0x62,0x04,0xb3,0xe4,0x57,0xa6,0x0e,0x2b,
+ 0xdb,0x07,0x25,0xed,0x23,0x91,0x36,0x99,
+ 0x48,0xa8,0x4c,0x0e,0x57,0xda,0x0f,0x23,
+ 0xdd,0x37,0x31,0x4d,0x58,0x50,0x2e,0x1f,
+ 0x1b,0xbd,0xa6,0x72,0x2a,0xd3,0x01,0x15,
+ 0xf9,0x83,0xea,0xf7,0x81,0xce,0xfb,0x59,
+ 0xe4,0x2b,0xa7,0x06,0x2d,0xeb,0x13,0x85,
+ 0x96,0xe2,0x89,0xb0,0xca,0x5d,0x42,0x30,
+ 0x73,0x5e,0xd4,0x39,0x07,0x69,0xec,0x8b,
+ 0x94,0xc6,0x85,0x68,0xe0,0x8d,0xbc,0xd2,
+ 0x75,0x12,0xc1,0x91,0x7a,0x98,0xe0,0xad,
+ 0xbc,0x12,0x77,0x92,0xce,0x91,0x58,0x98,
+ 0x2c,0xaf,0x14,0x1d,0x87,0xb2,0xee,0x51,
+ 0x9a,0x1a,0xa3,0xa0,0x36,0x3f,0x4b,0x7c,
+ 0x44,0xf6,0x65,0xca,0xa3,0x40,0x34,0x7f,
+ 0x46,0xfc,0x69,0xf6,0x8b,0xc8,0xc7,0x4d,
+ 0x6c,0x50,0x96,0x1c,0x8b,0xb4,0xc6,0x45,
+ 0x6a,0x60,0x82,0xbc,0xf0,0x75,0xde,0xc3,
+ 0x39,0x75,0x68,0xc0,0x8d,0x7c,0xd0,0xf5,
+ 0x1d,0xc1,0xb3,0x7a,0x54,0xe2,0x05,0xb3,
+ 0xe2,0x57,0xb2,0x0e,0x53,0xda,0x17,0x23,
+ 0x8d,0x36,0xd1,0x49,0x18,0x49,0xae,0x4a,
+ 0x1a,0x43,0xa2,0x76,0x32,0xcb,0x51,0x44,
+ 0x18,0x67,0xae,0xae,0x18,0x1b,0xaf,0xa6,
+ 0x1e,0x2b,0xbb,0x06,0x65,0xea,0xa3,0x80,
+ 0x36,0xff,0x49,0xfc,0x4b,0xf6,0x47,0xca,
+ 0x6f,0x42,0x9c,0x70,0xb6,0xdc,0x49,0x36,
+ 0x49,0x4a,0x48,0x42,0x4e,0x72,0x5a,0xd2,
+ 0x21,0x13,0x39,0x95,0x6a,0x80,0x80,0xfc,
+ 0xfd,0xf5,0xf3,0xc3,0xd7,0x77,0x0c,0xcd,
+ 0xd5,0x53,0x00,0x15,0xff,0x83,0xfe,0xf7,
+ 0xf9,0xcf,0xeb,0x5f,0x84,0x3e,0xe7,0x79,
+ 0xac,0xea,0x15,0x83,0x82,0xf6,0xf1,0xc9,
+ 0xdb,0x4b,0x24,0x45,0x26,0x61,0x2a,0xb9,
+ 0x00,0x69,0xfe,0x8b,0xf8,0xc7,0xed,0x6f,
+ 0x90,0x9e,0x9c,0xb8,0xb4,0x6c,0x46,0x96,
+ 0x68,0x8a,0x8c,0xc0,0xd5,0x7d,0x00,0xf1,
+ 0xfd,0xdb,0xf3,0x27,0xd5,0x2f,0x01,0x1d,
+ 0xf9,0xb3,0xea,0x57,0x82,0x0e,0xf3,0xd9,
+ 0xd7,0x2b,0x0d,0x05,0xd1,0xe3,0x1b,0xb5,
+ 0xa6,0x42,0x2a,0x73,0x02,0xd5,0xf1,0x03,
+ 0xd9,0xf7,0x2b,0xcd,0x07,0x51,0xec,0x1b,
+ 0x97,0xa6,0x8e,0x28,0xdb,0x0d,0x25,0xd1,
+ 0x23,0x19,0x35,0xa9,0x42,0x08,0x73,0xce,
+ 0xd7,0x59,0x0c,0x29,0xd7,0x0b,0x0d,0xc5,
+ 0xd3,0x63,0x14,0xb5,0x84,0x42,0xe6,0x71,
+ 0xaa,0xda,0x01,0x23,0xf9,0x37,0xe9,0x4f,
+ 0x88,0x5e,0xce,0x39,0x5b,0x68,0x24,0x8f,
+ 0x24,0xdd,0x25,0x31,0x21,0x59,0x38,0x29,
+ 0x6f,0x08,0x9d,0xcc,0xb3,0x54,0x54,0x06,
+ 0x07,0xeb,0xef,0x87,0x9e,0xee,0xb9,0x98,
+ 0x6a,0xae,0x80,0x18,0xff,0xad,0xfe,0x13,
+ 0xfb,0x97,0xe6,0x8f,0xa8,0xde,0x0d,0x3b,
+ 0xd1,0x67,0x18,0xad,0xac,0x12,0x17,0x93,
+ 0x8e,0x96,0xd8,0x89,0x2c,0xc9,0x15,0x49,
+ 0x80,0x4a,0xfe,0x41,0xfa,0x7b,0xe2,0xe7,
+ 0xb1,0xae,0x5a,0x1a,0x23,0xa3,0x36,0x35,
+ 0x4b,0x40,0x44,0x7e,0x66,0xfa,0xa9,0xe0,
+ 0x0b,0xbf,0xc6,0x7f,0x6a,0xfc,0x81,0xf4,
+ 0xfb,0xc5,0xe7,0x63,0xac,0xb6,0x14,0x4b,
+ 0x86,0x46,0xea,0x69,0x82,0x8a,0xf0,0xc1,
+ 0xdd,0x7b,0x30,0xe5,0x5d,0xa0,0x32,0x3f,
+ 0x53,0x7c,0x14,0xf7,0x85,0xce,0xe3,0x59,
+ 0xb4,0x2a,0x47,0x02,0x6d,0xf2,0x93,0xd0,
+ 0x97,0x1c,0x8d,0xb4,0xd2,0x45,0x12,0x61,
+ 0x92,0xba,0x90,0x60,0x9e,0xbc,0xb8,0x74,
+ 0x6e,0xc6,0x99,0x68,0xa8,0x8c,0x0c,0xd7,
+ 0xd5,0x0f,0x01,0xdd,0xfb,0x33,0xe5,0x57,
+ 0xa0,0x0e,0x3f,0xdb,0x7f,0x24,0xfd,0x25,
+ 0xf1,0x23,0xd9,0x37,0x29,0x4d,0x08,0x51,
+ 0xce,0x1b,0x5b,0xa4,0x26,0x27,0x2b,0x2d,
+ 0x05,0x11,0xe1,0x9b,0xba,0xa6,0x60,0x2a,
+ 0xbf,0x00,0x7d,0xfe,0xf3,0xf9,0xd7,0xeb,
+ 0x0f,0x85,0xde,0xe3,0x39,0xb5,0x6a,0x40,
+ 0x82,0x7c,0xf2,0xf5,0xd1,0xc3,0x1b,0x75,
+ 0xa4,0xc2,0x25,0x73,0x20,0xd5,0x3d,0x01,
+ 0x71,0xf8,0xdb,0xed,0x27,0x91,0x2e,0x99,
+ 0x18,0xa9,0xac,0x0a,0x17,0xc3,0x8f,0x76,
+ 0xdc,0xc9,0x35,0x49,0x40,0x48,0x7e,0x4e,
+ 0xfa,0x59,0xe2,0x2b,0xb3,0x06,0x55,0xe2,
+ 0x03,0x83,0xf6,0xf7,0xc9,0xcf,0x4b,0x5c,
+ 0x04,0x3e,0x67,0x4e,0xac,0x60,0x17,0x7f,
+ 0x80,0xfe,0xc1,0xf9,0x7b,0xe8,0xe7,0x87,
+ 0xae,0xc2,0x19,0x93,0xfc,0x96,0x08,0x8f,
+ 0xc0,0xe7,0xfc,0x2c,0xf0,0x1d,0xcc,0xc3,
+ 0x9e,0x70,0x00,0xc0,0x63,0x7f,0x54,0x78,
+ 0x40,0xfe,0x61,0x9b,0xf3,0x40,0x64,0x3f,
+ 0x0f,0xf8,0x2c,0xf3,0x3f,0x99,0x83,0x2a,
+ 0x79,0x07,0xcb,0xe1,0x9f,0xcc,0xce,0x60,
+ 0x6c,0x00,0x84,0x7c,0x0f,0xf5,0xe8,0xcf,
+ 0x15,0x66,0x80,0xb0,0xf8,0x5d,0xf4,0x33,
+ 0x8a,0x57,0x44,0x0c,0x67,0xd6,0xaf,0x08,
+ 0x1f,0xcf,0xb3,0x5e,0x54,0x3a,0x07,0x63,
+ 0xec,0xb7,0x94,0x4e,0x86,0x58,0xea,0x2d,
+ 0x83,0x12,0xf5,0x91,0xc2,0x9b,0x70,0xa4,
+ 0xdc,0x25,0x37,0x21,0x4d,0x38,0x51,0x6e,
+ 0x18,0x9b,0xac,0xa6,0x14,0x2b,0x87,0x06,
+ 0xed,0xe9,0x93,0x8a,0x96,0xc0,0x89,0x7c,
+ 0xc8,0xf5,0x4d,0xc0,0x53,0x7e,0x14,0xfb,
+ 0x85,0xe6,0xe3,0xa9,0xb6,0x0a,0x4b,0xc2,
+ 0x47,0x72,0x6c,0xd2,0x95,0x10,0x81,0x9c,
+ 0xfa,0xb5,0xe0,0x43,0xbe,0x76,0x7a,0xca,
+ 0xe1,0x41,0xb8,0x7a,0x6e,0xe2,0x99,0xb0,
+ 0xaa,0x5c,0x02,0x37,0xf3,0x4f,0xd4,0x5f,
+ 0x06,0x3d,0xeb,0x73,0x84,0xd6,0xe5,0x09,
+ 0xa1,0xca,0x3b,0x43,0x64,0x74,0xa6,0xc4,
+ 0x29,0x67,0x08,0xad,0xcc,0x13,0x57,0x94,
+ 0x0e,0x87,0xd8,0xef,0x2d,0x9d,0x12,0xb1,
+ 0x90,0x5a,0x9e,0x20,0xbb,0x3c,0x65,0x76,
+ 0xa0,0xc8,0x3d,0x4f,0x70,0x5c,0xde,0x35,
+ 0x3b,0x41,0x64,0x78,0xa6,0xec,0x29,0x97,
+ 0x0a,0x8d,0xc0,0xd3,0x7d,0x14,0xf1,0x85,
+ 0xda,0xe3,0x21,0xb5,0x3a,0x41,0x62,0x78,
+ 0xb2,0xec,0x51,0x96,0x1a,0x8b,0xa0,0xc6,
+ 0x3d,0x6b,0x70,0x84,0xdc,0xe5,0x35,0xa1,
+ 0x42,0x38,0x73,0x6e,0xd4,0x99,0x04,0xa9,
+ 0xe4,0x0b,0xa7,0xc6,0x2f,0x6b,0x1c,0x85,
+ 0xb4,0xe2,0x45,0xb2,0x62,0x52,0xb2,0x10,
+ 0x53,0x9e,0x16,0xbb,0x88,0x66,0xce,0xa9,
+ 0x58,0x08,0x2f,0xcf,0x1f,0x5d,0xbc,0x32,
+ 0x77,0x52,0xcc,0x11,0x57,0x98,0x0e,0xaf,
+ 0xd8,0x1f,0x2f,0xbd,0x1e,0x71,0xba,0xda,
+ 0x61,0x22,0xb9,0x30,0x69,0x5e,0x88,0x38,
+ 0xcf,0x6d,0x5c,0x90,0x34,0x9f,0x44,0xbc,
+ 0x64,0x76,0xa6,0xc8,0x29,0x4f,0x08,0x5d,
+ 0xce,0x33,0x5b,0x54,0x24,0x07,0x27,0xed,
+ 0x2f,0x91,0x1e,0x99,0xb8,0xaa,0x6c,0x02,
+ 0x97,0xf0,0x8f,0xdc,0xdf,0x35,0x3d,0x41,
+ 0x70,0x78,0xde,0xed,0x39,0x91,0x6a,0x98,
+ 0x80,0xac,0xfc,0x15,0xf7,0x83,0xce,0xf7,
+ 0x59,0xcc,0x2b,0x57,0x04,0x0d,0xe7,0xd3,
+ 0xaf,0x16,0x1d,0x8b,0xb2,0xc6,0x51,0x6a,
+ 0x18,0x83,0xac,0xf6,0x15,0xcb,0x83,0x46,
+ 0xf4,0x69,0xc6,0x8b,0x68,0xc4,0x8d,0x64,
+ 0xd0,0xa5,0x1c,0x21,0xb7,0x3a,0x4d,0x62,
+ 0x50,0xb2,0x1c,0x53,0xb6,0x16,0x4b,0x8a,
+ 0x46,0xc2,0x69,0x72,0x88,0xd0,0xcd,0x1d,
+ 0x51,0xb0,0x1a,0x5f,0xa2,0x3e,0x33,0x7b,
+ 0x54,0xe4,0x05,0xa7,0xe2,0x2f,0xb3,0x1e,
+ 0x55,0xba,0x02,0x63,0xf2,0xb7,0xd0,0x4f,
+ 0x1e,0x5d,0xba,0x32,0x63,0x52,0xb4,0x10,
+ 0x47,0x9e,0x6e,0xba,0x98,0x60,0xae,0xbc,
+ 0x18,0x77,0xae,0xce,0x19,0x5b,0xa8,0x26,
+ 0x0f,0x2b,0xdd,0x07,0x31,0xed,0x5b,0x90,
+ 0x26,0x9f,0x28,0xbd,0x0c,0x71,0xd6,0xdb,
+ 0x09,0x25,0xc9,0x23,0x49,0x34,0x49,0x46,
+ 0x48,0x6a,0x4e,0x82,0x58,0xf2,0x2d,0xd3,
+ 0x13,0x15,0x95,0x82,0x82,0xf0,0xf1,0xdd,
+ 0xdb,0x33,0x25,0x55,0x20,0x01,0x3f,0xf9,
+ 0x7f,0xe8,0xff,0x8d,0xfe,0xd3,0xf9,0x17,
+ 0xe9,0x8f,0x8a,0xde,0xc1,0x39,0x79,0x68,
+ 0xe8,0x8d,0x8c,0xd2,0xd5,0x11,0x01,0x99,
+ 0xfa,0xab,0xe0,0x07,0xbf,0xee,0x7f,0x9a,
+ 0xfe,0xa1,0xf8,0x3b,0xef,0x67,0x9c,0xae,
+ 0xb4,0x18,0x47,0xae,0x6e,0x1a,0x9b,0xa0,
+ 0xa6,0x3c,0x2b,0x77,0x04,0xcd,0xe5,0x53,
+ 0xa0,0x16,0x3f,0x8b,0x7e,0xc4,0xf9,0x65,
+ 0xe8,0xa3,0x8c,0x36,0xd7,0x49,0x0c,0x49,
+ 0xd6,0x4b,0x0a,0x45,0xc2,0x63,0x72,0xb4,
+ 0xd0,0x45,0x1e,0x61,0xba,0xba,0x60,0x62,
+ 0xbe,0xb0,0x78,0x5e,0xee,0x39,0x9b,0x6a,
+ 0xa4,0x80,0x24,0xff,0x25,0xfd,0x23,0xf1,
+ 0x37,0xd9,0x4f,0x28,0x5d,0x0e,0x31,0xdb,
+ 0x5b,0x24,0x25,0x27,0x21,0x2d,0x39,0x11,
+ 0x69,0x98,0x8a,0xac,0xc0,0x15,0x7f,0x80,
+ 0xfe,0xfd,0xf9,0xf3,0xeb,0xd7,0x87,0x0e,
+ 0xed,0xd9,0x93,0x2a,0x95,0x00,0x81,0xfc,
+ 0xfb,0xf5,0xe7,0xc3,0xaf,0x76,0x1c,0xcb,
+ 0xb5,0x46,0x40,0x6a,0x7e,0x82,0xf8,0xf1,
+ 0xed,0xdb,0x93,0x26,0x95,0x28,0x81,0x0c,
+ 0xf9,0xd5,0xeb,0x03,0x85,0xf6,0xe3,0xc9,
+ 0xb7,0x4a,0x4c,0x42,0x56,0x72,0x0a,0xd3,
+ 0xc1,0x17,0x79,0x8c,0xea,0xd5,0x81,0x02,
+ 0xf9,0xf1,0xeb,0xdb,0x87,0x26,0xed,0x29,
+ 0x91,0x0a,0x99,0xc0,0xab,0x7c,0x04,0xf7,
+ 0xe5,0xcf,0xa3,0x5e,0x34,0x3b,0x47,0x64,
+ 0x6c,0xa6,0x94,0x28,0x87,0x0c,0xed,0xd5,
+ 0x93,0x02,0x95,0xf0,0x83,0xdc,0xf7,0x35,
+ 0xcd,0x43,0x50,0x74,0x1e,0xc7,0xb9,0x6e,
+ 0x68,0x9a,0x8c,0xa0,0xd4,0x3d,0x07,0x71,
+ 0xec,0xdb,0x95,0x26,0x81,0x28,0xf9,0x0d,
+ 0xe9,0xd3,0x8b,0x16,0xc5,0x89,0x62,0xc8,
+ 0xb1,0x4c,0x58,0x56,0x2e,0x0b,0x1b,0xc5,
+ 0xa7,0x62,0x2c,0xb3,0x14,0x55,0x86,0x02,
+ 0xeb,0xf1,0x87,0xda,0xef,0x21,0x9d,0x3a,
+ 0xb1,0x60,0x58,0xbe,0x2c,0x7b,0x16,0xe5,
+ 0x89,0xa2,0xca,0x31,0x43,0x58,0x74,0x2e,
+ 0xc7,0x19,0x6d,0xa8,0x92,0x0c,0x93,0xd4,
+ 0x97,0x04,0x8d,0xe4,0xd3,0xa5,0x16,0x21,
+ 0x8b,0x3a,0xc5,0x61,0x60,0xb8,0xbc,0x6c,
+ 0x76,0x96,0xc8,0x89,0x4c,0xc8,0x55,0x4e,
+ 0x00,0x5b,0xfe,0x27,0xfb,0x2f,0xe5,0x1f,
+ 0xa1,0xbe,0x3a,0x7b,0x62,0xe4,0xb1,0xa4,
+ 0x5a,0x26,0x23,0x2b,0x35,0x05,0x41,0xe0,
+ 0x7b,0xbe,0xe6,0x79,0xaa,0xea,0x01,0x83,
+ 0xfa,0xf7,0xe1,0xcf,0xbb,0x5e,0x64,0x3a,
+ 0xa7,0x60,0x2c,0xbf,0x14,0x7d,0x86,0xf2,
+ 0xe9,0xd1,0x8b,0x1a,0xc5,0xa1,0x62,0x38,
+ 0xb3,0x6c,0x54,0x96,0x04,0x8b,0xe4,0xc7,
+ 0xa5,0x6e,0x20,0x9b,0x3c,0xa5,0x74,0x20,
+ 0xc7,0x3d,0x6d,0x70,0x90,0xdc,0x9d,0x34,
+ 0xb1,0x44,0x58,0x66,0x2e,0xab,0x18,0x05,
+ 0xaf,0xe2,0x1f,0xb3,0xbe,0x56,0x7a,0x0a,
+ 0xe3,0xc1,0xb7,0x7a,0x4c,0xe2,0x55,0xb2,
+ 0x02,0x53,0xf2,0x17,0xd3,0x8f,0x16,0xdd,
+ 0x89,0x32,0xc9,0x51,0x48,0x18,0x4f,0xae,
+ 0x5e,0x1a,0x3b,0xa3,0x66,0x34,0xab,0x44,
+ 0x04,0x67,0xe6,0xaf,0xa8,0x1e,0x0f,0xbb,
+ 0xde,0x67,0x3a,0xad,0x60,0x10,0xbf,0x9c,
+ 0x7e,0xb6,0xf8,0x49,0xee,0x4b,0x9a,0x46,
+ 0xa2,0x68,0x32,0x8f,0x50,0xdc,0x1d,0x37,
+ 0xb1,0x4e,0x58,0x5a,0x2e,0x23,0x1b,0x35,
+ 0xa5,0x42,0x20,0x73,0x3e,0xd5,0x79,0x00,
+ 0xe9,0xfd,0x8b,0xf2,0xc7,0xd1,0x6f,0x18,
+ 0x9d,0xac,0xb2,0x14,0x53,0x86,0x16,0xeb,
+ 0x89,0x86,0xca,0xe9,0x41,0x88,0x7a,0xce,
+ 0xe1,0x59,0xb8,0x2a,0x6f,0x02,0x9d,0xf0,
+ 0xb3,0xdc,0x57,0x36,0x0d,0x4b,0xd0,0x47,
+ 0x1e,0x6d,0xba,0x92,0x60,0x92,0xbc,0x90,
+ 0x74,0x9e,0xc4,0xb9,0x64,0x68,0xa6,0x8c,
+ 0x28,0xd7,0x0d,0x0d,0xd1,0xd3,0x1b,0x15,
+ 0xa5,0x82,0x22,0xf3,0x31,0xd5,0x5b,0x00,
+ 0x25,0xff,0x23,0xfd,0x37,0xf1,0x4f,0xd8,
+ 0x5f,0x2e,0x3d,0x1b,0x71,0xa4,0xda,0x25,
+ 0x23,0x21,0x35,0x39,0x41,0x68,0x78,0x8e,
+ 0xec,0xd9,0x95,0x2a,0x81,0x00,0xf9,0xfd,
+ 0xeb,0xf3,0x87,0xd6,0xef,0x09,0x9d,0xca,
+ 0xb3,0x40,0x54,0x7e,0x06,0xfb,0xe9,0xe7,
+ 0x8b,0xae,0xc6,0x19,0x6b,0xa8,0x86,0x0c,
+ 0xeb,0xd5,0x87,0x02,0xed,0xf1,0x93,0xda,
+ 0x97,0x20,0x8d,0x3c,0xd1,0x75,0x18,0xc1,
+ 0xad,0x7a,0x10,0xe3,0x9d,0xb6,0xb2,0x48,
+ 0x52,0x4e,0x12,0x5b,0x92,0x26,0x93,0x28,
+ 0x95,0x0c,0x81,0xd4,0xfb,0x05,0xe5,0xe3,
+ 0xa3,0xb6,0x36,0x4b,0x4a,0x44,0x42,0x66,
+ 0x72,0xaa,0xd0,0x01,0x1f,0xf9,0xbf,0xea,
+ 0x7f,0x82,0xfe,0xf1,0xf9,0xdb,0xeb,0x27,
+ 0x85,0x2e,0xe1,0x19,0xb9,0xaa,0x6a,0x02,
+ 0x83,0xf0,0xf7,0xdd,0xcf,0x33,0x5d,0x54,
+ 0x30,0x07,0x5f,0xec,0x3f,0x97,0x7e,0x8c,
+ 0xf8,0xd5,0xed,0x03,0x91,0xf6,0x9b,0xc8,
+ 0xa7,0x4c,0x2c,0x57,0x16,0x0d,0x8b,0xd2,
+ 0xc7,0x11,0x6d,0x98,0x92,0xac,0x90,0x14,
+ 0x9f,0x84,0xbe,0xe4,0x79,0xa6,0xea,0x29,
+ 0x83,0x0a,0xf5,0xc1,0xc3,0x7b,0x74,0xe4,
+ 0xc5,0xa5,0x62,0x20,0xb3,0x3c,0x55,0x76,
+ 0x00,0xcb,0xfd,0x47,0xf0,0x6f,0xde,0x9f,
+ 0x38,0xbd,0x6c,0x70,0x96,0xdc,0x89,0x34,
+ 0xc9,0x45,0x48,0x60,0x4e,0xbe,0x58,0x7a,
+ 0x2e,0xe3,0x19,0xb5,0xaa,0x42,0x02,0x73,
+ 0xf2,0xd7,0xd1,0x0f,0x19,0xdd,0xab,0x32,
+ 0x05,0x53,0xe0,0x17,0xbf,0x8e,0x7e,0xda,
+ 0xf9,0x21,0xe9,0x3b,0x89,0x66,0xc8,0xa9,
+ 0x4c,0x08,0x57,0xce,0x0f,0x5b,0xdc,0x27,
+ 0x37,0x2d,0x4d,0x10,0x51,0x9e,0x1a,0xbb,
+ 0xa0,0x66,0x3e,0xab,0x78,0x04,0xef,0xe5,
+ 0x9f,0xa2,0xbe,0x30,0x7b,0x5e,0xe4,0x39,
+ 0xa7,0x6a,0x2c,0x83,0x14,0xf5,0x85,0xc2,
+ 0xe3,0x71,0xb4,0xda,0x45,0x22,0x61,0x32,
+ 0xb9,0x50,0x68,0x1e,0x8f,0xb8,0xde,0x6d,
+ 0x3a,0x91,0x60,0x98,0xbc,0xac,0x74,0x16,
+ 0xc7,0x89,0x6e,0xc8,0x99,0x4c,0xa8,0x54,
+ 0x0e,0x07,0xdb,0xef,0x27,0x9d,0x2e,0xb1,
+ 0x18,0x59,0xae,0x2a,0x1b,0x03,0xa5,0xf6,
+ 0x23,0xcb,0x37,0x45,0x4c,0x60,0x56,0xbe,
+ 0x08,0x7b,0xce,0xe7,0x59,0xac,0x2a,0x17,
+ 0x03,0x8d,0xf6,0xd3,0xc9,0x17,0x49,0x8c,
+ 0x4a,0xd6,0x41,0x0a,0x79,0xc2,0xeb,0x71,
+ 0x84,0xda,0xe5,0x21,0xa1,0x3a,0x39,0x63,
+ 0x68,0xb4,0x8c,0x44,0xd6,0x65,0x0a,0xa1,
+ 0xc0,0x3b,0x7f,0x64,0xfc,0xa5,0xf4,0x23,
+ 0xc7,0x37,0x6d,0x4c,0x90,0x54,0x9e,0x04,
+ 0xbb,0xe4,0x67,0xa6,0xae,0x28,0x1b,0x0f,
+ 0xa5,0xde,0x23,0x3b,0x35,0x65,0x40,0xa0,
+ 0x7c,0x3e,0xf7,0x79,0xcc,0xeb,0x55,0x84,
+ 0x02,0xe7,0xf1,0xaf,0xda,0x1f,0x23,0xbd,
+ 0x36,0x71,0x4a,0xd8,0x41,0x2e,0x79,0x1a,
+ 0xe9,0xa1,0x8a,0x3a,0xc3,0x61,0x74,0xb8,
+ 0xc4,0x6d,0x66,0x90,0xa8,0x9c,0x0c,0xb7,
+ 0xd4,0x4f,0x06,0x5d,0xea,0x33,0x83,0x56,
+ 0xf4,0x09,0xc7,0xcb,0x6f,0x44,0x9c,0x64,
+ 0xb6,0xa4,0x48,0x26,0x4f,0x2a,0x5d,0x02,
+ 0x31,0xf3,0x5b,0xd4,0x27,0x07,0x2d,0xed,
+ 0x13,0x91,0x96,0x9a,0x88,0xa0,0xcc,0x3d,
+ 0x57,0x70,0x0c,0xdf,0xd5,0x3f,0x01,0x7d,
+ 0xf8,0xf3,0xed,0xd7,0x93,0x0e,0x95,0xd8,
+ 0x83,0x2c,0xf5,0x15,0xc1,0x83,0x7a,0xf4,
+ 0xe1,0xc5,0xbb,0x62,0x64,0xb2,0xa4,0x50,
+ 0x26,0x1f,0x2b,0xbd,0x06,0x71,0xea,0xdb,
+ 0x81,0x26,0xf9,0x29,0xe9,0x0b,0x89,0xc6,
+ 0xcb,0x69,0x44,0x88,0x64,0xce,0xa5,0x58,
+ 0x20,0x2f,0x3f,0x1d,0x7d,0xb0,0xf2,0x5d,
+ 0xd2,0x33,0x13,0x55,0x94,0x02,0x87,0xf0,
+ 0xef,0xdd,0x9f,0x32,0xbd,0x50,0x70,0x1e,
+ 0xdf,0xb9,0x3e,0x69,0x7a,0x88,0xe0,0xcd,
+ 0xbd,0x52,0x70,0x12,0xdf,0x91,0x3e,0x99,
+ 0x78,0xa8,0xec,0x0d,0x97,0xd2,0x8f,0x10,
+ 0xdd,0x9d,0x32,0xb1,0x50,0x58,0x1e,0x2f,
+ 0xbb,0x1e,0x65,0xba,0xa2,0x60,0x32,0xbf,
+ 0x50,0x7c,0x1e,0xf7,0xb9,0xce,0x6b,0x5a,
+ 0x84,0x20,0xe7,0x3d,0xad,0x72,0x10,0xd3,
+ 0x9d,0x16,0xb1,0x88,0x5a,0xce,0x21,0x5b,
+ 0x38,0x25,0x6f,0x20,0x9d,0x3c,0xb1,0x74,
+ 0x58,0xc6,0x2d,0x6b,0x10,0x85,0x9c,0xe2,
+ 0xb5,0xb0,0x42,0x5e,0x72,0x3a,0xd3,0x61,
+ 0x14,0xb9,0x84,0x6a,0xe6,0x81,0xa8,0xfa,
+ 0x0d,0xe3,0xd3,0xb7,0x16,0x4d,0x8a,0x52,
+ 0xc2,0x11,0x73,0x98,0xd6,0xad,0x08,0x11,
+ 0xcf,0x9b,0x5e,0xa4,0x38,0x27,0x6f,0x2c,
+ 0x9d,0x14,0xb1,0x84,0x5a,0xe6,0x21,0xab,
+ 0x3a,0x05,0x63,0xe0,0xb7,0xbc,0x4e,0x76,
+ 0x5a,0xca,0x21,0x43,0x38,0x75,0x6e,0xc0,
+ 0x99,0x7c,0xa8,0xf4,0x0d,0xc7,0xd3,0x6f,
+ 0x14,0x9d,0x84,0xb2,0xe4,0x51,0xa6,0x1a,
+ 0x2b,0xa3,0x06,0x35,0xeb,0x43,0x84,0x76,
+ 0xe6,0xc9,0xa9,0x4a,0x08,0x43,0xce,0x77,
+ 0x5a,0xcc,0x21,0x57,0x38,0x0d,0x6f,0xd0,
+ 0x9f,0x1c,0xbd,0xb4,0x72,0x46,0xd2,0x69,
+ 0x12,0x89,0x90,0xca,0x9d,0x40,0xb0,0x7c,
+ 0x5e,0xf6,0x39,0xcb,0x6b,0x44,0x84,0x64,
+ 0xe6,0xa5,0xa8,0x22,0x0f,0x33,0xdd,0x57,
+ 0x30,0x0d,0x5f,0xd0,0x3f,0x1f,0x7d,0xbc,
+ 0xf2,0x75,0xd2,0xc3,0x11,0x75,0x98,0xc2,
+ 0xad,0x70,0x10,0xdf,0x9d,0x3e,0xb1,0x78,
+ 0x58,0xee,0x2d,0x9b,0x12,0xa5,0x90,0x22,
+ 0x9f,0x30,0xbd,0x5c,0x70,0x36,0xdf,0x49,
+ 0x3c,0x49,0x76,0x48,0xca,0x4d,0x42,0x50,
+ 0x72,0x1e,0xd3,0xb9,0x16,0x69,0x8a,0x8a,
+ 0xc0,0xc1,0x7d,0x78,0xf0,0xed,0xdd,0x93,
+ 0x32,0x95,0x50,0x80,0x1c,0xff,0xb5,0xfe,
+ 0x43,0xfa,0x77,0xe2,0xcf,0xb1,0x5e,0x58,
+ 0x3a,0x2f,0x63,0x1c,0xb5,0xb4,0x42,0x46,
+ 0x72,0x6a,0xd2,0x81,0x10,0xf9,0x9d,0xea,
+ 0xb3,0x80,0x56,0xfe,0x09,0xfb,0xcb,0xe7,
+ 0x47,0xac,0x6e,0x16,0x9b,0x88,0xa6,0xcc,
+ 0x29,0x57,0x08,0x0d,0xcf,0xd3,0x5f,0x14,
+ 0x3d,0x87,0x72,0xec,0xd1,0x95,0x1a,0x81,
+ 0xa0,0xfa,0x3d,0xe3,0x73,0xb4,0xd6,0x45,
+ 0x0a,0x61,0xc2,0xbb,0x70,0x64,0xde,0xa5,
+ 0x38,0x21,0x6f,0x38,0x9d,0x6c,0xb0,0x94,
+ 0x5c,0x86,0x3e,0xeb,0x45,0x84,0x62,0xe6,
+ 0xb1,0xa8,0x5a,0x0e,0x23,0xfb,0x33,0x25,
+ 0x47,0x20,0x51,0x3e,0x19,0x7f,0xa8,0x66,
+ 0x0c,0xfb,0xd0,0x07,0x13,0xe5,0x9f,0x83,
+ 0xce,0x98,0x58,0xcd,0x2e,0x19,0x14,0x39,
+ 0x86,0x3f,0xff,0x01,0x85,0xff,0xe1,0xe1,
+ 0xb3,0xfc,0x46,0x63,0x0f,0xf8,0x00,0x53,
+ 0xbe,0x1f,0xfb,0xc0,0xe6,0x7e,0xbc,0xf0,
+ 0x01,0xe3,0xc3,0x9f,0xa6,0xcc,0x48,0x7e,
+ 0x40,0x82,0x9d,0xf2,0xff,0xd6,0x07,0x13,
+ 0xf5,0x87,0x80,0x0f,0x71,0x9c,0xfd,0x35,
+ 0x61,0x43,0xf8,0x78,0x7e,0xcf,0x19,0x99,
+ 0xa8,0x32,0x00,0x53,0xfc,0x17,0xfb,0x8f,
+ 0xc6,0xdf,0xa9,0x3e,0x09,0x7b,0xc8,0xe7,
+ 0x4d,0xac,0x52,0x16,0x13,0x8b,0x96,0xc6,
+ 0x89,0x68,0xc8,0x8d,0x4c,0xd0,0x55,0x1e,
+ 0x01,0xbb,0xfa,0x67,0xe2,0xaf,0xb0,0x1e,
+ 0x5f,0xba,0x3e,0x63,0x7a,0xb4,0xe0,0x45,
+ 0xbe,0x62,0x7a,0xb2,0xe0,0x51,0xbe,0x1a,
+ 0x7b,0xa2,0xe6,0x31,0xab,0x5a,0x04,0x23,
+ 0xe7,0x37,0xad,0x4e,0x10,0x5b,0x9e,0x26,
+ 0xbb,0x28,0x65,0x0e,0xa1,0xd8,0x3b,0x2f,
+ 0x65,0x1c,0xa1,0xb4,0x3a,0x47,0x62,0x6c,
+ 0xb2,0x94,0x50,0x86,0x1c,0xeb,0xb5,0x86,
+ 0x42,0xea,0x71,0x82,0xda,0xf1,0x21,0xd9,
+ 0x3b,0x29,0x65,0x08,0xa1,0xcc,0x3b,0x57,
+ 0x64,0x0c,0xa7,0xd4,0x2f,0x07,0x1d,0xed,
+ 0xb3,0x92,0x56,0x92,0x08,0x93,0xcc,0x97,
+ 0x54,0x8c,0x04,0xd7,0xe5,0x0f,0xa1,0xde,
+ 0x3b,0x3b,0x65,0x64,0xa0,0xa4,0x3c,0x27,
+ 0x77,0x2c,0xcd,0x15,0x51,0x80,0x1a,0xff,
+ 0xa1,0xfe,0x3b,0xfb,0x67,0xe4,0xaf,0xa4,
+ 0x1e,0x27,0xbb,0x2e,0x65,0x1a,0xa1,0xa0,
+ 0x3a,0x3f,0x63,0x7c,0xb4,0xf4,0x45,0xc6,
+ 0x63,0x6a,0xb4,0x80,0x44,0xfe,0x65,0xfa,
+ 0xa3,0xe0,0x37,0xbf,0x4e,0x7c,0x5a,0xf6,
+ 0x21,0xcb,0x3b,0x45,0x64,0x60,0xa6,0xbc,
+ 0x28,0x77,0x0e,0xcd,0xd9,0x53,0x28,0x15,
+ 0x0f,0x81,0xde,0xfb,0x39,0xe5,0x6b,0xa0,
+ 0x86,0x3c,0xeb,0x75,0x84,0xc2,0xe5,0x71,
+ 0xa0,0xda,0x3d,0x23,0x71,0x34,0xd9,0x45,
+ 0x28,0x61,0x0e,0xb9,0xd8,0x6b,0x2e,0x85,
+ 0x18,0xe1,0xad,0xba,0x12,0x63,0x92,0xb6,
+ 0x90,0x48,0x9e,0x4c,0xba,0x54,0x62,0x06,
+ 0xb3,0xe8,0x57,0x8e,0x0e,0xdb,0xd9,0x27,
+ 0x29,0x2d,0x09,0x11,0xc9,0x9b,0x4a,0xa4,
+ 0x40,0x26,0x7f,0x2a,0xfd,0x01,0xf1,0xfb,
+ 0xdb,0xe7,0x27,0xad,0x2e,0x11,0x1b,0x99,
+ 0xa6,0xaa,0x28,0x03,0x0f,0xf5,0xdf,0xc3,
+ 0x3f,0x75,0x7c,0xc0,0xf5,0x7d,0xc0,0xf3,
+ 0x7d,0xd4,0xf3,0x05,0xd5,0xe3,0x03,0xb5,
+ 0xf6,0x43,0xca,0x77,0x42,0xcc,0x71,0x56,
+ 0xd8,0x09,0x2f,0xc9,0x1f,0x49,0xbc,0x4a,
+ 0x76,0x42,0xca,0x71,0x42,0xd8,0x71,0x2e,
+ 0xd9,0x19,0x29,0xa9,0x0a,0x09,0xc3,0xcb,
+ 0x77,0x44,0xcc,0x65,0x56,0xa0,0x08,0x3f,
+ 0xcf,0x7f,0x5c,0xfc,0x35,0xf7,0x43,0xcc,
+ 0x77,0x56,0xcc,0x09,0x57,0xc8,0x0f,0x4f,
+ 0xdc,0x5f,0x36,0x3d,0x4b,0x70,0x44,0xde,
+ 0x65,0x3a,0xa1,0x60,0x38,0xbf,0x6c,0x7c,
+ 0x96,0xf4,0x89,0xc4,0xcb,0x65,0x44,0xa0,
+ 0x64,0x3e,0xa7,0x78,0x2c,0xef,0x15,0x9d,
+ 0x82,0xb2,0xf0,0x51,0xde,0x1b,0x3b,0xa5,
+ 0x66,0x20,0xab,0x3c,0x05,0x77,0xe0,0xcf,
+ 0xbd,0x5e,0x70,0x3a,0xdf,0x61,0x3c,0xb9,
+ 0x74,0x68,0xc6,0x8d,0x68,0xd0,0x8d,0x1c,
+ 0xd1,0xb5,0x1a,0x41,0xa2,0x7a,0x32,0xe3,
+ 0x51,0xb4,0x1a,0x47,0xa2,0x6e,0x32,0x9b,
+ 0x50,0xa4,0x1c,0x27,0xb7,0x2e,0x4d,0x1a,
+ 0x51,0xa2,0x1a,0x33,0xa3,0x56,0x34,0x0b,
+ 0x47,0xc4,0x6f,0x66,0x9c,0xa8,0xb4,0x0c,
+ 0x47,0xd6,0x6f,0x0a,0x9d,0xc0,0xb3,0x7c,
+ 0x54,0xf6,0x05,0xcb,0xe3,0x47,0xb4,0x6e,
+ 0x46,0x9a,0x68,0xa2,0x8c,0x30,0xd7,0x5d,
+ 0x0c,0x31,0xd7,0x5b,0x0c,0x25,0xd7,0x23,
+ 0x0d,0x35,0xd1,0x43,0x18,0x75,0xae,0xc2,
+ 0x19,0x73,0xa8,0xd6,0x0d,0x0b,0xd1,0xc7,
+ 0x1b,0x6d,0xa4,0x92,0x24,0x93,0x24,0x95,
+ 0x24,0x81,0x24,0xf9,0x25,0xe9,0x23,0x89,
+ 0x36,0xc9,0x49,0x48,0x48,0x4e,0x4e,0x5a,
+ 0x5a,0x22,0x23,0x33,0x35,0x55,0x40,0x00,
+};
+
+
+#endif
+
diff --git a/apps/plugins/rockboy/nosound.c b/apps/plugins/rockboy/nosound.c
new file mode 100644
index 0000000..a0c9b17
--- /dev/null
+++ b/apps/plugins/rockboy/nosound.c
@@ -0,0 +1,43 @@
+
+
+
+#include "rockmacros.h"
+#include "defs.h"
+#include "pcm.h"
+#include "rc.h"
+
+
+struct pcm pcm;
+
+static byte buf[4096];
+
+
+rcvar_t pcm_exports[] =
+{
+ RCV_END
+};
+
+
+void pcm_init(void)
+{
+ pcm.hz = 11025;
+ pcm.buf = buf;
+ pcm.len = sizeof buf;
+ pcm.pos = 0;
+}
+
+void pcm_close(void)
+{
+ memset(&pcm, 0, sizeof pcm);
+}
+
+int pcm_submit(void)
+{
+ pcm.pos = 0;
+ return 0;
+}
+
+
+
+
+
diff --git a/apps/plugins/rockboy/palette.c b/apps/plugins/rockboy/palette.c
new file mode 100644
index 0000000..5c5083d
--- /dev/null
+++ b/apps/plugins/rockboy/palette.c
@@ -0,0 +1,153 @@
+
+
+#include "rockmacros.h"
+#include "defs.h"
+#include "fb.h"
+#include "palette.h"
+
+
+static byte palmap[32768];
+static byte pallock[256];
+static int palrev[256];
+
+/* Course color mapping, for when palette is exhausted. */
+static byte crsmap[4][32768];
+static int crsrev[4][256];
+static const int crsmask[4] = { 0x7BDE, 0x739C, 0x6318, 0x4210 };
+
+enum plstatus
+{
+ pl_unused = 0,
+ pl_linger,
+ pl_active,
+ pl_locked
+};
+
+/*
+static byte bestmatch(int c)
+{
+ byte n, best;
+ int r, g, b;
+ int r2, g2, b2, c2;
+ int err, besterr;
+
+ r = (c & 0x001F) << 3;
+ g = (c & 0x03E0) >> 2;
+ b = (c & 0x7C00) >> 7;
+
+ best = 0;
+ besterr = 1024;
+ for (n = 1; n; n++)
+ {
+ c2 = palrev[n];
+ r2 = (c2 & 0x001F) << 3;
+ g2 = (c2 & 0x03E0) >> 2;
+ b2 = (c2 & 0x7C00) >> 7;
+ err = abs(r-r2) + abs(b-b2) + abs(g-g2);
+ if (err < besterr)
+ {
+ besterr = err;
+ best = n;
+ }
+ }
+ return best;
+}
+*/
+
+static void makecourse(int c, byte n)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ c &= crsmask[i];
+ crsmap[i][c] = n;
+ crsrev[i][n] = c;
+ }
+}
+
+static byte findcourse(int c)
+{
+ int i;
+ byte n;
+ for (i = 0; i < 4; i++)
+ {
+ c &= crsmask[i];
+ n = crsmap[i][c];
+ if (crsrev[i][n] == c)
+ return n;
+ }
+ return 0;
+}
+
+
+void pal_lock(byte n)
+{
+ if (!n) return;
+ if (pallock[n] >= pl_locked)
+ pallock[n]++;
+ else pallock[n] = pl_locked;
+}
+
+byte pal_getcolor(int c, int r, int g, int b)
+{
+ byte n;
+ static byte l;
+ n = palmap[c];
+ if (n && pallock[n] && palrev[n] == c)
+ {
+ pal_lock(n);
+ return n;
+ }
+ for (n = l+1; n != l; n++)
+ {
+ if (!n || pallock[n] /* || n < 16 */) continue;
+ pal_lock(n);
+ palmap[c] = n;
+ palrev[n] = c;
+ makecourse(c, n);
+ vid_setpal(n, r, g, b);
+ return (l = n);
+ }
+ n = findcourse(c);
+ pal_lock(n);
+ return n;
+}
+
+void pal_release(byte n)
+{
+ if (pallock[n] >= pl_locked)
+ pallock[n]--;
+}
+
+
+void pal_expire(void)
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (pallock[i] && pallock[i] < pl_locked)
+ pallock[i]--;
+}
+
+
+void pal_set332(void)
+{
+ int i, r, g, b;
+
+ fb.indexed = 0;
+ fb.cc[0].r = 5;
+ fb.cc[1].r = 5;
+ fb.cc[2].r = 6;
+ fb.cc[0].l = 0;
+ fb.cc[1].l = 3;
+ fb.cc[2].l = 6;
+
+ i = 0;
+ for (b = 0; b < 4; b++) for (g = 0; g < 8; g++) for (r = 0; r < 8; r++)
+ vid_setpal(i++, (r<<5)|(r<<2)|(r>>1),
+ (g<<5)|(g<<2)|(g>>1), (b<<6)|(b<<4)|(b<<2)|b);
+}
+
+
+
+
+
diff --git a/apps/plugins/rockboy/palette.h b/apps/plugins/rockboy/palette.h
new file mode 100644
index 0000000..05b093b
--- /dev/null
+++ b/apps/plugins/rockboy/palette.h
@@ -0,0 +1,6 @@
+void pal_lock(byte n);
+byte pal_getcolor(int c, int r, int g, int b);
+void pal_release(byte n);
+void pal_expire(void);
+void pal_set332(void);
+void vid_setpal(int i, int r, int g, int b);
diff --git a/apps/plugins/rockboy/pcm.h b/apps/plugins/rockboy/pcm.h
new file mode 100644
index 0000000..3719933
--- /dev/null
+++ b/apps/plugins/rockboy/pcm.h
@@ -0,0 +1,21 @@
+
+#ifndef __PCM_H__
+#define __PCM_H__
+
+
+#include "defs.h"
+
+struct pcm
+{
+ int hz, len;
+ int stereo;
+ byte *buf;
+ int pos;
+};
+
+extern struct pcm pcm;
+
+
+#endif
+
+
diff --git a/apps/plugins/rockboy/rc.h b/apps/plugins/rockboy/rc.h
new file mode 100644
index 0000000..217b05f
--- /dev/null
+++ b/apps/plugins/rockboy/rc.h
@@ -0,0 +1,71 @@
+
+
+
+#ifndef __RC_H__
+#define __RC_H__
+
+
+
+typedef enum rctype
+{
+ rcv_end,
+ rcv_int,
+ rcv_string,
+ rcv_vector,
+ rcv_bool
+} rcvtype_t;
+
+
+typedef struct rcvar_s
+{
+ char *name;
+ int type;
+ int len;
+ void *mem;
+} rcvar_t;
+
+#define RCV_END { 0, rcv_end, 0, 0 }
+#define RCV_INT(n,v) { (n), rcv_int, 1, (v) }
+#define RCV_STRING(n,v) { (n), rcv_string, 0, (v) }
+#define RCV_VECTOR(n,v,l) { (n), rcv_vector, (l), (v) }
+#define RCV_BOOL(n,v) { (n), rcv_bool, 1, (v) }
+
+typedef struct rccmd_s
+{
+ char *name;
+ int (*func)(int, char **);
+} rccmd_t;
+
+#define RCC(n,f) { (n), (f) }
+#define RCC_END { 0, 0 }
+
+void rc_export(rcvar_t *v);
+void rc_exportvars(rcvar_t *vars);
+
+int rc_findvar(char *name);
+
+int rc_setvar_n(int i, int c, char **v);
+int rc_setvar(char *name, int c, char **v);
+
+int rc_getint_n(int i);
+int *rc_getvec_n(int i);
+char *rc_getstr_n(int i);
+
+int rc_getint(char *name);
+int *rc_getvec(char *name);
+char *rc_getstr(char *name);
+
+int rc_bindkey(char *keyname, char *cmd);
+int rc_unbindkey(char *keyname);
+void rc_unbindall(void);
+
+int rc_sourcefile(char *filename);
+void rc_dokey(int key, int st);
+
+int rc_command(char *line);
+
+#endif
+
+
+
+
diff --git a/apps/plugins/rockboy/rccmds.c b/apps/plugins/rockboy/rccmds.c
new file mode 100644
index 0000000..c9375b6
--- /dev/null
+++ b/apps/plugins/rockboy/rccmds.c
@@ -0,0 +1,122 @@
+
+
+
+
+#include "rockmacros.h"
+
+#include "defs.h"
+#include "rc.h"
+#include "hw.h"
+#include "emu.h"
+#include "save.h"
+#include "split.h"
+
+/*
+ * the set command is used to set rc-exported variables.
+ */
+
+static int cmd_set(int argc, char **argv)
+{
+ if (argc < 3)
+ return -1;
+ return rc_setvar(argv[1], argc-2, argv+2);
+}
+
+
+
+/*
+ * the following commands allow keys to be bound to perform rc commands.
+ */
+
+static int cmd_reset(int argc, char **argv)
+{
+ (void)argc;
+ (void)argv;
+ emu_reset();
+ return 0;
+}
+
+static int cmd_savestate(int argc, char **argv)
+{
+ state_save(argc > 1 ? atoi(argv[1]) : -1);
+ return 0;
+}
+
+static int cmd_loadstate(int argc, char **argv)
+{
+ state_load(argc > 1 ? atoi(argv[1]) : -1);
+ return 0;
+}
+
+
+
+/*
+ * table of command names and the corresponding functions to be called
+ */
+
+rccmd_t rccmds[] =
+{
+ RCC("set", cmd_set),
+ RCC("reset", cmd_reset),
+ RCC("savestate", cmd_savestate),
+ RCC("loadstate", cmd_loadstate),
+ RCC_END
+};
+
+
+
+
+
+int rc_command(char *line)
+{
+ int i, argc, ret;
+ char *argv[128], linecopy[500];
+
+// linecopy = malloc(strlen(line)+1);
+ strcpy(linecopy, line);
+
+ argc = splitline(argv, (sizeof argv)/(sizeof argv[0]), linecopy);
+ if (!argc)
+ {
+// free(linecopy);
+ return -1;
+ }
+
+ for (i = 0; rccmds[i].name; i++)
+ {
+ if (!strcmp(argv[0], rccmds[i].name))
+ {
+ ret = rccmds[i].func(argc, argv);
+// free(linecopy);
+ return ret;
+ }
+ }
+
+ /* printf("unknown command: %s\n", argv[0]); */
+// free(linecopy);
+
+ return -1;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/plugins/rockboy/rcvars.c b/apps/plugins/rockboy/rcvars.c
new file mode 100644
index 0000000..e37657d
--- /dev/null
+++ b/apps/plugins/rockboy/rcvars.c
@@ -0,0 +1,233 @@
+
+
+
+
+#include <string.h>
+#include "rockmacros.h"
+
+#include "defs.h"
+#include "rc.h"
+
+
+
+
+
+
+static rcvar_t rcvars[150];
+
+static int nvars;
+
+
+
+
+
+void rc_export(rcvar_t *v)
+{
+ const rcvar_t end = RCV_END;
+
+ if (!v) return;
+ nvars++;
+// rcvars = realloc(rcvars, sizeof (rcvar_t) * (nvars+1));
+// if (!rcvars)
+// die("out of memory adding rcvar %s\n", v->name);
+ rcvars[nvars-1] = *v;
+ rcvars[nvars] = end;
+}
+
+void rc_exportvars(rcvar_t *vars)
+{
+ while(vars->type)
+ rc_export(vars++);
+}
+
+
+
+int rc_findvar(char *name)
+{
+ int i;
+ if (!rcvars) return -1;
+ for (i = 0; rcvars[i].name; i++)
+ if (!strcmp(rcvars[i].name, name))
+ break;
+ if (!rcvars[i].name)
+ return -1;
+ return i;
+}
+
+
+int my_atoi(const char *s)
+{
+ int a = 0;
+ if (*s == '0')
+ {
+ s++;
+ if (*s == 'x' || *s == 'X')
+ {
+ s++;
+ while (*s)
+ {
+ if (isdigit(*s))
+ a = (a<<4) + *s - '0';
+ else if (strchr("ABCDEF", *s))
+ a = (a<<4) + *s - 'A' + 10;
+ else if (strchr("abcdef", *s))
+ a = (a<<4) + *s - 'a' + 10;
+ else return a;
+ s++;
+ }
+ return a;
+ }
+ while (*s)
+ {
+ if (strchr("01234567", *s))
+ a = (a<<3) + *s - '0';
+ else return a;
+ s++;
+ }
+ return a;
+ }
+ if (*s == '-')
+ {
+ s++;
+ for (;;)
+ {
+ if (isdigit(*s))
+ a = (a*10) + *s - '0';
+ else return -a;
+ s++;
+ }
+ }
+ while (*s)
+ {
+ if (isdigit(*s))
+ a = (a*10) + *s - '0';
+ else return a;
+ s++;
+ }
+ return a;
+}
+
+
+int rc_setvar_n(int i, int c, char **v)
+{
+ int j;
+ int *n;
+ char **s;
+
+ switch (rcvars[i].type)
+ {
+ case rcv_int:
+ if (c < 1) return -1;
+ n = (int *)rcvars[i].mem;
+ *n = my_atoi(v[0]);
+ return 0;
+ case rcv_string:
+ if (c < 1) return -1;
+ s = (char **)rcvars[i].mem;
+// if (*s) free(*s);
+ strcpy(*s,v[0]);
+ if (!*s)
+ die("out of memory setting rcvar %s\n", rcvars[i].name);
+ return 0;
+ case rcv_vector:
+ if (c > rcvars[i].len)
+ c = rcvars[i].len;
+ for (j = 0; j < c ; j++)
+ ((int *)rcvars[i].mem)[j] = my_atoi(v[j]);
+ return 0;
+ case rcv_bool:
+ if (c < 1 || atoi(v[0]) || strchr("yYtT", v[0][0]))
+ *(int *)rcvars[i].mem = 1;
+ else if (strchr("0nNfF", v[0][0]))
+ *(int *)rcvars[i].mem = 0;
+ else
+ return -1;
+ return 0;
+ }
+ return -1;
+}
+
+
+int rc_setvar(char *name, int c, char **v)
+{
+ int i;
+
+ i = rc_findvar(name);
+ if (i < 0) return i;
+
+ return rc_setvar_n(i, c, v);
+}
+
+
+void *rc_getmem_n(int i)
+{
+ return rcvars[i].mem;
+}
+
+
+void *rc_getmem(char *name)
+{
+ int i;
+ i = rc_findvar(name);
+ if (i < 0) return NULL;
+ return rcvars[i].mem;
+}
+
+int rc_getint_n(int i)
+{
+ if (i < 0) return 0;
+ switch (rcvars[i].type)
+ {
+ case rcv_int:
+ case rcv_bool:
+ return *(int *)rcvars[i].mem;
+ }
+ return 0;
+}
+
+int *rc_getvec_n(int i)
+{
+ if (i < 0) return NULL;
+ switch (rcvars[i].type)
+ {
+ case rcv_int:
+ case rcv_bool:
+ case rcv_vector:
+ return (int *)rcvars[i].mem;
+ }
+ return NULL;
+}
+
+char *rc_getstr_n(int i)
+{
+ if (i < 0) return 0;
+ switch (rcvars[i].type)
+ {
+ case rcv_string:
+ return *(char **)rcvars[i].mem;
+ }
+ return 0;
+}
+
+int rc_getint(char *name)
+{
+ return rc_getint_n(rc_findvar(name));
+}
+
+int *rc_getvec(char *name)
+{
+ return rc_getvec_n(rc_findvar(name));
+}
+
+char *rc_getstr(char *name)
+{
+ return rc_getstr_n(rc_findvar(name));
+}
+
+
+
+
+
+
+
+
diff --git a/apps/plugins/rockboy/regs.h b/apps/plugins/rockboy/regs.h
new file mode 100644
index 0000000..4457fd9
--- /dev/null
+++ b/apps/plugins/rockboy/regs.h
@@ -0,0 +1,181 @@
+
+#ifndef __REGS_H__
+#define __REGS_H__
+
+
+#include "mem.h"
+
+/* General internal/io stuff */
+
+#define RI_P1 0x00
+#define RI_SB 0x01
+#define RI_SC 0x02
+#define RI_DIV 0x04
+#define RI_TIMA 0x05
+#define RI_TMA 0x06
+#define RI_TAC 0x07
+
+#define RI_KEY1 0x4D
+
+#define RI_RP 0x56
+
+#define RI_SVBK 0x70
+
+
+
+/* Interrupts flags */
+
+#define RI_IF 0x0F
+#define RI_IE 0xFF
+
+
+
+
+/* LCDC */
+
+#define RI_LCDC 0x40
+#define RI_STAT 0x41
+#define RI_SCY 0x42
+#define RI_SCX 0x43
+#define RI_LY 0x44
+#define RI_LYC 0x45
+#define RI_DMA 0x46
+#define RI_BGP 0x47
+#define RI_OBP0 0x48
+#define RI_OBP1 0x49
+#define RI_WY 0x4A
+#define RI_WX 0x4B
+
+#define RI_VBK 0x4F
+
+#define RI_HDMA1 0x51
+#define RI_HDMA2 0x52
+#define RI_HDMA3 0x53
+#define RI_HDMA4 0x54
+#define RI_HDMA5 0x55
+
+#define RI_BCPS 0x68
+#define RI_BCPD 0x69
+#define RI_OCPS 0x6A
+#define RI_OCPD 0x6B
+
+
+
+/* Sound */
+
+#define RI_NR10 0x10
+#define RI_NR11 0x11
+#define RI_NR12 0x12
+#define RI_NR13 0x13
+#define RI_NR14 0x14
+#define RI_NR21 0x16
+#define RI_NR22 0x17
+#define RI_NR23 0x18
+#define RI_NR24 0x19
+#define RI_NR30 0x1A
+#define RI_NR31 0x1B
+#define RI_NR32 0x1C
+#define RI_NR33 0x1D
+#define RI_NR34 0x1E
+#define RI_NR41 0x20
+#define RI_NR42 0x21
+#define RI_NR43 0x22
+#define RI_NR44 0x23
+#define RI_NR50 0x24
+#define RI_NR51 0x25
+#define RI_NR52 0x26
+
+
+
+#define REG(n) ram.hi[(n)]
+
+
+
+/* General internal/io stuff */
+
+#define R_P1 REG(RI_P1)
+#define R_SB REG(RI_SB)
+#define R_SC REG(RI_SC)
+#define R_DIV REG(RI_DIV)
+#define R_TIMA REG(RI_TIMA)
+#define R_TMA REG(RI_TMA)
+#define R_TAC REG(RI_TAC)
+
+#define R_KEY1 REG(RI_KEY1)
+
+#define R_RP REG(RI_RP)
+
+#define R_SVBK REG(RI_SVBK)
+
+
+
+/* Interrupts flags */
+
+#define R_IF REG(RI_IF)
+#define R_IE REG(RI_IE)
+
+
+
+
+/* LCDC */
+
+#define R_LCDC REG(RI_LCDC)
+#define R_STAT REG(RI_STAT)
+#define R_SCY REG(RI_SCY)
+#define R_SCX REG(RI_SCX)
+#define R_LY REG(RI_LY)
+#define R_LYC REG(RI_LYC)
+#define R_DMA REG(RI_DMA)
+#define R_BGP REG(RI_BGP)
+#define R_OBP0 REG(RI_OBP0)
+#define R_OBP1 REG(RI_OBP1)
+#define R_WY REG(RI_WY)
+#define R_WX REG(RI_WX)
+
+#define R_VBK REG(RI_VBK)
+
+#define R_HDMA1 REG(RI_HDMA1)
+#define R_HDMA2 REG(RI_HDMA2)
+#define R_HDMA3 REG(RI_HDMA3)
+#define R_HDMA4 REG(RI_HDMA4)
+#define R_HDMA5 REG(RI_HDMA5)
+
+#define R_BCPS REG(RI_BCPS)
+#define R_BCPD REG(RI_BCPD)
+#define R_OCPS REG(RI_OCPS)
+#define R_OCPD REG(RI_OCPD)
+
+
+
+/* Sound */
+
+#define R_NR10 REG(RI_NR10)
+#define R_NR11 REG(RI_NR11)
+#define R_NR12 REG(RI_NR12)
+#define R_NR13 REG(RI_NR13)
+#define R_NR14 REG(RI_NR14)
+#define R_NR21 REG(RI_NR21)
+#define R_NR22 REG(RI_NR22)
+#define R_NR23 REG(RI_NR23)
+#define R_NR24 REG(RI_NR24)
+#define R_NR30 REG(RI_NR30)
+#define R_NR31 REG(RI_NR31)
+#define R_NR32 REG(RI_NR32)
+#define R_NR33 REG(RI_NR33)
+#define R_NR34 REG(RI_NR34)
+#define R_NR41 REG(RI_NR41)
+#define R_NR42 REG(RI_NR42)
+#define R_NR43 REG(RI_NR43)
+#define R_NR44 REG(RI_NR44)
+#define R_NR50 REG(RI_NR50)
+#define R_NR51 REG(RI_NR51)
+#define R_NR52 REG(RI_NR52)
+
+
+
+#endif
+
+
+
+
+
diff --git a/apps/plugins/rockboy/rockboy.c b/apps/plugins/rockboy/rockboy.c
new file mode 100644
index 0000000..c9788e2
--- /dev/null
+++ b/apps/plugins/rockboy/rockboy.c
@@ -0,0 +1,137 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Gameboy emulator based on gnuboy
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "plugin.h"
+#include "loader.h"
+#include "rockmacros.h"
+
+#if MEM <= 8 && !defined(SIMULATOR)
+/* On archos this is loaded as an overlay */
+
+/* These are defined in the linker script */
+extern unsigned char ovl_start_addr[];
+extern unsigned char ovl_end_addr[];
+
+const struct {
+ unsigned long magic;
+ unsigned char *start_addr;
+ unsigned char *end_addr;
+ enum plugin_status (*entry_point)(struct plugin_api*, void*);
+} header __attribute__ ((section (".header"))) = {
+ 0x524f564c, /* ROVL */
+ ovl_start_addr, ovl_end_addr, plugin_start
+};
+#endif
+
+/* here is a global api struct pointer. while not strictly necessary,
+ it's nice not to have to pass the api pointer in all function calls
+ in the plugin */
+struct plugin_api* rb;
+int shut,cleanshut;
+char *errormsg;
+int gnuboy_main(char *rom);
+
+/* libc functions */
+
+int isdigit(int c) {
+ return c>='0' && c<= '9';
+}
+
+int isalpha(int c) {
+ return (c>='a' && c<='z')||(c>='A' && c<='Z');
+}
+
+int isupper(int c) {
+ return c>='A'&&c<='Z';
+}
+
+int isalnum(int c) {
+ return isdigit(c)||isalpha(c);
+}
+
+void die(char *message, ...)
+{
+ shut=1;
+ errormsg=message;
+}
+
+void *mp3_bufferbase;
+void *mp3_bufferpointer;
+unsigned int mp3_buffer_free;
+
+void *my_malloc(size_t size)
+{
+ void *alloc;
+
+ if (!mp3_bufferbase)
+ {
+ mp3_bufferbase = mp3_bufferpointer
+ = rb->plugin_get_mp3_buffer(&mp3_buffer_free);
+#if MEM <= 8 && !defined(SIMULATOR)
+ /* loaded as an overlay, protect from overwriting ourselves */
+ if ((unsigned)(ovl_start_addr - (unsigned char *)mp3_bufferbase)
+ < mp3_buffer_free)
+ mp3_buffer_free = ovl_start_addr - (unsigned char *)mp3_bufferbase;
+#endif
+ }
+ if (size + 4 > mp3_buffer_free)
+ return 0;
+ alloc = mp3_bufferpointer;
+ mp3_bufferpointer += size + 4;
+ mp3_buffer_free -= size + 4;
+ return alloc;
+}
+
+void setmallocpos(void *pointer)
+{
+ mp3_bufferpointer = pointer;
+ mp3_buffer_free = mp3_bufferpointer - mp3_bufferbase;
+}
+
+/* this is the plugin entry point */
+enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
+{
+ /* this macro should be called as the first thing you do in the plugin.
+ it test that the api version and model the plugin was compiled for
+ matches the machine it is running on */
+ TEST_PLUGIN_API(api);
+
+ /* if you are using a global api pointer, don't forget to copy it!
+ otherwise you will get lovely "I04: IllInstr" errors... :-) */
+ rb = api;
+ shut=0;
+ cleanshut=0;
+ mp3_bufferbase=mp3_bufferpointer=0;
+ mp3_buffer_free=0;
+
+ /* now go ahead and have fun! */
+ rb->splash(HZ*2, true, "Rockboy v0.3");
+ rb->lcd_clear_display();
+ gnuboy_main(parameter);
+
+ if(shut&&!cleanshut) {
+ rb->splash(HZ*2, true, errormsg);
+ return PLUGIN_ERROR;
+ }
+
+ rb->splash(HZ*2, true, "Shutting down.. byebye ^^");
+
+ cleanup();
+
+ return PLUGIN_OK;
+}
diff --git a/apps/plugins/rockboy/rockmacros.h b/apps/plugins/rockboy/rockmacros.h
new file mode 100644
index 0000000..63f9b10
--- /dev/null
+++ b/apps/plugins/rockboy/rockmacros.h
@@ -0,0 +1,88 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 Michiel van der Kolk, Jens Arnold
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <plugin.h>
+
+/* workaround for cygwin not defining endian macros */
+#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) && defined(_X86_)
+#define LITTLE_ENDIAN
+#endif
+
+#define malloc(a) my_malloc(a)
+void *my_malloc(size_t size);
+
+extern struct plugin_api* rb;
+extern int shut,cleanshut;
+void vid_update(int scanline);
+void vid_init(void);
+void vid_begin(void);
+void vid_end(void);
+void die(char *message, ...);
+void setmallocpos(void *pointer);
+void vid_settitle(char *title);
+void *sys_timer(void);
+int sys_elapsed(long *oldtick);
+void sys_sleep(int us);
+int pcm_submit(void);
+void pcm_init(void);
+void doevents(void);
+int isupper(int c);
+int isdigit(int c);
+void ev_poll(void);
+
+#ifdef SIMULATOR
+#undef opendir
+#define opendir(a) rb->sim_opendir((a))
+#undef closedir
+#define closedir(a) rb->sim_closedir((a))
+#undef mkdir
+#define mkdir(a,b) rb->sim_mkdir((a),(b))
+#undef open
+#define open(a,b) rb->sim_open((a),(b))
+#undef lseek
+#define lseek(a,b,c) rb->sim_lseek((a),(b),(c))
+#else /* !SIMULATOR */
+#define opendir(a) rb->opendir((a))
+#define closedir(a) rb->closedir((a))
+#define mkdir(a,b) rb->mkdir((a),(b))
+#define open(a,b) rb->open((a),(b))
+#define lseek(a,b,c) rb->lseek((a),(b),(c))
+#endif /* !SIMULATOR */
+
+#define strcat(a,b) rb->strcat((a),(b))
+#define close(a) rb->close((a))
+#define read(a,b,c) rb->read((a),(b),(c))
+#define write(a,b,c) rb->write((a),(b),(c))
+#define memset(a,b,c) rb->memset((a),(b),(c))
+#define memcpy(a,b,c) rb->memcpy((a),(b),(c))
+#define strcpy(a,b) rb->strcpy((a),(b))
+#define strncpy(a,b,c) rb->strncpy((a),(b),(c))
+#define strlen(a) rb->strlen((a))
+#define strcmp(a,b) rb->strcmp((a),(b))
+#define strchr(a,b) rb->strchr((a),(b))
+#define strrchr(a,b) rb->strrchr((a),(b))
+#define strcasecmp(a,b) rb->strcasecmp((a),(b))
+#define srand(a) rb->srand((a))
+#define rand() rb->rand()
+#define atoi(a) rb->atoi((a))
+#define strcat(a,b) rb->strcat((a),(b))
+#define snprintf(...) rb->snprintf(__VA_ARGS__)
+#define fprintf(...) rb->fdprintf(__VA_ARGS__)
+#define tolower(_A_) (isupper(_A_) ? (_A_ - 'A' + 'a') : _A_)
+
diff --git a/apps/plugins/rockboy/rtc.c b/apps/plugins/rockboy/rtc.c
new file mode 100644
index 0000000..99e71dc
--- /dev/null
+++ b/apps/plugins/rockboy/rtc.c
@@ -0,0 +1,135 @@
+
+
+
+#include "rockmacros.h"
+#include <stdio.h>
+
+#include "defs.h"
+#include "mem.h"
+#include "rtc.h"
+#include "rc.h"
+
+struct rtc rtc;
+
+static int syncrtc = 1;
+
+rcvar_t rtc_exports[] =
+{
+ RCV_BOOL("syncrtc", &syncrtc),
+ RCV_END
+};
+
+
+void rtc_latch(byte b)
+{
+ if ((rtc.latch ^ b) & b & 1)
+ {
+ rtc.regs[0] = rtc.s;
+ rtc.regs[1] = rtc.m;
+ rtc.regs[2] = rtc.h;
+ rtc.regs[3] = rtc.d;
+ rtc.regs[4] = (rtc.d>>9) | (rtc.stop<<6) | (rtc.carry<<7);
+ rtc.regs[5] = 0xff;
+ rtc.regs[6] = 0xff;
+ rtc.regs[7] = 0xff;
+ }
+ rtc.latch = b;
+}
+
+void rtc_write(byte b)
+{
+ /* printf("write %02X: %02X (%d)\n", rtc.sel, b, b); */
+ if (!(rtc.sel & 8)) return;
+ switch (rtc.sel & 7)
+ {
+ case 0:
+ rtc.s = rtc.regs[0] = b;
+ while (rtc.s >= 60) rtc.s -= 60;
+ break;
+ case 1:
+ rtc.m = rtc.regs[1] = b;
+ while (rtc.m >= 60) rtc.m -= 60;
+ break;
+ case 2:
+ rtc.h = rtc.regs[2] = b;
+ while (rtc.h >= 24) rtc.h -= 24;
+ break;
+ case 3:
+ rtc.regs[3] = b;
+ rtc.d = (rtc.d & 0x100) | b;
+ break;
+ case 4:
+ rtc.regs[4] = b;
+ rtc.d = (rtc.d & 0xff) | ((b&1)<<9);
+ rtc.stop = (b>>6)&1;
+ rtc.carry = (b>>7)&1;
+ break;
+ }
+}
+
+void rtc_tick()
+{
+ if (rtc.stop) return;
+ if (++rtc.t == 60)
+ {
+ if (++rtc.s == 60)
+ {
+ if (++rtc.m == 60)
+ {
+ if (++rtc.h == 24)
+ {
+ if (++rtc.d == 365)
+ {
+ rtc.d = 0;
+ rtc.carry = 1;
+ }
+ rtc.h = 0;
+ }
+ rtc.m = 0;
+ }
+ rtc.s = 0;
+ }
+ rtc.t = 0;
+ }
+}
+
+void rtc_save_internal(int fd)
+{
+ (void)fd; // stop compiler complaining
+ // TODO
+// fprintf(f, "%d %d %d %02d %02d %02d %02d\n%d\n",
+// rtc.carry, rtc.stop, rtc.d, rtc.h, rtc.m, rtc.s, rtc.t,
+// time(0));
+}
+
+void rtc_load_internal(int fd)
+{
+ //int rt = 0;
+ (void)fd; // stop compiler complaining
+ // TODO
+/* fscanf(
+ f, "%d %d %d %02d %02d %02d %02d\n%d\n",
+ &rtc.carry, &rtc.stop, &rtc.d,
+ &rtc.h, &rtc.m, &rtc.s, &rtc.t, &rt);
+ while (rtc.t >= 60) rtc.t -= 60;
+ while (rtc.s >= 60) rtc.s -= 60;
+ while (rtc.m >= 60) rtc.m -= 60;
+ while (rtc.h >= 24) rtc.h -= 24;
+ while (rtc.d >= 365) rtc.d -= 365;
+ rtc.stop &= 1;
+ rtc.carry &= 1;
+ if (rt) rt = (time(0) - rt) * 60;
+ if (syncrtc) while (rt-- > 0) rtc_tick(); */
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/plugins/rockboy/rtc.h b/apps/plugins/rockboy/rtc.h
new file mode 100644
index 0000000..2665cd8
--- /dev/null
+++ b/apps/plugins/rockboy/rtc.h
@@ -0,0 +1,25 @@
+
+
+#ifndef __RTC_H__
+#define __RTC_H__
+
+
+struct rtc
+{
+ int batt;
+ int sel;
+ int latch;
+ int d, h, m, s, t;
+ int stop, carry;
+ byte regs[8];
+};
+
+extern struct rtc rtc;
+
+void rtc_latch(byte b);
+void rtc_write(byte b);
+void rtc_tick(void);
+void rtc_save_internal(int fd);
+void rtc_load_internal(int fd);
+
+#endif
diff --git a/apps/plugins/rockboy/save.c b/apps/plugins/rockboy/save.c
new file mode 100644
index 0000000..bb9f905
--- /dev/null
+++ b/apps/plugins/rockboy/save.c
@@ -0,0 +1,286 @@
+
+
+#include "rockmacros.h"
+#include <stdio.h>
+
+#include "defs.h"
+#include "cpu.h"
+#include "cpuregs.h"
+#include "hw.h"
+#include "regs.h"
+#include "lcd.h"
+#include "rtc.h"
+#include "mem.h"
+#include "sound.h"
+
+
+
+#ifdef LITTLE_ENDIAN
+#define LIL(x) (x)
+#else
+#define LIL(x) ((x<<24)|((x&0xff00)<<8)|((x>>8)&0xff00)|(x>>24))
+#endif
+
+#define I1(s, p) { 1, s, p }
+#define I2(s, p) { 2, s, p }
+#define I4(s, p) { 4, s, p }
+#define R(r) I1(#r, &R_##r)
+#define NOSAVE { -1, "\0\0\0\0", 0 }
+#define END { 0, "\0\0\0\0", 0 }
+
+struct svar
+{
+ int len;
+ char key[4];
+ void *ptr;
+};
+
+static int ver;
+static int sramblock, iramblock, vramblock;
+static int hramofs, hiofs, palofs, oamofs, wavofs;
+
+struct svar svars[] =
+{
+ I4("GbSs", &ver),
+
+ I2("PC ", &PC),
+ I2("SP ", &SP),
+ I2("BC ", &BC),
+ I2("DE ", &DE),
+ I2("HL ", &HL),
+ I2("AF ", &AF),
+
+ I4("IME ", &cpu.ime),
+ I4("ima ", &cpu.ima),
+ I4("spd ", &cpu.speed),
+ I4("halt", &cpu.halt),
+ I4("div ", &cpu.div),
+ I4("tim ", &cpu.tim),
+ I4("lcdc", &cpu.lcdc),
+ I4("snd ", &cpu.snd),
+
+ I1("ints", &hw.ilines),
+ I1("pad ", &hw.pad),
+ I4("cgb ", &hw.cgb),
+ I4("gba ", &hw.gba),
+
+ I4("mbcm", &mbc.model),
+ I4("romb", &mbc.rombank),
+ I4("ramb", &mbc.rambank),
+ I4("enab", &mbc.enableram),
+ I4("batt", &mbc.batt),
+
+ I4("rtcR", &rtc.sel),
+ I4("rtcL", &rtc.latch),
+ I4("rtcC", &rtc.carry),
+ I4("rtcS", &rtc.stop),
+ I4("rtcd", &rtc.d),
+ I4("rtch", &rtc.h),
+ I4("rtcm", &rtc.m),
+ I4("rtcs", &rtc.s),
+ I4("rtct", &rtc.t),
+ I1("rtR8", &rtc.regs[0]),
+ I1("rtR9", &rtc.regs[1]),
+ I1("rtRA", &rtc.regs[2]),
+ I1("rtRB", &rtc.regs[3]),
+ I1("rtRC", &rtc.regs[4]),
+
+ I4("S1on", &snd.ch[0].on),
+ I4("S1p ", &snd.ch[0].pos),
+ I4("S1c ", &snd.ch[0].cnt),
+ I4("S1ec", &snd.ch[0].encnt),
+ I4("S1sc", &snd.ch[0].swcnt),
+ I4("S1sf", &snd.ch[0].swfreq),
+
+ I4("S2on", &snd.ch[1].on),
+ I4("S2p ", &snd.ch[1].pos),
+ I4("S2c ", &snd.ch[1].cnt),
+ I4("S2ec", &snd.ch[1].encnt),
+
+ I4("S3on", &snd.ch[2].on),
+ I4("S3p ", &snd.ch[2].pos),
+ I4("S3c ", &snd.ch[2].cnt),
+
+ I4("S4on", &snd.ch[3].on),
+ I4("S4p ", &snd.ch[3].pos),
+ I4("S4c ", &snd.ch[3].cnt),
+ I4("S4ec", &snd.ch[3].encnt),
+
+ I4("hdma", &hw.hdma),
+
+ I4("sram", &sramblock),
+ I4("iram", &iramblock),
+ I4("vram", &vramblock),
+ I4("hi ", &hiofs),
+ I4("pal ", &palofs),
+ I4("oam ", &oamofs),
+ I4("wav ", &wavofs),
+
+ /* NOSAVE is a special code to prevent the rest of the table
+ * from being saved, used to support old stuff for backwards
+ * compatibility... */
+ NOSAVE,
+
+ /* the following are obsolete as of 0x104 */
+
+ I4("hram", &hramofs),
+
+ R(P1), R(SB), R(SC),
+ R(DIV), R(TIMA), R(TMA), R(TAC),
+ R(IE), R(IF),
+ R(LCDC), R(STAT), R(LY), R(LYC),
+ R(SCX), R(SCY), R(WX), R(WY),
+ R(BGP), R(OBP0), R(OBP1),
+ R(DMA),
+
+ R(VBK), R(SVBK), R(KEY1),
+ R(BCPS), R(BCPD), R(OCPS), R(OCPD),
+
+ R(NR10), R(NR11), R(NR12), R(NR13), R(NR14),
+ R(NR21), R(NR22), R(NR23), R(NR24),
+ R(NR30), R(NR31), R(NR32), R(NR33), R(NR34),
+ R(NR41), R(NR42), R(NR43), R(NR44),
+ R(NR50), R(NR51), R(NR52),
+
+ I1("DMA1", &R_HDMA1),
+ I1("DMA2", &R_HDMA2),
+ I1("DMA3", &R_HDMA3),
+ I1("DMA4", &R_HDMA4),
+ I1("DMA5", &R_HDMA5),
+
+ END
+};
+
+
+void loadstate(int fd)
+{
+ int i, j;
+ byte buf[4096];
+ un32 (*header)[2] = (un32 (*)[2])buf;
+ un32 d;
+ int irl = hw.cgb ? 8 : 2;
+ int vrl = hw.cgb ? 4 : 2;
+ int srl = mbc.ramsize << 1;
+
+ ver = hramofs = hiofs = palofs = oamofs = wavofs = 0;
+
+ read(fd,buf, 4096);
+
+ for (j = 0; header[j][0]; j++)
+ {
+ for (i = 0; svars[i].ptr; i++)
+ {
+ if (header[j][0] != *(un32 *)svars[i].key)
+ continue;
+ d = LIL(header[j][1]);
+ switch (svars[i].len)
+ {
+ case 1:
+ *(byte *)svars[i].ptr = d;
+ break;
+ case 2:
+ *(un16 *)svars[i].ptr = d;
+ break;
+ case 4:
+ *(un32 *)svars[i].ptr = d;
+ break;
+ }
+ break;
+ }
+ }
+
+ /* obsolete as of version 0x104 */
+ if (hramofs) memcpy(ram.hi+128, buf+hramofs, 127);
+
+ if (hiofs) memcpy(ram.hi, buf+hiofs, sizeof ram.hi);
+ if (palofs) memcpy(lcd.pal, buf+palofs, sizeof lcd.pal);
+ if (oamofs) memcpy(lcd.oam.mem, buf+oamofs, sizeof lcd.oam);
+
+ if (wavofs) memcpy(snd.wave, buf+wavofs, sizeof snd.wave);
+ else memcpy(snd.wave, ram.hi+0x30, 16); /* patch data from older files */
+
+ lseek(fd, iramblock<<12, SEEK_SET);
+ read(fd,ram.ibank, 4096*irl);
+
+ lseek(fd, vramblock<<12, SEEK_SET);
+ read(fd,lcd.vbank, 4096*vrl);
+
+ lseek(fd, sramblock<<12, SEEK_SET);
+ read(fd,ram.sbank, 4096*srl);
+}
+
+void savestate(int fd)
+{
+ int i;
+ byte buf[4096];
+ un32 (*header)[2] = (un32 (*)[2])buf;
+ un32 d = 0;
+ int irl = hw.cgb ? 8 : 2;
+ int vrl = hw.cgb ? 4 : 2;
+ int srl = mbc.ramsize << 1;
+
+ ver = 0x105;
+ iramblock = 1;
+ vramblock = 1+irl;
+ sramblock = 1+irl+vrl;
+ wavofs = 4096 - 784;
+ hiofs = 4096 - 768;
+ palofs = 4096 - 512;
+ oamofs = 4096 - 256;
+ memset(buf, 0, sizeof buf);
+
+ for (i = 0; svars[i].len > 0; i++)
+ {
+ header[i][0] = *(un32 *)svars[i].key;
+ switch (svars[i].len)
+ {
+ case 1:
+ d = *(byte *)svars[i].ptr;
+ break;
+ case 2:
+ d = *(un16 *)svars[i].ptr;
+ break;
+ case 4:
+ d = *(un32 *)svars[i].ptr;
+ break;
+ }
+ header[i][1] = LIL(d);
+ }
+ header[i][0] = header[i][1] = 0;
+
+ memcpy(buf+hiofs, ram.hi, sizeof ram.hi);
+ memcpy(buf+palofs, lcd.pal, sizeof lcd.pal);
+ memcpy(buf+oamofs, lcd.oam.mem, sizeof lcd.oam);
+ memcpy(buf+wavofs, snd.wave, sizeof snd.wave);
+
+ lseek(fd, 0, SEEK_SET);
+ write(fd,buf, 4096);
+
+ lseek(fd, iramblock<<12, SEEK_SET);
+ write(fd,ram.ibank, 4096*irl);
+
+ lseek(fd, vramblock<<12, SEEK_SET);
+ write(fd,lcd.vbank, 4096*vrl);
+
+ lseek(fd, sramblock<<12, SEEK_SET);
+ write(fd,ram.sbank, 4096*srl);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/plugins/rockboy/save.h b/apps/plugins/rockboy/save.h
new file mode 100644
index 0000000..01b3b14
--- /dev/null
+++ b/apps/plugins/rockboy/save.h
@@ -0,0 +1,4 @@
+void loadstate(int fd);
+void savestate(int fd);
+void state_save(int n);
+void state_load(int n);
diff --git a/apps/plugins/rockboy/sound.c b/apps/plugins/rockboy/sound.c
new file mode 100644
index 0000000..edf31d8
--- /dev/null
+++ b/apps/plugins/rockboy/sound.c
@@ -0,0 +1,466 @@
+
+
+
+#include "rockmacros.h"
+#include "defs.h"
+#include "pcm.h"
+#include "sound.h"
+#include "cpu.h"
+#include "hw.h"
+#include "regs.h"
+#include "rc.h"
+#include "noise.h"
+
+
+static const byte dmgwave[16] =
+ {
+ 0xac, 0xdd, 0xda, 0x48,
+ 0x36, 0x02, 0xcf, 0x16,
+ 0x2c, 0x04, 0xe5, 0x2c,
+ 0xac, 0xdd, 0xda, 0x48
+ };
+
+static const byte cgbwave[16] =
+ {
+ 0x00, 0xff, 0x00, 0xff,
+ 0x00, 0xff, 0x00, 0xff,
+ 0x00, 0xff, 0x00, 0xff,
+ 0x00, 0xff, 0x00, 0xff,
+ };
+
+
+static const byte sqwave[4][8] =
+ {
+ { 0, 0,-1, 0, 0, 0, 0, 0 },
+ { 0,-1,-1, 0, 0, 0, 0, 0 },
+ { -1,-1,-1,-1, 0, 0, 0, 0 },
+ { -1, 0, 0,-1,-1,-1,-1,-1 }
+ };
+
+static const int freqtab[8] =
+ {
+ (1<<14)*2,
+ (1<<14),
+ (1<<14)/2,
+ (1<<14)/3,
+ (1<<14)/4,
+ (1<<14)/5,
+ (1<<14)/6,
+ (1<<14)/7
+ };
+
+struct snd snd;
+int pcm_submit(void);
+
+#define RATE (snd.rate)
+#define WAVE (snd.wave) /* ram.hi+0x30 */
+#define S1 (snd.ch[0])
+#define S2 (snd.ch[1])
+#define S3 (snd.ch[2])
+#define S4 (snd.ch[3])
+
+rcvar_t sound_exports[] =
+ {
+ RCV_END
+ };
+
+
+static void s1_freq_d(int d)
+{
+ if (RATE > (d<<4)) S1.freq = 0;
+ else S1.freq = (RATE << 17)/d;
+}
+
+static void s1_freq(void)
+{
+ s1_freq_d(2048 - (((R_NR14&7)<<8) + R_NR13));
+}
+
+static void s2_freq(void)
+{
+ int d = 2048 - (((R_NR24&7)<<8) + R_NR23);
+ if (RATE > (d<<4)) S2.freq = 0;
+ else S2.freq = (RATE << 17)/d;
+}
+
+static void s3_freq(void)
+{
+ int d = 2048 - (((R_NR34&7)<<8) + R_NR33);
+ if (RATE > (d<<3)) S3.freq = 0;
+ else S3.freq = (RATE << 21)/d;
+}
+
+static void s4_freq(void)
+{
+ S4.freq = (freqtab[R_NR43&7] >> (R_NR43 >> 4)) * RATE;
+ if (S4.freq >> 18) S4.freq = 1<<18;
+}
+
+void sound_dirty(void)
+{
+ S1.swlen = ((R_NR10>>4) & 7) << 14;
+ S1.len = (64-(R_NR11&63)) << 13;
+ S1.envol = R_NR12 >> 4;
+ S1.endir = (R_NR12>>3) & 1;
+ S1.endir |= S1.endir - 1;
+ S1.enlen = (R_NR12 & 7) << 15;
+ s1_freq();
+ S2.len = (64-(R_NR21&63)) << 13;
+ S2.envol = R_NR22 >> 4;
+ S2.endir = (R_NR22>>3) & 1;
+ S2.endir |= S2.endir - 1;
+ S2.enlen = (R_NR22 & 7) << 15;
+ s2_freq();
+ S3.len = (256-R_NR31) << 20;
+ s3_freq();
+ S4.len = (64-(R_NR41&63)) << 13;
+ S4.envol = R_NR42 >> 4;
+ S4.endir = (R_NR42>>3) & 1;
+ S4.endir |= S4.endir - 1;
+ S4.enlen = (R_NR42 & 7) << 15;
+ s4_freq();
+}
+
+void sound_off(void)
+{
+ memset(&S1, 0, sizeof S1);
+ memset(&S2, 0, sizeof S2);
+ memset(&S3, 0, sizeof S3);
+ memset(&S4, 0, sizeof S4);
+ R_NR10 = 0x80;
+ R_NR11 = 0xBF;
+ R_NR12 = 0xF3;
+ R_NR14 = 0xBF;
+ R_NR21 = 0x3F;
+ R_NR22 = 0x00;
+ R_NR24 = 0xBF;
+ R_NR30 = 0x7F;
+ R_NR31 = 0xFF;
+ R_NR32 = 0x9F;
+ R_NR33 = 0xBF;
+ R_NR41 = 0xFF;
+ R_NR42 = 0x00;
+ R_NR43 = 0x00;
+ R_NR44 = 0xBF;
+ R_NR50 = 0x77;
+ R_NR51 = 0xF3;
+ R_NR52 = 0xF1;
+ sound_dirty();
+}
+
+void sound_reset(void)
+{
+ memset(&snd, 0, sizeof snd);
+ if (pcm.hz) snd.rate = (1<<21) / pcm.hz;
+ else snd.rate = 0;
+ memcpy(WAVE, hw.cgb ? cgbwave : dmgwave, 16);
+ memcpy(ram.hi+0x30, WAVE, 16);
+ sound_off();
+}
+
+
+void sound_mix(void)
+{
+ int s, l, r, f, n;
+
+ if (!RATE || cpu.snd < RATE) return;
+
+ for (; cpu.snd >= RATE; cpu.snd -= RATE)
+ {
+ l = r = 0;
+
+ if (S1.on)
+ {
+ s = sqwave[R_NR11>>6][(S1.pos>>18)&7] & S1.envol;
+ S1.pos += S1.freq;
+ if ((R_NR14 & 64) && ((S1.cnt += RATE) >= S1.len))
+ S1.on = 0;
+ if (S1.enlen && (S1.encnt += RATE) >= S1.enlen)
+ {
+ S1.encnt -= S1.enlen;
+ S1.envol += S1.endir;
+ if (S1.envol < 0) S1.envol = 0;
+ if (S1.envol > 15) S1.envol = 15;
+ }
+ if (S1.swlen && (S1.swcnt += RATE) >= S1.swlen)
+ {
+ S1.swcnt -= S1.swlen;
+ f = S1.swfreq;
+ n = (R_NR10 & 7);
+ if (R_NR10 & 8) f -= (f >> n);
+ else f += (f >> n);
+ if (f > 2047)
+ S1.on = 0;
+ else
+ {
+ S1.swfreq = f;
+ R_NR13 = f;
+ R_NR14 = (R_NR14 & 0xF8) | (f>>8);
+ s1_freq_d(2048 - f);
+ }
+ }
+ s <<= 2;
+ if (R_NR51 & 1) r += s;
+ if (R_NR51 & 16) l += s;
+ }
+
+ if (S2.on)
+ {
+ s = sqwave[R_NR21>>6][(S2.pos>>18)&7] & S2.envol;
+ S2.pos += S2.freq;
+ if ((R_NR24 & 64) && ((S2.cnt += RATE) >= S2.len))
+ S2.on = 0;
+ if (S2.enlen && (S2.encnt += RATE) >= S2.enlen)
+ {
+ S2.encnt -= S2.enlen;
+ S2.envol += S2.endir;
+ if (S2.envol < 0) S2.envol = 0;
+ if (S2.envol > 15) S2.envol = 15;
+ }
+ s <<= 2;
+ if (R_NR51 & 2) r += s;
+ if (R_NR51 & 32) l += s;
+ }
+
+ if (S3.on)
+ {
+ s = WAVE[(S3.pos>>22) & 15];
+ if (S3.pos & (1<<21)) s &= 15;
+ else s >>= 4;
+ s -= 8;
+ S3.pos += S3.freq;
+ if ((R_NR34 & 64) && ((S3.cnt += RATE) >= S3.len))
+ S3.on = 0;
+ if (R_NR32 & 96) s <<= (3 - ((R_NR32>>5)&3));
+ else s = 0;
+ if (R_NR51 & 4) r += s;
+ if (R_NR51 & 64) l += s;
+ }
+
+ if (S4.on)
+ {
+ if (R_NR43 & 8) s = 1 & (noise7[
+ (S4.pos>>20)&15] >> (7-((S4.pos>>17)&7)));
+ else s = 1 & (noise15[
+ (S4.pos>>20)&4095] >> (7-((S4.pos>>17)&7)));
+ s = (-s) & S4.envol;
+ S4.pos += S4.freq;
+ if ((R_NR44 & 64) && ((S4.cnt += RATE) >= S4.len))
+ S4.on = 0;
+ if (S4.enlen && (S4.encnt += RATE) >= S4.enlen)
+ {
+ S4.encnt -= S4.enlen;
+ S4.envol += S4.endir;
+ if (S4.envol < 0) S4.envol = 0;
+ if (S4.envol > 15) S4.envol = 15;
+ }
+ s += s << 1;
+ if (R_NR51 & 8) r += s;
+ if (R_NR51 & 128) l += s;
+ }
+
+ l *= (R_NR50 & 0x07);
+ r *= ((R_NR50 & 0x70)>>4);
+ l >>= 4;
+ r >>= 4;
+
+ if (l > 127) l = 127;
+ else if (l < -128) l = -128;
+ if (r > 127) r = 127;
+ else if (r < -128) r = -128;
+
+ if (pcm.buf)
+ {
+ if (pcm.pos >= pcm.len)
+ pcm_submit();
+ if (pcm.stereo)
+ {
+ pcm.buf[pcm.pos++] = l+128;
+ pcm.buf[pcm.pos++] = r+128;
+ }
+ else pcm.buf[pcm.pos++] = ((l+r)>>1)+128;
+ }
+ }
+ R_NR52 = (R_NR52&0xf0) | S1.on | (S2.on<<1) | (S3.on<<2) | (S4.on<<3);
+}
+
+
+
+byte sound_read(byte r)
+{
+ sound_mix();
+ /* printf("read %02X: %02X\n", r, REG(r)); */
+ return REG(r);
+}
+
+void s1_init(void)
+{
+ S1.swcnt = 0;
+ S1.swfreq = ((R_NR14&7)<<8) + R_NR13;
+ S1.envol = R_NR12 >> 4;
+ S1.endir = (R_NR12>>3) & 1;
+ S1.endir |= S1.endir - 1;
+ S1.enlen = (R_NR12 & 7) << 15;
+ if (!S1.on) S1.pos = 0;
+ S1.on = 1;
+ S1.cnt = 0;
+ S1.encnt = 0;
+}
+
+void s2_init(void)
+{
+ S2.envol = R_NR22 >> 4;
+ S2.endir = (R_NR22>>3) & 1;
+ S2.endir |= S2.endir - 1;
+ S2.enlen = (R_NR22 & 7) << 15;
+ if (!S2.on) S2.pos = 0;
+ S2.on = 1;
+ S2.cnt = 0;
+ S2.encnt = 0;
+}
+
+void s3_init(void)
+{
+ int i;
+ if (!S3.on) S3.pos = 0;
+ S3.cnt = 0;
+ S3.on = R_NR30 >> 7;
+ if (S3.on) for (i = 0; i < 16; i++)
+ ram.hi[i+0x30] = 0x13 ^ ram.hi[i+0x31];
+}
+
+void s4_init(void)
+{
+ S4.envol = R_NR42 >> 4;
+ S4.endir = (R_NR42>>3) & 1;
+ S4.endir |= S4.endir - 1;
+ S4.enlen = (R_NR42 & 7) << 15;
+ S4.on = 1;
+ S4.pos = 0;
+ S4.cnt = 0;
+ S4.encnt = 0;
+}
+
+
+void sound_write(byte r, byte b)
+{
+#if 0
+ static void *timer;
+ if (!timer) timer = sys_timer();
+ printf("write %02X: %02X @ %d\n", r, b, sys_elapsed(timer));
+#endif
+
+ if (!(R_NR52 & 128) && r != RI_NR52) return;
+ if ((r & 0xF0) == 0x30)
+ {
+ if (S3.on) sound_mix();
+ if (!S3.on)
+ WAVE[r-0x30] = ram.hi[r] = b;
+ return;
+ }
+ sound_mix();
+ switch (r)
+ {
+ case RI_NR10:
+ R_NR10 = b;
+ S1.swlen = ((R_NR10>>4) & 7) << 14;
+ S1.swfreq = ((R_NR14&7)<<8) + R_NR13;
+ break;
+ case RI_NR11:
+ R_NR11 = b;
+ S1.len = (64-(R_NR11&63)) << 13;
+ break;
+ case RI_NR12:
+ R_NR12 = b;
+ S1.envol = R_NR12 >> 4;
+ S1.endir = (R_NR12>>3) & 1;
+ S1.endir |= S1.endir - 1;
+ S1.enlen = (R_NR12 & 7) << 15;
+ break;
+ case RI_NR13:
+ R_NR13 = b;
+ s1_freq();
+ break;
+ case RI_NR14:
+ R_NR14 = b;
+ s1_freq();
+ if (b & 128) s1_init();
+ break;
+ case RI_NR21:
+ R_NR21 = b;
+ S2.len = (64-(R_NR21&63)) << 13;
+ break;
+ case RI_NR22:
+ R_NR22 = b;
+ S2.envol = R_NR22 >> 4;
+ S2.endir = (R_NR22>>3) & 1;
+ S2.endir |= S2.endir - 1;
+ S2.enlen = (R_NR22 & 7) << 15;
+ break;
+ case RI_NR23:
+ R_NR23 = b;
+ s2_freq();
+ break;
+ case RI_NR24:
+ R_NR24 = b;
+ s2_freq();
+ if (b & 128) s2_init();
+ break;
+ case RI_NR30:
+ R_NR30 = b;
+ if (!(b & 128)) S3.on = 0;
+ break;
+ case RI_NR31:
+ R_NR31 = b;
+ S3.len = (256-R_NR31) << 13;
+ break;
+ case RI_NR32:
+ R_NR32 = b;
+ break;
+ case RI_NR33:
+ R_NR33 = b;
+ s3_freq();
+ break;
+ case RI_NR34:
+ R_NR34 = b;
+ s3_freq();
+ if (b & 128) s3_init();
+ break;
+ case RI_NR41:
+ R_NR41 = b;
+ S4.len = (64-(R_NR41&63)) << 13;
+ break;
+ case RI_NR42:
+ R_NR42 = b;
+ S4.envol = R_NR42 >> 4;
+ S4.endir = (R_NR42>>3) & 1;
+ S4.endir |= S4.endir - 1;
+ S4.enlen = (R_NR42 & 7) << 15;
+ break;
+ case RI_NR43:
+ R_NR43 = b;
+ s4_freq();
+ break;
+ case RI_NR44:
+ R_NR44 = b;
+ if (b & 128) s4_init();
+ break;
+ case RI_NR50:
+ R_NR50 = b;
+ break;
+ case RI_NR51:
+ R_NR51 = b;
+ break;
+ case RI_NR52:
+ R_NR52 = b;
+ if (!(R_NR52 & 128))
+ sound_off();
+ break;
+ default:
+ return;
+ }
+}
+
+
+
+
diff --git a/apps/plugins/rockboy/sound.h b/apps/plugins/rockboy/sound.h
new file mode 100644
index 0000000..1a24ee6
--- /dev/null
+++ b/apps/plugins/rockboy/sound.h
@@ -0,0 +1,41 @@
+
+
+#ifndef __SOUND_H__
+#define __SOUND_H__
+
+
+struct sndchan
+{
+ int on;
+ unsigned pos;
+ int cnt, encnt, swcnt;
+ int len, enlen, swlen;
+ int swfreq;
+ int freq;
+ int envol, endir;
+};
+
+
+struct snd
+{
+ int rate;
+ struct sndchan ch[4];
+ byte wave[16];
+};
+
+
+extern struct snd snd;
+
+byte sound_read(byte r);
+void sound_write(byte r, byte b);
+void sound_dirty(void);
+void sound_off(void);
+void sound_reset(void);
+void sound_mix(void);
+void s1_init(void);
+void s2_init(void);
+void s3_init(void);
+void s4_init(void);
+
+#endif
+
diff --git a/apps/plugins/rockboy/split.c b/apps/plugins/rockboy/split.c
new file mode 100644
index 0000000..5d8af08
--- /dev/null
+++ b/apps/plugins/rockboy/split.c
@@ -0,0 +1,59 @@
+
+#include "rockmacros.h"
+
+/*
+ * splitline is a destructive argument parser, much like a very primitive
+ * form of a shell parser. it supports quotes for embedded spaces and
+ * literal quotes with the backslash escape.
+ */
+
+char *splitnext(char **pos)
+{
+ char *a, *d, *s;
+
+ d = s = *pos;
+ while (*s == ' ' || *s == '\t') s++;
+ a = s;
+ while (*s && *s != ' ' && *s != '\t')
+ {
+ if (*s == '"')
+ {
+ s++;
+ while (*s && *s != '"')
+ {
+ if (*s == '\\')
+ s++;
+ if (*s)
+ *(d++) = *(s++);
+ }
+ if (*s == '"') s++;
+ }
+ else
+ {
+ if (*s == '\\')
+ s++;
+ *(d++) = *(s++);
+ }
+ }
+ while (*s == ' ' || *s == '\t') s++;
+ *d = 0;
+ *pos = s;
+ return a;
+}
+
+int splitline(char **argv, int max, char *line)
+{
+ char *s;
+ int i;
+
+ s = line;
+ for (i = 0; *s && i < max + 1; i++)
+ argv[i] = splitnext(&s);
+ argv[i] = 0;
+ return i;
+}
+
+
+
+
+
diff --git a/apps/plugins/rockboy/split.h b/apps/plugins/rockboy/split.h
new file mode 100644
index 0000000..a371430
--- /dev/null
+++ b/apps/plugins/rockboy/split.h
@@ -0,0 +1 @@
+int splitline(char **argv, int max, char *line);
diff --git a/apps/plugins/rockboy/sys_rockbox.c b/apps/plugins/rockboy/sys_rockbox.c
new file mode 100644
index 0000000..43cd8ad
--- /dev/null
+++ b/apps/plugins/rockboy/sys_rockbox.c
@@ -0,0 +1,271 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 Michiel van der Kolk, Jens Arnold
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "rockmacros.h"
+#include "fb.h"
+#include "input.h"
+#include "rc.h"
+#include "lcd.h"
+#include "hw.h"
+#include "config.h"
+
+rcvar_t joy_exports[] =
+{
+ RCV_END
+};
+
+rcvar_t vid_exports[] =
+{
+ RCV_END
+};
+
+struct fb fb;
+byte *video_base_buf;
+
+extern int debug_trace;
+
+static byte frameb[145][160];
+
+void vid_settitle(char *title)
+{
+ rb->splash(HZ*2, true, title);
+}
+
+void joy_init(void)
+{
+}
+
+void joy_close(void)
+{
+}
+
+#if CONFIG_KEYPAD == IRIVER_H100_PAD
+#define ROCKBOY_PAD_A BUTTON_ON
+#define ROCKBOY_PAD_B BUTTON_OFF
+#define ROCKBOY_PAD_START BUTTON_REC
+#define ROCKBOY_PAD_SELECT BUTTON_MODE
+#define ROCKBOY_QUIT BUTTON_SELECT
+
+#elif CONFIG_KEYPAD == RECORDER_PAD
+#define ROCKBOY_PAD_A BUTTON_F1
+#define ROCKBOY_PAD_B BUTTON_F2
+#define ROCKBOY_PAD_START BUTTON_F3
+#define ROCKBOY_PAD_SELECT BUTTON_PLAY
+#define ROCKBOY_QUIT BUTTON_OFF
+
+#endif
+
+unsigned int oldbuttonstate = 0, newbuttonstate;
+
+void ev_poll(void)
+{
+ event_t ev;
+ int released, pressed;
+ newbuttonstate = rb->button_status();
+ released = ~newbuttonstate & oldbuttonstate;
+ pressed = newbuttonstate & ~oldbuttonstate;
+ oldbuttonstate = newbuttonstate;
+
+ if(released) {
+ ev.type = EV_RELEASE;
+ if(released & BUTTON_LEFT) { ev.code=PAD_LEFT; ev_postevent(&ev); }
+ if(released & BUTTON_RIGHT) {ev.code=PAD_RIGHT; ev_postevent(&ev);}
+ if(released & BUTTON_DOWN) { ev.code=PAD_DOWN; ev_postevent(&ev); }
+ if(released & BUTTON_UP) { ev.code=PAD_UP; ev_postevent(&ev); }
+ if(released & ROCKBOY_PAD_A) { ev.code=PAD_A; ev_postevent(&ev); }
+ if(released & ROCKBOY_PAD_B) { ev.code=PAD_B; ev_postevent(&ev); }
+ if(released & ROCKBOY_PAD_START) {
+ ev.code=PAD_START;
+ ev_postevent(&ev);
+ }
+ if(released & ROCKBOY_PAD_SELECT) {
+ ev.code=PAD_SELECT;
+ ev_postevent(&ev);
+ }
+ }
+ if(pressed) { /* button press */
+ ev.type = EV_PRESS;
+ if(pressed & BUTTON_LEFT) { ev.code=PAD_LEFT; ev_postevent(&ev); }
+ if(pressed & BUTTON_RIGHT) { ev.code=PAD_RIGHT; ev_postevent(&ev);}
+ if(pressed & BUTTON_DOWN) { ev.code=PAD_DOWN; ev_postevent(&ev); }
+ if(pressed & BUTTON_UP) { ev.code=PAD_UP; ev_postevent(&ev); }
+ if(pressed & ROCKBOY_PAD_A) { ev.code=PAD_A; ev_postevent(&ev); }
+ if(pressed & ROCKBOY_PAD_B) { ev.code=PAD_B; ev_postevent(&ev); }
+ if(pressed & ROCKBOY_PAD_START) {
+ ev.code=PAD_START;
+ ev_postevent(&ev);
+ }
+ if(pressed & ROCKBOY_PAD_SELECT) {
+ ev.code=PAD_SELECT;
+ ev_postevent(&ev);
+ }
+ if(pressed & ROCKBOY_QUIT) {
+ die("");
+ cleanshut=1;
+ }
+ }
+
+}
+
+void vid_setpal(int i, int r, int g, int b)
+{
+ (void)i;
+ (void)r;
+ (void)g;
+ (void)b;
+}
+
+void vid_init(void)
+{
+}
+
+void vid_begin(void)
+{
+ fb.pelsize=1; // 8 bit framebuffer.. (too much.. but lowest gnuboy will support.. so yea...
+ fb.h=144;
+ fb.w=160;
+ fb.pitch=160;
+ fb.enabled=1;
+ fb.dirty=0;
+ video_base_buf=fb.ptr=(byte *)frameb;
+}
+
+void vid_update(int scanline)
+{
+ int cnt=0,scanline_remapped;
+ byte *frameb;
+#if LCD_HEIGHT == 64 /* Archos */
+ int balance = 0;
+ if (scanline >= 128)
+ return;
+ scanline_remapped = scanline / 16;
+ frameb = rb->lcd_framebuffer + scanline_remapped * LCD_WIDTH;
+ while (cnt < 160) {
+ balance += LCD_WIDTH;
+ if (balance > 0)
+ {
+#ifdef SIMULATOR /* simulator uses C */
+ register unsigned scrbyte = 0;
+ if (scan.buf[0][cnt] & 0x02) scrbyte |= 0x01;
+ if (scan.buf[1][cnt] & 0x02) scrbyte |= 0x02;
+ if (scan.buf[2][cnt] & 0x02) scrbyte |= 0x04;
+ if (scan.buf[3][cnt] & 0x02) scrbyte |= 0x08;
+ if (scan.buf[4][cnt] & 0x02) scrbyte |= 0x10;
+ if (scan.buf[5][cnt] & 0x02) scrbyte |= 0x20;
+ if (scan.buf[6][cnt] & 0x02) scrbyte |= 0x40;
+ if (scan.buf[7][cnt] & 0x02) scrbyte |= 0x80;
+ *(frameb++) = scrbyte;
+#else
+ asm volatile (
+ "mov.b @%0,r0 \n"
+ "add %1,%0 \n"
+ "tst #0x02, r0 \n" /* ~bit 1 */
+ "rotcr r1 \n"
+ "mov.b @%0,r0 \n"
+ "add %1,%0 \n"
+ "tst #0x02, r0 \n" /* ~bit 1 */
+ "rotcr r1 \n"
+ "mov.b @%0,r0 \n"
+ "add %1,%0 \n"
+ "tst #0x02, r0 \n" /* ~bit 1 */
+ "rotcr r1 \n"
+ "mov.b @%0,r0 \n"
+ "add %1,%0 \n"
+ "tst #0x02, r0 \n" /* ~bit 1 */
+ "rotcr r1 \n"
+ "mov.b @%0,r0 \n"
+ "add %1,%0 \n"
+ "tst #0x02, r0 \n" /* ~bit 1 */
+ "rotcr r1 \n"
+ "mov.b @%0,r0 \n"
+ "add %1,%0 \n"
+ "tst #0x02, r0 \n" /* ~bit 1 */
+ "rotcr r1 \n"
+ "mov.b @%0,r0 \n"
+ "add %1,%0 \n"
+ "tst #0x02, r0 \n" /* ~bit 1 */
+ "rotcr r1 \n"
+ "mov.b @%0,r0 \n"
+ "add %1,%0 \n"
+ "tst #0x02, r0 \n" /* ~bit 1 */
+ "rotcr r1 \n"
+
+ "shlr16 r1 \n"
+ "shlr8 r1 \n"
+ "not r1,r1 \n" /* account for negated bits */
+ "mov.b r1,@%2 \n"
+ : /* outputs */
+ : /* inputs */
+ /* %0 */ "r"(scan.buf[0] + cnt),
+ /* %1 */ "r"(256), /* scan.buf line length */
+ /* %2 */ "r"(frameb++)
+ : /* clobbers */
+ "r0", "r1"
+ );
+#endif
+ balance -= 160;
+ }
+ cnt ++;
+ }
+ rb->lcd_update_rect(0, (scanline/2) & ~7, LCD_WIDTH, 8);
+#else /* LCD_HEIGHT != 64, iRiver */
+ if (scanline >= 128)
+ return;
+ scanline_remapped = scanline / 8;
+ frameb = rb->lcd_framebuffer + scanline_remapped * LCD_WIDTH;
+ while (cnt < 160) {
+ register unsigned scrbyte = 0;
+ if (scan.buf[0][cnt] & 0x02) scrbyte |= 0x01;
+ if (scan.buf[1][cnt] & 0x02) scrbyte |= 0x02;
+ if (scan.buf[2][cnt] & 0x02) scrbyte |= 0x04;
+ if (scan.buf[3][cnt] & 0x02) scrbyte |= 0x08;
+ if (scan.buf[4][cnt] & 0x02) scrbyte |= 0x10;
+ if (scan.buf[5][cnt] & 0x02) scrbyte |= 0x20;
+ if (scan.buf[6][cnt] & 0x02) scrbyte |= 0x40;
+ if (scan.buf[7][cnt] & 0x02) scrbyte |= 0x80;
+ *(frameb++) = scrbyte;
+ cnt++;
+ }
+ rb->lcd_update_rect(0, scanline & ~7, LCD_WIDTH, 8);
+#endif
+}
+
+void vid_end(void)
+{
+}
+
+long timerresult;
+
+void *sys_timer(void)
+{
+ timerresult=*rb->current_tick;
+ return &timerresult;
+}
+
+// returns microseconds passed since sys_timer
+int sys_elapsed(long *oldtick)
+{
+ return ((*rb->current_tick-(*oldtick))*1000000)/HZ;
+}
+
+void sys_sleep(int us)
+{
+ if (us <= 0) return;
+// rb->sleep(HZ*us/1000000);
+}
diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config
index 2290a8e..08bd7ff 100644
--- a/apps/plugins/viewers.config
+++ b/apps/plugins/viewers.config
@@ -6,6 +6,8 @@ rvf,video.rock,5D 7F 5D 7F 5D 7F
mp3,vbrfix.rock,10 08 58 38 04 02
m3u,search.rock,00 00 00 00 00 00
txt,sort.rock, 00 00 00 00 00 00
+gb,rockboy.rock, 0C 2A 59 7A 2E 0C
+cgb,rockboy.rock, 0C 2A 59 7A 2E 0C
mp2,mpa2wav.rock, 00 00 00 00 00 00
mp3,mpa2wav.rock, 00 00 00 00 00 00
ac3,a52towav.rock, 00 00 00 00 00 00